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