Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/openj9
Path: blob/master/jcl/src/java.base/share/classes/com/ibm/jit/BigDecimalExtension.java
12628 views
1
/*[INCLUDE-IF]*/
2
package com.ibm.jit;
3
4
import java.math.BigDecimal;
5
import java.math.BigInteger;
6
import java.math.MathContext;
7
import java.math.RoundingMode;
8
import java.util.Arrays;
9
10
/*******************************************************************************
11
* Copyright (c) 2009, 2021 IBM Corp. and others
12
*
13
* This program and the accompanying materials are made available under
14
* the terms of the Eclipse Public License 2.0 which accompanies this
15
* distribution and is available at https://www.eclipse.org/legal/epl-2.0/
16
* or the Apache License, Version 2.0 which accompanies this distribution and
17
* is available at https://www.apache.org/licenses/LICENSE-2.0.
18
*
19
* This Source Code may also be made available under the following
20
* Secondary Licenses when the conditions for such availability set
21
* forth in the Eclipse Public License, v. 2.0 are satisfied: GNU
22
* General Public License, version 2 with the GNU Classpath
23
* Exception [1] and GNU General Public License, version 2 with the
24
* OpenJDK Assembly Exception [2].
25
*
26
* [1] https://www.gnu.org/software/classpath/license.html
27
* [2] http://openjdk.java.net/legal/assembly-exception.html
28
*
29
* SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 OR LicenseRef-GPL-2.0 WITH Assembly-exception
30
*******************************************************************************/
31
32
public class BigDecimalExtension implements java.math.BigDecimal.BigDecimalExtension {
33
// Used to keep behavior of DFPHWAvailable consistent between
34
// jitted code and interpreter
35
// DO NOT CHANGE OR MOVE THIS LINE
36
// IT MUST BE THE FIRST THING IN THE INITIALIZATION
37
private static final boolean DFP_HW_AVAILABLE = DFPCheckHWAvailable();
38
39
/*
40
* public static final int ROUND_CEILING 2
41
* DFP hardware uses the value 010 == 2
42
* public static final int ROUND_DOWN 1
43
* DFP hardware uses the value 001 = 1
44
* public static final int ROUND_FLOOR 3
45
* DFP hardware uses the value 011 = 3
46
* public static final int ROUND_HALF_DOWN 5
47
* DFP hardware uses the value 101 = 5
48
* public static final int ROUND_HALF_EVEN 6 <--mismatch in HW/Classlib spec
49
* DFP hardware uses the value 000 = 0
50
* public static final int ROUND_HALF_UP 4
51
* DFP hardware uses the value 100 = 4
52
* public static final int ROUND_UNNECESSARY 7
53
* DFP hardware uses the value 111 = 7
54
* public static final int ROUND_UP 0 <--mismatch in HW/Classlib spec
55
* DFP hardware uses the value 110 = 6
56
*/
57
58
/**
59
* LUT for DFP double combination field - gives us the leftmost
60
* digit of the coefficient, as well as the first two bits of the
61
* exponent in form: 0xXY where X = LMD, Y = first two bits
62
*/
63
private static byte []doubleDFPComboField = comboinit();
64
65
// LUT for converting DPD to BCD, 1024 elements
66
private static short []DPD2BCD = dpd2bcdinit();
67
68
// DFP 0 with exponent 0
69
private static final long dfpZERO = 2465720795985346560L;
70
71
private static final BigInteger MAXDFP64 = BigInteger.valueOf(9999999999999999L);
72
private static final BigInteger MINDFP64 = BigInteger.valueOf(-9999999999999999L);
73
74
/* Used for Hysteresis for mixed-representation
75
* We want the BigDecimal class to choose the best representation
76
* for construction and operations. We start assuming the LL
77
* is the best representation. Over the course of time, using
78
* hysterisis, we might alter this decision.
79
*
80
* The constructors are annotated with the checks on deciding
81
* which representation to use, and other APIs contribute
82
* to biasing towards or away from a representation.
83
*
84
* NOTE: Hysterisis only works on platforms that supports DFP
85
* since we prepend a DFPHWAvailable check before performing
86
* mods to the counters, and before basing decisions off them.
87
*/
88
private static int hys_threshold = 1000; // threshold for representation change
89
// above means that hys_counter must reach -/+ MAX_VALUE before changing rep
90
private static boolean hys_type; // false = non-dfp, true = dfp
91
private static int hys_counter; // increment for dfp, decrement for non-dfp
92
93
private static BigDecimalExtension instance;
94
95
protected BigDecimalExtension() {
96
}
97
98
public static BigDecimalExtension getInstance() {
99
if (instance == null) {
100
instance = new BigDecimalExtension();
101
}
102
return instance;
103
}
104
105
public boolean performHardwareUsageHeuristic(MathContext set, int bias) {
106
if (DFPPerformHysteresis() &&
107
set.getPrecision() == 16 && set.getRoundingMode().ordinal() == BigDecimal.ROUND_HALF_EVEN){
108
performHardwareUsageHeuristic(bias);
109
return true;
110
}
111
return false;
112
}
113
114
private void performHardwareUsageHeuristic(int bias) {
115
int sum = hys_counter + bias;
116
hys_counter += bias & ~(((sum^bias) & (sum^hys_counter)) >>> 31);
117
118
if (hys_counter<-hys_threshold){
119
hys_type = false; //nonDFP
120
hys_counter=0;
121
}
122
else if (hys_counter>hys_threshold){
123
hys_type = true; // DFP
124
hys_counter=0;
125
}
126
}
127
128
public boolean isAvailable() {
129
return DFPHWAvailable();
130
}
131
132
public boolean useExtension() {
133
return DFPUseDFP();
134
}
135
136
public boolean suitableForExtension(int nDigits, int scale) {
137
return (nDigits < 17 && scale >= -398 && scale < 369);
138
}
139
140
public int add(BigDecimal res, BigDecimal lhs, BigDecimal rhs) {
141
int resExp =-(Math.max(lhs.scale(), rhs.scale()));
142
/* Precision = 0, rounding = UNNECESSARY */
143
if (resExp >=-398 && resExp<=369){
144
if(DFPScaledAdd(res, getlaside(rhs), getlaside(lhs), resExp+398)){
145
// we can and out the flags because we don't have
146
// a sense of the exponent/precision/sign
147
// of this result, nor do we want to use DFP hw
148
// to figure it out, so we do not cache anything
149
150
//set res as DFP - (already set to 00)
151
152
// because DFP add takes the exclusive or of the sign bits
153
//for the result, need to make sure result of add 0 by -0
154
//doesn't store a negative sign...
155
long laside = getlaside(res);
156
if(isDFPZero(laside)) {
157
laside &= 0x7FFFFFFFFFFFFFFFL;
158
setlaside(res, laside);
159
}
160
return HARDWARE_OPERATION_SUCCESS;
161
}
162
}
163
return HARDWARE_OPERATION_FAIL;
164
}
165
166
public int add(BigDecimal res, BigDecimal lhs, BigDecimal rhs, MathContext set) {
167
boolean passed = false;
168
int prec = set.getPrecision();
169
int rm = set.getRoundingMode().ordinal();
170
long lhslaside = getlaside(lhs);
171
long rhslaside = getlaside(rhs);
172
173
// need to special case this since DFP hardware
174
// doesn't conform to BigDecimal API when adding
175
// to a 0..
176
if (prec != 0 && set.getRoundingMode().ordinal() != BigDecimal.ROUND_UNNECESSARY){
177
boolean lZero = isDFPZero(lhslaside);
178
boolean rZero = isDFPZero(rhslaside);
179
180
if(lZero || rZero) {
181
if(!lZero) {
182
clone(lhs, res); // rhs is zero
183
if (rhs.scale() > lhs.scale()){
184
if (set.getPrecision()-rhs.precision() >0) {
185
clone(res.setScale(Math.abs(-rhs.scale())), res); //might return BI
186
}
187
}
188
} else if (!rZero) {
189
clone(rhs, res); // lhs is zero
190
if (lhs.scale() > rhs.scale()){
191
if (set.getPrecision()-rhs.precision() >0) {
192
clone(res.setScale(Math.abs(-lhs.scale())), res); //might return BI
193
}
194
}
195
} else {
196
BigDecimal temp = BigDecimal.valueOf(0, Math.max(lhs.scale(), rhs.scale())); // both operands are zero
197
clone(temp, res); //CMVC 136111 -- res could be one of statics (shared)
198
}
199
200
if (set != MathContext.UNLIMITED) {
201
if(finish(res, set.getPrecision(), set.getRoundingMode().ordinal()) == HARDWARE_OPERATION_FAIL) {
202
return HARDWARE_OPERATION_FAIL;
203
}
204
205
}
206
return HARDWARE_OPERATION_SUCCESS;
207
}
208
}
209
210
// we can and out the flags because we don't have
211
// a sense of the exponent/precision/sign
212
// of this result, nor do we want to use DFP hw
213
// to figure it out, so we do not cache anything
214
215
// fast path for MathContext64
216
if (prec == 16 && rm == BigDecimal.ROUND_HALF_EVEN){
217
if(DFPAdd(res, rhslaside, lhslaside, 64, 0, 0)){
218
passed =true;
219
}
220
} else if (prec == 0) { // same as scaled DFPAddition
221
int resExp =-(Math.max(lhs.scale(), rhs.scale()));
222
if (resExp >=-398 && resExp <= 369){
223
if(DFPScaledAdd(res, rhslaside, lhslaside, resExp+398)){
224
//set res as DFP - (already set to 00)
225
passed = true;
226
}
227
}
228
} else if (prec > 0 && rm == BigDecimal.ROUND_UNNECESSARY){ // fast path for NO ROUNDING, as well as the ArithmeticException
229
if(DFPAdd(res, rhslaside, lhslaside, 0, 0, 0)){
230
performHardwareUsageHeuristic(set, -3);
231
// set res as DFP - (already set to 00)
232
if(finish(res, prec, rm) == HARDWARE_OPERATION_FAIL) { // See if we need to throw an arithmetic exception
233
return HARDWARE_OPERATION_FAIL;
234
}
235
passed = true;
236
}
237
} else if (prec <=16) { // Otherwise, if a precision to round to is specified
238
239
// NOTE: We do the following two if statements
240
// since the constants used for HALF_EVEN and ROUND_UP in
241
// the classlib do not map correctly to the DFP hardware
242
// rounding mode bits. All other classlib RoundingModes, however, do.
243
244
//the default DFP rounding mode
245
if (rm == BigDecimal.ROUND_HALF_EVEN)
246
rm = BigDecimal.ROUND_UP; //correct DFP HW rounding mode for HALF_EVEN
247
else if (rm == BigDecimal.ROUND_UP)
248
rm = BigDecimal.ROUND_HALF_EVEN; //correct DFP HW rounding mode for HALF_UP
249
250
// defect 144394
251
boolean dfpPassed = prec == 16 ?
252
DFPAdd(res, rhslaside, lhslaside, 1, 16, rm) :
253
DFPAdd(res, rhslaside, lhslaside, 1, prec, rm);
254
if(dfpPassed){
255
performHardwareUsageHeuristic(set, -3);
256
// set res as DFP - (already set to 00)
257
passed=true;
258
}
259
}
260
261
// because DFP add takes the exclusive or of the sign bits
262
//for the result, need to make sure result of add 0 by -0
263
//doesn't store a negative sign...
264
if (passed){
265
long reslaside = getlaside(res);
266
if(isDFPZero(reslaside)) {
267
reslaside &= 0x7FFFFFFFFFFFFFFFL;
268
setlaside(res, reslaside);
269
}
270
return HARDWARE_OPERATION_SUCCESS;
271
}
272
return HARDWARE_OPERATION_FAIL;
273
}
274
275
public int subtract(BigDecimal res, BigDecimal lhs, BigDecimal rhs) {
276
277
int resExp =-(Math.max(lhs.scale(), rhs.scale()));
278
// Precision = 0, rounding = UNNECESSARY
279
if (resExp >=-398 && resExp<=369){
280
if(DFPScaledSubtract(res, getlaside(rhs), getlaside(lhs), resExp+398)){
281
// set res as DFP - (already set to 00)
282
283
// because DFP subtract takes the exclusive or of the sign bits
284
//for the result, need to make sure result of subtract 0 by -0
285
//doesn't store a negative sign...
286
long laside = getlaside(res);
287
if(isDFPZero(laside)) {
288
laside &= 0x7FFFFFFFFFFFFFFFL;
289
setlaside(res, laside);
290
}
291
return HARDWARE_OPERATION_SUCCESS;
292
293
}
294
}
295
return HARDWARE_OPERATION_FAIL;
296
}
297
298
public int subtract(BigDecimal res, BigDecimal lhs, BigDecimal rhs, MathContext set) {
299
boolean passed = false;
300
int prec = set.getPrecision();
301
int rm = set.getRoundingMode().ordinal();
302
long lhslaside = getlaside(lhs);
303
long rhslaside = getlaside(rhs);
304
305
// need to special case this since DFP hardware
306
// doesn't conform to BigDecimal API when adding
307
// to a 0..
308
if (prec != 0 && set.getRoundingMode().ordinal() != BigDecimal.ROUND_UNNECESSARY){
309
boolean lZero = isDFPZero(lhslaside);
310
boolean rZero = isDFPZero(rhslaside);
311
if(lZero || rZero) {
312
if(!lZero) {
313
clone(lhs, res); // rhs is zero
314
if (rhs.scale() > lhs.scale()){
315
if (set.getPrecision()-rhs.precision() >0) {
316
clone(res.setScale(Math.abs(-rhs.scale())), res); //might return BI
317
}
318
}
319
} else if (!rZero) {
320
clone(rhs.negate(), res); // lhs is zero
321
if (lhs.scale() > rhs.scale()){
322
if (set.getPrecision()-rhs.precision() >0) {
323
clone(res.setScale(Math.abs(-lhs.scale())), res); //might return BI
324
}
325
}
326
} else {
327
BigDecimal temp = BigDecimal.valueOf(0, Math.max(lhs.scale(), rhs.scale())); // both operands are zero
328
clone(temp, res); //CMVC 136111 -- res could be one of statics (shared)
329
}
330
331
if (set != MathContext.UNLIMITED) {
332
if(finish(res, set.getPrecision(), set.getRoundingMode().ordinal()) == HARDWARE_OPERATION_FAIL) {
333
return HARDWARE_OPERATION_FAIL;
334
}
335
}
336
return HARDWARE_OPERATION_SUCCESS;
337
}
338
}
339
340
341
342
// at this point, not dealing with 0s
343
// fast path for MathContext64
344
if (prec == 16 && rm == BigDecimal.ROUND_HALF_EVEN){
345
if(DFPSubtract(res, rhslaside, lhslaside, 64, 0, 0)){
346
// set res as DFP - (already set to 00)
347
passed=true;
348
}
349
} else if (prec == 0){ // same as DFPScaledSubtract
350
int resExp =-(Math.max(lhs.scale(), rhs.scale()));
351
if (resExp >=-398 && resExp<=369){
352
if(DFPScaledSubtract(res, rhslaside, lhslaside, resExp+398)){
353
// we can and out the flags because we don't have
354
// a sense of the exponent/precision/sign
355
// of this result, nor do we want to use DFP hw
356
// to figure it out, so we do not cache anything
357
358
// set res as DFP - (already set to 00)
359
passed = true;
360
}
361
}
362
} else if (prec > 0 && rm == BigDecimal.ROUND_UNNECESSARY){ // fast path for NO ROUNDING, as well as the ArithmeticException
363
if(DFPSubtract(res, rhslaside, lhslaside, 0, 0, 0)){
364
performHardwareUsageHeuristic(set, -3);
365
// set res as DFP - (already set to 00)
366
// See if we need to throw an arithmetic exception
367
if(finish(res, prec, rm) == HARDWARE_OPERATION_FAIL) {
368
return HARDWARE_OPERATION_FAIL;
369
}
370
passed=true;
371
}
372
} else if(prec <=16){ // Otherwise, if a precision to round to is specified
373
374
/* NOTE: We do the following two if statements
375
* since the constants used for HALF_EVEN and ROUND_UP in
376
* the classlib do not map correctly to the DFP hardware
377
* rounding mode bits. All other classlib RoundingModes, however, do.
378
*/
379
380
//the default DFP rounding mode
381
if (rm == BigDecimal.ROUND_HALF_EVEN) {
382
rm = BigDecimal.ROUND_UP; //correct DFP HW rounding mode for HALF_EVEN
383
} else if (rm == BigDecimal.ROUND_UP) {
384
rm = BigDecimal.ROUND_HALF_EVEN; //correct DFP HW rounding mode for HALF_UP
385
}
386
// defect 144394
387
boolean dfpPassed = prec == 16 ?
388
DFPSubtract(res, rhslaside, lhslaside, 1, 16, rm) :
389
DFPSubtract(res, rhslaside, lhslaside, 1, prec, rm);
390
if(dfpPassed){
391
performHardwareUsageHeuristic(set, -3);
392
// set res as DFP - (already set to 00)
393
passed=true;
394
}
395
}
396
397
// because DFP subtracts takes the exclusive or of the sign bits
398
//for the result, need to make sure result of subtract 0 by -0
399
//doesn't store a negative sign...
400
if (passed){
401
long reslaside = getlaside(res);
402
if(isDFPZero(reslaside)) {
403
reslaside &= 0x7FFFFFFFFFFFFFFFL;
404
setlaside(res, reslaside);
405
}
406
return HARDWARE_OPERATION_SUCCESS;
407
}
408
return HARDWARE_OPERATION_FAIL;
409
}
410
411
public int multiply(BigDecimal res, BigDecimal lhs, BigDecimal rhs) {
412
413
int resExp =-(lhs.scale()+rhs.scale());
414
415
/* Precision = 0, rounding = UNNECESSARY */
416
if (resExp >=-398 && resExp<=369){
417
if(DFPScaledMultiply(res, getlaside(rhs), getlaside(lhs), resExp+398)){
418
// set res as DFP - (already set to 00)
419
420
// because DFP subtract takes the exclusive or of the sign bits
421
//for the result, need to make sure result of subtract 0 by -0
422
//doesn't store a negative sign...
423
long laside = getlaside(res);
424
if(isDFPZero(laside)) {
425
laside &= 0x7FFFFFFFFFFFFFFFL;
426
setlaside(res, laside);
427
}
428
return HARDWARE_OPERATION_SUCCESS;
429
}
430
}
431
return HARDWARE_OPERATION_FAIL;
432
}
433
434
public int multiply(BigDecimal res, BigDecimal lhs, BigDecimal rhs, MathContext set) {
435
436
boolean passed = false;
437
int prec = set.getPrecision();
438
int rm = set.getRoundingMode().ordinal();
439
long lhslaside = getlaside(lhs);
440
long rhslaside = getlaside(rhs);
441
442
443
// fast path for MathContext64
444
if (prec == 16 && rm == BigDecimal.ROUND_HALF_EVEN){
445
if(DFPMultiply(res, rhslaside, lhslaside, 64, 0, 0)){
446
// set res as DFP - (already set to 00)
447
passed = true;
448
}
449
} else if (prec == 0){ // same as DFPScaledMultiply
450
int resExp =-(lhs.scale()+rhs.scale());
451
if (resExp >=-398 && resExp<=369){
452
if(DFPScaledMultiply(res, rhslaside, lhslaside, resExp+398)){
453
// set res as DFP - (already set to 00)
454
// because DFP multiply takes the exclusive or of the sign bits
455
//for the result, need to make sure result of multiply by 0
456
//doesn't store a negative sign...
457
passed = true;
458
}
459
}
460
} else if (prec > 0 && rm == BigDecimal.ROUND_UNNECESSARY){ // fast path for NO ROUNDING, as well as the ArithmeticException
461
if(DFPMultiply(res, rhslaside, lhslaside, 0, 0, 0)){
462
// set res as DFP - (already set to 00)
463
464
// See if we need to throw an arithmetic exception
465
if(finish(res, prec, rm) == HARDWARE_OPERATION_FAIL) {
466
return HARDWARE_OPERATION_FAIL;
467
}
468
passed=true;
469
}
470
} else if (prec <= 16) { // Otherwise, if a precision to round to is specified
471
/* NOTE: We do the following two if statements
472
* since the constants used for HALF_EVEN and ROUND_UP in
473
* the classlib do not map correctly to the DFP hardware
474
* rounding mode bits. All other classlib RoundingModes, however, do.
475
*/
476
477
//the default DFP rounding mode
478
if (rm == BigDecimal.ROUND_HALF_EVEN) {
479
rm = BigDecimal.ROUND_UP; //correct DFP HW rounding mode for HALF_EVEN
480
} else if (rm == BigDecimal.ROUND_UP) {
481
rm = BigDecimal.ROUND_HALF_EVEN; //correct DFP HW rounding mode for HALF_UP
482
}
483
484
// defect 144394
485
boolean dfpPassed = prec == 16 ?
486
DFPMultiply(res, rhslaside, lhslaside, 1, 16, rm) :
487
DFPMultiply(res, rhslaside, lhslaside, 1, prec, rm);
488
if(dfpPassed) {
489
// set res as DFP - (already set to 00)
490
passed =true;
491
}
492
}
493
494
// because DFP multiply takes the exclusive or of the sign bits
495
// for the result, need to make sure result of multiply by 0
496
// doesn't store a negative sign...
497
if (passed){
498
long reslaside = getlaside(res);
499
if(isDFPZero(reslaside)) {
500
reslaside &= 0x7FFFFFFFFFFFFFFFL;
501
setlaside(res, reslaside);
502
}
503
return HARDWARE_OPERATION_SUCCESS;
504
}
505
return HARDWARE_OPERATION_FAIL;
506
}
507
508
public int divide(BigDecimal res, BigDecimal lhs, BigDecimal rhs) {
509
510
long rhslaside = getlaside(rhs);
511
if(isDFPZero(rhslaside)) {
512
badDivideByZero();
513
}
514
boolean passed = false;
515
long lhslaside = getlaside(lhs);
516
517
/*
518
* Interpreted return value:
519
* Returns -1 if not JIT compiled.
520
*
521
* JIT compiled return value:
522
* Return 1 if JIT compiled and DFP divide is successful.
523
* Return 0 if JIT compiled, but DFP divide was inexact
524
* Return -2 if JIT compiled, but other exception (i.e. overflow)
525
*/
526
527
// we need this in order to throw a "non-terminating decimal expansion" error
528
int desiredPrecision = (int)Math.min(lhs.precision() + Math.ceil(10*rhs.precision()/3),Integer.MAX_VALUE);
529
530
int ret = DFPDivide(res, rhslaside, lhslaside, true, 0, 0, 0);
531
532
// we passed, just check for non-terminating decimal expansion
533
if (ret == 1){
534
if (res.precision() > desiredPrecision) {
535
/*[MSG "K0460", "Non-terminating decimal expansion"]*/
536
throw new ArithmeticException(com.ibm.oti.util.Msg.getString("K0460")); //$NON-NLS-1$
537
}
538
// set res as DFP - (already set to 00)
539
passed=true;
540
}
541
542
//otherwise, we had an inexact, or failure... so we'll continue on slow path
543
544
// because DFP divide takes the exclusive or of the sign bits
545
//for the result, need to make sure result of multiply by 0
546
//doesn't store a negative sign...
547
if (passed){
548
long reslaside = getlaside(res);
549
if(isDFPZero(reslaside)) {
550
reslaside &= 0x7FFFFFFFFFFFFFFFL;
551
setlaside(res, reslaside);
552
}
553
return HARDWARE_OPERATION_SUCCESS;
554
}
555
556
return HARDWARE_OPERATION_FAIL;
557
}
558
559
public int divide(BigDecimal res, BigDecimal lhs, BigDecimal rhs, MathContext set) {
560
561
long rhslaside = getlaside(rhs);
562
if(isDFPZero(rhslaside)) {
563
badDivideByZero();
564
}
565
long lhslaside = getlaside(lhs);
566
int prec = set.getPrecision();
567
int rm = set.getRoundingMode().ordinal();
568
boolean passed=false;
569
570
// fast path for MathContext64
571
if (prec == 16 && rm == BigDecimal.ROUND_HALF_EVEN){
572
int ret = DFPDivide(res, rhslaside, lhslaside, false, 64, 0, 0);
573
if (ret == 1){
574
// set res as DFP - (already set to 00)
575
passed = true;
576
}
577
} else if (prec <= 16) {
578
579
//the default DFP rounding mode
580
if (rm == BigDecimal.ROUND_HALF_EVEN) {
581
rm = BigDecimal.ROUND_UP; //correct DFP HW rounding mode for HALF_EVEN
582
} else if (rm == BigDecimal.ROUND_UP) {
583
rm = BigDecimal.ROUND_HALF_EVEN; //correct DFP HW rounding mode for HALF_UP
584
}
585
586
// defect 144394
587
int ret = prec == 16 ?
588
DFPDivide(res, rhslaside, lhslaside, true, 1, 16, rm) :
589
DFPDivide(res, rhslaside, lhslaside, true, 1, prec, rm);
590
if (ret == 0 && rm == BigDecimal.ROUND_UNNECESSARY) {
591
/*[MSG "K0461", "Inexact result requires rounding"]*/
592
throw new ArithmeticException(com.ibm.oti.util.Msg.getString("K0461")); //$NON-NLS-1$
593
}
594
//otherwise, we divide perfectly and returned 1, or divided
595
//and got inexact (in the absence of checking for ROUND_UNNECESSARY
596
//but that's ok because we had:
597
// REREOUND + TGDT + CHECKINEXACT
598
599
//d120228
600
if (ret == 1){
601
performHardwareUsageHeuristic(set, 10);
602
// set res as DFP - (already set to 00)
603
passed = true;
604
}
605
}
606
// because DFP divide takes the exclusive or of the sign bits
607
//for the result, need to make sure result of multiply by 0
608
//doesn't store a negative sign...
609
if (passed){
610
long reslaside = getlaside(res);
611
if(isDFPZero(reslaside)) {
612
reslaside &= 0x7FFFFFFFFFFFFFFFL;
613
setlaside(res, reslaside);
614
}
615
return HARDWARE_OPERATION_SUCCESS;
616
}
617
618
return HARDWARE_OPERATION_FAIL;
619
}
620
621
public int negate(BigDecimal res, MathContext set) {
622
623
int signum = res.signum();
624
int flags = getflags(res);
625
long laside = getlaside(res);
626
// we're going to cache a new sign bit...
627
628
flags |= 0x4;
629
630
// need to flip DFP sign bit and cached sign
631
if (signum == -1){
632
laside &= 0x7FFFFFFFFFFFFFFFL; //flip DFP sign bit
633
flags &= 0xFFFFFF9F; //clear the cached sign bits
634
flags |= ( 1 << 5) & 0x60;// ispos
635
}
636
else if (signum == 1){
637
laside |= 0x8000000000000000L; //flip DFP sign bit
638
flags &= 0xFFFFFF9F; //clear the cached sign bits
639
flags |= (3 << 5) & 0x60; // isneg
640
}
641
if (getbi(res) != null) {
642
setbi(res, getbi(res).negate());
643
}
644
setflags(res, flags);
645
setlaside(res, laside);
646
647
return HARDWARE_OPERATION_SUCCESS;
648
}
649
650
public int compareTo(BigDecimal lhs, BigDecimal rhs) {
651
652
int res = DFPCompareTo(getlaside(lhs), getlaside(rhs));
653
if (res != -2) {
654
return res;
655
}
656
return HARDWARE_OPERATION_FAIL;
657
}
658
659
public int getScale(BigDecimal bd) {
660
661
int myscale = getscale(bd);
662
// have we cached it?
663
if ((getflags(bd) & 0x8) != 0) {
664
return myscale;
665
}
666
667
//caching it
668
669
setflags(bd, getflags(bd) | 0x8); //cache on
670
671
int newExp = DFPExponent(getlaside(bd));
672
if (newExp == 1000) {
673
myscale = -(extractDFPExponent(getlaside(bd))-398);
674
} else {
675
myscale = -(newExp-398);
676
}
677
setscale(bd, myscale);
678
return myscale;
679
}
680
681
public int setScale(BigDecimal bd, int scale) {
682
683
if (-scale >= -398 && -scale <= 369){
684
int ret = DFPSetScale(bd, getlaside(bd), -scale+398, false, 0, true);
685
if (ret == 1){
686
if(DFPPerformHysteresis()) {
687
performHardwareUsageHeuristic(5);
688
}
689
690
/* cache - SGP ESRR */
691
692
// set representation to DFP
693
// (already 00)
694
695
// because DFPSetScale maintains the sign of the DFP
696
// -23 might get scaled down to -0
697
long laside = getlaside(bd);
698
int flags = getflags(bd);
699
if(isDFPZero(laside)){
700
laside &= 0x7FFFFFFFFFFFFFFFL;
701
flags |= 0x4;
702
flags &= 0xFFFFFF9F; //clear signum bits for 0
703
}
704
else{
705
// cache the sign of the src
706
flags|= 0x4;
707
flags |= (bd.signum()<<5)&0x60;
708
}
709
710
// cache the exponent
711
flags|=0x8;
712
//NOTE: We do not cache precision!
713
flags&=0xFFFFFFEF; //clear prec cache bit
714
715
setscale(bd, scale);
716
setflags(bd, flags);
717
setlaside(bd, laside);
718
719
720
return HARDWARE_OPERATION_SUCCESS;
721
}
722
else if (ret == 0) {
723
/*[MSG "K0455", "Requires rounding: {0}"]*/
724
throw new ArithmeticException(com.ibm.oti.util.Msg.getString("K0455", Long.toString(scale))); //$NON-NLS-1$
725
}
726
}
727
728
return HARDWARE_OPERATION_FAIL;
729
}
730
731
public int setScale(BigDecimal bd, int scale, int roundingMode) {
732
733
if (-scale >= -398 && -scale <= 369){
734
735
// If the rounding mode is UNNECESSARY, then we can set
736
// the scale as if we were setting in the previous API
737
// i.e. with no concern to rounding (the 3rd parameter)
738
if (roundingMode == BigDecimal.ROUND_UNNECESSARY){
739
740
//120991 (changed last param from false to true)
741
int ret = DFPSetScale(bd, getlaside(bd), -scale+398,false, 0, true);
742
if (ret == 1){
743
if (DFPPerformHysteresis()){
744
performHardwareUsageHeuristic(5);
745
}
746
747
/* cache - SGP ESRR */
748
749
// set representation to DFP
750
// (already 00)
751
752
// because DFPSetScale maintains the sign of the DFP
753
// -23 might get scaled down to -0
754
long laside = getlaside(bd);
755
int flags = 0;
756
757
if(isDFPZero(laside)){
758
laside &= 0x7FFFFFFFFFFFFFFFL;
759
flags|=0x4;
760
flags&=0xFFFFFF9F; //clear signum bits for 0
761
}
762
else{
763
// cache the sign of the src
764
flags|=0x4;
765
flags |=(bd.signum()<<5)&0x60;
766
}
767
768
// cache the exponent
769
flags|=0x8;
770
771
setscale(bd, scale);
772
setflags(bd, flags);
773
setlaside(bd, laside);
774
return HARDWARE_OPERATION_SUCCESS;
775
776
}
777
}
778
else{
779
780
//the default DFP rounding mode
781
if (roundingMode == BigDecimal.ROUND_HALF_EVEN) {
782
roundingMode = BigDecimal.ROUND_UP; //correct DFP HW rounding mode for HALF_EVEN
783
} else if (roundingMode == BigDecimal.ROUND_UP) {
784
roundingMode = BigDecimal.ROUND_HALF_EVEN; //correct DFP HW rounding mode for HALF_UP
785
}
786
int ret = DFPSetScale(bd, getlaside(bd), -scale+398,true, roundingMode, false);
787
if (ret == 1){
788
if (DFPPerformHysteresis()){
789
performHardwareUsageHeuristic(5);
790
}
791
792
/* cache - SGP ESRR */
793
794
// set representation to DFP
795
// (already 00)
796
797
// because DFPSetScale maintains the sign of the DFP
798
// -23 might get scaled down to -0
799
long laside = getlaside(bd);
800
int flags = 0;
801
802
if(isDFPZero(laside)){
803
laside &= 0x7FFFFFFFFFFFFFFFL;
804
flags |= 0x4;
805
flags &= 0xFFFFFF9F; //clear signum bits for 0
806
}
807
else{
808
// cache the sign of the src
809
flags |= 0x4;
810
flags |= (bd.signum()<<5)&0x60;
811
}
812
813
// cache the exponent
814
flags |= 0x8;
815
setscale(bd, scale);
816
setflags(bd, flags);
817
setlaside(bd, laside);
818
819
return HARDWARE_OPERATION_SUCCESS;
820
}
821
}
822
}
823
return HARDWARE_OPERATION_FAIL;
824
}
825
826
public String toStringNoDecimal(BigDecimal bd) {
827
// Get the unscaled value;
828
long laside = getlaside(bd);
829
long lVal = DFPUnscaledValue(laside);
830
if (lVal == Long.MAX_VALUE){
831
lVal = DFPBCDDigits(laside);
832
if (lVal == 10) {
833
lVal = extractDFPDigitsBCD(laside);
834
}
835
// now extract each 4 bit BCD digit from left to right
836
long val=0; //to store the result
837
int i=0;
838
while (lVal!= 0){
839
val += (lVal & 0xF) * powerOfTenLL(i++);
840
lVal >>>= 4;
841
}
842
//is the sign negative?
843
return Long.toString(val * bd.signum());
844
} else {
845
return Long.toString(lVal);
846
}
847
}
848
849
public String toString(BigDecimal bd, int length) {
850
// Get the exponent
851
// Need to store it as a long since we may have
852
// stored Long.MIN_VALUE (which needs to be printed
853
// to screen as Long.MIN_VALUE
854
855
long actualExp = -(long)bd.scale();
856
857
// Get the precision
858
int precision = bd.precision();
859
860
// Get the unscaled value;
861
long laside = getlaside(bd);
862
long bcd = DFPBCDDigits(laside);
863
if (bcd == 10)
864
bcd = extractDFPDigitsBCD(laside);
865
866
long adjExp= actualExp + precision -1;
867
868
// two cases to consider:
869
/*
870
* case 1: precision > 1
871
* singlenumber.remaining numbersE(+/-adjusted exponent)
872
* case 2: else
873
* numberE(+/-adjusted exponent)
874
*/
875
876
int expPrecision = numDigits(adjExp);
877
878
// Fill 'er up
879
880
// the character array to fill up
881
char [] str;
882
int index=0;
883
884
if (length <=22)
885
str = (char [])thLocalToString.get();
886
else
887
str = new char [ length ];
888
889
// the sign
890
if (bd.signum() == -1){
891
str[index++] = '-';
892
}
893
894
// the first digit
895
str[index++] = (char)(digitAtBCD(bcd,precision,0)|0x0030);
896
897
if (precision > 1){
898
899
// the decimal dot
900
str[index++] = '.';
901
902
// rest of the digits
903
for (int i=0;i < precision-1 ;i++)
904
str[index++] = (char)(digitAtBCD(bcd,precision,i+1)|0x0030);
905
}
906
907
// E
908
str[index++] = 'E';
909
910
// the +
911
if (actualExp>0)
912
str[index++] = '+';
913
else if (actualExp<0)
914
str[index++] = '-';
915
916
// exponent digits
917
for (int i=0; i < expPrecision; i++)
918
str[index++] = (char)(digitAt(adjExp,expPrecision,i)|0x0030);
919
920
return new String(str, 0, length);
921
}
922
923
public String toStringPadded(BigDecimal bd, int sign, int precision, int strlen) {
924
//NOTE : unscaledValue is in BCD form
925
char [] str;
926
int actualExp = -bd.scale();
927
int signLen=0;
928
if (sign == -1)
929
signLen = 1;
930
long laside = getlaside(bd);
931
// Get the unscaled value;
932
long unscaledValue= DFPBCDDigits(laside);
933
if (unscaledValue == 10) {
934
unscaledValue = extractDFPDigitsBCD(laside);
935
}
936
// if scale is less than precision, won't have
937
// any leading zeros, and our number will have a decimal
938
// point somewhere in the middle...
939
940
/*
941
* 1234 scale 1 = 123.4
942
* 1234 scale 2 = 12.34
943
* 1234 scale 3 = 1.234
944
* 123400 scale 3 = 123.400 <-- need to handle trailing zeros for BI rep
945
* 123400 scale 5 = 12340.0 <-- need to handle trailing zeros for BI rep
946
*
947
* NOTE: don't need to handle scale <= 0 since this is taken care of
948
* in other branches in toStringHelper
949
*/
950
if (-actualExp < precision){
951
int i=0;
952
953
// for LL
954
// 1 no need to fill with trailing zeros
955
// 2 lay down sign
956
// 3 lay down all digits after decimal point
957
// 4 lay down digits before decimal point
958
959
int length= signLen + 1 /*for .*/ + precision;
960
961
if (length <=22)
962
str = (char [])thLocalToString.get();
963
else
964
str = new char [ length ];
965
int start=0;
966
int decimalPointLoc = length-(-actualExp)-1;
967
968
// 2 Place sign
969
if (signLen !=0){
970
str[start++]='-';
971
}
972
973
int curBCD = 0;
974
975
//3 lay down all digits after decimal point
976
for (i=(length-1); i > decimalPointLoc; i--){
977
curBCD = (int)(unscaledValue & 0xF);
978
unscaledValue >>>=4;
979
str[i] = (char)(curBCD|0x0030);
980
}
981
982
// lay down decimal point
983
str[i--]='.';
984
985
//4 lay down all digits before decimal point
986
for (;i >=start; i--){
987
curBCD = (int) (unscaledValue & 0xF);
988
unscaledValue >>>=4;
989
str[i] = (char)(curBCD|0x0030);
990
}
991
}
992
else{
993
// easy case.. where scale >= precision
994
995
/*
996
* 1234 scale 4 = 0.1234
997
* 1234 scale 5 = 0.01234
998
* 1234 scale 6 = 0.001234
999
*/
1000
1001
int numZeros = -actualExp - precision;
1002
1003
// for both LL & BI
1004
// 1 fill with zeros
1005
// 2 lay down sign & lay down decimal point
1006
// 3 lay down all digits
1007
1008
int length= signLen + 1 /*for 0*/ +
1009
1 /*for .*/+ numZeros + precision;
1010
1011
if (length <=22)
1012
str = (char [])thLocalToString.get();
1013
else
1014
str = new char [ length ];
1015
int start=0;
1016
int i=0;
1017
1018
//1 Fill with 0
1019
Arrays.fill(str,0,length,'0');
1020
1021
//2 Place sign
1022
if (signLen !=0)
1023
str[start++]='-';
1024
1025
//2 skip leading zero
1026
start++;
1027
1028
//2 Place decimal point
1029
str[start++]='.';
1030
1031
//2 skip more leading zeros that occur after decimal point
1032
start+=(-actualExp - precision);
1033
1034
// fill up laside bytes (from back to front)
1035
int curBCD=0;
1036
for (i=length-1; i >= start; i--){
1037
curBCD = (int) (unscaledValue & 0xF);
1038
unscaledValue >>>=4;
1039
str[i] = (char)(curBCD|0x0030);
1040
}
1041
}
1042
1043
return new String(str, 0, strlen);
1044
}
1045
1046
public int valueOf(BigDecimal res, long value, int scale) {
1047
1048
if (DFPUseDFP()) {
1049
if (value == 0 && scale == 0){
1050
createZero(res);
1051
return HARDWARE_OPERATION_SUCCESS;
1052
}
1053
1054
if (value <= 9999999999999999L && value >= -9999999999999999L && -scale>= -398 && -scale<= 369){
1055
1056
// NOTE: When we don't specify rounding in DFP, we'll never
1057
// fail, so don't bother checking the return value
1058
if (DFPLongExpConstructor(res, value, -scale + 398, 0, 0, 0, false)){
1059
int tempFlags = getflags(res);
1060
/* cache: SGP ESRR */
1061
1062
// store DFP representation
1063
// (already 00)
1064
1065
// cache the exponent for all DFP paths
1066
tempFlags|=0x8; //cache on
1067
setscale(res, scale);
1068
1069
// cache the sign for DFP, on all paths
1070
tempFlags|=0x4; //cache on
1071
if (value < 0) {
1072
tempFlags |= 0x60; //isneg
1073
} else if (value > 0) {
1074
tempFlags |= 0x20; //ispos
1075
//iszero is already 00
1076
}
1077
setflags(res, tempFlags);
1078
return HARDWARE_OPERATION_SUCCESS;
1079
}
1080
}
1081
}
1082
1083
return HARDWARE_OPERATION_FAIL;
1084
}
1085
1086
public int round(BigDecimal res, int precision, int roundingMode) {
1087
1088
// Only enter here iff precision > 0
1089
if (res.precision() > precision){ // and only perform if request is shorter then us
1090
long laside = getlaside(res);
1091
int flags = getflags(res);
1092
long bcd = DFPBCDDigits(laside);
1093
if (bcd == 10) {
1094
bcd = extractDFPDigitsBCD(laside);
1095
}
1096
1097
if (roundingMode== BigDecimal.ROUND_UNNECESSARY){
1098
if (!allzeroBCD(bcd, res.precision() - precision)) {
1099
/*[MSG "K0468", "Rounding mode unnecessary, but rounding changes value"]*/
1100
throw new ArithmeticException(com.ibm.oti.util.Msg.getString("K0468")); //$NON-NLS-1$
1101
}
1102
}
1103
1104
//the default DFP rounding mode
1105
if (roundingMode == BigDecimal.ROUND_HALF_EVEN) {
1106
roundingMode = BigDecimal.ROUND_UP; //correct DFP HW rounding mode for HALF_EVEN
1107
} else if (roundingMode == BigDecimal.ROUND_UP) {
1108
roundingMode = BigDecimal.ROUND_HALF_EVEN; //correct DFP HW rounding mode for HALF_UP
1109
}
1110
if(!DFPRound(res, laside, precision, roundingMode)) {
1111
return HARDWARE_OPERATION_FAIL;
1112
} else {
1113
/* cache - SGP ESRR */
1114
// if successful, update the precision cache...
1115
flags = getflags(res);
1116
flags |= 0x10; //cache on
1117
flags &= 0x7F;
1118
flags |= precision << 7;
1119
1120
//exponent may have changed, but we don't know
1121
//to what...
1122
flags &= 0xFFFFFFF7; //clear exponent cache bit
1123
setflags(res, flags);
1124
}
1125
1126
// if the result is still in DFP and is 0, make
1127
// sure the sign bit is off...
1128
laside = getlaside(res);
1129
if ((flags & 0x3) == 0x0 && isDFPZero(laside)) {
1130
laside &= 0x7FFFFFFFFFFFFFFFL;
1131
setlaside(res, laside);
1132
}
1133
}
1134
1135
return HARDWARE_OPERATION_SUCCESS;
1136
}
1137
1138
public int convertToLongLookaside(BigDecimal res) {
1139
1140
long laside = getlaside(res);
1141
int flags = getflags(res);
1142
//quick check for 0
1143
if (laside == dfpZERO){
1144
1145
// set representation as long lookaside
1146
flags &= 0xFFFFFFFC; //clear bits
1147
flags |= 0x00000001;
1148
1149
// reset exponent
1150
setscale(res, 0);
1151
// set long lookaside
1152
setlaside(res, 0);
1153
1154
// cache the precision of 1
1155
flags &= 0x7F; // clear the cached precision
1156
flags |= 0x10; //caching the precision
1157
flags |= 1 << 7; //precision of 1
1158
}
1159
else{
1160
1161
// need to store representation and new long lookaside last
1162
// since helper functions that are called
1163
// depend on the correct internal representation flag bit
1164
1165
int signum = res.signum();;
1166
1167
//store the exponent
1168
setscale(res, res.scale());
1169
1170
//cache the precision
1171
int prec = res.precision();
1172
flags &= 0x7F; // clear the cached precision
1173
flags &= 0xFFFFFFEF;//clear bits
1174
flags |= 0x10; //cache on
1175
flags |= prec << 7;
1176
1177
long lVal = DFPUnscaledValue(laside);
1178
1179
if (lVal == Long.MAX_VALUE){
1180
lVal = DFPBCDDigits(laside);
1181
if (lVal == 10) {
1182
lVal = extractDFPDigitsBCD(laside);
1183
}
1184
// now extract each 4 bit BCD digit from left to right
1185
long val = 0; //to store the result
1186
int i = 0;
1187
while (lVal!= 0) {
1188
val += (lVal & 0xF) * powerOfTenLL(i++);
1189
lVal >>>= 4;
1190
}
1191
1192
//is the sign negative?
1193
laside = val * signum;
1194
} else {
1195
laside = lVal;
1196
}
1197
1198
// store representation as long lookaside
1199
flags &= 0xFFFFFFFC;
1200
flags |= 0x00000001;
1201
setlaside(res, laside);
1202
}
1203
setflags(res, flags);
1204
// need to make sure bi is not cached by previous calls to unscaled value
1205
setbi(res, null);
1206
1207
return HARDWARE_OPERATION_SUCCESS;
1208
}
1209
1210
public int convertToBigInteger(BigDecimal res) {
1211
1212
long laside = getlaside(res);
1213
int flags = getflags(res);
1214
//quick check for 0
1215
if (laside == dfpZERO){
1216
1217
//store BigInteger representation
1218
flags &= 0xFFFFFFFC; //clear bits
1219
flags |= 0x00000002;
1220
1221
//clear exponent
1222
setscale(res, 0);
1223
1224
//store BI
1225
setbi(res, BigInteger.ZERO);
1226
1227
// cache the precision of 1
1228
flags&=0x7F; // clear the cached precision
1229
flags|=0x10; //caching the precision
1230
flags |= 1 << 7; //precision of 1
1231
} else {
1232
1233
// need to store representation last
1234
// since helper functions that are called
1235
// depend on the correct internal representation flag bit
1236
1237
//store the exponent
1238
setscale(res, res.scale());
1239
1240
//store the BigInteger
1241
1242
setbi(res, res.unscaledValue());
1243
1244
/* cache - SGP ESRR */
1245
1246
//cache the precision
1247
int prec = res.precision();
1248
flags &= 0x7F; // clear the cached precision
1249
flags |= 0x10; //cache on
1250
flags |= prec << 7;
1251
1252
// store representation as BigInteger
1253
flags &= 0xFFFFFFFC; //clear bits
1254
flags |= 0x00000002;
1255
}
1256
setlaside(res, laside);
1257
setflags(res, flags);
1258
1259
return HARDWARE_OPERATION_SUCCESS;
1260
}
1261
1262
public int convertToExtension(BigDecimal res) {
1263
1264
int flags = getflags(res);
1265
BigInteger bi = getbi(res);
1266
int scale = getscale(res);
1267
long laside =getlaside(res);
1268
// from BI to DFP
1269
if ((flags & 0x3) == 0x2 &&
1270
bi.compareTo(MAXDFP64) <= 0 &&
1271
bi.compareTo(MINDFP64) >=0 &&
1272
scale > -369 && scale < 398){
1273
1274
long lint = bi.longValue();
1275
1276
// NOTE: When we don't specify rounding in DFP, we'll never
1277
// fail, so don't bother checking the return value
1278
if (DFPLongExpConstructor(res, lint, -scale + 398, 0, 0, 0, false)){
1279
1280
/* cache: SGP ESRR */
1281
1282
// store DFP representation
1283
flags &= 0xFFFFFFFC; // clear rep bits
1284
//sets the bits to (00)
1285
1286
// cache the exponent
1287
flags |= 0x8; //cache on
1288
//res.exp already stores the value
1289
1290
// cache the sign
1291
flags |= 0x4; //cache on
1292
flags &= 0xFFFFFF9F; //clear signum
1293
if (bi.signum() < 0) {
1294
flags |= 0x60; //isneg
1295
} else if (bi.signum() > 0) {
1296
flags |= 0x20; //ispos
1297
} else {
1298
flags &= 0xFFFFFF9F;
1299
}
1300
1301
// fix to d124362
1302
setbi(res, null);
1303
}
1304
}
1305
1306
// from LL to DFP
1307
else if ((flags & 0x3) == 0x1 &&
1308
laside <= 9999999999999999L &&
1309
laside >= -9999999999999999L &&
1310
scale > -369 && scale < 398){
1311
1312
int signum = res.signum();
1313
1314
// NOTE: When we don't specify rounding in DFP, we'll never
1315
// fail, so don't bother checking the return value
1316
if (DFPLongExpConstructor(res, laside, -scale + 398, 0, 0, 0, false)){
1317
1318
/* cache: SGP ESRR */
1319
1320
// store DFP representation
1321
flags &= 0xFFFFFFFC; // clear rep bits
1322
//sets the bits to (00)
1323
1324
// cache the exponent
1325
flags |= 0x8; //cache on
1326
//res.exp already stores the value
1327
1328
// cache the sign
1329
flags |= 0x4; //cache on
1330
flags &= 0xFFFFFF9F; //clear signum
1331
if (signum < 0) {
1332
flags |= 0x60; //isneg
1333
} else if (signum > 0) {
1334
flags |= 0x20; //ispos
1335
} else {
1336
flags &= 0xFFFFFF9F;
1337
}
1338
}
1339
}
1340
1341
setflags(res, flags);
1342
1343
return HARDWARE_OPERATION_SUCCESS;
1344
}
1345
1346
public int significance(BigDecimal bd) {
1347
1348
int tempFlags = getflags(bd);
1349
long laside = getlaside(bd);
1350
1351
// we're caching it
1352
tempFlags |= 0x10; // cache on
1353
tempFlags &= 0x7F; //clear pre-existing bits
1354
1355
int sig = DFPSignificance(laside);
1356
if (sig < 0){
1357
long digits = DFPBCDDigits(laside);
1358
if (digits == 10){
1359
digits = extractDFPDigitsBCD(laside);
1360
}
1361
int nlz = Long.numberOfLeadingZeros(digits);
1362
nlz>>=2;
1363
nlz=16-nlz;
1364
1365
// Preceding algorithm would return 0 for 0
1366
// and we need it to return a precision of 1
1367
if (nlz == 0)
1368
nlz++;
1369
1370
1371
tempFlags |= nlz << 7;
1372
setflags(bd, tempFlags);
1373
return nlz;
1374
}
1375
else{
1376
// DFPSignificance would return 0 for 0
1377
// and we need it to return a precision of 1
1378
if (sig ==0) {
1379
sig++;
1380
}
1381
tempFlags |= sig << 7;
1382
setflags(bd, tempFlags);
1383
return sig;
1384
}
1385
}
1386
1387
public int signum(BigDecimal bd) {
1388
1389
int tempFlags = getflags(bd);
1390
long laside = getlaside(bd);
1391
// is it cached?
1392
if ((tempFlags&0x4)!=0) {
1393
return (((tempFlags & 0x00000060) << 25) >>30);
1394
}
1395
1396
//we're going to cache it
1397
tempFlags |= 0x4; //cache on
1398
1399
//check for negative first
1400
if ((laside & 0x8000000000000000L) == 0x8000000000000000L){
1401
tempFlags |= 0x60; //store negative
1402
setflags(bd, tempFlags);
1403
return -1;
1404
}
1405
1406
//now we're checking for positive or zero
1407
long mask = DFPBCDDigits(laside);
1408
if (mask == 10){
1409
//still haven't jitted the method
1410
if (isDFPZero(laside)){
1411
tempFlags&=0xFFFFFF9F; //clear the signum cache (00)
1412
setflags(bd, tempFlags);
1413
return 0;
1414
} else {
1415
tempFlags&=0xFFFFFF9F; //clear the signum cache
1416
tempFlags|=0x20; //store positive
1417
setflags(bd, tempFlags);
1418
return 1;
1419
}
1420
} else if (mask !=0) {
1421
tempFlags&=0xFFFFFF9F; //clear the signum cache
1422
tempFlags|=0x20; //store positive
1423
setflags(bd, tempFlags);
1424
return 1;
1425
} else {
1426
tempFlags&=0xFFFFFF9F; //clear the signum cache (00)
1427
}
1428
setflags(bd, tempFlags);
1429
return 0;
1430
}
1431
1432
public BigInteger unscaledValue(BigDecimal bd) {
1433
long laside = getlaside(bd);
1434
long lVal = DFPUnscaledValue(laside);
1435
if (lVal != Long.MAX_VALUE) {
1436
setbi(bd, BigInteger.valueOf(lVal));
1437
return getbi(bd);
1438
} else {
1439
lVal = DFPBCDDigits(laside);
1440
if (lVal == 10) {
1441
lVal = extractDFPDigitsBCD(laside);
1442
}
1443
1444
//check for zero
1445
if (lVal == 0) {
1446
setbi(bd, BigInteger.ZERO);
1447
return getbi(bd);
1448
}
1449
1450
// now extract each 4 bit BCD digit from left to right
1451
long val = 0; //to store the result
1452
int i = 0;
1453
while (lVal != 0){
1454
val += (lVal & 0xF) * powerOfTenLL(i++);
1455
lVal >>>= 4;
1456
}
1457
setbi(bd, BigInteger.valueOf(bd.signum() * val));
1458
return getbi(bd);
1459
}
1460
}
1461
1462
public int createZero(BigDecimal res) {
1463
setlaside(res, dfpZERO);
1464
setbi(res, null);
1465
setscale(res, 0);
1466
int flags = getflags(res);
1467
1468
flags|=0x4; //cache on
1469
1470
// cache the precision of 1
1471
flags&=0x7F; // clear the cached precision
1472
flags|=0x10; //caching the precision
1473
flags |= 1 << 7; //precision of 1
1474
1475
// cache the exponent (exp already 0)
1476
flags|=0x8; //cache on
1477
setflags(res, flags);
1478
1479
return HARDWARE_OPERATION_SUCCESS;
1480
}
1481
1482
public int intConstructor(BigDecimal res, int value, MathContext set) {
1483
// quick path for 0e0
1484
if (value == 0){
1485
createZero(res);
1486
return HARDWARE_OPERATION_SUCCESS;
1487
}
1488
1489
// cache the exp for all DFP paths
1490
// exp remains 0
1491
int flags = getflags(res);
1492
flags |= 0x8; //cache on
1493
1494
// cache the sign for DFP, on all paths
1495
flags|=0x4; //cache on
1496
if (value < 0) {
1497
flags|=0x60; //isneg
1498
} else if (value > 0) {
1499
flags|=0x20; //ispos
1500
}
1501
//iszero is already 00
1502
1503
// we're going to take the full blown path to
1504
// constructing a DFP internal representation
1505
1506
int prec = set.getPrecision();
1507
int rm = set.getRoundingMode().ordinal();
1508
1509
// fast path for MathContext64
1510
if (prec == 16 && rm == BigDecimal.ROUND_HALF_EVEN){
1511
if (DFPIntConstructor(res, value, 64, 0, 0)){
1512
1513
// We assume in the worst case that the precision and
1514
// exp remain the same since the number of digits
1515
// is at most 16. If we passed in 999999999999999999be767
1516
// and rounded to +inf, we'd get overflow, fail and take
1517
// the slow path anyway.
1518
1519
/* cache: SGP ESRR */
1520
1521
// cache the precision
1522
flags |= 0x10;
1523
flags |= numDigits(value) << 7;
1524
1525
// store DFP representation
1526
// (representation bits already 00)
1527
setflags(res, flags);
1528
return HARDWARE_OPERATION_SUCCESS;
1529
}
1530
}
1531
1532
// fast path for NO ROUNDING, as well as the ArithmeticException
1533
if ((prec == 0) || (prec > 0 && rm == BigDecimal.ROUND_UNNECESSARY) ||
1534
(prec > 16)){
1535
1536
/* This case catches:
1537
* -when no rounding is required
1538
* -if rounding is unnecessary and precision !=0, check
1539
* to see that result wasn't inexact (via call to Finish)
1540
* (the latter satisfies the API description of :
1541
* ArithmeticException - if the result is inexact but
1542
* the rounding mode is UNNECESSARY.
1543
*/
1544
1545
if (DFPIntConstructor(res, value, 0, 0, 0)){
1546
1547
/* cache: SGP ESRR */
1548
1549
// store DFP representation
1550
// (representation bits already 00)
1551
1552
// See if we need to throw an arithmetic exception
1553
1554
/*[IF]*/
1555
//TODO: Return a special value in DFP hardware to improve
1556
// this case
1557
/*[ENDIF]*/
1558
1559
if (prec > 0 && rm == BigDecimal.ROUND_UNNECESSARY) {
1560
setflags(res, flags);
1561
if(finish(res, prec, rm) == HARDWARE_OPERATION_FAIL) {
1562
return HARDWARE_OPERATION_FAIL;
1563
}
1564
} else {
1565
// we can cache the precision and exp
1566
// since no rounding meant that (no rounding)
1567
1568
// cache the precision
1569
flags |= 0x10; //cache on
1570
flags |= numDigits(value) << 7;
1571
setflags(res, flags);
1572
1573
}
1574
return HARDWARE_OPERATION_SUCCESS;
1575
}
1576
// Otherwise, if a precision to round to is specified
1577
} else if (prec <= 16){
1578
1579
/* NOTE: We do the following two if statements
1580
* since the constants used for HALF_EVEN and ROUND_UP in
1581
* the classlib do not map correctly to the DFP hardware
1582
* rounding mode bits. All other classlib RoundingModes, however, do.
1583
*/
1584
1585
//the default DFP rounding mode
1586
if (rm == BigDecimal.ROUND_HALF_EVEN) {
1587
rm = BigDecimal.ROUND_UP; //correct DFP HW rounding mode for HALF_EVEN
1588
} else if (rm == BigDecimal.ROUND_UP) {
1589
rm = BigDecimal.ROUND_HALF_EVEN; //correct DFP HW rounding mode for HALF_UP
1590
}
1591
1592
// now construct in hardware if possible
1593
if(DFPIntConstructor(res, value, 1, prec, rm)){
1594
1595
/* cache: SGP ESRR */
1596
1597
// store DFP representation
1598
// (representation bits already 00)
1599
1600
//don't try to cache precision/exp since
1601
//prec might be different precision(val)
1602
1603
//so turn cache of exp off...
1604
flags &= 0xFFFFFFF7;
1605
1606
return HARDWARE_OPERATION_SUCCESS;
1607
}
1608
}
1609
return HARDWARE_OPERATION_FAIL;
1610
}
1611
1612
public int longConstructor(BigDecimal res, long value, int scale, MathContext set) {
1613
// don't want to send in 0 and then round with hardware
1614
// cause it might place a crummy exponent value...
1615
if (value == 0){
1616
createZero(res);
1617
return HARDWARE_OPERATION_SUCCESS;
1618
// otherwise, make sure the long is within 64-bit DFP range
1619
} else if (value <=9999999999999999L && value >= -9999999999999999L &&
1620
-scale>=-398 && -scale<369){
1621
int flags = getflags(res);
1622
/* cache: SGP ESRR */
1623
1624
// cache the sign for DFP, on all paths
1625
flags|=0x4; //cache on
1626
1627
if (value < 0) {
1628
flags|=0x60; //isneg
1629
} else if (value > 0) {
1630
flags|=0x20; //ispos
1631
}
1632
//iszero is already 00
1633
1634
int prec = set.getPrecision();
1635
int rm = set.getRoundingMode().ordinal();
1636
1637
// fast path for MathContext64
1638
if (prec == 16 && rm == BigDecimal.ROUND_HALF_EVEN){
1639
if(DFPLongExpConstructor(res, value, -scale + 398, 64, 0, 0, false)){
1640
1641
// We assume in the worst case that the precision and
1642
// exponent remain the same since the number of digits
1643
// is at most 16. If we passed in 999999999999999999be767
1644
// and rounded to +inf, we'd get overflow, fail and take
1645
// the slow path anyway.
1646
1647
/* cache: SGP ESRR */
1648
1649
// cache the precision
1650
flags |= 0x10; //cache on
1651
flags |= numDigits(value) << 7;
1652
1653
// cache the exponent
1654
flags |= 0x8; //cache on
1655
1656
setflags(res, flags);
1657
setscale(res, scale);
1658
1659
1660
//store DFP representation
1661
// (already set to 00)
1662
1663
return HARDWARE_OPERATION_SUCCESS;
1664
}
1665
}
1666
1667
// fast path for NO ROUNDING, as well as the ArithmeticException
1668
if ((prec == 0) || (prec > 0 && rm == BigDecimal.ROUND_UNNECESSARY)
1669
|| (prec > 16)){
1670
1671
/* This case catches:
1672
* -when no rounding is required
1673
* -if rounding is unnecessary and precision !=0, check
1674
* to see that result wasn't inexact (via call to Finish)
1675
* (the latter satisfies the API description of :
1676
* ArithmeticException - if the result is inexact but
1677
* the rounding mode is UNNECESSARY.
1678
*/
1679
1680
// NOTE: When we don't specify rounding in DFP, we'll never
1681
// fail, so don't bother checking the return value
1682
if (this.DFPLongExpConstructor(res, value, -scale + 398, 0, 0, 0, false)){
1683
1684
// store DFP representation
1685
// (already set to 00)
1686
1687
/*[IF]*/
1688
//TODO: Return a special value in DFP hardware to improve
1689
// this case
1690
/*[ENDIF]*/
1691
1692
// See if we need to throw an arithmetic exception
1693
if (prec > 0 && rm == BigDecimal.ROUND_UNNECESSARY) {
1694
setflags(res, flags);
1695
if(finish(res, prec, rm) == HARDWARE_OPERATION_FAIL) {
1696
return HARDWARE_OPERATION_FAIL;
1697
}
1698
} else {
1699
1700
// cache the exponent
1701
flags|=0x8; //cache on
1702
1703
// cache the precision
1704
flags |= 0x10; //cache on
1705
flags |= numDigits(value) << 7;
1706
1707
setflags(res, flags);
1708
setscale(res, scale);
1709
}
1710
return HARDWARE_OPERATION_SUCCESS;
1711
}
1712
// Otherwise, if a precision to round to is specified
1713
} else if (prec <=16){
1714
1715
/* NOTE: We do the following two if statements
1716
* since the constants used for HALF_EVEN and ROUND_UP in
1717
* the classlib do not map correctly to the DFP hardware
1718
* rounding mode bits. All other classlib RoundingModes, however, do.
1719
*/
1720
1721
//the default DFP rounding mode
1722
if (rm == BigDecimal.ROUND_HALF_EVEN) {
1723
rm = BigDecimal.ROUND_UP; //correct DFP HW rounding mode for HALF_EVEN
1724
} else if (rm == BigDecimal.ROUND_UP) {
1725
rm = BigDecimal.ROUND_HALF_EVEN; //correct DFP HW rounding mode for HALF_UP
1726
}
1727
1728
// now construct in hardware if possible
1729
if(DFPLongExpConstructor(res, value, -scale + 398, 1, prec, rm, false)){
1730
1731
//store DFP representation
1732
// (already 00)
1733
1734
//don't try to cache precision/exponent since
1735
//prec might be different precision(val)
1736
1737
// so turn caching of exponent off
1738
setflags(res, flags);
1739
1740
return HARDWARE_OPERATION_SUCCESS;
1741
}
1742
}
1743
}
1744
1745
return HARDWARE_OPERATION_FAIL;
1746
}
1747
1748
public int longConstructor(BigDecimal res, long value, int scale, int nDigits, int sign, MathContext set) {
1749
int prec = set.getPrecision();
1750
int rm = set.getRoundingMode().ordinal();
1751
1752
// fast path for 0e0
1753
if (value == 0 && scale == 0){
1754
createZero(res);
1755
return HARDWARE_OPERATION_SUCCESS;
1756
}
1757
1758
/* cache - SGP ESRR */
1759
1760
int flags = getflags(res);
1761
1762
// cache the sign for DFP on all paths..
1763
flags|=0x4; //cache on
1764
if (value != 0) { //if not-zero, then we set the val
1765
flags|=sign;
1766
}
1767
1768
// cache the exponent for DFP on all paths..
1769
flags |= 0x8; //cache on
1770
setscale(res, -scale);
1771
1772
// fast path for MathContext64
1773
if (prec == 16 && rm == BigDecimal.ROUND_HALF_EVEN){
1774
if (sign == 0x60){ //isneg
1775
if (DFPLongExpConstructor(res, value, scale + 398, 64, 0, 0, true)){
1776
1777
// store DFP representation
1778
// (already 00)
1779
long laside = getlaside(res);
1780
// since we use unsigned BCDs to get full 16 digits worth
1781
// lets flip the DFP's sign bit to indicate the fact...
1782
if (sign == 0x60) { //inseg
1783
laside |= 0x8000000000000000l;
1784
}
1785
setlaside(res, laside);
1786
/* cache - SGP ESRR */
1787
1788
// cache the precision
1789
flags |= 0x10;
1790
flags |= nDigits << 7;
1791
1792
setflags(res, flags);
1793
if(finish(res, prec, rm) == HARDWARE_OPERATION_FAIL) {
1794
return HARDWARE_OPERATION_FAIL;
1795
}
1796
return HARDWARE_OPERATION_SUCCESS;
1797
}
1798
}
1799
else{
1800
if(DFPLongExpConstructor(res, value, scale + 398, 64, 0, 0, true)){
1801
1802
// We assume in the worst case that the precision and
1803
// exponent remain the same since the number of digits
1804
// is at most 16. If we passed in 999999999999999999be767
1805
// and rounded to +inf, we'd get overflow, fail and take
1806
// the slow path anyway.
1807
1808
// cache the precision
1809
flags|=0x10;
1810
flags |= nDigits << 7;
1811
1812
setflags(res, flags);
1813
1814
//store DFP representation
1815
//(already 00)
1816
return HARDWARE_OPERATION_SUCCESS;
1817
}
1818
}
1819
}
1820
1821
// fast path for NO ROUNDING, as well as the ArithmeticException
1822
if ((prec == 0) || (prec > 0 && rm == BigDecimal.ROUND_UNNECESSARY) ||
1823
(prec > 16)){
1824
1825
/* This case catches:
1826
* -when no rounding is required
1827
* -if rounding is unnecessary and precision !=0, check
1828
* to see that result wasn't inexact (via call to Finish)
1829
* (the latter satisfies the API description of :
1830
* ArithmeticException - if the result is inexact but
1831
* the rounding mode is UNNECESSARY.
1832
*/
1833
if (DFPLongExpConstructor(res, value, scale + 398, 0, 0, 0, true)){
1834
1835
// store DFP representation
1836
// (already 00)
1837
1838
// since we use unsigned BCDs to get full 16 digits worth
1839
// lets flip the DFP's sign bit to indicate the fact...
1840
long laside = getlaside(res);
1841
if (sign == 0x60) { //isneg
1842
laside |= 0x8000000000000000l;
1843
}
1844
setlaside(res, laside);
1845
// See if we need to throw an arithmetic exception
1846
if (prec > 0 && rm == BigDecimal.ROUND_UNNECESSARY){
1847
1848
// since we use unsigned BCDs to get full 16 digits worth
1849
// lets flip the DFP's sign bit to indicate the fact...
1850
if (sign == 0x60) { //inseg
1851
laside |= 0x8000000000000000l;
1852
}
1853
setlaside(res, laside);
1854
setflags(res, flags);
1855
1856
if(finish(res, prec, rm) == HARDWARE_OPERATION_FAIL) {
1857
return HARDWARE_OPERATION_FAIL;
1858
}
1859
}
1860
else{
1861
// we can cache the precision and exponent
1862
// since no rounding meant that (no rounding)
1863
// cache the precision
1864
flags|=0x10;
1865
flags |= nDigits << 7;
1866
setflags(res, flags);
1867
1868
1869
}
1870
return HARDWARE_OPERATION_SUCCESS;
1871
}
1872
}
1873
1874
// Otherwise, if a precision to round to is specified
1875
else if (prec <=16){
1876
1877
/* NOTE: We do the following two if statements
1878
* since the constants used for HALF_EVEN and ROUND_UP in
1879
* the classlib do not map correctly to the DFP hardware
1880
* rounding mode bits. All other classlib RoundingModes, however, do.
1881
*/
1882
1883
// for negative BCDs
1884
if (sign == 0x60){
1885
if (DFPLongExpConstructor(res, value, scale + 398, 0, 0, 0, true)){
1886
1887
// store DFP representation
1888
// (already 00)
1889
1890
// since we use unsigned BCDs to get full 16 digits worth
1891
// lets flip the DFP's sign bit to indicate the fact...
1892
long laside = getlaside(res);
1893
laside |= 0x8000000000000000l;
1894
setlaside(res, laside);
1895
1896
/* cache - SGP ESRR */
1897
1898
// can't store precision since it's going to be prec,
1899
// but isn't just yet...
1900
setflags(res, flags);
1901
if(finish(res, prec, rm) == HARDWARE_OPERATION_FAIL) {
1902
return HARDWARE_OPERATION_FAIL;
1903
}
1904
return HARDWARE_OPERATION_SUCCESS;
1905
}
1906
}
1907
else{
1908
1909
// NOTE: We do the following rm reversal here because
1910
// doing so in common code above would cause the eventual
1911
// call to roundDFP to switch them back.
1912
1913
// the default DFP rounding mode
1914
if (rm == BigDecimal.ROUND_HALF_EVEN) {
1915
rm = BigDecimal.ROUND_UP; //correct DFP HW rounding mode for HALF_EVEN
1916
} else if (rm == BigDecimal.ROUND_UP) {
1917
rm = BigDecimal.ROUND_HALF_EVEN; //correct DFP HW rounding mode for HALF_UP
1918
}
1919
// for positive BCDs
1920
if(DFPLongExpConstructor(res, value, scale + 398, 1, prec, rm, true)){
1921
1922
//store DFP representation
1923
//(already 00)
1924
1925
//don't try to cache precision/exponent since
1926
//exp might be diff due to rounding, and precision
1927
//may be larger than actual
1928
1929
/* cache - SGP ESRR */
1930
1931
//reset caching of exponent
1932
flags&=0xFFFFFFF7;
1933
setflags(res, flags);
1934
1935
1936
return HARDWARE_OPERATION_SUCCESS;
1937
}
1938
}
1939
}
1940
//at this point, DFP paths were unsuccessful, want to stick with BI
1941
return HARDWARE_OPERATION_FAIL;
1942
}
1943
1944
public int bigIntegerConstructor(BigDecimal res, BigInteger bi, int scale, MathContext set) {
1945
1946
int biPrecision = bi.toString().length() + ((bi.signum() ==-1) ? -1 : 0);
1947
1948
if (biPrecision < 17 && -scale <= 369 && -scale >= -398){
1949
1950
// get the long value with the appropriate sign
1951
long val = bi.longValue();
1952
1953
// quick path for 0e0
1954
if (val == 0 && scale == 0){
1955
createZero(res);
1956
return HARDWARE_OPERATION_SUCCESS;
1957
}
1958
1959
// otherwise, we'll need to perform DFP construction
1960
// using the correct precision/roundingmodes
1961
1962
int prec = set.getPrecision();
1963
int rm = set.getRoundingMode().ordinal();
1964
1965
int flags = getflags(res);
1966
// fast path for MathContext64
1967
if (prec == 16 && rm == BigDecimal.ROUND_HALF_EVEN){
1968
if(DFPLongExpConstructor(res, val, -scale + 398, 64, 0, 0, false)){
1969
1970
// We assume in the worst case that the precision and
1971
// exponent remain the same since the number of digits
1972
// is at most 16. If we passed in 999999999999999999be767
1973
// and rounded to +inf, we'd get overflow, fail and take
1974
// the slow path anyway.
1975
1976
/* cache - SGP ESRR */
1977
1978
// cache the precision
1979
flags |= 0x10; //cache on
1980
flags |= numDigits(val) << 7;
1981
1982
// cache the sign
1983
flags|=0x4; //cache on
1984
flags|= ((bi.signum() <<5) & 0x60);
1985
1986
//cache the exponent
1987
flags|=0x8; //cache on
1988
1989
setflags(res, flags);
1990
setscale(res, scale);
1991
1992
// store DFP representation
1993
// (representation bits already 00)
1994
1995
return HARDWARE_OPERATION_SUCCESS;
1996
}
1997
}
1998
1999
// fast path for NO ROUNDING, as well as the ArithmeticException
2000
if ((prec == 0) || (prec > 0 && rm == BigDecimal.ROUND_UNNECESSARY)
2001
|| (prec > 16)){
2002
2003
/* This case catches:
2004
* -when no rounding is required
2005
* -if rounding is unnecessary and precision !=0, check
2006
* to see that result wasn't inexact (via call to Finish)
2007
* (the latter satisfies the API description of :
2008
* ArithmeticException - if the result is inexact but
2009
* the rounding mode is UNNECESSARY.
2010
*/
2011
2012
// NOTE: When we don't specify rounding in DFP, we'll never
2013
// fail, so don't bother checking the return value
2014
if (DFPLongExpConstructor(res, val, -scale + 398, 0, 0, 0, false)){
2015
/* cache - SGP ESRR */
2016
2017
// cache the sign
2018
flags |= 0x4; // cache on
2019
flags |= ((bi.signum() <<5) & 0x60);
2020
2021
// store DFP representation
2022
// (representation bits already 00)
2023
2024
// See if we need to throw an arithmetic exception
2025
2026
/*[IF]*/
2027
//TODO: Return a special value in DFP hardware to improve
2028
// this case
2029
/*[ENDIF]*/
2030
2031
if (prec > 0 && rm == BigDecimal.ROUND_UNNECESSARY) {
2032
setflags(res, flags);
2033
if(finish(res, prec, rm) == HARDWARE_OPERATION_FAIL) {
2034
return HARDWARE_OPERATION_FAIL;
2035
}
2036
} else {
2037
// we can cache the precision and exponent
2038
// since no rounding left things as is
2039
2040
// cache the precision
2041
flags|=0x10; // cache on
2042
flags |= numDigits(val) << 7;
2043
2044
//cache the exponent
2045
flags|=0x8; // cache on
2046
2047
setflags(res, flags);
2048
setscale(res, scale);
2049
}
2050
return HARDWARE_OPERATION_SUCCESS;
2051
}
2052
}
2053
2054
// Otherwise, if a precision to round to is specified
2055
else if (prec <=16){
2056
2057
/* NOTE: We do the following two if statements
2058
* since the constants used for HALF_EVEN and ROUND_UP in
2059
* the classlib do not map correctly to the DFP hardware
2060
* rounding mode bits. All other classlib RoundingModes, however, do.
2061
*/
2062
2063
//the default DFP rounding mode
2064
if (rm == BigDecimal.ROUND_HALF_EVEN) {
2065
rm = BigDecimal.ROUND_UP; //correct DFP HW rounding mode for HALF_EVEN
2066
} else if (rm == BigDecimal.ROUND_UP) {
2067
rm = BigDecimal.ROUND_HALF_EVEN; //correct DFP HW rounding mode for HALF_UP
2068
}
2069
2070
// now construct in hardware if possible
2071
if(DFPLongExpConstructor(res, val,-scale + 398, 1, prec, rm, false)){
2072
2073
/* cache - SGP ESRR */
2074
2075
// cache the sign
2076
flags|=0x4; //cache on
2077
flags|=((bi.signum() <<5) & 0x60);
2078
setflags(res, flags);
2079
2080
//store DFP representation
2081
// (representation bits already 00)
2082
2083
//don't try to cache precision/exponent since
2084
//prec might be different after rounding
2085
return HARDWARE_OPERATION_SUCCESS;
2086
}
2087
}
2088
}
2089
return HARDWARE_OPERATION_FAIL;
2090
}
2091
2092
2093
2094
2095
2096
2097
2098
2099
2100
2101
2102
2103
2104
2105
2106
2107
2108
2109
2110
2111
2112
2113
2114
// DO NOT MODIFY THIS METHOD
2115
/* The method is only called once to setup the flag DFP_HW_AVAILABLE
2116
* Return value
2117
* true - when JIT compiled this method, replaces it with loadconst 1
2118
* if user -Xnodfp hasn't been supplied
2119
* false - if still interpreting this method or disabled by VM option
2120
*/
2121
private final static boolean DFPCheckHWAvailable() {
2122
return false;
2123
}
2124
2125
// DO NOT MODIFY THIS METHOD
2126
/*
2127
* Return value
2128
* true - when JIT compiled this method, replaces it with loadconst 1
2129
* if user -Xnodfp hasn't been supplied
2130
* false - if still interpreting this method or disabled by VM option
2131
*/
2132
private final static boolean DFPHWAvailable(){
2133
return DFP_HW_AVAILABLE;
2134
}
2135
2136
/*
2137
* Return value
2138
* true - when JIT compiled this method, replaces it with loadconst 1
2139
* if user -Xjit:disableDFPHys hasn't been supplied
2140
* false - if still interpreting this method or disabled by JIT option
2141
*/
2142
private final static boolean DFPPerformHysteresis(){
2143
return false;
2144
}
2145
2146
/*
2147
* Return value
2148
* true - when JIT compiled this method, replaces it with loadconst 1
2149
* if -Xjit:disableDFPHys has been supplied OR when hys_type becomes true
2150
* false - when hys_type is false
2151
*/
2152
private final static boolean DFPUseDFP(){
2153
return hys_type;
2154
}
2155
2156
// DO NOT MODIFY THIS METHOD
2157
2158
/* NOTE: The fact we return a boolean means we kill a register
2159
* in the cases we don't want to perform rounding.
2160
* i.e. rndFlag = 0 or 64 since we must load and
2161
* return a 1 value in the generated JIT code.
2162
*/
2163
private final static boolean DFPIntConstructor(BigDecimal bd, int val, int rndFlag, int prec, int rm){
2164
return false;
2165
}
2166
2167
// DO NOT MODIFY THIS METHOD
2168
/*[IF]*/
2169
//TODO: Use this for the longConstructor when it's called with scale=0
2170
/*[ENDIF]*/
2171
private final static boolean DFPLongConstructor(BigDecimal bd, long val, int rndFlag, int prec, int rm){
2172
return false;
2173
}
2174
2175
// DO NOT MODIFY THIS METHOD
2176
/*
2177
* Interpreted return value:
2178
* true - never
2179
* false - always
2180
*
2181
* Jitted return value:
2182
* true - if rounding succeeded
2183
* false - if rounding failed
2184
*
2185
* Parameters:
2186
* val - long to be converted to DFP
2187
* biasedExp - biased exponent to be inserted into DFP
2188
* rndFlag
2189
* =0 - no rounding
2190
* =1 - rounding according to prec, rm
2191
* =64 - rounding according to MathContext64
2192
* prec - precision to round constructed DFP to
2193
* rm - rm to use
2194
* bcd - whether long is in bcd form
2195
*
2196
*/
2197
private final static boolean DFPLongExpConstructor(BigDecimal bd, long val, int biasedExp, int rndFlag, int prec, int rm, boolean bcd){
2198
return false;
2199
}
2200
2201
// DO NOT MODIFY THIS METHOD
2202
private final static boolean DFPScaledAdd(BigDecimal bd, long lhsDFP,long rhsDFP,int biasedExp){
2203
return false;
2204
}
2205
2206
// DO NOT MODIFY THIS METHOD
2207
/*
2208
* Parameters:
2209
* rndFlag
2210
* =0 - no rounding
2211
* =1 - rounding according to prec, rm
2212
* =64 - rounding according to MathContext64
2213
*/
2214
private final static boolean DFPAdd(BigDecimal bd, long lhsDFP,long rhsDFP, int rndFlag, int precision, int rm){
2215
return false;
2216
}
2217
2218
// DO NOT MODIFY THIS METHOD
2219
private final static boolean DFPScaledSubtract(BigDecimal bd, long lhsDFP,long rhsDFP,int biasedExp){
2220
return false;
2221
}
2222
2223
// DO NOT MODIFY THIS METHOD
2224
/*
2225
* Parameters:
2226
* rndFlag
2227
* =0 - no rounding
2228
* =1 - rounding according to prec, rm
2229
* =64 - rounding according to MathContext64
2230
*/
2231
private final static boolean DFPSubtract(BigDecimal res, long lhsDFP, long rhsDFP, int rndFlag, int precision, int rm){
2232
return false;
2233
}
2234
2235
// DO NOT MODIFY THIS METHOD
2236
private final static boolean DFPScaledMultiply(BigDecimal res, long lhsDFP,long rhsDFP,int biasedExp){
2237
return false;
2238
}
2239
2240
// DO NOT MODIFY THIS METHOD
2241
/*
2242
* Parameters:
2243
* rndFlag
2244
* =0 - no rounding
2245
* =1 - rounding according to prec, rm
2246
* =64 - rounding according to MathContext64
2247
*/
2248
private final static boolean DFPMultiply(BigDecimal res, long lhsDFP, long rhsDFP, int rndFlag, int precision, int rm){
2249
return false;
2250
}
2251
2252
// DO NOT MODIFY THIS METHOD
2253
/*
2254
* Interpreted return value:
2255
* Returns -1 if not JIT compiled.
2256
*
2257
* JIT compiled return value:
2258
* 0 - ok, but inexact exception --> check UNNECESSARY
2259
* 1 - ok, no inexact
2260
* -1 - not ok --> try slow path
2261
*
2262
* rndFlag
2263
* =0 - rounding according to MathContext64
2264
* =1 - rounding according to prec, rm
2265
*/
2266
private final static int DFPScaledDivide(BigDecimal res, long lhsDFP, long rhsDFP, int scale, int rndFlg, int rm){
2267
return -1;
2268
}
2269
2270
// DO NOT MODIFY THIS METHOD
2271
/*
2272
* Interpreted return value:
2273
* -1 = always
2274
*
2275
* JIT compiled return value:
2276
* Return 1 if JIT compiled and DFP divide is successful.
2277
* Return 0 if JIT compiled, but DFP divide was inexact
2278
* Return -1 if JIT compiled, but other exception (i.e. overflow)
2279
*
2280
* rndFlag
2281
* =0 - no rounding
2282
* =1 - rounding according to prec, rm
2283
* =64 - rounding according to MathContext64
2284
*/
2285
private final static int DFPDivide(BigDecimal bd, long lhsDFP, long rhsDFP, boolean checkForInexact, int rndFlag, int prec, int rm){
2286
return -1; //return an invalid result
2287
}
2288
2289
// DO NOT MODIFY THIS METHOD
2290
private final static boolean DFPRound(BigDecimal bd, long dfpSrc, int precision, int rm){
2291
return false;
2292
}
2293
2294
// DO NOT MODIFY THIS METHOD
2295
private final static int DFPCompareTo(long lhsDFP, long rhsDFP){
2296
return -2; //return an invalid result
2297
}
2298
2299
// DO NOT MODIFY THIS METHOD
2300
private final static long DFPBCDDigits(long dfp){
2301
return 10; //since each digit in a BCD is from 0 to 9
2302
}
2303
2304
// DO NOT MODIFY THIS METHOD
2305
private final static int DFPSignificance(long dfp){
2306
return -1; //illegal significance
2307
}
2308
2309
// DO NOT MODIFY THIS METHOD
2310
private final static int DFPExponent(long dfp){
2311
return 1000; //return a value out of the range of Double DFP
2312
}
2313
2314
// DO NOT MODIFY THIS METHOD
2315
/*
2316
* Interpreted return value:
2317
* -1 = always
2318
*
2319
* JIT compiled return value:
2320
* Return 1 if passed
2321
* Return 0 if JIT compiled, but inexact result
2322
* Return -1 if JIT compiled, but other failure
2323
*
2324
*/
2325
private final static int DFPSetScale(BigDecimal bd, long srcDFP, int biasedExp, boolean round, int rm, boolean checkInexact){
2326
return -1;
2327
}
2328
2329
// DO NOT MODIFY THIS METHOD
2330
private final static long DFPUnscaledValue(long srcDFP){
2331
return Long.MAX_VALUE;
2332
}
2333
2334
2335
2336
2337
2338
2339
2340
2341
2342
2343
2344
2345
2346
2347
2348
2349
2350
2351
2352
2353
2354
private static final ThreadLocal thLocalToString = new ThreadLocal(){
2355
/* 22 is the best number for the fastest path
2356
* [-]digits.digits when scale > 0 & scale <=19
2357
*/
2358
2359
protected synchronized Object initialValue() {
2360
return new char[22];
2361
}
2362
};
2363
2364
private final static byte [] comboinit(){
2365
final byte comboCode[]={
2366
0, 4, 8, 12, 16, 20, 24, 28,
2367
1, 5, 9, 13, 17, 21, 25, 29,
2368
2, 6, 10, 14, 18, 22, 26, 30,
2369
32, 36, 33, 37, 34, 38
2370
};
2371
return comboCode;
2372
}
2373
2374
private final static short [] dpd2bcdinit(){
2375
final short[] dpd2bcd = {
2376
0, 1, 2, 3, 4, 5, 6, 7,
2377
8, 9, 128, 129, 2048, 2049, 2176, 2177, 16, 17, 18, 19, 20,
2378
21, 22, 23, 24, 25, 144, 145, 2064, 2065, 2192, 2193, 32, 33,
2379
34, 35, 36, 37, 38, 39, 40, 41, 130, 131, 2080, 2081, 2056,
2380
2057, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 146, 147,
2381
2096, 2097, 2072, 2073, 64, 65, 66, 67, 68, 69, 70, 71, 72,
2382
73, 132, 133, 2112, 2113, 136, 137, 80, 81, 82, 83, 84, 85,
2383
86, 87, 88, 89, 148, 149, 2128, 2129, 152, 153, 96, 97, 98,
2384
99, 100, 101, 102, 103, 104, 105, 134, 135, 2144, 2145, 2184, 2185,
2385
112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 150, 151, 2160,
2386
2161, 2200, 2201, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265,
2387
384, 385, 2304, 2305, 2432, 2433, 272, 273, 274, 275, 276, 277, 278,
2388
279, 280, 281, 400, 401, 2320, 2321, 2448, 2449, 288, 289, 290, 291,
2389
292, 293, 294, 295, 296, 297, 386, 387, 2336, 2337, 2312, 2313, 304,
2390
305, 306, 307, 308, 309, 310, 311, 312, 313, 402, 403, 2352, 2353,
2391
2328, 2329, 320, 321, 322, 323, 324, 325, 326, 327, 328, 329, 388,
2392
389, 2368, 2369, 392, 393, 336, 337, 338, 339, 340, 341, 342, 343,
2393
344, 345, 404, 405, 2384, 2385, 408, 409, 352, 353, 354, 355, 356,
2394
357, 358, 359, 360, 361, 390, 391, 2400, 2401, 2440, 2441, 368, 369,
2395
370, 371, 372, 373, 374, 375, 376, 377, 406, 407, 2416, 2417, 2456,
2396
2457, 512, 513, 514, 515, 516, 517, 518, 519, 520, 521, 640, 641,
2397
2050, 2051, 2178, 2179, 528, 529, 530, 531, 532, 533, 534, 535, 536,
2398
537, 656, 657, 2066, 2067, 2194, 2195, 544, 545, 546, 547, 548, 549,
2399
550, 551, 552, 553, 642, 643, 2082, 2083, 2088, 2089, 560, 561, 562,
2400
563, 564, 565, 566, 567, 568, 569, 658, 659, 2098, 2099, 2104, 2105,
2401
576, 577, 578, 579, 580, 581, 582, 583, 584, 585, 644, 645, 2114,
2402
2115, 648, 649, 592, 593, 594, 595, 596, 597, 598, 599, 600, 601,
2403
660, 661, 2130, 2131, 664, 665, 608, 609, 610, 611, 612, 613, 614,
2404
615, 616, 617, 646, 647, 2146, 2147, 2184, 2185, 624, 625, 626, 627,
2405
628, 629, 630, 631, 632, 633, 662, 663, 2162, 2163, 2200, 2201, 768,
2406
769, 770, 771, 772, 773, 774, 775, 776, 777, 896, 897, 2306, 2307,
2407
2434, 2435, 784, 785, 786, 787, 788, 789, 790, 791, 792, 793, 912,
2408
913, 2322, 2323, 2450, 2451, 800, 801, 802, 803, 804, 805, 806, 807,
2409
808, 809, 898, 899, 2338, 2339, 2344, 2345, 816, 817, 818, 819, 820,
2410
821, 822, 823, 824, 825, 914, 915, 2354, 2355, 2360, 2361, 832, 833,
2411
834, 835, 836, 837, 838, 839, 840, 841, 900, 901, 2370, 2371, 904,
2412
905, 848, 849, 850, 851, 852, 853, 854, 855, 856, 857, 916, 917,
2413
2386, 2387, 920, 921, 864, 865, 866, 867, 868, 869, 870, 871, 872,
2414
873, 902, 903, 2402, 2403, 2440, 2441, 880, 881, 882, 883, 884, 885,
2415
886, 887, 888, 889, 918, 919, 2418, 2419, 2456, 2457, 1024, 1025, 1026,
2416
1027, 1028, 1029, 1030, 1031, 1032, 1033, 1152, 1153, 2052, 2053, 2180, 2181,
2417
1040, 1041, 1042, 1043, 1044, 1045, 1046, 1047, 1048, 1049, 1168, 1169, 2068,
2418
2069, 2196, 2197, 1056, 1057, 1058, 1059, 1060, 1061, 1062, 1063, 1064, 1065,
2419
1154, 1155, 2084, 2085, 2120, 2121, 1072, 1073, 1074, 1075, 1076, 1077, 1078,
2420
1079, 1080, 1081, 1170, 1171, 2100, 2101, 2136, 2137, 1088, 1089, 1090, 1091,
2421
1092, 1093, 1094, 1095, 1096, 1097, 1156, 1157, 2116, 2117, 1160, 1161, 1104,
2422
1105, 1106, 1107, 1108, 1109, 1110, 1111, 1112, 1113, 1172, 1173, 2132, 2133,
2423
1176, 1177, 1120, 1121, 1122, 1123, 1124, 1125, 1126, 1127, 1128, 1129, 1158,
2424
1159, 2148, 2149, 2184, 2185, 1136, 1137, 1138, 1139, 1140, 1141, 1142, 1143,
2425
1144, 1145, 1174, 1175, 2164, 2165, 2200, 2201, 1280, 1281, 1282, 1283, 1284,
2426
1285, 1286, 1287, 1288, 1289, 1408, 1409, 2308, 2309, 2436, 2437, 1296, 1297,
2427
1298, 1299, 1300, 1301, 1302, 1303, 1304, 1305, 1424, 1425, 2324, 2325, 2452,
2428
2453, 1312, 1313, 1314, 1315, 1316, 1317, 1318, 1319, 1320, 1321, 1410, 1411,
2429
2340, 2341, 2376, 2377, 1328, 1329, 1330, 1331, 1332, 1333, 1334, 1335, 1336,
2430
1337, 1426, 1427, 2356, 2357, 2392, 2393, 1344, 1345, 1346, 1347, 1348, 1349,
2431
1350, 1351, 1352, 1353, 1412, 1413, 2372, 2373, 1416, 1417, 1360, 1361, 1362,
2432
1363, 1364, 1365, 1366, 1367, 1368, 1369, 1428, 1429, 2388, 2389, 1432, 1433,
2433
1376, 1377, 1378, 1379, 1380, 1381, 1382, 1383, 1384, 1385, 1414, 1415, 2404,
2434
2405, 2440, 2441, 1392, 1393, 1394, 1395, 1396, 1397, 1398, 1399, 1400, 1401,
2435
1430, 1431, 2420, 2421, 2456, 2457, 1536, 1537, 1538, 1539, 1540, 1541, 1542,
2436
1543, 1544, 1545, 1664, 1665, 2054, 2055, 2182, 2183, 1552, 1553, 1554, 1555,
2437
1556, 1557, 1558, 1559, 1560, 1561, 1680, 1681, 2070, 2071, 2198, 2199, 1568,
2438
1569, 1570, 1571, 1572, 1573, 1574, 1575, 1576, 1577, 1666, 1667, 2086, 2087,
2439
2152, 2153, 1584, 1585, 1586, 1587, 1588, 1589, 1590, 1591, 1592, 1593, 1682,
2440
1683, 2102, 2103, 2168, 2169, 1600, 1601, 1602, 1603, 1604, 1605, 1606, 1607,
2441
1608, 1609, 1668, 1669, 2118, 2119, 1672, 1673, 1616, 1617, 1618, 1619, 1620,
2442
1621, 1622, 1623, 1624, 1625, 1684, 1685, 2134, 2135, 1688, 1689, 1632, 1633,
2443
1634, 1635, 1636, 1637, 1638, 1639, 1640, 1641, 1670, 1671, 2150, 2151, 2184,
2444
2185, 1648, 1649, 1650, 1651, 1652, 1653, 1654, 1655, 1656, 1657, 1686, 1687,
2445
2166, 2167, 2200, 2201, 1792, 1793, 1794, 1795, 1796, 1797, 1798, 1799, 1800,
2446
1801, 1920, 1921, 2310, 2311, 2438, 2439, 1808, 1809, 1810, 1811, 1812, 1813,
2447
1814, 1815, 1816, 1817, 1936, 1937, 2326, 2327, 2454, 2455, 1824, 1825, 1826,
2448
1827, 1828, 1829, 1830, 1831, 1832, 1833, 1922, 1923, 2342, 2343, 2408, 2409,
2449
1840, 1841, 1842, 1843, 1844, 1845, 1846, 1847, 1848, 1849, 1938, 1939, 2358,
2450
2359, 2424, 2425, 1856, 1857, 1858, 1859, 1860, 1861, 1862, 1863, 1864, 1865,
2451
1924, 1925, 2374, 2375, 1928, 1929, 1872, 1873, 1874, 1875, 1876, 1877, 1878,
2452
1879, 1880, 1881, 1940, 1941, 2390, 2391, 1944, 1945, 1888, 1889, 1890, 1891,
2453
1892, 1893, 1894, 1895, 1896, 1897, 1926, 1927, 2406, 2407, 2440, 2441, 1904,
2454
1905, 1906, 1907, 1908, 1909, 1910, 1911, 1912, 1913, 1942, 1943, 2422, 2423,
2455
2456, 2457};
2456
return dpd2bcd;
2457
}
2458
2459
/**
2460
* LUT for powers of ten
2461
*/
2462
private static final long [/*19*/]powersOfTenLL={
2463
1L, 10L, 100L, 1000L, /*0 to 4 */
2464
10000L, 100000L, 1000000L, 10000000L, /*5 to 8*/
2465
100000000L, 1000000000L, 10000000000L, 100000000000L, /*9 to 12*/
2466
1000000000000L, 10000000000000L, 100000000000000L, 1000000000000000L, /*13 to 16 */
2467
10000000000000000L, 100000000000000000L, 1000000000000000000L /*17 to 18 */
2468
};
2469
2470
private final static boolean isDFPZero(long laside){
2471
// quick check for 0
2472
if (laside == dfpZERO) {
2473
return true;
2474
}
2475
// if DPF is ZERO, then the combo field will be XX000 where XX is I don't care
2476
// values, and then coefficient continuation field will be all 0s
2477
return ((laside & 0x0003FFFFFFFFFFFFL) == 0 && ((laside >>> 58) & 0x7) == 0);
2478
}
2479
2480
private final void clone(BigDecimal src, BigDecimal tar) {
2481
int tempFlags = getflags(src);
2482
setflags(tar, tempFlags);
2483
setlaside(tar, getlaside(src));
2484
setscale(tar, getscale(src));
2485
if ((tempFlags & 0x3) == 0x2) {
2486
setbi(tar, getbi(src));
2487
}
2488
}
2489
2490
private final int finish(BigDecimal bd, int prec, int rm){
2491
if (prec > 0 && bd.precision() > prec) {
2492
if ((getflags(bd) & 0x3) == 0x0) {
2493
return round(bd, prec, rm);
2494
} else {
2495
MathContext mc = new MathContext(prec, RoundingMode.valueOf(rm));
2496
clone(bd.round(mc), bd);
2497
}
2498
}
2499
return HARDWARE_OPERATION_SUCCESS;
2500
}
2501
2502
protected final static int getflags(BigDecimal bd) {
2503
throw new RuntimeException("getflags not compiled\n"); //$NON-NLS-1$
2504
}
2505
2506
protected final static long getlaside(BigDecimal bd) {
2507
throw new RuntimeException("getlaside not compiled\n"); //$NON-NLS-1$
2508
}
2509
2510
protected final static int getscale(BigDecimal bd) {
2511
throw new RuntimeException("getscale not compiled\n"); //$NON-NLS-1$
2512
}
2513
2514
protected final static BigInteger getbi(BigDecimal bd) {
2515
throw new RuntimeException("getbi not compiled\n"); //$NON-NLS-1$
2516
}
2517
2518
protected final static void setflags(BigDecimal bd, int flags) {
2519
throw new RuntimeException("setflags not compiled\n"); //$NON-NLS-1$
2520
}
2521
2522
protected final static void setlaside(BigDecimal bd, long laside) {
2523
throw new RuntimeException("setlaside not compiled\n"); //$NON-NLS-1$
2524
}
2525
2526
protected final static void setscale(BigDecimal bd, int scale) {
2527
throw new RuntimeException("setscale not compiled\n"); //$NON-NLS-1$
2528
}
2529
2530
protected final static void setbi(BigDecimal bd, BigInteger bi) {
2531
throw new RuntimeException("setbi not compiled\n"); //$NON-NLS-1$
2532
}
2533
2534
private final static long extractDFPDigitsBCD(long dfpNum){
2535
2536
int combo=0; // 5 bit combo field
2537
2538
//quick check for 0
2539
if (dfpNum == dfpZERO)
2540
return 0;
2541
2542
// store the combo field bits
2543
combo = (int)(dfpNum >>> 58); //shift out extraneous bits
2544
combo &= 0x1F; //and out sign bit
2545
2546
// MANTISSA
2547
2548
// store the mantissa continuation field bits 14 to 62 (50 bits in total)
2549
long ccf = dfpNum & 0x0003FFFFFFFFFFFFL;
2550
2551
// Convert each set of 10 DPD bits from continuation bits to 12 BCD digits
2552
long ccBCD=0;
2553
long bcd=0;
2554
for (int i=0; i <5; i++){ //5 groups of 10 bits
2555
bcd = DPD2BCD[(int)((ccf & 0x3FF0000000000L)>>>40)];
2556
ccBCD <<=12;
2557
ccBCD|=bcd;
2558
ccf <<= 10; //shift out top 10 bits
2559
}
2560
2561
//ccBCD contains 15 BCD digits, now need to prepend the first one
2562
ccBCD|=(((long)(doubleDFPComboField[combo]>>>2))<<60);
2563
return ccBCD;
2564
}
2565
2566
2567
private final static boolean allzeroBCD(long num, int numDigsToCheck){
2568
2569
// isolate numDigsToCheck rightmost digits...
2570
long mask = 0xFFFFFFFFFFFFFFFFL;
2571
mask >>>= (64-numDigsToCheck)*4;
2572
return ((mask & num) == 0);
2573
}
2574
2575
private final static int extractDFPExponent(long dfpNum){
2576
2577
byte combo=0; // 5 bit combo field
2578
2579
// store the combo field bits
2580
combo = (byte)(dfpNum >>> 58); //shift out extraneous bits
2581
//combo &= 0x1F; //and out sign bit - not sure why I was doing this
2582
2583
// store the biased exponent field bits 6 to 13
2584
short bxf = (short)(dfpNum >>> 50); //shift out extraneous bits
2585
bxf &= 0x00FF; //and out sign and combo field
2586
2587
// parse the combo field
2588
byte exp2Digits = (byte)(doubleDFPComboField[combo] & 0x03);
2589
2590
// unbias the exponent
2591
short unbExp = (short)(exp2Digits);
2592
unbExp <<= 8;
2593
unbExp|=bxf;
2594
return unbExp;
2595
}
2596
2597
private static final long powerOfTenLL(long i){
2598
if (i > -1 && i <= 18)
2599
return powersOfTenLL[(int)i];
2600
else
2601
return -1;
2602
}
2603
2604
/* Return number of digits in lon
2605
* The value '0' has numDigits = 1.
2606
*/
2607
private final static int numDigits(long lon){
2608
//if (lon <0) lon*=-1; //need to make it positive for this to work
2609
lon = Math.abs(lon);
2610
2611
//hardcode powers of ten to avoid LUT lookups
2612
2613
//rhs of the tree
2614
if (lon < 1000000000L /*powerOfTenLL[9]*/){
2615
if (lon < 100000000L /*powerOfTenLL[8]*/){
2616
if (lon < 10000L /*powerOfTenLL[4]*/){
2617
if (lon < 100L /* powerOfTenLL[2]*/){
2618
if (lon < 10L /*powerOfTenLL[1]*/)
2619
return 1;
2620
else
2621
return 2;
2622
}
2623
else if (lon < 1000L /*powerOfTenLL[3]*/)
2624
return 3;
2625
else
2626
return 4;
2627
}
2628
else if (lon < 1000000L /*powerOfTenLL[6]*/){
2629
if ( lon < 100000L /*powerOfTenLL[5]*/)
2630
return 5;
2631
else
2632
return 6;
2633
}
2634
else if (lon < 10000000L /*powerOfTenLL[7]*/)
2635
return 7;
2636
else return 8;
2637
}
2638
else
2639
return 9;
2640
}
2641
//lhs of the tree
2642
else{
2643
if (lon < 10000000000L /*powerOfTenLL[10]*/)
2644
return 10;
2645
else if (lon < 100000000000000L /*powerOfTenLL[14]*/){
2646
if (lon < 1000000000000L /*powerOfTenLL[12]*/){
2647
if (lon < 100000000000L /*powerOfTenLL[11]*/)
2648
return 11;
2649
else
2650
return 12;
2651
}
2652
else if (lon < 10000000000000L /*powerOfTenLL[13]*/)
2653
return 13;
2654
else
2655
return 14;
2656
}
2657
else if (lon < 10000000000000000L /*powerOfTenLL[16]*/){
2658
if (lon < 1000000000000000L /*powerOfTenLL[15]*/)
2659
return 15;
2660
else
2661
return 16;
2662
}
2663
else if (lon < 100000000000000000L /*powerOfTenLL[17]*/)
2664
return 17;
2665
else if (lon < 1000000000000000000L /*powerOfTenLL[18]*/)
2666
return 18;
2667
return 19;
2668
}
2669
}
2670
2671
private final static int digitAtBCD(long bcd, int numDigits, int indexFromLeft){
2672
2673
int indexFromRight = numDigits-indexFromLeft-1;
2674
switch (indexFromRight){
2675
case 0:
2676
return (int)(bcd & 0x000000000000000FL);
2677
case 1:
2678
return (int)((bcd & 0x00000000000000F0L)>>>4);
2679
case 2:
2680
return (int)((bcd & 0x0000000000000F00L)>>>8);
2681
case 3:
2682
return (int)((bcd & 0x000000000000F000L)>>>12);
2683
case 4:
2684
return (int)((bcd & 0x00000000000F0000L)>>>16);
2685
case 5:
2686
return (int)((bcd & 0x0000000000F00000L)>>>20);
2687
case 6:
2688
return (int)((bcd & 0x000000000F000000L)>>>24);
2689
case 7:
2690
return (int)((bcd & 0x00000000F0000000L)>>>28);
2691
case 8:
2692
return (int)((bcd & 0xF00000000L)>>>32);
2693
case 9:
2694
return (int)((bcd & 0xF000000000L)>>>36);
2695
case 10:
2696
return (int)((bcd & 0xF0000000000L)>>>40);
2697
case 11:
2698
return (int)((bcd & 0xF00000000000L)>>44);
2699
case 12:
2700
return (int)((bcd & 0xF000000000000L)>>>48);
2701
case 13:
2702
return (int)((bcd & 0xF0000000000000L)>>>52);
2703
case 14:
2704
return (int)((bcd & 0xF00000000000000L)>>>56);
2705
case 15:
2706
return (int)((bcd & 0xF000000000000000L)>>>60);
2707
default:
2708
return 0;
2709
}
2710
}
2711
2712
private final static int digitAt(long lon, int numdigits, int loc){
2713
2714
lon = Math.abs(lon);
2715
if (loc > numdigits-1)return -1;
2716
if (loc < 0) return -1;
2717
int indexFromRight = numdigits-loc-1;
2718
if (lon <= Integer.MAX_VALUE){
2719
int temp=(int)lon;
2720
switch (indexFromRight){
2721
case 0:
2722
break;
2723
case 1:
2724
temp /=10;
2725
break;
2726
case 2:
2727
temp /=100;
2728
break;
2729
case 3:
2730
temp /=1000;
2731
break;
2732
case 4:
2733
temp /=10000;
2734
break;
2735
case 5:
2736
temp /=100000;
2737
break;
2738
case 6:
2739
temp /=1000000;
2740
break;
2741
case 7:
2742
temp /=10000000;
2743
break;
2744
case 8:
2745
temp /=100000000;
2746
break;
2747
case 9:
2748
temp /=1000000000; //unsure whether remaining cases would
2749
break; //ever be taken in the Integer case
2750
case 10:
2751
temp /=10000000000L;
2752
break;
2753
case 11:
2754
temp /=100000000000L;
2755
break;
2756
case 12:
2757
temp /=1000000000000L;
2758
break;
2759
case 13:
2760
temp /=10000000000000L;
2761
break;
2762
case 14:
2763
temp /=100000000000000L;
2764
break;
2765
case 15:
2766
temp /=1000000000000000L;
2767
break;
2768
case 16:
2769
temp /=10000000000000000L;
2770
break;
2771
case 17:
2772
temp /=100000000000000000L;
2773
break;
2774
case 18:
2775
temp /=1000000000000000000L;
2776
break;
2777
}
2778
2779
// find remainder
2780
if (temp <= Integer.MAX_VALUE){
2781
int intTmp = (int)temp;
2782
int tmpVal = intTmp;
2783
intTmp = uDivideByTen(intTmp);
2784
return (tmpVal - ((intTmp << 3) + (intTmp << 1)));
2785
}
2786
else{
2787
long tmpVal = temp;
2788
temp/=10;
2789
return (int)(tmpVal - (((temp << 3) + (temp << 1))));
2790
}
2791
}
2792
else{
2793
long temp=lon;
2794
switch (indexFromRight){
2795
case 0:
2796
break;
2797
case 1:
2798
temp /= 10;
2799
break;
2800
case 2:
2801
temp /= 100;
2802
break;
2803
case 3:
2804
temp /= 1000;
2805
break;
2806
case 4:
2807
temp /= 10000;
2808
break;
2809
case 5:
2810
temp /= 100000;
2811
break;
2812
case 6:
2813
temp /= 1000000;
2814
break;
2815
case 7:
2816
temp /= 10000000;
2817
break;
2818
case 8:
2819
temp /= 100000000;
2820
break;
2821
case 9:
2822
temp /= 1000000000;
2823
break;
2824
case 10:
2825
temp /= 10000000000L;
2826
break;
2827
case 11:
2828
temp /= 100000000000L;
2829
break;
2830
case 12:
2831
temp /= 1000000000000L;
2832
break;
2833
case 13:
2834
temp /= 10000000000000L;
2835
break;
2836
case 14:
2837
temp /= 100000000000000L;
2838
break;
2839
case 15:
2840
temp /= 1000000000000000L;
2841
break;
2842
case 16:
2843
temp /= 10000000000000000L;
2844
break;
2845
case 17:
2846
temp /= 100000000000000000L;
2847
break;
2848
case 18:
2849
temp /= 1000000000000000000L;
2850
break;
2851
}
2852
2853
// find remainder
2854
if (temp <= Integer.MAX_VALUE){
2855
int intTmp = (int)temp;
2856
int tmpVal = intTmp;
2857
intTmp = uDivideByTen(intTmp);
2858
return (tmpVal - ((intTmp << 3) + (intTmp << 1)));
2859
}
2860
else{
2861
long tmpVal = temp;
2862
temp/=10;
2863
return (int)(tmpVal - (((temp << 3) + (temp << 1))));
2864
}
2865
}
2866
}
2867
2868
private final static int uDivideByTen(int x){
2869
int q = (x >> 1) + (x >> 2);
2870
q = q + (q >> 4);
2871
q = q + (q >> 8);
2872
q = q + (q >> 16);
2873
q >>=3;
2874
x -= q*10;
2875
return q + ((x + 6) >> 4);
2876
}
2877
2878
private final void badDivideByZero() {
2879
/*[MSG "K0407", "division by zero"]*/
2880
throw new ArithmeticException(com.ibm.oti.util.Msg.getString("K0407")); //$NON-NLS-1$
2881
}
2882
private final void conversionOverflow(BigDecimal bd) {
2883
/*[MSG "K0458", "Conversion overflow: {0}"]*/
2884
throw new ArithmeticException(com.ibm.oti.util.Msg.getString("K0458", bd)); //$NON-NLS-1$
2885
}
2886
private final void nonZeroDecimals(BigDecimal bd) {
2887
/*[MSG "K0457", "Non-zero decimal digits: {0}"]*/
2888
throw new ArithmeticException(com.ibm.oti.util.Msg.getString("K0457", bd)); //$NON-NLS-1$
2889
}
2890
private final void scaleOutOfRange(long s) {
2891
/*[MSG "K0451", "BigDecimal scale outside legal range: {0}"]*/
2892
throw new ArithmeticException(com.ibm.oti.util.Msg.getString("K0451", Long.toString(s))); //$NON-NLS-1$
2893
}
2894
private static final void scaleOverflow() {
2895
/*[MSG "K0453", "Scale overflow"]*/
2896
throw new ArithmeticException(com.ibm.oti.util.Msg.getString("K0453")); //$NON-NLS-1$
2897
}
2898
}
2899
2900
/*[ENDIF] #INCLUDE */
2901
/*[REM] do not remove following blank line*/
2902
2903
2904