1 /*
2 ******************************************************************************
3 *
4 *   Copyright (C) 1997-2015, International Business Machines
5 *   Corporation and others.  All Rights Reserved.
6 *
7 ******************************************************************************
8 *
9 * File DIGITLST.H
10 *
11 * Modification History:
12 *
13 *   Date        Name        Description
14 *   02/25/97    aliu        Converted from java.
15 *   03/21/97    clhuang     Updated per C++ implementation.
16 *   04/15/97    aliu        Changed MAX_COUNT to DBL_DIG.  Changed Digit to char.
17 *   09/09/97    aliu        Adapted for exponential notation support.
18 *   08/02/98    stephen     Added nearest/even rounding
19 *   06/29/99    stephen     Made LONG_DIGITS a macro to satisfy SUN compiler
20 *   07/09/99    stephen     Removed kMaxCount (unused, for HP compiler)
21 ******************************************************************************
22 */
23 
24 #ifndef DIGITLST_H
25 #define DIGITLST_H
26 
27 #include "unicode/uobject.h"
28 
29 #if !UCONFIG_NO_FORMATTING
30 #include "unicode/decimfmt.h"
31 #include <float.h>
32 #include "decContext.h"
33 #include "decNumber.h"
34 #include "cmemory.h"
35 
36 // Decimal digits in a 64-bit int
37 #define INT64_DIGITS 19
38 
39 typedef enum EDigitListValues {
40     MAX_DBL_DIGITS = DBL_DIG,
41     MAX_I64_DIGITS = INT64_DIGITS,
42     MAX_DIGITS = MAX_I64_DIGITS,
43     MAX_EXPONENT = DBL_DIG,
44     DIGIT_PADDING = 3,
45     DEFAULT_DIGITS = 40,   // Initial storage size, will grow as needed.
46 
47      // "+." + fDigits + "e" + fDecimalAt
48     MAX_DEC_DIGITS = MAX_DIGITS + DIGIT_PADDING + MAX_EXPONENT
49 } EDigitListValues;
50 
51 U_NAMESPACE_BEGIN
52 
53 class CharString;
54 class DigitInterval;
55 
56 // Export an explicit template instantiation of the MaybeStackHeaderAndArray that
57 //    is used as a data member of DigitList.
58 //
59 //    MSVC requires this, even though it should not be necessary.
60 //    No direct access to the MaybeStackHeaderAndArray leaks out of the i18n library.
61 //
62 //    Macintosh produces duplicate definition linker errors with the explicit template
63 //    instantiation.
64 //
65 #if !U_PLATFORM_IS_DARWIN_BASED
66 template class U_I18N_API MaybeStackHeaderAndArray<decNumber, char, DEFAULT_DIGITS>;
67 #endif
68 
69 
70 enum EStackMode { kOnStack };
71 
72 enum EFastpathBits { kFastpathOk = 1, kNoDecimal = 2 };
73 
74 /**
75  * Digit List is actually a Decimal Floating Point number.
76  * The original implementation has been replaced by a thin wrapper onto a
77  * decimal number from the decNumber library.
78  *
79  * The original DigitList API has been retained, to minimize the impact of
80  * the change on the rest of the ICU formatting code.
81  *
82  * The change to decNumber enables support for big decimal numbers, and
83  * allows rounding computations to be done directly in decimal, avoiding
84  * extra, and inaccurate, conversions to and from doubles.
85  *
86  * Original DigitList comments:
87  *
88  * Digit List utility class. Private to DecimalFormat.  Handles the transcoding
89  * between numeric values and strings of characters.  Only handles
90  * non-negative numbers.  The division of labor between DigitList and
91  * DecimalFormat is that DigitList handles the radix 10 representation
92  * issues; DecimalFormat handles the locale-specific issues such as
93  * positive/negative, grouping, decimal point, currency, and so on.
94  * <P>
95  * A DigitList is really a representation of a floating point value.
96  * It may be an integer value; we assume that a double has sufficient
97  * precision to represent all digits of a long.
98  * <P>
99  * The DigitList representation consists of a string of characters,
100  * which are the digits radix 10, from '0' to '9'.  It also has a radix
101  * 10 exponent associated with it.  The value represented by a DigitList
102  * object can be computed by mulitplying the fraction f, where 0 <= f < 1,
103  * derived by placing all the digits of the list to the right of the
104  * decimal point, by 10^exponent.
105  *
106  * --------
107  *
108  * DigitList vs. decimalNumber:
109  *
110  *    DigitList stores digits with the most significant first.
111  *    decNumber stores digits with the least significant first.
112  *
113  *    DigitList, decimal point is before the most significant.
114  *    decNumber, decimal point is after the least signficant digit.
115  *
116  *       digitList:    0.ddddd * 10 ^ exp
117  *       decNumber:    ddddd. * 10 ^ exp
118  *
119  *       digitList exponent = decNumber exponent + digit count
120  *
121  *    digitList, digits are platform invariant chars, '0' - '9'
122  *    decNumber, digits are binary, one per byte, 0 - 9.
123  *
124  *       (decNumber library is configurable in how digits are stored, ICU has configured
125  *        it this way for convenience in replacing the old DigitList implementation.)
126  */
127 class U_I18N_API DigitList : public UMemory { // Declare external to make compiler happy
128 public:
129 
130     DigitList();
131     ~DigitList();
132 
133     /* copy constructor
134      * @param DigitList The object to be copied.
135      * @return the newly created object.
136      */
137     DigitList(const DigitList&); // copy constructor
138 
139     /* assignment operator
140      * @param DigitList The object to be copied.
141      * @return the newly created object.
142      */
143     DigitList& operator=(const DigitList&);  // assignment operator
144 
145     /**
146      * Return true if another object is semantically equal to this one.
147      * @param other The DigitList to be compared for equality
148      * @return true if another object is semantically equal to this one.
149      * return false otherwise.
150      */
151     UBool operator==(const DigitList& other) const;
152 
153     int32_t  compare(const DigitList& other);
154 
155 
156     inline UBool operator!=(const DigitList& other) const { return !operator==(other); }
157 
158     /**
159      * Clears out the digits.
160      * Use before appending them.
161      * Typically, you set a series of digits with append, then at the point
162      * you hit the decimal point, you set myDigitList.fDecimalAt = myDigitList.fCount;
163      * then go on appending digits.
164      */
165     void clear(void);
166 
167     /**
168      *  Remove, by rounding, any fractional part of the decimal number,
169      *  leaving an integer value.
170      */
171     void toIntegralValue();
172 
173     /**
174      * Appends digits to the list.
175      *    CAUTION:  this function is not recommended for new code.
176      *              In the original DigitList implementation, decimal numbers were
177      *              parsed by appending them to a digit list as they were encountered.
178      *              With the revamped DigitList based on decNumber, append is very
179      *              inefficient, and the interaction with the exponent value is confusing.
180      *              Best avoided.
181      *              TODO:  remove this function once all use has been replaced.
182      *              TODO:  describe alternative to append()
183      * @param digit The digit to be appended.
184      */
185     void append(char digit);
186 
187     /**
188      * Utility routine to get the value of the digit list
189      * Returns 0.0 if zero length.
190      * @return the value of the digit list.
191      */
192     double getDouble(void) const;
193 
194     /**
195      * Utility routine to get the value of the digit list
196      * Make sure that fitsIntoLong() is called before calling this function.
197      * Returns 0 if zero length.
198      * @return the value of the digit list, return 0 if it is zero length
199      */
200     int32_t getLong(void) /*const*/;
201 
202     /**
203      * Utility routine to get the value of the digit list
204      * Make sure that fitsIntoInt64() is called before calling this function.
205      * Returns 0 if zero length.
206      * @return the value of the digit list, return 0 if it is zero length
207      */
208     int64_t getInt64(void) /*const*/;
209 
210     /**
211      *  Utility routine to get the value of the digit list as a decimal string.
212      */
213     void getDecimal(CharString &str, UErrorCode &status);
214 
215     /**
216      * Return true if the number represented by this object can fit into
217      * a long.
218      * @param ignoreNegativeZero True if negative zero is ignored.
219      * @return true if the number represented by this object can fit into
220      * a long, return false otherwise.
221      */
222     UBool fitsIntoLong(UBool ignoreNegativeZero) /*const*/;
223 
224     /**
225      * Return true if the number represented by this object can fit into
226      * an int64_t.
227      * @param ignoreNegativeZero True if negative zero is ignored.
228      * @return true if the number represented by this object can fit into
229      * a long, return false otherwise.
230      */
231     UBool fitsIntoInt64(UBool ignoreNegativeZero) /*const*/;
232 
233     /**
234      * Utility routine to set the value of the digit list from a double.
235      * @param source The value to be set
236      */
237     void set(double source);
238 
239     /**
240      * Utility routine to set the value of the digit list from a long.
241      * If a non-zero maximumDigits is specified, no more than that number of
242      * significant digits will be produced.
243      * @param source The value to be set
244      */
245     void set(int32_t source);
246 
247     /**
248      * Utility routine to set the value of the digit list from an int64.
249      * If a non-zero maximumDigits is specified, no more than that number of
250      * significant digits will be produced.
251      * @param source The value to be set
252      */
253     void set(int64_t source);
254 
255     /**
256      * Utility routine to set the value of the digit list from an int64.
257      * Does not set the decnumber unless requested later
258      * If a non-zero maximumDigits is specified, no more than that number of
259      * significant digits will be produced.
260      * @param source The value to be set
261      */
262     void setInteger(int64_t source);
263 
264    /**
265      * Utility routine to set the value of the digit list from a decimal number
266      * string.
267      * @param source The value to be set.  The string must be nul-terminated.
268      * @param fastpathBits special flags for fast parsing
269      */
270     void set(const StringPiece &source, UErrorCode &status, uint32_t fastpathBits = 0);
271 
272     /**
273      * Multiply    this = this * arg
274      *    This digitlist will be expanded if necessary to accomodate the result.
275      *  @param arg  the number to multiply by.
276      */
277     void mult(const DigitList &arg, UErrorCode &status);
278 
279     /**
280      *   Divide    this = this / arg
281      */
282     void div(const DigitList &arg, UErrorCode &status);
283 
284     //  The following functions replace direct access to the original DigitList implmentation
285     //  data structures.
286 
287     void setRoundingMode(DecimalFormat::ERoundingMode m);
288 
289     /** Test a number for zero.
290      * @return  TRUE if the number is zero
291      */
292     UBool isZero(void) const;
293 
294     /** Test for a Nan
295      * @return  TRUE if the number is a NaN
296      */
isNaN(void)297     UBool isNaN(void) const {return decNumberIsNaN(fDecNumber);}
298 
isInfinite()299     UBool isInfinite() const {return decNumberIsInfinite(fDecNumber);}
300 
301     /**  Reduce, or normalize.  Removes trailing zeroes, adjusts exponent appropriately. */
302     void     reduce();
303 
304     /**  Remove trailing fraction zeros, adjust exponent accordingly. */
305     void     trim();
306 
307     /** Set to zero */
setToZero()308     void     setToZero() {uprv_decNumberZero(fDecNumber);}
309 
310     /** get the number of digits in the decimal number */
digits()311     int32_t  digits() const {return fDecNumber->digits;}
312 
313     /**
314      * Round the number to the given number of digits.
315      * @param maximumDigits The maximum number of digits to be shown.
316      * Upon return, count will be less than or equal to maximumDigits.
317      * result is guaranteed to be trimmed.
318      */
319     void round(int32_t maximumDigits);
320 
321     void roundFixedPoint(int32_t maximumFractionDigits);
322 
323     /** Ensure capacity for digits.  Grow the storage if it is currently less than
324      *      the requested size.   Capacity is not reduced if it is already greater
325      *      than requested.
326      */
327     void  ensureCapacity(int32_t  requestedSize, UErrorCode &status);
328 
isPositive(void)329     UBool    isPositive(void) const { return decNumberIsNegative(fDecNumber) == 0;}
330     void     setPositive(UBool s);
331 
332     void     setDecimalAt(int32_t d);
333     int32_t  getDecimalAt();
334 
335     void     setCount(int32_t c);
336     int32_t  getCount() const;
337 
338     /**
339      * Set the digit in platform (invariant) format, from '0'..'9'
340      * @param i index of digit
341      * @param v digit value, from '0' to '9' in platform invariant format
342      */
343     void     setDigit(int32_t i, char v);
344 
345     /**
346      * Get the digit in platform (invariant) format, from '0'..'9' inclusive
347      * @param i index of digit
348      * @return invariant format of the digit
349      */
350     char     getDigit(int32_t i);
351 
352 
353     /**
354      * Get the digit's value, as an integer from 0..9 inclusive.
355      * Note that internally this value is a decNumberUnit, but ICU configures it to be a uint8_t.
356      * @param i index of digit
357      * @return value of that digit
358      */
359     uint8_t     getDigitValue(int32_t i);
360 
361     /**
362      * Gets the upper bound exponent for this value. For 987, returns 3
363      * because 10^3 is the smallest power of 10 that is just greater than
364      * 987.
365      */
366     int32_t getUpperExponent() const;
367 
368     /**
369      * Gets the lower bound exponent for this value. For 98.7, returns -1
370      * because the right most digit, is the 10^-1 place.
371      */
getLowerExponent()372     int32_t getLowerExponent() const { return fDecNumber->exponent; }
373 
374     /**
375      * Sets result to the smallest DigitInterval needed to display this
376      * DigitList in fixed point form and returns result.
377      */
378     DigitInterval& getSmallestInterval(DigitInterval &result) const;
379 
380     /**
381      * Like getDigitValue, but the digit is identified by exponent.
382      * For example, getDigitByExponent(7) returns the 10^7 place of this
383      * DigitList. Unlike getDigitValue, there are no upper or lower bounds
384      * for passed parameter. Instead, getDigitByExponent returns 0 if
385      * the exponent falls outside the interval for this DigitList.
386      */
387     uint8_t getDigitByExponent(int32_t exponent) const;
388 
389     /**
390      * Appends the digits in this object to a CharString.
391      * 3 is appended as (char) 3, not '3'
392      */
393     void appendDigitsTo(CharString &str, UErrorCode &status) const;
394 
395     /**
396      * Equivalent to roundFixedPoint(-digitExponent) except unlike
397      * roundFixedPoint, this works for any digitExponent value.
398      * If maxSigDigits is set then this instance is rounded to have no more
399      * than maxSigDigits. The end result is guaranteed to be trimmed.
400      */
401     void roundAtExponent(int32_t digitExponent, int32_t maxSigDigits=INT32_MAX);
402 
403     /**
404      * Quantizes according to some amount and rounds according to the
405      * context of this instance. Quantizing 3.233 with 0.05 gives 3.25.
406      */
407     void quantize(const DigitList &amount, UErrorCode &status);
408 
409     /**
410      * Like toScientific but only returns the exponent
411      * leaving this instance unchanged.
412      */
413     int32_t getScientificExponent(
414             int32_t minIntDigitCount, int32_t exponentMultiplier) const;
415 
416     /**
417      * Converts this instance to scientific notation. This instance
418      * becomes the mantissa and the exponent is returned.
419      * @param minIntDigitCount minimum integer digits in mantissa
420      *   Exponent is set so that the actual number of integer digits
421      *   in mantissa is as close to the minimum as possible.
422      * @param exponentMultiplier The exponent is always a multiple of
423      *  This number. Usually 1, but set to 3 for engineering notation.
424      * @return exponent
425      */
426     int32_t toScientific(
427             int32_t minIntDigitCount, int32_t exponentMultiplier);
428 
429     /**
430      * Shifts decimal to the right.
431      */
432     void shiftDecimalRight(int32_t numPlaces);
433 
434 private:
435     /*
436      * These data members are intentionally public and can be set directly.
437      *<P>
438      * The value represented is given by placing the decimal point before
439      * fDigits[fDecimalAt].  If fDecimalAt is < 0, then leading zeros between
440      * the decimal point and the first nonzero digit are implied.  If fDecimalAt
441      * is > fCount, then trailing zeros between the fDigits[fCount-1] and the
442      * decimal point are implied.
443      * <P>
444      * Equivalently, the represented value is given by f * 10^fDecimalAt.  Here
445      * f is a value 0.1 <= f < 1 arrived at by placing the digits in fDigits to
446      * the right of the decimal.
447      * <P>
448      * DigitList is normalized, so if it is non-zero, fDigits[0] is non-zero.  We
449      * don't allow denormalized numbers because our exponent is effectively of
450      * unlimited magnitude.  The fCount value contains the number of significant
451      * digits present in fDigits[].
452      * <P>
453      * Zero is represented by any DigitList with fCount == 0 or with each fDigits[i]
454      * for all i <= fCount == '0'.
455      *
456      * int32_t                         fDecimalAt;
457      * int32_t                         fCount;
458      * UBool                           fIsPositive;
459      * char                            *fDigits;
460      * DecimalFormat::ERoundingMode    fRoundingMode;
461      */
462 
463 public:
464     decContext    fContext;   // public access to status flags.
465 
466 private:
467     decNumber     *fDecNumber;
468     MaybeStackHeaderAndArray<decNumber, char, DEFAULT_DIGITS>  fStorage;
469 
470     /* Cached double value corresponding to this decimal number.
471      * This is an optimization for the formatting implementation, which may
472      * ask for the double value multiple times.
473      */
474     union DoubleOrInt64 {
475       double        fDouble;
476       int64_t       fInt64;
477     } fUnion;
478     enum EHave {
479       kNone=0,
480       kDouble
481     } fHave;
482 
483 
484 
485     UBool shouldRoundUp(int32_t maximumDigits) const;
486 
487  public:
488 
489 #if U_OVERRIDE_CXX_ALLOCATION
490     using UMemory::operator new;
491     using UMemory::operator delete;
492 #else
493     static inline void * U_EXPORT2 operator new(size_t size) U_NO_THROW { return ::operator new(size); };
494     static inline void U_EXPORT2 operator delete(void *ptr )  U_NO_THROW { ::operator delete(ptr); };
495 #endif
496     static char U_EXPORT2 getStrtodDecimalSeparator();
497 
498     /**
499      * Placement new for stack usage
500      * @internal
501      */
new(size_t,void * onStack,EStackMode)502     static inline void * U_EXPORT2 operator new(size_t /*size*/, void * onStack, EStackMode  /*mode*/) U_NO_THROW { return onStack; }
503 
504     /**
505      * Placement delete for stack usage
506      * @internal
507      */
delete(void *,void *,EStackMode)508     static inline void U_EXPORT2 operator delete(void * /*ptr*/, void * /*onStack*/, EStackMode /*mode*/)  U_NO_THROW {}
509 
510  private:
internalSetDouble(double d)511     inline void internalSetDouble(double d) {
512       fHave = kDouble;
513       fUnion.fDouble=d;
514     }
internalClear()515     inline void internalClear() {
516       fHave = kNone;
517     }
518 };
519 
520 
521 U_NAMESPACE_END
522 
523 #endif // #if !UCONFIG_NO_FORMATTING
524 #endif // _DIGITLST
525 
526 //eof
527