• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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