OSDN Git Service

original
[gb-231r1-is01/Gingerbread_2.3.3_r1_IS01.git] / libcore / luni / src / main / java / java / math / MathContext.java
1 /*
2  *  Licensed to the Apache Software Foundation (ASF) under one or more
3  *  contributor license agreements.  See the NOTICE file distributed with
4  *  this work for additional information regarding copyright ownership.
5  *  The ASF licenses this file to You under the Apache License, Version 2.0
6  *  (the "License"); you may not use this file except in compliance with
7  *  the License.  You may obtain a copy of the License at
8  *
9  *     http://www.apache.org/licenses/LICENSE-2.0
10  *
11  *  Unless required by applicable law or agreed to in writing, software
12  *  distributed under the License is distributed on an "AS IS" BASIS,
13  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  *  See the License for the specific language governing permissions and
15  *  limitations under the License.
16  */
17
18 package java.math;
19
20 import java.io.IOException;
21 import java.io.ObjectInputStream;
22 import java.io.Serializable;
23 import java.io.StreamCorruptedException;
24
25 /**
26  * Immutable objects describing settings such as rounding mode and digit
27  * precision for the numerical operations provided by class {@link BigDecimal}.
28  */
29 public final class MathContext implements Serializable {
30
31     /**
32      * A {@code MathContext} which corresponds to the IEEE 754r quadruple
33      * decimal precision format: 34 digit precision and
34      * {@link RoundingMode#HALF_EVEN} rounding.
35      */
36     public static final MathContext DECIMAL128 = new MathContext(34,
37             RoundingMode.HALF_EVEN);
38
39     /**
40      * A {@code MathContext} which corresponds to the IEEE 754r single decimal
41      * precision format: 7 digit precision and {@link RoundingMode#HALF_EVEN}
42      * rounding.
43      */
44     public static final MathContext DECIMAL32 = new MathContext(7,
45             RoundingMode.HALF_EVEN);
46
47     /**
48      * A {@code MathContext} which corresponds to the IEEE 754r double decimal
49      * precision format: 16 digit precision and {@link RoundingMode#HALF_EVEN}
50      * rounding.
51      */
52     public static final MathContext DECIMAL64 = new MathContext(16,
53             RoundingMode.HALF_EVEN);
54
55     /**
56      * A {@code MathContext} for unlimited precision with
57      * {@link RoundingMode#HALF_UP} rounding.
58      */
59     public static final MathContext UNLIMITED = new MathContext(0,
60             RoundingMode.HALF_UP);
61
62     /** This is the serialVersionUID used by the sun implementation */
63     private static final long serialVersionUID = 5579720004786848255L;
64
65     /**
66      * The number of digits to be used for an operation; results are rounded to
67      * this precision.
68      */
69     private int precision;
70
71     /**
72      * A {@code RoundingMode} object which specifies the algorithm to be used
73      * for rounding.
74      */
75     private RoundingMode roundingMode;
76
77     /**
78      * An array of {@code char} containing: {@code
79      * 'p','r','e','c','i','s','i','o','n','='}. It's used to improve the
80      * methods related to {@code String} conversion.
81      *
82      * @see #MathContext(String)
83      * @see #toString()
84      */
85     private final static char[] chPrecision = { 'p', 'r', 'e', 'c', 'i', 's',
86             'i', 'o', 'n', '=' };
87
88     /**
89      * An array of {@code char} containing: {@code
90      * 'r','o','u','n','d','i','n','g','M','o','d','e','='}. It's used to
91      * improve the methods related to {@code String} conversion.
92      *
93      * @see #MathContext(String)
94      * @see #toString()
95      */
96     private final static char[] chRoundingMode = { 'r', 'o', 'u', 'n', 'd',
97             'i', 'n', 'g', 'M', 'o', 'd', 'e', '=' };
98
99     /**
100      * Constructs a new {@code MathContext} with the specified precision and
101      * with the rounding mode {@link RoundingMode#HALF_UP HALF_UP}. If the
102      * precision passed is zero, then this implies that the computations have to
103      * be performed exact, the rounding mode in this case is irrelevant.
104      *
105      * @param precision
106      *            the precision for the new {@code MathContext}.
107      * @throws IllegalArgumentException
108      *             if {@code precision < 0}.
109      */
110     public MathContext(int precision) {
111         this(precision, RoundingMode.HALF_UP);
112     }
113
114     /**
115      * Constructs a new {@code MathContext} with the specified precision and
116      * with the specified rounding mode. If the precision passed is zero, then
117      * this implies that the computations have to be performed exact, the
118      * rounding mode in this case is irrelevant.
119      *
120      * @param precision
121      *            the precision for the new {@code MathContext}.
122      * @param roundingMode
123      *            the rounding mode for the new {@code MathContext}.
124      * @throws IllegalArgumentException
125      *             if {@code precision < 0}.
126      * @throws NullPointerException
127      *             if {@code roundingMode} is {@code null}.
128      */
129     public MathContext(int precision, RoundingMode roundingMode) {
130         if (precision < 0) {
131             throw new IllegalArgumentException("precision < 0");
132         }
133         if (roundingMode == null) {
134             throw new NullPointerException("roundingMode == null");
135         }
136         this.precision = precision;
137         this.roundingMode = roundingMode;
138     }
139
140     /**
141      * Constructs a new {@code MathContext} from a string. The string has to
142      * specify the precision and the rounding mode to be used and has to follow
143      * the following syntax: "precision=&lt;precision&gt; roundingMode=&lt;roundingMode&gt;"
144      * This is the same form as the one returned by the {@link #toString}
145      * method.
146      *
147      * @param val
148      *            a string describing the precision and rounding mode for the
149      *            new {@code MathContext}.
150      * @throws IllegalArgumentException
151      *             if the string is not in the correct format or if the
152      *             precision specified is < 0.
153      */
154     public MathContext(String val) {
155         char[] charVal = val.toCharArray();
156         int i; // Index of charVal
157         int j; // Index of chRoundingMode
158         int digit; // It will contain the digit parsed
159
160         if ((charVal.length < 27) || (charVal.length > 45)) {
161             throw new IllegalArgumentException("Bad string format");
162         }
163         // Parsing "precision=" String
164         for (i = 0; (i < chPrecision.length) && (charVal[i] == chPrecision[i]); i++) {
165             ;
166         }
167
168         if (i < chPrecision.length) {
169             throw new IllegalArgumentException("Bad string format");
170         }
171         // Parsing the value for "precision="...
172         digit = Character.digit(charVal[i], 10);
173         if (digit == -1) {
174             throw new IllegalArgumentException("Bad string format");
175         }
176         // BEGIN android-changed
177         this.precision = digit;
178         // END android-changed
179         i++;
180
181         do {
182             digit = Character.digit(charVal[i], 10);
183             if (digit == -1) {
184                 if (charVal[i] == ' ') {
185                     // It parsed all the digits
186                     i++;
187                     break;
188                 }
189                 // It isn't  a valid digit, and isn't a white space
190                 throw new IllegalArgumentException("Bad string format");
191             }
192             // Accumulating the value parsed
193             this.precision = this.precision * 10 + digit;
194             if (this.precision < 0) {
195                 throw new IllegalArgumentException("Bad string format");
196             }
197             i++;
198         } while (true);
199         // Parsing "roundingMode="
200         for (j = 0; (j < chRoundingMode.length)
201                 && (charVal[i] == chRoundingMode[j]); i++, j++) {
202             ;
203         }
204
205         if (j < chRoundingMode.length) {
206             throw new IllegalArgumentException("Bad string format");
207         }
208         // Parsing the value for "roundingMode"...
209         this.roundingMode = RoundingMode.valueOf(String.valueOf(charVal, i,
210                 charVal.length - i));
211     }
212
213     /* Public Methods */
214
215     /**
216      * Returns the precision. The precision is the number of digits used for an
217      * operation. Results are rounded to this precision. The precision is
218      * guaranteed to be non negative. If the precision is zero, then the
219      * computations have to be performed exact, results are not rounded in this
220      * case.
221      *
222      * @return the precision.
223      */
224     public int getPrecision() {
225         return precision;
226     }
227
228     /**
229      * Returns the rounding mode. The rounding mode is the strategy to be used
230      * to round results.
231      * <p>
232      * The rounding mode is one of
233      * {@link RoundingMode#UP},
234      * {@link RoundingMode#DOWN},
235      * {@link RoundingMode#CEILING},
236      * {@link RoundingMode#FLOOR},
237      * {@link RoundingMode#HALF_UP},
238      * {@link RoundingMode#HALF_DOWN},
239      * {@link RoundingMode#HALF_EVEN}, or
240      * {@link RoundingMode#UNNECESSARY}.
241      *
242      * @return the rounding mode.
243      */
244     public RoundingMode getRoundingMode() {
245         return roundingMode;
246     }
247
248     /**
249      * Returns true if x is a {@code MathContext} with the same precision
250      * setting and the same rounding mode as this {@code MathContext} instance.
251      *
252      * @param x
253      *            object to be compared.
254      * @return {@code true} if this {@code MathContext} instance is equal to the
255      *         {@code x} argument; {@code false} otherwise.
256      */
257     @Override
258     public boolean equals(Object x) {
259         return ((x instanceof MathContext)
260                 && (((MathContext) x).getPrecision() == precision) && (((MathContext) x)
261                 .getRoundingMode() == roundingMode));
262     }
263
264     /**
265      * Returns the hash code for this {@code MathContext} instance.
266      *
267      * @return the hash code for this {@code MathContext}.
268      */
269     @Override
270     public int hashCode() {
271         // Make place for the necessary bits to represent 8 rounding modes
272         return ((precision << 3) | roundingMode.ordinal());
273     }
274
275     /**
276      * Returns the string representation for this {@code MathContext} instance.
277      * The string has the form
278      * {@code
279      * "precision=&lt;precision&gt; roundingMode=&lt;roundingMode&gt;"
280      * } where {@code &lt;precision&gt;} is an integer describing the number
281      * of digits used for operations and {@code &lt;roundingMode&gt;} is the
282      * string representation of the rounding mode.
283      *
284      * @return a string representation for this {@code MathContext} instance
285      */
286     @Override
287     public String toString() {
288         return "precision=" + precision + " roundingMode=" + roundingMode;
289     }
290
291     /**
292      * Makes checks upon deserialization of a {@code MathContext} instance.
293      * Checks whether {@code precision >= 0} and {@code roundingMode != null}
294      *
295      * @throws StreamCorruptedException
296      *             if {@code precision < 0}
297      * @throws StreamCorruptedException
298      *             if {@code roundingMode == null}
299      */
300     private void readObject(ObjectInputStream s) throws IOException, ClassNotFoundException {
301         s.defaultReadObject();
302         if (precision < 0) {
303             throw new StreamCorruptedException("precision < 0");
304         }
305         if (roundingMode == null) {
306             throw new StreamCorruptedException("roundingMode == null");
307         }
308     }
309
310 }