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 4package android.icu.number; 5 6import java.math.BigDecimal; 7import java.math.MathContext; 8import java.math.RoundingMode; 9 10import android.icu.impl.number.DecimalQuantity; 11import android.icu.impl.number.MultiplierProducer; 12import android.icu.impl.number.RoundingUtils; 13import android.icu.util.Currency; 14import android.icu.util.Currency.CurrencyUsage; 15 16/** 17 * A class that defines the rounding strategy to be used when formatting numbers in NumberFormatter. 18 * 19 * <p> 20 * To create a Rounder, use one of the factory methods. 21 * 22 * @see NumberFormatter 23 * @hide Only a subset of ICU is exposed in Android 24 * @hide draft / provisional / internal are hidden on Android 25 */ 26public abstract class Rounder implements Cloneable { 27 28 /* package-private final */ MathContext mathContext; 29 30 /* package-private */ Rounder() { 31 mathContext = RoundingUtils.mathContextUnlimited(RoundingUtils.DEFAULT_ROUNDING_MODE); 32 } 33 34 /** 35 * Show all available digits to full precision. 36 * 37 * <p> 38 * <strong>NOTE:</strong> When formatting a <em>double</em>, this method, along with {@link #minFraction} and 39 * {@link #minDigits}, will trigger complex algorithm similar to <em>Dragon4</em> to determine the low-order digits 40 * and the number of digits to display based on the value of the double. If the number of fraction places or 41 * significant digits can be bounded, consider using {@link #maxFraction} or {@link #maxDigits} instead to maximize 42 * performance. For more information, read the following blog post. 43 * 44 * <p> 45 * http://www.serpentine.com/blog/2011/06/29/here-be-dragons-advances-in-problems-you-didnt-even-know-you-had/ 46 * 47 * @return A Rounder for chaining or passing to the NumberFormatter rounding() setter. 48 * @see NumberFormatter 49 * @hide draft / provisional / internal are hidden on Android 50 */ 51 public static Rounder unlimited() { 52 return constructInfinite(); 53 } 54 55 /** 56 * Show numbers rounded if necessary to the nearest integer. 57 * 58 * @return A FractionRounder for chaining or passing to the NumberFormatter rounding() setter. 59 * @see NumberFormatter 60 * @hide draft / provisional / internal are hidden on Android 61 */ 62 public static FractionRounder integer() { 63 return constructFraction(0, 0); 64 } 65 66 /** 67 * Show numbers rounded if necessary to a certain number of fraction places (numerals after the decimal separator). 68 * Additionally, pad with zeros to ensure that this number of places are always shown. 69 * 70 * <p> 71 * Example output with minMaxFractionPlaces = 3: 72 * 73 * <p> 74 * 87,650.000<br> 75 * 8,765.000<br> 76 * 876.500<br> 77 * 87.650<br> 78 * 8.765<br> 79 * 0.876<br> 80 * 0.088<br> 81 * 0.009<br> 82 * 0.000 (zero) 83 * 84 * <p> 85 * This method is equivalent to {@link #minMaxFraction} with both arguments equal. 86 * 87 * @param minMaxFractionPlaces 88 * The minimum and maximum number of numerals to display after the decimal separator (rounding if too 89 * long or padding with zeros if too short). 90 * @return A FractionRounder for chaining or passing to the NumberFormatter rounding() setter. 91 * @see NumberFormatter 92 * @hide draft / provisional / internal are hidden on Android 93 */ 94 public static FractionRounder fixedFraction(int minMaxFractionPlaces) { 95 if (minMaxFractionPlaces >= 0 && minMaxFractionPlaces <= RoundingUtils.MAX_INT_FRAC_SIG) { 96 return constructFraction(minMaxFractionPlaces, minMaxFractionPlaces); 97 } else { 98 throw new IllegalArgumentException( 99 "Fraction length must be between 0 and " + RoundingUtils.MAX_INT_FRAC_SIG); 100 } 101 } 102 103 /** 104 * Always show at least a certain number of fraction places after the decimal separator, padding with zeros if 105 * necessary. Do not perform rounding (display numbers to their full precision). 106 * 107 * <p> 108 * <strong>NOTE:</strong> If you are formatting <em>doubles</em>, see the performance note in {@link #unlimited}. 109 * 110 * @param minFractionPlaces 111 * The minimum number of numerals to display after the decimal separator (padding with zeros if 112 * necessary). 113 * @return A FractionRounder for chaining or passing to the NumberFormatter rounding() setter. 114 * @see NumberFormatter 115 * @hide draft / provisional / internal are hidden on Android 116 */ 117 public static FractionRounder minFraction(int minFractionPlaces) { 118 if (minFractionPlaces >= 0 && minFractionPlaces < RoundingUtils.MAX_INT_FRAC_SIG) { 119 return constructFraction(minFractionPlaces, -1); 120 } else { 121 throw new IllegalArgumentException( 122 "Fraction length must be between 0 and " + RoundingUtils.MAX_INT_FRAC_SIG); 123 } 124 } 125 126 /** 127 * Show numbers rounded if necessary to a certain number of fraction places (numerals after the decimal separator). 128 * Unlike the other fraction rounding strategies, this strategy does <em>not</em> pad zeros to the end of the 129 * number. 130 * 131 * @param maxFractionPlaces 132 * The maximum number of numerals to display after the decimal mark (rounding if necessary). 133 * @return A FractionRounder for chaining or passing to the NumberFormatter rounding() setter. 134 * @see NumberFormatter 135 * @hide draft / provisional / internal are hidden on Android 136 */ 137 public static FractionRounder maxFraction(int maxFractionPlaces) { 138 if (maxFractionPlaces >= 0 && maxFractionPlaces < RoundingUtils.MAX_INT_FRAC_SIG) { 139 return constructFraction(0, maxFractionPlaces); 140 } else { 141 throw new IllegalArgumentException( 142 "Fraction length must be between 0 and " + RoundingUtils.MAX_INT_FRAC_SIG); 143 } 144 } 145 146 /** 147 * Show numbers rounded if necessary to a certain number of fraction places (numerals after the decimal separator); 148 * in addition, always show at least a certain number of places after the decimal separator, padding with zeros if 149 * necessary. 150 * 151 * @param minFractionPlaces 152 * The minimum number of numerals to display after the decimal separator (padding with zeros if 153 * necessary). 154 * @param maxFractionPlaces 155 * The maximum number of numerals to display after the decimal separator (rounding if necessary). 156 * @return A FractionRounder for chaining or passing to the NumberFormatter rounding() setter. 157 * @see NumberFormatter 158 * @hide draft / provisional / internal are hidden on Android 159 */ 160 public static FractionRounder minMaxFraction(int minFractionPlaces, int maxFractionPlaces) { 161 if (minFractionPlaces >= 0 && maxFractionPlaces <= RoundingUtils.MAX_INT_FRAC_SIG 162 && minFractionPlaces <= maxFractionPlaces) { 163 return constructFraction(minFractionPlaces, maxFractionPlaces); 164 } else { 165 throw new IllegalArgumentException( 166 "Fraction length must be between 0 and " + RoundingUtils.MAX_INT_FRAC_SIG); 167 } 168 } 169 170 /** 171 * Show numbers rounded if necessary to a certain number of significant digits or significant figures. Additionally, 172 * pad with zeros to ensure that this number of significant digits/figures are always shown. 173 * 174 * <p> 175 * This method is equivalent to {@link #minMaxDigits} with both arguments equal. 176 * 177 * @param minMaxSignificantDigits 178 * The minimum and maximum number of significant digits to display (rounding if too long or padding with 179 * zeros if too short). 180 * @return A Rounder for chaining or passing to the NumberFormatter rounding() setter. 181 * @see NumberFormatter 182 * @hide draft / provisional / internal are hidden on Android 183 */ 184 public static Rounder fixedDigits(int minMaxSignificantDigits) { 185 if (minMaxSignificantDigits > 0 && minMaxSignificantDigits <= RoundingUtils.MAX_INT_FRAC_SIG) { 186 return constructSignificant(minMaxSignificantDigits, minMaxSignificantDigits); 187 } else { 188 throw new IllegalArgumentException( 189 "Significant digits must be between 0 and " + RoundingUtils.MAX_INT_FRAC_SIG); 190 } 191 } 192 193 /** 194 * Always show at least a certain number of significant digits/figures, padding with zeros if necessary. Do not 195 * perform rounding (display numbers to their full precision). 196 * 197 * <p> 198 * <strong>NOTE:</strong> If you are formatting <em>doubles</em>, see the performance note in {@link #unlimited}. 199 * 200 * @param minSignificantDigits 201 * The minimum number of significant digits to display (padding with zeros if too short). 202 * @return A Rounder for chaining or passing to the NumberFormatter rounding() setter. 203 * @see NumberFormatter 204 * @hide draft / provisional / internal are hidden on Android 205 */ 206 public static Rounder minDigits(int minSignificantDigits) { 207 if (minSignificantDigits > 0 && minSignificantDigits <= RoundingUtils.MAX_INT_FRAC_SIG) { 208 return constructSignificant(minSignificantDigits, -1); 209 } else { 210 throw new IllegalArgumentException( 211 "Significant digits must be between 0 and " + RoundingUtils.MAX_INT_FRAC_SIG); 212 } 213 } 214 215 /** 216 * Show numbers rounded if necessary to a certain number of significant digits/figures. 217 * 218 * @param maxSignificantDigits 219 * The maximum number of significant digits to display (rounding if too long). 220 * @return A Rounder for chaining or passing to the NumberFormatter rounding() setter. 221 * @see NumberFormatter 222 * @hide draft / provisional / internal are hidden on Android 223 */ 224 public static Rounder maxDigits(int maxSignificantDigits) { 225 if (maxSignificantDigits > 0 && maxSignificantDigits <= RoundingUtils.MAX_INT_FRAC_SIG) { 226 return constructSignificant(0, maxSignificantDigits); 227 } else { 228 throw new IllegalArgumentException( 229 "Significant digits must be between 0 and " + RoundingUtils.MAX_INT_FRAC_SIG); 230 } 231 } 232 233 /** 234 * Show numbers rounded if necessary to a certain number of significant digits/figures; in addition, always show at 235 * least a certain number of significant digits, padding with zeros if necessary. 236 * 237 * @param minSignificantDigits 238 * The minimum number of significant digits to display (padding with zeros if necessary). 239 * @param maxSignificantDigits 240 * The maximum number of significant digits to display (rounding if necessary). 241 * @return A Rounder for chaining or passing to the NumberFormatter rounding() setter. 242 * @see NumberFormatter 243 * @hide draft / provisional / internal are hidden on Android 244 */ 245 public static Rounder minMaxDigits(int minSignificantDigits, int maxSignificantDigits) { 246 if (minSignificantDigits > 0 && maxSignificantDigits <= RoundingUtils.MAX_INT_FRAC_SIG 247 && minSignificantDigits <= maxSignificantDigits) { 248 return constructSignificant(minSignificantDigits, maxSignificantDigits); 249 } else { 250 throw new IllegalArgumentException( 251 "Significant digits must be between 0 and " + RoundingUtils.MAX_INT_FRAC_SIG); 252 } 253 } 254 255 /** 256 * Show numbers rounded if necessary to the closest multiple of a certain rounding increment. For example, if the 257 * rounding increment is 0.5, then round 1.2 to 1 and round 1.3 to 1.5. 258 * 259 * <p> 260 * In order to ensure that numbers are padded to the appropriate number of fraction places, set the scale on the 261 * rounding increment BigDecimal. For example, to round to the nearest 0.5 and always display 2 numerals after the 262 * decimal separator (to display 1.2 as "1.00" and 1.3 as "1.50"), you can run: 263 * 264 * <pre> 265 * Rounder.increment(new BigDecimal("0.50")) 266 * </pre> 267 * 268 * <p> 269 * For more information on the scale of Java BigDecimal, see {@link java.math.BigDecimal#scale()}. 270 * 271 * @param roundingIncrement 272 * The increment to which to round numbers. 273 * @return A Rounder for chaining or passing to the NumberFormatter rounding() setter. 274 * @see NumberFormatter 275 * @hide draft / provisional / internal are hidden on Android 276 */ 277 public static Rounder increment(BigDecimal roundingIncrement) { 278 if (roundingIncrement != null && roundingIncrement.compareTo(BigDecimal.ZERO) > 0) { 279 return constructIncrement(roundingIncrement); 280 } else { 281 throw new IllegalArgumentException("Rounding increment must be positive and non-null"); 282 } 283 } 284 285 /** 286 * Show numbers rounded and padded according to the rules for the currency unit. The most common rounding settings 287 * for currencies include <code>Rounder.fixedFraction(2)</code>, <code>Rounder.integer()</code>, and 288 * <code>Rounder.increment(0.05)</code> for cash transactions ("nickel rounding"). 289 * 290 * <p> 291 * The exact rounding details will be resolved at runtime based on the currency unit specified in the 292 * NumberFormatter chain. To round according to the rules for one currency while displaying the symbol for another 293 * currency, the withCurrency() method can be called on the return value of this method. 294 * 295 * @param currencyUsage 296 * Either STANDARD (for digital transactions) or CASH (for transactions where the rounding increment may 297 * be limited by the available denominations of cash or coins). 298 * @return A CurrencyRounder for chaining or passing to the NumberFormatter rounding() setter. 299 * @see NumberFormatter 300 * @hide draft / provisional / internal are hidden on Android 301 */ 302 public static CurrencyRounder currency(CurrencyUsage currencyUsage) { 303 if (currencyUsage != null) { 304 return constructCurrency(currencyUsage); 305 } else { 306 throw new IllegalArgumentException("CurrencyUsage must be non-null"); 307 } 308 } 309 310 /** 311 * Sets the {@link java.math.RoundingMode} to use when picking the direction to round (up or down). Common values 312 * include HALF_EVEN, HALF_UP, and FLOOR. The default is HALF_EVEN. 313 * 314 * @param roundingMode 315 * The RoundingMode to use. 316 * @return A Rounder for chaining. 317 * @see NumberFormatter 318 * @hide draft / provisional / internal are hidden on Android 319 */ 320 public Rounder withMode(RoundingMode roundingMode) { 321 return withMode(RoundingUtils.mathContextUnlimited(roundingMode)); 322 } 323 324 /** 325 * Sets a MathContext directly instead of RoundingMode. 326 * 327 * @deprecated This API is ICU internal only. 328 * @hide draft / provisional / internal are hidden on Android 329 */ 330 @Deprecated 331 public Rounder withMode(MathContext mathContext) { 332 if (this.mathContext.equals(mathContext)) { 333 return this; 334 } 335 Rounder other = (Rounder) this.clone(); 336 other.mathContext = mathContext; 337 return other; 338 } 339 340 /** 341 * @deprecated This API is ICU internal only. 342 * @hide draft / provisional / internal are hidden on Android 343 */ 344 @Deprecated 345 @Override 346 public Object clone() { 347 try { 348 return super.clone(); 349 } catch (CloneNotSupportedException e) { 350 // Should not happen since parent is Object 351 throw new AssertionError(e); 352 } 353 } 354 355 /** 356 * @deprecated ICU 60 This API is ICU internal only. 357 * @hide draft / provisional / internal are hidden on Android 358 */ 359 @Deprecated 360 public abstract void apply(DecimalQuantity value); 361 362 ////////////////////////// 363 // PACKAGE-PRIVATE APIS // 364 ////////////////////////// 365 366 static final InfiniteRounderImpl NONE = new InfiniteRounderImpl(); 367 368 static final FractionRounderImpl FIXED_FRAC_0 = new FractionRounderImpl(0, 0); 369 static final FractionRounderImpl FIXED_FRAC_2 = new FractionRounderImpl(2, 2); 370 static final FractionRounderImpl MAX_FRAC_6 = new FractionRounderImpl(0, 6); 371 372 static final SignificantRounderImpl FIXED_SIG_2 = new SignificantRounderImpl(2, 2); 373 static final SignificantRounderImpl FIXED_SIG_3 = new SignificantRounderImpl(3, 3); 374 static final SignificantRounderImpl RANGE_SIG_2_3 = new SignificantRounderImpl(2, 3); 375 376 static final FracSigRounderImpl COMPACT_STRATEGY = new FracSigRounderImpl(0, 0, 2, -1); 377 378 static final IncrementRounderImpl NICKEL = new IncrementRounderImpl(BigDecimal.valueOf(0.05)); 379 380 static final CurrencyRounderImpl MONETARY_STANDARD = new CurrencyRounderImpl(CurrencyUsage.STANDARD); 381 static final CurrencyRounderImpl MONETARY_CASH = new CurrencyRounderImpl(CurrencyUsage.CASH); 382 383 static final PassThroughRounderImpl PASS_THROUGH = new PassThroughRounderImpl(); 384 385 static Rounder constructInfinite() { 386 return NONE; 387 } 388 389 static FractionRounder constructFraction(int minFrac, int maxFrac) { 390 if (minFrac == 0 && maxFrac == 0) { 391 return FIXED_FRAC_0; 392 } else if (minFrac == 2 && maxFrac == 2) { 393 return FIXED_FRAC_2; 394 } else if (minFrac == 0 && maxFrac == 6) { 395 return MAX_FRAC_6; 396 } else { 397 return new FractionRounderImpl(minFrac, maxFrac); 398 } 399 } 400 401 /** Assumes that minSig <= maxSig. */ 402 static Rounder constructSignificant(int minSig, int maxSig) { 403 if (minSig == 2 && maxSig == 2) { 404 return FIXED_SIG_2; 405 } else if (minSig == 3 && maxSig == 3) { 406 return FIXED_SIG_3; 407 } else if (minSig == 2 && maxSig == 3) { 408 return RANGE_SIG_2_3; 409 } else { 410 return new SignificantRounderImpl(minSig, maxSig); 411 } 412 } 413 414 static Rounder constructFractionSignificant(FractionRounder base_, int minSig, int maxSig) { 415 assert base_ instanceof FractionRounderImpl; 416 FractionRounderImpl base = (FractionRounderImpl) base_; 417 if (base.minFrac == 0 && base.maxFrac == 0 && minSig == 2 /* && maxSig == -1 */) { 418 return COMPACT_STRATEGY; 419 } else { 420 return new FracSigRounderImpl(base.minFrac, base.maxFrac, minSig, maxSig); 421 } 422 } 423 424 static Rounder constructIncrement(BigDecimal increment) { 425 // NOTE: .equals() is what we want, not .compareTo() 426 if (increment.equals(NICKEL.increment)) { 427 return NICKEL; 428 } else { 429 return new IncrementRounderImpl(increment); 430 } 431 } 432 433 static CurrencyRounder constructCurrency(CurrencyUsage usage) { 434 if (usage == CurrencyUsage.STANDARD) { 435 return MONETARY_STANDARD; 436 } else if (usage == CurrencyUsage.CASH) { 437 return MONETARY_CASH; 438 } else { 439 throw new AssertionError(); 440 } 441 } 442 443 static Rounder constructFromCurrency(CurrencyRounder base_, Currency currency) { 444 assert base_ instanceof CurrencyRounderImpl; 445 CurrencyRounderImpl base = (CurrencyRounderImpl) base_; 446 double incrementDouble = currency.getRoundingIncrement(base.usage); 447 if (incrementDouble != 0.0) { 448 BigDecimal increment = BigDecimal.valueOf(incrementDouble); 449 return constructIncrement(increment); 450 } else { 451 int minMaxFrac = currency.getDefaultFractionDigits(base.usage); 452 return constructFraction(minMaxFrac, minMaxFrac); 453 } 454 } 455 456 static Rounder constructPassThrough() { 457 return PASS_THROUGH; 458 } 459 460 /** 461 * Returns a valid working Rounder. If the Rounder is a CurrencyRounder, applies the given currency. Otherwise, 462 * simply passes through the argument. 463 * 464 * @param currency 465 * A currency object to use in case the input object needs it. 466 * @return A Rounder object ready for use. 467 */ 468 Rounder withLocaleData(Currency currency) { 469 if (this instanceof CurrencyRounder) { 470 return ((CurrencyRounder) this).withCurrency(currency); 471 } else { 472 return this; 473 } 474 } 475 476 int chooseMultiplierAndApply(DecimalQuantity input, MultiplierProducer producer) { 477 // TODO: Make a better and more efficient implementation. 478 // TODO: Avoid the object creation here. 479 DecimalQuantity copy = input.createCopy(); 480 481 assert !input.isZero(); 482 int magnitude = input.getMagnitude(); 483 int multiplier = producer.getMultiplier(magnitude); 484 input.adjustMagnitude(multiplier); 485 apply(input); 486 487 // If the number turned to zero when rounding, do not re-attempt the rounding. 488 if (!input.isZero() && input.getMagnitude() == magnitude + multiplier + 1) { 489 magnitude += 1; 490 input.copyFrom(copy); 491 multiplier = producer.getMultiplier(magnitude); 492 input.adjustMagnitude(multiplier); 493 assert input.getMagnitude() == magnitude + multiplier - 1; 494 apply(input); 495 assert input.getMagnitude() == magnitude + multiplier; 496 } 497 498 return multiplier; 499 } 500 501 /////////////// 502 // INTERNALS // 503 /////////////// 504 505 static class InfiniteRounderImpl extends Rounder { 506 507 public InfiniteRounderImpl() { 508 } 509 510 @Override 511 public void apply(DecimalQuantity value) { 512 value.roundToInfinity(); 513 value.setFractionLength(0, Integer.MAX_VALUE); 514 } 515 } 516 517 static class FractionRounderImpl extends FractionRounder { 518 final int minFrac; 519 final int maxFrac; 520 521 public FractionRounderImpl(int minFrac, int maxFrac) { 522 this.minFrac = minFrac; 523 this.maxFrac = maxFrac; 524 } 525 526 @Override 527 public void apply(DecimalQuantity value) { 528 value.roundToMagnitude(getRoundingMagnitudeFraction(maxFrac), mathContext); 529 value.setFractionLength(Math.max(0, -getDisplayMagnitudeFraction(minFrac)), Integer.MAX_VALUE); 530 } 531 } 532 533 static class SignificantRounderImpl extends Rounder { 534 final int minSig; 535 final int maxSig; 536 537 public SignificantRounderImpl(int minSig, int maxSig) { 538 this.minSig = minSig; 539 this.maxSig = maxSig; 540 } 541 542 @Override 543 public void apply(DecimalQuantity value) { 544 value.roundToMagnitude(getRoundingMagnitudeSignificant(value, maxSig), mathContext); 545 value.setFractionLength(Math.max(0, -getDisplayMagnitudeSignificant(value, minSig)), Integer.MAX_VALUE); 546 } 547 548 /** Version of {@link #apply} that obeys minInt constraints. Used for scientific notation compatibility mode. */ 549 public void apply(DecimalQuantity quantity, int minInt) { 550 assert quantity.isZero(); 551 quantity.setFractionLength(minSig - minInt, Integer.MAX_VALUE); 552 } 553 } 554 555 static class FracSigRounderImpl extends Rounder { 556 final int minFrac; 557 final int maxFrac; 558 final int minSig; 559 final int maxSig; 560 561 public FracSigRounderImpl(int minFrac, int maxFrac, int minSig, int maxSig) { 562 this.minFrac = minFrac; 563 this.maxFrac = maxFrac; 564 this.minSig = minSig; 565 this.maxSig = maxSig; 566 } 567 568 @Override 569 public void apply(DecimalQuantity value) { 570 int displayMag = getDisplayMagnitudeFraction(minFrac); 571 int roundingMag = getRoundingMagnitudeFraction(maxFrac); 572 if (minSig == -1) { 573 // Max Sig override 574 int candidate = getRoundingMagnitudeSignificant(value, maxSig); 575 roundingMag = Math.max(roundingMag, candidate); 576 } else { 577 // Min Sig override 578 int candidate = getDisplayMagnitudeSignificant(value, minSig); 579 roundingMag = Math.min(roundingMag, candidate); 580 } 581 value.roundToMagnitude(roundingMag, mathContext); 582 value.setFractionLength(Math.max(0, -displayMag), Integer.MAX_VALUE); 583 } 584 } 585 586 static class IncrementRounderImpl extends Rounder { 587 final BigDecimal increment; 588 589 public IncrementRounderImpl(BigDecimal increment) { 590 this.increment = increment; 591 } 592 593 @Override 594 public void apply(DecimalQuantity value) { 595 value.roundToIncrement(increment, mathContext); 596 value.setFractionLength(increment.scale(), increment.scale()); 597 } 598 } 599 600 static class CurrencyRounderImpl extends CurrencyRounder { 601 final CurrencyUsage usage; 602 603 public CurrencyRounderImpl(CurrencyUsage usage) { 604 this.usage = usage; 605 } 606 607 @Override 608 public void apply(DecimalQuantity value) { 609 // Call .withCurrency() before .apply()! 610 throw new AssertionError(); 611 } 612 } 613 614 static class PassThroughRounderImpl extends Rounder { 615 616 public PassThroughRounderImpl() { 617 } 618 619 @Override 620 public void apply(DecimalQuantity value) { 621 // TODO: Assert that value has already been rounded 622 } 623 } 624 625 private static int getRoundingMagnitudeFraction(int maxFrac) { 626 if (maxFrac == -1) { 627 return Integer.MIN_VALUE; 628 } 629 return -maxFrac; 630 } 631 632 private static int getRoundingMagnitudeSignificant(DecimalQuantity value, int maxSig) { 633 if (maxSig == -1) { 634 return Integer.MIN_VALUE; 635 } 636 int magnitude = value.isZero() ? 0 : value.getMagnitude(); 637 return magnitude - maxSig + 1; 638 } 639 640 private static int getDisplayMagnitudeFraction(int minFrac) { 641 if (minFrac == 0) { 642 return Integer.MAX_VALUE; 643 } 644 return -minFrac; 645 } 646 647 private static int getDisplayMagnitudeSignificant(DecimalQuantity value, int minSig) { 648 int magnitude = value.isZero() ? 0 : value.getMagnitude(); 649 return magnitude - minSig + 1; 650 } 651} 652