Imported Upstream version 58.1
[platform/upstream/icu.git] / source / i18n / precision.h
1 // Copyright (C) 2016 and later: Unicode, Inc. and others.
2 // License & terms of use: http://www.unicode.org/copyright.html
3 /*
4 *******************************************************************************
5 * Copyright (C) 2015, International Business Machines
6 * Corporation and others.  All Rights Reserved.
7 *******************************************************************************
8 * precision.h
9 *
10 * created on: 2015jan06
11 * created by: Travis Keep
12 */
13
14 #ifndef __PRECISION_H__
15 #define __PRECISION_H__
16
17 #include "unicode/uobject.h"
18
19 #if !UCONFIG_NO_FORMATTING
20 #include "unicode/utypes.h"
21
22 #include "digitinterval.h"
23 #include "digitlst.h"
24 #include "significantdigitinterval.h"
25
26 U_NAMESPACE_BEGIN
27
28 class VisibleDigits;
29 class VisibleDigitsWithExponent;
30
31
32 /**
33  * A precision manager for values to be formatted as fixed point.
34  * Handles rounding of number to prepare it for formatting.
35  */
36 class U_I18N_API FixedPrecision : public UMemory {
37 public:
38
39     /**
40      * The smallest format interval allowed. Default is 1 integer digit and no
41      * fraction digits.
42      */
43     DigitInterval fMin;
44
45     /**
46      * The largest format interval allowed. Must contain fMin.
47      *  Default is all digits.
48      */
49     DigitInterval fMax;
50
51     /**
52      * Min and max significant digits allowed. The default is no constraints.
53      */
54     SignificantDigitInterval fSignificant;
55
56     /**
57      * The rounding increment or zero if there is no rounding increment.
58      * Default is zero.
59      */
60     DigitList fRoundingIncrement;
61     
62     /**
63      * If set, causes round() to set status to U_FORMAT_INEXACT_ERROR if
64      * any rounding is done. Default is FALSE.
65      */
66     UBool fExactOnly;
67     
68     /**
69      * If set, causes round() to set status to U_ILLEGAL_ARGUMENT_ERROR if
70      * rounded number has more than maximum integer digits. Default is FALSE.
71      */
72     UBool fFailIfOverMax;
73     
74     /**
75      * Controls the rounding mode that initVisibleDigits uses.
76      * Default is DecimalFormat::kRoundHalfEven
77      */
78     DecimalFormat::ERoundingMode fRoundingMode;
79     
80     FixedPrecision();
81     
82     /**
83      * Returns TRUE if this object equals rhs.
84      */
85     UBool equals(const FixedPrecision &rhs) const {
86         return (fMin.equals(rhs.fMin) &&
87                 fMax.equals(rhs.fMax) &&
88                 fSignificant.equals(rhs.fSignificant) &&
89                 (fRoundingIncrement == rhs.fRoundingIncrement) &&
90                 fExactOnly == rhs.fExactOnly &&
91                 fFailIfOverMax == rhs.fFailIfOverMax &&
92                 fRoundingMode == rhs.fRoundingMode);
93     }
94     
95     /**
96      * Rounds value in place to prepare it for formatting.
97      * @param value The value to be rounded. It is rounded in place.
98      * @param exponent Always pass 0 for fixed decimal formatting. scientific
99      *  precision passes the exponent value.  Essentially, it divides value by
100      *  10^exponent, rounds and then multiplies by 10^exponent.
101      * @param status error returned here.
102      * @return reference to value.
103      */
104     DigitList &round(DigitList &value, int32_t exponent, UErrorCode &status) const;
105     
106     /**
107      * Returns the interval to use to format the rounded value.
108      * @param roundedValue the already rounded value to format.
109      * @param interval modified in place to be the interval to use to format
110      *   the rounded value.
111      * @return a reference to interval.
112      */
113     DigitInterval &getInterval(
114             const DigitList &roundedValue, DigitInterval &interval) const;
115     
116     /**
117      * Returns TRUE if this instance allows for fast formatting of integers.
118      */
119     UBool isFastFormattable() const;
120     
121     /**
122      * Initializes a VisibleDigits.
123      * @param value value for VisibleDigits
124      *    Caller must not assume that the value of this parameter will remain
125      *    unchanged.
126      * @param digits This is the value that is initialized.
127      * @param status any error returned here.
128      * @return digits
129      */
130     VisibleDigits &initVisibleDigits(
131             DigitList &value,
132             VisibleDigits &digits,
133             UErrorCode &status) const;
134     
135     /**
136      * Initializes a VisibleDigits.
137      * @param value value for VisibleDigits
138      * @param digits This is the value that is initialized.
139      * @param status any error returned here.
140      * @return digits
141      */
142     VisibleDigits &initVisibleDigits(
143             double value,
144             VisibleDigits &digits,
145             UErrorCode &status) const;
146     
147     /**
148      * Initializes a VisibleDigits.
149      * @param value value for VisibleDigits
150      * @param digits This is the value that is initialized.
151      * @param status any error returned here.
152      * @return digits
153      */
154     VisibleDigits &initVisibleDigits(
155             int64_t value,
156             VisibleDigits &digits,
157             UErrorCode &status) const;
158     
159     /**
160      * Initializes a VisibleDigitsWithExponent.
161      * @param value value for VisibleDigits
162      *    Caller must not assume that the value of this parameter will remain
163      *    unchanged.
164      * @param digits This is the value that is initialized.
165      * @param status any error returned here.
166      * @return digits
167      */
168     VisibleDigitsWithExponent &initVisibleDigitsWithExponent(
169             DigitList &value,
170             VisibleDigitsWithExponent &digits,
171             UErrorCode &status) const;
172     
173     /**
174      * Initializes a VisibleDigitsWithExponent.
175      * @param value value for VisibleDigits
176      * @param digits This is the value that is initialized.
177      * @param status any error returned here.
178      * @return digits
179      */
180     VisibleDigitsWithExponent &initVisibleDigitsWithExponent(
181             double value,
182             VisibleDigitsWithExponent &digits,
183             UErrorCode &status) const;
184     
185     /**
186      * Initializes a VisibleDigitsWithExponent.
187      * @param value value for VisibleDigits
188      * @param digits This is the value that is initialized.
189      * @param status any error returned here.
190      * @return digits
191      */
192     VisibleDigitsWithExponent &initVisibleDigitsWithExponent(
193             int64_t value,
194             VisibleDigitsWithExponent &digits,
195             UErrorCode &status) const;
196     
197 private:
198     /**
199      * Attempts to initialize 'digits' using simple mod 10 arithmetic.
200      * Returns FALSE if this is not possible such as when rounding
201      * would change the value. Otherwise returns TRUE.
202      *
203      * If the method returns FALSE, caller should create a DigitList
204      * and use it to initialize 'digits'. If this method returns TRUE,
205      * caller should accept the value stored in 'digits'. If this
206      * method returns TRUE along with a non zero error, caller must accept
207      * the error and not try again with a DigitList.
208      *
209      * Before calling this method, caller must verify that this object
210      * has no rounding increment set.
211      *
212      * The value that 'digits' is initialized to is mantissa * 10^exponent.
213      * For example mantissa = 54700 and exponent = -3 means 54.7. The
214      * properties of this object (such as min and max fraction digits),
215      * not the number of trailing zeros in the mantissa, determine whether or
216      * not the result contains any trailing 0's after the decimal point.
217      *
218      * @param mantissa the digits. May be positive or negative. May contain
219      *  trailing zeros.
220      * @param exponent must always be zero or negative. An exponent > 0
221      *  yields undefined results! 
222      * @param digits result stored here.
223      * @param status any error returned here.
224      */
225     UBool
226     initVisibleDigits(
227             int64_t mantissa,
228             int32_t exponent,
229             VisibleDigits &digits,
230             UErrorCode &status) const;
231     UBool isRoundingRequired(
232             int32_t upperExponent, int32_t lowerExponent) const;
233     DigitInterval &getIntervalForZero(DigitInterval &interval) const;
234     DigitInterval &getInterval(
235             int32_t upperExponent, DigitInterval &interval) const;
236     static UBool handleNonNumeric(DigitList &value, VisibleDigits &digits);
237     
238     friend class ScientificPrecision;
239 };
240
241 /**
242  * A precision manager for values to be expressed as scientific notation.
243  */
244 class U_I18N_API ScientificPrecision : public UMemory {
245 public:
246     FixedPrecision fMantissa;
247     int32_t fMinExponentDigits;
248
249     ScientificPrecision();
250
251     /**
252      * rounds value in place to prepare it for formatting.
253      * @param value The value to be rounded. It is rounded in place.
254      * @param status error returned here.
255      * @return reference to value.
256      */
257     DigitList &round(DigitList &value, UErrorCode &status) const;
258
259     /**
260      * Converts value to a mantissa and exponent.
261      *
262      * @param value modified in place to be the mantissa. Depending on
263      *   the precision settings, the resulting mantissa may not fall
264      *   between 1.0 and 10.0.
265      * @return the exponent of value.
266      */
267     int32_t toScientific(DigitList &value) const;
268
269     /**
270      * Returns TRUE if this object equals rhs.
271      */
272     UBool equals(const ScientificPrecision &rhs) const {
273         return fMantissa.equals(rhs.fMantissa) && fMinExponentDigits == rhs.fMinExponentDigits;
274     }
275
276     /**
277      * Initializes a VisibleDigitsWithExponent.
278      * @param value the value
279      *    Caller must not assume that the value of this parameter will remain
280      *    unchanged.
281      * @param digits This is the value that is initialized.
282      * @param status any error returned here.
283      * @return digits
284      */
285     VisibleDigitsWithExponent &initVisibleDigitsWithExponent(
286             DigitList &value,
287             VisibleDigitsWithExponent &digits,
288             UErrorCode &status) const;
289     
290     /**
291      * Initializes a VisibleDigitsWithExponent.
292      * @param value the value
293      * @param digits This is the value that is initialized.
294      * @param status any error returned here.
295      * @return digits
296      */
297     VisibleDigitsWithExponent &initVisibleDigitsWithExponent(
298             double value,
299             VisibleDigitsWithExponent &digits,
300             UErrorCode &status) const;
301     
302     /**
303      * Initializes a VisibleDigitsWithExponent.
304      * @param value the value
305      * @param digits This is the value that is initialized.
306      * @param status any error returned here.
307      * @return digits
308      */
309     VisibleDigitsWithExponent &initVisibleDigitsWithExponent(
310             int64_t value,
311             VisibleDigitsWithExponent &digits,
312             UErrorCode &status) const;
313     
314 private:
315     int32_t getMultiplier() const;
316
317 };
318
319
320
321 U_NAMESPACE_END
322 #endif // #if !UCONFIG_NO_FORMATTING
323 #endif  // __PRECISION_H__