1 |
/* java.math.BigDecimal -- Arbitrary precision decimals. |
/* java.math.BigDecimal -- Arbitrary precision decimals. |
2 |
Copyright (C) 1999, 2000, 2001 Free Software Foundation, Inc. |
Copyright (C) 1999, 2000, 2001, 2003 Free Software Foundation, Inc. |
3 |
|
|
4 |
This file is part of GNU Classpath. |
This file is part of GNU Classpath. |
5 |
|
|
273 |
// Ensure that pow gets a non-negative value. |
// Ensure that pow gets a non-negative value. |
274 |
int valScale = val.scale; |
int valScale = val.scale; |
275 |
BigInteger valIntVal = val.intVal; |
BigInteger valIntVal = val.intVal; |
276 |
int power = newScale + 1 - (scale - val.scale); |
int power = newScale - (scale - val.scale); |
277 |
if (power < 0) |
if (power < 0) |
278 |
{ |
{ |
279 |
// Effectively increase the scale of val to avoid an |
// Effectively increase the scale of val to avoid an |
288 |
// System.out.println("int: " + parts[0]); |
// System.out.println("int: " + parts[0]); |
289 |
// System.out.println("rem: " + parts[1]); |
// System.out.println("rem: " + parts[1]); |
290 |
|
|
291 |
int roundDigit = parts[0].mod (BigInteger.valueOf (10)).intValue (); |
BigInteger unrounded = parts[0]; |
292 |
BigInteger unrounded = parts[0].divide (BigInteger.valueOf (10)); |
if (parts[1].signum () == 0) // no remainder, no rounding necessary |
|
|
|
|
if (roundDigit == 0 && parts[1].signum () == 0) // no rounding necessary |
|
293 |
return new BigDecimal (unrounded, newScale); |
return new BigDecimal (unrounded, newScale); |
294 |
|
|
295 |
|
if (roundingMode == ROUND_UNNECESSARY) |
296 |
|
throw new ArithmeticException ("newScale is not large enough"); |
297 |
|
|
298 |
int sign = unrounded.signum (); |
int sign = unrounded.signum (); |
299 |
|
|
300 |
switch (roundingMode) |
if (roundingMode == ROUND_CEILING) |
301 |
|
roundingMode = (sign == 1) ? ROUND_UP : ROUND_DOWN; |
302 |
|
else if (roundingMode == ROUND_FLOOR) |
303 |
|
roundingMode = (sign == 1) ? ROUND_DOWN : ROUND_UP; |
304 |
|
else |
305 |
{ |
{ |
306 |
case ROUND_UNNECESSARY: |
// half is -1 if remainder*2 < positive intValue (*power), 0 if equal, |
307 |
throw new ArithmeticException ("newScale is not large enough"); |
// 1 if >. This implies that the remainder to round is less than, |
308 |
case ROUND_CEILING: |
// equal to, or greater than half way to the next digit. |
309 |
roundingMode = (sign == 1) ? ROUND_UP : ROUND_DOWN; |
BigInteger posRemainder = sign == -1 ? parts[1].negate() : parts[1]; |
310 |
break; |
int half = posRemainder.shiftLeft(1).compareTo(valIntVal); |
311 |
case ROUND_FLOOR: |
|
312 |
roundingMode = (sign == 1) ? ROUND_DOWN : ROUND_UP; |
switch(roundingMode) |
|
break; |
|
|
case ROUND_HALF_UP: |
|
|
roundingMode = (roundDigit >= 5) ? ROUND_UP : ROUND_DOWN; |
|
|
break; |
|
|
case ROUND_HALF_DOWN: |
|
|
roundingMode = (roundDigit > 5) ? ROUND_UP : ROUND_DOWN; |
|
|
break; |
|
|
case ROUND_HALF_EVEN: |
|
|
if (roundDigit < 5) |
|
|
roundingMode = ROUND_DOWN; |
|
|
else |
|
313 |
{ |
{ |
314 |
int rightmost = |
case ROUND_HALF_UP: |
315 |
unrounded.mod (BigInteger.valueOf (10)).intValue (); |
roundingMode = (half == -1) ? ROUND_DOWN : ROUND_UP; |
316 |
if (rightmost % 2 == 1) // odd, then ROUND_HALF_UP |
break; |
317 |
|
case ROUND_HALF_DOWN: |
318 |
|
roundingMode = (half == 1) ? ROUND_UP : ROUND_DOWN; |
319 |
|
break; |
320 |
|
case ROUND_HALF_EVEN: |
321 |
|
if (half == -1) |
322 |
|
roundingMode = ROUND_DOWN; |
323 |
|
else if (half == 1) |
324 |
|
roundingMode = ROUND_UP; |
325 |
|
else if (unrounded.testBit(0)) // odd, then ROUND_HALF_UP |
326 |
roundingMode = ROUND_UP; |
roundingMode = ROUND_UP; |
327 |
else // even, then ROUND_HALF_DOWN |
else // even, ROUND_HALF_DOWN |
328 |
roundingMode = (roundDigit > 5) ? ROUND_UP : ROUND_DOWN; |
roundingMode = ROUND_DOWN; |
329 |
|
break; |
330 |
} |
} |
|
break; |
|
331 |
} |
} |
332 |
|
|
333 |
if (roundingMode == ROUND_UP) |
if (roundingMode == ROUND_UP) |
334 |
return new BigDecimal (unrounded.add (BigInteger.valueOf (1)), newScale); |
return new BigDecimal (unrounded.add (BigInteger.valueOf |
335 |
|
(sign != 0 ? sign : 1)), newScale); |
336 |
|
|
337 |
// roundingMode == ROUND_DOWN |
// roundingMode == ROUND_DOWN |
338 |
return new BigDecimal (unrounded, newScale); |
return new BigDecimal (unrounded, newScale); |