1 /* GENERATED SOURCE. DO NOT MODIFY. */ 2 // © 2018 and later: Unicode, Inc. and others. 3 // License & terms of use: http://www.unicode.org/copyright.html 4 package android.icu.number; 5 6 import java.math.BigDecimal; 7 import java.math.BigInteger; 8 import java.math.MathContext; 9 10 import android.icu.impl.number.DecimalQuantity; 11 import android.icu.impl.number.RoundingUtils; 12 13 /** 14 * A class that defines a quantity by which a number should be multiplied when formatting. 15 * 16 * <p> 17 * To create a Multiplier, use one of the factory methods. 18 * 19 * @see NumberFormatter 20 */ 21 public class Scale { 22 23 private static final Scale DEFAULT = new Scale(0, null); 24 private static final Scale HUNDRED = new Scale(2, null); 25 private static final Scale THOUSAND = new Scale(3, null); 26 27 private static final BigDecimal BIG_DECIMAL_100 = BigDecimal.valueOf(100); 28 private static final BigDecimal BIG_DECIMAL_1000 = BigDecimal.valueOf(1000); 29 30 final int magnitude; 31 final BigDecimal arbitrary; 32 final BigDecimal reciprocal; 33 final MathContext mc; 34 Scale(int magnitude, BigDecimal arbitrary)35 private Scale(int magnitude, BigDecimal arbitrary) { 36 this(magnitude, arbitrary, RoundingUtils.DEFAULT_MATH_CONTEXT_34_DIGITS); 37 } 38 Scale(int magnitude, BigDecimal arbitrary, MathContext mc)39 private Scale(int magnitude, BigDecimal arbitrary, MathContext mc) { 40 if (arbitrary != null) { 41 // Attempt to convert the BigDecimal to a magnitude multiplier. 42 // ICU-20000: JDKs have inconsistent behavior on stripTrailingZeros() for Zero. 43 arbitrary = 44 arbitrary.compareTo(BigDecimal.ZERO) == 0 45 ? BigDecimal.ZERO 46 : arbitrary.stripTrailingZeros(); 47 if (arbitrary.precision() == 1 && arbitrary.unscaledValue().equals(BigInteger.ONE)) { 48 // Success! 49 magnitude -= arbitrary.scale(); 50 arbitrary = null; 51 } 52 } 53 54 this.magnitude = magnitude; 55 this.arbitrary = arbitrary; 56 this.mc = mc; 57 // We need to use a math context in order to prevent non-terminating decimal expansions. 58 // This is only used when dividing by the multiplier. 59 if (arbitrary != null && BigDecimal.ZERO.compareTo(arbitrary) != 0) { 60 this.reciprocal = BigDecimal.ONE.divide(arbitrary, mc); 61 } else { 62 this.reciprocal = null; 63 } 64 } 65 66 /** 67 * Do not change the value of numbers when formatting or parsing. 68 * 69 * @return A Multiplier to prevent any multiplication. 70 * @see NumberFormatter 71 */ none()72 public static Scale none() { 73 return DEFAULT; 74 } 75 76 /** 77 * Multiply numbers by 100 before formatting. Useful for combining with a percent unit: 78 * 79 * <pre> 80 * NumberFormatter.with().unit(NoUnit.PERCENT).multiplier(Multiplier.powerOfTen(2)) 81 * </pre> 82 * 83 * @return A Multiplier for passing to the setter in NumberFormatter. 84 * @see NumberFormatter 85 */ powerOfTen(int power)86 public static Scale powerOfTen(int power) { 87 if (power == 0) { 88 return DEFAULT; 89 } else if (power == 2) { 90 return HUNDRED; 91 } else if (power == 3) { 92 return THOUSAND; 93 } else { 94 return new Scale(power, null); 95 } 96 } 97 98 /** 99 * Multiply numbers by an arbitrary value before formatting. Useful for unit conversions. 100 * <p> 101 * This method takes a BigDecimal; also see the version that takes a double. 102 * 103 * @return A Multiplier for passing to the setter in NumberFormatter. 104 * @see NumberFormatter 105 */ byBigDecimal(BigDecimal multiplicand)106 public static Scale byBigDecimal(BigDecimal multiplicand) { 107 if (multiplicand.compareTo(BigDecimal.ONE) == 0) { 108 return DEFAULT; 109 } else if (multiplicand.compareTo(BIG_DECIMAL_100) == 0) { 110 return HUNDRED; 111 } else if (multiplicand.compareTo(BIG_DECIMAL_1000) == 0) { 112 return THOUSAND; 113 } else { 114 return new Scale(0, multiplicand); 115 } 116 } 117 118 /** 119 * Multiply numbers by an arbitrary value before formatting. Useful for unit conversions. 120 * <p> 121 * This method takes a double; also see the version that takes a BigDecimal. 122 * 123 * @return A Multiplier for passing to the setter in NumberFormatter. 124 * @see NumberFormatter 125 */ byDouble(double multiplicand)126 public static Scale byDouble(double multiplicand) { 127 if (multiplicand == 1) { 128 return DEFAULT; 129 } else if (multiplicand == 100.0) { 130 return HUNDRED; 131 } else if (multiplicand == 1000.0) { 132 return THOUSAND; 133 } else { 134 return new Scale(0, BigDecimal.valueOf(multiplicand)); 135 } 136 } 137 138 /** 139 * Multiply a number by both a power of ten and by an arbitrary double value before formatting. 140 * 141 * @return A Multiplier for passing to the setter in NumberFormatter. 142 * @see NumberFormatter 143 */ byDoubleAndPowerOfTen(double multiplicand, int power)144 public static Scale byDoubleAndPowerOfTen(double multiplicand, int power) { 145 return new Scale(power, BigDecimal.valueOf(multiplicand)); 146 } 147 148 /** 149 * Returns whether the multiplier will change the number. 150 */ isValid()151 boolean isValid() { 152 return magnitude != 0 || arbitrary != null; 153 } 154 155 /** 156 * @deprecated ICU 62 This API is ICU internal only. 157 * @hide draft / provisional / internal are hidden on Android 158 */ 159 @Deprecated withMathContext(MathContext mc)160 public Scale withMathContext(MathContext mc) { 161 // TODO: Make this public? 162 if (this.mc.equals(mc)) { 163 return this; 164 } 165 return new Scale(magnitude, arbitrary, mc); 166 } 167 168 /** 169 * @deprecated ICU 62 This API is ICU internal only. 170 * @hide draft / provisional / internal are hidden on Android 171 */ 172 @Deprecated applyTo(DecimalQuantity quantity)173 public void applyTo(DecimalQuantity quantity) { 174 quantity.adjustMagnitude(magnitude); 175 if (arbitrary != null) { 176 quantity.multiplyBy(arbitrary); 177 } 178 } 179 180 /** 181 * @deprecated ICU 62 This API is ICU internal only. 182 * @hide draft / provisional / internal are hidden on Android 183 */ 184 @Deprecated applyReciprocalTo(DecimalQuantity quantity)185 public void applyReciprocalTo(DecimalQuantity quantity) { 186 quantity.adjustMagnitude(-magnitude); 187 if (reciprocal != null) { 188 quantity.multiplyBy(reciprocal); 189 quantity.roundToMagnitude(quantity.getMagnitude() - mc.getPrecision(), mc); 190 } 191 } 192 193 } 194