LCOV - code coverage report
Current view: top level - intl/icu/source/i18n - digitlst.h (source / functions) Hit Total Coverage
Test: output.info Lines: 0 14 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 9 0.0 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.13