Index: icu46/source/i18n/digitlst.h |
=================================================================== |
--- icu46/source/i18n/digitlst.h (revision 0) |
+++ icu46/source/i18n/digitlst.h (revision 0) |
@@ -0,0 +1,399 @@ |
+/* |
+****************************************************************************** |
+* |
+* Copyright (C) 1997-2010, International Business Machines |
+* Corporation and others. All Rights Reserved. |
+* |
+****************************************************************************** |
+* |
+* File DIGITLST.H |
+* |
+* Modification History: |
+* |
+* Date Name Description |
+* 02/25/97 aliu Converted from java. |
+* 03/21/97 clhuang Updated per C++ implementation. |
+* 04/15/97 aliu Changed MAX_COUNT to DBL_DIG. Changed Digit to char. |
+* 09/09/97 aliu Adapted for exponential notation support. |
+* 08/02/98 stephen Added nearest/even rounding |
+* 06/29/99 stephen Made LONG_DIGITS a macro to satisfy SUN compiler |
+* 07/09/99 stephen Removed kMaxCount (unused, for HP compiler) |
+****************************************************************************** |
+*/ |
+ |
+#ifndef DIGITLST_H |
+#define DIGITLST_H |
+ |
+#include "unicode/uobject.h" |
+ |
+#if !UCONFIG_NO_FORMATTING |
+#include "unicode/decimfmt.h" |
+#include <float.h> |
+#include "decContext.h" |
+#include "decNumber.h" |
+#include "cmemory.h" |
+ |
+// Decimal digits in a 64-bit int |
+#define INT64_DIGITS 19 |
+ |
+typedef enum EDigitListValues { |
+ MAX_DBL_DIGITS = DBL_DIG, |
+ MAX_I64_DIGITS = INT64_DIGITS, |
+ MAX_DIGITS = MAX_I64_DIGITS, |
+ MAX_EXPONENT = DBL_DIG, |
+ DIGIT_PADDING = 3, |
+ DEFAULT_DIGITS = 40, // Initial storage size, will grow as needed. |
+ |
+ // "+." + fDigits + "e" + fDecimalAt |
+ MAX_DEC_DIGITS = MAX_DIGITS + DIGIT_PADDING + MAX_EXPONENT |
+} EDigitListValues; |
+ |
+U_NAMESPACE_BEGIN |
+ |
+class CharString; |
+ |
+// Export an explicit template instantiation of the MaybeStackHeaderAndArray that |
+// is used as a data member of DigitList. |
+// |
+// MSVC requires this, even though it should not be necessary. |
+// No direct access to the MaybeStackHeaderAndArray leaks out of the i18n library. |
+// |
+// Macintosh produces duplicate definition linker errors with the explicit template |
+// instantiation. |
+// |
+#if !defined(U_DARWIN) |
+template class U_I18N_API MaybeStackHeaderAndArray<decNumber, char, DEFAULT_DIGITS>; |
+#endif |
+ |
+ |
+/** |
+ * Digit List is actually a Decimal Floating Point number. |
+ * The original implementation has been replaced by a thin wrapper onto a |
+ * decimal number from the decNumber library. |
+ * |
+ * The original DigitList API has been retained, to minimize the impact of |
+ * the change on the rest of the ICU formatting code. |
+ * |
+ * The change to decNumber enables support for big decimal numbers, and |
+ * allows rounding computations to be done directly in decimal, avoiding |
+ * extra, and inaccurate, conversions to and from doubles. |
+ * |
+ * Original DigitList comments: |
+ * |
+ * Digit List utility class. Private to DecimalFormat. Handles the transcoding |
+ * between numeric values and strings of characters. Only handles |
+ * non-negative numbers. The division of labor between DigitList and |
+ * DecimalFormat is that DigitList handles the radix 10 representation |
+ * issues; DecimalFormat handles the locale-specific issues such as |
+ * positive/negative, grouping, decimal point, currency, and so on. |
+ * <P> |
+ * A DigitList is really a representation of a floating point value. |
+ * It may be an integer value; we assume that a double has sufficient |
+ * precision to represent all digits of a long. |
+ * <P> |
+ * The DigitList representation consists of a string of characters, |
+ * which are the digits radix 10, from '0' to '9'. It also has a radix |
+ * 10 exponent associated with it. The value represented by a DigitList |
+ * object can be computed by mulitplying the fraction f, where 0 <= f < 1, |
+ * derived by placing all the digits of the list to the right of the |
+ * decimal point, by 10^exponent. |
+ * |
+ * -------- |
+ * |
+ * DigitList vs. decimalNumber: |
+ * |
+ * DigitList stores digits with the most significant first. |
+ * decNumber stores digits with the least significant first. |
+ * |
+ * DigitList, decimal point is before the most significant. |
+ * decNumber, decimal point is after the least signficant digit. |
+ * |
+ * digitList: 0.ddddd * 10 ^ exp |
+ * decNumber: ddddd. * 10 ^ exp |
+ * |
+ * digitList exponent = decNumber exponent + digit count |
+ * |
+ * digitList, digits are platform invariant chars, '0' - '9' |
+ * decNumber, digits are binary, one per byte, 0 - 9. |
+ * |
+ * (decNumber library is configurable in how digits are stored, ICU has configured |
+ * it this way for convenience in replacing the old DigitList implementation.) |
+ */ |
+class U_I18N_API DigitList : public UMemory { // Declare external to make compiler happy |
+public: |
+ |
+ DigitList(); |
+ ~DigitList(); |
+ |
+ /* copy constructor |
+ * @param DigitList The object to be copied. |
+ * @return the newly created object. |
+ */ |
+ DigitList(const DigitList&); // copy constructor |
+ |
+ /* assignment operator |
+ * @param DigitList The object to be copied. |
+ * @return the newly created object. |
+ */ |
+ DigitList& operator=(const DigitList&); // assignment operator |
+ |
+ /** |
+ * Return true if another object is semantically equal to this one. |
+ * @param other The DigitList to be compared for equality |
+ * @return true if another object is semantically equal to this one. |
+ * return false otherwise. |
+ */ |
+ UBool operator==(const DigitList& other) const; |
+ |
+ int32_t compare(const DigitList& other); |
+ |
+ |
+ inline UBool operator!=(const DigitList& other) const { return !operator==(other); }; |
+ |
+ /** |
+ * Clears out the digits. |
+ * Use before appending them. |
+ * Typically, you set a series of digits with append, then at the point |
+ * you hit the decimal point, you set myDigitList.fDecimalAt = myDigitList.fCount; |
+ * then go on appending digits. |
+ */ |
+ void clear(void); |
+ |
+ /** |
+ * Remove, by rounding, any fractional part of the decimal number, |
+ * leaving an integer value. |
+ */ |
+ void toIntegralValue(); |
+ |
+ /** |
+ * Appends digits to the list. |
+ * CAUTION: this function is not recommended for new code. |
+ * In the original DigitList implementation, decimal numbers were |
+ * parsed by appending them to a digit list as they were encountered. |
+ * With the revamped DigitList based on decNumber, append is very |
+ * inefficient, and the interaction with the exponent value is confusing. |
+ * Best avoided. |
+ * TODO: remove this function once all use has been replaced. |
+ * TODO: describe alternative to append() |
+ * @param digit The digit to be appended. |
+ */ |
+ void append(char digit); |
+ |
+ /** |
+ * Utility routine to get the value of the digit list |
+ * Returns 0.0 if zero length. |
+ * @return the value of the digit list. |
+ */ |
+ double getDouble(void) const; |
+ |
+ /** |
+ * Utility routine to get the value of the digit list |
+ * Make sure that fitsIntoLong() is called before calling this function. |
+ * Returns 0 if zero length. |
+ * @return the value of the digit list, return 0 if it is zero length |
+ */ |
+ int32_t getLong(void) /*const*/; |
+ |
+ /** |
+ * Utility routine to get the value of the digit list |
+ * Make sure that fitsIntoInt64() is called before calling this function. |
+ * Returns 0 if zero length. |
+ * @return the value of the digit list, return 0 if it is zero length |
+ */ |
+ int64_t getInt64(void) /*const*/; |
+ |
+ /** |
+ * Utility routine to get the value of the digit list as a decimal string. |
+ */ |
+ void getDecimal(CharString &str, UErrorCode &status); |
+ |
+ /** |
+ * Return true if the number represented by this object can fit into |
+ * a long. |
+ * @param ignoreNegativeZero True if negative zero is ignored. |
+ * @return true if the number represented by this object can fit into |
+ * a long, return false otherwise. |
+ */ |
+ UBool fitsIntoLong(UBool ignoreNegativeZero) /*const*/; |
+ |
+ /** |
+ * Return true if the number represented by this object can fit into |
+ * an int64_t. |
+ * @param ignoreNegativeZero True if negative zero is ignored. |
+ * @return true if the number represented by this object can fit into |
+ * a long, return false otherwise. |
+ */ |
+ UBool fitsIntoInt64(UBool ignoreNegativeZero) /*const*/; |
+ |
+ /** |
+ * Utility routine to set the value of the digit list from a double. |
+ * @param source The value to be set |
+ */ |
+ void set(double source); |
+ |
+ /** |
+ * Utility routine to set the value of the digit list from a long. |
+ * If a non-zero maximumDigits is specified, no more than that number of |
+ * significant digits will be produced. |
+ * @param source The value to be set |
+ */ |
+ void set(int32_t source); |
+ |
+ /** |
+ * Utility routine to set the value of the digit list from an int64. |
+ * If a non-zero maximumDigits is specified, no more than that number of |
+ * significant digits will be produced. |
+ * @param source The value to be set |
+ */ |
+ void set(int64_t source); |
+ |
+ /** |
+ * Utility routine to set the value of the digit list from a decimal number |
+ * string. |
+ * @param source The value to be set. The string must be nul-terminated. |
+ */ |
+ void set(const StringPiece &source, UErrorCode &status); |
+ |
+ /** |
+ * Multiply this = this * arg |
+ * This digitlist will be expanded if necessary to accomodate the result. |
+ * @param arg the number to multiply by. |
+ */ |
+ void mult(const DigitList &arg, UErrorCode &status); |
+ |
+ /** |
+ * Divide this = this / arg |
+ */ |
+ void div(const DigitList &arg, UErrorCode &status); |
+ |
+ // The following functions replace direct access to the original DigitList implmentation |
+ // data structures. |
+ |
+ void setRoundingMode(DecimalFormat::ERoundingMode m); |
+ |
+ /** Test a number for zero. |
+ * @return TRUE if the number is zero |
+ */ |
+ UBool isZero(void) const; |
+ |
+ /** Test for a Nan |
+ * @return TRUE if the number is a NaN |
+ */ |
+ UBool isNaN(void) const {return decNumberIsNaN(fDecNumber);}; |
+ |
+ UBool isInfinite() const {return decNumberIsInfinite(fDecNumber);}; |
+ |
+ /** Reduce, or normalize. Removes trailing zeroes, adjusts exponent appropriately. */ |
+ void reduce(); |
+ |
+ /** Remove trailing fraction zeros, adjust exponent accordingly. */ |
+ void trim(); |
+ |
+ /** Set to zero */ |
+ void setToZero() {uprv_decNumberZero(fDecNumber);}; |
+ |
+ /** get the number of digits in the decimal number */ |
+ int32_t digits() const {return fDecNumber->digits;}; |
+ |
+ /** |
+ * Round the number to the given number of digits. |
+ * @param maximumDigits The maximum number of digits to be shown. |
+ * Upon return, count will be less than or equal to maximumDigits. |
+ */ |
+ void round(int32_t maximumDigits); |
+ |
+ void roundFixedPoint(int32_t maximumFractionDigits); |
+ |
+ /** Ensure capacity for digits. Grow the storage if it is currently less than |
+ * the requested size. Capacity is not reduced if it is already greater |
+ * than requested. |
+ */ |
+ void ensureCapacity(int32_t requestedSize, UErrorCode &status); |
+ |
+ UBool isPositive(void) const { return decNumberIsNegative(fDecNumber) == 0;}; |
+ void setPositive(UBool s); |
+ |
+ void setDecimalAt(int32_t d); |
+ int32_t getDecimalAt(); |
+ |
+ void setCount(int32_t c); |
+ int32_t getCount() const; |
+ |
+ /** |
+ * Set the digit in platform (invariant) format, from '0'..'9' |
+ * @param i index of digit |
+ * @param v digit value, from '0' to '9' in platform invariant format |
+ */ |
+ void setDigit(int32_t i, char v); |
+ |
+ /** |
+ * Get the digit in platform (invariant) format, from '0'..'9' inclusive |
+ * @param i index of digit |
+ * @return invariant format of the digit |
+ */ |
+ char getDigit(int32_t i); |
+ |
+ |
+ /** |
+ * Get the digit's value, as an integer from 0..9 inclusive. |
+ * Note that internally this value is a decNumberUnit, but ICU configures it to be a uint8_t. |
+ * @param i index of digit |
+ * @return value of that digit |
+ */ |
+ uint8_t getDigitValue(int32_t i); |
+ |
+ |
+private: |
+ /* |
+ * These data members are intentionally public and can be set directly. |
+ *<P> |
+ * The value represented is given by placing the decimal point before |
+ * fDigits[fDecimalAt]. If fDecimalAt is < 0, then leading zeros between |
+ * the decimal point and the first nonzero digit are implied. If fDecimalAt |
+ * is > fCount, then trailing zeros between the fDigits[fCount-1] and the |
+ * decimal point are implied. |
+ * <P> |
+ * Equivalently, the represented value is given by f * 10^fDecimalAt. Here |
+ * f is a value 0.1 <= f < 1 arrived at by placing the digits in fDigits to |
+ * the right of the decimal. |
+ * <P> |
+ * DigitList is normalized, so if it is non-zero, fDigits[0] is non-zero. We |
+ * don't allow denormalized numbers because our exponent is effectively of |
+ * unlimited magnitude. The fCount value contains the number of significant |
+ * digits present in fDigits[]. |
+ * <P> |
+ * Zero is represented by any DigitList with fCount == 0 or with each fDigits[i] |
+ * for all i <= fCount == '0'. |
+ * |
+ * int32_t fDecimalAt; |
+ * int32_t fCount; |
+ * UBool fIsPositive; |
+ * char *fDigits; |
+ * DecimalFormat::ERoundingMode fRoundingMode; |
+ */ |
+ |
+private: |
+ |
+ decContext fContext; |
+ decNumber *fDecNumber; |
+ MaybeStackHeaderAndArray<decNumber, char, DEFAULT_DIGITS> fStorage; |
+ |
+ /* Cached double value corresponding to this decimal number. |
+ * This is an optimization for the formatting implementation, which may |
+ * ask for the double value multiple times. |
+ */ |
+ double fDouble; |
+ UBool fHaveDouble; |
+ |
+ |
+ |
+ UBool shouldRoundUp(int32_t maximumDigits) const; |
+}; |
+ |
+ |
+U_NAMESPACE_END |
+ |
+#endif // #if !UCONFIG_NO_FORMATTING |
+#endif // _DIGITLST |
+ |
+//eof |
Property changes on: icu46/source/i18n/digitlst.h |
___________________________________________________________________ |
Added: svn:eol-style |
+ LF |