1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package org.apache.commons.math4.legacy.core.dfp;
19
20
21
22
23
24
25
26 public class DfpDec extends Dfp {
27
28
29
30
31 protected DfpDec(final DfpField factory) {
32 super(factory);
33 }
34
35
36
37
38
39 protected DfpDec(final DfpField factory, byte x) {
40 super(factory, x);
41 }
42
43
44
45
46
47 protected DfpDec(final DfpField factory, int x) {
48 super(factory, x);
49 }
50
51
52
53
54
55 protected DfpDec(final DfpField factory, long x) {
56 super(factory, x);
57 }
58
59
60
61
62
63 protected DfpDec(final DfpField factory, double x) {
64 super(factory, x);
65 round(0);
66 }
67
68
69
70
71 public DfpDec(final Dfp d) {
72 super(d);
73 round(0);
74 }
75
76
77
78
79
80 protected DfpDec(final DfpField factory, final String s) {
81 super(factory, s);
82 round(0);
83 }
84
85
86
87
88
89
90
91 protected DfpDec(final DfpField factory, final byte sign, final byte nans) {
92 super(factory, sign, nans);
93 }
94
95
96 @Override
97 public Dfp newInstance() {
98 return new DfpDec(getField());
99 }
100
101
102 @Override
103 public Dfp newInstance(final byte x) {
104 return new DfpDec(getField(), x);
105 }
106
107
108 @Override
109 public Dfp newInstance(final int x) {
110 return new DfpDec(getField(), x);
111 }
112
113
114 @Override
115 public Dfp newInstance(final long x) {
116 return new DfpDec(getField(), x);
117 }
118
119
120 @Override
121 public Dfp newInstance(final double x) {
122 return new DfpDec(getField(), x);
123 }
124
125
126 @Override
127 public Dfp newInstance(final Dfp d) {
128
129
130 if (getField().getRadixDigits() != d.getField().getRadixDigits()) {
131 getField().setIEEEFlagsBits(DfpField.FLAG_INVALID);
132 final Dfp result = newInstance(getZero());
133 result.nans = QNAN;
134 return dotrap(DfpField.FLAG_INVALID, "newInstance", d, result);
135 }
136
137 return new DfpDec(d);
138 }
139
140
141 @Override
142 public Dfp newInstance(final String s) {
143 return new DfpDec(getField(), s);
144 }
145
146
147 @Override
148 public Dfp newInstance(final byte sign, final byte nans) {
149 return new DfpDec(getField(), sign, nans);
150 }
151
152
153
154
155
156
157 protected int getDecimalDigits() {
158 return getRadixDigits() * 4 - 3;
159 }
160
161
162 @Override
163 protected int round(int in) {
164
165 int msb = mant[mant.length - 1];
166 if (msb == 0) {
167
168 return 0;
169 }
170
171 int cmaxdigits = mant.length * 4;
172 int lsbthreshold = 1000;
173 while (lsbthreshold > msb) {
174 lsbthreshold /= 10;
175 cmaxdigits--;
176 }
177
178
179 final int digits = getDecimalDigits();
180 final int lsbshift = cmaxdigits - digits;
181 final int lsd = lsbshift / 4;
182
183 lsbthreshold = 1;
184 for (int i = 0; i < lsbshift % 4; i++) {
185 lsbthreshold *= 10;
186 }
187
188 final int lsb = mant[lsd];
189
190 if (lsbthreshold <= 1 && digits == 4 * mant.length - 3) {
191 return super.round(in);
192 }
193
194 int discarded = in;
195 final int n;
196 if (lsbthreshold == 1) {
197
198 n = (mant[lsd - 1] / 1000) % 10;
199 mant[lsd - 1] %= 1000;
200 discarded |= mant[lsd - 1];
201 } else {
202 n = (lsb * 10 / lsbthreshold) % 10;
203 discarded |= lsb % (lsbthreshold / 10);
204 }
205
206 for (int i = 0; i < lsd; i++) {
207 discarded |= mant[i];
208 mant[i] = 0;
209 }
210
211 mant[lsd] = lsb / lsbthreshold * lsbthreshold;
212
213 final boolean inc;
214 switch (getField().getRoundingMode()) {
215 case ROUND_DOWN:
216 inc = false;
217 break;
218
219 case ROUND_UP:
220 inc = (n != 0) || (discarded != 0);
221 break;
222
223 case ROUND_HALF_UP:
224 inc = n >= 5;
225 break;
226
227 case ROUND_HALF_DOWN:
228 inc = n > 5;
229 break;
230
231 case ROUND_HALF_EVEN:
232 inc = (n > 5) ||
233 (n == 5 && discarded != 0) ||
234 (n == 5 && discarded == 0 && ((lsb / lsbthreshold) & 1) == 1);
235 break;
236
237 case ROUND_HALF_ODD:
238 inc = (n > 5) ||
239 (n == 5 && discarded != 0) ||
240 (n == 5 && discarded == 0 && ((lsb / lsbthreshold) & 1) == 0);
241 break;
242
243 case ROUND_CEIL:
244 inc = (sign == 1) && (n != 0 || discarded != 0);
245 break;
246
247 case ROUND_FLOOR:
248 default:
249 inc = (sign == -1) && (n != 0 || discarded != 0);
250 break;
251 }
252
253 if (inc) {
254
255 int rh = lsbthreshold;
256 for (int i = lsd; i < mant.length; i++) {
257 final int r = mant[i] + rh;
258 rh = r / RADIX;
259 mant[i] = r % RADIX;
260 }
261
262 if (rh != 0) {
263 shiftRight();
264 mant[mant.length - 1] = rh;
265 }
266 }
267
268
269 if (exp < MIN_EXP) {
270
271 getField().setIEEEFlagsBits(DfpField.FLAG_UNDERFLOW);
272 return DfpField.FLAG_UNDERFLOW;
273 }
274
275 if (exp > MAX_EXP) {
276
277 getField().setIEEEFlagsBits(DfpField.FLAG_OVERFLOW);
278 return DfpField.FLAG_OVERFLOW;
279 }
280
281 if (n != 0 || discarded != 0) {
282
283 getField().setIEEEFlagsBits(DfpField.FLAG_INEXACT);
284 return DfpField.FLAG_INEXACT;
285 }
286 return 0;
287 }
288
289
290 @Override
291 public Dfp nextAfter(Dfp x) {
292
293 final String trapName = "nextAfter";
294
295
296 if (getField().getRadixDigits() != x.getField().getRadixDigits()) {
297 getField().setIEEEFlagsBits(DfpField.FLAG_INVALID);
298 final Dfp result = newInstance(getZero());
299 result.nans = QNAN;
300 return dotrap(DfpField.FLAG_INVALID, trapName, x, result);
301 }
302
303 boolean up = false;
304 Dfp result;
305 Dfp inc;
306
307
308 if (this.lessThan(x)) {
309 up = true;
310 }
311
312 if (equals(x)) {
313 return newInstance(x);
314 }
315
316 if (lessThan(getZero())) {
317 up = !up;
318 }
319
320 if (up) {
321 inc = power10(intLog10() - getDecimalDigits() + 1);
322 inc = copySign(inc, this);
323
324 if (this.equals(getZero())) {
325 inc = power10K(MIN_EXP - mant.length - 1);
326 }
327
328 if (inc.equals(getZero())) {
329 result = copySign(newInstance(getZero()), this);
330 } else {
331 result = add(inc);
332 }
333 } else {
334 inc = power10(intLog10());
335 inc = copySign(inc, this);
336
337 if (this.equals(inc)) {
338 inc = inc.divide(power10(getDecimalDigits()));
339 } else {
340 inc = inc.divide(power10(getDecimalDigits() - 1));
341 }
342
343 if (this.equals(getZero())) {
344 inc = power10K(MIN_EXP - mant.length - 1);
345 }
346
347 if (inc.equals(getZero())) {
348 result = copySign(newInstance(getZero()), this);
349 } else {
350 result = subtract(inc);
351 }
352 }
353
354 if (result.classify() == INFINITE && this.classify() != INFINITE) {
355 getField().setIEEEFlagsBits(DfpField.FLAG_INEXACT);
356 result = dotrap(DfpField.FLAG_INEXACT, trapName, x, result);
357 }
358
359 if (result.equals(getZero()) && !this.equals(getZero())) {
360 getField().setIEEEFlagsBits(DfpField.FLAG_INEXACT);
361 result = dotrap(DfpField.FLAG_INEXACT, trapName, x, result);
362 }
363
364 return result;
365 }
366 }