• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 ohos.global.icu.impl.number;
5 
6 import java.math.BigDecimal;
7 import java.math.MathContext;
8 import java.math.RoundingMode;
9 
10 import ohos.global.icu.impl.StandardPlural;
11 import ohos.global.icu.number.Precision;
12 import ohos.global.icu.number.Scale;
13 import ohos.global.icu.text.PluralRules;
14 
15 /** @author sffc
16  * @hide exposed on OHOS*/
17 public class RoundingUtils {
18 
19     public static final int SECTION_LOWER = 1;
20     public static final int SECTION_MIDPOINT = 2;
21     public static final int SECTION_UPPER = 3;
22 
23     /**
24      * The default rounding mode.
25      */
26     public static final RoundingMode DEFAULT_ROUNDING_MODE = RoundingMode.HALF_EVEN;
27 
28     /**
29      * The maximum number of fraction places, integer numerals, or significant digits. TODO: This does
30      * not feel like the best home for this value.
31      */
32     public static final int MAX_INT_FRAC_SIG = 999;
33 
34     /**
35      * Converts a rounding mode and metadata about the quantity being rounded to a boolean determining
36      * whether the value should be rounded toward infinity or toward zero.
37      *
38      * <p>
39      * The parameters are of type int because benchmarks on an x86-64 processor against OpenJDK showed
40      * that ints were demonstrably faster than enums in switch statements.
41      *
42      * @param isEven
43      *            Whether the digit immediately before the rounding magnitude is even.
44      * @param isNegative
45      *            Whether the quantity is negative.
46      * @param section
47      *            Whether the part of the quantity to the right of the rounding magnitude is exactly
48      *            halfway between two digits, whether it is in the lower part (closer to zero), or
49      *            whether it is in the upper part (closer to infinity). See {@link #SECTION_LOWER},
50      *            {@link #SECTION_MIDPOINT}, and {@link #SECTION_UPPER}.
51      * @param roundingMode
52      *            The integer version of the {@link RoundingMode}, which you can get via
53      *            {@link RoundingMode#ordinal}.
54      * @param reference
55      *            A reference object to be used when throwing an ArithmeticException.
56      * @return true if the number should be rounded toward zero; false if it should be rounded toward
57      *         infinity.
58      */
getRoundingDirection( boolean isEven, boolean isNegative, int section, int roundingMode, Object reference)59     public static boolean getRoundingDirection(
60             boolean isEven,
61             boolean isNegative,
62             int section,
63             int roundingMode,
64             Object reference) {
65         switch (roundingMode) {
66         case BigDecimal.ROUND_UP:
67             // round away from zero
68             return false;
69 
70         case BigDecimal.ROUND_DOWN:
71             // round toward zero
72             return true;
73 
74         case BigDecimal.ROUND_CEILING:
75             // round toward positive infinity
76             return isNegative;
77 
78         case BigDecimal.ROUND_FLOOR:
79             // round toward negative infinity
80             return !isNegative;
81 
82         case BigDecimal.ROUND_HALF_UP:
83             switch (section) {
84             case SECTION_MIDPOINT:
85                 return false;
86             case SECTION_LOWER:
87                 return true;
88             case SECTION_UPPER:
89                 return false;
90             }
91             break;
92 
93         case BigDecimal.ROUND_HALF_DOWN:
94             switch (section) {
95             case SECTION_MIDPOINT:
96                 return true;
97             case SECTION_LOWER:
98                 return true;
99             case SECTION_UPPER:
100                 return false;
101             }
102             break;
103 
104         case BigDecimal.ROUND_HALF_EVEN:
105             switch (section) {
106             case SECTION_MIDPOINT:
107                 return isEven;
108             case SECTION_LOWER:
109                 return true;
110             case SECTION_UPPER:
111                 return false;
112             }
113             break;
114         }
115 
116         // Rounding mode UNNECESSARY
117         throw new ArithmeticException("Rounding is required on " + reference.toString());
118     }
119 
120     /**
121      * Gets whether the given rounding mode's rounding boundary is at the midpoint. The rounding boundary
122      * is the point at which a number switches from being rounded down to being rounded up. For example,
123      * with rounding mode HALF_EVEN, HALF_UP, or HALF_DOWN, the rounding boundary is at the midpoint, and
124      * this function would return true. However, for UP, DOWN, CEILING, and FLOOR, the rounding boundary
125      * is at the "edge", and this function would return false.
126      *
127      * @param roundingMode
128      *            The integer version of the {@link RoundingMode}.
129      * @return true if rounding mode is HALF_EVEN, HALF_UP, or HALF_DOWN; false otherwise.
130      */
roundsAtMidpoint(int roundingMode)131     public static boolean roundsAtMidpoint(int roundingMode) {
132         switch (roundingMode) {
133         case BigDecimal.ROUND_UP:
134         case BigDecimal.ROUND_DOWN:
135         case BigDecimal.ROUND_CEILING:
136         case BigDecimal.ROUND_FLOOR:
137             return false;
138 
139         default:
140             return true;
141         }
142     }
143 
144     private static final MathContext[] MATH_CONTEXT_BY_ROUNDING_MODE_UNLIMITED = new MathContext[RoundingMode
145             .values().length];
146 
147     private static final MathContext[] MATH_CONTEXT_BY_ROUNDING_MODE_34_DIGITS = new MathContext[RoundingMode
148             .values().length];
149 
150     static {
151         for (int i = 0; i < MATH_CONTEXT_BY_ROUNDING_MODE_34_DIGITS.length; i++) {
152             MATH_CONTEXT_BY_ROUNDING_MODE_UNLIMITED[i] = new MathContext(0, RoundingMode.valueOf(i));
153             MATH_CONTEXT_BY_ROUNDING_MODE_34_DIGITS[i] = new MathContext(34);
154         }
155     }
156 
157     /** The default MathContext, unlimited-precision version. */
158     public static final MathContext DEFAULT_MATH_CONTEXT_UNLIMITED
159             = MATH_CONTEXT_BY_ROUNDING_MODE_UNLIMITED[DEFAULT_ROUNDING_MODE.ordinal()];
160 
161     /** The default MathContext, 34-digit version. */
162     public static final MathContext DEFAULT_MATH_CONTEXT_34_DIGITS
163             = MATH_CONTEXT_BY_ROUNDING_MODE_34_DIGITS[DEFAULT_ROUNDING_MODE.ordinal()];
164 
165     /**
166      * Gets the user-specified math context out of the property bag. If there is none, falls back to a
167      * math context with unlimited precision and the user-specified rounding mode, which defaults to
168      * HALF_EVEN (the IEEE 754R default).
169      *
170      * @param properties
171      *            The property bag.
172      * @return A {@link MathContext}. Never null.
173      */
getMathContextOrUnlimited(DecimalFormatProperties properties)174     public static MathContext getMathContextOrUnlimited(DecimalFormatProperties properties) {
175         MathContext mathContext = properties.getMathContext();
176         if (mathContext == null) {
177             RoundingMode roundingMode = properties.getRoundingMode();
178             if (roundingMode == null)
179                 roundingMode = RoundingMode.HALF_EVEN;
180             mathContext = MATH_CONTEXT_BY_ROUNDING_MODE_UNLIMITED[roundingMode.ordinal()];
181         }
182         return mathContext;
183     }
184 
185     /**
186      * Gets the user-specified math context out of the property bag. If there is none, falls back to a
187      * math context with 34 digits of precision (the 128-bit IEEE 754R default) and the user-specified
188      * rounding mode, which defaults to HALF_EVEN (the IEEE 754R default).
189      *
190      * @param properties
191      *            The property bag.
192      * @return A {@link MathContext}. Never null.
193      */
getMathContextOr34Digits(DecimalFormatProperties properties)194     public static MathContext getMathContextOr34Digits(DecimalFormatProperties properties) {
195         MathContext mathContext = properties.getMathContext();
196         if (mathContext == null) {
197             RoundingMode roundingMode = properties.getRoundingMode();
198             if (roundingMode == null)
199                 roundingMode = RoundingMode.HALF_EVEN;
200             mathContext = MATH_CONTEXT_BY_ROUNDING_MODE_34_DIGITS[roundingMode.ordinal()];
201         }
202         return mathContext;
203     }
204 
205     /**
206      * Gets a MathContext with unlimited precision and the specified RoundingMode. Equivalent to "new
207      * MathContext(0, roundingMode)", but pulls from a singleton to prevent object thrashing.
208      *
209      * @param roundingMode
210      *            The {@link RoundingMode} to use.
211      * @return The corresponding {@link MathContext}.
212      */
mathContextUnlimited(RoundingMode roundingMode)213     public static MathContext mathContextUnlimited(RoundingMode roundingMode) {
214         return MATH_CONTEXT_BY_ROUNDING_MODE_UNLIMITED[roundingMode.ordinal()];
215     }
216 
scaleFromProperties(DecimalFormatProperties properties)217     public static Scale scaleFromProperties(DecimalFormatProperties properties) {
218         MathContext mc = getMathContextOr34Digits(properties);
219         if (properties.getMagnitudeMultiplier() != 0) {
220             return Scale.powerOfTen(properties.getMagnitudeMultiplier()).withMathContext(mc);
221         } else if (properties.getMultiplier() != null) {
222             return Scale.byBigDecimal(properties.getMultiplier()).withMathContext(mc);
223         } else {
224             return null;
225         }
226     }
227 
228     /**
229      * Computes the plural form after copying the number and applying rounding rules.
230      */
getPluralSafe( Precision rounder, PluralRules rules, DecimalQuantity dq)231     public static StandardPlural getPluralSafe(
232             Precision rounder, PluralRules rules, DecimalQuantity dq) {
233         if (rounder == null) {
234             return dq.getStandardPlural(rules);
235         }
236         // TODO(ICU-20500): Avoid the copy?
237         DecimalQuantity copy = dq.createCopy();
238         rounder.apply(copy);
239         return copy.getStandardPlural(rules);
240     }
241 }
242