OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [insight/] [tcl/] [compat/] [strtod.c] - Diff between revs 578 and 1765

Only display areas with differences | Details | Blame | View Log

Rev 578 Rev 1765
/*
/*
 * strtod.c --
 * strtod.c --
 *
 *
 *      Source code for the "strtod" library procedure.
 *      Source code for the "strtod" library procedure.
 *
 *
 * Copyright (c) 1988-1993 The Regents of the University of California.
 * Copyright (c) 1988-1993 The Regents of the University of California.
 * Copyright (c) 1994 Sun Microsystems, Inc.
 * Copyright (c) 1994 Sun Microsystems, Inc.
 *
 *
 * See the file "license.terms" for information on usage and redistribution
 * See the file "license.terms" for information on usage and redistribution
 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
 *
 *
 * RCS: @(#) $Id: strtod.c,v 1.1.1.1 2002-01-16 10:25:23 markom Exp $
 * RCS: @(#) $Id: strtod.c,v 1.1.1.1 2002-01-16 10:25:23 markom Exp $
 */
 */
 
 
#include "tcl.h"
#include "tcl.h"
#ifdef NO_STDLIB_H
#ifdef NO_STDLIB_H
#   include "../compat/stdlib.h"
#   include "../compat/stdlib.h"
#else
#else
#   include <stdlib.h>
#   include <stdlib.h>
#endif
#endif
#include <ctype.h>
#include <ctype.h>
 
 
#ifndef TRUE
#ifndef TRUE
#define TRUE 1
#define TRUE 1
#define FALSE 0
#define FALSE 0
#endif
#endif
#ifndef NULL
#ifndef NULL
#define NULL 0
#define NULL 0
#endif
#endif
 
 
static int maxExponent = 511;   /* Largest possible base 10 exponent.  Any
static int maxExponent = 511;   /* Largest possible base 10 exponent.  Any
                                 * exponent larger than this will already
                                 * exponent larger than this will already
                                 * produce underflow or overflow, so there's
                                 * produce underflow or overflow, so there's
                                 * no need to worry about additional digits.
                                 * no need to worry about additional digits.
                                 */
                                 */
static double powersOf10[] = {  /* Table giving binary powers of 10.  Entry */
static double powersOf10[] = {  /* Table giving binary powers of 10.  Entry */
    10.,                        /* is 10^2^i.  Used to convert decimal */
    10.,                        /* is 10^2^i.  Used to convert decimal */
    100.,                       /* exponents into floating-point numbers. */
    100.,                       /* exponents into floating-point numbers. */
    1.0e4,
    1.0e4,
    1.0e8,
    1.0e8,
    1.0e16,
    1.0e16,
    1.0e32,
    1.0e32,
    1.0e64,
    1.0e64,
    1.0e128,
    1.0e128,
    1.0e256
    1.0e256
};
};


/*
/*
 *----------------------------------------------------------------------
 *----------------------------------------------------------------------
 *
 *
 * strtod --
 * strtod --
 *
 *
 *      This procedure converts a floating-point number from an ASCII
 *      This procedure converts a floating-point number from an ASCII
 *      decimal representation to internal double-precision format.
 *      decimal representation to internal double-precision format.
 *
 *
 * Results:
 * Results:
 *      The return value is the double-precision floating-point
 *      The return value is the double-precision floating-point
 *      representation of the characters in string.  If endPtr isn't
 *      representation of the characters in string.  If endPtr isn't
 *      NULL, then *endPtr is filled in with the address of the
 *      NULL, then *endPtr is filled in with the address of the
 *      next character after the last one that was part of the
 *      next character after the last one that was part of the
 *      floating-point number.
 *      floating-point number.
 *
 *
 * Side effects:
 * Side effects:
 *      None.
 *      None.
 *
 *
 *----------------------------------------------------------------------
 *----------------------------------------------------------------------
 */
 */
 
 
