FreeWRL
view release on metacpan or search on metacpan
JS/js/prdtoa.c view on Meta::CPAN
carry = ys >> 16;
y = *bx - (ys & 0xffff) + borrow;
borrow = y >> 16;
Sign_Extend(borrow, y);
*bx++ = y & 0xffff;
#endif
}
while(sx <= sxe);
bx = b->x;
bxe = bx + n;
if (!*bxe) {
while(--bxe > bx && !*bxe)
--n;
b->wds = n;
}
}
return (int)q;
}
/* dtoa for IEEE arithmetic (dmg): convert double to ASCII string.
*
* Inspired by "How to Print Floating-Point Numbers Accurately" by
* Guy L. Steele, Jr. and Jon L. White [Proc. ACM SIGPLAN '90, pp. 92-101].
*
* Modifications:
* 1. Rather than iterating, we use a simple numeric overestimate
* to determine k = floor(log10(d)). We scale relevant
* quantities using O(log2(k)) rather than O(k) multiplications.
* 2. For some modes > 2 (corresponding to ecvt and fcvt), we don't
* try to generate digits strictly left to right. Instead, we
* compute with fewer bits and propagate the carry if necessary
* when rounding the final digit up. This is often faster.
* 3. Under the assumption that input will be rounded nearest,
* mode 0 renders 1e23 as 1e23 rather than 9.999999999999999e22.
* That is, we allow equality in stopping tests when the
* round-nearest rule will give the same floating-point value
* as would satisfaction of the stopping test with strict
* inequality.
* 4. We remove common factors of powers of 2 from relevant
* quantities.
* 5. When converting floating-point integers less than 1e16,
* we use floating-point arithmetic rather than resorting
* to multiple-precision integers.
* 6. When asked to produce fewer than 15 digits, we first try
* to get by with floating-point arithmetic; we resort to
* multiple-precision integer arithmetic only if we cannot
* guarantee that the floating-point calculation has given
* the correctly rounded result. For k requested digits and
* "uniformly" distributed input, the probability is
* something like 10^(k-15) that we must resort to the Long
* calculation.
*/
static PRBool
PR_dtoa(double d, int mode, int ndigits,
int *decpt, int *sign, char **rve, char *buf, size_t bufsize)
{
/* Arguments ndigits, decpt, sign are similar to those
of ecvt and fcvt; trailing zeros are suppressed from
the returned string. If not null, *rve is set to point
to the end of the return value. If d is +-Infinity or NaN,
then *decpt is set to 9999.
mode:
0 ==> shortest string that yields d when read in
and rounded to nearest.
1 ==> like 0, but with Steele & White stopping rule;
e.g. with IEEE P754 arithmetic , mode 0 gives
1e23 whereas mode 1 gives 9.999999999999999e22.
2 ==> max(1,ndigits) significant digits. This gives a
return value similar to that of ecvt, except
that trailing zeros are suppressed.
3 ==> through ndigits past the decimal point. This
gives a return value similar to that from fcvt,
except that trailing zeros are suppressed, and
ndigits can be negative.
4-9 should give the same return values as 2-3, i.e.,
4 <= mode <= 9 ==> same return as mode
2 + (mode & 1). These modes are mainly for
debugging; often they run slower but sometimes
faster than modes 2-3.
4,5,8,9 ==> left-to-right digit generation.
6-9 ==> don't try fast floating-point estimate
(if applicable).
Values of mode other than 0-9 are treated as mode 0.
Sufficient space is allocated to the return value
to hold the suppressed trailing zeros.
*/
int32 bbits, b2, b5, be, dig, i, ieps, ilim, ilim0, ilim1,
j, j1, k, k0, k_check, leftright, m2, m5, s2, s5,
spec_case, try_quick;
Long L;
#ifndef Sudden_Underflow
int32 denorm;
ULong x;
#endif
Bigint *b, *b1, *delta, *mlo, *mhi, *S;
double d2, ds, eps;
char *s, *s0;
Bigint *result = 0;
static int32 result_k;
PRBool retval;
size_t strsize;
#ifdef JS_THREADSAFE
if (!initialized) InitDtoa();
#endif
if (word0(d) & Sign_bit) {
/* set sign for everything, including 0's and NaNs */
*sign = 1;
word0(d) &= ~Sign_bit; /* clear sign bit */
}
else
*sign = 0;
#if defined(IEEE_Arith) + defined(VAX)
#ifdef IEEE_Arith
if ((word0(d) & Exp_mask) == Exp_mask)
#else
if (word0(d) == 0x8000)
#endif
{
/* Infinity or NaN */
*decpt = 9999;
s =
#ifdef IEEE_Arith
!word1(d) && !(word0(d) & 0xfffff) ? "Infinity" :
#endif
"NaN";
if ((s[0] == 'I' && bufsize < 9) || (s[0] == 'N' && bufsize < 4)) {
PR_ASSERT(PR_FALSE);
/* PR_SetError(PR_BUFFER_OVERFLOW_ERROR, 0); */
return PR_FALSE;
}
strcpy(buf, s);
if (rve) {
*rve =
#ifdef IEEE_Arith
buf[3] ? buf + 8 :
#endif
buf + 3;
PR_ASSERT(**rve == '\0');
}
return PR_TRUE;
}
#endif
#ifdef IBM
d += 0; /* normalize */
#endif
if (!d) {
*decpt = 1;
if (bufsize < 2) {
PR_ASSERT(PR_FALSE);
/* PR_SetError(PR_BUFFER_OVERFLOW_ERROR, 0); */
return PR_FALSE;
}
buf[0] = '0'; buf[1] = '\0'; /* copy "0" to buffer */
if (rve) {
*rve = buf + 1;
PR_ASSERT(**rve == '\0');
}
return PR_TRUE;
}
b = d2b(d, &be, &bbits);
#ifdef Sudden_Underflow
i = (int32)(word0(d) >> Exp_shift1 & (Exp_mask>>Exp_shift1));
#else
if ((i = (int32)(word0(d) >> Exp_shift1 & (Exp_mask>>Exp_shift1))) != 0) {
#endif
d2 = d;
word0(d2) &= Frac_mask1;
word0(d2) |= Exp_11;
#ifdef IBM
if (j = 11 - hi0bits(word0(d2) & Frac_mask))
d2 /= 1 << j;
#endif
/* log(x) ~=~ log(1.5) + (x-1.5)/1.5
* log10(x) = log(x) / log(10)
* ~=~ log(1.5)/log(10) + (x-1.5)/(1.5*log(10))
* log10(d) = (i-Bias)*log(2)/log(10) + log10(d2)
*
* This suggests computing an approximation k to log10(d) by
*
* k = (i - Bias)*0.301029995663981
* + ( (d2-1.5)*0.289529654602168 + 0.176091259055681 );
*
* We want k to be too large rather than too small.
JS/js/prdtoa.c view on Meta::CPAN
ret1:
Bfree(b);
*s = 0;
*decpt = k + 1;
strsize = (s - s0) + 1;
if (strsize <= bufsize) {
retval = PR_TRUE;
memcpy(buf, s0, strsize);
if (rve) {
*rve = buf + strsize - 1;
PR_ASSERT(**rve == '\0');
}
} else {
PR_ASSERT(PR_FALSE);
/* PR_SetError(PR_BUFFER_OVERFLOW_ERROR, 0); */
retval = PR_FALSE;
}
/* cleanup */
result->k = result_k;
result->maxwds = 1 << result_k;
Bfree(result);
return retval;
}
/*
** conversion routines for floating point
** prcsn - number of digits of precision to generate floating
** point value.
** This should be reparameterized so that you can send in a
** prcn for the positive and negative ranges. For now,
** conform to the ECMA JavaScript spec which says numbers
** less than 1e-6 are in scientific notation.
** Also, the ECMA spec says that there should always be a
** '+' or '-' after the 'e' in scientific notation
*/
PR_PUBLIC_API(void)
PR_cnvtf(char *buf,int bufsz, int prcsn,double fval)
{
intN decpt,sign,numdigits;
char *num, *nump;
char *bufp = buf;
char *endnum;
/* If anything fails, we store an empty string in 'buf' */
num = (char *)MALLOC(bufsz);
if (num == NULL) {
buf[0] = '\0';
return;
}
/* XXX Why use mode 1? */
if (PR_dtoa(fval,1,prcsn,&decpt,&sign,&endnum,num,bufsz)
== PR_FALSE) {
buf[0] = '\0';
goto done;
}
numdigits = endnum - num;
nump = num;
/* If negative and not signed zero and not a NaN, print leading "-". */
if (sign &&
!(word0(fval) == Sign_bit && word1(fval) == 0) &&
!((word0(fval) & Exp_mask) == Exp_mask &&
(word1(fval) || (word0(fval) & 0xfffff)))) {
*bufp++ = '-';
}
if(decpt == 9999){
while((*bufp++ = *nump++) != 0) ;
goto done;
}
if(decpt > (prcsn+1) || decpt < -(prcsn-1) || decpt < -5){
*bufp++ = *nump++;
if(numdigits != 1){
*bufp++ = '.';
}
while(*nump != '\0'){
*bufp++ = *nump++;
}
*bufp++ = 'e';
PR_snprintf(bufp,bufsz - (bufp - buf), "%+d",decpt-1);
}
else if(decpt >= 0){
if (decpt == 0){
*bufp++ = '0';
}
else {
while(decpt--){
if(*nump != '\0'){
*bufp++ = *nump++;
}
else {
*bufp++ = '0';
}
}
}
if(*nump != '\0'){
*bufp++ = '.';
while(*nump != '\0'){
*bufp++ = *nump++;
}
}
*bufp++ = '\0';
}
else if(decpt < 0){
*bufp++ = '0';
*bufp++ = '.';
while(decpt++){
*bufp++ = '0';
}
while(*nump != '\0'){
*bufp++ = *nump++;
}
*bufp++ = '\0';
}
done:
free(num);
( run in 0.984 second using v1.01-cache-2.11-cpan-39bf76dae61 )