|  | /* | 
|  | *  Licensed to the Apache Software Foundation (ASF) under one or more | 
|  | *  contributor license agreements.  See the NOTICE file distributed with | 
|  | *  this work for additional information regarding copyright ownership. | 
|  | *  The ASF licenses this file to You under the Apache License, Version 2.0 | 
|  | *  (the "License"); you may not use this file except in compliance with | 
|  | *  the License.  You may obtain a copy of the License at | 
|  | * | 
|  | *     http://www.apache.org/licenses/LICENSE-2.0 | 
|  | * | 
|  | *  Unless required by applicable law or agreed to in writing, software | 
|  | *  distributed under the License is distributed on an "AS IS" BASIS, | 
|  | *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | 
|  | *  See the License for the specific language governing permissions and | 
|  | *  limitations under the License. | 
|  | */ | 
|  |  | 
|  | package java.math; | 
|  |  | 
|  | import java.io.IOException; | 
|  | import java.io.ObjectInputStream; | 
|  | import java.io.Serializable; | 
|  | import java.io.StreamCorruptedException; | 
|  |  | 
|  | /** | 
|  | * Immutable objects describing settings such as rounding mode and digit | 
|  | * precision for the numerical operations provided by class {@link BigDecimal}. | 
|  | */ | 
|  | public final class MathContext implements Serializable { | 
|  | private static final long serialVersionUID = 5579720004786848255L; | 
|  |  | 
|  | /** | 
|  | * A {@code MathContext} which corresponds to the <a href="http://en.wikipedia.org/wiki/IEEE_754-1985">IEEE 754</a> quadruple | 
|  | * decimal precision format: 34 digit precision and | 
|  | * {@link RoundingMode#HALF_EVEN} rounding. | 
|  | */ | 
|  | public static final MathContext DECIMAL128 = new MathContext(34, RoundingMode.HALF_EVEN); | 
|  |  | 
|  | /** | 
|  | * A {@code MathContext} which corresponds to the <a href="http://en.wikipedia.org/wiki/IEEE_754-1985">IEEE 754</a> single decimal | 
|  | * precision format: 7 digit precision and {@link RoundingMode#HALF_EVEN} | 
|  | * rounding. | 
|  | */ | 
|  | public static final MathContext DECIMAL32 = new MathContext(7, RoundingMode.HALF_EVEN); | 
|  |  | 
|  | /** | 
|  | * A {@code MathContext} which corresponds to the <a href="http://en.wikipedia.org/wiki/IEEE_754-1985">IEEE 754</a> double decimal | 
|  | * precision format: 16 digit precision and {@link RoundingMode#HALF_EVEN} | 
|  | * rounding. | 
|  | */ | 
|  | public static final MathContext DECIMAL64 = new MathContext(16, RoundingMode.HALF_EVEN); | 
|  |  | 
|  | /** | 
|  | * A {@code MathContext} for unlimited precision with | 
|  | * {@link RoundingMode#HALF_UP} rounding. | 
|  | */ | 
|  | public static final MathContext UNLIMITED = new MathContext(0, RoundingMode.HALF_UP); | 
|  |  | 
|  | /** | 
|  | * The number of digits to be used for an operation; results are rounded to | 
|  | * this precision. | 
|  | */ | 
|  | private final int precision; | 
|  |  | 
|  | /** | 
|  | * A {@code RoundingMode} object which specifies the algorithm to be used | 
|  | * for rounding. | 
|  | */ | 
|  | private final RoundingMode roundingMode; | 
|  |  | 
|  | /** | 
|  | * Constructs a new {@code MathContext} with the specified precision and | 
|  | * with the rounding mode {@link RoundingMode#HALF_UP HALF_UP}. If the | 
|  | * precision passed is zero, then this implies that the computations have to | 
|  | * be performed exact, the rounding mode in this case is irrelevant. | 
|  | * | 
|  | * @param precision | 
|  | *            the precision for the new {@code MathContext}. | 
|  | * @throws IllegalArgumentException | 
|  | *             if {@code precision < 0}. | 
|  | */ | 
|  | public MathContext(int precision) { | 
|  | this(precision, RoundingMode.HALF_UP); | 
|  | } | 
|  |  | 
|  | /** | 
|  | * Constructs a new {@code MathContext} with the specified precision and | 
|  | * with the specified rounding mode. If the precision passed is zero, then | 
|  | * this implies that the computations have to be performed exact, the | 
|  | * rounding mode in this case is irrelevant. | 
|  | * | 
|  | * @param precision | 
|  | *            the precision for the new {@code MathContext}. | 
|  | * @param roundingMode | 
|  | *            the rounding mode for the new {@code MathContext}. | 
|  | * @throws IllegalArgumentException | 
|  | *             if {@code precision < 0}. | 
|  | * @throws NullPointerException | 
|  | *             if {@code roundingMode} is {@code null}. | 
|  | */ | 
|  | public MathContext(int precision, RoundingMode roundingMode) { | 
|  | this.precision = precision; | 
|  | this.roundingMode = roundingMode; | 
|  | checkValid(); | 
|  | } | 
|  |  | 
|  | /** | 
|  | * Constructs a new {@code MathContext} from a string. The string has to | 
|  | * specify the precision and the rounding mode to be used and has to follow | 
|  | * the following syntax: "precision=<precision> roundingMode=<roundingMode>" | 
|  | * This is the same form as the one returned by the {@link #toString} | 
|  | * method. | 
|  | * | 
|  | * @throws IllegalArgumentException | 
|  | *             if the string is not in the correct format or if the | 
|  | *             precision specified is < 0. | 
|  | */ | 
|  | public MathContext(String s) { | 
|  | int precisionLength = "precision=".length(); | 
|  | int roundingModeLength = "roundingMode=".length(); | 
|  |  | 
|  | int spaceIndex; | 
|  | if (!s.startsWith("precision=") || (spaceIndex = s.indexOf(' ', precisionLength)) == -1) { | 
|  | throw invalidMathContext("Missing precision", s); | 
|  | } | 
|  | String precisionString = s.substring(precisionLength, spaceIndex); | 
|  | try { | 
|  | this.precision = Integer.parseInt(precisionString); | 
|  | } catch (NumberFormatException nfe) { | 
|  | throw invalidMathContext("Bad precision", s); | 
|  | } | 
|  |  | 
|  | int roundingModeStart = spaceIndex + 1; | 
|  | if (!s.regionMatches(roundingModeStart, "roundingMode=", 0, roundingModeLength)) { | 
|  | throw invalidMathContext("Missing rounding mode", s); | 
|  | } | 
|  | roundingModeStart += roundingModeLength; | 
|  | this.roundingMode = RoundingMode.valueOf(s.substring(roundingModeStart)); | 
|  |  | 
|  | checkValid(); | 
|  | } | 
|  |  | 
|  | private IllegalArgumentException invalidMathContext(String reason, String s) { | 
|  | throw new IllegalArgumentException(reason + ": " + s); | 
|  | } | 
|  |  | 
|  | private void checkValid() { | 
|  | if (precision < 0) { | 
|  | throw new IllegalArgumentException("Negative precision: " + precision); | 
|  | } | 
|  | if (roundingMode == null) { | 
|  | throw new NullPointerException("roundingMode == null"); | 
|  | } | 
|  | } | 
|  |  | 
|  | /** | 
|  | * Returns the precision. The precision is the number of digits used for an | 
|  | * operation. Results are rounded to this precision. The precision is | 
|  | * guaranteed to be non negative. If the precision is zero, then the | 
|  | * computations have to be performed exact, results are not rounded in this | 
|  | * case. | 
|  | * | 
|  | * @return the precision. | 
|  | */ | 
|  | public int getPrecision() { | 
|  | return precision; | 
|  | } | 
|  |  | 
|  | /** | 
|  | * Returns the rounding mode. The rounding mode is the strategy to be used | 
|  | * to round results. | 
|  | * <p> | 
|  | * The rounding mode is one of | 
|  | * {@link RoundingMode#UP}, | 
|  | * {@link RoundingMode#DOWN}, | 
|  | * {@link RoundingMode#CEILING}, | 
|  | * {@link RoundingMode#FLOOR}, | 
|  | * {@link RoundingMode#HALF_UP}, | 
|  | * {@link RoundingMode#HALF_DOWN}, | 
|  | * {@link RoundingMode#HALF_EVEN}, or | 
|  | * {@link RoundingMode#UNNECESSARY}. | 
|  | * | 
|  | * @return the rounding mode. | 
|  | */ | 
|  | public RoundingMode getRoundingMode() { | 
|  | return roundingMode; | 
|  | } | 
|  |  | 
|  | /** | 
|  | * Returns true if x is a {@code MathContext} with the same precision | 
|  | * setting and the same rounding mode as this {@code MathContext} instance. | 
|  | * | 
|  | * @param x | 
|  | *            object to be compared. | 
|  | * @return {@code true} if this {@code MathContext} instance is equal to the | 
|  | *         {@code x} argument; {@code false} otherwise. | 
|  | */ | 
|  | @Override | 
|  | public boolean equals(Object x) { | 
|  | return ((x instanceof MathContext) | 
|  | && (((MathContext) x).getPrecision() == precision) && (((MathContext) x) | 
|  | .getRoundingMode() == roundingMode)); | 
|  | } | 
|  |  | 
|  | /** | 
|  | * Returns the hash code for this {@code MathContext} instance. | 
|  | * | 
|  | * @return the hash code for this {@code MathContext}. | 
|  | */ | 
|  | @Override | 
|  | public int hashCode() { | 
|  | // Make place for the necessary bits to represent 8 rounding modes | 
|  | return ((precision << 3) | roundingMode.ordinal()); | 
|  | } | 
|  |  | 
|  | /** | 
|  | * Returns the string representation for this {@code MathContext} instance. | 
|  | * The string has the form | 
|  | * {@code | 
|  | * "precision=<precision> roundingMode=<roundingMode>" | 
|  | * } where {@code <precision>} is an integer describing the number | 
|  | * of digits used for operations and {@code <roundingMode>} is the | 
|  | * string representation of the rounding mode. | 
|  | * | 
|  | * @return a string representation for this {@code MathContext} instance | 
|  | */ | 
|  | @Override | 
|  | public String toString() { | 
|  | return "precision=" + precision + " roundingMode=" + roundingMode; | 
|  | } | 
|  |  | 
|  | /** | 
|  | * Makes checks upon deserialization of a {@code MathContext} instance. | 
|  | * Checks whether {@code precision >= 0} and {@code roundingMode != null} | 
|  | * | 
|  | * @throws StreamCorruptedException | 
|  | *             if {@code precision < 0} | 
|  | * @throws StreamCorruptedException | 
|  | *             if {@code roundingMode == null} | 
|  | */ | 
|  | private void readObject(ObjectInputStream s) throws IOException, ClassNotFoundException { | 
|  | s.defaultReadObject(); | 
|  | try { | 
|  | checkValid(); | 
|  | } catch (Exception ex) { | 
|  | throw new StreamCorruptedException(ex.getMessage()); | 
|  | } | 
|  | } | 
|  | } |