double
double
strtod(string, endPtr)
strtod(string, endPtr)
    CONST char *string;         /* A decimal ASCII floating-point number,
    CONST char *string;         /* A decimal ASCII floating-point number,
                                 * optionally preceded by white space.
                                 * optionally preceded by white space.
                                 * Must have form "-I.FE-X", where I is the
                                 * Must have form "-I.FE-X", where I is the
                                 * integer part of the mantissa, F is the
                                 * integer part of the mantissa, F is the
                                 * fractional part of the mantissa, and X
                                 * fractional part of the mantissa, and X
                                 * is the exponent.  Either of the signs
                                 * is the exponent.  Either of the signs
                                 * may be "+", "-", or omitted.  Either I
                                 * may be "+", "-", or omitted.  Either I
                                 * or F may be omitted, or both.  The decimal
                                 * or F may be omitted, or both.  The decimal
                                 * point isn't necessary unless F is present.
                                 * point isn't necessary unless F is present.
                                 * The "E" may actually be an "e".  E and X
                                 * The "E" may actually be an "e".  E and X
                                 * may both be omitted (but not just one).
                                 * may both be omitted (but not just one).
                                 */
                                 */
    char **endPtr;              /* If non-NULL, store terminating character's
    char **endPtr;              /* If non-NULL, store terminating character's
                                 * address here. */
                                 * address here. */
{
{
    int sign, expSign = FALSE;
    int sign, expSign = FALSE;
    double fraction, dblExp, *d;
    double fraction, dblExp, *d;
    register CONST char *p;
    register CONST char *p;
    register int c;
    register int c;
    int exp = 0;         /* Exponent read from "EX" field. */
    int exp = 0;         /* Exponent read from "EX" field. */
    int fracExp = 0;             /* Exponent that derives from the fractional
    int fracExp = 0;             /* Exponent that derives from the fractional
                                 * part.  Under normal circumstatnces, it is
                                 * part.  Under normal circumstatnces, it is
                                 * the negative of the number of digits in F.
                                 * the negative of the number of digits in F.
                                 * However, if I is very long, the last digits
                                 * However, if I is very long, the last digits
                                 * of I get dropped (otherwise a long I with a
                                 * of I get dropped (otherwise a long I with a
                                 * large negative exponent could cause an
                                 * large negative exponent could cause an
                                 * unnecessary overflow on I alone).  In this
                                 * unnecessary overflow on I alone).  In this
                                 * case, fracExp is incremented one for each
                                 * case, fracExp is incremented one for each
                                 * dropped digit. */
                                 * dropped digit. */
    int mantSize;               /* Number of digits in mantissa. */
    int mantSize;               /* Number of digits in mantissa. */
    int decPt;                  /* Number of mantissa digits BEFORE decimal
    int decPt;                  /* Number of mantissa digits BEFORE decimal
                                 * point. */
                                 * point. */
    CONST char *pExp;           /* Temporarily holds location of exponent
    CONST char *pExp;           /* Temporarily holds location of exponent
                                 * in string. */
                                 * in string. */
 
 
    /*
    /*
     * Strip off leading blanks and check for a sign.
     * Strip off leading blanks and check for a sign.
     */
     */
 
 
    p = string;
    p = string;
    while (isspace(*p)) {
    while (isspace(*p)) {
        p += 1;
        p += 1;
    }
    }
    if (*p == '-') {
    if (*p == '-') {
        sign = TRUE;
        sign = TRUE;
        p += 1;
        p += 1;
    } else {
    } else {
        if (*p == '+') {
        if (*p == '+') {
            p += 1;
            p += 1;
        }
        }
        sign = FALSE;
        sign = FALSE;
    }
    }
 
 
    /*
    /*
     * Count the number of digits in the mantissa (including the decimal
     * Count the number of digits in the mantissa (including the decimal
     * point), and also locate the decimal point.
     * point), and also locate the decimal point.
     */
     */
 
 
    decPt = -1;
    decPt = -1;
    for (mantSize = 0; ; mantSize += 1)
    for (mantSize = 0; ; mantSize += 1)
    {
    {
        c = *p;
        c = *p;
        if (!isdigit(c)) {
        if (!isdigit(c)) {
            if ((c != '.') || (decPt >= 0)) {
            if ((c != '.') || (decPt >= 0)) {
                break;
                break;
            }
            }
            decPt = mantSize;
            decPt = mantSize;
        }
        }
        p += 1;
        p += 1;
    }
    }
 
 
    /*
    /*
     * Now suck up the digits in the mantissa.  Use two integers to
     * Now suck up the digits in the mantissa.  Use two integers to
     * collect 9 digits each (this is faster than using floating-point).
     * collect 9 digits each (this is faster than using floating-point).
     * If the mantissa has more than 18 digits, ignore the extras, since
     * If the mantissa has more than 18 digits, ignore the extras, since
     * they can't affect the value anyway.
     * they can't affect the value anyway.
     */
     */
 
 
    pExp  = p;
    pExp  = p;
    p -= mantSize;
    p -= mantSize;
    if (decPt < 0) {
    if (decPt < 0) {
        decPt = mantSize;
        decPt = mantSize;
    } else {
    } else {
        mantSize -= 1;                  /* One of the digits was the point. */
        mantSize -= 1;                  /* One of the digits was the point. */
    }
    }
    if (mantSize > 18) {
    if (mantSize > 18) {
        fracExp = decPt - 18;
        fracExp = decPt - 18;
        mantSize = 18;
        mantSize = 18;
    } else {
    } else {
        fracExp = decPt - mantSize;
        fracExp = decPt - mantSize;
    }
    }
    if (mantSize == 0) {
    if (mantSize == 0) {
        fraction = 0.0;
        fraction = 0.0;
        p = string;
        p = string;
        goto done;
        goto done;
    } else {
    } else {
        int frac1, frac2;
        int frac1, frac2;
        frac1 = 0;
        frac1 = 0;
        for ( ; mantSize > 9; mantSize -= 1)
        for ( ; mantSize > 9; mantSize -= 1)
        {
        {
            c = *p;
            c = *p;
            p += 1;
            p += 1;
            if (c == '.') {
            if (c == '.') {
                c = *p;
                c = *p;
                p += 1;
                p += 1;
            }
            }
            frac1 = 10*frac1 + (c - '0');
            frac1 = 10*frac1 + (c - '0');
        }
        }
        frac2 = 0;
        frac2 = 0;
        for (; mantSize > 0; mantSize -= 1)
        for (; mantSize > 0; mantSize -= 1)
        {
        {
            c = *p;
            c = *p;
            p += 1;
            p += 1;
            if (c == '.') {
            if (c == '.') {
                c = *p;
                c = *p;
                p += 1;
                p += 1;
            }
            }
            frac2 = 10*frac2 + (c - '0');
            frac2 = 10*frac2 + (c - '0');
        }
        }
        fraction = (1.0e9 * frac1) + frac2;
        fraction = (1.0e9 * frac1) + frac2;
    }
    }
 
 
    /*
    /*
     * Skim off the exponent.
     * Skim off the exponent.
     */
     */
 
 
    p = pExp;
    p = pExp;
    if ((*p == 'E') || (*p == 'e')) {
    if ((*p == 'E') || (*p == 'e')) {
        p += 1;
        p += 1;
        if (*p == '-') {
        if (*p == '-') {
            expSign = TRUE;
            expSign = TRUE;
            p += 1;
            p += 1;
        } else {
        } else {
            if (*p == '+') {
            if (*p == '+') {
                p += 1;
                p += 1;
            }
            }
            expSign = FALSE;
            expSign = FALSE;
        }
        }
        while (isdigit(*p)) {
        while (isdigit(*p)) {
            exp = exp * 10 + (*p - '0');
            exp = exp * 10 + (*p - '0');
            p += 1;
            p += 1;
        }
        }
    }
    }
    if (expSign) {
    if (expSign) {
        exp = fracExp - exp;
        exp = fracExp - exp;
    } else {
    } else {
        exp = fracExp + exp;
        exp = fracExp + exp;
    }
    }
 
 
    /*
    /*
     * Generate a floating-point number that represents the exponent.
     * Generate a floating-point number that represents the exponent.
     * Do this by processing the exponent one bit at a time to combine
     * Do this by processing the exponent one bit at a time to combine
     * many powers of 2 of 10. Then combine the exponent with the
     * many powers of 2 of 10. Then combine the exponent with the
     * fraction.
     * fraction.
     */
     */
 
 
    if (exp < 0) {
    if (exp < 0) {
        expSign = TRUE;
        expSign = TRUE;
        exp = -exp;
        exp = -exp;
    } else {
    } else {
        expSign = FALSE;
        expSign = FALSE;
    }
    }
    if (exp > maxExponent) {
    if (exp > maxExponent) {
        exp = maxExponent;
        exp = maxExponent;
    }
    }
    dblExp = 1.0;
    dblExp = 1.0;
    for (d = powersOf10; exp != 0; exp >>= 1, d += 1) {
    for (d = powersOf10; exp != 0; exp >>= 1, d += 1) {
        if (exp & 01) {
        if (exp & 01) {
            dblExp *= *d;
            dblExp *= *d;
        }
        }
    }
    }
    if (expSign) {
    if (expSign) {
        fraction /= dblExp;
        fraction /= dblExp;
    } else {
    } else {
        fraction *= dblExp;
        fraction *= dblExp;
    }
    }
 
 
done:
done:
    if (endPtr != NULL) {
    if (endPtr != NULL) {
        *endPtr = (char *) p;
        *endPtr = (char *) p;
    }
    }
 
 
    if (sign) {
    if (sign) {
        return -fraction;
        return -fraction;
    }
    }
    return fraction;
    return fraction;
}
}
 
 

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.