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.MathContext; 8 import java.math.RoundingMode; 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 import android.icu.testsharding.MainTestShard; 16 17 /** 18 * This is an older implementation of DecimalQuantity. A newer, faster implementation is 19 * DecimalQuantity2. I kept this implementation around because it was useful for testing purposes 20 * (being able to compare the output of one implementation with the other). 21 * 22 * <p>This class is NOT IMMUTABLE and NOT THREAD SAFE and is intended to be used by a single thread 23 * to format a number through a formatter, which is thread-safe. 24 */ 25 @MainTestShard 26 public class DecimalQuantity_SimpleStorage implements DecimalQuantity { 27 // Four positions: left optional '(', left required '[', right required ']', right optional ')'. 28 // These four positions determine which digits are displayed in the output string. They do NOT 29 // affect rounding. These positions are internal-only and can be specified only by the public 30 // endpoints like setFractionLength, setIntegerLength, and setSignificantDigits, among others. 31 // 32 // * Digits between lReqPos and rReqPos are in the "required zone" and are always displayed. 33 // * Digits between lOptPos and rOptPos but outside the required zone are in the "optional zone" 34 // and are displayed unless they are trailing off the left or right edge of the number and 35 // have a numerical value of zero. In order to be "trailing", the digits need to be beyond 36 // the decimal point in their respective directions. 37 // * Digits outside of the "optional zone" are never displayed. 38 // 39 // See the table below for illustrative examples. 40 // 41 // +---------+---------+---------+---------+------------+------------------------+--------------+ 42 // | lOptPos | lReqPos | rReqPos | rOptPos | number | positions | en-US string | 43 // +---------+---------+---------+---------+------------+------------------------+--------------+ 44 // | 5 | 2 | -1 | -5 | 1234.567 | ( 12[34.5]67 ) | 1,234.567 | 45 // | 3 | 2 | -1 | -5 | 1234.567 | 1(2[34.5]67 ) | 234.567 | 46 // | 3 | 2 | -1 | -2 | 1234.567 | 1(2[34.5]6)7 | 234.56 | 47 // | 6 | 4 | 2 | -5 | 123456789. | 123(45[67]89. ) | 456,789. | 48 // | 6 | 4 | 2 | 1 | 123456789. | 123(45[67]8)9. | 456,780. | 49 // | -1 | -1 | -3 | -4 | 0.123456 | 0.1([23]4)56 | .0234 | 50 // | 6 | 4 | -2 | -2 | 12.3 | ( [ 12.3 ]) | 0012.30 | 51 // +---------+---------+---------+---------+------------+------------------------+--------------+ 52 // 53 private int lOptPos = Integer.MAX_VALUE; 54 private int lReqPos = 0; 55 private int rReqPos = 0; 56 private int rOptPos = Integer.MIN_VALUE; 57 58 // Internally, attempt to use a long to store the number. A long can hold numbers between 18 and 59 // 19 digits, covering the vast majority of use cases. We store three values: the long itself, 60 // the "scale" of the long (the power of 10 represented by the rightmost digit in the long), and 61 // the "precision" (the number of digits in the long). "primary" and "primaryScale" are the only 62 // two variables that are required for representing the number in memory. "primaryPrecision" is 63 // saved only for the sake of performance enhancements when performing certain operations. It can 64 // always be re-computed from "primary" and "primaryScale". 65 private long primary; 66 private int primaryScale; 67 private int primaryPrecision; 68 69 // If the decimal can't fit into the long, fall back to a BigDecimal. 70 private BigDecimal fallback; 71 72 // Other properties 73 private int flags; 74 private static final int NEGATIVE_FLAG = 1; 75 private static final int INFINITY_FLAG = 2; 76 private static final int NAN_FLAG = 4; 77 private static final long[] POWERS_OF_TEN = { 78 1L, 79 10L, 80 100L, 81 1000L, 82 10000L, 83 100000L, 84 1000000L, 85 10000000L, 86 100000000L, 87 1000000000L, 88 10000000000L, 89 100000000000L, 90 1000000000000L, 91 10000000000000L, 92 100000000000000L, 93 1000000000000000L, 94 10000000000000000L, 95 100000000000000000L, 96 1000000000000000000L 97 }; 98 99 @Override 100 public int maxRepresentableDigits() { 101 return Integer.MAX_VALUE; 102 } 103 104 public DecimalQuantity_SimpleStorage(long input) { 105 if (input < 0) { 106 setNegative(true); 107 input *= -1; 108 } 109 110 primary = input; 111 primaryScale = 0; 112 primaryPrecision = computePrecision(primary); 113 fallback = null; 114 } 115 116 /** 117 * Creates a DecimalQuantity from the given double value. Internally attempts several strategies 118 * for converting the double to an exact representation, falling back on a BigDecimal if it fails 119 * to do so. 120 * 121 * @param input The double to represent by this DecimalQuantity. 122 */ 123 public DecimalQuantity_SimpleStorage(double input) { 124 if (input < 0) { 125 setNegative(true); 126 input *= -1; 127 } 128 129 // First try reading from IEEE bits. This is trivial only for doubles in [2^52, 2^64). If it 130 // fails, we wasted only a few CPU cycles. 131 long ieeeBits = Double.doubleToLongBits(input); 132 int exponent = (int) ((ieeeBits & 0x7ff0000000000000L) >> 52) - 0x3ff; 133 if (exponent >= 52 && exponent <= 63) { 134 // We can convert this double directly to a long. 135 long mantissa = (ieeeBits & 0x000fffffffffffffL) + 0x0010000000000000L; 136 primary = (mantissa << (exponent - 52)); 137 primaryScale = 0; 138 primaryPrecision = computePrecision(primary); 139 return; 140 } 141 142 // Now try parsing the string produced by Double.toString(). 143 String temp = Double.toString(input); 144 try { 145 if (temp.length() == 3 && temp.equals("0.0")) { 146 // Case 1: Zero. 147 primary = 0L; 148 primaryScale = 0; 149 primaryPrecision = 0; 150 } else if (temp.indexOf('E') != -1) { 151 // Case 2: Exponential notation. 152 assert temp.indexOf('.') == 1; 153 int expPos = temp.indexOf('E'); 154 primary = Long.parseLong(temp.charAt(0) + temp.substring(2, expPos)); 155 primaryScale = Integer.parseInt(temp.substring(expPos + 1)) - (expPos - 1) + 1; 156 primaryPrecision = expPos - 1; 157 } else if (temp.charAt(0) == '0') { 158 // Case 3: Fraction-only number. 159 assert temp.indexOf('.') == 1; 160 primary = Long.parseLong(temp.substring(2)); // ignores leading zeros 161 primaryScale = 2 - temp.length(); 162 primaryPrecision = computePrecision(primary); 163 } else if (temp.charAt(temp.length() - 1) == '0') { 164 // Case 4: Integer-only number. 165 assert temp.indexOf('.') == temp.length() - 2; 166 int rightmostNonzeroDigitIndex = temp.length() - 3; 167 while (temp.charAt(rightmostNonzeroDigitIndex) == '0') { 168 rightmostNonzeroDigitIndex -= 1; 169 } 170 primary = Long.parseLong(temp.substring(0, rightmostNonzeroDigitIndex + 1)); 171 primaryScale = temp.length() - rightmostNonzeroDigitIndex - 3; 172 primaryPrecision = rightmostNonzeroDigitIndex + 1; 173 } else if (temp.equals("Infinity")) { 174 // Case 5: Infinity. 175 primary = 0; 176 setInfinity(true); 177 } else if (temp.equals("NaN")) { 178 // Case 6: NaN. 179 primary = 0; 180 setNaN(true); 181 } else { 182 // Case 7: Number with both a fraction and an integer. 183 int decimalPos = temp.indexOf('.'); 184 primary = Long.parseLong(temp.substring(0, decimalPos) + temp.substring(decimalPos + 1)); 185 primaryScale = decimalPos - temp.length() + 1; 186 primaryPrecision = temp.length() - 1; 187 } 188 } catch (NumberFormatException e) { 189 // The digits of the double can't fit into the long. 190 primary = -1; 191 fallback = new BigDecimal(temp); 192 } 193 } 194 195 static final double LOG_2_OF_TEN = 3.32192809489; 196 197 public DecimalQuantity_SimpleStorage(double input, boolean fast) { 198 if (input < 0) { 199 setNegative(true); 200 input *= -1; 201 } 202 203 // Our strategy is to read all digits that are *guaranteed* to be valid without delving into 204 // the IEEE rounding rules. This strategy might not end up with a perfect representation of 205 // the fractional part of the double. 206 long ieeeBits = Double.doubleToLongBits(input); 207 int exponent = (int) ((ieeeBits & 0x7ff0000000000000L) >> 52) - 0x3ff; 208 long mantissa = (ieeeBits & 0x000fffffffffffffL) + 0x0010000000000000L; 209 if (exponent > 63) { 210 throw new IllegalArgumentException(); // FIXME 211 } else if (exponent >= 52) { 212 primary = (mantissa << (exponent - 52)); 213 primaryScale = 0; 214 primaryPrecision = computePrecision(primary); 215 return; 216 } else if (exponent >= 0) { 217 int shift = 52 - exponent; 218 primary = (mantissa >> shift); // integer part 219 int fractionCount = (int) (shift / LOG_2_OF_TEN); 220 long fraction = (mantissa - (primary << shift)) + 1L; // TODO: Explain the +1L 221 primary *= POWERS_OF_TEN[fractionCount]; 222 for (int i = 0; i < fractionCount; i++) { 223 long times10 = (fraction * 10L); 224 long digit = times10 >> shift; 225 assert digit >= 0 && digit < 10; 226 primary += digit * POWERS_OF_TEN[fractionCount - i - 1]; 227 fraction = times10 & ((1L << shift) - 1); 228 } 229 primaryScale = -fractionCount; 230 primaryPrecision = computePrecision(primary); 231 } else { 232 throw new IllegalArgumentException(); // FIXME 233 } 234 } 235 236 public DecimalQuantity_SimpleStorage(BigDecimal decimal) { 237 setToBigDecimal(decimal); 238 } 239 240 public DecimalQuantity_SimpleStorage(DecimalQuantity_SimpleStorage other) { 241 copyFrom(other); 242 } 243 244 @Override 245 public void setToBigDecimal(BigDecimal decimal) { 246 if (decimal.compareTo(BigDecimal.ZERO) < 0) { 247 setNegative(true); 248 decimal = decimal.negate(); 249 } 250 251 primary = -1; 252 if (decimal.compareTo(BigDecimal.ZERO) == 0) { 253 fallback = BigDecimal.ZERO; 254 } else { 255 fallback = decimal; 256 } 257 } 258 259 @Override 260 public DecimalQuantity_SimpleStorage createCopy() { 261 return new DecimalQuantity_SimpleStorage(this); 262 } 263 264 /** 265 * Make the internal state of this DecimalQuantity equal to another DecimalQuantity. 266 * 267 * @param other The template DecimalQuantity. All properties from this DecimalQuantity will be 268 * copied into this DecimalQuantity. 269 */ 270 @Override 271 public void copyFrom(DecimalQuantity other) { 272 // TODO: Check before casting 273 DecimalQuantity_SimpleStorage _other = (DecimalQuantity_SimpleStorage) other; 274 lOptPos = _other.lOptPos; 275 lReqPos = _other.lReqPos; 276 rReqPos = _other.rReqPos; 277 rOptPos = _other.rOptPos; 278 primary = _other.primary; 279 primaryScale = _other.primaryScale; 280 primaryPrecision = _other.primaryPrecision; 281 fallback = _other.fallback; 282 flags = _other.flags; 283 } 284 285 @Override 286 public long getPositionFingerprint() { 287 long fingerprint = 0; 288 fingerprint ^= lOptPos; 289 fingerprint ^= (lReqPos << 16); 290 fingerprint ^= ((long) rReqPos << 32); 291 fingerprint ^= ((long) rOptPos << 48); 292 return fingerprint; 293 } 294 295 /** 296 * Utility method to compute the number of digits ("precision") in a long. 297 * 298 * @param input The long (which can't contain more than 19 digits). 299 * @return The precision of the long. 300 */ 301 private static int computePrecision(long input) { 302 int precision = 0; 303 while (input > 0) { 304 input /= 10; 305 precision++; 306 } 307 return precision; 308 } 309 310 /** 311 * Changes the internal representation from a long to a BigDecimal. Used only for operations that 312 * don't support longs. 313 */ 314 private void convertToBigDecimal() { 315 if (primary == -1) { 316 return; 317 } 318 319 fallback = new BigDecimal(primary).scaleByPowerOfTen(primaryScale); 320 primary = -1; 321 } 322 323 @Override 324 public void setIntegerLength(int minInt, int maxInt) { 325 // Graceful failures for bogus input 326 minInt = Math.max(0, minInt); 327 maxInt = Math.max(0, maxInt); 328 329 // The minima must be less than or equal to the maxima 330 if (maxInt < minInt) { 331 minInt = maxInt; 332 } 333 334 // Save values into internal state 335 // Negation is safe for minFrac/maxFrac because -Integer.MAX_VALUE > Integer.MIN_VALUE 336 lOptPos = maxInt; 337 lReqPos = minInt; 338 } 339 340 @Override 341 public void setFractionLength(int minFrac, int maxFrac) { 342 // Graceful failures for bogus input 343 minFrac = Math.max(0, minFrac); 344 maxFrac = Math.max(0, maxFrac); 345 346 // The minima must be less than or equal to the maxima 347 if (maxFrac < minFrac) { 348 minFrac = maxFrac; 349 } 350 351 // Save values into internal state 352 // Negation is safe for minFrac/maxFrac because -Integer.MAX_VALUE > Integer.MIN_VALUE 353 rReqPos = -minFrac; 354 rOptPos = -maxFrac; 355 } 356 357 @Override 358 public void roundToIncrement(BigDecimal roundingInterval, MathContext mathContext) { 359 BigDecimal d = 360 (primary == -1) ? fallback : new BigDecimal(primary).scaleByPowerOfTen(primaryScale); 361 if (isNegative()) d = d.negate(); 362 d = d.divide(roundingInterval, 0, mathContext.getRoundingMode()).multiply(roundingInterval); 363 if (isNegative()) d = d.negate(); 364 fallback = d; 365 primary = -1; 366 } 367 368 @Override 369 public void roundToMagnitude(int roundingMagnitude, MathContext mathContext) { 370 if (roundingMagnitude < -1000) { 371 roundToInfinity(); 372 return; 373 } 374 if (primary == -1) { 375 if (isNegative()) fallback = fallback.negate(); 376 fallback = fallback.setScale(-roundingMagnitude, mathContext.getRoundingMode()); 377 if (isNegative()) fallback = fallback.negate(); 378 // Enforce the math context. 379 fallback = fallback.round(mathContext); 380 } else { 381 int relativeScale = primaryScale - roundingMagnitude; 382 if (relativeScale < -18) { 383 // No digits will remain after rounding the number. 384 primary = 0L; 385 primaryScale = roundingMagnitude; 386 primaryPrecision = 0; 387 } else if (relativeScale < 0) { 388 // This is the harder case, when we need to perform the rounding logic. 389 // First check if the rightmost digits are already zero, where we can skip rounding. 390 if ((primary % POWERS_OF_TEN[0 - relativeScale]) == 0) { 391 // No rounding is necessary. 392 } else { 393 // TODO: Make this more efficient. Temporarily, convert to a BigDecimal and back again. 394 BigDecimal temp = new BigDecimal(primary).scaleByPowerOfTen(primaryScale); 395 if (isNegative()) temp = temp.negate(); 396 temp = temp.setScale(-roundingMagnitude, mathContext.getRoundingMode()); 397 if (isNegative()) temp = temp.negate(); 398 temp = temp.scaleByPowerOfTen(-roundingMagnitude); 399 primary = temp.longValueExact(); // should never throw 400 primaryScale = roundingMagnitude; 401 primaryPrecision = computePrecision(primary); 402 } 403 } else { 404 // No rounding is necessary. All digits are to the left of the rounding magnitude. 405 } 406 // Enforce the math context. 407 primary = new BigDecimal(primary).round(mathContext).longValueExact(); 408 primaryPrecision = computePrecision(primary); 409 } 410 } 411 412 @Override 413 public void roundToInfinity() { 414 // noop 415 } 416 417 /** 418 * Multiply the internal number by the specified multiplicand. This method forces the internal 419 * representation into a BigDecimal. If you are multiplying by a power of 10, use {@link 420 * #adjustMagnitude} instead. 421 * 422 * @param multiplicand The number to be passed to {@link BigDecimal#multiply}. 423 */ 424 @Override 425 public void multiplyBy(BigDecimal multiplicand) { 426 convertToBigDecimal(); 427 fallback = fallback.multiply(multiplicand); 428 if (fallback.compareTo(BigDecimal.ZERO) < 0) { 429 setNegative(!isNegative()); 430 fallback = fallback.negate(); 431 } 432 } 433 434 /** 435 * Divide the internal number by the specified quotient. This method forces the internal 436 * representation into a BigDecimal. If you are dividing by a power of 10, use {@link 437 * #adjustMagnitude} instead. 438 * 439 * @param divisor The number to be passed to {@link BigDecimal#divide}. 440 * @param scale The scale of the final rounded number. More negative means more decimal places. 441 * @param mathContext The math context to use if rounding is necessary. 442 */ 443 @SuppressWarnings("unused") 444 private void divideBy(BigDecimal divisor, int scale, MathContext mathContext) { 445 convertToBigDecimal(); 446 // Negate the scale because BigDecimal's scale is defined as the inverse of our scale 447 fallback = fallback.divide(divisor, -scale, mathContext.getRoundingMode()); 448 if (fallback.compareTo(BigDecimal.ZERO) < 0) { 449 setNegative(!isNegative()); 450 fallback = fallback.negate(); 451 } 452 } 453 454 @Override 455 public boolean isZero() { 456 if (primary == -1) { 457 return fallback.compareTo(BigDecimal.ZERO) == 0; 458 } else { 459 return primary == 0; 460 } 461 } 462 463 /** @return The power of ten of the highest digit represented by this DecimalQuantity */ 464 @Override 465 public int getMagnitude() throws ArithmeticException { 466 int scale = (primary == -1) ? scaleBigDecimal(fallback) : primaryScale; 467 int precision = (primary == -1) ? precisionBigDecimal(fallback) : primaryPrecision; 468 if (precision == 0) { 469 throw new ArithmeticException("Magnitude is not well-defined for zero"); 470 } else { 471 return scale + precision - 1; 472 } 473 } 474 475 /** 476 * Changes the magnitude of this DecimalQuantity. If the indices of the represented digits had been 477 * previously specified, those indices are moved relative to the DecimalQuantity. 478 * 479 * <p>This method does NOT perform rounding. 480 * 481 * @param delta The number of powers of ten to shift (positive shifts to the left). 482 */ 483 @Override 484 public void adjustMagnitude(int delta) { 485 if (primary == -1) { 486 fallback = fallback.scaleByPowerOfTen(delta); 487 } else { 488 primaryScale = addOrMaxValue(primaryScale, delta); 489 } 490 } 491 492 private static int addOrMaxValue(int a, int b) { 493 // Check for overflow, and return min/max value if overflow occurs. 494 if (b < 0 && a + b > a) { 495 return Integer.MIN_VALUE; 496 } else if (b > 0 && a + b < a) { 497 return Integer.MAX_VALUE; 498 } 499 return a + b; 500 } 501 502 /** @return If the number represented by this DecimalQuantity is less than zero */ 503 @Override 504 public boolean isNegative() { 505 return (flags & NEGATIVE_FLAG) != 0; 506 } 507 508 private void setNegative(boolean isNegative) { 509 flags = (flags & (~NEGATIVE_FLAG)) | (isNegative ? NEGATIVE_FLAG : 0); 510 } 511 512 @Override 513 public boolean isInfinite() { 514 return (flags & INFINITY_FLAG) != 0; 515 } 516 517 private void setInfinity(boolean isInfinity) { 518 flags = (flags & (~INFINITY_FLAG)) | (isInfinity ? INFINITY_FLAG : 0); 519 } 520 521 @Override 522 public boolean isNaN() { 523 return (flags & NAN_FLAG) != 0; 524 } 525 526 private void setNaN(boolean isNaN) { 527 flags = (flags & (~NAN_FLAG)) | (isNaN ? NAN_FLAG : 0); 528 } 529 530 /** 531 * Returns a representation of this DecimalQuantity as a double, with possible loss of information. 532 */ 533 @Override 534 public double toDouble() { 535 double result; 536 if (primary == -1) { 537 result = fallback.doubleValue(); 538 } else { 539 // TODO: Make this more efficient 540 result = primary; 541 for (int i = 0; i < primaryScale; i++) { 542 result *= 10.; 543 } 544 for (int i = 0; i > primaryScale; i--) { 545 result /= 10.; 546 } 547 } 548 return isNegative() ? -result : result; 549 } 550 551 @Override 552 public BigDecimal toBigDecimal() { 553 BigDecimal result; 554 if (primary != -1) { 555 result = new BigDecimal(primary).scaleByPowerOfTen(primaryScale); 556 } else { 557 result = fallback; 558 } 559 return isNegative() ? result.negate() : result; 560 } 561 562 @Override 563 public StandardPlural getStandardPlural(PluralRules rules) { 564 if (rules == null) { 565 // Fail gracefully if the user didn't provide a PluralRules 566 return StandardPlural.OTHER; 567 } else { 568 // TODO: Avoid converting to a double for the sake of PluralRules 569 String ruleString = rules.select(toDouble()); 570 return StandardPlural.orOtherFromString(ruleString); 571 } 572 } 573 574 @Override 575 public double getPluralOperand(Operand operand) { 576 // TODO: This is a temporary hack. 577 return new PluralRules.FixedDecimal(toDouble()).getPluralOperand(operand); 578 } 579 580 public boolean hasNextFraction() { 581 if (rReqPos < 0) { 582 // We are in the required zone. 583 return true; 584 } else if (rOptPos >= 0) { 585 // We are in the forbidden zone. 586 return false; 587 } else { 588 // We are in the optional zone. 589 if (primary == -1) { 590 return fallback.remainder(BigDecimal.ONE).compareTo(BigDecimal.ZERO) > 0; 591 } else { 592 if (primaryScale <= -19) { 593 // The number is a fraction so small that it consists of only fraction digits. 594 return primary > 0; 595 } else if (primaryScale < 0) { 596 // Check if we have a fraction part. 597 long factor = POWERS_OF_TEN[0 - primaryScale]; 598 return ((primary % factor) != 0); 599 } else { 600 // The lowest digit in the long has magnitude greater than -1. 601 return false; 602 } 603 } 604 } 605 } 606 607 public byte nextFraction() { 608 byte returnValue; 609 if (primary == -1) { 610 BigDecimal temp = fallback.multiply(BigDecimal.TEN); 611 returnValue = temp.setScale(0, RoundingMode.FLOOR).remainder(BigDecimal.TEN).byteValue(); 612 fallback = fallback.setScale(0, RoundingMode.FLOOR).add(temp.remainder(BigDecimal.ONE)); 613 } else { 614 if (primaryScale <= -20) { 615 // The number is a fraction so small that it has no first fraction digit. 616 primaryScale += 1; 617 returnValue = 0; 618 } else if (primaryScale < 0) { 619 // Extract the fraction digit out of the middle of the long. 620 long factor = POWERS_OF_TEN[0 - primaryScale - 1]; 621 long temp1 = primary / factor; 622 long temp2 = primary % factor; 623 returnValue = (byte) (temp1 % 10); // not necessarily nonzero 624 primary = ((temp1 / 10) * factor) + temp2; 625 primaryScale += 1; 626 if (temp1 != 0) { 627 primaryPrecision -= 1; 628 } 629 } else { 630 // The lowest digit in the long has magnitude greater than -1. 631 returnValue = 0; 632 } 633 } 634 635 // Update digit brackets 636 if (lOptPos < 0) { 637 lOptPos += 1; 638 } 639 if (lReqPos < 0) { 640 lReqPos += 1; 641 } 642 if (rReqPos < 0) { 643 rReqPos += 1; 644 } 645 if (rOptPos < 0) { 646 rOptPos += 1; 647 } 648 649 assert returnValue >= 0; 650 return returnValue; 651 } 652 653 public boolean hasNextInteger() { 654 if (lReqPos > 0) { 655 // We are in the required zone. 656 return true; 657 } else if (lOptPos <= 0) { 658 // We are in the forbidden zone. 659 return false; 660 } else { 661 // We are in the optional zone. 662 if (primary == -1) { 663 return fallback.setScale(0, RoundingMode.FLOOR).compareTo(BigDecimal.ZERO) > 0; 664 } else { 665 if (primaryScale < -18) { 666 // The number is a fraction so small that it has no integer part. 667 return false; 668 } else if (primaryScale < 0) { 669 // Check if we have an integer part. 670 long factor = POWERS_OF_TEN[0 - primaryScale]; 671 return ((primary % factor) != primary); // equivalent: ((primary / 10) != 0) 672 } else { 673 // The lowest digit in the long has magnitude of at least 0. 674 return primary != 0; 675 } 676 } 677 } 678 } 679 680 private int integerCount() { 681 int digitsRemaining; 682 if (primary == -1) { 683 digitsRemaining = precisionBigDecimal(fallback) + scaleBigDecimal(fallback); 684 } else { 685 digitsRemaining = primaryPrecision + primaryScale; 686 } 687 return Math.min(Math.max(digitsRemaining, lReqPos), lOptPos); 688 } 689 690 private int fractionCount() { 691 // TODO: This is temporary. 692 DecimalQuantity_SimpleStorage copy = new DecimalQuantity_SimpleStorage(this); 693 int fractionCount = 0; 694 while (copy.hasNextFraction()) { 695 copy.nextFraction(); 696 fractionCount++; 697 } 698 return fractionCount; 699 } 700 701 @Override 702 public int getUpperDisplayMagnitude() { 703 return integerCount() - 1; 704 } 705 706 @Override 707 public int getLowerDisplayMagnitude() { 708 return -fractionCount(); 709 } 710 711 // @Override 712 // public byte getIntegerDigit(int index) { 713 // return getDigitPos(index); 714 // } 715 // 716 // @Override 717 // public byte getFractionDigit(int index) { 718 // return getDigitPos(-index - 1); 719 // } 720 721 @Override 722 public byte getDigit(int magnitude) { 723 // TODO: This is temporary. 724 DecimalQuantity_SimpleStorage copy = new DecimalQuantity_SimpleStorage(this); 725 if (magnitude < 0) { 726 for (int p = -1; p > magnitude; p--) { 727 copy.nextFraction(); 728 } 729 return copy.nextFraction(); 730 } else { 731 for (int p = 0; p < magnitude; p++) { 732 copy.nextInteger(); 733 } 734 return copy.nextInteger(); 735 } 736 } 737 738 public byte nextInteger() { 739 byte returnValue; 740 if (primary == -1) { 741 returnValue = fallback.setScale(0, RoundingMode.FLOOR).remainder(BigDecimal.TEN).byteValue(); 742 BigDecimal temp = fallback.divide(BigDecimal.TEN).setScale(0, RoundingMode.FLOOR); 743 fallback = fallback.remainder(BigDecimal.ONE).add(temp); 744 } else { 745 if (primaryScale < -18) { 746 // The number is a fraction so small that it has no integer part. 747 returnValue = 0; 748 } else if (primaryScale < 0) { 749 // Extract the integer digit out of the middle of the long. In many ways, this is the heart 750 // of the digit iterator algorithm. 751 long factor = POWERS_OF_TEN[0 - primaryScale]; 752 if ((primary % factor) != primary) { // equivalent: ((primary / 10) != 0) 753 returnValue = (byte) ((primary / factor) % 10); 754 long temp = (primary / 10); 755 primary = temp - (temp % factor) + (primary % factor); 756 primaryPrecision -= 1; 757 } else { 758 returnValue = 0; 759 } 760 } else if (primaryScale == 0) { 761 // Fast-path for primaryScale == 0 (otherwise equivalent to previous step). 762 if (primary != 0) { 763 returnValue = (byte) (primary % 10); 764 primary /= 10; 765 primaryPrecision -= 1; 766 } else { 767 returnValue = 0; 768 } 769 } else { 770 // The lowest digit in the long has magnitude greater than 0. 771 primaryScale -= 1; 772 returnValue = 0; 773 } 774 } 775 776 // Update digit brackets 777 if (lOptPos > 0) { 778 lOptPos -= 1; 779 } 780 if (lReqPos > 0) { 781 lReqPos -= 1; 782 } 783 if (rReqPos > 0) { 784 rReqPos -= 1; 785 } 786 if (rOptPos > 0) { 787 rOptPos -= 1; 788 } 789 790 assert returnValue >= 0; 791 return returnValue; 792 } 793 794 /** 795 * Helper method to compute the precision of a BigDecimal by our definition of precision, which is 796 * that the number zero gets precision zero. 797 * 798 * @param decimal The BigDecimal whose precision to compute. 799 * @return The precision by our definition. 800 */ 801 private static int precisionBigDecimal(BigDecimal decimal) { 802 if (decimal.compareTo(BigDecimal.ZERO) == 0) { 803 return 0; 804 } else { 805 return decimal.precision(); 806 } 807 } 808 809 /** 810 * Helper method to compute the scale of a BigDecimal by our definition of scale, which is that 811 * deeper fractions result in negative scales as opposed to positive scales. 812 * 813 * @param decimal The BigDecimal whose scale to compute. 814 * @return The scale by our definition. 815 */ 816 private static int scaleBigDecimal(BigDecimal decimal) { 817 return -decimal.scale(); 818 } 819 820 @Override 821 public String toString() { 822 StringBuilder sb = new StringBuilder(); 823 sb.append("<DecimalQuantity1 "); 824 if (primary == -1) { 825 sb.append(lOptPos > 1000 ? "max" : lOptPos); 826 sb.append(":"); 827 sb.append(lReqPos); 828 sb.append(":"); 829 sb.append(rReqPos); 830 sb.append(":"); 831 sb.append(rOptPos < -1000 ? "min" : rOptPos); 832 sb.append(" "); 833 sb.append(fallback.toString()); 834 } else { 835 String digits = Long.toString(primary); 836 int iDec = digits.length() + primaryScale; 837 int iLP = iDec - toRange(lOptPos, -1000, 1000); 838 int iLB = iDec - toRange(lReqPos, -1000, 1000); 839 int iRB = iDec - toRange(rReqPos, -1000, 1000); 840 int iRP = iDec - toRange(rOptPos, -1000, 1000); 841 iDec = Math.max(Math.min(iDec, digits.length() + 1), -1); 842 iLP = Math.max(Math.min(iLP, digits.length() + 1), -1); 843 iLB = Math.max(Math.min(iLB, digits.length() + 1), -1); 844 iRB = Math.max(Math.min(iRB, digits.length() + 1), -1); 845 iRP = Math.max(Math.min(iRP, digits.length() + 1), -1); 846 847 for (int i = -1; i <= digits.length() + 1; i++) { 848 if (i == iLP) sb.append('('); 849 if (i == iLB) sb.append('['); 850 if (i == iDec) sb.append('.'); 851 if (i == iRB) sb.append(']'); 852 if (i == iRP) sb.append(')'); 853 if (i >= 0 && i < digits.length()) sb.append(digits.charAt(i)); 854 else sb.append('\u00A0'); 855 } 856 } 857 sb.append(">"); 858 return sb.toString(); 859 } 860 861 @Override 862 public String toPlainString() { 863 // NOTE: This logic is duplicated between here and DecimalQuantity_AbstractBCD. 864 StringBuilder sb = new StringBuilder(); 865 if (isNegative()) { 866 sb.append('-'); 867 } 868 for (int m = getUpperDisplayMagnitude(); m >= getLowerDisplayMagnitude(); m--) { 869 sb.append(getDigit(m)); 870 if (m == 0) sb.append('.'); 871 } 872 return sb.toString(); 873 } 874 875 private static int toRange(int i, int lo, int hi) { 876 if (i < lo) { 877 return lo; 878 } else if (i > hi) { 879 return hi; 880 } else { 881 return i; 882 } 883 } 884 885 @Override 886 public void populateUFieldPosition(FieldPosition fp) { 887 if (fp instanceof UFieldPosition) { 888 ((UFieldPosition) fp) 889 .setFractionDigits((int) getPluralOperand(Operand.v), (long) getPluralOperand(Operand.f)); 890 } 891 } 892 } 893