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