Back to index

lightning-sunbird  0.9+nobinonly
Defines | Typedefs | Enumerations | Functions
jsdtoa.h File Reference
#include "jscompat.h"
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Defines

#define JS_DTOA_ERANGE   1
#define JS_DTOA_ENOMEM   2
#define DTOSTR_STANDARD_BUFFER_SIZE   26
#define DTOSTR_VARIABLE_BUFFER_SIZE(precision)   ((precision)+24 > DTOSTR_STANDARD_BUFFER_SIZE ? (precision)+24 : DTOSTR_STANDARD_BUFFER_SIZE)

Typedefs

typedef enum JSDToStrMode JSDToStrMode

Enumerations

enum  JSDToStrMode {
  DTOSTR_STANDARD, DTOSTR_STANDARD_EXPONENTIAL, DTOSTR_FIXED, DTOSTR_EXPONENTIAL,
  DTOSTR_PRECISION
}

Functions

 JS_strtod (const char *s00, char **se, int *err)
 JS_dtostr (char *buffer, size_t bufferSize, JSDToStrMode mode, int precision, double dval)
 JS_dtobasestr (int base, double d)
void js_FinishDtoa (void)

Define Documentation

Definition at line 92 of file jsdtoa.h.

#define DTOSTR_VARIABLE_BUFFER_SIZE (   precision)    ((precision)+24 > DTOSTR_STANDARD_BUFFER_SIZE ? (precision)+24 : DTOSTR_STANDARD_BUFFER_SIZE)

Definition at line 96 of file jsdtoa.h.

Definition at line 65 of file jsdtoa.h.

Definition at line 64 of file jsdtoa.h.


Typedef Documentation

typedef enum JSDToStrMode JSDToStrMode

Enumeration Type Documentation

Enumerator:
DTOSTR_STANDARD 
DTOSTR_STANDARD_EXPONENTIAL 
DTOSTR_FIXED 
DTOSTR_EXPONENTIAL 
DTOSTR_PRECISION 

Definition at line 81 of file jsdtoa.h.

                          {
    DTOSTR_STANDARD,              /* Either fixed or exponential format; round-trip */
    DTOSTR_STANDARD_EXPONENTIAL,  /* Always exponential format; round-trip */
    DTOSTR_FIXED,                 /* Round to <precision> digits after the decimal point; exponential if number is large */
    DTOSTR_EXPONENTIAL,           /* Always exponential format; <precision> significant digits */
    DTOSTR_PRECISION              /* Either fixed or exponential format; <precision> significant digits */
} JSDToStrMode;

Function Documentation

JS_dtobasestr ( int  base,
double  d 
)

Definition at line 2918 of file jsdtoa.c.

