mirror of
https://github.com/unicode-org/icu.git
synced 2025-04-05 21:45:37 +00:00
ICU-5193 Big decimal number formatting.
X-SVN-Rev: 27696
This commit is contained in:
parent
cae10acab5
commit
4e56218eb1
33 changed files with 2717 additions and 1212 deletions
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
******************************************************************************
|
||||
*
|
||||
* Copyright (C) 1997-2009, International Business Machines
|
||||
* Copyright (C) 1997-2010, International Business Machines
|
||||
* Corporation and others. All Rights Reserved.
|
||||
*
|
||||
******************************************************************************
|
||||
|
@ -250,16 +250,24 @@ private:
|
|||
}
|
||||
}
|
||||
/* No comparison operators with other MaybeStackArray's. */
|
||||
bool operator==(const MaybeStackArray &other);
|
||||
bool operator!=(const MaybeStackArray &other);
|
||||
bool operator==(const MaybeStackArray & /*other*/) {return FALSE;};
|
||||
bool operator!=(const MaybeStackArray & /*other*/) {return TRUE;};
|
||||
/* No ownership transfer: No copy constructor, no assignment operator. */
|
||||
MaybeStackArray(const MaybeStackArray &other);
|
||||
void operator=(const MaybeStackArray &other);
|
||||
/* No heap allocation. Use only on the stack. */
|
||||
static void * U_EXPORT2 operator new(size_t size);
|
||||
static void * U_EXPORT2 operator new[](size_t size);
|
||||
MaybeStackArray(const MaybeStackArray & /*other*/) {};
|
||||
void operator=(const MaybeStackArray & /*other*/) {};
|
||||
|
||||
// No heap allocation. Use only on the stack.
|
||||
// (Declaring these functions private triggers a cascade of problems:
|
||||
// MSVC insists on exporting an instantiation of MaybeStackArray, which
|
||||
// requires that all functions be defined.
|
||||
// An empty implementation of new() is rejected, it must return a value.
|
||||
// Returning NULL is rejected by gcc for operator new.
|
||||
// The expedient thing is just not to override operator new.
|
||||
// While relatively pointless, heap allocated instances will function.
|
||||
// static void * U_EXPORT2 operator new(size_t size);
|
||||
// static void * U_EXPORT2 operator new[](size_t size);
|
||||
#if U_HAVE_PLACEMENT_NEW
|
||||
static void * U_EXPORT2 operator new(size_t, void *ptr);
|
||||
// static void * U_EXPORT2 operator new(size_t, void *ptr);
|
||||
#endif
|
||||
};
|
||||
|
||||
|
|
|
@ -742,6 +742,7 @@ typedef enum UErrorCode {
|
|||
U_DUPLICATE_KEYWORD, /**< Duplicate keyword in PluralFormat */
|
||||
U_UNDEFINED_KEYWORD, /**< Undefined Plural keyword */
|
||||
U_DEFAULT_KEYWORD_MISSING, /**< Missing DEFAULT rule in plural rules */
|
||||
U_DECIMAL_NUMBER_SYNTAX_ERROR, /**< Decimal number syntax error */
|
||||
U_FMT_PARSE_ERROR_LIMIT, /**< The limit for format library errors */
|
||||
|
||||
/*
|
||||
|
|
|
@ -121,7 +121,8 @@ _uFmtErrorName[U_FMT_PARSE_ERROR_LIMIT - U_FMT_PARSE_ERROR_START] = {
|
|||
"U_ARGUMENT_TYPE_MISMATCH",
|
||||
"U_DUPLICATE_KEYWORD",
|
||||
"U_UNDEFINED_KEYWORD",
|
||||
"U_DEFAULT_KEYWORD_MISSING"
|
||||
"U_DEFAULT_KEYWORD_MISSING",
|
||||
"U_DECIMAL_NUMBER_SYNTAX_ERROR"
|
||||
};
|
||||
|
||||
static const char * const
|
||||
|
|
|
@ -84,7 +84,7 @@ zonemeta.o zstrfmt.o plurrule.o plurfmt.o selfmt.o dtitvfmt.o dtitvinf.o \
|
|||
tmunit.o tmutamt.o tmutfmt.o colldata.o bmsearch.o bms.o currpinf.o \
|
||||
uspoof.o uspoof_impl.o uspoof_build.o uspoof_conf.o uspoof_wsconf.o \
|
||||
ztrans.o zrule.o vzone.o fphdlimp.o fpositer.o locdspnm.o \
|
||||
decNumber.o decContext.o
|
||||
decNumber.o decContext.o decnumstr.o
|
||||
|
||||
## Header files to install
|
||||
HEADERS = $(srcdir)/unicode/*.h
|
||||
|
|
|
@ -51,7 +51,7 @@ const uInt DECPOWERS[10]={1, 10, 100, 1000, 10000, 100000, 1000000,
|
|||
/* */
|
||||
/* No error is possible. */
|
||||
/* ------------------------------------------------------------------ */
|
||||
decContext *uprv_decContextClearStatus(decContext *context, uInt mask) {
|
||||
U_CAPI decContext * U_EXPORT2 uprv_decContextClearStatus(decContext *context, uInt mask) {
|
||||
context->status&=~mask;
|
||||
return context;
|
||||
} /* decContextClearStatus */
|
||||
|
@ -69,7 +69,7 @@ decContext *uprv_decContextClearStatus(decContext *context, uInt mask) {
|
|||
/* Invalid_operation set in the status field. */
|
||||
/* returns a context structure with the appropriate initial values. */
|
||||
/* ------------------------------------------------------------------ */
|
||||
decContext * uprv_decContextDefault(decContext *context, Int kind) {
|
||||
U_CAPI decContext * U_EXPORT2 uprv_decContextDefault(decContext *context, Int kind) {
|
||||
/* set defaults... */
|
||||
context->digits=9; /* 9 digits */
|
||||
context->emax=DEC_MAX_EMAX; /* 9-digit exponents */
|
||||
|
@ -134,7 +134,7 @@ decContext * uprv_decContextDefault(decContext *context, Int kind) {
|
|||
/* */
|
||||
/* No error is possible. */
|
||||
/* ------------------------------------------------------------------ */
|
||||
enum rounding uprv_decContextGetRounding(decContext *context) {
|
||||
U_CAPI enum rounding U_EXPORT2 uprv_decContextGetRounding(decContext *context) {
|
||||
return context->round;
|
||||
} /* decContextGetRounding */
|
||||
|
||||
|
@ -146,7 +146,7 @@ enum rounding uprv_decContextGetRounding(decContext *context) {
|
|||
/* */
|
||||
/* No error is possible. */
|
||||
/* ------------------------------------------------------------------ */
|
||||
uInt uprv_decContextGetStatus(decContext *context) {
|
||||
U_CAPI uInt U_EXPORT2 uprv_decContextGetStatus(decContext *context) {
|
||||
return context->status;
|
||||
} /* decContextGetStatus */
|
||||
|
||||
|
@ -162,7 +162,7 @@ uInt uprv_decContextGetStatus(decContext *context) {
|
|||
/* */
|
||||
/* No error is possible. */
|
||||
/* ------------------------------------------------------------------ */
|
||||
decContext *uprv_decContextRestoreStatus(decContext *context,
|
||||
U_CAPI decContext * U_EXPORT2 uprv_decContextRestoreStatus(decContext *context,
|
||||
uInt newstatus, uInt mask) {
|
||||
context->status&=~mask; /* clear the selected bits */
|
||||
context->status|=(mask&newstatus); /* or in the new bits */
|
||||
|
@ -179,7 +179,7 @@ decContext *uprv_decContextRestoreStatus(decContext *context,
|
|||
/* */
|
||||
/* No error is possible. */
|
||||
/* ------------------------------------------------------------------ */
|
||||
uInt uprv_decContextSaveStatus(decContext *context, uInt mask) {
|
||||
U_CAPI uInt U_EXPORT2 uprv_decContextSaveStatus(decContext *context, uInt mask) {
|
||||
return context->status&mask;
|
||||
} /* decContextSaveStatus */
|
||||
|
||||
|
@ -192,7 +192,7 @@ uInt uprv_decContextSaveStatus(decContext *context, uInt mask) {
|
|||
/* */
|
||||
/* No error is possible. */
|
||||
/* ------------------------------------------------------------------ */
|
||||
decContext *uprv_decContextSetRounding(decContext *context,
|
||||
U_CAPI decContext * U_EXPORT2 uprv_decContextSetRounding(decContext *context,
|
||||
enum rounding newround) {
|
||||
context->round=newround;
|
||||
return context;
|
||||
|
@ -208,7 +208,7 @@ decContext *uprv_decContextSetRounding(decContext *context,
|
|||
/* Control may never return from this routine, if there is a signal */
|
||||
/* handler and it takes a long jump. */
|
||||
/* ------------------------------------------------------------------ */
|
||||
decContext * uprv_decContextSetStatus(decContext *context, uInt status) {
|
||||
U_CAPI decContext * U_EXPORT2 uprv_decContextSetStatus(decContext *context, uInt status) {
|
||||
context->status|=status;
|
||||
if (status & context->traps) raise(SIGFPE);
|
||||
return context;} /* decContextSetStatus */
|
||||
|
@ -227,7 +227,7 @@ decContext * uprv_decContextSetStatus(decContext *context, uInt status) {
|
|||
/* DEC_Condition_MU or is not recognized. In these cases NULL is */
|
||||
/* returned. */
|
||||
/* ------------------------------------------------------------------ */
|
||||
decContext * uprv_decContextSetStatusFromString(decContext *context,
|
||||
U_CAPI decContext * U_EXPORT2 uprv_decContextSetStatusFromString(decContext *context,
|
||||
const char *string) {
|
||||
if (strcmp(string, DEC_Condition_CS)==0)
|
||||
return uprv_decContextSetStatus(context, DEC_Conversion_syntax);
|
||||
|
@ -278,7 +278,7 @@ decContext * uprv_decContextSetStatusFromString(decContext *context,
|
|||
/* DEC_Condition_MU or is not recognized. In these cases NULL is */
|
||||
/* returned. */
|
||||
/* ------------------------------------------------------------------ */
|
||||
decContext * uprv_decContextSetStatusFromStringQuiet(decContext *context,
|
||||
U_CAPI decContext * U_EXPORT2 uprv_decContextSetStatusFromStringQuiet(decContext *context,
|
||||
const char *string) {
|
||||
if (strcmp(string, DEC_Condition_CS)==0)
|
||||
return uprv_decContextSetStatusQuiet(context, DEC_Conversion_syntax);
|
||||
|
@ -324,7 +324,7 @@ decContext * uprv_decContextSetStatusFromStringQuiet(decContext *context,
|
|||
/* */
|
||||
/* No error is possible. */
|
||||
/* ------------------------------------------------------------------ */
|
||||
decContext * uprv_decContextSetStatusQuiet(decContext *context, uInt status) {
|
||||
U_CAPI decContext * U_EXPORT2 uprv_decContextSetStatusQuiet(decContext *context, uInt status) {
|
||||
context->status|=status;
|
||||
return context;} /* decContextSetStatusQuiet */
|
||||
|
||||
|
@ -336,7 +336,7 @@ decContext * uprv_decContextSetStatusQuiet(decContext *context, uInt status) {
|
|||
/* returns a constant string describing the condition. If multiple */
|
||||
/* (or no) flags are set, a generic constant message is returned. */
|
||||
/* ------------------------------------------------------------------ */
|
||||
const char *uprv_decContextStatusToString(const decContext *context) {
|
||||
U_CAPI const char * U_EXPORT2 uprv_decContextStatusToString(const decContext *context) {
|
||||
Int status=context->status;
|
||||
|
||||
/* test the five IEEE first, as some of the others are ambiguous when */
|
||||
|
@ -374,7 +374,7 @@ const char *uprv_decContextStatusToString(const decContext *context) {
|
|||
/* */
|
||||
/* No error is possible. */
|
||||
/* ------------------------------------------------------------------ */
|
||||
Int uprv_decContextTestEndian(Flag quiet) {
|
||||
U_CAPI Int U_EXPORT2 uprv_decContextTestEndian(Flag quiet) {
|
||||
Int res=0; /* optimist */
|
||||
uInt dle=(uInt)DECLITEND; /* unsign */
|
||||
if (dle>1) dle=1; /* ensure 0 or 1 */
|
||||
|
@ -402,7 +402,7 @@ Int uprv_decContextTestEndian(Flag quiet) {
|
|||
/* */
|
||||
/* No error is possible. */
|
||||
/* ------------------------------------------------------------------ */
|
||||
uInt uprv_decContextTestSavedStatus(uInt oldstatus, uInt mask) {
|
||||
U_CAPI uInt U_EXPORT2 uprv_decContextTestSavedStatus(uInt oldstatus, uInt mask) {
|
||||
return (oldstatus&mask)!=0;
|
||||
} /* decContextTestSavedStatus */
|
||||
|
||||
|
@ -416,7 +416,7 @@ uInt uprv_decContextTestSavedStatus(uInt oldstatus, uInt mask) {
|
|||
/* */
|
||||
/* No error is possible. */
|
||||
/* ------------------------------------------------------------------ */
|
||||
uInt uprv_decContextTestStatus(decContext *context, uInt mask) {
|
||||
U_CAPI uInt U_EXPORT2 uprv_decContextTestStatus(decContext *context, uInt mask) {
|
||||
return (context->status&mask)!=0;
|
||||
} /* decContextTestStatus */
|
||||
|
||||
|
@ -428,7 +428,7 @@ uInt uprv_decContextTestStatus(decContext *context, uInt mask) {
|
|||
/* */
|
||||
/* No error is possible. */
|
||||
/* ------------------------------------------------------------------ */
|
||||
decContext *uprv_decContextZeroStatus(decContext *context) {
|
||||
U_CAPI decContext * U_EXPORT2 uprv_decContextZeroStatus(decContext *context) {
|
||||
context->status=0;
|
||||
return context;
|
||||
} /* decContextZeroStatus */
|
||||
|
|
|
@ -247,21 +247,21 @@
|
|||
#define DEC_INIT_DECQUAD DEC_INIT_DECIMAL128
|
||||
|
||||
/* decContext routines */
|
||||
extern decContext * uprv_decContextClearStatus(decContext *, uint32_t);
|
||||
extern decContext * uprv_decContextDefault(decContext *, int32_t);
|
||||
extern enum rounding uprv_decContextGetRounding(decContext *);
|
||||
extern uint32_t uprv_decContextGetStatus(decContext *);
|
||||
extern decContext * uprv_decContextRestoreStatus(decContext *, uint32_t, uint32_t);
|
||||
extern uint32_t uprv_decContextSaveStatus(decContext *, uint32_t);
|
||||
extern decContext * uprv_decContextSetRounding(decContext *, enum rounding);
|
||||
extern decContext * uprv_decContextSetStatus(decContext *, uint32_t);
|
||||
extern decContext * uprv_decContextSetStatusFromString(decContext *, const char *);
|
||||
extern decContext * uprv_decContextSetStatusFromStringQuiet(decContext *, const char *);
|
||||
extern decContext * uprv_decContextSetStatusQuiet(decContext *, uint32_t);
|
||||
extern const char * uprv_decContextStatusToString(const decContext *);
|
||||
extern int32_t uprv_decContextTestEndian(uint8_t);
|
||||
extern uint32_t uprv_decContextTestSavedStatus(uint32_t, uint32_t);
|
||||
extern uint32_t uprv_decContextTestStatus(decContext *, uint32_t);
|
||||
extern decContext * uprv_decContextZeroStatus(decContext *);
|
||||
U_INTERNAL decContext * U_EXPORT2 uprv_decContextClearStatus(decContext *, uint32_t);
|
||||
U_INTERNAL decContext * U_EXPORT2 uprv_decContextDefault(decContext *, int32_t);
|
||||
U_INTERNAL enum rounding U_EXPORT2 uprv_decContextGetRounding(decContext *);
|
||||
U_INTERNAL uint32_t U_EXPORT2 uprv_decContextGetStatus(decContext *);
|
||||
U_INTERNAL decContext * U_EXPORT2 uprv_decContextRestoreStatus(decContext *, uint32_t, uint32_t);
|
||||
U_INTERNAL uint32_t U_EXPORT2 uprv_decContextSaveStatus(decContext *, uint32_t);
|
||||
U_INTERNAL decContext * U_EXPORT2 uprv_decContextSetRounding(decContext *, enum rounding);
|
||||
U_INTERNAL decContext * U_EXPORT2 uprv_decContextSetStatus(decContext *, uint32_t);
|
||||
U_INTERNAL decContext * U_EXPORT2 uprv_decContextSetStatusFromString(decContext *, const char *);
|
||||
U_INTERNAL decContext * U_EXPORT2 uprv_decContextSetStatusFromStringQuiet(decContext *, const char *);
|
||||
U_INTERNAL decContext * U_EXPORT2 uprv_decContextSetStatusQuiet(decContext *, uint32_t);
|
||||
U_INTERNAL const char * U_EXPORT2 uprv_decContextStatusToString(const decContext *);
|
||||
U_INTERNAL int32_t U_EXPORT2 uprv_decContextTestEndian(uint8_t);
|
||||
U_INTERNAL uint32_t U_EXPORT2 uprv_decContextTestSavedStatus(uint32_t, uint32_t);
|
||||
U_INTERNAL uint32_t U_EXPORT2 uprv_decContextTestStatus(decContext *, uint32_t);
|
||||
U_INTERNAL decContext * U_EXPORT2 uprv_decContextZeroStatus(decContext *);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -348,7 +348,7 @@ static void decDumpAr(char, const Unit *, Int);
|
|||
/* */
|
||||
/* No error is possible. */
|
||||
/* ------------------------------------------------------------------ */
|
||||
decNumber * uprv_decNumberFromInt32(decNumber *dn, Int in) {
|
||||
U_CAPI decNumber * U_EXPORT2 uprv_decNumberFromInt32(decNumber *dn, Int in) {
|
||||
uInt unsig;
|
||||
if (in>=0) unsig=in;
|
||||
else { /* negative (possibly BADINT) */
|
||||
|
@ -361,7 +361,7 @@ decNumber * uprv_decNumberFromInt32(decNumber *dn, Int in) {
|
|||
return dn;
|
||||
} /* decNumberFromInt32 */
|
||||
|
||||
decNumber * uprv_decNumberFromUInt32(decNumber *dn, uInt uin) {
|
||||
U_CAPI decNumber * U_EXPORT2 uprv_decNumberFromUInt32(decNumber *dn, uInt uin) {
|
||||
Unit *up; /* work pointer */
|
||||
uprv_decNumberZero(dn); /* clean */
|
||||
if (uin==0) return dn; /* [or decGetDigits bad call] */
|
||||
|
@ -383,7 +383,7 @@ decNumber * uprv_decNumberFromUInt32(decNumber *dn, uInt uin) {
|
|||
/* Invalid is set if the decNumber does not have exponent==0 or if */
|
||||
/* it is a NaN, Infinite, or out-of-range. */
|
||||
/* ------------------------------------------------------------------ */
|
||||
Int uprv_decNumberToInt32(const decNumber *dn, decContext *set) {
|
||||
U_CAPI Int U_EXPORT2 uprv_decNumberToInt32(const decNumber *dn, decContext *set) {
|
||||
#if DECCHECK
|
||||
if (decCheckOperands(DECUNRESU, DECUNUSED, dn, set)) return 0;
|
||||
#endif
|
||||
|
@ -419,7 +419,7 @@ Int uprv_decNumberToInt32(const decNumber *dn, decContext *set) {
|
|||
return 0;
|
||||
} /* decNumberToInt32 */
|
||||
|
||||
uInt uprv_decNumberToUInt32(const decNumber *dn, decContext *set) {
|
||||
U_CAPI uInt U_EXPORT2 uprv_decNumberToUInt32(const decNumber *dn, decContext *set) {
|
||||
#if DECCHECK
|
||||
if (decCheckOperands(DECUNRESU, DECUNUSED, dn, set)) return 0;
|
||||
#endif
|
||||
|
@ -462,12 +462,12 @@ uInt uprv_decNumberToUInt32(const decNumber *dn, decContext *set) {
|
|||
/* */
|
||||
/* No error is possible, and no status can be set. */
|
||||
/* ------------------------------------------------------------------ */
|
||||
char * uprv_decNumberToString(const decNumber *dn, char *string){
|
||||
U_CAPI char * U_EXPORT2 uprv_decNumberToString(const decNumber *dn, char *string){
|
||||
decToString(dn, string, 0);
|
||||
return string;
|
||||
} /* DecNumberToString */
|
||||
|
||||
char * uprv_decNumberToEngString(const decNumber *dn, char *string){
|
||||
U_CAPI char * U_EXPORT2 uprv_decNumberToEngString(const decNumber *dn, char *string){
|
||||
decToString(dn, string, 1);
|
||||
return string;
|
||||
} /* DecNumberToEngString */
|
||||
|
@ -492,7 +492,7 @@ char * uprv_decNumberToEngString(const decNumber *dn, char *string){
|
|||
/* */
|
||||
/* If bad syntax is detected, the result will be a quiet NaN. */
|
||||
/* ------------------------------------------------------------------ */
|
||||
decNumber * uprv_decNumberFromString(decNumber *dn, const char chars[],
|
||||
U_CAPI decNumber * U_EXPORT2 uprv_decNumberFromString(decNumber *dn, const char chars[],
|
||||
decContext *set) {
|
||||
Int exponent=0; /* working exponent [assume 0] */
|
||||
uByte bits=0; /* working flags [assume +ve] */
|
||||
|
@ -741,7 +741,7 @@ decNumber * uprv_decNumberFromString(decNumber *dn, const char chars[],
|
|||
/* This has the same effect as decNumberPlus unless A is negative, */
|
||||
/* in which case it has the same effect as decNumberMinus. */
|
||||
/* ------------------------------------------------------------------ */
|
||||
decNumber * uprv_decNumberAbs(decNumber *res, const decNumber *rhs,
|
||||
U_CAPI decNumber * U_EXPORT2 uprv_decNumberAbs(decNumber *res, const decNumber *rhs,
|
||||
decContext *set) {
|
||||
decNumber dzero; /* for 0 */
|
||||
uInt status=0; /* accumulator */
|
||||
|
@ -773,7 +773,7 @@ decNumber * uprv_decNumberAbs(decNumber *res, const decNumber *rhs,
|
|||
/* C must have space for set->digits digits. */
|
||||
/* ------------------------------------------------------------------ */
|
||||
/* This just calls the routine shared with Subtract */
|
||||
decNumber * uprv_decNumberAdd(decNumber *res, const decNumber *lhs,
|
||||
U_CAPI decNumber * U_EXPORT2 uprv_decNumberAdd(decNumber *res, const decNumber *lhs,
|
||||
const decNumber *rhs, decContext *set) {
|
||||
uInt status=0; /* accumulator */
|
||||
decAddOp(res, lhs, rhs, set, 0, &status);
|
||||
|
@ -799,7 +799,7 @@ decNumber * uprv_decNumberAdd(decNumber *res, const decNumber *lhs,
|
|||
/* Logical function restrictions apply (see above); a NaN is */
|
||||
/* returned with Invalid_operation if a restriction is violated. */
|
||||
/* ------------------------------------------------------------------ */
|
||||
decNumber * uprv_decNumberAnd(decNumber *res, const decNumber *lhs,
|
||||
U_CAPI decNumber * U_EXPORT2 uprv_decNumberAnd(decNumber *res, const decNumber *lhs,
|
||||
const decNumber *rhs, decContext *set) {
|
||||
const Unit *ua, *ub; /* -> operands */
|
||||
const Unit *msua, *msub; /* -> operand msus */
|
||||
|
@ -867,7 +867,7 @@ decNumber * uprv_decNumberAnd(decNumber *res, const decNumber *lhs,
|
|||
/* */
|
||||
/* C must have space for one digit (or NaN). */
|
||||
/* ------------------------------------------------------------------ */
|
||||
decNumber * uprv_decNumberCompare(decNumber *res, const decNumber *lhs,
|
||||
U_CAPI decNumber * U_EXPORT2 uprv_decNumberCompare(decNumber *res, const decNumber *lhs,
|
||||
const decNumber *rhs, decContext *set) {
|
||||
uInt status=0; /* accumulator */
|
||||
decCompareOp(res, lhs, rhs, set, COMPARE, &status);
|
||||
|
@ -887,7 +887,7 @@ decNumber * uprv_decNumberCompare(decNumber *res, const decNumber *lhs,
|
|||
/* */
|
||||
/* C must have space for one digit (or NaN). */
|
||||
/* ------------------------------------------------------------------ */
|
||||
decNumber * uprv_decNumberCompareSignal(decNumber *res, const decNumber *lhs,
|
||||
U_CAPI decNumber * U_EXPORT2 uprv_decNumberCompareSignal(decNumber *res, const decNumber *lhs,
|
||||
const decNumber *rhs, decContext *set) {
|
||||
uInt status=0; /* accumulator */
|
||||
decCompareOp(res, lhs, rhs, set, COMPSIG, &status);
|
||||
|
@ -908,7 +908,7 @@ decNumber * uprv_decNumberCompareSignal(decNumber *res, const decNumber *lhs,
|
|||
/* C must have space for one digit; the result will always be one of */
|
||||
/* -1, 0, or 1. */
|
||||
/* ------------------------------------------------------------------ */
|
||||
decNumber * uprv_decNumberCompareTotal(decNumber *res, const decNumber *lhs,
|
||||
U_CAPI decNumber * U_EXPORT2 uprv_decNumberCompareTotal(decNumber *res, const decNumber *lhs,
|
||||
const decNumber *rhs, decContext *set) {
|
||||
uInt status=0; /* accumulator */
|
||||
decCompareOp(res, lhs, rhs, set, COMPTOTAL, &status);
|
||||
|
@ -929,7 +929,7 @@ decNumber * uprv_decNumberCompareTotal(decNumber *res, const decNumber *lhs,
|
|||
/* C must have space for one digit; the result will always be one of */
|
||||
/* -1, 0, or 1. */
|
||||
/* ------------------------------------------------------------------ */
|
||||
decNumber * uprv_decNumberCompareTotalMag(decNumber *res, const decNumber *lhs,
|
||||
U_CAPI decNumber * U_EXPORT2 uprv_decNumberCompareTotalMag(decNumber *res, const decNumber *lhs,
|
||||
const decNumber *rhs, decContext *set) {
|
||||
uInt status=0; /* accumulator */
|
||||
uInt needbytes; /* for space calculations */
|
||||
|
@ -994,7 +994,7 @@ decNumber * uprv_decNumberCompareTotalMag(decNumber *res, const decNumber *lhs,
|
|||
/* */
|
||||
/* C must have space for set->digits digits. */
|
||||
/* ------------------------------------------------------------------ */
|
||||
decNumber * uprv_decNumberDivide(decNumber *res, const decNumber *lhs,
|
||||
U_CAPI decNumber * U_EXPORT2 uprv_decNumberDivide(decNumber *res, const decNumber *lhs,
|
||||
const decNumber *rhs, decContext *set) {
|
||||
uInt status=0; /* accumulator */
|
||||
decDivideOp(res, lhs, rhs, set, DIVIDE, &status);
|
||||
|
@ -1017,7 +1017,7 @@ decNumber * uprv_decNumberDivide(decNumber *res, const decNumber *lhs,
|
|||
/* */
|
||||
/* C must have space for set->digits digits. */
|
||||
/* ------------------------------------------------------------------ */
|
||||
decNumber * uprv_decNumberDivideInteger(decNumber *res, const decNumber *lhs,
|
||||
U_CAPI decNumber * U_EXPORT2 uprv_decNumberDivideInteger(decNumber *res, const decNumber *lhs,
|
||||
const decNumber *rhs, decContext *set) {
|
||||
uInt status=0; /* accumulator */
|
||||
decDivideOp(res, lhs, rhs, set, DIVIDEINT, &status);
|
||||
|
@ -1050,7 +1050,7 @@ decNumber * uprv_decNumberDivideInteger(decNumber *res, const decNumber *lhs,
|
|||
/* (double) range needed by Ln (which has to be able to calculate */
|
||||
/* exp(-a) where a can be the tiniest number (Ntiny). */
|
||||
/* ------------------------------------------------------------------ */
|
||||
decNumber * uprv_decNumberExp(decNumber *res, const decNumber *rhs,
|
||||
U_CAPI decNumber * U_EXPORT2 uprv_decNumberExp(decNumber *res, const decNumber *rhs,
|
||||
decContext *set) {
|
||||
uInt status=0; /* accumulator */
|
||||
#if DECSUBSET
|
||||
|
@ -1106,7 +1106,7 @@ decNumber * uprv_decNumberExp(decNumber *res, const decNumber *rhs,
|
|||
/* */
|
||||
/* C must have space for set->digits digits. */
|
||||
/* ------------------------------------------------------------------ */
|
||||
decNumber * uprv_decNumberFMA(decNumber *res, const decNumber *lhs,
|
||||
U_CAPI decNumber * U_EXPORT2 uprv_decNumberFMA(decNumber *res, const decNumber *lhs,
|
||||
const decNumber *rhs, const decNumber *fhs,
|
||||
decContext *set) {
|
||||
uInt status=0; /* accumulator */
|
||||
|
@ -1197,7 +1197,7 @@ decNumber * uprv_decNumberFMA(decNumber *res, const decNumber *lhs,
|
|||
/* Logical function restrictions apply (see above); a NaN is */
|
||||
/* returned with Invalid_operation if a restriction is violated. */
|
||||
/* ------------------------------------------------------------------ */
|
||||
decNumber * uprv_decNumberInvert(decNumber *res, const decNumber *rhs,
|
||||
U_CAPI decNumber * U_EXPORT2 uprv_decNumberInvert(decNumber *res, const decNumber *rhs,
|
||||
decContext *set) {
|
||||
const Unit *ua, *msua; /* -> operand and its msu */
|
||||
Unit *uc, *msuc; /* -> result and its msu */
|
||||
|
@ -1270,7 +1270,7 @@ decNumber * uprv_decNumberInvert(decNumber *res, const decNumber *rhs,
|
|||
/* (+11) range needed by Ln, Log10, etc. (which may have to be able */
|
||||
/* to calculate at p+e+2). */
|
||||
/* ------------------------------------------------------------------ */
|
||||
decNumber * uprv_decNumberLn(decNumber *res, const decNumber *rhs,
|
||||
U_CAPI decNumber * U_EXPORT2 uprv_decNumberLn(decNumber *res, const decNumber *rhs,
|
||||
decContext *set) {
|
||||
uInt status=0; /* accumulator */
|
||||
#if DECSUBSET
|
||||
|
@ -1336,7 +1336,7 @@ decNumber * uprv_decNumberLn(decNumber *res, const decNumber *rhs,
|
|||
/* A=1 exactly -> 0 (Exact) */
|
||||
/* NaNs are propagated as usual */
|
||||
/* ------------------------------------------------------------------ */
|
||||
decNumber * uprv_decNumberLogB(decNumber *res, const decNumber *rhs,
|
||||
U_CAPI decNumber * U_EXPORT2 uprv_decNumberLogB(decNumber *res, const decNumber *rhs,
|
||||
decContext *set) {
|
||||
uInt status=0; /* accumulator */
|
||||
|
||||
|
@ -1392,7 +1392,7 @@ decNumber * uprv_decNumberLogB(decNumber *res, const decNumber *rhs,
|
|||
/* fastpath in decLnOp. The final division is done to the requested */
|
||||
/* precision. */
|
||||
/* ------------------------------------------------------------------ */
|
||||
decNumber * uprv_decNumberLog10(decNumber *res, const decNumber *rhs,
|
||||
U_CAPI decNumber * U_EXPORT2 uprv_decNumberLog10(decNumber *res, const decNumber *rhs,
|
||||
decContext *set) {
|
||||
uInt status=0, ignore=0; /* status accumulators */
|
||||
uInt needbytes; /* for space calculations */
|
||||
|
@ -1540,7 +1540,7 @@ decNumber * uprv_decNumberLog10(decNumber *res, const decNumber *rhs,
|
|||
/* */
|
||||
/* C must have space for set->digits digits. */
|
||||
/* ------------------------------------------------------------------ */
|
||||
decNumber * uprv_decNumberMax(decNumber *res, const decNumber *lhs,
|
||||
U_CAPI decNumber * U_EXPORT2 uprv_decNumberMax(decNumber *res, const decNumber *lhs,
|
||||
const decNumber *rhs, decContext *set) {
|
||||
uInt status=0; /* accumulator */
|
||||
decCompareOp(res, lhs, rhs, set, COMPMAX, &status);
|
||||
|
@ -1563,7 +1563,7 @@ decNumber * uprv_decNumberMax(decNumber *res, const decNumber *lhs,
|
|||
/* */
|
||||
/* C must have space for set->digits digits. */
|
||||
/* ------------------------------------------------------------------ */
|
||||
decNumber * uprv_decNumberMaxMag(decNumber *res, const decNumber *lhs,
|
||||
U_CAPI decNumber * U_EXPORT2 uprv_decNumberMaxMag(decNumber *res, const decNumber *lhs,
|
||||
const decNumber *rhs, decContext *set) {
|
||||
uInt status=0; /* accumulator */
|
||||
decCompareOp(res, lhs, rhs, set, COMPMAXMAG, &status);
|
||||
|
@ -1586,7 +1586,7 @@ decNumber * uprv_decNumberMaxMag(decNumber *res, const decNumber *lhs,
|
|||
/* */
|
||||
/* C must have space for set->digits digits. */
|
||||
/* ------------------------------------------------------------------ */
|
||||
decNumber * uprv_decNumberMin(decNumber *res, const decNumber *lhs,
|
||||
U_CAPI decNumber * U_EXPORT2 uprv_decNumberMin(decNumber *res, const decNumber *lhs,
|
||||
const decNumber *rhs, decContext *set) {
|
||||
uInt status=0; /* accumulator */
|
||||
decCompareOp(res, lhs, rhs, set, COMPMIN, &status);
|
||||
|
@ -1609,7 +1609,7 @@ decNumber * uprv_decNumberMin(decNumber *res, const decNumber *lhs,
|
|||
/* */
|
||||
/* C must have space for set->digits digits. */
|
||||
/* ------------------------------------------------------------------ */
|
||||
decNumber * uprv_decNumberMinMag(decNumber *res, const decNumber *lhs,
|
||||
U_CAPI decNumber * U_EXPORT2 uprv_decNumberMinMag(decNumber *res, const decNumber *lhs,
|
||||
const decNumber *rhs, decContext *set) {
|
||||
uInt status=0; /* accumulator */
|
||||
decCompareOp(res, lhs, rhs, set, COMPMINMAG, &status);
|
||||
|
@ -1634,7 +1634,7 @@ decNumber * uprv_decNumberMinMag(decNumber *res, const decNumber *lhs,
|
|||
/* ------------------------------------------------------------------ */
|
||||
/* Simply use AddOp for the subtract, which will do the necessary. */
|
||||
/* ------------------------------------------------------------------ */
|
||||
decNumber * uprv_decNumberMinus(decNumber *res, const decNumber *rhs,
|
||||
U_CAPI decNumber * U_EXPORT2 uprv_decNumberMinus(decNumber *res, const decNumber *rhs,
|
||||
decContext *set) {
|
||||
decNumber dzero;
|
||||
uInt status=0; /* accumulator */
|
||||
|
@ -1664,7 +1664,7 @@ decNumber * uprv_decNumberMinus(decNumber *res, const decNumber *rhs,
|
|||
/* */
|
||||
/* This is a generalization of 754 NextDown. */
|
||||
/* ------------------------------------------------------------------ */
|
||||
decNumber * uprv_decNumberNextMinus(decNumber *res, const decNumber *rhs,
|
||||
U_CAPI decNumber * U_EXPORT2 uprv_decNumberNextMinus(decNumber *res, const decNumber *rhs,
|
||||
decContext *set) {
|
||||
decNumber dtiny; /* constant */
|
||||
decContext workset=*set; /* work */
|
||||
|
@ -1700,7 +1700,7 @@ decNumber * uprv_decNumberNextMinus(decNumber *res, const decNumber *rhs,
|
|||
/* */
|
||||
/* This is a generalization of 754 NextUp. */
|
||||
/* ------------------------------------------------------------------ */
|
||||
decNumber * uprv_decNumberNextPlus(decNumber *res, const decNumber *rhs,
|
||||
U_CAPI decNumber * U_EXPORT2 uprv_decNumberNextPlus(decNumber *res, const decNumber *rhs,
|
||||
decContext *set) {
|
||||
decNumber dtiny; /* constant */
|
||||
decContext workset=*set; /* work */
|
||||
|
@ -1740,7 +1740,7 @@ decNumber * uprv_decNumberNextPlus(decNumber *res, const decNumber *rhs,
|
|||
/* */
|
||||
/* This is a generalization of 754-1985 NextAfter. */
|
||||
/* ------------------------------------------------------------------ */
|
||||
decNumber * uprv_decNumberNextToward(decNumber *res, const decNumber *lhs,
|
||||
U_CAPI decNumber * U_EXPORT2 uprv_decNumberNextToward(decNumber *res, const decNumber *lhs,
|
||||
const decNumber *rhs, decContext *set) {
|
||||
decNumber dtiny; /* constant */
|
||||
decContext workset=*set; /* work */
|
||||
|
@ -1808,7 +1808,7 @@ decNumber * uprv_decNumberNextToward(decNumber *res, const decNumber *lhs,
|
|||
/* Logical function restrictions apply (see above); a NaN is */
|
||||
/* returned with Invalid_operation if a restriction is violated. */
|
||||
/* ------------------------------------------------------------------ */
|
||||
decNumber * uprv_decNumberOr(decNumber *res, const decNumber *lhs,
|
||||
U_CAPI decNumber * U_EXPORT2 uprv_decNumberOr(decNumber *res, const decNumber *lhs,
|
||||
const decNumber *rhs, decContext *set) {
|
||||
const Unit *ua, *ub; /* -> operands */
|
||||
const Unit *msua, *msub; /* -> operand msus */
|
||||
|
@ -1878,7 +1878,7 @@ decNumber * uprv_decNumberOr(decNumber *res, const decNumber *lhs,
|
|||
/* Performance is a concern here, as this routine is often used to */
|
||||
/* check operands and apply rounding and overflow/underflow testing. */
|
||||
/* ------------------------------------------------------------------ */
|
||||
decNumber * uprv_decNumberPlus(decNumber *res, const decNumber *rhs,
|
||||
U_CAPI decNumber * U_EXPORT2 uprv_decNumberPlus(decNumber *res, const decNumber *rhs,
|
||||
decContext *set) {
|
||||
decNumber dzero;
|
||||
uInt status=0; /* accumulator */
|
||||
|
@ -1908,7 +1908,7 @@ decNumber * uprv_decNumberPlus(decNumber *res, const decNumber *rhs,
|
|||
/* */
|
||||
/* C must have space for set->digits digits. */
|
||||
/* ------------------------------------------------------------------ */
|
||||
decNumber * uprv_decNumberMultiply(decNumber *res, const decNumber *lhs,
|
||||
U_CAPI decNumber * U_EXPORT2 uprv_decNumberMultiply(decNumber *res, const decNumber *lhs,
|
||||
const decNumber *rhs, decContext *set) {
|
||||
uInt status=0; /* accumulator */
|
||||
decMultiplyOp(res, lhs, rhs, set, &status);
|
||||
|
@ -1945,7 +1945,7 @@ decNumber * uprv_decNumberMultiply(decNumber *res, const decNumber *lhs,
|
|||
/* almost always be correctly rounded, but may be up to 1 ulp in */
|
||||
/* error in rare cases. */
|
||||
/* ------------------------------------------------------------------ */
|
||||
decNumber * uprv_decNumberPower(decNumber *res, const decNumber *lhs,
|
||||
U_CAPI decNumber * U_EXPORT2 uprv_decNumberPower(decNumber *res, const decNumber *lhs,
|
||||
const decNumber *rhs, decContext *set) {
|
||||
#if DECSUBSET
|
||||
decNumber *alloclhs=NULL; /* non-NULL if rounded lhs allocated */
|
||||
|
@ -2290,7 +2290,7 @@ decNumber * uprv_decNumberPower(decNumber *res, const decNumber *lhs,
|
|||
/* Unless there is an error or the result is infinite, the exponent */
|
||||
/* after the operation is guaranteed to be equal to that of B. */
|
||||
/* ------------------------------------------------------------------ */
|
||||
decNumber * uprv_decNumberQuantize(decNumber *res, const decNumber *lhs,
|
||||
U_CAPI decNumber * U_EXPORT2 uprv_decNumberQuantize(decNumber *res, const decNumber *lhs,
|
||||
const decNumber *rhs, decContext *set) {
|
||||
uInt status=0; /* accumulator */
|
||||
decQuantizeOp(res, lhs, rhs, set, 1, &status);
|
||||
|
@ -2310,12 +2310,12 @@ decNumber * uprv_decNumberQuantize(decNumber *res, const decNumber *lhs,
|
|||
/* C must have space for set->digits digits. */
|
||||
/* ------------------------------------------------------------------ */
|
||||
/* Previously known as Normalize */
|
||||
decNumber * uprv_decNumberNormalize(decNumber *res, const decNumber *rhs,
|
||||
U_CAPI decNumber * U_EXPORT2 uprv_decNumberNormalize(decNumber *res, const decNumber *rhs,
|
||||
decContext *set) {
|
||||
return uprv_decNumberReduce(res, rhs, set);
|
||||
} /* decNumberNormalize */
|
||||
|
||||
decNumber * uprv_decNumberReduce(decNumber *res, const decNumber *rhs,
|
||||
U_CAPI decNumber * U_EXPORT2 uprv_decNumberReduce(decNumber *res, const decNumber *rhs,
|
||||
decContext *set) {
|
||||
#if DECSUBSET
|
||||
decNumber *allocrhs=NULL; /* non-NULL if rounded rhs allocated */
|
||||
|
@ -2379,7 +2379,7 @@ decNumber * uprv_decNumberReduce(decNumber *res, const decNumber *rhs,
|
|||
/* Unless there is an error or the result is infinite, the exponent */
|
||||
/* after the operation is guaranteed to be equal to B. */
|
||||
/* ------------------------------------------------------------------ */
|
||||
decNumber * uprv_decNumberRescale(decNumber *res, const decNumber *lhs,
|
||||
U_CAPI decNumber * U_EXPORT2 uprv_decNumberRescale(decNumber *res, const decNumber *lhs,
|
||||
const decNumber *rhs, decContext *set) {
|
||||
uInt status=0; /* accumulator */
|
||||
decQuantizeOp(res, lhs, rhs, set, 0, &status);
|
||||
|
@ -2399,7 +2399,7 @@ decNumber * uprv_decNumberRescale(decNumber *res, const decNumber *lhs,
|
|||
/* */
|
||||
/* C must have space for set->digits digits. */
|
||||
/* ------------------------------------------------------------------ */
|
||||
decNumber * uprv_decNumberRemainder(decNumber *res, const decNumber *lhs,
|
||||
U_CAPI decNumber * U_EXPORT2 uprv_decNumberRemainder(decNumber *res, const decNumber *lhs,
|
||||
const decNumber *rhs, decContext *set) {
|
||||
uInt status=0; /* accumulator */
|
||||
decDivideOp(res, lhs, rhs, set, REMAINDER, &status);
|
||||
|
@ -2422,7 +2422,7 @@ decNumber * uprv_decNumberRemainder(decNumber *res, const decNumber *lhs,
|
|||
/* */
|
||||
/* C must have space for set->digits digits. */
|
||||
/* ------------------------------------------------------------------ */
|
||||
decNumber * uprv_decNumberRemainderNear(decNumber *res, const decNumber *lhs,
|
||||
U_CAPI decNumber * U_EXPORT2 uprv_decNumberRemainderNear(decNumber *res, const decNumber *lhs,
|
||||
const decNumber *rhs, decContext *set) {
|
||||
uInt status=0; /* accumulator */
|
||||
decDivideOp(res, lhs, rhs, set, REMNEAR, &status);
|
||||
|
@ -2458,7 +2458,7 @@ decNumber * uprv_decNumberRemainderNear(decNumber *res, const decNumber *lhs,
|
|||
/* B must be valid). No status is set unless B is invalid or an */
|
||||
/* operand is an sNaN. */
|
||||
/* ------------------------------------------------------------------ */
|
||||
decNumber * uprv_decNumberRotate(decNumber *res, const decNumber *lhs,
|
||||
U_CAPI decNumber * U_EXPORT2 uprv_decNumberRotate(decNumber *res, const decNumber *lhs,
|
||||
const decNumber *rhs, decContext *set) {
|
||||
uInt status=0; /* accumulator */
|
||||
Int rotate; /* rhs as an Int */
|
||||
|
@ -2579,7 +2579,7 @@ decNumber * uprv_decNumberRotate(decNumber *res, const decNumber *lhs,
|
|||
/* */
|
||||
/* No errors are possible and no context is needed. */
|
||||
/* ------------------------------------------------------------------ */
|
||||
decNumber * uprv_decNumberSameQuantum(decNumber *res, const decNumber *lhs,
|
||||
U_CAPI decNumber * U_EXPORT2 uprv_decNumberSameQuantum(decNumber *res, const decNumber *lhs,
|
||||
const decNumber *rhs) {
|
||||
Unit ret=0; /* return value */
|
||||
|
||||
|
@ -2614,7 +2614,7 @@ decNumber * uprv_decNumberSameQuantum(decNumber *res, const decNumber *lhs,
|
|||
/* */
|
||||
/* The result may underflow or overflow. */
|
||||
/* ------------------------------------------------------------------ */
|
||||
decNumber * uprv_decNumberScaleB(decNumber *res, const decNumber *lhs,
|
||||
U_CAPI decNumber * U_EXPORT2 uprv_decNumberScaleB(decNumber *res, const decNumber *lhs,
|
||||
const decNumber *rhs, decContext *set) {
|
||||
Int reqexp; /* requested exponent change [B] */
|
||||
uInt status=0; /* accumulator */
|
||||
|
@ -2671,7 +2671,7 @@ decNumber * uprv_decNumberScaleB(decNumber *res, const decNumber *lhs,
|
|||
/* B must be valid). No status is set unless B is invalid or an */
|
||||
/* operand is an sNaN. */
|
||||
/* ------------------------------------------------------------------ */
|
||||
decNumber * uprv_decNumberShift(decNumber *res, const decNumber *lhs,
|
||||
U_CAPI decNumber * U_EXPORT2 uprv_decNumberShift(decNumber *res, const decNumber *lhs,
|
||||
const decNumber *rhs, decContext *set) {
|
||||
uInt status=0; /* accumulator */
|
||||
Int shift; /* rhs as an Int */
|
||||
|
@ -2800,7 +2800,7 @@ decNumber * uprv_decNumberShift(decNumber *res, const decNumber *lhs,
|
|||
/* result setexp(approx, e div 2) % fix exponent */
|
||||
/* end sqrt */
|
||||
/* ------------------------------------------------------------------ */
|
||||
decNumber * uprv_decNumberSquareRoot(decNumber *res, const decNumber *rhs,
|
||||
U_CAPI decNumber * U_EXPORT2 uprv_decNumberSquareRoot(decNumber *res, const decNumber *rhs,
|
||||
decContext *set) {
|
||||
decContext workset, approxset; /* work contexts */
|
||||
decNumber dzero; /* used for constant zero */
|
||||
|
@ -3142,7 +3142,7 @@ decNumber * uprv_decNumberSquareRoot(decNumber *res, const decNumber *rhs,
|
|||
/* */
|
||||
/* C must have space for set->digits digits. */
|
||||
/* ------------------------------------------------------------------ */
|
||||
decNumber * uprv_decNumberSubtract(decNumber *res, const decNumber *lhs,
|
||||
U_CAPI decNumber * U_EXPORT2 uprv_decNumberSubtract(decNumber *res, const decNumber *lhs,
|
||||
const decNumber *rhs, decContext *set) {
|
||||
uInt status=0; /* accumulator */
|
||||
|
||||
|
@ -3175,7 +3175,7 @@ decNumber * uprv_decNumberSubtract(decNumber *res, const decNumber *lhs,
|
|||
/* Inexact if the result differs numerically from rhs; the other */
|
||||
/* never signals Inexact. */
|
||||
/* ------------------------------------------------------------------ */
|
||||
decNumber * uprv_decNumberToIntegralExact(decNumber *res, const decNumber *rhs,
|
||||
U_CAPI decNumber * U_EXPORT2 uprv_decNumberToIntegralExact(decNumber *res, const decNumber *rhs,
|
||||
decContext *set) {
|
||||
decNumber dn;
|
||||
decContext workset; /* working context */
|
||||
|
@ -3205,7 +3205,7 @@ decNumber * uprv_decNumberToIntegralExact(decNumber *res, const decNumber *rhs,
|
|||
return res;
|
||||
} /* decNumberToIntegralExact */
|
||||
|
||||
decNumber * uprv_decNumberToIntegralValue(decNumber *res, const decNumber *rhs,
|
||||
U_CAPI decNumber * U_EXPORT2 uprv_decNumberToIntegralValue(decNumber *res, const decNumber *rhs,
|
||||
decContext *set) {
|
||||
decContext workset=*set; /* working context */
|
||||
workset.traps=0; /* no traps */
|
||||
|
@ -3231,7 +3231,7 @@ decNumber * uprv_decNumberToIntegralValue(decNumber *res, const decNumber *rhs,
|
|||
/* Logical function restrictions apply (see above); a NaN is */
|
||||
/* returned with Invalid_operation if a restriction is violated. */
|
||||
/* ------------------------------------------------------------------ */
|
||||
decNumber * uprv_decNumberXor(decNumber *res, const decNumber *lhs,
|
||||
U_CAPI decNumber * U_EXPORT2 uprv_decNumberXor(decNumber *res, const decNumber *lhs,
|
||||
const decNumber *rhs, decContext *set) {
|
||||
const Unit *ua, *ub; /* -> operands */
|
||||
const Unit *msua, *msub; /* -> operand msus */
|
||||
|
@ -3349,7 +3349,7 @@ const char *uprv_decNumberClassToString(enum decClass eclass) {
|
|||
/* All fields are updated as required. This is a utility operation, */
|
||||
/* so special values are unchanged and no error is possible. */
|
||||
/* ------------------------------------------------------------------ */
|
||||
decNumber * uprv_decNumberCopy(decNumber *dest, const decNumber *src) {
|
||||
U_CAPI decNumber * U_EXPORT2 uprv_decNumberCopy(decNumber *dest, const decNumber *src) {
|
||||
|
||||
#if DECCHECK
|
||||
if (src==NULL) return uprv_decNumberZero(dest);
|
||||
|
@ -3389,7 +3389,7 @@ decNumber * uprv_decNumberCopy(decNumber *dest, const decNumber *src) {
|
|||
/* No exception or error can occur; this is a quiet bitwise operation.*/
|
||||
/* See also decNumberAbs for a checking version of this. */
|
||||
/* ------------------------------------------------------------------ */
|
||||
decNumber * uprv_decNumberCopyAbs(decNumber *res, const decNumber *rhs) {
|
||||
U_CAPI decNumber * U_EXPORT2 uprv_decNumberCopyAbs(decNumber *res, const decNumber *rhs) {
|
||||
#if DECCHECK
|
||||
if (decCheckOperands(res, DECUNUSED, rhs, DECUNCONT)) return res;
|
||||
#endif
|
||||
|
@ -3410,7 +3410,7 @@ decNumber * uprv_decNumberCopyAbs(decNumber *res, const decNumber *rhs) {
|
|||
/* No exception or error can occur; this is a quiet bitwise operation.*/
|
||||
/* See also decNumberMinus for a checking version of this. */
|
||||
/* ------------------------------------------------------------------ */
|
||||
decNumber * uprv_decNumberCopyNegate(decNumber *res, const decNumber *rhs) {
|
||||
U_CAPI decNumber * U_EXPORT2 uprv_decNumberCopyNegate(decNumber *res, const decNumber *rhs) {
|
||||
#if DECCHECK
|
||||
if (decCheckOperands(res, DECUNUSED, rhs, DECUNCONT)) return res;
|
||||
#endif
|
||||
|
@ -3431,7 +3431,7 @@ decNumber * uprv_decNumberCopyNegate(decNumber *res, const decNumber *rhs) {
|
|||
/* C must have space for set->digits digits. */
|
||||
/* No exception or error can occur; this is a quiet bitwise operation.*/
|
||||
/* ------------------------------------------------------------------ */
|
||||
decNumber * uprv_decNumberCopySign(decNumber *res, const decNumber *lhs,
|
||||
U_CAPI decNumber * U_EXPORT2 uprv_decNumberCopySign(decNumber *res, const decNumber *lhs,
|
||||
const decNumber *rhs) {
|
||||
uByte sign; /* rhs sign */
|
||||
#if DECCHECK
|
||||
|
@ -3454,7 +3454,7 @@ decNumber * uprv_decNumberCopySign(decNumber *res, const decNumber *lhs,
|
|||
/* bcd must have at least dn->digits bytes. No error is possible; if */
|
||||
/* dn is a NaN or Infinite, digits must be 1 and the coefficient 0. */
|
||||
/* ------------------------------------------------------------------ */
|
||||
uByte * uprv_decNumberGetBCD(const decNumber *dn, uByte *bcd) {
|
||||
U_CAPI uByte * U_EXPORT2 uprv_decNumberGetBCD(const decNumber *dn, uByte *bcd) {
|
||||
uByte *ub=bcd+dn->digits-1; /* -> lsd */
|
||||
const Unit *up=dn->lsu; /* Unit pointer, -> lsu */
|
||||
|
||||
|
@ -3488,7 +3488,7 @@ uByte * uprv_decNumberGetBCD(const decNumber *dn, uByte *bcd) {
|
|||
/* if dn is a NaN, or Infinite, or is to become a zero, n must be 1 */
|
||||
/* and bcd[0] zero. */
|
||||
/* ------------------------------------------------------------------ */
|
||||
decNumber * uprv_decNumberSetBCD(decNumber *dn, const uByte *bcd, uInt n) {
|
||||
U_CAPI decNumber * U_EXPORT2 uprv_decNumberSetBCD(decNumber *dn, const uByte *bcd, uInt n) {
|
||||
Unit *up=dn->lsu+D2U(dn->digits)-1; /* -> msu [target pointer] */
|
||||
const uByte *ub=bcd; /* -> source msd */
|
||||
|
||||
|
@ -3557,7 +3557,7 @@ Int uprv_decNumberIsSubnormal(const decNumber *dn, decContext *set) {
|
|||
/* so special values are unchanged and no error is possible. The */
|
||||
/* zeros are removed unconditionally. */
|
||||
/* ------------------------------------------------------------------ */
|
||||
decNumber * uprv_decNumberTrim(decNumber *dn) {
|
||||
U_CAPI decNumber * U_EXPORT2 uprv_decNumberTrim(decNumber *dn) {
|
||||
Int dropped; /* work */
|
||||
decContext set; /* .. */
|
||||
#if DECCHECK
|
||||
|
@ -3585,7 +3585,7 @@ const char * uprv_decNumberVersion(void) {
|
|||
/* No error is possible. */
|
||||
/* ------------------------------------------------------------------ */
|
||||
/* Memset is not used as it is much slower in some environments. */
|
||||
decNumber * uprv_decNumberZero(decNumber *dn) {
|
||||
U_CAPI decNumber * U_EXPORT2 uprv_decNumberZero(decNumber *dn) {
|
||||
|
||||
#if DECCHECK
|
||||
if (decCheckOperands(dn, DECUNUSED, DECUNUSED, DECUNCONT)) return dn;
|
||||
|
@ -6001,7 +6001,7 @@ static decNumber * decQuantizeOp(decNumber *res, const decNumber *lhs,
|
|||
/* The emphasis here is on speed for common cases, and avoiding */
|
||||
/* coefficient comparison if possible. */
|
||||
/* ------------------------------------------------------------------ */
|
||||
decNumber * decCompareOp(decNumber *res, const decNumber *lhs,
|
||||
static decNumber * decCompareOp(decNumber *res, const decNumber *lhs,
|
||||
const decNumber *rhs, decContext *set,
|
||||
Flag op, uInt *status) {
|
||||
#if DECSUBSET
|
||||
|
|
|
@ -51,7 +51,10 @@
|
|||
/* constant. This must not be changed without recompiling the */
|
||||
/* decNumber library modules. */
|
||||
|
||||
#define DECDPUN 3 /* DECimal Digits Per UNit [must be >0 */
|
||||
/* For ICU, use one digit per byte, to make it easier to emulate the
|
||||
* old DigitList interface on top of a decNumber
|
||||
*/
|
||||
#define DECDPUN 1 /* DECimal Digits Per UNit [must be >0 */
|
||||
/* and <10; 3 or powers of 2 are best]. */
|
||||
|
||||
/* DECNUMDIGITS is the default number of digits that can be held in */
|
||||
|
@ -107,74 +110,74 @@
|
|||
/* decNumber public functions and macros */
|
||||
/* ---------------------------------------------------------------- */
|
||||
/* Conversions */
|
||||
decNumber * uprv_decNumberFromInt32(decNumber *, int32_t);
|
||||
decNumber * uprv_decNumberFromUInt32(decNumber *, uint32_t);
|
||||
decNumber * uprv_decNumberFromString(decNumber *, const char *, decContext *);
|
||||
char * uprv_decNumberToString(const decNumber *, char *);
|
||||
char * uprv_decNumberToEngString(const decNumber *, char *);
|
||||
uint32_t uprv_decNumberToUInt32(const decNumber *, decContext *);
|
||||
int32_t uprv_decNumberToInt32(const decNumber *, decContext *);
|
||||
uint8_t * uprv_decNumberGetBCD(const decNumber *, uint8_t *);
|
||||
decNumber * uprv_decNumberSetBCD(decNumber *, const uint8_t *, uint32_t);
|
||||
U_INTERNAL decNumber * U_EXPORT2 uprv_decNumberFromInt32(decNumber *, int32_t);
|
||||
U_INTERNAL decNumber * U_EXPORT2 uprv_decNumberFromUInt32(decNumber *, uint32_t);
|
||||
U_INTERNAL decNumber * U_EXPORT2 uprv_decNumberFromString(decNumber *, const char *, decContext *);
|
||||
U_INTERNAL char * U_EXPORT2 uprv_decNumberToString(const decNumber *, char *);
|
||||
U_INTERNAL char * U_EXPORT2 uprv_decNumberToEngString(const decNumber *, char *);
|
||||
U_INTERNAL uint32_t U_EXPORT2 uprv_decNumberToUInt32(const decNumber *, decContext *);
|
||||
U_INTERNAL int32_t U_EXPORT2 uprv_decNumberToInt32(const decNumber *, decContext *);
|
||||
U_INTERNAL uint8_t * U_EXPORT2 uprv_decNumberGetBCD(const decNumber *, uint8_t *);
|
||||
U_INTERNAL decNumber * U_EXPORT2 uprv_decNumberSetBCD(decNumber *, const uint8_t *, uint32_t);
|
||||
|
||||
/* Operators and elementary functions */
|
||||
decNumber * uprv_decNumberAbs(decNumber *, const decNumber *, decContext *);
|
||||
decNumber * uprv_decNumberAdd(decNumber *, const decNumber *, const decNumber *, decContext *);
|
||||
decNumber * uprv_decNumberAnd(decNumber *, const decNumber *, const decNumber *, decContext *);
|
||||
decNumber * uprv_decNumberCompare(decNumber *, const decNumber *, const decNumber *, decContext *);
|
||||
decNumber * uprv_decNumberCompareSignal(decNumber *, const decNumber *, const decNumber *, decContext *);
|
||||
decNumber * uprv_decNumberCompareTotal(decNumber *, const decNumber *, const decNumber *, decContext *);
|
||||
decNumber * uprv_decNumberCompareTotalMag(decNumber *, const decNumber *, const decNumber *, decContext *);
|
||||
decNumber * uprv_decNumberDivide(decNumber *, const decNumber *, const decNumber *, decContext *);
|
||||
decNumber * uprv_decNumberDivideInteger(decNumber *, const decNumber *, const decNumber *, decContext *);
|
||||
decNumber * uprv_decNumberExp(decNumber *, const decNumber *, decContext *);
|
||||
decNumber * uprv_decNumberFMA(decNumber *, const decNumber *, const decNumber *, const decNumber *, decContext *);
|
||||
decNumber * uprv_decNumberInvert(decNumber *, const decNumber *, decContext *);
|
||||
decNumber * uprv_decNumberLn(decNumber *, const decNumber *, decContext *);
|
||||
decNumber * uprv_decNumberLogB(decNumber *, const decNumber *, decContext *);
|
||||
decNumber * uprv_decNumberLog10(decNumber *, const decNumber *, decContext *);
|
||||
decNumber * uprv_decNumberMax(decNumber *, const decNumber *, const decNumber *, decContext *);
|
||||
decNumber * uprv_decNumberMaxMag(decNumber *, const decNumber *, const decNumber *, decContext *);
|
||||
decNumber * uprv_decNumberMin(decNumber *, const decNumber *, const decNumber *, decContext *);
|
||||
decNumber * uprv_decNumberMinMag(decNumber *, const decNumber *, const decNumber *, decContext *);
|
||||
decNumber * uprv_decNumberMinus(decNumber *, const decNumber *, decContext *);
|
||||
decNumber * uprv_decNumberMultiply(decNumber *, const decNumber *, const decNumber *, decContext *);
|
||||
decNumber * uprv_decNumberNormalize(decNumber *, const decNumber *, decContext *);
|
||||
decNumber * uprv_decNumberOr(decNumber *, const decNumber *, const decNumber *, decContext *);
|
||||
decNumber * uprv_decNumberPlus(decNumber *, const decNumber *, decContext *);
|
||||
decNumber * uprv_decNumberPower(decNumber *, const decNumber *, const decNumber *, decContext *);
|
||||
decNumber * uprv_decNumberQuantize(decNumber *, const decNumber *, const decNumber *, decContext *);
|
||||
decNumber * uprv_decNumberReduce(decNumber *, const decNumber *, decContext *);
|
||||
decNumber * uprv_decNumberRemainder(decNumber *, const decNumber *, const decNumber *, decContext *);
|
||||
decNumber * uprv_decNumberRemainderNear(decNumber *, const decNumber *, const decNumber *, decContext *);
|
||||
decNumber * uprv_decNumberRescale(decNumber *, const decNumber *, const decNumber *, decContext *);
|
||||
decNumber * uprv_decNumberRotate(decNumber *, const decNumber *, const decNumber *, decContext *);
|
||||
decNumber * uprv_decNumberSameQuantum(decNumber *, const decNumber *, const decNumber *);
|
||||
decNumber * uprv_decNumberScaleB(decNumber *, const decNumber *, const decNumber *, decContext *);
|
||||
decNumber * uprv_decNumberShift(decNumber *, const decNumber *, const decNumber *, decContext *);
|
||||
decNumber * uprv_decNumberSquareRoot(decNumber *, const decNumber *, decContext *);
|
||||
decNumber * uprv_decNumberSubtract(decNumber *, const decNumber *, const decNumber *, decContext *);
|
||||
decNumber * uprv_decNumberToIntegralExact(decNumber *, const decNumber *, decContext *);
|
||||
decNumber * uprv_decNumberToIntegralValue(decNumber *, const decNumber *, decContext *);
|
||||
decNumber * uprv_decNumberXor(decNumber *, const decNumber *, const decNumber *, decContext *);
|
||||
U_INTERNAL decNumber * U_EXPORT2 uprv_decNumberAbs(decNumber *, const decNumber *, decContext *);
|
||||
U_INTERNAL decNumber * U_EXPORT2 uprv_decNumberAdd(decNumber *, const decNumber *, const decNumber *, decContext *);
|
||||
U_INTERNAL decNumber * U_EXPORT2 uprv_decNumberAnd(decNumber *, const decNumber *, const decNumber *, decContext *);
|
||||
U_INTERNAL decNumber * U_EXPORT2 uprv_decNumberCompare(decNumber *, const decNumber *, const decNumber *, decContext *);
|
||||
U_INTERNAL decNumber * U_EXPORT2 uprv_decNumberCompareSignal(decNumber *, const decNumber *, const decNumber *, decContext *);
|
||||
U_INTERNAL decNumber * U_EXPORT2 uprv_decNumberCompareTotal(decNumber *, const decNumber *, const decNumber *, decContext *);
|
||||
U_INTERNAL decNumber * U_EXPORT2 uprv_decNumberCompareTotalMag(decNumber *, const decNumber *, const decNumber *, decContext *);
|
||||
U_INTERNAL decNumber * U_EXPORT2 uprv_decNumberDivide(decNumber *, const decNumber *, const decNumber *, decContext *);
|
||||
U_INTERNAL decNumber * U_EXPORT2 uprv_decNumberDivideInteger(decNumber *, const decNumber *, const decNumber *, decContext *);
|
||||
U_INTERNAL decNumber * U_EXPORT2 uprv_decNumberExp(decNumber *, const decNumber *, decContext *);
|
||||
U_INTERNAL decNumber * U_EXPORT2 uprv_decNumberFMA(decNumber *, const decNumber *, const decNumber *, const decNumber *, decContext *);
|
||||
U_INTERNAL decNumber * U_EXPORT2 uprv_decNumberInvert(decNumber *, const decNumber *, decContext *);
|
||||
U_INTERNAL decNumber * U_EXPORT2 uprv_decNumberLn(decNumber *, const decNumber *, decContext *);
|
||||
U_INTERNAL decNumber * U_EXPORT2 uprv_decNumberLogB(decNumber *, const decNumber *, decContext *);
|
||||
U_INTERNAL decNumber * U_EXPORT2 uprv_decNumberLog10(decNumber *, const decNumber *, decContext *);
|
||||
U_INTERNAL decNumber * U_EXPORT2 uprv_decNumberMax(decNumber *, const decNumber *, const decNumber *, decContext *);
|
||||
U_INTERNAL decNumber * U_EXPORT2 uprv_decNumberMaxMag(decNumber *, const decNumber *, const decNumber *, decContext *);
|
||||
U_INTERNAL decNumber * U_EXPORT2 uprv_decNumberMin(decNumber *, const decNumber *, const decNumber *, decContext *);
|
||||
U_INTERNAL decNumber * U_EXPORT2 uprv_decNumberMinMag(decNumber *, const decNumber *, const decNumber *, decContext *);
|
||||
U_INTERNAL decNumber * U_EXPORT2 uprv_decNumberMinus(decNumber *, const decNumber *, decContext *);
|
||||
U_INTERNAL decNumber * U_EXPORT2 uprv_decNumberMultiply(decNumber *, const decNumber *, const decNumber *, decContext *);
|
||||
U_INTERNAL decNumber * U_EXPORT2 uprv_decNumberNormalize(decNumber *, const decNumber *, decContext *);
|
||||
U_INTERNAL decNumber * U_EXPORT2 uprv_decNumberOr(decNumber *, const decNumber *, const decNumber *, decContext *);
|
||||
U_INTERNAL decNumber * U_EXPORT2 uprv_decNumberPlus(decNumber *, const decNumber *, decContext *);
|
||||
U_INTERNAL decNumber * U_EXPORT2 uprv_decNumberPower(decNumber *, const decNumber *, const decNumber *, decContext *);
|
||||
U_INTERNAL decNumber * U_EXPORT2 uprv_decNumberQuantize(decNumber *, const decNumber *, const decNumber *, decContext *);
|
||||
U_INTERNAL decNumber * U_EXPORT2 uprv_decNumberReduce(decNumber *, const decNumber *, decContext *);
|
||||
U_INTERNAL decNumber * U_EXPORT2 uprv_decNumberRemainder(decNumber *, const decNumber *, const decNumber *, decContext *);
|
||||
U_INTERNAL decNumber * U_EXPORT2 uprv_decNumberRemainderNear(decNumber *, const decNumber *, const decNumber *, decContext *);
|
||||
U_INTERNAL decNumber * U_EXPORT2 uprv_decNumberRescale(decNumber *, const decNumber *, const decNumber *, decContext *);
|
||||
U_INTERNAL decNumber * U_EXPORT2 uprv_decNumberRotate(decNumber *, const decNumber *, const decNumber *, decContext *);
|
||||
U_INTERNAL decNumber * U_EXPORT2 uprv_decNumberSameQuantum(decNumber *, const decNumber *, const decNumber *);
|
||||
U_INTERNAL decNumber * U_EXPORT2 uprv_decNumberScaleB(decNumber *, const decNumber *, const decNumber *, decContext *);
|
||||
U_INTERNAL decNumber * U_EXPORT2 uprv_decNumberShift(decNumber *, const decNumber *, const decNumber *, decContext *);
|
||||
U_INTERNAL decNumber * U_EXPORT2 uprv_decNumberSquareRoot(decNumber *, const decNumber *, decContext *);
|
||||
U_INTERNAL decNumber * U_EXPORT2 uprv_decNumberSubtract(decNumber *, const decNumber *, const decNumber *, decContext *);
|
||||
U_INTERNAL decNumber * U_EXPORT2 uprv_decNumberToIntegralExact(decNumber *, const decNumber *, decContext *);
|
||||
U_INTERNAL decNumber * U_EXPORT2 uprv_decNumberToIntegralValue(decNumber *, const decNumber *, decContext *);
|
||||
U_INTERNAL decNumber * U_EXPORT2 uprv_decNumberXor(decNumber *, const decNumber *, const decNumber *, decContext *);
|
||||
|
||||
/* Utilities */
|
||||
enum decClass uprv_decNumberClass(const decNumber *, decContext *);
|
||||
const char * uprv_decNumberClassToString(enum decClass);
|
||||
decNumber * uprv_decNumberCopy(decNumber *, const decNumber *);
|
||||
decNumber * uprv_decNumberCopyAbs(decNumber *, const decNumber *);
|
||||
decNumber * uprv_decNumberCopyNegate(decNumber *, const decNumber *);
|
||||
decNumber * uprv_decNumberCopySign(decNumber *, const decNumber *, const decNumber *);
|
||||
decNumber * uprv_decNumberNextMinus(decNumber *, const decNumber *, decContext *);
|
||||
decNumber * uprv_decNumberNextPlus(decNumber *, const decNumber *, decContext *);
|
||||
decNumber * uprv_decNumberNextToward(decNumber *, const decNumber *, const decNumber *, decContext *);
|
||||
decNumber * uprv_decNumberTrim(decNumber *);
|
||||
const char * uprv_decNumberVersion(void);
|
||||
decNumber * uprv_decNumberZero(decNumber *);
|
||||
U_INTERNAL const char * U_EXPORT2 uprv_decNumberClassToString(enum decClass);
|
||||
U_INTERNAL decNumber * U_EXPORT2 uprv_decNumberCopy(decNumber *, const decNumber *);
|
||||
U_INTERNAL decNumber * U_EXPORT2 uprv_decNumberCopyAbs(decNumber *, const decNumber *);
|
||||
U_INTERNAL decNumber * U_EXPORT2 uprv_decNumberCopyNegate(decNumber *, const decNumber *);
|
||||
U_INTERNAL decNumber * U_EXPORT2 uprv_decNumberCopySign(decNumber *, const decNumber *, const decNumber *);
|
||||
U_INTERNAL decNumber * U_EXPORT2 uprv_decNumberNextMinus(decNumber *, const decNumber *, decContext *);
|
||||
U_INTERNAL decNumber * U_EXPORT2 uprv_decNumberNextPlus(decNumber *, const decNumber *, decContext *);
|
||||
U_INTERNAL decNumber * U_EXPORT2 uprv_decNumberNextToward(decNumber *, const decNumber *, const decNumber *, decContext *);
|
||||
U_INTERNAL decNumber * U_EXPORT2 uprv_decNumberTrim(decNumber *);
|
||||
U_INTERNAL const char * U_EXPORT2 uprv_decNumberVersion(void);
|
||||
U_INTERNAL decNumber * U_EXPORT2 uprv_decNumberZero(decNumber *);
|
||||
|
||||
/* Functions for testing decNumbers (normality depends on context) */
|
||||
int32_t uprv_decNumberIsNormal(const decNumber *, decContext *);
|
||||
int32_t uprv_decNumberIsSubnormal(const decNumber *, decContext *);
|
||||
U_INTERNAL int32_t U_EXPORT2 uprv_decNumberIsNormal(const decNumber *, decContext *);
|
||||
U_INTERNAL int32_t U_EXPORT2 uprv_decNumberIsSubnormal(const decNumber *, decContext *);
|
||||
|
||||
/* Macros for testing decNumber *dn */
|
||||
#define decNumberIsCanonical(dn) (1) /* All decNumbers are saintly */
|
||||
|
|
File diff suppressed because it is too large
Load diff
100
icu4c/source/i18n/decnumstr.cpp
Normal file
100
icu4c/source/i18n/decnumstr.cpp
Normal file
|
@ -0,0 +1,100 @@
|
|||
/*
|
||||
******************************************************************************
|
||||
*
|
||||
* Copyright (C) 2010, International Business Machines
|
||||
* Corporation and others. All Rights Reserved.
|
||||
*
|
||||
******************************************************************************
|
||||
*
|
||||
* File decnumstr.cpp
|
||||
*
|
||||
*/
|
||||
|
||||
#include "unicode/utypes.h"
|
||||
#include "decnumstr.h"
|
||||
#include "cmemory.h"
|
||||
#include "uassert.h"
|
||||
|
||||
U_NAMESPACE_BEGIN
|
||||
|
||||
DecimalNumberString::DecimalNumberString() {
|
||||
fLength = 0;
|
||||
fText[0] = 0;
|
||||
}
|
||||
|
||||
DecimalNumberString::~DecimalNumberString() {
|
||||
}
|
||||
|
||||
DecimalNumberString::DecimalNumberString(const StringPiece &source, UErrorCode &status) {
|
||||
fLength = 0;
|
||||
fText[0] = 0;
|
||||
append(source, status);
|
||||
}
|
||||
|
||||
DecimalNumberString & DecimalNumberString::append(char c, UErrorCode &status) {
|
||||
if (ensureCapacity(fLength + 2, status) == FALSE) {
|
||||
return *this;
|
||||
}
|
||||
fText[fLength++] = c;
|
||||
fText[fLength] = 0;
|
||||
return *this;
|
||||
}
|
||||
|
||||
DecimalNumberString &DecimalNumberString::append(const StringPiece &str, UErrorCode &status) {
|
||||
int32_t sLength = str.length();
|
||||
if (ensureCapacity(fLength + sLength + 1, status) == FALSE) {
|
||||
return *this;
|
||||
}
|
||||
uprv_memcpy(&fText[fLength], str.data(), sLength);
|
||||
fLength += sLength;
|
||||
fText[fLength] = 0;
|
||||
return *this;
|
||||
}
|
||||
|
||||
char & DecimalNumberString::operator [] (int32_t index) {
|
||||
U_ASSERT(index>=0 && index<fLength);
|
||||
return fText[index];
|
||||
}
|
||||
|
||||
const char & DecimalNumberString::operator [] (int32_t index) const {
|
||||
U_ASSERT(index>=0 && index<fLength);
|
||||
return fText[index];
|
||||
}
|
||||
|
||||
int32_t DecimalNumberString::length() const {
|
||||
return fLength;
|
||||
}
|
||||
|
||||
void DecimalNumberString::setLength(int32_t length, UErrorCode &status) {
|
||||
if (ensureCapacity(length+1, status) == FALSE) {
|
||||
return;
|
||||
}
|
||||
if (length > fLength) {
|
||||
uprv_memset(&fText[fLength], length - fLength, 0);
|
||||
}
|
||||
fLength = length;
|
||||
fText[fLength] = 0;
|
||||
}
|
||||
|
||||
DecimalNumberString::operator StringPiece() const {
|
||||
return StringPiece(fText, fLength);
|
||||
}
|
||||
|
||||
UBool DecimalNumberString::ensureCapacity(int32_t neededSize, UErrorCode &status) {
|
||||
if (U_FAILURE(status)) {
|
||||
return FALSE;
|
||||
}
|
||||
if (fText.getCapacity() < neededSize) {
|
||||
char *newBuf = fText.resize(neededSize, fText.getCapacity());
|
||||
if (newBuf == NULL) {
|
||||
status = U_MEMORY_ALLOCATION_ERROR;
|
||||
return FALSE;
|
||||
}
|
||||
U_ASSERT(fText.getCapacity() >= neededSize);
|
||||
U_ASSERT(fText.getAlias() == newBuf);
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
U_NAMESPACE_END
|
||||
|
54
icu4c/source/i18n/decnumstr.h
Normal file
54
icu4c/source/i18n/decnumstr.h
Normal file
|
@ -0,0 +1,54 @@
|
|||
/*
|
||||
******************************************************************************
|
||||
*
|
||||
* Copyright (C) 2010, International Business Machines
|
||||
* Corporation and others. All Rights Reserved.
|
||||
*
|
||||
******************************************************************************
|
||||
*
|
||||
* File decnumstr.h
|
||||
*
|
||||
* A simple eight bit char string class.
|
||||
* Used by decimal number formatting to hold the string form of numbers.
|
||||
*
|
||||
* For internal ICU use only. Not public API.
|
||||
*
|
||||
* TODO: ICU should have a light-weight general purpose (char *) string class
|
||||
* available for internal use; this would eliminate the
|
||||
* need for this class.
|
||||
*/
|
||||
|
||||
#ifndef DECNUMSTR_H
|
||||
#define DECNUMSTR_H
|
||||
|
||||
#include "unicode/utypes.h"
|
||||
#include "unicode/stringpiece.h"
|
||||
#include "cmemory.h"
|
||||
|
||||
U_NAMESPACE_BEGIN
|
||||
|
||||
class DecimalNumberString: public UMemory {
|
||||
public:
|
||||
DecimalNumberString();
|
||||
~DecimalNumberString();
|
||||
|
||||
DecimalNumberString(const StringPiece &, UErrorCode &status);
|
||||
|
||||
DecimalNumberString &append(char, UErrorCode &status);
|
||||
DecimalNumberString &append(const StringPiece &s, UErrorCode &status);
|
||||
char &operator[] (int32_t index);
|
||||
const char &operator[] (int32_t index) const;
|
||||
int32_t length() const;
|
||||
void setLength(int32_t length, UErrorCode &status);
|
||||
operator StringPiece() const;
|
||||
private:
|
||||
int32_t fLength;
|
||||
MaybeStackArray<char, 40> fText;
|
||||
|
||||
UBool ensureCapacity(int32_t neededSize, UErrorCode &status);
|
||||
};
|
||||
|
||||
U_NAMESPACE_END
|
||||
|
||||
#endif // DECNUMSTR_H
|
||||
|
File diff suppressed because it is too large
Load diff
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
******************************************************************************
|
||||
*
|
||||
* Copyright (C) 1997-2007, International Business Machines
|
||||
* Copyright (C) 1997-2010, International Business Machines
|
||||
* Corporation and others. All Rights Reserved.
|
||||
*
|
||||
******************************************************************************
|
||||
|
@ -29,9 +29,12 @@
|
|||
#if !UCONFIG_NO_FORMATTING
|
||||
#include "unicode/decimfmt.h"
|
||||
#include <float.h>
|
||||
#include "decContext.h"
|
||||
#include "decNumber.h"
|
||||
#include "cmemory.h"
|
||||
#include "decnumstr.h"
|
||||
|
||||
// Decimal digits in a 64-bit int
|
||||
//#define LONG_DIGITS 19
|
||||
#define INT64_DIGITS 19
|
||||
|
||||
typedef enum EDigitListValues {
|
||||
|
@ -40,6 +43,7 @@ typedef enum EDigitListValues {
|
|||
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
|
||||
|
@ -47,7 +51,34 @@ typedef enum EDigitListValues {
|
|||
|
||||
U_NAMESPACE_BEGIN
|
||||
|
||||
// Export an explicit template instantiation of the MaybeStackArray that
|
||||
// is used as a data member of DigitList.
|
||||
//
|
||||
// MSVC requires this, even though it should not be necessary.
|
||||
// No direct access to the MaybeStackArray 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 MaybeStackArray<char, sizeof(decNumber) + 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
|
||||
|
@ -65,9 +96,31 @@ U_NAMESPACE_BEGIN
|
|||
* 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 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 DigitList : public UMemory { // Declare external to make compiler happy
|
||||
class U_I18N_API DigitList : public UMemory { // Declare external to make compiler happy
|
||||
public:
|
||||
|
||||
DigitList();
|
||||
~DigitList();
|
||||
|
||||
|
@ -91,12 +144,10 @@ public:
|
|||
*/
|
||||
UBool operator==(const DigitList& other) const;
|
||||
|
||||
private:
|
||||
/**
|
||||
* Commented out due to lack of usage and low code coverage.
|
||||
*/
|
||||
inline UBool operator!=(const DigitList& other) const;
|
||||
public:
|
||||
int32_t compare(const DigitList& other);
|
||||
|
||||
|
||||
inline UBool operator!=(const DigitList& other) const { return !operator==(other); };
|
||||
|
||||
/**
|
||||
* Clears out the digits.
|
||||
|
@ -108,18 +159,30 @@ public:
|
|||
void clear(void);
|
||||
|
||||
/**
|
||||
* Appends digits to the list. Ignores all digits beyond the first DBL_DIG,
|
||||
* since they are not significant for either longs or doubles.
|
||||
* 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.
|
||||
* @param digit The digit to be appended.
|
||||
*/
|
||||
inline void append(char digit);
|
||||
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*/;
|
||||
double getDouble(void) const;
|
||||
|
||||
/**
|
||||
* Utility routine to get the value of the digit list
|
||||
|
@ -137,6 +200,11 @@ public:
|
|||
*/
|
||||
int64_t getInt64(void) /*const*/;
|
||||
|
||||
/**
|
||||
* Utility routine to get the value of the digit list as a decimal string.
|
||||
*/
|
||||
void getDecimal(DecimalNumberString &str, UErrorCode &status);
|
||||
|
||||
/**
|
||||
* Return true if the number represented by this object can fit into
|
||||
* a long.
|
||||
|
@ -156,49 +224,105 @@ public:
|
|||
UBool fitsIntoInt64(UBool ignoreNegativeZero) /*const*/;
|
||||
|
||||
/**
|
||||
* Utility routine to set the value of the digit list from a double
|
||||
* Input must be non-negative, and must not be Inf, -Inf, or NaN.
|
||||
* The maximum fraction digits helps us round properly.
|
||||
* Utility routine to set the value of the digit list from a double.
|
||||
* @param source The value to be set
|
||||
* @param maximunDigits The maximum number of digits to be shown
|
||||
* @param fixedPoint True if the point is fixed
|
||||
*/
|
||||
void set(double source, int32_t maximumDigits, UBool fixedPoint = TRUE);
|
||||
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
|
||||
* @param maximunDigits The maximum number of digits to be shown
|
||||
*/
|
||||
void set(int32_t source, int32_t maximumDigits = 0);
|
||||
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
|
||||
* @param maximunDigits The maximum number of digits to be shown
|
||||
*/
|
||||
void set(int64_t source, int32_t maximumDigits = 0);
|
||||
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);
|
||||
|
||||
/**
|
||||
* Return true if this is a representation of zero.
|
||||
* @return true if this is a representation of zero.
|
||||
* 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;
|
||||
|
||||
/**
|
||||
* Return true if this is a representation of LONG_MIN. You must use
|
||||
* this method to determine if this is so; you cannot check directly,
|
||||
* because a special format is used to handle this.
|
||||
/** Test for a Nan
|
||||
* @return TRUE if the number is a NaN
|
||||
*/
|
||||
// This code is unused.
|
||||
//UBool isLONG_MIN(void) const;
|
||||
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;};
|
||||
|
||||
public:
|
||||
/**
|
||||
* 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;
|
||||
|
||||
void setDigit(int32_t i, char v);
|
||||
char getDigit(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
|
||||
|
@ -218,46 +342,32 @@ public:
|
|||
* <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;
|
||||
*/
|
||||
int32_t fDecimalAt;
|
||||
int32_t fCount;
|
||||
UBool fIsPositive;
|
||||
char *fDigits;
|
||||
DecimalFormat::ERoundingMode fRoundingMode;
|
||||
|
||||
private:
|
||||
|
||||
/* One character before fDigits for the decimal*/
|
||||
char fDecimalDigits[MAX_DEC_DIGITS + 1];
|
||||
|
||||
/**
|
||||
* Round the representation 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.
|
||||
decContext fContext;
|
||||
decNumber *fDecNumber;
|
||||
MaybeStackArray<char, sizeof(decNumber) + 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.
|
||||
*/
|
||||
void round(int32_t maximumDigits);
|
||||
double fDouble;
|
||||
UBool fHaveDouble;
|
||||
|
||||
|
||||
|
||||
UBool shouldRoundUp(int32_t maximumDigits) const;
|
||||
};
|
||||
|
||||
// -------------------------------------
|
||||
// Appends the digit to the digit list if it's not out of scope.
|
||||
// Ignores the digit, otherwise.
|
||||
|
||||
inline void
|
||||
DigitList::append(char digit)
|
||||
{
|
||||
// Ignore digits which exceed the precision we can represent
|
||||
if (fCount < MAX_DIGITS)
|
||||
fDigits[fCount++] = digit;
|
||||
}
|
||||
|
||||
#if 0
|
||||
inline UBool
|
||||
DigitList::operator!=(const DigitList& other) const {
|
||||
return !operator==(other);
|
||||
}
|
||||
#endif
|
||||
|
||||
U_NAMESPACE_END
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
*******************************************************************************
|
||||
* Copyright (C) 1997-2008, International Business Machines Corporation and *
|
||||
* Copyright (C) 1997-2010, International Business Machines Corporation and *
|
||||
* others. All Rights Reserved. *
|
||||
*******************************************************************************
|
||||
*
|
||||
|
@ -22,6 +22,10 @@
|
|||
#include "unicode/measure.h"
|
||||
#include "unicode/curramt.h"
|
||||
#include "cmemory.h"
|
||||
#include "cstring.h"
|
||||
#include "decNumber.h"
|
||||
#include "decnumstr.h"
|
||||
#include "digitlst.h"
|
||||
|
||||
// *****************************************************************************
|
||||
// class Formattable
|
||||
|
@ -68,7 +72,7 @@ static inline UBool instanceOfMeasure(const UObject* a) {
|
|||
* @param count the original array count
|
||||
* @return the new Formattable array.
|
||||
*/
|
||||
static inline Formattable* createArrayCopy(const Formattable* array, int32_t count) {
|
||||
static Formattable* createArrayCopy(const Formattable* array, int32_t count) {
|
||||
Formattable *result = new Formattable[count];
|
||||
if (result != NULL) {
|
||||
for (int32_t i=0; i<count; ++i)
|
||||
|
@ -82,30 +86,39 @@ static inline Formattable* createArrayCopy(const Formattable* array, int32_t cou
|
|||
/**
|
||||
* Set 'ec' to 'err' only if 'ec' is not already set to a failing UErrorCode.
|
||||
*/
|
||||
static inline void setError(UErrorCode& ec, UErrorCode err) {
|
||||
static void setError(UErrorCode& ec, UErrorCode err) {
|
||||
if (U_SUCCESS(ec)) {
|
||||
ec = err;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Common initialization code, shared by constructors.
|
||||
// Put everything into a known state.
|
||||
//
|
||||
void Formattable::init() {
|
||||
fValue.fInt64 = 0;
|
||||
fType = kLong;
|
||||
fDecimalStr = NULL;
|
||||
fDecimalNum = NULL;
|
||||
fBogus.setToBogus();
|
||||
}
|
||||
|
||||
// -------------------------------------
|
||||
// default constructor.
|
||||
// Creates a formattable object with a long value 0.
|
||||
|
||||
Formattable::Formattable()
|
||||
: UObject(), fType(kLong)
|
||||
{
|
||||
fBogus.setToBogus();
|
||||
fValue.fInt64 = 0;
|
||||
Formattable::Formattable() {
|
||||
init();
|
||||
}
|
||||
|
||||
// -------------------------------------
|
||||
// Creates a formattable object with a Date instance.
|
||||
|
||||
Formattable::Formattable(UDate date, ISDATE /*isDate*/)
|
||||
: UObject(), fType(kDate)
|
||||
{
|
||||
fBogus.setToBogus();
|
||||
init();
|
||||
fType = kDate;
|
||||
fValue.fDate = date;
|
||||
}
|
||||
|
||||
|
@ -113,39 +126,47 @@ Formattable::Formattable(UDate date, ISDATE /*isDate*/)
|
|||
// Creates a formattable object with a double value.
|
||||
|
||||
Formattable::Formattable(double value)
|
||||
: UObject(), fType(kDouble)
|
||||
{
|
||||
fBogus.setToBogus();
|
||||
init();
|
||||
fType = kDouble;
|
||||
fValue.fDouble = value;
|
||||
}
|
||||
|
||||
// -------------------------------------
|
||||
// Creates a formattable object with a long value.
|
||||
// Creates a formattable object with an int32_t value.
|
||||
|
||||
Formattable::Formattable(int32_t value)
|
||||
: UObject(), fType(kLong)
|
||||
{
|
||||
fBogus.setToBogus();
|
||||
init();
|
||||
fValue.fInt64 = value;
|
||||
}
|
||||
|
||||
// -------------------------------------
|
||||
// Creates a formattable object with a long value.
|
||||
// Creates a formattable object with an int64_t value.
|
||||
|
||||
Formattable::Formattable(int64_t value)
|
||||
: UObject(), fType(kInt64)
|
||||
{
|
||||
fBogus.setToBogus();
|
||||
init();
|
||||
fType = kInt64;
|
||||
fValue.fInt64 = value;
|
||||
}
|
||||
|
||||
// -------------------------------------
|
||||
// Creates a formattable object with a decimal number value from a string.
|
||||
|
||||
Formattable::Formattable(const StringPiece &number, UErrorCode &status) {
|
||||
init();
|
||||
setDecimalNumber(number, status);
|
||||
}
|
||||
|
||||
|
||||
// -------------------------------------
|
||||
// Creates a formattable object with a UnicodeString instance.
|
||||
|
||||
Formattable::Formattable(const UnicodeString& stringToCopy)
|
||||
: UObject(), fType(kString)
|
||||
{
|
||||
fBogus.setToBogus();
|
||||
init();
|
||||
fType = kString;
|
||||
fValue.fString = new UnicodeString(stringToCopy);
|
||||
}
|
||||
|
||||
|
@ -154,16 +175,16 @@ Formattable::Formattable(const UnicodeString& stringToCopy)
|
|||
// (adopting symantics)
|
||||
|
||||
Formattable::Formattable(UnicodeString* stringToAdopt)
|
||||
: UObject(), fType(kString)
|
||||
{
|
||||
fBogus.setToBogus();
|
||||
init();
|
||||
fType = kString;
|
||||
fValue.fString = stringToAdopt;
|
||||
}
|
||||
|
||||
Formattable::Formattable(UObject* objectToAdopt)
|
||||
: UObject(), fType(kObject)
|
||||
{
|
||||
fBogus.setToBogus();
|
||||
init();
|
||||
fType = kObject;
|
||||
fValue.fObject = objectToAdopt;
|
||||
}
|
||||
|
||||
|
@ -172,7 +193,8 @@ Formattable::Formattable(UObject* objectToAdopt)
|
|||
Formattable::Formattable(const Formattable* arrayToCopy, int32_t count)
|
||||
: UObject(), fType(kArray)
|
||||
{
|
||||
fBogus.setToBogus();
|
||||
init();
|
||||
fType = kArray;
|
||||
fValue.fArrayAndCount.fArray = createArrayCopy(arrayToCopy, count);
|
||||
fValue.fArrayAndCount.fCount = count;
|
||||
}
|
||||
|
@ -180,10 +202,11 @@ Formattable::Formattable(const Formattable* arrayToCopy, int32_t count)
|
|||
// -------------------------------------
|
||||
// copy constructor
|
||||
|
||||
|
||||
Formattable::Formattable(const Formattable &source)
|
||||
: UObject(source), fType(kLong)
|
||||
: UObject(*this)
|
||||
{
|
||||
fBogus.setToBogus();
|
||||
init();
|
||||
*this = source;
|
||||
}
|
||||
|
||||
|
@ -229,6 +252,18 @@ Formattable::operator=(const Formattable& source)
|
|||
fValue.fObject = objectClone(source.fValue.fObject);
|
||||
break;
|
||||
}
|
||||
|
||||
UErrorCode status = U_ZERO_ERROR;
|
||||
if (source.fDecimalNum != NULL) {
|
||||
fDecimalNum = new DigitList(*source.fDecimalNum);
|
||||
}
|
||||
if (source.fDecimalStr != NULL) {
|
||||
fDecimalStr = new DecimalNumberString(*source.fDecimalStr, status);
|
||||
if (U_FAILURE(status)) {
|
||||
delete fDecimalStr;
|
||||
fDecimalStr = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
@ -283,6 +318,7 @@ Formattable::operator==(const Formattable& that) const
|
|||
break;
|
||||
}
|
||||
|
||||
// TODO: compare digit lists if numeric.
|
||||
return equal;
|
||||
}
|
||||
|
||||
|
@ -311,6 +347,13 @@ void Formattable::dispose()
|
|||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
fType = kLong;
|
||||
fValue.fInt64 = 0;
|
||||
delete fDecimalStr;
|
||||
fDecimalStr = NULL;
|
||||
delete fDecimalNum;
|
||||
fDecimalNum = NULL;
|
||||
}
|
||||
|
||||
Formattable *
|
||||
|
@ -625,6 +668,113 @@ Formattable::getBogus() const
|
|||
return (UnicodeString*)&fBogus; /* cast away const :-( */
|
||||
}
|
||||
|
||||
|
||||
// --------------------------------------
|
||||
StringPiece Formattable::getDecimalNumber(UErrorCode &status) {
|
||||
if (U_FAILURE(status)) {
|
||||
return "";
|
||||
}
|
||||
if (fDecimalStr != NULL) {
|
||||
return *fDecimalStr;
|
||||
}
|
||||
|
||||
if (fDecimalNum == NULL) {
|
||||
// No decimal number for the formattable yet. Which means the value was
|
||||
// set directly by the user as an int, int64 or double. If the value came
|
||||
// from parsing, or from the user setting a decimal number, fDecimalNum
|
||||
// would already be set.
|
||||
//
|
||||
fDecimalNum = new DigitList;
|
||||
if (fDecimalNum == NULL) {
|
||||
status = U_MEMORY_ALLOCATION_ERROR;
|
||||
return "";
|
||||
}
|
||||
|
||||
switch (fType) {
|
||||
case kDouble:
|
||||
fDecimalNum->set(this->getDouble());
|
||||
break;
|
||||
case kLong:
|
||||
fDecimalNum->set(this->getLong());
|
||||
break;
|
||||
case kInt64:
|
||||
fDecimalNum->set(this->getInt64());
|
||||
break;
|
||||
default:
|
||||
// The formattable's value is not a numeric type.
|
||||
status = U_INVALID_STATE_ERROR;
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
fDecimalStr = new DecimalNumberString;
|
||||
if (fDecimalStr == NULL) {
|
||||
status = U_MEMORY_ALLOCATION_ERROR;
|
||||
return "";
|
||||
}
|
||||
fDecimalNum->getDecimal(*fDecimalStr, status);
|
||||
|
||||
return *fDecimalStr;
|
||||
}
|
||||
|
||||
|
||||
|
||||
// ---------------------------------------
|
||||
void
|
||||
Formattable::adoptDigitList(DigitList *dl) {
|
||||
dispose();
|
||||
|
||||
fDecimalNum = dl;
|
||||
|
||||
// Set the value into the Union of simple type values.
|
||||
// Cannot use the set() functions because they would delete the fDecimalNum value,
|
||||
|
||||
if (fDecimalNum->fitsIntoLong(FALSE)) {
|
||||
fType = kLong;
|
||||
fValue.fInt64 = fDecimalNum->getLong();
|
||||
} else if (fDecimalNum->fitsIntoInt64(FALSE)) {
|
||||
fType = kInt64;
|
||||
fValue.fInt64 = fDecimalNum->getInt64();
|
||||
} else {
|
||||
fType = kDouble;
|
||||
fValue.fDouble = fDecimalNum->getDouble();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// ---------------------------------------
|
||||
void
|
||||
Formattable::setDecimalNumber(const StringPiece &numberString, UErrorCode &status) {
|
||||
if (U_FAILURE(status)) {
|
||||
return;
|
||||
}
|
||||
dispose();
|
||||
|
||||
// Copy the input string and nul-terminate it.
|
||||
// The decNumber library requires nul-terminated input. StringPiece input
|
||||
// is not guaranteed nul-terminated. Too bad.
|
||||
// DecimalNumberStrings automatically adds the nul.
|
||||
DecimalNumberString s(numberString, status);
|
||||
if (U_FAILURE(status)) {
|
||||
return;
|
||||
}
|
||||
|
||||
DigitList *dnum = new DigitList();
|
||||
if (dnum == NULL) {
|
||||
status = U_MEMORY_ALLOCATION_ERROR;
|
||||
return;
|
||||
}
|
||||
dnum->set(s, status);
|
||||
if (U_FAILURE(status)) {
|
||||
delete dnum;
|
||||
return; // String didn't contain a decimal number.
|
||||
}
|
||||
adoptDigitList(dnum);
|
||||
|
||||
// Note that we do not hang on to the caller's input string.
|
||||
// If we are asked for the string, we will regenerate one from fDecimalNum.
|
||||
}
|
||||
|
||||
#if 0
|
||||
//----------------------------------------------------
|
||||
// console I/O
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
*******************************************************************************
|
||||
* Copyright (C) 1997-2005, International Business Machines Corporation and *
|
||||
* Copyright (C) 1997-2010, International Business Machines Corporation and *
|
||||
* others. All Rights Reserved. *
|
||||
*******************************************************************************
|
||||
*
|
||||
|
@ -31,9 +31,9 @@ U_NAMESPACE_BEGIN
|
|||
// This is just a grandfathered API.
|
||||
|
||||
Formattable::Formattable(const char* stringToCopy)
|
||||
: UObject(), fType(kString)
|
||||
{
|
||||
fBogus.setToBogus();
|
||||
init();
|
||||
fType = kString;
|
||||
fValue.fString = new UnicodeString(stringToCopy);
|
||||
}
|
||||
|
||||
|
|
|
@ -88,8 +88,10 @@ Format::Format(const Format &that)
|
|||
Format&
|
||||
Format::operator=(const Format& that)
|
||||
{
|
||||
uprv_strcpy(validLocale, that.validLocale);
|
||||
uprv_strcpy(actualLocale, that.actualLocale);
|
||||
if (this != &that) {
|
||||
uprv_strcpy(validLocale, that.validLocale);
|
||||
uprv_strcpy(actualLocale, that.actualLocale);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
|
|
@ -1426,6 +1426,14 @@
|
|||
RelativePath=".\decNumberLocal.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\decnumstr.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\decnumstr.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\digitlst.cpp"
|
||||
>
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
******************************************************************************
|
||||
* Copyright (C) 1997-2007, International Business Machines
|
||||
* Copyright (C) 1997-2010, International Business Machines
|
||||
* Corporation and others. All Rights Reserved.
|
||||
******************************************************************************
|
||||
* file name: nfsubs.cpp
|
||||
|
@ -1041,25 +1041,22 @@ FractionalPartSubstitution::doSubstitution(double number, UnicodeString& toInser
|
|||
// }
|
||||
|
||||
DigitList dl;
|
||||
dl.set(number, 20, TRUE);
|
||||
dl.set(number);
|
||||
dl.roundFixedPoint(20); // round to 20 fraction digits.
|
||||
dl.reduce(); // Removes any trailing zeros.
|
||||
|
||||
UBool pad = FALSE;
|
||||
while (dl.fCount > (dl.fDecimalAt <= 0 ? 0 : dl.fDecimalAt)) {
|
||||
for (int32_t didx = dl.getCount()-1; didx>=dl.getDecimalAt(); didx--) {
|
||||
// Loop iterates over fraction digits, starting with the LSD.
|
||||
// include both real digits from the number, and zeros
|
||||
// to the left of the MSD but to the right of the decimal point.
|
||||
if (pad && useSpaces) {
|
||||
toInsertInto.insert(_pos + getPos(), gSpace);
|
||||
} else {
|
||||
pad = TRUE;
|
||||
}
|
||||
getRuleSet()->format((int64_t)(dl.fDigits[--dl.fCount] - '0'), toInsertInto, _pos + getPos());
|
||||
}
|
||||
while (dl.fDecimalAt < 0) {
|
||||
if (pad && useSpaces) {
|
||||
toInsertInto.insert(_pos + getPos(), gSpace);
|
||||
} else {
|
||||
pad = TRUE;
|
||||
}
|
||||
getRuleSet()->format((int64_t)0, toInsertInto, _pos + getPos());
|
||||
++dl.fDecimalAt;
|
||||
int64_t digit = didx>=0 ? dl.getDigit(didx) - '0' : 0;
|
||||
getRuleSet()->format(digit, toInsertInto, _pos + getPos());
|
||||
}
|
||||
|
||||
if (!pad) {
|
||||
|
@ -1156,7 +1153,7 @@ FractionalPartSubstitution::doParse(const UnicodeString& text,
|
|||
}
|
||||
delete fmt;
|
||||
|
||||
result = dl.fCount == 0 ? 0 : dl.getDouble();
|
||||
result = dl.getCount() == 0 ? 0 : dl.getDouble();
|
||||
result = composeRuleValue(result, baseValue);
|
||||
resVal.setDouble(result);
|
||||
return TRUE;
|
||||
|
|
|
@ -44,6 +44,7 @@
|
|||
#include "cstring.h"
|
||||
#include "putilimp.h"
|
||||
#include "umutex.h"
|
||||
#include "digitlst.h"
|
||||
#include <float.h>
|
||||
|
||||
//#define FMT_DEBUG
|
||||
|
@ -210,6 +211,7 @@ NumberFormat::operator=(const NumberFormat& rhs)
|
|||
{
|
||||
if (this != &rhs)
|
||||
{
|
||||
Format::operator=(rhs);
|
||||
fGroupingUsed = rhs.fGroupingUsed;
|
||||
fMaxIntegerDigits = rhs.fMaxIntegerDigits;
|
||||
fMinIntegerDigits = rhs.fMinIntegerDigits;
|
||||
|
@ -322,18 +324,29 @@ NumberFormat::format(int64_t /* unused number */,
|
|||
}
|
||||
|
||||
// -------------------------------------
|
||||
// Default implementation sets unsupported error; subclasses should
|
||||
// override.
|
||||
// Decimal Number format() default implementation
|
||||
// Subclasses do not normally override this function, but rather the DigitList
|
||||
// formatting functions..
|
||||
// The expected call chain from here is
|
||||
// this function ->
|
||||
// NumberFormat::format(Formattable ->
|
||||
// DecimalFormat::format(DigitList
|
||||
//
|
||||
// Or, for subclasses of Formattable that do not know about DigitList,
|
||||
// this Function ->
|
||||
// NumberFormat::format(Formattable ->
|
||||
// NumberFormat::format(DigitList ->
|
||||
// XXXFormat::format(double
|
||||
|
||||
UnicodeString&
|
||||
NumberFormat::format(const StringPiece & /* unused decimal number */,
|
||||
NumberFormat::format(const StringPiece &decimalNum,
|
||||
UnicodeString& toAppendTo,
|
||||
FieldPositionIterator* /* unused posIter */,
|
||||
FieldPositionIterator* fpi,
|
||||
UErrorCode& status) const
|
||||
{
|
||||
if (!U_FAILURE(status)) {
|
||||
status = U_UNSUPPORTED_ERROR;
|
||||
}
|
||||
Formattable f;
|
||||
f.setDecimalNumber(decimalNum, status);
|
||||
format(f, toAppendTo, fpi, status);
|
||||
return toAppendTo;
|
||||
}
|
||||
|
||||
|
@ -388,6 +401,39 @@ ArgExtractor::~ArgExtractor() {
|
|||
}
|
||||
}
|
||||
|
||||
UnicodeString& NumberFormat::format(const DigitList &number,
|
||||
UnicodeString& appendTo,
|
||||
FieldPositionIterator* posIter,
|
||||
UErrorCode& status) const {
|
||||
// DecimalFormat overrides this function, and handles DigitList based big decimals.
|
||||
// Other subclasses (ChoiceFormat, RuleBasedNumberFormat) do not (yet) handle DigitLists,
|
||||
// so this default implementation falls back to formatting decimal numbers as doubles.
|
||||
if (U_FAILURE(status)) {
|
||||
return appendTo;
|
||||
}
|
||||
double dnum = number.getDouble();
|
||||
format(dnum, appendTo, posIter, status);
|
||||
return appendTo;
|
||||
}
|
||||
|
||||
|
||||
|
||||
UnicodeString&
|
||||
NumberFormat::format(const DigitList &number,
|
||||
UnicodeString& appendTo,
|
||||
FieldPosition& pos,
|
||||
UErrorCode &status) const {
|
||||
// DecimalFormat overrides this function, and handles DigitList based big decimals.
|
||||
// Other subclasses (ChoiceFormat, RuleBasedNumberFormat) do not (yet) handle DigitLists,
|
||||
// so this default implementation falls back to formatting decimal numbers as doubles.
|
||||
if (U_FAILURE(status)) {
|
||||
return appendTo;
|
||||
}
|
||||
double dnum = number.getDouble();
|
||||
format(dnum, appendTo, pos, status);
|
||||
return appendTo;
|
||||
}
|
||||
|
||||
UnicodeString&
|
||||
NumberFormat::format(const Formattable& obj,
|
||||
UnicodeString& appendTo,
|
||||
|
@ -399,19 +445,31 @@ NumberFormat::format(const Formattable& obj,
|
|||
ArgExtractor arg(*this, obj, status);
|
||||
const Formattable *n = arg.number();
|
||||
|
||||
switch (n->getType()) {
|
||||
case Formattable::kDouble:
|
||||
format(n->getDouble(), appendTo, pos);
|
||||
break;
|
||||
case Formattable::kLong:
|
||||
format(n->getLong(), appendTo, pos);
|
||||
break;
|
||||
case Formattable::kInt64:
|
||||
format(n->getInt64(), appendTo, pos);
|
||||
break;
|
||||
default:
|
||||
status = U_INVALID_FORMAT_ERROR;
|
||||
break;
|
||||
if (n->isNumeric() && n->getDigitList() != NULL) {
|
||||
// Decimal Number. We will have a DigitList available if the value was
|
||||
// set to a decimal number, or if the value originated with a parse.
|
||||
//
|
||||
// The default implementation for formatting a DigitList converts it
|
||||
// to a double, and formats that, allowing formatting classes that don't
|
||||
// know about DigitList to continue to operate as they had.
|
||||
//
|
||||
// DecimalFormat overrides the DigitList formatting functions.
|
||||
format(*n->getDigitList(), appendTo, pos, status);
|
||||
} else {
|
||||
switch (n->getType()) {
|
||||
case Formattable::kDouble:
|
||||
format(n->getDouble(), appendTo, pos);
|
||||
break;
|
||||
case Formattable::kLong:
|
||||
format(n->getLong(), appendTo, pos);
|
||||
break;
|
||||
case Formattable::kInt64:
|
||||
format(n->getInt64(), appendTo, pos);
|
||||
break;
|
||||
default:
|
||||
status = U_INVALID_FORMAT_ERROR;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return appendTo;
|
||||
|
@ -432,19 +490,24 @@ NumberFormat::format(const Formattable& obj,
|
|||
ArgExtractor arg(*this, obj, status);
|
||||
const Formattable *n = arg.number();
|
||||
|
||||
switch (n->getType()) {
|
||||
case Formattable::kDouble:
|
||||
format(n->getDouble(), appendTo, posIter, status);
|
||||
break;
|
||||
case Formattable::kLong:
|
||||
format(n->getLong(), appendTo, posIter, status);
|
||||
break;
|
||||
case Formattable::kInt64:
|
||||
format(n->getInt64(), appendTo, posIter, status);
|
||||
break;
|
||||
default:
|
||||
status = U_INVALID_FORMAT_ERROR;
|
||||
break;
|
||||
if (n->isNumeric() && n->getDigitList() != NULL) {
|
||||
// Decimal Number
|
||||
format(*n->getDigitList(), appendTo, posIter, status);
|
||||
} else {
|
||||
switch (n->getType()) {
|
||||
case Formattable::kDouble:
|
||||
format(n->getDouble(), appendTo, posIter, status);
|
||||
break;
|
||||
case Formattable::kLong:
|
||||
format(n->getLong(), appendTo, posIter, status);
|
||||
break;
|
||||
case Formattable::kInt64:
|
||||
format(n->getInt64(), appendTo, posIter, status);
|
||||
break;
|
||||
default:
|
||||
status = U_INVALID_FORMAT_ERROR;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return appendTo;
|
||||
|
|
|
@ -201,7 +201,7 @@ public:
|
|||
/**
|
||||
* Get one of the format symbols by its enum constant.
|
||||
* Each symbol is stored as a string so that graphemes
|
||||
* (characters with modifyer letters) can be used.
|
||||
* (characters with modifier letters) can be used.
|
||||
*
|
||||
* @param symbol Constant to indicate a number format symbol.
|
||||
* @return the format symbols by the param 'symbol'
|
||||
|
@ -212,10 +212,10 @@ public:
|
|||
/**
|
||||
* Set one of the format symbols by its enum constant.
|
||||
* Each symbol is stored as a string so that graphemes
|
||||
* (characters with modifyer letters) can be used.
|
||||
* (characters with modifier letters) can be used.
|
||||
*
|
||||
* @param symbol Constant to indicate a number format symbol.
|
||||
* @param value value of the format sybmol
|
||||
* @param value value of the format symbol
|
||||
* @stable ICU 2.0
|
||||
*/
|
||||
void setSymbol(ENumberFormatSymbol symbol, const UnicodeString &value);
|
||||
|
|
|
@ -946,6 +946,48 @@ public:
|
|||
FieldPositionIterator* posIter,
|
||||
UErrorCode& status) const;
|
||||
|
||||
|
||||
/**
|
||||
* Format a decimal number.
|
||||
* The number is a DigitList wrapper onto a floating point decimal number.
|
||||
* The default implementation in NumberFormat converts the decimal number
|
||||
* to a double and formats that.
|
||||
*
|
||||
* @param number The number, a DigitList format Decimal Floating Point.
|
||||
* @param appendTo Output parameter to receive result.
|
||||
* Result is appended to existing contents.
|
||||
* @param posIter On return, can be used to iterate over positions
|
||||
* of fields generated by this format call.
|
||||
* @param status Output param filled with success/failure status.
|
||||
* @return Reference to 'appendTo' parameter.
|
||||
* @internal
|
||||
*/
|
||||
virtual UnicodeString& format(const DigitList &number,
|
||||
UnicodeString& appendTo,
|
||||
FieldPositionIterator* posIter,
|
||||
UErrorCode& status) const;
|
||||
|
||||
/**
|
||||
* Format a decimal number.
|
||||
* The number is a DigitList wrapper onto a floating point decimal number.
|
||||
* The default implementation in NumberFormat converts the decimal number
|
||||
* to a double and formats that.
|
||||
*
|
||||
* @param number The number, a DigitList format Decimal Floating Point.
|
||||
* @param appendTo Output parameter to receive result.
|
||||
* Result is appended to existing contents.
|
||||
* @param pos On input: an alignment field, if desired.
|
||||
* On output: the offsets of the alignment field.
|
||||
* @param status Output param filled with success/failure status.
|
||||
* @return Reference to 'appendTo' parameter.
|
||||
* @internal
|
||||
*/
|
||||
virtual UnicodeString& format(const DigitList &number,
|
||||
UnicodeString& appendTo,
|
||||
FieldPosition& pos,
|
||||
UErrorCode& status) const;
|
||||
|
||||
|
||||
/**
|
||||
* Format a Formattable using base-10 representation.
|
||||
*
|
||||
|
@ -1806,7 +1848,13 @@ private:
|
|||
|
||||
DecimalFormat(); // default constructor not implemented
|
||||
|
||||
int32_t precision(UBool isIntegral) const;
|
||||
int32_t precision() const;
|
||||
|
||||
/**
|
||||
* Initialize all fields of a new DecimalFormatter.
|
||||
* Common code for use by constructors.
|
||||
*/
|
||||
void init();
|
||||
|
||||
/**
|
||||
* Do real work of constructing a new DecimalFormat.
|
||||
|
@ -1977,8 +2025,6 @@ private:
|
|||
|
||||
void expandAffixes(const UnicodeString* pluralCount);
|
||||
|
||||
static double round(double a, ERoundingMode mode, UBool isNegative);
|
||||
|
||||
void addPadding(UnicodeString& appendTo,
|
||||
FieldPositionHandler& handler,
|
||||
int32_t prefixLen, int32_t suffixLen) const;
|
||||
|
@ -2026,6 +2072,10 @@ private:
|
|||
UnicodeString& _format(double number,
|
||||
UnicodeString& appendTo,
|
||||
FieldPositionHandler& handler) const;
|
||||
UnicodeString& _format(const DigitList &number,
|
||||
UnicodeString& appendTo,
|
||||
FieldPositionHandler& handler,
|
||||
UErrorCode &status) const;
|
||||
|
||||
// currency sign count
|
||||
enum {
|
||||
|
@ -2038,9 +2088,6 @@ private:
|
|||
/**
|
||||
* Constants.
|
||||
*/
|
||||
//static const int8_t fgMaxDigit; // The largest digit, in this case 9
|
||||
|
||||
/*transient*/ //DigitList* fDigitList;
|
||||
|
||||
UnicodeString fPositivePrefix;
|
||||
UnicodeString fPositiveSuffix;
|
||||
|
@ -2058,7 +2105,7 @@ private:
|
|||
*/
|
||||
ChoiceFormat* fCurrencyChoice;
|
||||
|
||||
int32_t fMultiplier;
|
||||
DigitList * fMultiplier; // NULL for multiplier of one
|
||||
int32_t fGroupingSize;
|
||||
int32_t fGroupingSize2;
|
||||
UBool fDecimalSeparatorAlwaysShown;
|
||||
|
@ -2072,12 +2119,7 @@ private:
|
|||
int8_t fMinExponentDigits;
|
||||
UBool fExponentSignAlwaysShown;
|
||||
|
||||
/* If fRoundingIncrement is NULL, there is no rounding. Otherwise, round to
|
||||
* fRoundingIncrement.getDouble(). Since this operation may be expensive,
|
||||
* we cache the result in fRoundingDouble. All methods that update
|
||||
* fRoundingIncrement also update fRoundingDouble. */
|
||||
DigitList* fRoundingIncrement;
|
||||
/*transient*/ double fRoundingDouble;
|
||||
DigitList* fRoundingIncrement; // NULL if no rounding increment specified.
|
||||
ERoundingMode fRoundingMode;
|
||||
|
||||
UChar32 fPad;
|
||||
|
|
|
@ -28,6 +28,9 @@
|
|||
|
||||
U_NAMESPACE_BEGIN
|
||||
|
||||
class DecimalNumberString;
|
||||
class DigitList;
|
||||
|
||||
/**
|
||||
* Formattable objects can be passed to the Format class or
|
||||
* its subclasses for formatting. Formattable is a thin wrapper
|
||||
|
@ -464,10 +467,18 @@ public:
|
|||
* the full precision and range of the original input, unconstrained by
|
||||
* the limits of a double floating point or a 64 bit int.
|
||||
*
|
||||
* This function is not thread safe, and therfore is not declared const,
|
||||
* even though it is logically const.
|
||||
*
|
||||
* Possible errors include U_MEMORY_ALLOCATION_ERROR, and
|
||||
* U_INVALID_STATE if the formattable object has not been set to
|
||||
* a numeric type.
|
||||
*
|
||||
* @param status the error code.
|
||||
* @return the unformatted string representation of a number.
|
||||
* @draft ICU 4.4
|
||||
*/
|
||||
const StringPiece &getDecimalNumber() const;
|
||||
StringPiece getDecimalNumber(UErrorCode &status);
|
||||
|
||||
/**
|
||||
* Sets the double value of this object and changes the type to
|
||||
|
@ -581,12 +592,36 @@ public:
|
|||
*/
|
||||
inline int32_t getLong(UErrorCode* status) const;
|
||||
|
||||
/**
|
||||
* Internal function, do not use.
|
||||
* TODO: figure out how to make this be non-public.
|
||||
* NumberFormat::format(Formattable, ...
|
||||
* needs to get at the DigitList, if it exists, for
|
||||
* big decimal formatting.
|
||||
* @internal
|
||||
*/
|
||||
DigitList *getDigitList() const { return fDecimalNum;};
|
||||
|
||||
/**
|
||||
* Adopt, and set value from, a DigitList
|
||||
* Internal Function, do not use.
|
||||
* @param dl the Digit List to be adopted
|
||||
* @param status reports errors
|
||||
* @internal
|
||||
*/
|
||||
void adoptDigitList(DigitList *dl);
|
||||
|
||||
private:
|
||||
/**
|
||||
* Cleans up the memory for unwanted values. For example, the adopted
|
||||
* string or array objects.
|
||||
*/
|
||||
void dispose(void);
|
||||
|
||||
/**
|
||||
* Common initialization, for use by constructors.
|
||||
*/
|
||||
void init();
|
||||
|
||||
UnicodeString* getBogus() const;
|
||||
|
||||
|
@ -602,6 +637,9 @@ private:
|
|||
} fArrayAndCount;
|
||||
} fValue;
|
||||
|
||||
DecimalNumberString *fDecimalStr;
|
||||
DigitList *fDecimalNum;
|
||||
|
||||
Type fType;
|
||||
UnicodeString fBogus; // Bogus string when it's needed.
|
||||
};
|
||||
|
|
|
@ -471,9 +471,52 @@ public:
|
|||
UnicodeString& appendTo,
|
||||
FieldPositionIterator* posIter,
|
||||
UErrorCode& status) const;
|
||||
public:
|
||||
/**
|
||||
* Format a decimal number.
|
||||
* The number is a DigitList wrapper onto a floating point decimal number.
|
||||
* The default implementation in NumberFormat converts the decimal number
|
||||
* to a double and formats that. Subclasses of NumberFormat that want
|
||||
* to specifically handle big decimal numbers must override this method.
|
||||
* class DecimalFormat does so.
|
||||
*
|
||||
* @param number The number, a DigitList format Decimal Floating Point.
|
||||
* @param appendTo Output parameter to receive result.
|
||||
* Result is appended to existing contents.
|
||||
* @param posIter On return, can be used to iterate over positions
|
||||
* of fields generated by this format call.
|
||||
* @param status Output param filled with success/failure status.
|
||||
* @return Reference to 'appendTo' parameter.
|
||||
* @internal
|
||||
*/
|
||||
virtual UnicodeString& format(const DigitList &number,
|
||||
UnicodeString& appendTo,
|
||||
FieldPositionIterator* posIter,
|
||||
UErrorCode& status) const;
|
||||
|
||||
// TODO: do we also want a format of a decimal number that takes a
|
||||
// FieldPosition parameter?
|
||||
/**
|
||||
* Format a decimal number.
|
||||
* The number is a DigitList wrapper onto a floating point decimal number.
|
||||
* The default implementation in NumberFormat converts the decimal number
|
||||
* to a double and formats that. Subclasses of NumberFormat that want
|
||||
* to specifically handle big decimal numbers must override this method.
|
||||
* class DecimalFormat does so.
|
||||
*
|
||||
* @param number The number, a DigitList format Decimal Floating Point.
|
||||
* @param appendTo Output parameter to receive result.
|
||||
* Result is appended to existing contents.
|
||||
* @param pos On input: an alignment field, if desired.
|
||||
* On output: the offsets of the alignment field.
|
||||
* @param status Output param filled with success/failure status.
|
||||
* @return Reference to 'appendTo' parameter.
|
||||
* @internal
|
||||
*/
|
||||
virtual UnicodeString& format(const DigitList &number,
|
||||
UnicodeString& appendTo,
|
||||
FieldPosition& pos,
|
||||
UErrorCode& status) const;
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
* Redeclared Format method.
|
||||
|
|
|
@ -57,7 +57,7 @@ itrbnf.o itrbnfrt.o itrbnfp.o ucaconf.o icusvtst.o \
|
|||
uobjtest.o idnaref.o idnaconf.o nptrans.o punyref.o testidn.o testidna.o incaltst.o \
|
||||
calcasts.o v32test.o uvectest.o textfile.o tokiter.o utxttest.o \
|
||||
windttst.o winnmtst.o winutil.o csdetest.o tzrulets.o tzoffloc.o tzfmttst.o ssearch.o dtifmtts.o \
|
||||
tufmtts.o itspoof.o simplethread.o bidiconf.o locnmtst.o
|
||||
tufmtts.o itspoof.o simplethread.o bidiconf.o locnmtst.o dcfmtest.o
|
||||
|
||||
DEPS = $(OBJECTS:.o=.d)
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/********************************************************************
|
||||
* COPYRIGHT:
|
||||
* Copyright (c) 1997-2009, International Business Machines Corporation and
|
||||
* Copyright (c) 1997-2010, International Business Machines Corporation and
|
||||
* others. All Rights Reserved.
|
||||
********************************************************************/
|
||||
|
||||
|
@ -487,11 +487,15 @@ void IntlTestDecimalFormatAPI::testRoundingInc(/*char *par*/)
|
|||
return;
|
||||
}
|
||||
|
||||
// With rounding now being handled by decNumber, we no longer
|
||||
// set a rounding increment to enable non-default mode rounding,
|
||||
// checking of which was the original point of this test.
|
||||
|
||||
// set rounding mode with zero increment. Rounding
|
||||
// increment should be set by this operation
|
||||
// increment should not be set by this operation
|
||||
pat.setRoundingMode((DecimalFormat::ERoundingMode)0);
|
||||
roundingInc = pat.getRoundingIncrement();
|
||||
if (roundingInc == 0.0) {
|
||||
if (roundingInc != 0.0) {
|
||||
errln((UnicodeString)"ERROR: Rounding increment zero");
|
||||
return;
|
||||
}
|
||||
|
|
517
icu4c/source/test/intltest/dcfmtest.cpp
Normal file
517
icu4c/source/test/intltest/dcfmtest.cpp
Normal file
|
@ -0,0 +1,517 @@
|
|||
/********************************************************************
|
||||
* COPYRIGHT:
|
||||
* Copyright (c) 2002-2010, International Business Machines Corporation and
|
||||
* others. All Rights Reserved.
|
||||
********************************************************************/
|
||||
|
||||
//
|
||||
// dcfmtest.cpp
|
||||
//
|
||||
// Decimal Formatter tests, data driven.
|
||||
//
|
||||
|
||||
#include "intltest.h"
|
||||
#if !UCONFIG_NO_REGULAR_EXPRESSIONS
|
||||
|
||||
#include "unicode/regex.h"
|
||||
#include "unicode/uchar.h"
|
||||
#include "unicode/ustring.h"
|
||||
#include "unicode/unistr.h"
|
||||
#include "unicode/dcfmtsym.h"
|
||||
#include "unicode/decimfmt.h"
|
||||
#include "unicode/locid.h"
|
||||
#include "cmemory.h"
|
||||
#include "dcfmtest.h"
|
||||
#include "util.h"
|
||||
#include "cstring.h"
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include <string>
|
||||
#include <iostream>
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
//
|
||||
// Test class boilerplate
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
DecimalFormatTest::DecimalFormatTest()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
DecimalFormatTest::~DecimalFormatTest()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
|
||||
void DecimalFormatTest::runIndexedTest( int32_t index, UBool exec, const char* &name, char* /*par*/ )
|
||||
{
|
||||
if (exec) logln("TestSuite DecimalFormatTest: ");
|
||||
switch (index) {
|
||||
|
||||
#if !UCONFIG_NO_FILE_IO
|
||||
case 0: name = "DataDrivenTests";
|
||||
if (exec) DataDrivenTests();
|
||||
break;
|
||||
#else
|
||||
case 0: name = "skip";
|
||||
break;
|
||||
#endif
|
||||
|
||||
default: name = "";
|
||||
break; //needed to end loop
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
//
|
||||
// Error Checking / Reporting macros used in all of the tests.
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
#define DF_CHECK_STATUS {if (U_FAILURE(status)) \
|
||||
{dataerrln("DecimalFormatTest failure at line %d. status=%s", \
|
||||
__LINE__, u_errorName(status)); return 0;}}
|
||||
|
||||
#define DF_ASSERT(expr) {if ((expr)==FALSE) {errln("DecimalFormatTest failure at line %d.\n", __LINE__);};}
|
||||
|
||||
#define DF_ASSERT_FAIL(expr, errcode) {UErrorCode status=U_ZERO_ERROR; (expr);\
|
||||
if (status!=errcode) {dataerrln("DecimalFormatTest failure at line %d. Expected status=%s, got %s", \
|
||||
__LINE__, u_errorName(errcode), u_errorName(status));};}
|
||||
|
||||
#define DF_CHECK_STATUS_L(line) {if (U_FAILURE(status)) {errln( \
|
||||
"DecimalFormatTest failure at line %d, from %d. status=%d\n",__LINE__, (line), status); }}
|
||||
|
||||
#define DF_ASSERT_L(expr, line) {if ((expr)==FALSE) { \
|
||||
errln("DecimalFormatTest failure at line %d, from %d.", __LINE__, (line)); return;}}
|
||||
|
||||
|
||||
|
||||
//
|
||||
// InvariantStringPiece
|
||||
// Wrap a StringPiece around the extracted invariant data of a UnicodeString.
|
||||
// The data is guaranteed to be nul terminated. (This is not true of StringPiece
|
||||
// in general, but is true of InvariantStringPiece)
|
||||
//
|
||||
class InvariantStringPiece: public StringPiece {
|
||||
public:
|
||||
InvariantStringPiece(const UnicodeString &s);
|
||||
~InvariantStringPiece() {};
|
||||
private:
|
||||
MaybeStackArray<char, 20> buf;
|
||||
};
|
||||
|
||||
InvariantStringPiece::InvariantStringPiece(const UnicodeString &s) {
|
||||
int32_t len = s.length();
|
||||
if (len+1 > buf.getCapacity()) {
|
||||
buf.resize(len+1);
|
||||
}
|
||||
// Buffer size is len+1 so that s.extract() will nul-terminate the string.
|
||||
s.extract(0, len, buf.getAlias(), len+1, US_INV);
|
||||
this->set(buf, len);
|
||||
}
|
||||
|
||||
|
||||
// UnicodeStringPiece
|
||||
// Wrap a StringPiece around the extracted (to the default charset) data of
|
||||
// a UnicodeString. The extracted data is guaranteed to be nul terminated.
|
||||
// (This is not true of StringPiece in general, but is true of UnicodeStringPiece)
|
||||
//
|
||||
class UnicodeStringPiece: public StringPiece {
|
||||
public:
|
||||
UnicodeStringPiece(const UnicodeString &s);
|
||||
~UnicodeStringPiece() {};
|
||||
private:
|
||||
MaybeStackArray<char, 20> buf;
|
||||
};
|
||||
|
||||
UnicodeStringPiece::UnicodeStringPiece(const UnicodeString &s) {
|
||||
int32_t len = s.length();
|
||||
int32_t capacity = buf.getCapacity();
|
||||
int32_t requiredCapacity = s.extract(0, len, buf.getAlias(), capacity) + 1;
|
||||
if (capacity < requiredCapacity) {
|
||||
buf.resize(requiredCapacity);
|
||||
capacity = requiredCapacity;
|
||||
s.extract(0, len, buf.getAlias(), capacity);
|
||||
}
|
||||
this->set(buf, requiredCapacity - 1);
|
||||
}
|
||||
|
||||
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
//
|
||||
// DataDrivenTests
|
||||
// The test cases are in a separate data file,
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
// Translate a Formattable::type enum value to a string, for error message formatting.
|
||||
static const char *formattableType(Formattable::Type typ) {
|
||||
static const char *types[] = {"kDate",
|
||||
"kDouble",
|
||||
"kLong",
|
||||
"kString",
|
||||
"kArray",
|
||||
"kInt64",
|
||||
"kObject"
|
||||
};
|
||||
if (typ<0 || typ>Formattable::kObject) {
|
||||
return "Unknown";
|
||||
}
|
||||
return types[typ];
|
||||
}
|
||||
|
||||
const char *
|
||||
DecimalFormatTest::getPath(char *buffer, const char *filename) {
|
||||
UErrorCode status=U_ZERO_ERROR;
|
||||
const char *testDataDirectory = IntlTest::getSourceTestData(status);
|
||||
DF_CHECK_STATUS;
|
||||
|
||||
strcpy(buffer, testDataDirectory);
|
||||
strcat(buffer, filename);
|
||||
return buffer;
|
||||
}
|
||||
|
||||
void DecimalFormatTest::DataDrivenTests() {
|
||||
char tdd[2048];
|
||||
const char *srcPath;
|
||||
UErrorCode status = U_ZERO_ERROR;
|
||||
int32_t lineNum = 0;
|
||||
|
||||
//
|
||||
// Open and read the test data file.
|
||||
//
|
||||
srcPath=getPath(tdd, "dcfmtest.txt");
|
||||
if(srcPath==NULL) {
|
||||
return; /* something went wrong, error already output */
|
||||
}
|
||||
|
||||
int32_t len;
|
||||
UChar *testData = ReadAndConvertFile(srcPath, len, status);
|
||||
if (U_FAILURE(status)) {
|
||||
return; /* something went wrong, error already output */
|
||||
}
|
||||
|
||||
//
|
||||
// Put the test data into a UnicodeString
|
||||
//
|
||||
UnicodeString testString(FALSE, testData, len);
|
||||
|
||||
RegexMatcher parseLineMat(UnicodeString(
|
||||
"(?i)\\s*parse\\s+"
|
||||
"\"([^\"]*)\"\\s+" // Capture group 1: input text
|
||||
"([ild])\\s+" // Capture group 2: expected parsed type
|
||||
"\"([^\"]*)\"\\s+" // Capture group 3: expected parsed decimal
|
||||
"\\s*(?:#.*)?"), // Trailing comment
|
||||
0, status);
|
||||
|
||||
RegexMatcher formatLineMat(UnicodeString(
|
||||
"(?i)\\s*format\\s+"
|
||||
"(\\S+)\\s+" // Capture group 1: pattern
|
||||
"(ceiling|floor|down|up|halfeven|halfdown|halfup|default)\\s+" // Capture group 2: Rounding Mode
|
||||
"\"([^\"]*)\"\\s+" // Capture group 3: input
|
||||
"\"([^\"]*)\"" // Capture group 4: expected output
|
||||
"\\s*(?:#.*)?"), // Trailing comment
|
||||
0, status);
|
||||
|
||||
RegexMatcher commentMat (UNICODE_STRING_SIMPLE("\\s*(#.*)?$"), 0, status);
|
||||
RegexMatcher lineMat(UNICODE_STRING_SIMPLE("(?m)^(.*?)$"), testString, 0, status);
|
||||
|
||||
if (U_FAILURE(status)){
|
||||
dataerrln("Construct RegexMatcher() error.");
|
||||
delete [] testData;
|
||||
return;
|
||||
}
|
||||
|
||||
//
|
||||
// Loop over the test data file, once per line.
|
||||
//
|
||||
while (lineMat.find()) {
|
||||
lineNum++;
|
||||
if (U_FAILURE(status)) {
|
||||
errln("File dcfmtest.txt, line %d: ICU Error \"%s\"", lineNum, u_errorName(status));
|
||||
}
|
||||
|
||||
status = U_ZERO_ERROR;
|
||||
UnicodeString testLine = lineMat.group(1, status);
|
||||
// printf("%s\n", UnicodeStringPiece(testLine).data());
|
||||
if (testLine.length() == 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
//
|
||||
// Parse the test line. Skip blank and comment only lines.
|
||||
// Separate out the three main fields - pattern, flags, target.
|
||||
//
|
||||
|
||||
commentMat.reset(testLine);
|
||||
if (commentMat.lookingAt(status)) {
|
||||
// This line is a comment, or blank.
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// Handle "parse" test case line from file
|
||||
//
|
||||
parseLineMat.reset(testLine);
|
||||
if (parseLineMat.lookingAt(status)) {
|
||||
execParseTest(lineNum,
|
||||
parseLineMat.group(1, status), // input
|
||||
parseLineMat.group(2, status), // Expected Type
|
||||
parseLineMat.group(3, status), // Expected Decimal String
|
||||
status
|
||||
);
|
||||
continue;
|
||||
}
|
||||
|
||||
//
|
||||
// Handle "format" test case line
|
||||
//
|
||||
formatLineMat.reset(testLine);
|
||||
if (formatLineMat.lookingAt(status)) {
|
||||
execFormatTest(lineNum,
|
||||
formatLineMat.group(1, status), // Pattern
|
||||
formatLineMat.group(2, status), // rounding mode
|
||||
formatLineMat.group(3, status), // input decimal number
|
||||
formatLineMat.group(4, status), // expected formatted result
|
||||
status);
|
||||
continue;
|
||||
}
|
||||
|
||||
//
|
||||
// Line is not a recognizable test case.
|
||||
//
|
||||
errln("Badly formed test case at line %d.\n%s\n",
|
||||
lineNum, UnicodeStringPiece(testLine).data());
|
||||
|
||||
}
|
||||
|
||||
delete [] testData;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void DecimalFormatTest::execParseTest(int32_t lineNum,
|
||||
const UnicodeString &inputText,
|
||||
const UnicodeString &expectedType,
|
||||
const UnicodeString &expectedDecimal,
|
||||
UErrorCode &status) {
|
||||
|
||||
if (U_FAILURE(status)) {
|
||||
return;
|
||||
}
|
||||
|
||||
DecimalFormatSymbols symbols(Locale::getUS(), status);
|
||||
UnicodeString pattern = UNICODE_STRING_SIMPLE("####");
|
||||
DecimalFormat format(pattern, symbols, status);
|
||||
Formattable result;
|
||||
if (U_FAILURE(status)) {
|
||||
errln("file dcfmtest.txt, line %d: %s error creating the formatter.",
|
||||
lineNum, u_errorName(status));
|
||||
return;
|
||||
}
|
||||
|
||||
ParsePosition pos;
|
||||
int32_t expectedParseEndPosition = inputText.length();
|
||||
|
||||
format.parse(inputText, result, pos);
|
||||
|
||||
if (expectedParseEndPosition != pos.getIndex()) {
|
||||
errln("file dcfmtest.txt, line %d: Expected parse position afeter parsing: %d. "
|
||||
"Actual parse position: %d", expectedParseEndPosition, pos.getIndex());
|
||||
return;
|
||||
}
|
||||
|
||||
char expectedTypeC[2];
|
||||
expectedType.extract(0, 1, expectedTypeC, 2, US_INV);
|
||||
Formattable::Type expectType = Formattable::kDate;
|
||||
switch (expectedTypeC[0]) {
|
||||
case 'd': expectType = Formattable::kDouble; break;
|
||||
case 'i': expectType = Formattable::kLong; break;
|
||||
case 'l': expectType = Formattable::kInt64; break;
|
||||
default:
|
||||
errln("file dcfmtest.tx, line %d: unrecongized expected type \"%s\"",
|
||||
lineNum, InvariantStringPiece(expectedType).data());
|
||||
return;
|
||||
}
|
||||
if (result.getType() != expectType) {
|
||||
errln("file dcfmtest.txt, line %d: expectedParseType(%s) != actual parseType(%s)",
|
||||
lineNum, formattableType(expectType), formattableType(result.getType()));
|
||||
return;
|
||||
}
|
||||
|
||||
StringPiece decimalResult = result.getDecimalNumber(status);
|
||||
if (U_FAILURE(status)) {
|
||||
errln("File %s, line %d: error %s. Line in file dcfmtest.txt: %d:",
|
||||
__FILE__, __LINE__, u_errorName(status), lineNum);
|
||||
return;
|
||||
}
|
||||
|
||||
InvariantStringPiece expectedResults(expectedDecimal);
|
||||
if (decimalResult != expectedResults) {
|
||||
errln("file dcfmtest.txt, line %d: expected \"%s\", got \"%s\"",
|
||||
lineNum, expectedResults.data(), decimalResult.data());
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void DecimalFormatTest::execFormatTest(int32_t lineNum,
|
||||
const UnicodeString &pattern, // Pattern
|
||||
const UnicodeString &round, // rounding mode
|
||||
const UnicodeString &input, // input decimal number
|
||||
const UnicodeString &expected, // expected formatted result
|
||||
UErrorCode &status) {
|
||||
if (U_FAILURE(status)) {
|
||||
return;
|
||||
}
|
||||
|
||||
DecimalFormatSymbols symbols(Locale::getUS(), status);
|
||||
// printf("Pattern = %s\n", UnicodeStringPiece(pattern).data());
|
||||
DecimalFormat fmtr(pattern, symbols, status);
|
||||
if (U_FAILURE(status)) {
|
||||
errln("file dcfmtest.txt, line %d: %s error creating the formatter.",
|
||||
lineNum, u_errorName(status));
|
||||
return;
|
||||
}
|
||||
if (round=="ceiling") {
|
||||
fmtr.setRoundingMode(DecimalFormat::kRoundCeiling);
|
||||
} else if (round=="floor") {
|
||||
fmtr.setRoundingMode(DecimalFormat::kRoundFloor);
|
||||
} else if (round=="down") {
|
||||
fmtr.setRoundingMode(DecimalFormat::kRoundDown);
|
||||
} else if (round=="up") {
|
||||
fmtr.setRoundingMode(DecimalFormat::kRoundUp);
|
||||
} else if (round=="halfeven") {
|
||||
fmtr.setRoundingMode(DecimalFormat::kRoundHalfEven);
|
||||
} else if (round=="halfdown") {
|
||||
fmtr.setRoundingMode(DecimalFormat::kRoundHalfDown);
|
||||
} else if (round=="halfup") {
|
||||
fmtr.setRoundingMode(DecimalFormat::kRoundHalfUp);
|
||||
} else if (round=="default") {
|
||||
// don't set any value.
|
||||
} else {
|
||||
fmtr.setRoundingMode(DecimalFormat::kRoundFloor);
|
||||
errln("file dcfmtest.txt, line %d: Bad rounding mode \"%s\"",
|
||||
lineNum, UnicodeStringPiece(round).data());
|
||||
}
|
||||
|
||||
UnicodeString result;
|
||||
UnicodeStringPiece spInput(input);
|
||||
//fmtr.format(spInput, result, NULL, status);
|
||||
|
||||
Formattable fmtbl;
|
||||
fmtbl.setDecimalNumber(spInput, status);
|
||||
NumberFormat &nfmtr = fmtr;
|
||||
fmtr.format(fmtbl, result, NULL, status);
|
||||
|
||||
if (U_FAILURE(status)) {
|
||||
errln("file dcfmtest.txt, line %d: format() returned %s.",
|
||||
lineNum, u_errorName(status));
|
||||
return;
|
||||
}
|
||||
|
||||
if (result != expected) {
|
||||
errln("file dcfmtest.txt, line %d: expected \"%s\", got \"%s\"",
|
||||
lineNum, UnicodeStringPiece(expected).data(), UnicodeStringPiece(result).data());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------------------------------------
|
||||
//
|
||||
// Read a text data file, convert it from UTF-8 to UChars, and return the data
|
||||
// in one big UChar * buffer, which the caller must delete.
|
||||
//
|
||||
// (Lightly modified version of a similar function in regextst.cpp)
|
||||
//
|
||||
//--------------------------------------------------------------------------------
|
||||
UChar *DecimalFormatTest::ReadAndConvertFile(const char *fileName, int32_t &ulen,
|
||||
UErrorCode &status) {
|
||||
UChar *retPtr = NULL;
|
||||
char *fileBuf = NULL;
|
||||
const char *fileBufNoBOM = NULL;
|
||||
FILE *f = NULL;
|
||||
|
||||
ulen = 0;
|
||||
if (U_FAILURE(status)) {
|
||||
return retPtr;
|
||||
}
|
||||
|
||||
//
|
||||
// Open the file.
|
||||
//
|
||||
f = fopen(fileName, "rb");
|
||||
if (f == 0) {
|
||||
dataerrln("Error opening test data file %s\n", fileName);
|
||||
status = U_FILE_ACCESS_ERROR;
|
||||
return NULL;
|
||||
}
|
||||
//
|
||||
// Read it in
|
||||
//
|
||||
int32_t fileSize;
|
||||
int32_t amtRead;
|
||||
int32_t amtReadNoBOM;
|
||||
|
||||
fseek( f, 0, SEEK_END);
|
||||
fileSize = ftell(f);
|
||||
fileBuf = new char[fileSize];
|
||||
fseek(f, 0, SEEK_SET);
|
||||
amtRead = fread(fileBuf, 1, fileSize, f);
|
||||
if (amtRead != fileSize || fileSize <= 0) {
|
||||
errln("Error reading test data file.");
|
||||
goto cleanUpAndReturn;
|
||||
}
|
||||
|
||||
//
|
||||
// Look for a UTF-8 BOM on the data just read.
|
||||
// The test data file is UTF-8.
|
||||
// The BOM needs to be there in the source file to keep the Windows &
|
||||
// EBCDIC machines happy, so force an error if it goes missing.
|
||||
// Many Linux editors will silently strip it.
|
||||
//
|
||||
fileBufNoBOM = fileBuf + 3;
|
||||
amtReadNoBOM = amtRead - 3;
|
||||
if (fileSize<3 || uprv_strncmp(fileBuf, "\xEF\xBB\xBF", 3) != 0) {
|
||||
// TODO: restore this check.
|
||||
// errln("Test data file %s is missing its BOM", fileName);
|
||||
fileBufNoBOM = fileBuf;
|
||||
amtReadNoBOM = amtRead;
|
||||
}
|
||||
|
||||
//
|
||||
// Find the length of the input in UTF-16 UChars
|
||||
// (by preflighting the conversion)
|
||||
//
|
||||
u_strFromUTF8(NULL, 0, &ulen, fileBufNoBOM, amtReadNoBOM, &status);
|
||||
|
||||
//
|
||||
// Convert file contents from UTF-8 to UTF-16
|
||||
//
|
||||
if (status == U_BUFFER_OVERFLOW_ERROR) {
|
||||
// Buffer Overflow is expected from the preflight operation.
|
||||
status = U_ZERO_ERROR;
|
||||
retPtr = new UChar[ulen+1];
|
||||
u_strFromUTF8(retPtr, ulen+1, NULL, fileBufNoBOM, amtReadNoBOM, &status);
|
||||
}
|
||||
|
||||
cleanUpAndReturn:
|
||||
fclose(f);
|
||||
delete[] fileBuf;
|
||||
if (U_FAILURE(status)) {
|
||||
errln("ICU Error \"%s\"\n", u_errorName(status));
|
||||
delete retPtr;
|
||||
retPtr = NULL;
|
||||
};
|
||||
return retPtr;
|
||||
}
|
||||
|
||||
#endif /* !UCONFIG_NO_REGULAR_EXPRESSIONS */
|
||||
|
53
icu4c/source/test/intltest/dcfmtest.h
Normal file
53
icu4c/source/test/intltest/dcfmtest.h
Normal file
|
@ -0,0 +1,53 @@
|
|||
/********************************************************************
|
||||
* COPYRIGHT:
|
||||
* Copyright (c) 2010, International Business Machines Corporation and
|
||||
* others. All Rights Reserved.
|
||||
********************************************************************/
|
||||
|
||||
//
|
||||
// file: dcfmtest.h
|
||||
//
|
||||
// Data driven decimal formatter test.
|
||||
// Includes testing of both parsing and formatting.
|
||||
// Tests are in the text file dcfmtest.txt, in the source/test/testdata/ directory.
|
||||
//
|
||||
|
||||
#ifndef DCFMTEST_H
|
||||
#define DCFMTEST_H
|
||||
|
||||
#include "unicode/utypes.h"
|
||||
#if !UCONFIG_NO_REGULAR_EXPRESSIONS
|
||||
|
||||
#include "intltest.h"
|
||||
|
||||
|
||||
class DecimalFormatTest: public IntlTest {
|
||||
public:
|
||||
|
||||
DecimalFormatTest();
|
||||
virtual ~DecimalFormatTest();
|
||||
|
||||
virtual void runIndexedTest(int32_t index, UBool exec, const char* &name, char* par = NULL );
|
||||
|
||||
// The following are test functions that are visible from the intltest test framework.
|
||||
virtual void DataDrivenTests();
|
||||
|
||||
// The following functions are internal to the decimal format tests.
|
||||
virtual UChar *ReadAndConvertFile(const char *fileName, int32_t &len, UErrorCode &status);
|
||||
virtual const char *getPath(char buffer[2048], const char *filename);
|
||||
virtual void execParseTest(int32_t lineNum,
|
||||
const UnicodeString &inputText,
|
||||
const UnicodeString &expectedType,
|
||||
const UnicodeString &expectedDecimal,
|
||||
UErrorCode &status);
|
||||
|
||||
virtual void execFormatTest(int32_t lineNum,
|
||||
const UnicodeString &pattern,
|
||||
const UnicodeString &round,
|
||||
const UnicodeString &input,
|
||||
const UnicodeString &expected,
|
||||
UErrorCode &status);
|
||||
};
|
||||
|
||||
#endif // !UCONFIG_NO_REGULAR_EXPRESSIONS
|
||||
#endif
|
|
@ -845,6 +845,14 @@
|
|||
RelativePath=".\dcfmapts.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\dcfmtest.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\dcfmtest.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\dtfmapts.cpp"
|
||||
>
|
||||
|
|
|
@ -54,6 +54,7 @@
|
|||
#include "dtifmtts.h" // DateIntervalFormatTest
|
||||
#include "tufmtts.h" // TimeUnitTest
|
||||
#include "locnmtst.h" // LocaleDisplayNamesTest
|
||||
#include "dcfmtest.h" // DecimalFormatTest
|
||||
|
||||
#define TESTCLASS(id, TestClass) \
|
||||
case id: \
|
||||
|
@ -127,6 +128,7 @@ void IntlTestFormat::runIndexedTest( int32_t index, UBool exec, const char* &nam
|
|||
TESTCLASS(38,TimeUnitTest);
|
||||
TESTCLASS(39,SelectFormatTest);
|
||||
TESTCLASS(40,LocaleDisplayNamesTest);
|
||||
TESTCLASS(41,DecimalFormatTest);
|
||||
|
||||
default: name = ""; break; //needed to end loop
|
||||
}
|
||||
|
|
|
@ -33,6 +33,7 @@
|
|||
|
||||
//#define NUMFMTST_CACHE_DEBUG 1
|
||||
#include "stdio.h" /* for sprintf */
|
||||
// #include "iostream" // for cout
|
||||
|
||||
//#define NUMFMTST_DEBUG 1
|
||||
|
||||
|
@ -106,6 +107,7 @@ void NumberFormatTest::runIndexedTest( int32_t index, UBool exec, const char* &n
|
|||
CASE(44,TestParseCurrencyInUCurr);
|
||||
CASE(45,TestFormatAttributes);
|
||||
CASE(46,TestFieldPositionIterator);
|
||||
CASE(47,TestDecimal);
|
||||
default: name = ""; break;
|
||||
}
|
||||
}
|
||||
|
@ -2570,26 +2572,26 @@ void NumberFormatTest::TestNonpositiveMultiplier() {
|
|||
expect(df, "1.2", -1.2);
|
||||
expect(df, "-1.2", 1.2);
|
||||
|
||||
// TODO: change all the following int64_t tests once BigInteger is ported
|
||||
// (right now the big numbers get turned into doubles and lose tons of accuracy)
|
||||
static const char* posOutOfRange = "9223372036854780000";
|
||||
static const char* negOutOfRange = "-9223372036854780000";
|
||||
|
||||
expect(df, U_INT64_MIN, posOutOfRange);
|
||||
expect(df, U_INT64_MIN+1, "9223372036854775807");
|
||||
expect(df, (int64_t)-123, "123");
|
||||
expect(df, (int64_t)123, "-123");
|
||||
// Note: the tests with the final parameter of FALSE will not round trip.
|
||||
// The initial numeric value will format correctly, after the multiplier.
|
||||
// Parsing the formatted text will be out-of-range for an int64, however.
|
||||
// The expect() function could be modified to detect this and fall back
|
||||
// to looking at the decimal parsed value, but it doesn't.
|
||||
expect(df, U_INT64_MIN, "9223372036854775808", FALSE);
|
||||
expect(df, U_INT64_MIN+1, "9223372036854775807");
|
||||
expect(df, (int64_t)-123, "123");
|
||||
expect(df, (int64_t)123, "-123");
|
||||
expect(df, U_INT64_MAX-1, "-9223372036854775806");
|
||||
expect(df, U_INT64_MAX, "-9223372036854775807");
|
||||
expect(df, U_INT64_MAX, "-9223372036854775807");
|
||||
|
||||
df.setMultiplier(-2);
|
||||
expect(df, -(U_INT64_MIN/2)-1, "-9223372036854775806");
|
||||
expect(df, -(U_INT64_MIN/2), "-9223372036854775808");
|
||||
expect(df, -(U_INT64_MIN/2)+1, negOutOfRange);
|
||||
expect(df, -(U_INT64_MIN/2), "-9223372036854775808");
|
||||
expect(df, -(U_INT64_MIN/2)+1, "-9223372036854775810", FALSE);
|
||||
|
||||
df.setMultiplier(-7);
|
||||
expect(df, -(U_INT64_MAX/7)-1, posOutOfRange);
|
||||
expect(df, -(U_INT64_MAX/7), "9223372036854775807");
|
||||
expect(df, -(U_INT64_MAX/7)-1, "9223372036854775814", FALSE);
|
||||
expect(df, -(U_INT64_MAX/7), "9223372036854775807");
|
||||
expect(df, -(U_INT64_MAX/7)+1, "9223372036854775800");
|
||||
|
||||
// TODO: uncomment (and fix up) all the following int64_t tests once BigInteger is ported
|
||||
|
@ -5964,4 +5966,151 @@ const char* attrString(int32_t attrId) {
|
|||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Test formatting & parsing of big decimals.
|
||||
// API test, not a comprehensive test.
|
||||
// See DecimalFormatTest/DataDrivenTests
|
||||
//
|
||||
#define ASSERT_SUCCESS(status) {if (U_FAILURE(status)) errln("file %s, line %d: status: %s", \
|
||||
__FILE__, __LINE__, u_errorName(status));}
|
||||
#define ASSERT_EQUALS(expected, actual) {if ((expected) != (actual)) \
|
||||
errln("file %s, line %d: %s != %s", __FILE__, __LINE__, #expected, #actual);}
|
||||
|
||||
static UBool operator != (const char *s1, UnicodeString &s2) {
|
||||
// This function lets ASSERT_EQUALS("literal", UnicodeString) work.
|
||||
UnicodeString us1(s1);
|
||||
return us1 != s2;
|
||||
}
|
||||
|
||||
void NumberFormatTest::TestDecimal() {
|
||||
{
|
||||
UErrorCode status = U_ZERO_ERROR;
|
||||
Formattable f("12.345678999987654321E666", status);
|
||||
ASSERT_SUCCESS(status);
|
||||
StringPiece s = f.getDecimalNumber(status);
|
||||
ASSERT_SUCCESS(status);
|
||||
ASSERT_EQUALS("1.2345678999987654321E+667", s);
|
||||
//printf("%s\n", s.data());
|
||||
}
|
||||
|
||||
{
|
||||
UErrorCode status = U_ZERO_ERROR;
|
||||
Formattable f1("this is not a number", status);
|
||||
ASSERT_EQUALS(U_DECIMAL_NUMBER_SYNTAX_ERROR, status);
|
||||
}
|
||||
|
||||
{
|
||||
UErrorCode status = U_ZERO_ERROR;
|
||||
Formattable f;
|
||||
f.setDecimalNumber("123.45", status);
|
||||
ASSERT_SUCCESS(status);
|
||||
ASSERT_EQUALS( Formattable::kDouble, f.getType());
|
||||
ASSERT_EQUALS(123.45, f.getDouble());
|
||||
ASSERT_EQUALS(123.45, f.getDouble(status));
|
||||
ASSERT_SUCCESS(status);
|
||||
ASSERT_EQUALS("123.45", f.getDecimalNumber(status));
|
||||
ASSERT_SUCCESS(status);
|
||||
|
||||
f.setDecimalNumber("4.5678E7", status);
|
||||
int32_t n;
|
||||
n = f.getLong();
|
||||
ASSERT_EQUALS(45678000, n);
|
||||
|
||||
status = U_ZERO_ERROR;
|
||||
f.setDecimalNumber("-123", status);
|
||||
ASSERT_SUCCESS(status);
|
||||
ASSERT_EQUALS( Formattable::kLong, f.getType());
|
||||
ASSERT_EQUALS(-123, f.getLong());
|
||||
ASSERT_EQUALS(-123, f.getLong(status));
|
||||
ASSERT_SUCCESS(status);
|
||||
ASSERT_EQUALS("-123", f.getDecimalNumber(status));
|
||||
ASSERT_SUCCESS(status);
|
||||
|
||||
status = U_ZERO_ERROR;
|
||||
f.setDecimalNumber("1234567890123", status); // Number too big for 32 bits
|
||||
ASSERT_SUCCESS(status);
|
||||
ASSERT_EQUALS( Formattable::kInt64, f.getType());
|
||||
ASSERT_EQUALS(1234567890123LL, f.getInt64());
|
||||
ASSERT_EQUALS(1234567890123LL, f.getInt64(status));
|
||||
ASSERT_SUCCESS(status);
|
||||
ASSERT_EQUALS("1234567890123", f.getDecimalNumber(status));
|
||||
ASSERT_SUCCESS(status);
|
||||
}
|
||||
|
||||
{
|
||||
UErrorCode status = U_ZERO_ERROR;
|
||||
NumberFormat *fmtr = NumberFormat::createInstance(
|
||||
Locale::getUS(), NumberFormat::kNumberStyle, status);
|
||||
UnicodeString formattedResult;
|
||||
StringPiece num("244444444444444444444444444444444444446.4");
|
||||
fmtr->format(num, formattedResult, NULL, status);
|
||||
ASSERT_SUCCESS(status);
|
||||
ASSERT_EQUALS("244,444,444,444,444,444,444,444,444,444,444,444,446.4", formattedResult);
|
||||
//std::string ss; std::cout << formattedResult.toUTF8String(ss);
|
||||
delete fmtr;
|
||||
}
|
||||
|
||||
{
|
||||
// Check formatting a DigitList. DigitList is internal, but this is
|
||||
// a critical interface that must work.
|
||||
UErrorCode status = U_ZERO_ERROR;
|
||||
NumberFormat *fmtr = NumberFormat::createInstance(
|
||||
Locale::getUS(), NumberFormat::kNumberStyle, status);
|
||||
ASSERT_SUCCESS(status);
|
||||
UnicodeString formattedResult;
|
||||
DigitList dl;
|
||||
StringPiece num("123.4566666666666666666666666666666666621E+40");
|
||||
dl.set(num, status);
|
||||
ASSERT_SUCCESS(status);
|
||||
fmtr->format(dl, formattedResult, NULL, status);
|
||||
ASSERT_SUCCESS(status);
|
||||
ASSERT_EQUALS("1,234,566,666,666,666,666,666,666,666,666,666,666,621,000", formattedResult);
|
||||
|
||||
status = U_ZERO_ERROR;
|
||||
num.set("666.666");
|
||||
dl.set(num, status);
|
||||
FieldPosition pos(NumberFormat::FRACTION_FIELD);
|
||||
ASSERT_SUCCESS(status);
|
||||
formattedResult.remove();
|
||||
fmtr->format(dl, formattedResult, pos, status);
|
||||
ASSERT_SUCCESS(status);
|
||||
ASSERT_EQUALS("666.666", formattedResult);
|
||||
ASSERT_EQUALS(4, pos.getBeginIndex());
|
||||
ASSERT_EQUALS(7, pos.getEndIndex());
|
||||
delete fmtr;
|
||||
}
|
||||
|
||||
{
|
||||
// Check a parse with a formatter with a multiplier.
|
||||
UErrorCode status = U_ZERO_ERROR;
|
||||
NumberFormat *fmtr = NumberFormat::createInstance(
|
||||
Locale::getUS(), NumberFormat::kPercentStyle, status);
|
||||
ASSERT_SUCCESS(status);
|
||||
UnicodeString input = "1.84%";
|
||||
Formattable result;
|
||||
fmtr->parse(input, result, status);
|
||||
ASSERT_SUCCESS(status);
|
||||
ASSERT_EQUALS(0, strcmp("0.0184", result.getDecimalNumber(status).data()));
|
||||
//std::cout << result.getDecimalNumber(status).data();
|
||||
delete fmtr;
|
||||
}
|
||||
|
||||
{
|
||||
// Check that a parse returns a decimal number with full accuracy
|
||||
UErrorCode status = U_ZERO_ERROR;
|
||||
NumberFormat *fmtr = NumberFormat::createInstance(
|
||||
Locale::getUS(), NumberFormat::kNumberStyle, status);
|
||||
ASSERT_SUCCESS(status);
|
||||
UnicodeString input = "1.002200044400088880000070000";
|
||||
Formattable result;
|
||||
fmtr->parse(input, result, status);
|
||||
ASSERT_SUCCESS(status);
|
||||
ASSERT_EQUALS(0, strcmp("1.00220004440008888000007", result.getDecimalNumber(status).data()));
|
||||
ASSERT_EQUALS(1.00220004440008888, result.getDouble());
|
||||
//std::cout << result.getDecimalNumber(status).data();
|
||||
delete fmtr;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif /* #if !UCONFIG_NO_FORMATTING */
|
||||
|
|
|
@ -145,6 +145,8 @@ class NumberFormatTest: public CalendarTimeZoneTest {
|
|||
void TestFormatAttributes();
|
||||
void TestFieldPositionIterator();
|
||||
|
||||
void TestDecimal();
|
||||
|
||||
private:
|
||||
|
||||
static UBool equalValue(const Formattable& a, const Formattable& b);
|
||||
|
|
|
@ -1941,6 +1941,7 @@ void NumberFormatRegressionTest::Test4145457() {
|
|||
out2 = nf->format(pi, out2, pos);
|
||||
UnicodeString pat2;
|
||||
pat2 = nf->toPattern(pat2);
|
||||
pp.setIndex(0);
|
||||
nf->parse(out2, num, pp);
|
||||
double val2 = num.getDouble();
|
||||
|
||||
|
|
128
icu4c/source/test/testdata/dcfmtest.txt
vendored
Normal file
128
icu4c/source/test/testdata/dcfmtest.txt
vendored
Normal file
|
@ -0,0 +1,128 @@
|
|||
|
||||
# Copyright (c) 2010, International Business Machines Corporation and
|
||||
# others. All Rights Reserved.
|
||||
#
|
||||
|
||||
# File: dcfmtest.txt
|
||||
#
|
||||
# Decimal formatter test cases.
|
||||
# File Encoding: UTF-8
|
||||
#
|
||||
# The syntax for this file is this:
|
||||
# One test case per line. No continuations. No multiple cases per line.
|
||||
#
|
||||
# Parsing Test case line:
|
||||
# parse "input text" type "expected_decimal_text"
|
||||
#
|
||||
# Format Test Case Line:
|
||||
# format pattern round-mode "decimal number" "expected formatted result"
|
||||
#
|
||||
# Fields are separated by spaces or tabs. Input text to be parsed, decimal numbers
|
||||
# and formatted output are "quoted". Other fields are not.
|
||||
#
|
||||
# "type" is a single letter, representing the type that the ICU formattable produces
|
||||
# for the input.
|
||||
# d double
|
||||
# i int32
|
||||
# l int64
|
||||
#
|
||||
# RoundingMode is one of
|
||||
# default
|
||||
# ceiling
|
||||
# floor
|
||||
# down
|
||||
# up
|
||||
# halfeven
|
||||
# halfdown
|
||||
# halfup
|
||||
#
|
||||
|
||||
parse "123.45" d "123.45"
|
||||
|
||||
format 0.0000E0 default "1234.01" "1.2340E3"
|
||||
|
||||
format 00 default "1234" "1234"
|
||||
format 00 default ".01" "00"
|
||||
format 00 default "1" "01"
|
||||
format 00 default "1.9" "02"
|
||||
|
||||
format #.# default "12.34" "12.3"
|
||||
|
||||
format @@@ default "12.3456" "12.3"
|
||||
format @@@ default "123456" "123000"
|
||||
format @@@ default ".00123456" "0.00123"
|
||||
|
||||
format @@### default "12345678" "12346000"
|
||||
format @@### default "12300001" "12300000"
|
||||
format @@### default ".0012345678" "0.0012346"
|
||||
format @@### default ".0012300000" "0.00123"
|
||||
|
||||
format @@@@E0 default "1234567" "1.235E6"
|
||||
format 0.0##E0 default "1234567" "1.235E6"
|
||||
format 00.##E0 default "1234567" "12.35E5"
|
||||
format 00.##E0 default "1234567E111" "12.35E116"
|
||||
format 00.##E0 default "-1234567E111" "-12.35E116"
|
||||
|
||||
|
||||
#
|
||||
# Rounding Modes
|
||||
#
|
||||
format 0.00 default "32.045" "32.04"
|
||||
format 0.00 floor "32.045" "32.04"
|
||||
format 0.00 ceiling "32.045" "32.05"
|
||||
format 0.00 down "32.045" "32.04"
|
||||
format 0.00 up "32.045" "32.05"
|
||||
format 0.00 halfeven "32.045" "32.04"
|
||||
format 0.00 halfdown "32.045" "32.04"
|
||||
format 0.00 halfup "32.045" "32.05"
|
||||
|
||||
format 0.00 default "-32.045" "-32.04"
|
||||
format 0.00 floor "-32.045" "-32.05"
|
||||
format 0.00 ceiling "-32.045" "-32.04"
|
||||
format 0.00 down "-32.045" "-32.04"
|
||||
format 0.00 up "-32.045" "-32.05"
|
||||
format 0.00 halfeven "-32.045" "-32.04"
|
||||
format 0.00 halfdown "-32.045" "-32.04"
|
||||
format 0.00 halfup "-32.045" "-32.05"
|
||||
|
||||
format @@@ default "1235.00" "1240"
|
||||
format @@@ floor "1235.00" "1230"
|
||||
format @@@ ceiling "1235.00" "1240"
|
||||
format @@@ down "1235.00" "1230"
|
||||
format @@@ up "1235.00" "1240"
|
||||
format @@@ halfeven "1235.00" "1240"
|
||||
format @@@ halfdown "1235.00" "1230"
|
||||
format @@@ halfup "1235.00" "1240"
|
||||
|
||||
format @@@ default "-1235.00" "-1240"
|
||||
format @@@ floor "-1235.00" "-1240"
|
||||
format @@@ ceiling "-1235.00" "-1230"
|
||||
format @@@ down "-1235.00" "-1230"
|
||||
format @@@ up "-1235.00" "-1240"
|
||||
format @@@ halfeven "-1235.00" "-1240"
|
||||
format @@@ halfdown "-1235.00" "-1230"
|
||||
format @@@ halfup "-1235.00" "-1240"
|
||||
|
||||
format 0.000E0 default "12345" "1.234E4"
|
||||
format 0.000E0 floor "12345" "1.234E4"
|
||||
format 0.000E0 ceiling "12345" "1.235E4"
|
||||
format 0.000E0 down "12345" "1.234E4"
|
||||
format 0.000E0 up "12345" "1.235E4"
|
||||
format 0.000E0 halfeven "12345" "1.234E4"
|
||||
format 0.000E0 halfdown "12345" "1.234E4"
|
||||
format 0.000E0 halfup "12345" "1.235E4"
|
||||
|
||||
|
||||
format 0.0## default "1.00001" "1.0"
|
||||
format 0.0## up "1.00001" "1.001"
|
||||
format 0.0## up "1.0000000000000000000000000000000000000000000000000001" "1.001"
|
||||
format 0.0## up "1.0000000000000000000000000000000000000000000000000000" "1.0"
|
||||
|
||||
format # default "10000000000000000000000000000000000000000000000000001" "10000000000000000000000000000000000000000000000000001"
|
||||
|
||||
format 0.#E0 default "1234" "1.2E3"
|
||||
format 0.##E0 default "1234" "1.23E3"
|
||||
format .0E0 default "1234" ".1E4"
|
||||
format .0#E0 default "1234" ".12E4"
|
||||
format 0.##E0 default "1234" "1.23E3"
|
||||
|
Loading…
Add table
Reference in a new issue