source: src/main/java/agents/org/apache/commons/math/dfp/DfpDec.java

Last change on this file was 1, checked in by Wouter Pasman, 7 years ago

Initial import : Genius 9.0.0

File size: 10.9 KB
Line 
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
18package agents.org.apache.commons.math.dfp;
19
20/** Subclass of {@link Dfp} which hides the radix-10000 artifacts of the superclass.
21 * This should give outward appearances of being a decimal number with DIGITS*4-3
22 * decimal digits. This class can be subclassed to appear to be an arbitrary number
23 * of decimal digits less than DIGITS*4-3.
24 * @version $Revision: 1003892 $ $Date: 2010-10-02 23:28:56 +0200 (sam. 02 oct. 2010) $
25 * @since 2.2
26 */
27public class DfpDec extends Dfp {
28
29 /** Makes an instance with a value of zero.
30 * @param factory factory linked to this instance
31 */
32 protected DfpDec(final DfpField factory) {
33 super(factory);
34 }
35
36 /** Create an instance from a byte value.
37 * @param factory factory linked to this instance
38 * @param x value to convert to an instance
39 */
40 protected DfpDec(final DfpField factory, byte x) {
41 super(factory, x);
42 }
43
44 /** Create an instance from an int value.
45 * @param factory factory linked to this instance
46 * @param x value to convert to an instance
47 */
48 protected DfpDec(final DfpField factory, int x) {
49 super(factory, x);
50 }
51
52 /** Create an instance from a long value.
53 * @param factory factory linked to this instance
54 * @param x value to convert to an instance
55 */
56 protected DfpDec(final DfpField factory, long x) {
57 super(factory, x);
58 }
59
60 /** Create an instance from a double value.
61 * @param factory factory linked to this instance
62 * @param x value to convert to an instance
63 */
64 protected DfpDec(final DfpField factory, double x) {
65 super(factory, x);
66 round(0);
67 }
68
69 /** Copy constructor.
70 * @param d instance to copy
71 */
72 public DfpDec(final Dfp d) {
73 super(d);
74 round(0);
75 }
76
77 /** Create an instance from a String representation.
78 * @param factory factory linked to this instance
79 * @param s string representation of the instance
80 */
81 protected DfpDec(final DfpField factory, final String s) {
82 super(factory, s);
83 round(0);
84 }
85
86 /** Creates an instance with a non-finite value.
87 * @param factory factory linked to this instance
88 * @param sign sign of the Dfp to create
89 * @param nans code of the value, must be one of {@link #INFINITE},
90 * {@link #SNAN}, {@link #QNAN}
91 */
92 protected DfpDec(final DfpField factory, final byte sign, final byte nans) {
93 super(factory, sign, nans);
94 }
95
96 /** {@inheritDoc} */
97 @Override
98 public Dfp newInstance() {
99 return new DfpDec(getField());
100 }
101
102 /** {@inheritDoc} */
103 @Override
104 public Dfp newInstance(final byte x) {
105 return new DfpDec(getField(), x);
106 }
107
108 /** {@inheritDoc} */
109 @Override
110 public Dfp newInstance(final int x) {
111 return new DfpDec(getField(), x);
112 }
113
114 /** {@inheritDoc} */
115 @Override
116 public Dfp newInstance(final long x) {
117 return new DfpDec(getField(), x);
118 }
119
120 /** {@inheritDoc} */
121 @Override
122 public Dfp newInstance(final double x) {
123 return new DfpDec(getField(), x);
124 }
125
126 /** {@inheritDoc} */
127 @Override
128 public Dfp newInstance(final Dfp d) {
129
130 // make sure we don't mix number with different precision
131 if (getField().getRadixDigits() != d.getField().getRadixDigits()) {
132 getField().setIEEEFlagsBits(DfpField.FLAG_INVALID);
133 final Dfp result = newInstance(getZero());
134 result.nans = QNAN;
135 return dotrap(DfpField.FLAG_INVALID, "newInstance", d, result);
136 }
137
138 return new DfpDec(d);
139
140 }
141
142 /** {@inheritDoc} */
143 @Override
144 public Dfp newInstance(final String s) {
145 return new DfpDec(getField(), s);
146 }
147
148 /** {@inheritDoc} */
149 @Override
150 public Dfp newInstance(final byte sign, final byte nans) {
151 return new DfpDec(getField(), sign, nans);
152 }
153
154 /** Get the number of decimal digits this class is going to represent.
155 * Default implementation returns {@link #getRadixDigits()}*4-3. Subclasses can
156 * override this to return something less.
157 * @return number of decimal digits this class is going to represent
158 */
159 protected int getDecimalDigits() {
160 return getRadixDigits() * 4 - 3;
161 }
162
163 /** {@inheritDoc} */
164 @Override
165 protected int round(int in) {
166
167 int msb = mant[mant.length-1];
168 if (msb == 0) {
169 // special case -- this == zero
170 return 0;
171 }
172
173 int cmaxdigits = mant.length * 4;
174 int lsbthreshold = 1000;
175 while (lsbthreshold > msb) {
176 lsbthreshold /= 10;
177 cmaxdigits --;
178 }
179
180
181 final int digits = getDecimalDigits();
182 final int lsbshift = cmaxdigits - digits;
183 final int lsd = lsbshift / 4;
184
185 lsbthreshold = 1;
186 for (int i = 0; i < lsbshift % 4; i++) {
187 lsbthreshold *= 10;
188 }
189
190 final int lsb = mant[lsd];
191
192 if (lsbthreshold <= 1 && digits == 4 * mant.length - 3) {
193 return super.round(in);
194 }
195
196 int discarded = in; // not looking at this after this point
197 final int n;
198 if (lsbthreshold == 1) {
199 // look to the next digit for rounding
200 n = (mant[lsd-1] / 1000) % 10;
201 mant[lsd-1] %= 1000;
202 discarded |= mant[lsd-1];
203 } else {
204 n = (lsb * 10 / lsbthreshold) % 10;
205 discarded |= lsb % (lsbthreshold/10);
206 }
207
208 for (int i = 0; i < lsd; i++) {
209 discarded |= mant[i]; // need to know if there are any discarded bits
210 mant[i] = 0;
211 }
212
213 mant[lsd] = lsb / lsbthreshold * lsbthreshold;
214
215 final boolean inc;
216 switch (getField().getRoundingMode()) {
217 case ROUND_DOWN:
218 inc = false;
219 break;
220
221 case ROUND_UP:
222 inc = (n != 0) || (discarded != 0); // round up if n!=0
223 break;
224
225 case ROUND_HALF_UP:
226 inc = n >= 5; // round half up
227 break;
228
229 case ROUND_HALF_DOWN:
230 inc = n > 5; // round half down
231 break;
232
233 case ROUND_HALF_EVEN:
234 inc = (n > 5) ||
235 (n == 5 && discarded != 0) ||
236 (n == 5 && discarded == 0 && ((lsb / lsbthreshold) & 1) == 1); // round half-even
237 break;
238
239 case ROUND_HALF_ODD:
240 inc = (n > 5) ||
241 (n == 5 && discarded != 0) ||
242 (n == 5 && discarded == 0 && ((lsb / lsbthreshold) & 1) == 0); // round half-odd
243 break;
244
245 case ROUND_CEIL:
246 inc = (sign == 1) && (n != 0 || discarded != 0); // round ceil
247 break;
248
249 case ROUND_FLOOR:
250 default:
251 inc = (sign == -1) && (n != 0 || discarded != 0); // round floor
252 break;
253 }
254
255 if (inc) {
256 // increment if necessary
257 int rh = lsbthreshold;
258 for (int i = lsd; i < mant.length; i++) {
259 final int r = mant[i] + rh;
260 rh = r / RADIX;
261 mant[i] = r % RADIX;
262 }
263
264 if (rh != 0) {
265 shiftRight();
266 mant[mant.length-1]=rh;
267 }
268 }
269
270 // Check for exceptional cases and raise signals if necessary
271 if (exp < MIN_EXP) {
272 // Gradual Underflow
273 getField().setIEEEFlagsBits(DfpField.FLAG_UNDERFLOW);
274 return DfpField.FLAG_UNDERFLOW;
275 }
276
277 if (exp > MAX_EXP) {
278 // Overflow
279 getField().setIEEEFlagsBits(DfpField.FLAG_OVERFLOW);
280 return DfpField.FLAG_OVERFLOW;
281 }
282
283 if (n != 0 || discarded != 0) {
284 // Inexact
285 getField().setIEEEFlagsBits(DfpField.FLAG_INEXACT);
286 return DfpField.FLAG_INEXACT;
287 }
288 return 0;
289 }
290
291 /** {@inheritDoc} */
292 @Override
293 public Dfp nextAfter(Dfp x) {
294
295 final String trapName = "nextAfter";
296
297 // make sure we don't mix number with different precision
298 if (getField().getRadixDigits() != x.getField().getRadixDigits()) {
299 getField().setIEEEFlagsBits(DfpField.FLAG_INVALID);
300 final Dfp result = newInstance(getZero());
301 result.nans = QNAN;
302 return dotrap(DfpField.FLAG_INVALID, trapName, x, result);
303 }
304
305 boolean up = false;
306 Dfp result;
307 Dfp inc;
308
309 // if this is greater than x
310 if (this.lessThan(x)) {
311 up = true;
312 }
313
314 if (equals(x)) {
315 return newInstance(x);
316 }
317
318 if (lessThan(getZero())) {
319 up = !up;
320 }
321
322 if (up) {
323 inc = power10(log10() - getDecimalDigits() + 1);
324 inc = copysign(inc, this);
325
326 if (this.equals(getZero())) {
327 inc = power10K(MIN_EXP-mant.length-1);
328 }
329
330 if (inc.equals(getZero())) {
331 result = copysign(newInstance(getZero()), this);
332 } else {
333 result = add(inc);
334 }
335 } else {
336 inc = power10(log10());
337 inc = copysign(inc, this);
338
339 if (this.equals(inc)) {
340 inc = inc.divide(power10(getDecimalDigits()));
341 } else {
342 inc = inc.divide(power10(getDecimalDigits() - 1));
343 }
344
345 if (this.equals(getZero())) {
346 inc = power10K(MIN_EXP-mant.length-1);
347 }
348
349 if (inc.equals(getZero())) {
350 result = copysign(newInstance(getZero()), this);
351 } else {
352 result = subtract(inc);
353 }
354 }
355
356 if (result.classify() == INFINITE && this.classify() != INFINITE) {
357 getField().setIEEEFlagsBits(DfpField.FLAG_INEXACT);
358 result = dotrap(DfpField.FLAG_INEXACT, trapName, x, result);
359 }
360
361 if (result.equals(getZero()) && this.equals(getZero()) == false) {
362 getField().setIEEEFlagsBits(DfpField.FLAG_INEXACT);
363 result = dotrap(DfpField.FLAG_INEXACT, trapName, x, result);
364 }
365
366 return result;
367 }
368
369}
Note: See TracBrowser for help on using the repository browser.