emul/compact/src/main/java/java/math/MathContext.java
author Jaroslav Tulach <jaroslav.tulach@apidesign.org>
Sat, 07 Sep 2013 13:51:24 +0200
branchjdk7-b147
changeset 1258 724f3e1ea53e
permissions -rw-r--r--
Additional set of classes to make porting of lookup library more easier
     1 /*
     2  * Copyright (c) 2003, 2007, Oracle and/or its affiliates. All rights reserved.
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     4  *
     5  * This code is free software; you can redistribute it and/or modify it
     6  * under the terms of the GNU General Public License version 2 only, as
     7  * published by the Free Software Foundation.  Oracle designates this
     8  * particular file as subject to the "Classpath" exception as provided
     9  * by Oracle in the LICENSE file that accompanied this code.
    10  *
    11  * This code is distributed in the hope that it will be useful, but WITHOUT
    12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
    14  * version 2 for more details (a copy is included in the LICENSE file that
    15  * accompanied this code).
    16  *
    17  * You should have received a copy of the GNU General Public License version
    18  * 2 along with this work; if not, write to the Free Software Foundation,
    19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
    20  *
    21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
    22  * or visit www.oracle.com if you need additional information or have any
    23  * questions.
    24  */
    25 
    26 /*
    27  * Portions Copyright IBM Corporation, 1997, 2001. All Rights Reserved.
    28  */
    29 
    30 package java.math;
    31 import java.io.*;
    32 
    33 /**
    34  * Immutable objects which encapsulate the context settings which
    35  * describe certain rules for numerical operators, such as those
    36  * implemented by the {@link BigDecimal} class.
    37  *
    38  * <p>The base-independent settings are:
    39  * <ol>
    40  * <li>{@code precision}:
    41  * the number of digits to be used for an operation; results are
    42  * rounded to this precision
    43  *
    44  * <li>{@code roundingMode}:
    45  * a {@link RoundingMode} object which specifies the algorithm to be
    46  * used for rounding.
    47  * </ol>
    48  *
    49  * @see     BigDecimal
    50  * @see     RoundingMode
    51  * @author  Mike Cowlishaw
    52  * @author  Joseph D. Darcy
    53  * @since 1.5
    54  */
    55 
    56 public final class MathContext implements Serializable {
    57 
    58     /* ----- Constants ----- */
    59 
    60     // defaults for constructors
    61     private static final int DEFAULT_DIGITS = 9;
    62     private static final RoundingMode DEFAULT_ROUNDINGMODE = RoundingMode.HALF_UP;
    63     // Smallest values for digits (Maximum is Integer.MAX_VALUE)
    64     private static final int MIN_DIGITS = 0;
    65 
    66     // Serialization version
    67     private static final long serialVersionUID = 5579720004786848255L;
    68 
    69     /* ----- Public Properties ----- */
    70     /**
    71      *  A {@code MathContext} object whose settings have the values
    72      *  required for unlimited precision arithmetic.
    73      *  The values of the settings are:
    74      *  <code>
    75      *  precision=0 roundingMode=HALF_UP
    76      *  </code>
    77      */
    78     public static final MathContext UNLIMITED =
    79         new MathContext(0, RoundingMode.HALF_UP);
    80 
    81     /**
    82      *  A {@code MathContext} object with a precision setting
    83      *  matching the IEEE 754R Decimal32 format, 7 digits, and a
    84      *  rounding mode of {@link RoundingMode#HALF_EVEN HALF_EVEN}, the
    85      *  IEEE 754R default.
    86      */
    87     public static final MathContext DECIMAL32 =
    88         new MathContext(7, RoundingMode.HALF_EVEN);
    89 
    90     /**
    91      *  A {@code MathContext} object with a precision setting
    92      *  matching the IEEE 754R Decimal64 format, 16 digits, and a
    93      *  rounding mode of {@link RoundingMode#HALF_EVEN HALF_EVEN}, the
    94      *  IEEE 754R default.
    95      */
    96     public static final MathContext DECIMAL64 =
    97         new MathContext(16, RoundingMode.HALF_EVEN);
    98 
    99     /**
   100      *  A {@code MathContext} object with a precision setting
   101      *  matching the IEEE 754R Decimal128 format, 34 digits, and a
   102      *  rounding mode of {@link RoundingMode#HALF_EVEN HALF_EVEN}, the
   103      *  IEEE 754R default.
   104      */
   105     public static final MathContext DECIMAL128 =
   106         new MathContext(34, RoundingMode.HALF_EVEN);
   107 
   108     /* ----- Shared Properties ----- */
   109     /**
   110      * The number of digits to be used for an operation.  A value of 0
   111      * indicates that unlimited precision (as many digits as are
   112      * required) will be used.  Note that leading zeros (in the
   113      * coefficient of a number) are never significant.
   114      *
   115      * <p>{@code precision} will always be non-negative.
   116      *
   117      * @serial
   118      */
   119     final int precision;
   120 
   121     /**
   122      * The rounding algorithm to be used for an operation.
   123      *
   124      * @see RoundingMode
   125      * @serial
   126      */
   127     final RoundingMode roundingMode;
   128 
   129     /* ----- Constructors ----- */
   130 
   131     /**
   132      * Constructs a new {@code MathContext} with the specified
   133      * precision and the {@link RoundingMode#HALF_UP HALF_UP} rounding
   134      * mode.
   135      *
   136      * @param setPrecision The non-negative {@code int} precision setting.
   137      * @throws IllegalArgumentException if the {@code setPrecision} parameter is less
   138      *         than zero.
   139      */
   140     public MathContext(int setPrecision) {
   141         this(setPrecision, DEFAULT_ROUNDINGMODE);
   142         return;
   143     }
   144 
   145     /**
   146      * Constructs a new {@code MathContext} with a specified
   147      * precision and rounding mode.
   148      *
   149      * @param setPrecision The non-negative {@code int} precision setting.
   150      * @param setRoundingMode The rounding mode to use.
   151      * @throws IllegalArgumentException if the {@code setPrecision} parameter is less
   152      *         than zero.
   153      * @throws NullPointerException if the rounding mode argument is {@code null}
   154      */
   155     public MathContext(int setPrecision,
   156                        RoundingMode setRoundingMode) {
   157         if (setPrecision < MIN_DIGITS)
   158             throw new IllegalArgumentException("Digits < 0");
   159         if (setRoundingMode == null)
   160             throw new NullPointerException("null RoundingMode");
   161 
   162         precision = setPrecision;
   163         roundingMode = setRoundingMode;
   164         return;
   165     }
   166 
   167     /**
   168      * Constructs a new {@code MathContext} from a string.
   169      *
   170      * The string must be in the same format as that produced by the
   171      * {@link #toString} method.
   172      *
   173      * <p>An {@code IllegalArgumentException} is thrown if the precision
   174      * section of the string is out of range ({@code < 0}) or the string is
   175      * not in the format created by the {@link #toString} method.
   176      *
   177      * @param val The string to be parsed
   178      * @throws IllegalArgumentException if the precision section is out of range
   179      * or of incorrect format
   180      * @throws NullPointerException if the argument is {@code null}
   181      */
   182     public MathContext(String val) {
   183         boolean bad = false;
   184         int setPrecision;
   185         if (val == null)
   186             throw new NullPointerException("null String");
   187         try { // any error here is a string format problem
   188             if (!val.startsWith("precision=")) throw new RuntimeException();
   189             int fence = val.indexOf(' ');    // could be -1
   190             int off = 10;                     // where value starts
   191             setPrecision = Integer.parseInt(val.substring(10, fence));
   192 
   193             if (!val.startsWith("roundingMode=", fence+1))
   194                 throw new RuntimeException();
   195             off = fence + 1 + 13;
   196             String str = val.substring(off, val.length());
   197             roundingMode = RoundingMode.valueOf(str);
   198         } catch (RuntimeException re) {
   199             throw new IllegalArgumentException("bad string format");
   200         }
   201 
   202         if (setPrecision < MIN_DIGITS)
   203             throw new IllegalArgumentException("Digits < 0");
   204         // the other parameters cannot be invalid if we got here
   205         precision = setPrecision;
   206     }
   207 
   208     /**
   209      * Returns the {@code precision} setting.
   210      * This value is always non-negative.
   211      *
   212      * @return an {@code int} which is the value of the {@code precision}
   213      *         setting
   214      */
   215     public int getPrecision() {
   216         return precision;
   217     }
   218 
   219     /**
   220      * Returns the roundingMode setting.
   221      * This will be one of
   222      * {@link  RoundingMode#CEILING},
   223      * {@link  RoundingMode#DOWN},
   224      * {@link  RoundingMode#FLOOR},
   225      * {@link  RoundingMode#HALF_DOWN},
   226      * {@link  RoundingMode#HALF_EVEN},
   227      * {@link  RoundingMode#HALF_UP},
   228      * {@link  RoundingMode#UNNECESSARY}, or
   229      * {@link  RoundingMode#UP}.
   230      *
   231      * @return a {@code RoundingMode} object which is the value of the
   232      *         {@code roundingMode} setting
   233      */
   234 
   235     public RoundingMode getRoundingMode() {
   236         return roundingMode;
   237     }
   238 
   239     /**
   240      * Compares this {@code MathContext} with the specified
   241      * {@code Object} for equality.
   242      *
   243      * @param  x {@code Object} to which this {@code MathContext} is to
   244      *         be compared.
   245      * @return {@code true} if and only if the specified {@code Object} is
   246      *         a {@code MathContext} object which has exactly the same
   247      *         settings as this object
   248      */
   249     public boolean equals(Object x){
   250         MathContext mc;
   251         if (!(x instanceof MathContext))
   252             return false;
   253         mc = (MathContext) x;
   254         return mc.precision == this.precision
   255             && mc.roundingMode == this.roundingMode; // no need for .equals()
   256     }
   257 
   258     /**
   259      * Returns the hash code for this {@code MathContext}.
   260      *
   261      * @return hash code for this {@code MathContext}
   262      */
   263     public int hashCode() {
   264         return this.precision + roundingMode.hashCode() * 59;
   265     }
   266 
   267     /**
   268      * Returns the string representation of this {@code MathContext}.
   269      * The {@code String} returned represents the settings of the
   270      * {@code MathContext} object as two space-delimited words
   271      * (separated by a single space character, <tt>'&#92;u0020'</tt>,
   272      * and with no leading or trailing white space), as follows:
   273      * <ol>
   274      * <li>
   275      * The string {@code "precision="}, immediately followed
   276      * by the value of the precision setting as a numeric string as if
   277      * generated by the {@link Integer#toString(int) Integer.toString}
   278      * method.
   279      *
   280      * <li>
   281      * The string {@code "roundingMode="}, immediately
   282      * followed by the value of the {@code roundingMode} setting as a
   283      * word.  This word will be the same as the name of the
   284      * corresponding public constant in the {@link RoundingMode}
   285      * enum.
   286      * </ol>
   287      * <p>
   288      * For example:
   289      * <pre>
   290      * precision=9 roundingMode=HALF_UP
   291      * </pre>
   292      *
   293      * Additional words may be appended to the result of
   294      * {@code toString} in the future if more properties are added to
   295      * this class.
   296      *
   297      * @return a {@code String} representing the context settings
   298      */
   299     public java.lang.String toString() {
   300         return "precision=" +           precision + " " +
   301                "roundingMode=" +        roundingMode.toString();
   302     }
   303 
   304     // Private methods
   305 
   306     /**
   307      * Reconstitute the {@code MathContext} instance from a stream (that is,
   308      * deserialize it).
   309      *
   310      * @param s the stream being read.
   311      */
   312     private void readObject(java.io.ObjectInputStream s)
   313         throws java.io.IOException, ClassNotFoundException {
   314         s.defaultReadObject();     // read in all fields
   315         // validate possibly bad fields
   316         if (precision < MIN_DIGITS) {
   317             String message = "MathContext: invalid digits in stream";
   318             throw new java.io.StreamCorruptedException(message);
   319         }
   320         if (roundingMode == null) {
   321             String message = "MathContext: null roundingMode in stream";
   322             throw new java.io.StreamCorruptedException(message);
   323         }
   324     }
   325 
   326 }