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