jsdtoa.c revision 6b15695578f07a3f72c4c9475c1a261a3021472a
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is Mozilla Communicator client code, released
* March 31, 1998.
*
* The Initial Developer of the Original Code is
* Netscape Communications Corporation.
* Portions created by the Initial Developer are Copyright (C) 1998
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the terms of
* either of the GNU General Public License Version 2 or later (the "GPL"),
* or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
/*
* Portable double to alphanumeric string and back converters.
*/
#include "jsstddef.h"
#include "jslibmath.h"
#include "jstypes.h"
#include "jsdtoa.h"
#include "jsprf.h"
#include "jsutil.h" /* Added by JSIFY */
#include "jspubtd.h"
#include "jsnum.h"
#ifdef JS_THREADSAFE
#include "prlock.h"
#endif
/****************************************************************
*
* The author of this software is David M. Gay.
*
* Copyright (c) 1991 by Lucent Technologies.
*
* Permission to use, copy, modify, and distribute this software for any
* purpose without fee is hereby granted, provided that this entire notice
* is included in all copies of any software which is or includes a copy
* or modification of this software and in all copies of the supporting
* documentation for such software.
*
* THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED
* WARRANTY. IN PARTICULAR, NEITHER THE AUTHOR NOR LUCENT MAKES ANY
* REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY
* OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE.
*
***************************************************************/
/* Please send bug reports to
David M. Gay
Bell Laboratories, Room 2C-463
600 Mountain Avenue
Murray Hill, NJ 07974-0636
U.S.A.
dmg@bell-labs.com
*/
/* On a machine with IEEE extended-precision registers, it is
* necessary to specify double-precision (53-bit) rounding precision
* before invoking strtod or dtoa. If the machine uses (the equivalent
* of) Intel 80x87 arithmetic, the call
* _control87(PC_53, MCW_PC);
* does this with many compilers. Whether this or another call is
* appropriate depends on the compiler; for this to work, it may be
* necessary to #include "float.h" or another system-dependent header
* file.
*/
/* strtod for IEEE-arithmetic machines.
*
* This strtod returns a nearest machine number to the input decimal
* string (or sets err to JS_DTOA_ERANGE or JS_DTOA_ENOMEM). With IEEE
* arithmetic, ties are broken by the IEEE round-even rule. Otherwise
* ties are broken by biased rounding (add half and chop).
*
* Inspired loosely by William D. Clinger's paper "How to Read Floating
* Point Numbers Accurately" [Proc. ACM SIGPLAN '90, pp. 92-101].
*
* Modifications:
*
* 1. We only require IEEE double-precision
* arithmetic (not IEEE double-extended).
* 2. We get by with floating-point arithmetic in a case that
* Clinger missed -- when we're computing d * 10^n
* for a small integer d and the integer n is not too
* much larger than 22 (the maximum integer k for which
* we can represent 10^k exactly), we may be able to
* compute (d*10^k) * 10^(e-k) with just one roundoff.
* 3. Rather than a bit-at-a-time adjustment of the binary
* result in the hard case, we use floating-point
* arithmetic to determine the adjustment to within
* one bit; only in really hard cases do we need to
* compute a second residual.
* 4. Because of 3., we don't need a large table of powers of 10
* for ten-to-e (just some small tables, e.g. of 10^k
* for 0 <= k <= 22).
*/
/*
* #define IEEE_8087 for IEEE-arithmetic machines where the least
* significant byte has the lowest address.
* #define IEEE_MC68k for IEEE-arithmetic machines where the most
* significant byte has the lowest address.
* #define Long int on machines with 32-bit ints and 64-bit longs.
* #define Sudden_Underflow for IEEE-format machines without gradual
* underflow (i.e., that flush to zero on underflow).
* #define No_leftright to omit left-right logic in fast floating-point
* computation of js_dtoa.
* #define Check_FLT_ROUNDS if FLT_ROUNDS can assume the values 2 or 3.
* #define RND_PRODQUOT to use rnd_prod and rnd_quot (assembly routines
* that use extended-precision instructions to compute rounded
* products and quotients) with IBM.
* #define ROUND_BIASED for IEEE-format with biased rounding.
* #define Inaccurate_Divide for IEEE-format with correctly rounded
* products but inaccurate quotients, e.g., for Intel i860.
* #define JS_HAVE_LONG_LONG on machines that have a "long long"
* integer type (of >= 64 bits). If long long is available and the name is
* something other than "long long", #define Llong to be the name,
* and if "unsigned Llong" does not work as an unsigned version of
* Llong, #define #ULLong to be the corresponding unsigned type.
* #define Bad_float_h if your system lacks a float.h or if it does not
* define some or all of DBL_DIG, DBL_MAX_10_EXP, DBL_MAX_EXP,
* FLT_RADIX, FLT_ROUNDS, and DBL_MAX.
* #define MALLOC your_malloc, where your_malloc(n) acts like malloc(n)
* if memory is available and otherwise does something you deem
* appropriate. If MALLOC is undefined, malloc will be invoked
* directly -- and assumed always to succeed.
* #define Omit_Private_Memory to omit logic (added Jan. 1998) for making
* memory allocations from a private pool of memory when possible.
* When used, the private pool is PRIVATE_MEM bytes long: 2000 bytes,
* unless #defined to be a different length. This default length
* suffices to get rid of MALLOC calls except for unusual cases,
* such as decimal-to-binary conversion of a very long string of
* digits.
* #define INFNAN_CHECK on IEEE systems to cause strtod to check for
* Infinity and NaN (case insensitively). On some systems (e.g.,
* some HP systems), it may be necessary to #define NAN_WORD0
* appropriately -- to the most significant word of a quiet NaN.
* (On HP Series 700/800 machines, -DNAN_WORD0=0x7ff40000 works.)
* #define MULTIPLE_THREADS if the system offers preemptively scheduled
* multiple threads. In this case, you must provide (or suitably
* #define) two locks, acquired by ACQUIRE_DTOA_LOCK() and released
* by RELEASE_DTOA_LOCK(). (The second lock, accessed
* in pow5mult, ensures lazy evaluation of only one copy of high
* powers of 5; omitting this lock would introduce a small
* probability of wasting memory, but would otherwise be harmless.)
* You must also invoke freedtoa(s) to free the value s returned by
* dtoa. You may do so whether or not MULTIPLE_THREADS is #defined.
* #define NO_IEEE_Scale to disable new (Feb. 1997) logic in strtod that
* avoids underflows on inputs whose result does not underflow.
*/
#ifdef IS_LITTLE_ENDIAN
#define IEEE_8087
#else
#define IEEE_MC68k
#endif
#ifndef Long
#endif
#ifndef ULong
#endif
#include "stdlib.h"
#include "string.h"
#ifdef MALLOC
#else
#endif
#define Omit_Private_Memory
/* Private memory currently doesn't work with JS_THREADSAFE */
#ifndef Omit_Private_Memory
#ifndef PRIVATE_MEM
#define PRIVATE_MEM 2000
#endif
#endif
#ifdef Bad_float_h
#define DBL_DIG 15
#define DBL_MAX_10_EXP 308
#define DBL_MAX_EXP 1024
#define FLT_RADIX 2
#define FLT_ROUNDS 1
#define DBL_MAX 1.7976931348623157e+308
#ifndef LONG_MAX
#define LONG_MAX 2147483647
#endif
#else /* ifndef Bad_float_h */
#include "float.h"
/*
* MacOS 10.2 defines the macro FLT_ROUNDS to an internal function
* which does not exist on 10.1. We can safely #define it to 1 here
* to allow 10.2 builds to run on 10.1, since we can't use fesetround()
* (which does not exist on 10.1 either).
*/
#define FLT_ROUNDS 1
#endif
#endif /* Bad_float_h */
#ifndef __MATH_H__
#include "math.h"
#endif
#ifndef CONST
#define CONST const
#endif
#endif
#define word0(x) JSDOUBLE_HI32(x)
#define set_word0(x, y) JSDOUBLE_SET_HI32(x, y)
#define word1(x) JSDOUBLE_LO32(x)
#define set_word1(x, y) JSDOUBLE_SET_LO32(x, y)
/* #define P DBL_MANT_DIG */
/* Ten_pmax = floor(P*log(2)/log(5)) */
/* Bletch = (highest power of 2 < DBL_MAX_10_EXP) / 16 */
/* Quick_max = floor((P-1)*log(FLT_RADIX)/log(10) - 1) */
/* Int_max = floor(P*log(FLT_RADIX)/log(10) - 1) */
#define Exp_shift 20
#define Exp_shift1 20
#define Exp_msk1 0x100000
#define Exp_msk11 0x100000
#define Exp_mask 0x7ff00000
#define P 53
#define Bias 1023
#define Emin (-1022)
#define Exp_1 0x3ff00000
#define Exp_11 0x3ff00000
#define Ebits 11
#define Frac_mask 0xfffff
#define Frac_mask1 0xfffff
#define Ten_pmax 22
#define Bletch 0x10
#define Bndry_mask 0xfffff
#define Bndry_mask1 0xfffff
#define LSB 1
#define Sign_bit 0x80000000
#define Log2P 1
#define Tiny0 0
#define Tiny1 1
#define Quick_max 14
#define Int_max 14
#ifndef NO_IEEE_Scale
#define Avoid_Underflow
#endif
#ifdef RND_PRODQUOT
#define rounded_product(a,b) a = rnd_prod(a, b)
#define rounded_quotient(a,b) a = rnd_quot(a, b)
#else
#define rounded_product(a,b) a *= b
#define rounded_quotient(a,b) a /= b
#endif
#define Big1 0xffffffff
#ifndef JS_HAVE_LONG_LONG
#else /* long long available */
#ifndef Llong
#endif
#ifndef ULLong
#endif
#endif /* JS_HAVE_LONG_LONG */
#ifdef JS_THREADSAFE
#define MULTIPLE_THREADS
static PRLock *freelist_lock;
#define ACQUIRE_DTOA_LOCK() \
if (!initialized) \
InitDtoa(); \
PR_Lock(freelist_lock); \
#else
#define ACQUIRE_DTOA_LOCK() /*nothing*/
#define RELEASE_DTOA_LOCK() /*nothing*/
#endif
#define Kmax 15
struct Bigint {
int32 k; /* lg2(maxwds) */
int32 wds; /* Actual number of words. If value is nonzero, the most significant word must be nonzero. */
};
#ifdef ENABLE_OOM_TESTING
/* Out-of-memory testing. Use a good testcase (over and over) and then use
* these routines to cause a memory failure on every possible Balloc allocation,
* to make sure that all out-of-memory paths can be followed. See bug 14044.
*/
static int allocationNum; /* which allocation is next? */
static int desiredFailure; /* which allocation should fail? */
/**
* js_BigintTestingReset
*
* Call at the beginning of a test run to set the allocation failure position.
* (Set to 0 to just have the engine count allocations without failing.)
*/
JS_PUBLIC_API(void)
{
allocationNum = 0;
}
/**
* js_BigintTestingWhere
*
* Report the current allocation position. This is really only useful when you
* want to learn how many allocations a test run has.
*/
JS_PUBLIC_API(int)
{
return allocationNum;
}
/*
* So here's what you do: Set up a fantastic test case that exercises the
* elements of the code you wish. Set the failure point at 0 and run the test,
* then get the allocation position. This number is the number of allocations
* your test makes. Now loop from 1 to that number, setting the failure point
* at each loop count, and run the test over and over, causing failures at each
* step. Any memory failure *should* cause a Out-Of-Memory exception; if it
* doesn't, then there's still an error here.
*/
#endif
/*
* Allocate a Bigint with 2^k words.
* This is not threadsafe. The caller must use thread locks
*/
{
int32 x;
#ifndef Omit_Private_Memory
#endif
#ifdef ENABLE_OOM_TESTING
if (++allocationNum == desiredFailure) {
return NULL;
}
#endif
x = 1 << k;
#ifdef Omit_Private_Memory
#else
/sizeof(double);
}
else
#endif
if (!rv)
return NULL;
rv->k = k;
}
return rv;
}
{
if (v) {
freelist[v->k] = v;
}
}
/* Return b*m + a. Deallocate the old b. Both a and m must be between 0 and
* 65535 inclusive. NOTE: old b is deallocated on memory failure.
*/
{
#ifdef ULLong
ULong *x;
#else
#endif
#ifdef ENABLE_OOM_TESTING
if (++allocationNum == desiredFailure) {
/* Faux allocation, because I'm not getting all of the failure paths
* without it.
*/
Bfree(b);
return NULL;
}
#endif
x = b->x;
i = 0;
carry = a;
do {
#ifdef ULLong
carry = y >> 32;
*x++ = (ULong)(y & 0xffffffffUL);
#else
xi = *x;
carry = z >> 16;
*x++ = (z << 16) + (y & 0xffff);
#endif
}
while(++i < wds);
if (carry) {
if (!b1) {
Bfree(b);
return NULL;
}
Bfree(b);
b = b1;
}
}
return b;
}
{
Bigint *b;
int32 i, k;
Long x, y;
for(k = 0, y = 1; x > y; y <<= 1, k++) ;
b = Balloc(k);
if (!b)
return NULL;
b->x[0] = y9;
b->wds = 1;
i = 9;
if (9 < nd0) {
s += 9;
do {
if (!b)
return NULL;
} while(++i < nd0);
s++;
}
else
s += 10;
for(; i < nd; i++) {
if (!b)
return NULL;
}
return b;
}
/* Return the number (0 through 32) of most significant zero bits in x. */
{
register int32 k = 0;
if (!(x & 0xffff0000)) {
k = 16;
x <<= 16;
}
if (!(x & 0xff000000)) {
k += 8;
x <<= 8;
}
if (!(x & 0xf0000000)) {
k += 4;
x <<= 4;
}
if (!(x & 0xc0000000)) {
k += 2;
x <<= 2;
}
if (!(x & 0x80000000)) {
k++;
if (!(x & 0x40000000))
return 32;
}
return k;
}
/* Return the number (0 through 32) of least significant zero bits in y.
* Also shift y to the right past these 0 through 32 zeros so that y's
* least significant bit will be set unless y was originally zero. */
{
register int32 k;
register ULong x = *y;
if (x & 7) {
if (x & 1)
return 0;
if (x & 2) {
*y = x >> 1;
return 1;
}
*y = x >> 2;
return 2;
}
k = 0;
if (!(x & 0xffff)) {
k = 16;
x >>= 16;
}
if (!(x & 0xff)) {
k += 8;
x >>= 8;
}
if (!(x & 0xf)) {
k += 4;
x >>= 4;
}
if (!(x & 0x3)) {
k += 2;
x >>= 2;
}
if (!(x & 1)) {
k++;
x >>= 1;
if (!x & 1)
return 32;
}
*y = x;
return k;
}
/* Return a new Bigint with the given integer value, which must be nonnegative. */
{
Bigint *b;
b = Balloc(1);
if (!b)
return NULL;
b->x[0] = i;
b->wds = 1;
return b;
}
/* Return a newly allocated product of a and b. */
{
Bigint *c;
ULong y;
#ifdef ULLong
#else
#endif
t = a;
a = b;
b = t;
}
k = a->k;
k++;
c = Balloc(k);
if (!c)
return NULL;
*xc = 0;
xa = a->x;
xb = b->x;
xc0 = c->x;
#ifdef ULLong
if ((y = *xb++) != 0) {
x = xa;
carry = 0;
do {
carry = z >> 32;
}
while(x < xae);
}
}
#else
if ((y = *xb & 0xffff) != 0) {
x = xa;
carry = 0;
do {
carry = z >> 16;
}
while(x < xae);
}
if ((y = *xb >> 16) != 0) {
x = xa;
carry = 0;
do {
carry = z >> 16;
}
while(x < xae);
}
}
#endif
return c;
}
/*
* 'p5s' points to a linked list of Bigints that are powers of 5.
* This list grows on demand, and it can only grow: it won't change
* in any other way. So if we read 'p5s' or the 'next' field of
* some Bigint on the list, and it is not NULL, we know it won't
* change to NULL or some other value. Only when the value of
* 'p5s' or 'next' is NULL do we need to acquire the lock and add
* a new Bigint to the list.
*/
#ifdef JS_THREADSAFE
#endif
/* Return b * 5^k. Deallocate the old b. k must be nonnegative. */
/* NOTE: old b is deallocated on memory failure. */
{
int32 i;
if ((i = k & 3) != 0) {
if (!b)
return NULL;
}
if (!(k >>= 2))
return b;
#ifdef JS_THREADSAFE
/*
* We take great care to not call i2b() and Bfree()
* while holding the lock.
*/
if (!p5) {
Bfree(b);
return NULL;
}
/* lock and check again */
if (!p5s) {
/* first time */
} else {
/* some other thread just beat us */
wasted_effort = p5;
}
if (wasted_effort) {
}
#else
/* first time */
if (!p5) {
Bfree(b);
return NULL;
}
#endif
}
for(;;) {
if (k & 1) {
Bfree(b);
if (!b1)
return NULL;
b = b1;
}
if (!(k >>= 1))
break;
#ifdef JS_THREADSAFE
if (!p51) {
Bfree(b);
return NULL;
}
} else {
wasted_effort = p51;
}
if (wasted_effort) {
}
#else
if (!p51) {
Bfree(b);
return NULL;
}
#endif
}
}
return b;
}
/* Return b * 2^k. Deallocate the old b. k must be nonnegative.
* NOTE: on memory failure, old b is deallocated. */
{
n = k >> 5;
k1 = b->k;
k1++;
if (!b1)
goto done;
for(i = 0; i < n; i++)
*x1++ = 0;
x = b->x;
if (k &= 0x1f) {
k1 = 32 - k;
z = 0;
do {
*x1++ = *x << k | z;
z = *x++ >> k1;
}
while(x < xe);
if ((*x1 = z) != 0)
++n1;
}
else do
*x1++ = *x++;
while(x < xe);
done:
Bfree(b);
return b1;
}
/* Return -1, 0, or 1 depending on whether a<b, a==b, or a>b, respectively. */
{
int32 i, j;
i = a->wds;
j = b->wds;
#ifdef DEBUG
if (i > 1 && !a->x[i-1])
Bug("cmp called with a->x[a->wds-1] == 0");
if (j > 1 && !b->x[j-1])
Bug("cmp called with b->x[b->wds-1] == 0");
#endif
if (i -= j)
return i;
xa0 = a->x;
xb0 = b->x;
for(;;) {
break;
}
return 0;
}
{
Bigint *c;
#ifdef ULLong
#else
ULong z;
#endif
i = cmp(a,b);
if (!i) {
c = Balloc(0);
if (!c)
return NULL;
c->wds = 1;
c->x[0] = 0;
return c;
}
if (i < 0) {
c = a;
a = b;
b = c;
i = 1;
}
else
i = 0;
c = Balloc(a->k);
if (!c)
return NULL;
c->sign = i;
xa = a->x;
xb = b->x;
xc = c->x;
borrow = 0;
#ifdef ULLong
do {
}
}
#else
do {
}
}
#endif
while(!*--xc)
wa--;
return c;
}
/* Return the absolute difference between x and the adjacent greater-magnitude double number (ignoring exponent overflows). */
static double ulp(double x)
{
register Long L;
double a;
#ifndef Sudden_Underflow
if (L > 0) {
#endif
set_word0(a, L);
set_word1(a, 0);
#ifndef Sudden_Underflow
}
else {
L = -L >> Exp_shift;
if (L < Exp_shift) {
set_word0(a, 0x80000 >> L);
set_word1(a, 0);
}
else {
set_word0(a, 0);
L -= Exp_shift;
}
}
#endif
return a;
}
{
int32 k;
double d;
xa0 = a->x;
y = *--xa;
#ifdef DEBUG
if (!y) Bug("zero y in b2d");
#endif
k = hi0bits(y);
*e = 32 - k;
if (k < Ebits) {
goto ret_d;
}
if (k -= Ebits) {
set_d1(z << k | y >> (32 - k));
}
else {
set_d1(z);
}
return d;
}
/* Convert d into the form b*2^e, where b is an odd integer. b is the returned
* Bigint and e is the returned binary exponent. Return the number of significant
* bits in b in bits. d must be finite and nonzero. */
{
Bigint *b;
ULong *x, y, z;
b = Balloc(1);
if (!b)
return NULL;
x = b->x;
#ifdef Sudden_Underflow
z |= Exp_msk11;
#else
z |= Exp_msk1;
#endif
if ((y = d1) != 0) {
if ((k = lo0bits(&y)) != 0) {
x[0] = y | z << (32 - k);
z >>= k;
}
else
x[0] = y;
}
else {
JS_ASSERT(z);
k = lo0bits(&z);
x[0] = z;
i = b->wds = 1;
k += 32;
}
#ifndef Sudden_Underflow
if (de) {
#endif
*bits = P - k;
#ifndef Sudden_Underflow
}
else {
}
#endif
return b;
}
{
if (k > 0)
else {
k = -k;
}
}
static CONST double
tens[] = {
1e0, 1e1, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8, 1e9,
1e10, 1e11, 1e12, 1e13, 1e14, 1e15, 1e16, 1e17, 1e18, 1e19,
1e20, 1e21, 1e22
};
#ifdef Avoid_Underflow
9007199254740992.e-256
#else
1e-256
#endif
};
/* The factor of 2^53 in tinytens[4] helps us avoid setting the underflow */
/* flag unnecessarily. It leads to a song and dance at the end of strtod. */
#define Scale_Bit 0x10
#define n_bigtens 5
#ifdef INFNAN_CHECK
#ifndef NAN_WORD0
#define NAN_WORD0 0x7ff80000
#endif
#ifndef NAN_WORD1
#define NAN_WORD1 0
#endif
{
int c, d;
while(d = *t++) {
if ((c = *++s) >= 'A' && c <= 'Z')
c += 'a' - 'A';
if (c != d)
return 0;
}
*sp = s + 1;
return 1;
}
#endif /* INFNAN_CHECK */
#ifdef JS_THREADSAFE
/* hacked replica of nspr _PR_InitDtoa */
static void InitDtoa(void)
{
freelist_lock = PR_NewLock();
p5s_lock = PR_NewLock();
}
#endif
void js_FinishDtoa(void)
{
int count;
#ifdef JS_THREADSAFE
if (initialized == JS_TRUE) {
}
#endif
/* clear down the freelist array and p5s */
/* static Bigint *freelist[Kmax+1]; */
}
}
/* static Bigint *p5s; */
while (p5s) {
}
}
/* nspr2 watcom bug ifdef omitted */
JS_FRIEND_API(double)
{
Long L;
ULong y, z;
SET_FPU();
*err = 0;
rv = 0.;
/* Locking for Balloc's shared buffers that will be used in this block */
for(s = s00;;s++) switch(*s) {
case '-':
sign = 1;
/* no break */
case '+':
if (*++s)
goto break2;
/* no break */
case 0:
s = s00;
goto ret;
case '\t':
case '\n':
case '\v':
case '\f':
case '\r':
case ' ':
continue;
default:
goto break2;
}
if (*s == '0') {
nz0 = 1;
while(*++s == '0') ;
if (!*s)
goto ret;
}
s0 = s;
y = z = 0;
if (nd < 9)
y = 10*y + c - '0';
else if (nd < 16)
z = 10*z + c - '0';
if (c == '.') {
c = *++s;
if (!nd) {
for(; c == '0'; c = *++s)
nz++;
if (c > '0' && c <= '9') {
s0 = s;
nz = 0;
goto have_dig;
}
goto dig_done;
}
for(; c >= '0' && c <= '9'; c = *++s) {
nz++;
if (c -= '0') {
for(i = 1; i < nz; i++)
if (nd++ < 9)
y *= 10;
z *= 10;
if (nd++ < 9)
y = 10*y + c;
z = 10*z + c;
nz = 0;
}
}
}
e = 0;
if (c == 'e' || c == 'E') {
s = s00;
goto ret;
}
s00 = s;
esign = 0;
switch(c = *++s) {
case '-':
esign = 1;
case '+':
c = *++s;
}
if (c >= '0' && c <= '9') {
while(c == '0')
c = *++s;
if (c > '0' && c <= '9') {
L = c - '0';
s1 = s;
while((c = *++s) >= '0' && c <= '9')
L = 10*L + c - '0';
/* Avoid confusion from exponents
* so large that e might overflow.
*/
e = 19999; /* safe for 16 bit ints */
else
e = (int32)L;
if (esign)
e = -e;
}
else
e = 0;
}
else
s = s00;
}
if (!nd) {
#ifdef INFNAN_CHECK
/* Check for Nan and Infinity */
switch(c) {
case 'i':
case 'I':
if (match(&s,"nfinity")) {
goto ret;
}
break;
case 'n':
case 'N':
if (match(&s, "an")) {
goto ret;
}
}
#endif /* INFNAN_CHECK */
s = s00;
}
goto ret;
}
/* Now we have nd0 digits, starting at s0, followed by a
* decimal point, followed by nd-nd0 digits. The number we're
* after is the integer represented by those digits times
* 10**e */
if (!nd0)
rv = y;
if (k > 9)
bd0 = 0;
#ifndef RND_PRODQUOT
&& FLT_ROUNDS == 1
#endif
) {
if (!e)
goto ret;
if (e > 0) {
if (e <= Ten_pmax) {
goto ret;
}
if (e <= Ten_pmax + i) {
/* A fancier test would sometimes let us do
* this for larger i values.
*/
e -= i;
goto ret;
}
}
#ifndef Inaccurate_Divide
else if (e >= -Ten_pmax) {
goto ret;
}
#endif
}
scale = 0;
/* Get starting approximation = rv * 10**e1 */
if (e1 > 0) {
if ((i = e1 & 15) != 0)
if (e1 &= ~15) {
if (e1 > DBL_MAX_10_EXP) {
ovfl:
*err = JS_DTOA_ERANGE;
#ifdef __STDC__
#else
/* Can't trust HUGE_VAL */
#endif
if (bd0)
goto retfree;
goto ret;
}
e1 >>= 4;
if (e1 & 1)
/* The last multiplication could overflow. */
goto ovfl;
/* set to largest number */
/* (Can't trust DBL_MAX) */
}
else
}
}
else if (e1 < 0) {
if ((i = e1 & 15) != 0)
if (e1 &= ~15) {
e1 >>= 4;
goto undfl;
#ifdef Avoid_Underflow
scale = P;
if (e1 & 1)
>> Exp_shift)) > 0) {
/* scaled rv is denormal; zap j low bits */
if (j >= 32) {
}
else
}
#else
if (e1 & 1)
/* The last multiplication could underflow. */
if (!rv) {
#endif
if (!rv) {
rv = 0.;
*err = JS_DTOA_ERANGE;
if (bd0)
goto retfree;
goto ret;
}
#ifndef Avoid_Underflow
/* The refinement below will clean
* this approximation up.
*/
}
#endif
}
}
/* Now the hard part -- adjusting rv to the correct value.*/
/* Put digits into bd: true value = bd * 10^e */
if (!bd0)
goto nomem;
for(;;) {
if (!bd)
goto nomem;
if (!bb)
goto nomem;
if (!bs)
goto nomem;
if (e >= 0) {
}
else {
}
if (bbe >= 0)
else
#ifdef Sudden_Underflow
j = P + 1 - bbbits;
#else
#ifdef Avoid_Underflow
#else
j = bbe;
#endif
if (i < Emin) /* denormal */
j += P - Emin;
else
j = P + 1 - bbbits;
#endif
bb2 += j;
bd2 += j;
#ifdef Avoid_Underflow
#endif
if (i > bs2)
i = bs2;
if (i > 0) {
bb2 -= i;
bd2 -= i;
bs2 -= i;
}
if (bb5 > 0) {
if (!bs)
goto nomem;
if (!bb1)
goto nomem;
}
if (bb2 > 0) {
if (!bb)
goto nomem;
}
if (bd5 > 0) {
if (!bd)
goto nomem;
}
if (bd2 > 0) {
if (!bd)
goto nomem;
}
if (bs2 > 0) {
if (!bs)
goto nomem;
}
if (!delta)
goto nomem;
if (i < 0) {
/* Error is less than half an ulp -- check for
* special case of mantissa a power of two.
*/
#ifdef Avoid_Underflow
#else
#endif
) {
#ifdef Avoid_Underflow
dsign = 2;
#endif
break;
}
if (!delta)
goto nomem;
goto drop_down;
break;
}
if (i == 0) {
/* exactly half-way between */
if (dsign) {
/*boundary case -- increment exponent*/
#ifdef Avoid_Underflow
dsign = 0;
#endif
break;
}
}
#ifdef Avoid_Underflow
dsign = 2;
#endif
/* boundary case -- decrement exponent */
#ifdef Sudden_Underflow
if (L <= Exp_msk1)
goto undfl;
L -= Exp_msk1;
#else
#endif
break;
}
#ifndef ROUND_BIASED
break;
#endif
if (dsign)
#ifndef ROUND_BIASED
else {
#ifndef Sudden_Underflow
if (!rv)
goto undfl;
#endif
}
#ifdef Avoid_Underflow
#endif
#endif
break;
}
if (dsign)
#ifndef Sudden_Underflow
goto undfl;
#endif
aadj = 1.;
aadj1 = -1.;
}
else {
/* special case -- power of FLT_RADIX to be */
/* rounded down... */
else
aadj *= 0.5;
}
}
else {
aadj *= 0.5;
#ifdef Check_FLT_ROUNDS
switch(FLT_ROUNDS) {
case 2: /* towards +infinity */
aadj1 -= 0.5;
break;
case 0: /* towards 0 */
case 3: /* towards -infinity */
aadj1 += 0.5;
}
#else
if (FLT_ROUNDS == 0)
aadj1 += 0.5;
#endif
}
/* Check for overflow */
goto ovfl;
goto cont;
}
else
}
else {
#ifdef Sudden_Underflow
{
goto undfl;
goto cont;
}
else
}
else {
}
#else
/* Compute adj so that the IEEE rounding rules will
* correctly round rv + adj in some half-way cases.
* If rv * ulp(rv) is denormalized (i.e.,
* y <= (P-1)*Exp_msk1), we must adjust aadj to avoid
* trouble from bits lost to denormalization;
* example: 1.2e-307 .
*/
#ifdef Avoid_Underflow
#else
#endif
{
if (!dsign)
}
#ifdef Avoid_Underflow
#endif
#endif
}
#ifdef Avoid_Underflow
if (!scale)
#endif
if (y == z) {
/* Can we stop now? */
aadj -= L;
/* The tolerances below are conservative. */
break;
}
break;
}
cont:
}
#ifdef Avoid_Underflow
if (scale) {
&& dsign != 2) {
if (dsign) {
#ifdef Sudden_Underflow
/* rv will be 0, but this would give the */
/* right result if only rv *= rv0 worked. */
#endif
}
else
}
}
#endif /* Avoid_Underflow */
ret:
if (se)
*se = (char *)s;
goto ret1;
*err = JS_DTOA_ENOMEM;
rv0 = 0;
ret1:
RESTORE_FPU();
return rv0;
}
/* Return floor(b/2^k) and set b to be the remainder. The returned quotient must be less than 2^32. */
{
int32 w;
int32 n = k >> 5;
k &= 0x1F;
w = b->wds - n;
if (w <= 0)
return 0;
JS_ASSERT(w <= 2);
bx = b->x;
if (w == 2) {
if (k)
}
n++;
n--;
bxe--;
}
b->wds = n;
return result;
}
/* Return floor(b/S) and set b to be the remainder. As added restrictions, b must not have
* more words than S, the most significant word of S must not start with a 1 bit, and the
* returned quotient must be less than 36. */
{
int32 n;
#ifdef ULLong
#else
#endif
n = S->wds;
if (b->wds < n)
return 0;
sx = S->x;
bx = b->x;
JS_ASSERT(q < 36);
if (q) {
borrow = 0;
carry = 0;
do {
#ifdef ULLong
#else
#endif
}
if (!*bxe) {
bx = b->x;
--n;
b->wds = n;
}
}
if (cmp(b, S) >= 0) {
q++;
borrow = 0;
carry = 0;
bx = b->x;
sx = S->x;
do {
#ifdef ULLong
#else
#endif
bx = b->x;
if (!*bxe) {
--n;
b->wds = n;
}
}
return (int32)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.
*/
/* Always emits at least one digit. */
/* If biasUp is set, then rounding in modes 2 and 3 will round away from zero
* when the number is exactly halfway between two representable values. For example,
* rounding 2.5 to zero digits after the decimal point will return 3 and not 2.
* 2.49 will still round to 2, and 2.51 will still round to 3. */
/* bufsize should be at least 20 for modes 0 and 1. For the other modes,
* bufsize should be two greater than the maximum number of output characters expected. */
static JSBool
{
/* 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.
*/
Long L;
#ifndef Sudden_Underflow
ULong x;
#endif
char *s;
SET_FPU();
/* set sign for everything, including 0's and NaNs */
*sign = 1;
}
else
*sign = 0;
/* Infinity or NaN */
*decpt = 9999;
/* JS_SetError(JS_BUFFER_OVERFLOW_ERROR, 0); */
goto ret2;
}
if (rve) {
}
goto ret2;
}
b = NULL; /* initialize for abort protection */
S = NULL;
if (!d) {
*decpt = 1;
if (bufsize < 2) {
/* JS_SetError(JS_BUFFER_OVERFLOW_ERROR, 0); */
goto ret2;
}
if (rve)
/* We might have jumped to "no_digits" from below, so we need
* to be sure to free the potentially allocated Bigints to avoid
* memory leaks. */
Bfree(b);
Bfree(S);
goto ret2;
}
if (!b)
goto nomem;
#ifdef Sudden_Underflow
#else
#endif
d2 = d;
/* 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.
* The error in the first-order Taylor series approximation
* is in our favor, so we just round up the constant enough
* to compensate for any error in the multiplication of
* (i - Bias) by 0.301029995663981; since |i - Bias| <= 1077,
* and 1077 * 0.30103 * 2^-52 ~=~ 7.2e-14,
* adding 1e-13 to the constant term more than suffices.
* Hence we adjust the constant term to 0.1760912590558.
* (We could get a more accurate k by invoking log10,
* but this is probably not worthwhile.)
*/
i -= Bias;
#ifndef Sudden_Underflow
denorm = 0;
}
else {
/* d is denormalized */
d2 = x;
denorm = 1;
}
#endif
/* At this point d = f*2^i, where 1 <= f < 2. d2 is an approximation of f. */
k--; /* want k = floor(ds) */
k_check = 1;
if (k >= 0 && k <= Ten_pmax) {
if (d < tens[k])
k--;
k_check = 0;
}
/* At this point floor(log10(d)) <= k <= floor(log10(d))+1.
If k_check is zero, we're guaranteed that k = floor(log10(d)). */
j = bbits - i - 1;
/* At this point d = b/2^j, where b is an odd integer. */
if (j >= 0) {
b2 = 0;
s2 = j;
}
else {
b2 = -j;
s2 = 0;
}
if (k >= 0) {
b5 = 0;
s5 = k;
s2 += k;
}
else {
b2 -= k;
b5 = -k;
s5 = 0;
}
/* At this point d/10^k = (b * 2^b2 * 5^b5) / (2^s2 * 5^s5), where b is an odd integer,
b2 >= 0, b5 >= 0, s2 >= 0, and s5 >= 0. */
mode = 0;
try_quick = 1;
if (mode > 5) {
mode -= 4;
try_quick = 0;
}
leftright = 1;
switch(mode) {
case 0:
case 1:
i = 18;
ndigits = 0;
break;
case 2:
leftright = 0;
/* no break */
case 4:
if (ndigits <= 0)
ndigits = 1;
break;
case 3:
leftright = 0;
/* no break */
case 5:
i = ndigits + k + 1;
ilim = i;
ilim1 = i - 1;
if (i <= 0)
i = 1;
}
/* ilim is the maximum number of significant digits we want, based on k and ndigits. */
/* ilim1 is the maximum number of significant digits we want, based on k and ndigits,
when it turns out that k was computed too high by one. */
/* Ensure space for at least i+1 characters, including trailing null. */
Bfree(b);
goto ret2;
}
s = buf;
/* Try to get by with floating-point arithmetic. */
i = 0;
d2 = d;
k0 = k;
/* Divide d by 10^k, keeping track of the roundoff error and avoiding overflows. */
if (k > 0) {
j = k >> 4;
if (j & Bletch) {
/* prevent overflows */
j &= Bletch - 1;
ieps++;
}
for(; j; j >>= 1, i++)
if (j & 1) {
ieps++;
}
d /= ds;
}
else if ((j1 = -k) != 0) {
if (j & 1) {
ieps++;
d *= bigtens[i];
}
}
/* Check that k was computed correctly. */
if (ilim1 <= 0)
goto fast_failed;
k--;
d *= 10.;
ieps++;
}
/* eps bounds the cumulative error. */
if (ilim == 0) {
S = mhi = 0;
d -= 5.;
if (d > eps)
goto one_digit;
if (d < -eps)
goto no_digits;
goto fast_failed;
}
#ifndef No_leftright
if (leftright) {
/* Use Steele & White method of only
* generating digits needed.
*/
for(i = 0;;) {
L = (Long)d;
d -= L;
*s++ = '0' + (char)L;
if (d < eps)
goto ret1;
if (1. - d < eps)
goto bump_up;
if (++i >= ilim)
break;
eps *= 10.;
d *= 10.;
}
}
else {
#endif
/* Generate ilim digits, then fix them up. */
for(i = 1;; i++, d *= 10.) {
L = (Long)d;
d -= L;
*s++ = '0' + (char)L;
if (i == ilim) {
if (d > 0.5 + eps)
goto bump_up;
else if (d < 0.5 - eps) {
while(*--s == '0') ;
s++;
goto ret1;
}
break;
}
}
#ifndef No_leftright
}
#endif
s = buf;
d = d2;
k = k0;
}
/* Do we have a "small" integer? */
/* Yes. */
S = mhi = 0;
goto no_digits;
goto one_digit;
}
for(i = 1;; i++) {
d -= L*ds;
#ifdef Check_FLT_ROUNDS
/* If FLT_ROUNDS == 2, L will usually be high by 1 */
if (d < 0) {
L--;
d += ds;
}
#endif
*s++ = '0' + (char)L;
if (i == ilim) {
d += d;
while(*--s == '9')
if (s == buf) {
k++;
*s = '0';
break;
}
++*s++;
}
break;
}
if (!(d *= 10.))
break;
}
goto ret1;
}
if (leftright) {
if (mode < 2) {
i =
#ifndef Sudden_Underflow
#endif
1 + P - bbits;
/* i is 1 plus the number of trailing zero bits in d's significand. Thus,
(2^m2 * 5^m5) / (2^(s2+i) * 5^s5) = (1/2 lsb of d)/10^k. */
}
else {
j = ilim - 1;
if (m5 >= j)
m5 -= j;
else {
b5 += j;
m5 = 0;
}
if ((i = ilim) < 0) {
m2 -= i;
i = 0;
}
/* (2^m2 * 5^m5) / (2^(s2+i) * 5^s5) = (1/2 * 10^(1-ilim))/10^k. */
}
b2 += i;
s2 += i;
if (!mhi)
goto nomem;
/* (mhi * 2^m2 * 5^m5) / (2^s2 * 5^s5) = one-half of last printed (when mode >= 2) or
input (when mode < 2) significant digit, divided by 10^k. */
}
/* We still have d/10^k = (b * 2^b2 * 5^b5) / (2^s2 * 5^s5). Reduce common factors in
b2, m2, and s2 without changing the equalities. */
b2 -= i;
m2 -= i;
s2 -= i;
}
/* Fold b5 into b and m5 into mhi. */
if (b5 > 0) {
if (leftright) {
if (m5 > 0) {
if (!mhi)
goto nomem;
if (!b1)
goto nomem;
Bfree(b);
b = b1;
}
b = pow5mult(b, j);
if (!b)
goto nomem;
}
}
else {
if (!b)
goto nomem;
}
}
/* Now we have d/10^k = (b * 2^b2) / (2^s2 * 5^s5) and
(mhi * 2^m2) / (2^s2 * 5^s5) = one-half of last printed or input significant digit, divided by 10^k. */
S = i2b(1);
if (!S)
goto nomem;
if (s5 > 0) {
if (!S)
goto nomem;
}
/* Now we have d/10^k = (b * 2^b2) / (S * 2^s2) and
(mhi * 2^m2) / (S * 2^s2) = one-half of last printed or input significant digit, divided by 10^k. */
/* Check for special case that d is a normalized power of 2. */
spec_case = 0;
if (mode < 2) {
#ifndef Sudden_Underflow
#endif
) {
/* The special case. Here we want to be within a quarter of the last input
significant digit instead of one half of it when the decimal output string's value is less than d. */
spec_case = 1;
}
}
/* Arrange for convenient computation of quotients:
* shift left if necessary so divisor has 4 leading 0 bits.
*
* Perhaps we should just compute leading 28 bits of S once
* and for all and pass them and a shift to quorem, so it
* can do shifts and ors to compute the numerator for q.
*/
i = 32 - i;
/* i is the number of leading zero bits in the most significant word of S*2^s2. */
if (i > 4) {
i -= 4;
b2 += i;
m2 += i;
s2 += i;
}
else if (i < 4) {
i += 28;
b2 += i;
m2 += i;
s2 += i;
}
/* Now S*2^s2 has exactly four leading zero bits in its most significant word. */
if (b2 > 0) {
if (!b)
goto nomem;
}
if (s2 > 0) {
if (!S)
goto nomem;
}
/* Now we have d/10^k = b/S and
(mhi * 2^m2) / S = maximum acceptable error, divided by 10^k. */
if (k_check) {
if (cmp(b,S) < 0) {
k--;
if (!b)
goto nomem;
if (leftright) {
if (!mhi)
goto nomem;
}
}
}
/* At this point 1 <= d/10^k = b/S < 10. */
/* We're doing fixed-mode output and d is less than the minimum nonzero output in this mode.
Output either zero or the minimum nonzero output depending on which is closer to d. */
if (ilim < 0)
goto no_digits;
S = multadd(S,5,0);
if (!S)
goto nomem;
i = cmp(b,S);
if (i < 0 || (i == 0 && !biasUp)) {
/* Always emit at least one digit. If the number appears to be zero
using the current mode, then emit one '0' digit and set decpt to 1. */
/*no_digits:
k = -1 - ndigits;
goto ret; */
goto no_digits;
}
*s++ = '1';
k++;
goto ret;
}
if (leftright) {
if (m2 > 0) {
if (!mhi)
goto nomem;
}
/* Compute mlo -- check for special case
* that d is a normalized power of 2.
*/
if (spec_case) {
if (!mhi)
goto nomem;
if (!mhi)
goto nomem;
}
/* mlo/S = maximum acceptable error, divided by 10^k, if the output is less than d. */
/* mhi/S = maximum acceptable error, divided by 10^k, if the output is greater than d. */
for(i = 1;;i++) {
/* Do we yet have the shortest decimal string
* that will round to d?
*/
/* j is b/S compared with mlo/S. */
if (!delta)
goto nomem;
/* j1 is b/S compared with 1 - mhi/S. */
#ifndef ROUND_BIASED
if (dig == '9')
goto round_9_up;
if (j > 0)
dig++;
*s++ = (char)dig;
goto ret;
}
#endif
if ((j < 0) || (j == 0 && !mode
#ifndef ROUND_BIASED
&& !(word1(d) & 1)
#endif
)) {
if (j1 > 0) {
/* Either dig or dig+1 would work here as the least significant decimal digit.
Use whichever would produce a decimal value closer to d. */
b = lshift(b, 1);
if (!b)
goto nomem;
&& (dig++ == '9'))
goto round_9_up;
}
*s++ = (char)dig;
goto ret;
}
if (j1 > 0) {
*s++ = '9';
goto roundoff;
}
*s++ = dig + 1;
goto ret;
}
*s++ = (char)dig;
if (i == ilim)
break;
b = multadd(b, 10, 0);
if (!b)
goto nomem;
if (!mhi)
goto nomem;
}
else {
if (!mlo)
goto nomem;
if (!mhi)
goto nomem;
}
}
}
else
for(i = 1;; i++) {
if (i >= ilim)
break;
b = multadd(b, 10, 0);
if (!b)
goto nomem;
}
/* Round off last digit */
b = lshift(b, 1);
if (!b)
goto nomem;
j = cmp(b, S);
while(*--s == '9')
if (s == buf) {
k++;
*s++ = '1';
goto ret;
}
++*s++;
}
else {
/* Strip trailing zeros */
while(*--s == '0') ;
s++;
}
ret:
Bfree(S);
if (mhi) {
}
ret1:
Bfree(b);
*s = '\0';
if (rve)
*rve = s;
*decpt = k + 1;
goto ret2;
Bfree(S);
if (mhi) {
}
Bfree(b);
ret2:
RESTORE_FPU();
return ok;
}
/* Mapping of JSDToStrMode -> js_dtoa mode */
static const int dtoaModes[] = {
0, /* DTOSTR_STANDARD */
0, /* DTOSTR_STANDARD_EXPONENTIAL, */
3, /* DTOSTR_FIXED, */
2, /* DTOSTR_EXPONENTIAL, */
2}; /* DTOSTR_PRECISION */
JS_FRIEND_API(char *)
{
int decPt; /* Position of decimal point relative to first digit returned by js_dtoa */
int sign; /* Nonzero if the sign bit was set in d */
int nDigits; /* Number of significand digits returned by js_dtoa */
char *numEnd; /* Pointer past the digits returned by js_dtoa */
JS_ASSERT(bufferSize >= (size_t)(mode <= DTOSTR_STANDARD_EXPONENTIAL ? DTOSTR_STANDARD_BUFFER_SIZE :
mode = DTOSTR_STANDARD; /* Change mode here rather than below because the buffer may not be large enough to hold a large integer. */
/* Locking for Balloc's shared buffers */
dtoaRet = js_dtoa(d, dtoaModes[mode], mode >= DTOSTR_FIXED, precision, &decPt, &sign, &numEnd, numBegin, bufferSize-2);
if (!dtoaRet)
return 0;
/* If Infinity, -Infinity, or NaN, return the string regardless of the mode. */
if (decPt != 9999) {
int minNDigits = 0; /* Minimum number of significand digits required by mode and precision */
char *p;
char *q;
switch (mode) {
case DTOSTR_STANDARD:
else
minNDigits = decPt;
break;
case DTOSTR_FIXED:
if (precision >= 0)
else
minNDigits = decPt;
break;
case DTOSTR_EXPONENTIAL:
/* Fall through */
break;
case DTOSTR_PRECISION:
break;
}
/* If the number has fewer than minNDigits, pad it with zeros at the end */
if (nDigits < minNDigits) {
p = numBegin + minNDigits;
do {
*numEnd++ = '0';
} while (numEnd != p);
*numEnd = '\0';
}
if (exponentialNotation) {
/* Insert a decimal point if more than one significand digit */
if (nDigits != 1) {
numBegin--;
}
/* Some kind of a fraction in fixed notation */
if (decPt > 0) {
/* dd...dd . dd...dd */
p = --numBegin;
do {
*p = p[1];
p++;
} while (--decPt);
*p = '.';
} else {
/* 0 . 00...00dd...dd */
p = numEnd;
q = numEnd;
*numEnd = '\0';
while (p != numBegin)
*--q = *--p;
for (p = numBegin + 1; p != q; p++)
*p = '0';
*numBegin = '.';
*--numBegin = '0';
}
}
}
/* If negative and neither -0.0 nor NaN, output a leading '-'. */
if (sign &&
*--numBegin = '-';
}
return numBegin;
}
/* Let b = floor(b / divisor), and return the remainder. b must be nonnegative.
* divisor must be between 1 and 65536.
* This function cannot run out of memory. */
static uint32
{
if (!n)
return 0; /* b is zero */
bx = b->x;
do {
/* Decrease the size of the number if its most significant word is now zero. */
if (bx[n-1] == 0)
b->wds--;
return remainder;
}
/* "-0.0000...(1073 zeros after decimal point)...0001\0" is the longest string that we could produce,
* which occurs when printing -5e-324 in binary. We could compute a better estimate of the size of
* the output string and malloc fewer bytes depending on d and base, but why bother? */
#define DTOBASESTR_BUFFER_SIZE 1078
JS_FRIEND_API(char *)
JS_dtobasestr(int base, double d)
{
char *buffer; /* The output string */
char *p; /* Pointer to current position in the buffer */
char *pInt; /* Pointer to the beginning of the integer part of the string */
char *q;
double di; /* d truncated to an integer */
double df; /* The fractional part of d */
if (buffer) {
p = buffer;
if (d < 0.0
&& !((word0(d) & Exp_mask) == Exp_mask && ((word0(d) & Frac_mask) || word1(d))) /* Visual C++ doesn't know how to compare against NaN */
#endif
) {
*p++ = '-';
d = -d;
}
/* Check for Infinity and NaN */
return buffer;
}
/* Locking for Balloc's shared buffers */
/* Output the integer part of d with the digits in reverse order. */
pInt = p;
if (di <= 4294967295.0) {
if (n)
do {
n = m;
} while (n);
else *p++ = '0';
} else {
int32 e;
if (!b)
goto nomem1;
b = lshift(b, e);
if (!b) {
Bfree(b);
return NULL;
}
do {
} while (b->wds);
Bfree(b);
}
/* Reverse the digits of the integer part of d. */
q = p-1;
while (q > pInt) {
*pInt++ = *q;
*q-- = ch;
}
if (df != 0.0) {
/* We have a fraction. */
*p++ = '.';
if (!b) {
Bfree(b);
Bfree(s);
return NULL;
}
JS_ASSERT(e < 0);
/* At this point df = b * 2^e. e must be less than zero because 0 < df < 1. */
#ifndef Sudden_Underflow
if (!s2)
s2 = -1;
#endif
/* 1/2^s2 = (nextDouble(d) - d)/2 */
if (!mlo)
goto nomem2;
#ifndef Sudden_Underflow
#endif
) {
/* The special case. Here we want to be within a quarter of the last input
significant digit instead of one half of it when the output string's value is less than d. */
if (!mhi)
goto nomem2;
}
if (!b)
goto nomem2;
s = i2b(1);
if (!s)
goto nomem2;
if (!s)
goto nomem2;
/* At this point we have the following:
* s = 2^s2;
* 1 > df = b/2^s2 > 0;
* (d - prevDouble(d))/2 = mlo/2^s2;
* (nextDouble(d) - d)/2 = mhi/2^s2. */
do {
if (!b)
goto nomem2;
if (!mhi)
goto nomem2;
}
else {
if (!mlo)
goto nomem2;
if (!mhi)
goto nomem2;
}
/* Do we yet have the shortest string that will round to d? */
/* j is b/2^s2 compared with mlo/2^s2. */
if (!delta)
goto nomem2;
/* j1 is b/2^s2 compared with 1 - mhi/2^s2. */
#ifndef ROUND_BIASED
if (j > 0)
digit++;
} else
#endif
if (j < 0 || (j == 0
#ifndef ROUND_BIASED
&& !(word1(d) & 1)
#endif
)) {
if (j1 > 0) {
/* Either dig or dig+1 would work here as the least significant digit.
Use whichever would produce an output value closer to d. */
b = lshift(b, 1);
if (!b)
goto nomem2;
if (j1 > 0) /* The even test (|| (j1 == 0 && (digit & 1))) is not here because it messes up odd base output
* such as 3.5 in base 3. */
digit++;
}
} else if (j1 > 0) {
digit++;
}
} while (!done);
Bfree(b);
Bfree(s);
}
*p = '\0';
}
return buffer;
}