- /*
- * @(#)MathContext.java 1.2 03/12/19
- *
- * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
- * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
- */
-
- /*
- * @(#)MathContext.java 1.x 01/xx/xx
- *
- * Copyright IBM Corporation, 1997, 2001. All Rights Reserved.
- *
- * This software is the proprietary information of Sun Microsystems, Inc.
- * and IBM Corporation. Use is subject to license terms.
- *
- */
-
- package java.math;
- import java.io.*;
-
- /**
- * Immutable objects which encapsulate the context settings which
- * describe certain rules for numerical operators, such as those
- * implemented by the {@link BigDecimal} class.
- *
- * <p>The base-independent settings are:
- * <ol>
- * <li><tt>precision</tt>:
- * the number of digits to be used for an operation; results are
- * rounded to this precision
- *
- * <li><tt>roundingMode</tt>:
- * a {@link RoundingMode} object which specifies the algorithm to be
- * used for rounding.
- * </ol>
- *
- * @see BigDecimal
- * @see RoundingMode
- * @author Mike Cowlishaw
- * @author Joseph D. Darcy
- */
-
- public final class MathContext implements Serializable {
-
- /* ----- Constants ----- */
-
- // defaults for constructors
- private static final int DEFAULT_DIGITS = 9;
- private static final RoundingMode DEFAULT_ROUNDINGMODE = RoundingMode.HALF_UP;
- // Smallest values for digits (Maximum is Integer.MAX_VALUE)
- private static final int MIN_DIGITS = 0;
-
- // Serialization version
- private static final long serialVersionUID = 5579720004786848255L;
-
- /* ----- Public Properties ----- */
- /**
- * A <tt>MathContext</tt> object whose settings have the values
- * required for unlimited precision arithmetic.
- * The values of the settings are:
- * <code>
- * precision=0 roundingMode=HALF_UP
- * </code>
- */
- public static final MathContext UNLIMITED =
- new MathContext(0, RoundingMode.HALF_UP);
-
- /**
- * A <tt>MathContext</tt> object with a precision setting
- * matching the IEEE 754R Decimal32 format, 7 digits, and a
- * rounding mode of {@link RoundingMode#HALF_EVEN HALF_EVEN}, the
- * IEEE 754R default.
- */
- public static final MathContext DECIMAL32 =
- new MathContext(7, RoundingMode.HALF_EVEN);
-
- /**
- * A <tt>MathContext</tt> object with a precision setting
- * matching the IEEE 754R Decimal64 format, 16 digits, and a
- * rounding mode of {@link RoundingMode#HALF_EVEN HALF_EVEN}, the
- * IEEE 754R default.
- */
- public static final MathContext DECIMAL64 =
- new MathContext(16, RoundingMode.HALF_EVEN);
-
- /**
- * A <tt>MathContext</tt> object with a precision setting
- * matching the IEEE 754R Decimal128 format, 34 digits, and a
- * rounding mode of {@link RoundingMode#HALF_EVEN HALF_EVEN}, the
- * IEEE 754R default.
- */
- public static final MathContext DECIMAL128 =
- new MathContext(34, RoundingMode.HALF_EVEN);
-
- /* ----- Shared Properties ----- */
- /**
- * The number of digits to be used for an operation. A value of 0
- * indicates that unlimited precision (as many digits as are
- * required) will be used. Note that leading zeros (in the
- * coefficient of a number) are never significant.
- *
- * <p><tt>precision</tt> will always be non-negative.
- *
- * @serial
- */
- final int precision;
-
- /**
- * The rounding algorithm to be used for an operation.
- *
- * @see RoundingMode
- * @serial
- */
- final RoundingMode roundingMode;
-
- /**
- * Lookaside for the rounding points (the numbers which determine
- * whether the coefficient of a number will require rounding).
- * These will be present if precision>0 and
- * precision<=MAX_LOOKASIDE. In this case they will share the
- * <tt>BigInteger int[]</tt> array. Note that the transients
- * cannot be <tt>final</tt> because they are reconstructed on
- * deserialization.
- */
- transient BigInteger roundingMax = null;
- transient BigInteger roundingMin = null;
- private static final int MAX_LOOKASIDE = 1000;
-
- /* ----- Constructors ----- */
-
- /**
- * Constructs a new <tt>MathContext</tt> with the specified
- * precision and the {@link RoundingMode#HALF_UP HALF_UP} rounding
- * mode.
- *
- * @param setPrecision The non-negative <tt>int</tt> precision setting.
- * @throws IllegalArgumentException <tt>setPrecision</tt> parameter less
- * than zero.
- */
- public MathContext(int setPrecision) {
- this(setPrecision, DEFAULT_ROUNDINGMODE);
- return;
- }
-
- /**
- * Constructs a new <tt>MathContext</tt> with a specified
- * precision and rounding mode.
- *
- * @param setPrecision The non-negative <tt>int</tt> precision setting.
- * @param setRoundingMode The rounding mode to use.
- * @throws IllegalArgumentException <tt>setPrecision</tt> parameter less
- * than zero.
- */
- public MathContext(int setPrecision,
- RoundingMode setRoundingMode) {
- if (setPrecision < MIN_DIGITS)
- throw new IllegalArgumentException("Digits < 0");
- if (setRoundingMode == null)
- throw new NullPointerException("null RoundingMode");
-
- precision = setPrecision;
- if (precision > 0 && precision <= MAX_LOOKASIDE) {
- roundingMax = BigInteger.TEN.pow(precision);
- roundingMin = roundingMax.negate();
- }
-
- roundingMode = setRoundingMode;
- return;
- }
-
- /**
- * Constructs a new <tt>MathContext</tt> from a string.
- *
- * The string must be in the same format as that produced by the
- * {@link #toString} method.
- *
- * <p>An <tt>IllegalArgumentException</tt> is thrown if the precision
- * section of the string is out of range (< 0) or the string is
- * not in the format created by the {@link #toString} method.
- *
- * @param val The string to be parsed
- * @throws IllegalArgumentException precision parameter out of range
- * or incorrect format
- */
- public MathContext(String val) {
- boolean bad = false;
- int setPrecision;
- if (val == null)
- throw new NullPointerException("null String");
- try { // any error here is a string format problem
- if (!val.startsWith("precision=")) throw new RuntimeException();
- int fence = val.indexOf(' '); // could be -1
- int off = 10; // where value starts
- setPrecision = Integer.parseInt(val.substring(10, fence));
-
- if (!val.startsWith("roundingMode=", fence+1))
- throw new RuntimeException();
- off = fence + 1 + 13;
- String str = val.substring(off, val.length());
- roundingMode = RoundingMode.valueOf(str);
- } catch (RuntimeException re) {
- throw new IllegalArgumentException("bad string format");
- }
-
- if (setPrecision < MIN_DIGITS)
- throw new IllegalArgumentException("Digits < 0");
- // the other parameters cannot be invalid if we got here
- precision = setPrecision;
- if (precision > 0 && precision <= MAX_LOOKASIDE) {
- roundingMax = BigInteger.TEN.pow(precision);
- roundingMin = roundingMax.negate();
- }
- }
-
- /**
- * Returns the <tt>precision</tt> setting.
- * This value is always non-negative.
- *
- * @return an <tt>int</tt> which is the value of the <tt>precision</tt>
- * setting
- */
- public int getPrecision() {
- return precision;
- }
-
- /**
- * Returns the roundingMode setting.
- * This will be one of
- * {@link RoundingMode#CEILING},
- * {@link RoundingMode#DOWN},
- * {@link RoundingMode#FLOOR},
- * {@link RoundingMode#HALF_DOWN},
- * {@link RoundingMode#HALF_EVEN},
- * {@link RoundingMode#HALF_UP},
- * {@link RoundingMode#UNNECESSARY}, or
- * {@link RoundingMode#UP}.
- *
- * @return a <tt>RoundingMode</tt> object which is the value of the
- * <tt>roundingMode</tt> setting
- */
-
- public RoundingMode getRoundingMode() {
- return roundingMode;
- }
-
- /**
- * Compares this <tt>MathContext</tt> with the specified
- * <tt>Object</tt> for equality.
- *
- * @param x <tt>Object</tt> to which this <tt>MathContext</tt> is to
- * be compared.
- * @return <tt>true</tt> if and only if the specified <tt>Object</tt> is
- * a <tt>MathContext</tt> object which has exactly the same
- * settings as this object.
- */
- public boolean equals(Object x){
- MathContext mc;
- if (!(x instanceof MathContext))
- return false;
- mc = (MathContext) x;
- return mc.precision == this.precision
- && mc.roundingMode == this.roundingMode; // no need for .equals()
- }
-
- /**
- * Returns the hash code for this <tt>MathContext</tt>.
- *
- * @return hash code for this <tt>MathContext</tt>
- */
- public int hashCode() {
- return this.precision + roundingMode.hashCode() * 59;
- }
-
- /**
- * Returns the string representation of this <tt>MathContext</tt>.
- * The <tt>String</tt> returned represents the settings of the
- * <tt>MathContext</tt> object as two space-delimited words
- * (separated by a single space character, <tt>'\u0020'</tt>,
- * and with no leading or trailing white space), as follows:
- * <ol>
- * <li>
- * The string <tt>"precision="</tt>, immediately followed
- * by the value of the precision setting as a numeric string as if
- * generated by the {@link Integer#toString(int) Integer.toString}
- * method.
- *
- * <li>
- * The string <tt>"roundingMode="</tt>, immediately
- * followed by the value of the <tt>roundingMode</tt> setting as a
- * word. This word will be the same as the name of the
- * corresponding public constant in the {@link RoundingMode}
- * enum.
- * </ol>
- * <p>
- * For example:
- * <pre>
- * precision=9 roundingMode=HALF_UP
- * </pre>
- *
- * Additional words may be appended to the result of
- * <tt>toString</tt> in the future if more properties are added to
- * this class.
- *
- * @return a <tt>String</tt> representing the context settings.
- */
- public java.lang.String toString() {
- return "precision=" + precision + " " +
- "roundingMode=" + roundingMode.toString();
- }
-
- // Private methods
-
- /**
- * Reconstitute the <tt>MathContext</tt> instance from a stream (that is,
- * deserialize it).
- *
- * @param s the stream being read.
- */
- private synchronized void readObject(java.io.ObjectInputStream s)
- throws java.io.IOException, ClassNotFoundException {
- s.defaultReadObject(); // read in all fields
- // validate possibly bad fields
- if (precision < MIN_DIGITS) {
- String message = "MathContext: invalid digits in stream";
- throw new java.io.StreamCorruptedException(message);
- }
- if (roundingMode == null) {
- String message = "MathContext: null roundingMode in stream";
- throw new java.io.StreamCorruptedException(message);
- }
- // Set the lookaside, if applicable
- if (precision <= MAX_LOOKASIDE) {
- roundingMax = BigInteger.TEN.pow(precision);
- roundingMin = roundingMax.negate();
- }
- }
-
- }