1 /* GENERATED SOURCE. DO NOT MODIFY. */ 2 // 2017 and later: Unicode, Inc. and others. 3 // License & terms of use: http://www.unicode.org/copyright.html#License 4 package android.icu.impl.number; 5 6 import java.math.BigDecimal; 7 import java.math.BigInteger; 8 import java.math.MathContext; 9 import java.text.FieldPosition; 10 11 import android.icu.impl.StandardPlural; 12 import android.icu.text.PluralRules; 13 import android.icu.text.PluralRules.Operand; 14 import android.icu.text.UFieldPosition; 15 16 /** 17 * Represents numbers and digit display properties using Binary Coded Decimal (BCD). 18 * 19 * @implements {@link DecimalQuantity} 20 * @hide Only a subset of ICU is exposed in Android 21 */ 22 public abstract class DecimalQuantity_AbstractBCD implements DecimalQuantity { 23 24 /** 25 * The power of ten corresponding to the least significant digit in the BCD. For example, if this 26 * object represents the number "3.14", the BCD will be "0x314" and the scale will be -2. 27 * 28 * <p>Note that in {@link java.math.BigDecimal}, the scale is defined differently: the number of 29 * digits after the decimal place, which is the negative of our definition of scale. 30 */ 31 protected int scale; 32 33 /** 34 * The number of digits in the BCD. For example, "1007" has BCD "0x1007" and precision 4. The 35 * maximum precision is 16 since a long can hold only 16 digits. 36 * 37 * <p>This value must be re-calculated whenever the value in bcd changes by using {@link 38 * #computePrecisionAndCompact()}. 39 */ 40 protected int precision; 41 42 /** 43 * A bitmask of properties relating to the number represented by this object. 44 * 45 * @see #NEGATIVE_FLAG 46 * @see #INFINITY_FLAG 47 * @see #NAN_FLAG 48 */ 49 protected byte flags; 50 51 protected static final int NEGATIVE_FLAG = 1; 52 protected static final int INFINITY_FLAG = 2; 53 protected static final int NAN_FLAG = 4; 54 55 // The following three fields relate to the double-to-ascii fast path algorithm. 56 // When a double is given to DecimalQuantityBCD, it is converted to using a fast algorithm. The 57 // fast algorithm guarantees correctness to only the first ~12 digits of the double. The process 58 // of rounding the number ensures that the converted digits are correct, falling back to a slow- 59 // path algorithm if required. Therefore, if a DecimalQuantity is constructed from a double, it 60 // is *required* that roundToMagnitude(), roundToIncrement(), or roundToInfinity() is called. If 61 // you don't round, assertions will fail in certain other methods if you try calling them. 62 63 /** 64 * The original number provided by the user and which is represented in BCD. Used when we need to 65 * re-compute the BCD for an exact double representation. 66 */ 67 protected double origDouble; 68 69 /** 70 * The change in magnitude relative to the original double. Used when we need to re-compute the 71 * BCD for an exact double representation. 72 */ 73 protected int origDelta; 74 75 /** 76 * Whether the value in the BCD comes from the double fast path without having been rounded to 77 * ensure correctness 78 */ 79 protected boolean isApproximate; 80 81 // Four positions: left optional '(', left required '[', right required ']', right optional ')'. 82 // These four positions determine which digits are displayed in the output string. They do NOT 83 // affect rounding. These positions are internal-only and can be specified only by the public 84 // endpoints like setFractionLength, setIntegerLength, and setSignificantDigits, among others. 85 // 86 // * Digits between lReqPos and rReqPos are in the "required zone" and are always displayed. 87 // * Digits between lOptPos and rOptPos but outside the required zone are in the "optional zone" 88 // and are displayed unless they are trailing off the left or right edge of the number and 89 // have a numerical value of zero. In order to be "trailing", the digits need to be beyond 90 // the decimal point in their respective directions. 91 // * Digits outside of the "optional zone" are never displayed. 92 // 93 // See the table below for illustrative examples. 94 // 95 // +---------+---------+---------+---------+------------+------------------------+--------------+ 96 // | lOptPos | lReqPos | rReqPos | rOptPos | number | positions | en-US string | 97 // +---------+---------+---------+---------+------------+------------------------+--------------+ 98 // | 5 | 2 | -1 | -5 | 1234.567 | ( 12[34.5]67 ) | 1,234.567 | 99 // | 3 | 2 | -1 | -5 | 1234.567 | 1(2[34.5]67 ) | 234.567 | 100 // | 3 | 2 | -1 | -2 | 1234.567 | 1(2[34.5]6)7 | 234.56 | 101 // | 6 | 4 | 2 | -5 | 123456789. | 123(45[67]89. ) | 456,789. | 102 // | 6 | 4 | 2 | 1 | 123456789. | 123(45[67]8)9. | 456,780. | 103 // | -1 | -1 | -3 | -4 | 0.123456 | 0.1([23]4)56 | .0234 | 104 // | 6 | 4 | -2 | -2 | 12.3 | ( [ 12.3 ]) | 0012.30 | 105 // +---------+---------+---------+---------+------------+------------------------+--------------+ 106 // 107 protected int lOptPos = Integer.MAX_VALUE; 108 protected int lReqPos = 0; 109 protected int rReqPos = 0; 110 protected int rOptPos = Integer.MIN_VALUE; 111 112 @Override 113 public void copyFrom(DecimalQuantity _other) { 114 copyBcdFrom(_other); 115 DecimalQuantity_AbstractBCD other = (DecimalQuantity_AbstractBCD) _other; 116 lOptPos = other.lOptPos; 117 lReqPos = other.lReqPos; 118 rReqPos = other.rReqPos; 119 rOptPos = other.rOptPos; 120 scale = other.scale; 121 precision = other.precision; 122 flags = other.flags; 123 origDouble = other.origDouble; 124 origDelta = other.origDelta; 125 isApproximate = other.isApproximate; 126 } 127 128 public DecimalQuantity_AbstractBCD clear() { 129 lOptPos = Integer.MAX_VALUE; 130 lReqPos = 0; 131 rReqPos = 0; 132 rOptPos = Integer.MIN_VALUE; 133 flags = 0; 134 setBcdToZero(); // sets scale, precision, hasDouble, origDouble, origDelta, and BCD data 135 return this; 136 } 137 138 @Override 139 public void setIntegerLength(int minInt, int maxInt) { 140 // Validation should happen outside of DecimalQuantity, e.g., in the Rounder class. 141 assert minInt >= 0; 142 assert maxInt >= minInt; 143 144 // Save values into internal state 145 // Negation is safe for minFrac/maxFrac because -Integer.MAX_VALUE > Integer.MIN_VALUE 146 lOptPos = maxInt; 147 lReqPos = minInt; 148 } 149 150 @Override 151 public void setFractionLength(int minFrac, int maxFrac) { 152 // Validation should happen outside of DecimalQuantity, e.g., in the Rounder class. 153 assert minFrac >= 0; 154 assert maxFrac >= minFrac; 155 156 // Save values into internal state 157 // Negation is safe for minFrac/maxFrac because -Integer.MAX_VALUE > Integer.MIN_VALUE 158 rReqPos = -minFrac; 159 rOptPos = -maxFrac; 160 } 161 162 @Override 163 public long getPositionFingerprint() { 164 long fingerprint = 0; 165 fingerprint ^= lOptPos; 166 fingerprint ^= (lReqPos << 16); 167 fingerprint ^= ((long) rReqPos << 32); 168 fingerprint ^= ((long) rOptPos << 48); 169 return fingerprint; 170 } 171 172 @Override 173 public void roundToIncrement(BigDecimal roundingIncrement, MathContext mathContext) { 174 // TODO: Avoid converting back and forth to BigDecimal. 175 BigDecimal temp = toBigDecimal(); 176 temp = 177 temp.divide(roundingIncrement, 0, mathContext.getRoundingMode()) 178 .multiply(roundingIncrement) 179 .round(mathContext); 180 if (temp.signum() == 0) { 181 setBcdToZero(); // keeps negative flag for -0.0 182 } else { 183 setToBigDecimal(temp); 184 } 185 } 186 187 @Override 188 public void multiplyBy(BigDecimal multiplicand) { 189 if (isInfinite() || isZero() || isNaN()) { 190 return; 191 } 192 BigDecimal temp = toBigDecimal(); 193 temp = temp.multiply(multiplicand); 194 setToBigDecimal(temp); 195 } 196 197 @Override 198 public int getMagnitude() throws ArithmeticException { 199 if (precision == 0) { 200 throw new ArithmeticException("Magnitude is not well-defined for zero"); 201 } else { 202 return scale + precision - 1; 203 } 204 } 205 206 @Override 207 public void adjustMagnitude(int delta) { 208 if (precision != 0) { 209 scale += delta; 210 origDelta += delta; 211 } 212 } 213 214 @Override 215 public StandardPlural getStandardPlural(PluralRules rules) { 216 if (rules == null) { 217 // Fail gracefully if the user didn't provide a PluralRules 218 return StandardPlural.OTHER; 219 } else { 220 @SuppressWarnings("deprecation") 221 String ruleString = rules.select(this); 222 return StandardPlural.orOtherFromString(ruleString); 223 } 224 } 225 226 @Override 227 public double getPluralOperand(Operand operand) { 228 // If this assertion fails, you need to call roundToInfinity() or some other rounding method. 229 // See the comment at the top of this file explaining the "isApproximate" field. 230 assert !isApproximate; 231 232 switch (operand) { 233 case i: 234 return toLong(); 235 case f: 236 return toFractionLong(true); 237 case t: 238 return toFractionLong(false); 239 case v: 240 return fractionCount(); 241 case w: 242 return fractionCountWithoutTrailingZeros(); 243 default: 244 return Math.abs(toDouble()); 245 } 246 } 247 248 @Override 249 public void populateUFieldPosition(FieldPosition fp) { 250 if (fp instanceof UFieldPosition) { 251 ((UFieldPosition) fp) 252 .setFractionDigits((int) getPluralOperand(Operand.v), (long) getPluralOperand(Operand.f)); 253 } 254 } 255 256 @Override 257 public int getUpperDisplayMagnitude() { 258 // If this assertion fails, you need to call roundToInfinity() or some other rounding method. 259 // See the comment at the top of this file explaining the "isApproximate" field. 260 assert !isApproximate; 261 262 int magnitude = scale + precision; 263 int result = (lReqPos > magnitude) ? lReqPos : (lOptPos < magnitude) ? lOptPos : magnitude; 264 return result - 1; 265 } 266 267 @Override 268 public int getLowerDisplayMagnitude() { 269 // If this assertion fails, you need to call roundToInfinity() or some other rounding method. 270 // See the comment at the top of this file explaining the "isApproximate" field. 271 assert !isApproximate; 272 273 int magnitude = scale; 274 int result = (rReqPos < magnitude) ? rReqPos : (rOptPos > magnitude) ? rOptPos : magnitude; 275 return result; 276 } 277 278 @Override 279 public byte getDigit(int magnitude) { 280 // If this assertion fails, you need to call roundToInfinity() or some other rounding method. 281 // See the comment at the top of this file explaining the "isApproximate" field. 282 assert !isApproximate; 283 284 return getDigitPos(magnitude - scale); 285 } 286 287 private int fractionCount() { 288 return -getLowerDisplayMagnitude(); 289 } 290 291 private int fractionCountWithoutTrailingZeros() { 292 return Math.max(-scale, 0); 293 } 294 295 @Override 296 public boolean isNegative() { 297 return (flags & NEGATIVE_FLAG) != 0; 298 } 299 300 @Override 301 public boolean isInfinite() { 302 return (flags & INFINITY_FLAG) != 0; 303 } 304 305 @Override 306 public boolean isNaN() { 307 return (flags & NAN_FLAG) != 0; 308 } 309 310 @Override 311 public boolean isZero() { 312 return precision == 0; 313 } 314 315 public void setToInt(int n) { 316 setBcdToZero(); 317 flags = 0; 318 if (n < 0) { 319 flags |= NEGATIVE_FLAG; 320 n = -n; 321 } 322 if (n != 0) { 323 _setToInt(n); 324 compact(); 325 } 326 } 327 328 private void _setToInt(int n) { 329 if (n == Integer.MIN_VALUE) { 330 readLongToBcd(-(long) n); 331 } else { 332 readIntToBcd(n); 333 } 334 } 335 336 public void setToLong(long n) { 337 setBcdToZero(); 338 flags = 0; 339 if (n < 0) { 340 flags |= NEGATIVE_FLAG; 341 n = -n; 342 } 343 if (n != 0) { 344 _setToLong(n); 345 compact(); 346 } 347 } 348 349 private void _setToLong(long n) { 350 if (n == Long.MIN_VALUE) { 351 readBigIntegerToBcd(BigInteger.valueOf(n).negate()); 352 } else if (n <= Integer.MAX_VALUE) { 353 readIntToBcd((int) n); 354 } else { 355 readLongToBcd(n); 356 } 357 } 358 359 public void setToBigInteger(BigInteger n) { 360 setBcdToZero(); 361 flags = 0; 362 if (n.signum() == -1) { 363 flags |= NEGATIVE_FLAG; 364 n = n.negate(); 365 } 366 if (n.signum() != 0) { 367 _setToBigInteger(n); 368 compact(); 369 } 370 } 371 372 private void _setToBigInteger(BigInteger n) { 373 if (n.bitLength() < 32) { 374 readIntToBcd(n.intValue()); 375 } else if (n.bitLength() < 64) { 376 readLongToBcd(n.longValue()); 377 } else { 378 readBigIntegerToBcd(n); 379 } 380 } 381 382 /** 383 * Sets the internal BCD state to represent the value in the given double. 384 * 385 * @param n The value to consume. 386 */ 387 public void setToDouble(double n) { 388 setBcdToZero(); 389 flags = 0; 390 // Double.compare() handles +0.0 vs -0.0 391 if (Double.compare(n, 0.0) < 0) { 392 flags |= NEGATIVE_FLAG; 393 n = -n; 394 } 395 if (Double.isNaN(n)) { 396 flags |= NAN_FLAG; 397 } else if (Double.isInfinite(n)) { 398 flags |= INFINITY_FLAG; 399 } else if (n != 0) { 400 _setToDoubleFast(n); 401 compact(); 402 } 403 } 404 405 private static final double[] DOUBLE_MULTIPLIERS = { 406 1e0, 1e1, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8, 1e9, 1e10, 1e11, 1e12, 1e13, 1e14, 1e15, 1e16, 407 1e17, 1e18, 1e19, 1e20, 1e21 408 }; 409 410 /** 411 * Uses double multiplication and division to get the number into integer space before converting 412 * to digits. Since double arithmetic is inexact, the resulting digits may not be accurate. 413 */ 414 private void _setToDoubleFast(double n) { 415 isApproximate = true; 416 origDouble = n; 417 origDelta = 0; 418 419 // NOTE: Unlike ICU4C, doubles are always IEEE 754 doubles. 420 long ieeeBits = Double.doubleToLongBits(n); 421 int exponent = (int) ((ieeeBits & 0x7ff0000000000000L) >> 52) - 0x3ff; 422 423 // Not all integers can be represented exactly for exponent > 52 424 if (exponent <= 52 && (long) n == n) { 425 _setToLong((long) n); 426 return; 427 } 428 429 // 3.3219... is log2(10) 430 int fracLength = (int) ((52 - exponent) / 3.32192809489); 431 if (fracLength >= 0) { 432 int i = fracLength; 433 // 1e22 is the largest exact double. 434 for (; i >= 22; i -= 22) n *= 1e22; 435 n *= DOUBLE_MULTIPLIERS[i]; 436 } else { 437 int i = fracLength; 438 // 1e22 is the largest exact double. 439 for (; i <= -22; i += 22) n /= 1e22; 440 n /= DOUBLE_MULTIPLIERS[-i]; 441 } 442 long result = Math.round(n); 443 if (result != 0) { 444 _setToLong(result); 445 scale -= fracLength; 446 } 447 } 448 449 /** 450 * Uses Double.toString() to obtain an exact accurate representation of the double, overwriting it 451 * into the BCD. This method can be called at any point after {@link #_setToDoubleFast} while 452 * {@link #isApproximate} is still true. 453 */ 454 private void convertToAccurateDouble() { 455 double n = origDouble; 456 assert n != 0; 457 int delta = origDelta; 458 setBcdToZero(); 459 460 // Call the slow oracle function (Double.toString in Java, sprintf in C++). 461 String dstr = Double.toString(n); 462 463 if (dstr.indexOf('E') != -1) { 464 // Case 1: Exponential notation. 465 assert dstr.indexOf('.') == 1; 466 int expPos = dstr.indexOf('E'); 467 _setToLong(Long.parseLong(dstr.charAt(0) + dstr.substring(2, expPos))); 468 scale += Integer.parseInt(dstr.substring(expPos + 1)) - (expPos - 1) + 1; 469 } else if (dstr.charAt(0) == '0') { 470 // Case 2: Fraction-only number. 471 assert dstr.indexOf('.') == 1; 472 _setToLong(Long.parseLong(dstr.substring(2))); 473 scale += 2 - dstr.length(); 474 } else if (dstr.charAt(dstr.length() - 1) == '0') { 475 // Case 3: Integer-only number. 476 // Note: this path should not normally happen, because integer-only numbers are captured 477 // before the approximate double logic is performed. 478 assert dstr.indexOf('.') == dstr.length() - 2; 479 assert dstr.length() - 2 <= 18; 480 _setToLong(Long.parseLong(dstr.substring(0, dstr.length() - 2))); 481 // no need to adjust scale 482 } else { 483 // Case 4: Number with both a fraction and an integer. 484 int decimalPos = dstr.indexOf('.'); 485 _setToLong(Long.parseLong(dstr.substring(0, decimalPos) + dstr.substring(decimalPos + 1))); 486 scale += decimalPos - dstr.length() + 1; 487 } 488 489 scale += delta; 490 compact(); 491 explicitExactDouble = true; 492 } 493 494 /** 495 * Whether this {@link DecimalQuantity_DualStorageBCD} has been explicitly converted to an exact double. true if 496 * backed by a double that was explicitly converted via convertToAccurateDouble; false otherwise. 497 * Used for testing. 498 * 499 * @deprecated This API is ICU internal only. 500 * @hide draft / provisional / internal are hidden on Android 501 */ 502 @Deprecated public boolean explicitExactDouble = false; 503 504 /** 505 * Sets the internal BCD state to represent the value in the given BigDecimal. 506 * 507 * @param n The value to consume. 508 */ 509 @Override 510 public void setToBigDecimal(BigDecimal n) { 511 setBcdToZero(); 512 flags = 0; 513 if (n.signum() == -1) { 514 flags |= NEGATIVE_FLAG; 515 n = n.negate(); 516 } 517 if (n.signum() != 0) { 518 _setToBigDecimal(n); 519 compact(); 520 } 521 } 522 523 private void _setToBigDecimal(BigDecimal n) { 524 int fracLength = n.scale(); 525 n = n.scaleByPowerOfTen(fracLength); 526 BigInteger bi = n.toBigInteger(); 527 _setToBigInteger(bi); 528 scale -= fracLength; 529 } 530 531 /** 532 * Returns a long approximating the internal BCD. A long can only represent the integral part of 533 * the number. 534 * 535 * @return A double representation of the internal BCD. 536 */ 537 protected long toLong() { 538 long result = 0L; 539 for (int magnitude = scale + precision - 1; magnitude >= 0; magnitude--) { 540 result = result * 10 + getDigitPos(magnitude - scale); 541 } 542 return result; 543 } 544 545 /** 546 * This returns a long representing the fraction digits of the number, as required by PluralRules. 547 * For example, if we represent the number "1.20" (including optional and required digits), then 548 * this function returns "20" if includeTrailingZeros is true or "2" if false. 549 */ 550 protected long toFractionLong(boolean includeTrailingZeros) { 551 long result = 0L; 552 int magnitude = -1; 553 for (; 554 (magnitude >= scale || (includeTrailingZeros && magnitude >= rReqPos)) 555 && magnitude >= rOptPos; 556 magnitude--) { 557 result = result * 10 + getDigitPos(magnitude - scale); 558 } 559 return result; 560 } 561 562 /** 563 * Returns a double approximating the internal BCD. The double may not retain all of the 564 * information encoded in the BCD if the BCD represents a number out of range of a double. 565 * 566 * @return A double representation of the internal BCD. 567 */ 568 @Override 569 public double toDouble() { 570 if (isApproximate) { 571 return toDoubleFromOriginal(); 572 } 573 574 if (isNaN()) { 575 return Double.NaN; 576 } else if (isInfinite()) { 577 return isNegative() ? Double.NEGATIVE_INFINITY : Double.POSITIVE_INFINITY; 578 } 579 580 long tempLong = 0L; 581 int lostDigits = precision - Math.min(precision, 17); 582 for (int shift = precision - 1; shift >= lostDigits; shift--) { 583 tempLong = tempLong * 10 + getDigitPos(shift); 584 } 585 double result = tempLong; 586 int _scale = scale + lostDigits; 587 if (_scale >= 0) { 588 // 1e22 is the largest exact double. 589 int i = _scale; 590 for (; i >= 22; i -= 22) result *= 1e22; 591 result *= DOUBLE_MULTIPLIERS[i]; 592 } else { 593 // 1e22 is the largest exact double. 594 int i = _scale; 595 for (; i <= -22; i += 22) result /= 1e22; 596 result /= DOUBLE_MULTIPLIERS[-i]; 597 } 598 if (isNegative()) result = -result; 599 return result; 600 } 601 602 @Override 603 public BigDecimal toBigDecimal() { 604 if (isApproximate) { 605 // Converting to a BigDecimal requires Double.toString(). 606 convertToAccurateDouble(); 607 } 608 return bcdToBigDecimal(); 609 } 610 611 protected double toDoubleFromOriginal() { 612 double result = origDouble; 613 int delta = origDelta; 614 if (delta >= 0) { 615 // 1e22 is the largest exact double. 616 for (; delta >= 22; delta -= 22) result *= 1e22; 617 result *= DOUBLE_MULTIPLIERS[delta]; 618 } else { 619 // 1e22 is the largest exact double. 620 for (; delta <= -22; delta += 22) result /= 1e22; 621 result /= DOUBLE_MULTIPLIERS[-delta]; 622 } 623 if (isNegative()) result *= -1; 624 return result; 625 } 626 627 private static int safeSubtract(int a, int b) { 628 int diff = a - b; 629 if (b < 0 && diff < a) return Integer.MAX_VALUE; 630 if (b > 0 && diff > a) return Integer.MIN_VALUE; 631 return diff; 632 } 633 634 private static final int SECTION_LOWER_EDGE = -1; 635 private static final int SECTION_UPPER_EDGE = -2; 636 637 @Override 638 public void roundToMagnitude(int magnitude, MathContext mathContext) { 639 // The position in the BCD at which rounding will be performed; digits to the right of position 640 // will be rounded away. 641 // TODO: Andy: There was a test failure because of integer overflow here. Should I do 642 // "safe subtraction" everywhere in the code? What's the nicest way to do it? 643 int position = safeSubtract(magnitude, scale); 644 645 // Enforce the number of digits required by the MathContext. 646 int _mcPrecision = mathContext.getPrecision(); 647 if (magnitude == Integer.MAX_VALUE 648 || (_mcPrecision > 0 && precision - position > _mcPrecision)) { 649 position = precision - _mcPrecision; 650 } 651 652 if (position <= 0 && !isApproximate) { 653 // All digits are to the left of the rounding magnitude. 654 } else if (precision == 0) { 655 // No rounding for zero. 656 } else { 657 // Perform rounding logic. 658 // "leading" = most significant digit to the right of rounding 659 // "trailing" = least significant digit to the left of rounding 660 byte leadingDigit = getDigitPos(safeSubtract(position, 1)); 661 byte trailingDigit = getDigitPos(position); 662 663 // Compute which section of the number we are in. 664 // EDGE means we are at the bottom or top edge, like 1.000 or 1.999 (used by doubles) 665 // LOWER means we are between the bottom edge and the midpoint, like 1.391 666 // MIDPOINT means we are exactly in the middle, like 1.500 667 // UPPER means we are between the midpoint and the top edge, like 1.916 668 int section = RoundingUtils.SECTION_MIDPOINT; 669 if (!isApproximate) { 670 if (leadingDigit < 5) { 671 section = RoundingUtils.SECTION_LOWER; 672 } else if (leadingDigit > 5) { 673 section = RoundingUtils.SECTION_UPPER; 674 } else { 675 for (int p = safeSubtract(position, 2); p >= 0; p--) { 676 if (getDigitPos(p) != 0) { 677 section = RoundingUtils.SECTION_UPPER; 678 break; 679 } 680 } 681 } 682 } else { 683 int p = safeSubtract(position, 2); 684 int minP = Math.max(0, precision - 14); 685 if (leadingDigit == 0) { 686 section = SECTION_LOWER_EDGE; 687 for (; p >= minP; p--) { 688 if (getDigitPos(p) != 0) { 689 section = RoundingUtils.SECTION_LOWER; 690 break; 691 } 692 } 693 } else if (leadingDigit == 4) { 694 for (; p >= minP; p--) { 695 if (getDigitPos(p) != 9) { 696 section = RoundingUtils.SECTION_LOWER; 697 break; 698 } 699 } 700 } else if (leadingDigit == 5) { 701 for (; p >= minP; p--) { 702 if (getDigitPos(p) != 0) { 703 section = RoundingUtils.SECTION_UPPER; 704 break; 705 } 706 } 707 } else if (leadingDigit == 9) { 708 section = SECTION_UPPER_EDGE; 709 for (; p >= minP; p--) { 710 if (getDigitPos(p) != 9) { 711 section = RoundingUtils.SECTION_UPPER; 712 break; 713 } 714 } 715 } else if (leadingDigit < 5) { 716 section = RoundingUtils.SECTION_LOWER; 717 } else { 718 section = RoundingUtils.SECTION_UPPER; 719 } 720 721 boolean roundsAtMidpoint = 722 RoundingUtils.roundsAtMidpoint(mathContext.getRoundingMode().ordinal()); 723 if (safeSubtract(position, 1) < precision - 14 724 || (roundsAtMidpoint && section == RoundingUtils.SECTION_MIDPOINT) 725 || (!roundsAtMidpoint && section < 0 /* i.e. at upper or lower edge */)) { 726 // Oops! This means that we have to get the exact representation of the double, because 727 // the zone of uncertainty is along the rounding boundary. 728 convertToAccurateDouble(); 729 roundToMagnitude(magnitude, mathContext); // start over 730 return; 731 } 732 733 // Turn off the approximate double flag, since the value is now confirmed to be exact. 734 isApproximate = false; 735 origDouble = 0.0; 736 origDelta = 0; 737 738 if (position <= 0) { 739 // All digits are to the left of the rounding magnitude. 740 return; 741 } 742 743 // Good to continue rounding. 744 if (section == SECTION_LOWER_EDGE) section = RoundingUtils.SECTION_LOWER; 745 if (section == SECTION_UPPER_EDGE) section = RoundingUtils.SECTION_UPPER; 746 } 747 748 boolean roundDown = 749 RoundingUtils.getRoundingDirection( 750 (trailingDigit % 2) == 0, 751 isNegative(), 752 section, 753 mathContext.getRoundingMode().ordinal(), 754 this); 755 756 // Perform truncation 757 if (position >= precision) { 758 setBcdToZero(); 759 scale = magnitude; 760 } else { 761 shiftRight(position); 762 } 763 764 // Bubble the result to the higher digits 765 if (!roundDown) { 766 if (trailingDigit == 9) { 767 int bubblePos = 0; 768 // Note: in the long implementation, the most digits BCD can have at this point is 15, 769 // so bubblePos <= 15 and getDigitPos(bubblePos) is safe. 770 for (; getDigitPos(bubblePos) == 9; bubblePos++) {} 771 shiftRight(bubblePos); // shift off the trailing 9s 772 } 773 byte digit0 = getDigitPos(0); 774 assert digit0 != 9; 775 setDigitPos(0, (byte) (digit0 + 1)); 776 precision += 1; // in case an extra digit got added 777 } 778 779 compact(); 780 } 781 } 782 783 @Override 784 public void roundToInfinity() { 785 if (isApproximate) { 786 convertToAccurateDouble(); 787 } 788 } 789 790 /** 791 * Appends a digit, optionally with one or more leading zeros, to the end of the value represented 792 * by this DecimalQuantity. 793 * 794 * <p>The primary use of this method is to construct numbers during a parsing loop. It allows 795 * parsing to take advantage of the digit list infrastructure primarily designed for formatting. 796 * 797 * @param value The digit to append. 798 * @param leadingZeros The number of zeros to append before the digit. For example, if the value 799 * in this instance starts as 12.3, and you append a 4 with 1 leading zero, the value becomes 800 * 12.304. 801 * @param appendAsInteger If true, increase the magnitude of existing digits to make room for the 802 * new digit. If false, append to the end like a fraction digit. If true, there must not be 803 * any fraction digits already in the number. 804 * @deprecated This API is ICU internal only. 805 * @hide draft / provisional / internal are hidden on Android 806 */ 807 @Deprecated 808 public void appendDigit(byte value, int leadingZeros, boolean appendAsInteger) { 809 assert leadingZeros >= 0; 810 811 // Zero requires special handling to maintain the invariant that the least-significant digit 812 // in the BCD is nonzero. 813 if (value == 0) { 814 if (appendAsInteger && precision != 0) { 815 scale += leadingZeros + 1; 816 } 817 return; 818 } 819 820 // Deal with trailing zeros 821 if (scale > 0) { 822 leadingZeros += scale; 823 if (appendAsInteger) { 824 scale = 0; 825 } 826 } 827 828 // Append digit 829 shiftLeft(leadingZeros + 1); 830 setDigitPos(0, value); 831 832 // Fix scale if in integer mode 833 if (appendAsInteger) { 834 scale += leadingZeros + 1; 835 } 836 } 837 838 @Override 839 public String toPlainString() { 840 // NOTE: This logic is duplicated between here and DecimalQuantity_SimpleStorage. 841 StringBuilder sb = new StringBuilder(); 842 if (isNegative()) { 843 sb.append('-'); 844 } 845 for (int m = getUpperDisplayMagnitude(); m >= getLowerDisplayMagnitude(); m--) { 846 sb.append(getDigit(m)); 847 if (m == 0) sb.append('.'); 848 } 849 return sb.toString(); 850 } 851 852 /** 853 * Returns a single digit from the BCD list. No internal state is changed by calling this method. 854 * 855 * @param position The position of the digit to pop, counted in BCD units from the least 856 * significant digit. If outside the range supported by the implementation, zero is returned. 857 * @return The digit at the specified location. 858 */ 859 protected abstract byte getDigitPos(int position); 860 861 /** 862 * Sets the digit in the BCD list. This method only sets the digit; it is the caller's 863 * responsibility to call {@link #compact} after setting the digit. 864 * 865 * @param position The position of the digit to pop, counted in BCD units from the least 866 * significant digit. If outside the range supported by the implementation, an AssertionError 867 * is thrown. 868 * @param value The digit to set at the specified location. 869 */ 870 protected abstract void setDigitPos(int position, byte value); 871 872 /** 873 * Adds zeros to the end of the BCD list. This will result in an invalid BCD representation; it is 874 * the caller's responsibility to do further manipulation and then call {@link #compact}. 875 * 876 * @param numDigits The number of zeros to add. 877 */ 878 protected abstract void shiftLeft(int numDigits); 879 880 protected abstract void shiftRight(int numDigits); 881 882 /** 883 * Sets the internal representation to zero. Clears any values stored in scale, precision, 884 * hasDouble, origDouble, origDelta, and BCD data. 885 */ 886 protected abstract void setBcdToZero(); 887 888 /** 889 * Sets the internal BCD state to represent the value in the given int. The int is guaranteed to 890 * be either positive. The internal state is guaranteed to be empty when this method is called. 891 * 892 * @param n The value to consume. 893 */ 894 protected abstract void readIntToBcd(int input); 895 896 /** 897 * Sets the internal BCD state to represent the value in the given long. The long is guaranteed to 898 * be either positive. The internal state is guaranteed to be empty when this method is called. 899 * 900 * @param n The value to consume. 901 */ 902 protected abstract void readLongToBcd(long input); 903 904 /** 905 * Sets the internal BCD state to represent the value in the given BigInteger. The BigInteger is 906 * guaranteed to be positive, and it is guaranteed to be larger than Long.MAX_VALUE. The internal 907 * state is guaranteed to be empty when this method is called. 908 * 909 * @param n The value to consume. 910 */ 911 protected abstract void readBigIntegerToBcd(BigInteger input); 912 913 /** 914 * Returns a BigDecimal encoding the internal BCD value. 915 * 916 * @return A BigDecimal representation of the internal BCD. 917 */ 918 protected abstract BigDecimal bcdToBigDecimal(); 919 920 protected abstract void copyBcdFrom(DecimalQuantity _other); 921 922 /** 923 * Removes trailing zeros from the BCD (adjusting the scale as required) and then computes the 924 * precision. The precision is the number of digits in the number up through the greatest nonzero 925 * digit. 926 * 927 * <p>This method must always be called when bcd changes in order for assumptions to be correct in 928 * methods like {@link #fractionCount()}. 929 */ 930 protected abstract void compact(); 931 } 932