{
    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;
    uint32 digit;
    double di;           /* d truncated to an integer */
    double df;           /* The fractional part of d */

    JS_ASSERT(base >= 2 && base <= 36);

    buffer = (char*) malloc(DTOBASESTR_BUFFER_SIZE);
    if (buffer) {
        p = buffer;
        if (d < 0.0
#if defined(XP_WIN) || defined(XP_OS2)
            && !((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 */
        if ((word0(d) & Exp_mask) == Exp_mask) {
            strcpy(p, !word1(d) && !(word0(d) & Frac_mask) ? "Infinity" : "NaN");
            return buffer;
        }

        /* Locking for Balloc's shared buffers */
        ACQUIRE_DTOA_LOCK();

        /* Output the integer part of d with the digits in reverse order. */
        pInt = p;
        di = fd_floor(d);
        if (di <= 4294967295.0) {
            uint32 n = (uint32)di;
            if (n)
                do {
                    uint32 m = n / base;
                    digit = n - m*base;
                    n = m;
                    JS_ASSERT(digit < (uint32)base);
                    *p++ = BASEDIGIT(digit);
                } while (n);
            else *p++ = '0';
        } else {
            int32 e;
            int32 bits;  /* Number of significant bits in di; not used. */
            Bigint *b = d2b(di, &e, &bits);
            if (!b)
                goto nomem1;
            b = lshift(b, e);
            if (!b) {
              nomem1:
                Bfree(b);
                RELEASE_DTOA_LOCK();
                free(buffer);
                return NULL;
            }
            do {
                digit = divrem(b, base);
                JS_ASSERT(digit < (uint32)base);
                *p++ = BASEDIGIT(digit);
            } while (b->wds);
            Bfree(b);
        }
        /* Reverse the digits of the integer part of d. */
        q = p-1;
        while (q > pInt) {
            char ch = *pInt;
            *pInt++ = *q;
            *q-- = ch;
        }

        df = d - di;
        if (df != 0.0) {
            /* We have a fraction. */
            int32 e, bbits, s2, done;
            Bigint *b, *s, *mlo, *mhi;

            b = s = mlo = mhi = NULL;

            *p++ = '.';
            b = d2b(df, &e, &bbits);
            if (!b) {
              nomem2:
                Bfree(b);
                Bfree(s);
                if (mlo != mhi)
                    Bfree(mlo);
                Bfree(mhi);
                RELEASE_DTOA_LOCK();
                free(buffer);
                return NULL;
            }
            JS_ASSERT(e < 0);
            /* At this point df = b * 2^e.  e must be less than zero because 0 < df < 1. */

            s2 = -(int32)(word0(d) >> Exp_shift1 & Exp_mask>>Exp_shift1);
#ifndef Sudden_Underflow
            if (!s2)
                s2 = -1;
#endif
            s2 += Bias + P;
            /* 1/2^s2 = (nextDouble(d) - d)/2 */
            JS_ASSERT(-s2 < e);
            mlo = i2b(1);
            if (!mlo)
                goto nomem2;
            mhi = mlo;
            if (!word1(d) && !(word0(d) & Bndry_mask)
#ifndef Sudden_Underflow
                && word0(d) & (Exp_mask & Exp_mask << 1)
#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.  */
                s2 += Log2P;
                mhi = i2b(1<<Log2P);
                if (!mhi)
                    goto nomem2;
            }
            b = lshift(b, e + s2);
            if (!b)
                goto nomem2;
            s = i2b(1);
            if (!s)
                goto nomem2;
            s = lshift(s, s2);
            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. */

            done = JS_FALSE;
            do {
                int32 j, j1;
                Bigint *delta;

                b = multadd(b, base, 0);
                if (!b)
                    goto nomem2;
                digit = quorem2(b, s2);
                if (mlo == mhi) {
                    mlo = mhi = multadd(mlo, base, 0);
                    if (!mhi)
                        goto nomem2;
                }
                else {
                    mlo = multadd(mlo, base, 0);
                    if (!mlo)
                        goto nomem2;
                    mhi = multadd(mhi, base, 0);
                    if (!mhi)
                        goto nomem2;
                }

                /* Do we yet have the shortest string that will round to d? */
                j = cmp(b, mlo);
                /* j is b/2^s2 compared with mlo/2^s2. */
                delta = diff(s, mhi);
                if (!delta)
                    goto nomem2;
                j1 = delta->sign ? 1 : cmp(b, delta);
                Bfree(delta);
                /* j1 is b/2^s2 compared with 1 - mhi/2^s2. */

#ifndef ROUND_BIASED
                if (j1 == 0 && !(word1(d) & 1)) {
                    if (j > 0)
                        digit++;
                    done = JS_TRUE;
                } 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;
                        j1 = cmp(b, s);
                        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++;
                    }
                    done = JS_TRUE;
                } else if (j1 > 0) {
                    digit++;
                    done = JS_TRUE;
                }
                JS_ASSERT(digit < (uint32)base);
                *p++ = BASEDIGIT(digit);
            } while (!done);
            Bfree(b);
            Bfree(s);
            if (mlo != mhi)
                Bfree(mlo);
            Bfree(mhi);
        }
        JS_ASSERT(p < buffer + DTOBASESTR_BUFFER_SIZE);
        *p = '\0';
        RELEASE_DTOA_LOCK();
    }
    return buffer;
}

Here is the call graph for this function:

Here is the caller graph for this function:

JS_dtostr ( char *  buffer,
size_t  bufferSize,
JSDToStrMode  mode,
int  precision,
double  dval 
)

Definition at line 2753 of file jsdtoa.c.

{
    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 *numBegin = buffer+2;  /* Pointer to the digits returned by js_dtoa; the +2 leaves space for */
                                /* the sign and/or decimal point */
    char *numEnd;               /* Pointer past the digits returned by js_dtoa */
    JSBool dtoaRet;

    JS_ASSERT(bufferSize >= (size_t)(mode <= DTOSTR_STANDARD_EXPONENTIAL ? DTOSTR_STANDARD_BUFFER_SIZE :
            DTOSTR_VARIABLE_BUFFER_SIZE(precision)));

    if (mode == DTOSTR_FIXED && (d >= 1e21 || d <= -1e21))
        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 */
    ACQUIRE_DTOA_LOCK();
    dtoaRet = js_dtoa(d, dtoaModes[mode], mode >= DTOSTR_FIXED, precision, &decPt, &sign, &numEnd, numBegin, bufferSize-2);
    RELEASE_DTOA_LOCK();
    if (!dtoaRet)
        return 0;

    nDigits = numEnd - numBegin;

    /* If Infinity, -Infinity, or NaN, return the string regardless of the mode. */
    if (decPt != 9999) {
        JSBool exponentialNotation = JS_FALSE;
        int minNDigits = 0;         /* Minimum number of significand digits required by mode and precision */
        char *p;
        char *q;

        switch (mode) {
            case DTOSTR_STANDARD:
                if (decPt < -5 || decPt > 21)
                    exponentialNotation = JS_TRUE;
                else
                    minNDigits = decPt;
                break;

            case DTOSTR_FIXED:
                if (precision >= 0)
                    minNDigits = decPt + precision;
                else
                    minNDigits = decPt;
                break;

            case DTOSTR_EXPONENTIAL:
                JS_ASSERT(precision > 0);
                minNDigits = precision;
                /* Fall through */
            case DTOSTR_STANDARD_EXPONENTIAL:
                exponentialNotation = JS_TRUE;
                break;

            case DTOSTR_PRECISION:
                JS_ASSERT(precision > 0);
                minNDigits = precision;
                if (decPt < -5 || decPt > precision)
                    exponentialNotation = JS_TRUE;
                break;
        }

        /* If the number has fewer than minNDigits, pad it with zeros at the end */
        if (nDigits < minNDigits) {
            p = numBegin + minNDigits;
            nDigits = 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--;
                numBegin[0] = numBegin[1];
                numBegin[1] = '.';
            }
            JS_snprintf(numEnd, bufferSize - (numEnd - buffer), "e%+d", decPt-1);
        } else if (decPt != nDigits) {
            /* Some kind of a fraction in fixed notation */
            JS_ASSERT(decPt <= nDigits);
            if (decPt > 0) {
                /* dd...dd . dd...dd */
                p = --numBegin;
                do {
                    *p = p[1];
                    p++;
                } while (--decPt);
                *p = '.';
            } else {
                /* 0 . 00...00dd...dd */
                p = numEnd;
                numEnd += 1 - decPt;
                q = numEnd;
                JS_ASSERT(numEnd < buffer + bufferSize);
                *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 &&
            !(word0(d) == Sign_bit && word1(d) == 0) &&
            !((word0(d) & Exp_mask) == Exp_mask &&
              (word1(d) || (word0(d) & Frac_mask)))) {
        *--numBegin = '-';
    }
    return numBegin;
}

Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 1192 of file jsdtoa.c.

{
    int count;
    Bigint *temp;

#ifdef JS_THREADSAFE
    if (initialized == JS_TRUE) {
        PR_DestroyLock(freelist_lock);
        PR_DestroyLock(p5s_lock);
        initialized = JS_FALSE;
    }
#endif

    /* clear down the freelist array and p5s */

    /* static Bigint *freelist[Kmax+1]; */
    for (count = 0; count <= Kmax; count++) {
        Bigint **listp = &freelist[count];
        while ((temp = *listp) != NULL) {
            *listp = temp->next;
            free(temp);
        }
        freelist[count] = NULL;
    }

    /* static Bigint *p5s; */
    while (p5s) {
        temp = p5s;
        p5s = p5s->next;
        free(temp);
    }
}

Here is the call graph for this function:

Here is the caller graph for this function:

JS_strtod ( const char *  s00,
char **  se,
int err 
)