001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */
017:
018: package java.math;
019:
020: import java.io.IOException;
021: import java.io.ObjectInputStream;
022: import java.io.Serializable;
023: import java.io.StreamCorruptedException;
024:
025: import org.apache.harmony.math.internal.nls.Messages;
026:
027: /**
028: * @author Intel Middleware Product Division
029: * @author Instituto Tecnologico de Cordoba
030: */
031: public final class MathContext implements Serializable {
032:
033: /* Fields */
034:
035: /** @ar.org.fitc.spec_ref */
036: public static final MathContext DECIMAL128 = new MathContext(34,
037: RoundingMode.HALF_EVEN);
038:
039: /** @ar.org.fitc.spec_ref */
040: public static final MathContext DECIMAL32 = new MathContext(7,
041: RoundingMode.HALF_EVEN);
042:
043: /** @ar.org.fitc.spec_ref */
044: public static final MathContext DECIMAL64 = new MathContext(16,
045: RoundingMode.HALF_EVEN);
046:
047: /** @ar.org.fitc.spec_ref */
048: public static final MathContext UNLIMITED = new MathContext(0,
049: RoundingMode.HALF_UP);
050:
051: /** @ar.org.fitc.spec_ref */
052: private static final long serialVersionUID = 5579720004786848255L;
053:
054: /**
055: * The number of digits to be used for an operation;
056: * results are rounded to this precision.
057: */
058: private int precision;
059:
060: /**
061: * A {@code RoundingMode} object which specifies
062: * the algorithm to be used for rounding.
063: */
064: private RoundingMode roundingMode;
065:
066: /**
067: * An array of {@code char} containing:
068: * {@code 'p','r','e','c','i','s','i','o','n','='}.
069: * It's used to improve the methods related to {@code String} conversion.
070: * @see #MathContext(String)
071: * @see #toString()
072: */
073: private final static char[] chPrecision = { 'p', 'r', 'e', 'c',
074: 'i', 's', 'i', 'o', 'n', '=' };
075:
076: /**
077: * An array of {@code char} containing:
078: * {@code 'r','o','u','n','d','i','n','g','M','o','d','e','='}.
079: * It's used to improve the methods related to {@code String} conversion.
080: * @see #MathContext(String)
081: * @see #toString()
082: */
083: private final static char[] chRoundingMode = { 'r', 'o', 'u', 'n',
084: 'd', 'i', 'n', 'g', 'M', 'o', 'd', 'e', '=' };
085:
086: /* Constructors */
087:
088: /** @ar.org.fitc.spec_ref */
089: public MathContext(int setPrecision) {
090: this (setPrecision, RoundingMode.HALF_UP);
091: }
092:
093: /** @ar.org.fitc.spec_ref */
094: public MathContext(int setPrecision, RoundingMode setRoundingMode) {
095: if (setPrecision < 0) {
096: // math.0C=Digits < 0
097: throw new IllegalArgumentException(Messages
098: .getString("math.0C")); //$NON-NLS-1$
099: }
100: if (setRoundingMode == null) {
101: // math.0D=null RoundingMode
102: throw new NullPointerException(Messages
103: .getString("math.0D")); //$NON-NLS-1$
104: }
105: precision = setPrecision;
106: roundingMode = setRoundingMode;
107: }
108:
109: /** @ar.org.fitc.spec_ref */
110: public MathContext(String val) {
111: char[] charVal = val.toCharArray();
112: int i; // Index of charVal
113: int j; // Index of chRoundingMode
114: int digit; // It will contain the digit parsed
115:
116: if ((charVal.length < 27) || (charVal.length > 45)) {
117: // math.0E=bad string format
118: throw new IllegalArgumentException(Messages
119: .getString("math.0E")); //$NON-NLS-1$
120: }
121: // Parsing "precision=" String
122: for (i = 0; (i < chPrecision.length)
123: && (charVal[i] == chPrecision[i]); i++) {
124: ;
125: }
126:
127: if (i < chPrecision.length) {
128: // math.0E=bad string format
129: throw new IllegalArgumentException(Messages
130: .getString("math.0E")); //$NON-NLS-1$
131: }
132: // Parsing the value for "precision="...
133: digit = Character.digit(charVal[i], 10);
134: if (digit == -1) {
135: // math.0E=bad string format
136: throw new IllegalArgumentException(Messages
137: .getString("math.0E")); //$NON-NLS-1$
138: }
139: this .precision = this .precision * 10 + digit;
140: i++;
141:
142: do {
143: digit = Character.digit(charVal[i], 10);
144: if (digit == -1) {
145: if (charVal[i] == ' ') {
146: // It parsed all the digits
147: i++;
148: break;
149: }
150: // It isn't a valid digit, and isn't a white space
151: // math.0E=bad string format
152: throw new IllegalArgumentException(Messages
153: .getString("math.0E")); //$NON-NLS-1$
154: }
155: // Accumulating the value parsed
156: this .precision = this .precision * 10 + digit;
157: if (this .precision < 0) {
158: // math.0E=bad string format
159: throw new IllegalArgumentException(Messages
160: .getString("math.0E")); //$NON-NLS-1$
161: }
162: i++;
163: } while (true);
164: // Parsing "roundingMode="
165: for (j = 0; (j < chRoundingMode.length)
166: && (charVal[i] == chRoundingMode[j]); i++, j++) {
167: ;
168: }
169:
170: if (j < chRoundingMode.length) {
171: // math.0E=bad string format
172: throw new IllegalArgumentException(Messages
173: .getString("math.0E")); //$NON-NLS-1$
174: }
175: // Parsing the value for "roundingMode"...
176: this .roundingMode = RoundingMode.valueOf(String.valueOf(
177: charVal, i, charVal.length - i));
178: }
179:
180: /* Public Methods */
181:
182: /** @ar.org.fitc.spec_ref */
183: public int getPrecision() {
184: return precision;
185: }
186:
187: /** @ar.org.fitc.spec_ref */
188: public RoundingMode getRoundingMode() {
189: return roundingMode;
190: }
191:
192: /** @ar.org.fitc.spec_ref */
193: @Override
194: public boolean equals(Object x) {
195: return ((x instanceof MathContext)
196: && (((MathContext) x).getPrecision() == precision) && (((MathContext) x)
197: .getRoundingMode() == roundingMode));
198: }
199:
200: /** @ar.org.fitc.spec_ref */
201: @Override
202: public int hashCode() {
203: // Make place for the necessary bits to represent 8 rounding modes
204: return ((precision << 3) | roundingMode.ordinal());
205: }
206:
207: /** @ar.org.fitc.spec_ref */
208: @Override
209: public String toString() {
210: StringBuffer sb = new StringBuffer(45);
211:
212: sb.append(chPrecision);
213: sb.append(precision);
214: sb.append(' ');
215: sb.append(chRoundingMode);
216: sb.append(roundingMode);
217: return sb.toString();
218: }
219:
220: /** @ar.org.fitc.spec_ref */
221: private void readObject(ObjectInputStream s) throws IOException,
222: ClassNotFoundException {
223: s.defaultReadObject();
224: if (precision < 0) {
225: // math.0F=bad precision value
226: throw new StreamCorruptedException(Messages
227: .getString("math.0F")); //$NON-NLS-1$
228: }
229: if (roundingMode == null) {
230: // math.10=null roundingMode
231: throw new StreamCorruptedException(Messages
232: .getString("math.10")); //$NON-NLS-1$
233: }
234: }
235:
236: }
|