// © 2016 and later: Unicode, Inc. and others. // License & terms of use: http://www.unicode.org/copyright.html /* ******************************************************************************* * Copyright (C) 2015, International Business Machines * Corporation and others. All Rights Reserved. ******************************************************************************* * precision.h * * created on: 2015jan06 * created by: Travis Keep */ #ifndef __PRECISION_H__ #define __PRECISION_H__ #include "unicode/uobject.h" #if !UCONFIG_NO_FORMATTING #include "unicode/utypes.h" #include "digitinterval.h" #include "digitlst.h" #include "significantdigitinterval.h" U_NAMESPACE_BEGIN class VisibleDigits; class VisibleDigitsWithExponent; /** * A precision manager for values to be formatted as fixed point. * Handles rounding of number to prepare it for formatting. */ class U_I18N_API FixedPrecision : public UMemory { public: /** * The smallest format interval allowed. Default is 1 integer digit and no * fraction digits. */ DigitInterval fMin; /** * The largest format interval allowed. Must contain fMin. * Default is all digits. */ DigitInterval fMax; /** * Min and max significant digits allowed. The default is no constraints. */ SignificantDigitInterval fSignificant; /** * The rounding increment or zero if there is no rounding increment. * Default is zero. */ DigitList fRoundingIncrement; /** * If set, causes round() to set status to U_FORMAT_INEXACT_ERROR if * any rounding is done. Default is FALSE. */ UBool fExactOnly; /** * If set, causes round() to set status to U_ILLEGAL_ARGUMENT_ERROR if * rounded number has more than maximum integer digits. Default is FALSE. */ UBool fFailIfOverMax; /** * Controls the rounding mode that initVisibleDigits uses. * Default is DecimalFormat::kRoundHalfEven */ DecimalFormat::ERoundingMode fRoundingMode; FixedPrecision(); /** * Returns TRUE if this object equals rhs. */ UBool equals(const FixedPrecision &rhs) const { return (fMin.equals(rhs.fMin) && fMax.equals(rhs.fMax) && fSignificant.equals(rhs.fSignificant) && (fRoundingIncrement == rhs.fRoundingIncrement) && fExactOnly == rhs.fExactOnly && fFailIfOverMax == rhs.fFailIfOverMax && fRoundingMode == rhs.fRoundingMode); } /** * Rounds value in place to prepare it for formatting. * @param value The value to be rounded. It is rounded in place. * @param exponent Always pass 0 for fixed decimal formatting. scientific * precision passes the exponent value. Essentially, it divides value by * 10^exponent, rounds and then multiplies by 10^exponent. * @param status error returned here. * @return reference to value. */ DigitList &round(DigitList &value, int32_t exponent, UErrorCode &status) const; /** * Returns the interval to use to format the rounded value. * @param roundedValue the already rounded value to format. * @param interval modified in place to be the interval to use to format * the rounded value. * @return a reference to interval. */ DigitInterval &getInterval( const DigitList &roundedValue, DigitInterval &interval) const; /** * Returns TRUE if this instance allows for fast formatting of integers. */ UBool isFastFormattable() const; /** * Initializes a VisibleDigits. * @param value value for VisibleDigits * Caller must not assume that the value of this parameter will remain * unchanged. * @param digits This is the value that is initialized. * @param status any error returned here. * @return digits */ VisibleDigits &initVisibleDigits( DigitList &value, VisibleDigits &digits, UErrorCode &status) const; /** * Initializes a VisibleDigits. * @param value value for VisibleDigits * @param digits This is the value that is initialized. * @param status any error returned here. * @return digits */ VisibleDigits &initVisibleDigits( double value, VisibleDigits &digits, UErrorCode &status) const; /** * Initializes a VisibleDigits. * @param value value for VisibleDigits * @param digits This is the value that is initialized. * @param status any error returned here. * @return digits */ VisibleDigits &initVisibleDigits( int64_t value, VisibleDigits &digits, UErrorCode &status) const; /** * Initializes a VisibleDigitsWithExponent. * @param value value for VisibleDigits * Caller must not assume that the value of this parameter will remain * unchanged. * @param digits This is the value that is initialized. * @param status any error returned here. * @return digits */ VisibleDigitsWithExponent &initVisibleDigitsWithExponent( DigitList &value, VisibleDigitsWithExponent &digits, UErrorCode &status) const; /** * Initializes a VisibleDigitsWithExponent. * @param value value for VisibleDigits * @param digits This is the value that is initialized. * @param status any error returned here. * @return digits */ VisibleDigitsWithExponent &initVisibleDigitsWithExponent( double value, VisibleDigitsWithExponent &digits, UErrorCode &status) const; /** * Initializes a VisibleDigitsWithExponent. * @param value value for VisibleDigits * @param digits This is the value that is initialized. * @param status any error returned here. * @return digits */ VisibleDigitsWithExponent &initVisibleDigitsWithExponent( int64_t value, VisibleDigitsWithExponent &digits, UErrorCode &status) const; private: /** * Attempts to initialize 'digits' using simple mod 10 arithmetic. * Returns FALSE if this is not possible such as when rounding * would change the value. Otherwise returns TRUE. * * If the method returns FALSE, caller should create a DigitList * and use it to initialize 'digits'. If this method returns TRUE, * caller should accept the value stored in 'digits'. If this * method returns TRUE along with a non zero error, caller must accept * the error and not try again with a DigitList. * * Before calling this method, caller must verify that this object * has no rounding increment set. * * The value that 'digits' is initialized to is mantissa * 10^exponent. * For example mantissa = 54700 and exponent = -3 means 54.7. The * properties of this object (such as min and max fraction digits), * not the number of trailing zeros in the mantissa, determine whether or * not the result contains any trailing 0's after the decimal point. * * @param mantissa the digits. May be positive or negative. May contain * trailing zeros. * @param exponent must always be zero or negative. An exponent > 0 * yields undefined results! * @param digits result stored here. * @param status any error returned here. */ UBool initVisibleDigits( int64_t mantissa, int32_t exponent, VisibleDigits &digits, UErrorCode &status) const; UBool isRoundingRequired( int32_t upperExponent, int32_t lowerExponent) const; DigitInterval &getIntervalForZero(DigitInterval &interval) const; DigitInterval &getInterval( int32_t upperExponent, DigitInterval &interval) const; static UBool handleNonNumeric(DigitList &value, VisibleDigits &digits); friend class ScientificPrecision; }; /** * A precision manager for values to be expressed as scientific notation. */ class U_I18N_API ScientificPrecision : public UMemory { public: FixedPrecision fMantissa; int32_t fMinExponentDigits; ScientificPrecision(); /** * rounds value in place to prepare it for formatting. * @param value The value to be rounded. It is rounded in place. * @param status error returned here. * @return reference to value. */ DigitList &round(DigitList &value, UErrorCode &status) const; /** * Converts value to a mantissa and exponent. * * @param value modified in place to be the mantissa. Depending on * the precision settings, the resulting mantissa may not fall * between 1.0 and 10.0. * @return the exponent of value. */ int32_t toScientific(DigitList &value) const; /** * Returns TRUE if this object equals rhs. */ UBool equals(const ScientificPrecision &rhs) const { return fMantissa.equals(rhs.fMantissa) && fMinExponentDigits == rhs.fMinExponentDigits; } /** * Initializes a VisibleDigitsWithExponent. * @param value the value * Caller must not assume that the value of this parameter will remain * unchanged. * @param digits This is the value that is initialized. * @param status any error returned here. * @return digits */ VisibleDigitsWithExponent &initVisibleDigitsWithExponent( DigitList &value, VisibleDigitsWithExponent &digits, UErrorCode &status) const; /** * Initializes a VisibleDigitsWithExponent. * @param value the value * @param digits This is the value that is initialized. * @param status any error returned here. * @return digits */ VisibleDigitsWithExponent &initVisibleDigitsWithExponent( double value, VisibleDigitsWithExponent &digits, UErrorCode &status) const; /** * Initializes a VisibleDigitsWithExponent. * @param value the value * @param digits This is the value that is initialized. * @param status any error returned here. * @return digits */ VisibleDigitsWithExponent &initVisibleDigitsWithExponent( int64_t value, VisibleDigitsWithExponent &digits, UErrorCode &status) const; private: int32_t getMultiplier() const; }; U_NAMESPACE_END #endif // #if !UCONFIG_NO_FORMATTING #endif // __PRECISION_H__