mirror of
https://github.com/unicode-org/icu.git
synced 2025-04-15 01:42:37 +00:00
ICU-1271 Be more friendly to non-IEEE754 platforms and use the putil.h functions.
X-SVN-Rev: 6198
This commit is contained in:
parent
6fb93470d2
commit
1aa7e6714d
9 changed files with 160 additions and 255 deletions
|
@ -134,6 +134,7 @@ static double fgInf;
|
|||
/* protos */
|
||||
static char* u_topNBytesOfDouble(double* d, int n);
|
||||
static char* u_bottomNBytesOfDouble(double* d, int n);
|
||||
static void uprv_longBitsFromDouble(double d, int32_t *hi, uint32_t *lo);
|
||||
|
||||
|
||||
/*---------------------------------------------------------------------------
|
||||
|
@ -369,6 +370,12 @@ uprv_ceil(double x)
|
|||
return ceil(x);
|
||||
}
|
||||
|
||||
double
|
||||
uprv_round(double x)
|
||||
{
|
||||
return uprv_floor(x + 0.5);
|
||||
}
|
||||
|
||||
double
|
||||
uprv_fabs(double x)
|
||||
{
|
||||
|
@ -388,127 +395,18 @@ uprv_fmod(double x, double y)
|
|||
}
|
||||
|
||||
double
|
||||
uprv_pow10(int32_t x)
|
||||
uprv_pow(double x, double y)
|
||||
{
|
||||
/* This is declared as "double pow(double x, double y)" */
|
||||
return pow(x, y);
|
||||
}
|
||||
|
||||
double
|
||||
uprv_pow10(int32_t x)
|
||||
{
|
||||
return pow(10.0, (double)x);
|
||||
}
|
||||
|
||||
/**
|
||||
* Computes the remainder of an implied division of its operands, as
|
||||
* defined by the IEEE 754 standard. Commonly used to bring a value
|
||||
* into range without losing accuracy; e.g., bringing a large argument
|
||||
* to sin() into range.
|
||||
*
|
||||
* Returns r, where x = n * p + r. Here n is the integer nearest to
|
||||
* x / p. If two integers are equidistant from x / p, n is the even
|
||||
* integer. If r is zero, then it should have the same sign as the
|
||||
* dividend x.
|
||||
*
|
||||
* The IEEE remainder may be negative or positive.
|
||||
* IEEEremainder(5,3) = -1. IEEEremainder(4,3) = 1.
|
||||
*
|
||||
* The IEEE remainder r is always less than or equal to p/2 in
|
||||
* absolute value. That is, |r| <= |p/2|. By comparison, fmod()
|
||||
* returns a remainder r such that |r| <= |p|.
|
||||
*
|
||||
* Some floating point processors can compute this value in hardware.
|
||||
* We provide two implementations here, one that manipulates the IEEE
|
||||
* bit pattern directly, and one that is built upon other floating
|
||||
* point operations. The former implementation has superior accuracy
|
||||
* and is preferred; the latter may work on platforms where the former
|
||||
* fails, but will introduce inaccuracies.
|
||||
*/
|
||||
#if 0
|
||||
/* Several compilers can't optimize this properly, and no one uses it. */
|
||||
double
|
||||
uprv_IEEEremainder(double x, double p)
|
||||
{
|
||||
#if IEEE_754
|
||||
int32_t hx, hp;
|
||||
uint32_t sx, lx, lp;
|
||||
double p_half;
|
||||
|
||||
hx = *(int32_t*)u_topNBytesOfDouble(&x, sizeof(int32_t));
|
||||
lx = *(uint32_t*)u_bottomNBytesOfDouble(&x, sizeof(uint32_t));
|
||||
|
||||
hp = *(int32_t*)u_topNBytesOfDouble(&p, sizeof(int32_t));
|
||||
lp = *(uint32_t*)u_bottomNBytesOfDouble(&p, sizeof(uint32_t));
|
||||
|
||||
sx = hx & SIGN;
|
||||
|
||||
hp &= 0x7fffffff;
|
||||
hx &= 0x7fffffff;
|
||||
|
||||
/* purge off exception values */
|
||||
if((hp|lp) == 0)
|
||||
{
|
||||
return (x*p) / (x*p); /* p = 0 */
|
||||
}
|
||||
if((hx >= 0x7ff00000)|| /* x not finite */
|
||||
((hp>=0x7ff00000) && /* p is NaN */
|
||||
(((hp-0x7ff00000)|lp) != 0)))
|
||||
{
|
||||
return uprv_getNaN();
|
||||
}
|
||||
|
||||
if(hp <= 0x7fdfffff)
|
||||
{
|
||||
x = uprv_fmod(x, p + p); /* now x < 2p */
|
||||
}
|
||||
if(((hx-hp)|(lx-lp)) == 0)
|
||||
{
|
||||
return 0.0 * x;
|
||||
}
|
||||
x = uprv_fabs(x);
|
||||
p = uprv_fabs(p);
|
||||
if (hp < 0x00200000) {
|
||||
if(x + x > p) {
|
||||
x -= p;
|
||||
if(x + x >= p)
|
||||
x -= p;
|
||||
}
|
||||
}
|
||||
else {
|
||||
p_half = 0.5 * p;
|
||||
if(x > p_half) {
|
||||
x -= p;
|
||||
if(x >= p_half)
|
||||
x -= p;
|
||||
}
|
||||
}
|
||||
|
||||
*(int32_t*)u_topNBytesOfDouble(&x, sizeof(int32_t)) ^= sx;
|
||||
|
||||
return x;
|
||||
|
||||
#else
|
||||
/* INACCURATE but portable implementation of IEEEremainder. This
|
||||
* implementation should work on platforms that do not have IEEE
|
||||
* bit layouts. Deficiencies of this implementation are its
|
||||
* inaccuracy and that it does not attempt to handle NaN or
|
||||
* infinite parameters and it returns the dividend if the divisor
|
||||
* is zero. This is probably not an issue on non-IEEE
|
||||
* platforms. - aliu
|
||||
*/
|
||||
if (p != 0.0) { /* exclude zero divisor */
|
||||
double a = x / p;
|
||||
double aint = uprv_floor(a);
|
||||
double afrac = a - aint;
|
||||
if (afrac > 0.5) {
|
||||
aint += 1.0;
|
||||
} else if (!(afrac < 0.5)) { /* avoid == comparison */
|
||||
if (uprv_modf(aint / 2.0, &a) > 0.0) {
|
||||
aint += 1.0;
|
||||
}
|
||||
}
|
||||
x -= (p * aint);
|
||||
}
|
||||
return x;
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
double
|
||||
uprv_fmax(double x, double y)
|
||||
{
|
||||
|
@ -524,12 +422,10 @@ uprv_fmax(double x, double y)
|
|||
if(x == 0.0 && y == 0.0 && (lowBits & SIGN))
|
||||
return y;
|
||||
|
||||
return (x > y ? x : y);
|
||||
#else
|
||||
#endif
|
||||
|
||||
/* this should work for all flt point w/o NaN and Infpecial cases */
|
||||
return (x > y ? x : y);
|
||||
#endif
|
||||
}
|
||||
|
||||
int32_t
|
||||
|
@ -553,12 +449,10 @@ uprv_fmin(double x, double y)
|
|||
if(x == 0.0 && y == 0.0 && (lowBits & SIGN))
|
||||
return y;
|
||||
|
||||
return (x > y ? y : x);
|
||||
#else
|
||||
#endif
|
||||
|
||||
/* this should work for all flt point w/o NaN and Inf special cases */
|
||||
return (x > y ? y : x);
|
||||
#endif
|
||||
}
|
||||
|
||||
int32_t
|
||||
|
@ -593,18 +487,27 @@ uprv_trunc(double d)
|
|||
return floor(d);
|
||||
|
||||
#else
|
||||
return d >= 0 ? floor(d) : ceil(d);
|
||||
return d >= 0 ? floor(d) : ceil(d);
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
static void
|
||||
uprv_longBitsFromDouble(double d, int32_t *hi, uint32_t *lo)
|
||||
{
|
||||
*hi = *(int32_t*)u_topNBytesOfDouble(&d, sizeof(int32_t));
|
||||
*lo = *(uint32_t*)u_bottomNBytesOfDouble(&d, sizeof(uint32_t));
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the largest positive number that can be represented by an integer
|
||||
* type of arbitrary bit length.
|
||||
*/
|
||||
double
|
||||
uprv_maxMantissa(void)
|
||||
{
|
||||
return pow(2.0, DBL_MANT_DIG + 1.0) - 1.0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the floor of the log base 10 of a given double.
|
||||
|
@ -640,6 +543,12 @@ uprv_log10(double d)
|
|||
#endif
|
||||
}
|
||||
|
||||
double
|
||||
uprv_log(double d)
|
||||
{
|
||||
return log(d);
|
||||
}
|
||||
|
||||
int32_t
|
||||
uprv_digitsAfterDecimal(double x)
|
||||
{
|
||||
|
|
|
@ -39,30 +39,31 @@
|
|||
/**
|
||||
* Platform utilities isolates the platform dependencies of the
|
||||
* libarary. For each platform which this code is ported to, these
|
||||
* functions may have to be re-implemented. */
|
||||
* functions may have to be re-implemented.
|
||||
*/
|
||||
|
||||
/* Floating point utilities
|
||||
* @draft
|
||||
*/
|
||||
U_CAPI UBool U_EXPORT2 uprv_isNaN(double);
|
||||
U_CAPI UBool U_EXPORT2 uprv_isInfinite(double);
|
||||
U_CAPI UBool U_EXPORT2 uprv_isNaN(double);
|
||||
U_CAPI UBool U_EXPORT2 uprv_isInfinite(double);
|
||||
U_CAPI UBool U_EXPORT2 uprv_isPositiveInfinity(double);
|
||||
U_CAPI UBool U_EXPORT2 uprv_isNegativeInfinity(double);
|
||||
U_CAPI double U_EXPORT2 uprv_getNaN(void);
|
||||
U_CAPI double U_EXPORT2 uprv_getInfinity(void);
|
||||
U_CAPI double U_EXPORT2 uprv_getNaN(void);
|
||||
U_CAPI double U_EXPORT2 uprv_getInfinity(void);
|
||||
|
||||
U_CAPI double U_EXPORT2 uprv_floor(double x);
|
||||
U_CAPI double U_EXPORT2 uprv_ceil(double x);
|
||||
U_CAPI double U_EXPORT2 uprv_fabs(double x);
|
||||
U_CAPI double U_EXPORT2 uprv_modf(double x, double* y);
|
||||
U_CAPI double U_EXPORT2 uprv_fmod(double x, double y);
|
||||
U_CAPI double U_EXPORT2 uprv_pow10(int32_t x);
|
||||
U_CAPI double U_EXPORT2 uprv_fmax(double x, double y);
|
||||
U_CAPI double U_EXPORT2 uprv_fmin(double x, double y);
|
||||
U_CAPI int32_t U_EXPORT2 uprv_max(int32_t x, int32_t y);
|
||||
U_CAPI int32_t U_EXPORT2 uprv_min(int32_t x, int32_t y);
|
||||
U_CAPI double U_EXPORT2 uprv_trunc(double d);
|
||||
U_CAPI void U_EXPORT2 uprv_longBitsFromDouble(double d, int32_t *hi, uint32_t *lo);
|
||||
U_CAPI double U_EXPORT2 uprv_trunc(double d);
|
||||
U_CAPI double U_EXPORT2 uprv_floor(double x);
|
||||
U_CAPI double U_EXPORT2 uprv_ceil(double x);
|
||||
U_CAPI double U_EXPORT2 uprv_fabs(double x);
|
||||
U_CAPI double U_EXPORT2 uprv_modf(double x, double* y);
|
||||
U_CAPI double U_EXPORT2 uprv_fmod(double x, double y);
|
||||
U_CAPI double U_EXPORT2 uprv_pow(double x, double y);
|
||||
U_CAPI double U_EXPORT2 uprv_pow10(int32_t x);
|
||||
U_CAPI double U_EXPORT2 uprv_fmax(double x, double y);
|
||||
U_CAPI double U_EXPORT2 uprv_fmin(double x, double y);
|
||||
U_CAPI int32_t U_EXPORT2 uprv_max(int32_t x, int32_t y);
|
||||
U_CAPI int32_t U_EXPORT2 uprv_min(int32_t x, int32_t y);
|
||||
|
||||
#if U_IS_BIG_ENDIAN
|
||||
# define uprv_isNegative(number) (*((signed char *)&(number))<0)
|
||||
|
@ -70,15 +71,18 @@ U_CAPI void U_EXPORT2 uprv_longBitsFromDouble(double d, int32_t *hi, uint32_
|
|||
# define uprv_isNegative(number) (*((signed char *)&(number)+sizeof(number)-1)<0)
|
||||
#endif
|
||||
|
||||
/*
|
||||
/**
|
||||
* Return the largest positive number that can be represented by an integer
|
||||
* type of arbitrary bit length.
|
||||
*/
|
||||
U_CAPI double U_EXPORT2 uprv_maxMantissa(void);
|
||||
|
||||
/**
|
||||
* Return the floor of the log base 10 of a given double.
|
||||
* This method compensates for inaccuracies which arise naturally when
|
||||
* computing logs, and always gives the correct value. The parameter
|
||||
* must be positive and finite.
|
||||
* (Thanks to Alan Liu for supplying this function.)
|
||||
*/
|
||||
/**
|
||||
* Returns the common log of the double value d.
|
||||
*
|
||||
* @param d the double value to apply the common log function for.
|
||||
* @return the log of value d.
|
||||
|
@ -86,6 +90,11 @@ U_CAPI void U_EXPORT2 uprv_longBitsFromDouble(double d, int32_t *hi, uint32_
|
|||
*/
|
||||
U_CAPI int16_t U_EXPORT2 uprv_log10(double d);
|
||||
|
||||
U_CAPI double U_EXPORT2 uprv_log(double d);
|
||||
|
||||
/** Does common notion of rounding e.g. uprv_floor(x + 0.5); */
|
||||
U_CAPI double U_EXPORT2 uprv_round(double x);
|
||||
|
||||
/**
|
||||
* Returns the number of digits after the decimal point in a double number x.
|
||||
*
|
||||
|
|
|
@ -14,6 +14,9 @@
|
|||
*/
|
||||
|
||||
#include "llong.h"
|
||||
#include <float.h>
|
||||
|
||||
U_NAMESPACE_BEGIN
|
||||
|
||||
#if 0
|
||||
/*
|
||||
|
@ -29,7 +32,6 @@ const llong& llong::kOne = llong(0x0, 0x1);
|
|||
const llong& llong::kTwo = llong(0x0, 0x2);
|
||||
const llong& llong::kMaxDouble = llong(0x200000, 0x0);
|
||||
const llong& llong::kMinDouble = -kMaxDouble;
|
||||
#endif
|
||||
|
||||
static llong kMaxValueObj(0x7fffffff, 0xffffffff);
|
||||
static llong kMinValueObj(0x80000000, 0x0);
|
||||
|
@ -49,11 +51,38 @@ const llong& llong::kTwo = kTwoObj;
|
|||
const llong& llong::kMaxDouble = kMaxDoubleObj;
|
||||
const llong& llong::kMinDouble = kMinDoubleObj;
|
||||
|
||||
const double llong::kDMax = llong_asDouble(kMaxDouble);
|
||||
const double llong::kDMin = -kDMax;
|
||||
#endif
|
||||
|
||||
#define SQRT231 46340
|
||||
|
||||
const double llong::kD32 = ((double)(0xffffffffu)) + 1;
|
||||
const double llong::kDMax = llong_asDouble(kMaxDouble);
|
||||
const double llong::kDMin = -kDMax;
|
||||
|
||||
llong::llong(double d) { // avoid dependency on bit representation of double
|
||||
if (uprv_isNaN(d)) {
|
||||
hi = 0;
|
||||
lo = 0; /* zero */
|
||||
} else {
|
||||
double mant = uprv_maxMantissa();
|
||||
if (d < -mant) {
|
||||
d = -mant;
|
||||
} else if (d > mant) {
|
||||
d = mant;
|
||||
}
|
||||
UBool neg = d < 0;
|
||||
if (neg) {
|
||||
d = -d;
|
||||
}
|
||||
d = uprv_floor(d);
|
||||
hi = (int32_t)uprv_floor(d / kD32);
|
||||
d -= kD32 * hi;
|
||||
lo = (uint32_t)d;
|
||||
if (neg) {
|
||||
negate();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
llong& llong::operator*=(const llong& rhs)
|
||||
{
|
||||
|
@ -119,11 +148,12 @@ llong& llong::operator/=(const llong& rhs)
|
|||
}
|
||||
|
||||
if (b.isZero()) { // should throw div by zero error
|
||||
*this = sign < 0 ? kMinValue : kMaxValue;
|
||||
*this = sign < 0 ? -uprv_maxMantissa() : uprv_maxMantissa();
|
||||
} else if (a.hi == 0 && b.hi == 0) {
|
||||
*this = (int32_t)(sign * (a.lo / b.lo));
|
||||
} else if (b > a) {
|
||||
*this = kZero;
|
||||
hi = 0;
|
||||
lo = 0; /* zero */
|
||||
} else if (b == a) {
|
||||
*this = sign;
|
||||
} else {
|
||||
|
@ -322,3 +352,5 @@ uint32_t u_lltoa(const llong& val, UChar* buf, uint32_t len, uint32_t radix, UBo
|
|||
|
||||
return len;
|
||||
}
|
||||
|
||||
U_NAMESPACE_END
|
||||
|
|
|
@ -16,11 +16,10 @@
|
|||
#ifndef LLONG_H
|
||||
#define LLONG_H
|
||||
|
||||
// debug
|
||||
#include <stdio.h>
|
||||
|
||||
#include "unicode/utypes.h"
|
||||
|
||||
U_NAMESPACE_BEGIN
|
||||
|
||||
// machine dependent value, need to move
|
||||
//#define __u_IntBits 32
|
||||
|
||||
|
@ -29,20 +28,17 @@ private:
|
|||
uint32_t lo;
|
||||
int32_t hi;
|
||||
private:
|
||||
enum {
|
||||
MASK32 = 0xffffffffu
|
||||
};
|
||||
|
||||
static const double kD32; // 2^^32 as a double
|
||||
static const double kDMin; // -(2^^54), minimum double with full integer precision
|
||||
static const double kDMax; // 2^^54, maximum double with full integer precision
|
||||
|
||||
// private constructor
|
||||
// should be private, but we can't construct the way we want using SOLARISCC
|
||||
// so make public in order that file statics can access this constructor
|
||||
public:
|
||||
public:
|
||||
static const double kD32; // 2^^32 as a double
|
||||
static const double kDMin; // -(2^^54), minimum double with full integer precision
|
||||
static const double kDMax; // 2^^54, maximum double with full integer precision
|
||||
|
||||
llong(int32_t h, uint32_t l) : lo(l), hi(h) {}
|
||||
private:
|
||||
private:
|
||||
// convenience, size reduction in inline code
|
||||
llong& nnot() { hi = ~hi; lo = ~lo; return *this; }
|
||||
llong& negate() { hi = ~hi; lo = ~lo; if (!++lo) ++hi; return *this; }
|
||||
|
@ -64,23 +60,7 @@ public:
|
|||
//#if __u_IntBits == 64
|
||||
// llong(unsigned int i) : lo(i & MASK32), hi(i >> 32) {}
|
||||
//#endif
|
||||
llong(double d) { // avoid dependency on bit representation of double
|
||||
if (uprv_isNaN(d)) {
|
||||
*this = llong::kZero;
|
||||
} else if (d < kDMin) {
|
||||
*this = llong::kMinDouble;
|
||||
} else if (d > kDMax) {
|
||||
*this = llong::kMaxDouble;
|
||||
} else {
|
||||
int neg = d < 0;
|
||||
if (neg) d = -d;
|
||||
d = uprv_floor(d);
|
||||
hi = (int32_t)uprv_floor(d / kD32);
|
||||
d -= kD32 * hi;
|
||||
lo = (uint32_t)d;
|
||||
if (neg) negate();
|
||||
}
|
||||
}
|
||||
llong(double d);
|
||||
|
||||
llong(const llong& rhs) : lo(rhs.lo), hi(rhs.hi) {}
|
||||
|
||||
|
@ -217,16 +197,12 @@ public:
|
|||
friend uint32_t u_lltoa(const llong& lhs, UChar* buffer, uint32_t buflen, uint32_t radix = 10, UBool raw = FALSE);
|
||||
|
||||
// useful public constants - perhaps should not have class statics
|
||||
static const llong& kMaxValue;
|
||||
static const llong& kMinValue;
|
||||
static const llong& kMinusOne;
|
||||
static const llong& kZero;
|
||||
static const llong& kOne;
|
||||
static const llong& kTwo;
|
||||
// static const llong getZero();
|
||||
// static const llong getOne();
|
||||
|
||||
private:
|
||||
static const llong& kMaxDouble;
|
||||
static const llong& kMinDouble;
|
||||
static const llong getMaxDouble();
|
||||
static const llong getMinDouble();
|
||||
|
||||
// right shift without sign extension
|
||||
llong& ushr(int32_t shift) {
|
||||
|
@ -292,9 +268,9 @@ inline double llong_asDouble(const llong& lhs) { return llong::kD32 * lhs.hi +
|
|||
|
||||
inline llong llong_pow(const llong& lhs, uint32_t n) {
|
||||
if (lhs.isZero()) {
|
||||
return llong::kZero;
|
||||
return llong(0, 0); /* zero */
|
||||
} else if (n == 0) {
|
||||
return llong::kOne;
|
||||
return llong(0, 1); /* one */
|
||||
} else {
|
||||
llong r(lhs);
|
||||
while (--n > 0) {
|
||||
|
@ -321,5 +297,7 @@ inline UBool operator>=(const llong& lhs, const uint32_t rhs) { return lhs.hi ==
|
|||
inline UBool operator<=(const llong& lhs, const uint32_t rhs) { return lhs.hi == 0 ? lhs.lo <= rhs : lhs.hi <= 0; }
|
||||
#endif
|
||||
|
||||
U_NAMESPACE_END
|
||||
|
||||
// LLONG_H
|
||||
#endif
|
||||
|
|
|
@ -13,8 +13,6 @@
|
|||
* 10/11/2001 Doug Ported from ICU4J
|
||||
*/
|
||||
|
||||
#include <math.h>
|
||||
|
||||
#include "nfrs.h"
|
||||
#include "nfrule.h"
|
||||
#include "nfrlist.h"
|
||||
|
@ -447,7 +445,7 @@ NFRuleSet::findFractionRuleSetRule(double number) const
|
|||
}
|
||||
// for each rule, do the following...
|
||||
llong tempDifference;
|
||||
llong difference = llong::kMaxValue;
|
||||
llong difference(uprv_maxMantissa());
|
||||
int32_t winner = 0;
|
||||
for (uint32_t i = 0; i < rules.size(); ++i) {
|
||||
// "numerator" is the numerator of the fraction if the
|
||||
|
|
|
@ -78,9 +78,9 @@ static const UChar gEmptyString[] = {0}; /* "" */
|
|||
static const UChar gGreaterGreaterGreater[] = {0x3E, 0x3E, 0x3E, 0}; /* ">>>" */
|
||||
|
||||
static const UChar * const tokenStrings[] = {
|
||||
gLessLess, gLessPercent, gLessHash, gLessZero,
|
||||
gGreaterGreater, gGreaterPercent,gGreaterHash, gGreaterZero,
|
||||
gEqualPercent, gEqualHash, gEqualZero, NULL
|
||||
gLessLess, gLessPercent, gLessHash, gLessZero,
|
||||
gGreaterGreater, gGreaterPercent,gGreaterHash, gGreaterZero,
|
||||
gEqualPercent, gEqualHash, gEqualZero, NULL
|
||||
};
|
||||
|
||||
void
|
||||
|
@ -492,7 +492,7 @@ NFRule::expectedExponent() const
|
|||
// we get rounding error in some cases-- for example, log 1000 / log 10
|
||||
// gives us 1.9999999996 instead of 2. The extra logic here is to take
|
||||
// that into account
|
||||
int16_t tempResult = (int16_t)(log(llong_asDouble(baseValue)) / log((double)radix));
|
||||
int16_t tempResult = (int16_t)(uprv_log(llong_asDouble(baseValue)) / uprv_log((double)radix));
|
||||
llong temp = llong_pow(radix, tempResult + 1);
|
||||
if (temp <= baseValue) {
|
||||
tempResult += 1;
|
||||
|
@ -709,7 +709,7 @@ NFRule::shouldRollBack(double number) const
|
|||
// multiple of 100. This is called the "rollback rule."
|
||||
if ((sub1->isModulusSubstitution()) || (sub2->isModulusSubstitution())) {
|
||||
llong re = llong_pow(radix, exponent);
|
||||
return java_fmod(number, llong_asDouble(re)) == 0 && (baseValue % re) != 0;
|
||||
return uprv_fmod(number, llong_asDouble(re)) == 0 && (baseValue % re) != 0;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
|
|
@ -12,8 +12,6 @@
|
|||
|
||||
#include "llong.h"
|
||||
|
||||
#include <math.h>
|
||||
|
||||
U_NAMESPACE_BEGIN
|
||||
|
||||
class FieldPosition;
|
||||
|
@ -26,7 +24,7 @@ class RuleBasedNumberFormat;
|
|||
class UnicodeString;
|
||||
|
||||
class NFRule {
|
||||
public:
|
||||
public:
|
||||
|
||||
enum ERuleType {
|
||||
kNoBase = 0,
|
||||
|
@ -56,7 +54,7 @@ class NFRule {
|
|||
llong getBaseValue() const { return baseValue; }
|
||||
void setBaseValue(llong value);
|
||||
|
||||
double getDivisor() const { return pow(radix, exponent); }
|
||||
double getDivisor() const { return uprv_pow(radix, exponent); }
|
||||
|
||||
void doFormat(llong number, UnicodeString& toAppendTo, int32_t pos) const;
|
||||
void doFormat(double number, UnicodeString& toAppendTo, int32_t pos) const;
|
||||
|
@ -71,7 +69,7 @@ class NFRule {
|
|||
|
||||
void appendRuleText(UnicodeString& result) const;
|
||||
|
||||
private:
|
||||
private:
|
||||
void parseRuleDescriptor(UnicodeString& descriptor, UErrorCode& status);
|
||||
void extractSubstitutions(const NFRuleSet* ruleSet, const NFRule* predecessor, const RuleBasedNumberFormat* rbnf, UErrorCode& status);
|
||||
NFSubstitution* extractSubstitution(const NFRuleSet* ruleSet, const NFRule* predecessor, const RuleBasedNumberFormat* rbnf, UErrorCode& status);
|
||||
|
@ -80,13 +78,13 @@ class NFRule {
|
|||
int32_t indexOfAny(const UChar* const strings[]) const;
|
||||
double matchToDelimiter(const UnicodeString& text, int32_t startPos, double baseValue,
|
||||
const UnicodeString& delimiter, ParsePosition& pp, const NFSubstitution* sub,
|
||||
double upperBound) const;
|
||||
double upperBound) const;
|
||||
void stripPrefix(UnicodeString& text, const UnicodeString& prefix, ParsePosition& pp) const;
|
||||
|
||||
int32_t prefixLength(const UnicodeString& str, const UnicodeString& prefix) const;
|
||||
UBool allIgnorable(const UnicodeString& str) const;
|
||||
int32_t findText(const UnicodeString& str, const UnicodeString& key,
|
||||
int32_t startingAt, int32_t* resultCount) const;
|
||||
int32_t prefixLength(const UnicodeString& str, const UnicodeString& prefix) const;
|
||||
UBool allIgnorable(const UnicodeString& str) const;
|
||||
int32_t findText(const UnicodeString& str, const UnicodeString& key,
|
||||
int32_t startingAt, int32_t* resultCount) const;
|
||||
|
||||
private:
|
||||
llong baseValue;
|
||||
|
|
|
@ -292,7 +292,7 @@ NFSubstitution::doSubstitution(llong number, UnicodeString& toInsertInto, int32_
|
|||
// to format the result
|
||||
double numberToFormat = transformNumber(llong_asDouble(number));
|
||||
if (numberFormat->getMaximumFractionDigits() == 0) {
|
||||
numberToFormat = floor(numberToFormat);
|
||||
numberToFormat = uprv_floor(numberToFormat);
|
||||
}
|
||||
|
||||
UnicodeString temp;
|
||||
|
@ -319,7 +319,7 @@ NFSubstitution::doSubstitution(double number, UnicodeString& toInsertInto, int32
|
|||
|
||||
// if the result is an integer, from here on out we work in integer
|
||||
// space (saving time and memory and preserving accuracy)
|
||||
if (numberToFormat == floor(numberToFormat) && ruleSet != NULL) {
|
||||
if (numberToFormat == uprv_floor(numberToFormat) && ruleSet != NULL) {
|
||||
ruleSet->format(llong(numberToFormat), toInsertInto, _pos + this->pos);
|
||||
|
||||
// if the result isn't an integer, then call either our rule set's
|
||||
|
@ -490,7 +490,7 @@ SameValueSubstitution::SameValueSubstitution(int32_t _pos,
|
|||
}
|
||||
}
|
||||
|
||||
char SameValueSubstitution::fgClassID;
|
||||
const char SameValueSubstitution::fgClassID = 0;
|
||||
|
||||
UClassID
|
||||
SameValueSubstitution::getDynamicClassID() const {
|
||||
|
@ -749,7 +749,7 @@ FractionalPartSubstitution::doSubstitution(double number, UnicodeString& toInser
|
|||
// (this is slower, but more accurate, than doing it from the
|
||||
// other end)
|
||||
} else {
|
||||
int32_t numberToFormat = (int32_t)round(transformNumber(number) * pow(10, kMaxDecimalDigits));
|
||||
int32_t numberToFormat = (int32_t)uprv_round(transformNumber(number) * uprv_pow(10, kMaxDecimalDigits));
|
||||
// this flag keeps us from formatting trailing zeros. It starts
|
||||
// out false because we're pulling from the right, and switches
|
||||
// to true the first time we encounter a non-zero digit
|
||||
|
|
|
@ -21,34 +21,15 @@
|
|||
#include "nfrs.h"
|
||||
#include "nfrule.h"
|
||||
#include "llong.h"
|
||||
#include "float.h"
|
||||
|
||||
U_NAMESPACE_BEGIN
|
||||
|
||||
static double MAX_DOUBLE = 1.7976931348623157e+308;
|
||||
static double java_fmod(double n, double d)
|
||||
{
|
||||
// c doesn't define '%' for floating point, but java does.
|
||||
// from the java language spec 15.17:
|
||||
// "In the remaining cases, where neither an infinity, nor a zero,
|
||||
// nor NaN is involved, the floating-point remainder r from the
|
||||
// division of a dividend n by a divisor d is defined by the
|
||||
// mathematical relation r = n - (d . q) where q is an integer
|
||||
// that is negative only if n/d is negative and positive only if
|
||||
// n/d is positive, and whose magnitude is as large as possible
|
||||
// without exceeding the magnitude of the true mathematical
|
||||
// quotient of n and d."
|
||||
//
|
||||
// I'm not sure if fmod (from what header?) has the same implemenation
|
||||
|
||||
double q = n/d;
|
||||
q = q < 0 ? -floor(-q) : floor(q);
|
||||
return n - d * q;
|
||||
}
|
||||
|
||||
static double round(double n)
|
||||
{
|
||||
return floor(n + .5);
|
||||
}
|
||||
//static double round(double n)
|
||||
//{
|
||||
// return floor(n + .5);
|
||||
//}
|
||||
|
||||
class NFSubstitution {
|
||||
int32_t pos;
|
||||
|
@ -242,7 +223,7 @@ public:
|
|||
double calcUpperBound(double oldUpperBound) const { return oldUpperBound; }
|
||||
UChar tokenChar() const { return (UChar)0x003d; } // '='
|
||||
private:
|
||||
static char fgClassID;
|
||||
static const char fgClassID;
|
||||
|
||||
public:
|
||||
static UClassID getStaticClassID(void) { return (UClassID)&fgClassID; }
|
||||
|
@ -266,7 +247,7 @@ public:
|
|||
}
|
||||
|
||||
void setDivisor(int32_t radix, int32_t exponent) {
|
||||
divisor = pow(radix, exponent);
|
||||
divisor = uprv_pow(radix, exponent);
|
||||
ldivisor = divisor;
|
||||
}
|
||||
|
||||
|
@ -277,7 +258,7 @@ public:
|
|||
}
|
||||
|
||||
double transformNumber(double number) const {
|
||||
return floor(number / divisor);
|
||||
return uprv_floor(number / divisor);
|
||||
}
|
||||
|
||||
double composeRuleValue(double newRuleValue, double oldRuleValue) const {
|
||||
|
@ -309,7 +290,7 @@ public:
|
|||
UErrorCode& status);
|
||||
|
||||
void setDivisor(int32_t radix, int32_t exponent) {
|
||||
divisor = pow(radix, exponent);
|
||||
divisor = uprv_pow(radix, exponent);
|
||||
ldivisor = divisor;
|
||||
}
|
||||
|
||||
|
@ -319,7 +300,7 @@ public:
|
|||
void doSubstitution(double number, UnicodeString& toInsertInto, int32_t pos) const;
|
||||
|
||||
llong transformNumber(llong number) const { return number % ldivisor; }
|
||||
double transformNumber(double number) const { return java_fmod(number, divisor); }
|
||||
double transformNumber(double number) const { return uprv_fmod(number, divisor); }
|
||||
|
||||
UBool doParse(const UnicodeString& text,
|
||||
ParsePosition& parsePosition,
|
||||
|
@ -329,7 +310,7 @@ public:
|
|||
Formattable& result) const;
|
||||
|
||||
double composeRuleValue(double newRuleValue, double oldRuleValue) const {
|
||||
return oldRuleValue - java_fmod(oldRuleValue, divisor) + newRuleValue;
|
||||
return oldRuleValue - uprv_fmod(oldRuleValue, divisor) + newRuleValue;
|
||||
}
|
||||
|
||||
double calcUpperBound(double oldUpperBound) const { return divisor; }
|
||||
|
@ -355,9 +336,9 @@ public:
|
|||
: NFSubstitution(_pos, _ruleSet, formatter, description, status) {}
|
||||
|
||||
llong transformNumber(llong number) const { return number; }
|
||||
double transformNumber(double number) const { return floor(number); }
|
||||
double transformNumber(double number) const { return uprv_floor(number); }
|
||||
double composeRuleValue(double newRuleValue, double oldRuleValue) const { return newRuleValue + oldRuleValue; }
|
||||
double calcUpperBound(double oldUpperBound) const { return MAX_DOUBLE; }
|
||||
double calcUpperBound(double oldUpperBound) const { return DBL_MAX; }
|
||||
UChar tokenChar() const { return (UChar)0x003c; } // '<'
|
||||
private:
|
||||
static const char fgClassID;
|
||||
|
@ -381,8 +362,8 @@ public:
|
|||
UBool operator==(const NFSubstitution& rhs) const;
|
||||
|
||||
void doSubstitution(double number, UnicodeString& toInsertInto, int32_t pos) const;
|
||||
llong transformNumber(llong number) const { return llong::kZero; }
|
||||
double transformNumber(double number) const { return number - floor(number); }
|
||||
llong transformNumber(llong number) const { return llong(0,0); }
|
||||
double transformNumber(double number) const { return number - uprv_floor(number); }
|
||||
|
||||
UBool doParse(const UnicodeString& text,
|
||||
ParsePosition& parsePosition,
|
||||
|
@ -412,9 +393,9 @@ public:
|
|||
: NFSubstitution(_pos, _ruleSet, formatter, description, status) {}
|
||||
|
||||
llong transformNumber(llong number) const { return llong_abs(number); }
|
||||
double transformNumber(double number) const { return fabs(number); }
|
||||
double transformNumber(double number) const { return uprv_fabs(number); }
|
||||
double composeRuleValue(double newRuleValue, double oldRuleValue) const { return -newRuleValue; }
|
||||
double calcUpperBound(double oldUpperBound) const { return MAX_DOUBLE; }
|
||||
double calcUpperBound(double oldUpperBound) const { return DBL_MAX; }
|
||||
UChar tokenChar() const { return (UChar)0x003e; } // '>'
|
||||
private:
|
||||
static const char fgClassID;
|
||||
|
@ -442,7 +423,7 @@ public:
|
|||
UBool operator==(const NFSubstitution& rhs) const;
|
||||
|
||||
llong transformNumber(llong number) const { return number * ldenominator; }
|
||||
double transformNumber(double number) const { return round(number * denominator); }
|
||||
double transformNumber(double number) const { return uprv_round(number * denominator); }
|
||||
|
||||
UBool doParse(const UnicodeString& text,
|
||||
ParsePosition& parsePosition,
|
||||
|
@ -479,15 +460,15 @@ public:
|
|||
void toString(UnicodeString& result) const {}
|
||||
void doSubstitution(double number, UnicodeString& toInsertInto, int32_t _pos) const {}
|
||||
void doSubstitution(llong number, UnicodeString& toInsertInto, int32_t _pos) const {}
|
||||
llong transformNumber(llong number) const { return llong::kZero; }
|
||||
llong transformNumber(llong number) const { return llong(0,0); }
|
||||
double transformNumber(double number) const { return 0; }
|
||||
UBool doParse(const UnicodeString& text,
|
||||
ParsePosition& parsePosition,
|
||||
double baseValue,
|
||||
double upperBound,
|
||||
UBool lenientParse,
|
||||
Formattable& result) const
|
||||
{ result.setDouble(baseValue); return TRUE; }
|
||||
ParsePosition& parsePosition,
|
||||
double baseValue,
|
||||
double upperBound,
|
||||
UBool lenientParse,
|
||||
Formattable& result) const
|
||||
{ result.setDouble(baseValue); return TRUE; }
|
||||
double composeRuleValue(double newRuleValue, double oldRuleValue) const { return 0; } // never called
|
||||
double calcUpperBound(double oldUpperBound) const { return 0; } // never called
|
||||
UBool isNullSubstitution() const { return TRUE; }
|
||||
|
|
Loading…
Add table
Reference in a new issue