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

Subversion Repositories or1k

[/] [or1k/] [trunk/] [insight/] [tcl/] [compat/] [strtod.c] - Blame information for rev 578

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 578 markom
/*
2
 * strtod.c --
3
 *
4
 *      Source code for the "strtod" library procedure.
5
 *
6
 * Copyright (c) 1988-1993 The Regents of the University of California.
7
 * Copyright (c) 1994 Sun Microsystems, Inc.
8
 *
9
 * See the file "license.terms" for information on usage and redistribution
10
 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
11
 *
12
 * RCS: @(#) $Id: strtod.c,v 1.1.1.1 2002-01-16 10:25:23 markom Exp $
13
 */
14
 
15
#include "tcl.h"
16
#ifdef NO_STDLIB_H
17
#   include "../compat/stdlib.h"
18
#else
19
#   include <stdlib.h>
20
#endif
21
#include <ctype.h>
22
 
23
#ifndef TRUE
24
#define TRUE 1
25
#define FALSE 0
26
#endif
27
#ifndef NULL
28
#define NULL 0
29
#endif
30
 
31
static int maxExponent = 511;   /* Largest possible base 10 exponent.  Any
32
                                 * exponent larger than this will already
33
                                 * produce underflow or overflow, so there's
34
                                 * no need to worry about additional digits.
35
                                 */
36
static double powersOf10[] = {  /* Table giving binary powers of 10.  Entry */
37
    10.,                        /* is 10^2^i.  Used to convert decimal */
38
    100.,                       /* exponents into floating-point numbers. */
39
    1.0e4,
40
    1.0e8,
41
    1.0e16,
42
    1.0e32,
43
    1.0e64,
44
    1.0e128,
45
    1.0e256
46
};
47
 
48
/*
49
 *----------------------------------------------------------------------
50
 *
51
 * strtod --
52
 *
53
 *      This procedure converts a floating-point number from an ASCII
54
 *      decimal representation to internal double-precision format.
55
 *
56
 * Results:
57
 *      The return value is the double-precision floating-point
58
 *      representation of the characters in string.  If endPtr isn't
59
 *      NULL, then *endPtr is filled in with the address of the
60
 *      next character after the last one that was part of the
61
 *      floating-point number.
62
 *
63
 * Side effects:
64
 *      None.
65
 *
66
 *----------------------------------------------------------------------
67
 */
68
 
69
double
70
strtod(string, endPtr)
71
    CONST char *string;         /* A decimal ASCII floating-point number,
72
                                 * optionally preceded by white space.
73
                                 * Must have form "-I.FE-X", where I is the
74
                                 * integer part of the mantissa, F is the
75
                                 * fractional part of the mantissa, and X
76
                                 * is the exponent.  Either of the signs
77
                                 * may be "+", "-", or omitted.  Either I
78
                                 * or F may be omitted, or both.  The decimal
79
                                 * point isn't necessary unless F is present.
80
                                 * The "E" may actually be an "e".  E and X
81
                                 * may both be omitted (but not just one).
82
                                 */
83
    char **endPtr;              /* If non-NULL, store terminating character's
84
                                 * address here. */
85
{
86
    int sign, expSign = FALSE;
87
    double fraction, dblExp, *d;
88
    register CONST char *p;
89
    register int c;
90
    int exp = 0;         /* Exponent read from "EX" field. */
91
    int fracExp = 0;             /* Exponent that derives from the fractional
92
                                 * part.  Under normal circumstatnces, it is
93
                                 * the negative of the number of digits in F.
94
                                 * However, if I is very long, the last digits
95
                                 * of I get dropped (otherwise a long I with a
96
                                 * large negative exponent could cause an
97
                                 * unnecessary overflow on I alone).  In this
98
                                 * case, fracExp is incremented one for each
99
                                 * dropped digit. */
100
    int mantSize;               /* Number of digits in mantissa. */
101
    int decPt;                  /* Number of mantissa digits BEFORE decimal
102
                                 * point. */
103
    CONST char *pExp;           /* Temporarily holds location of exponent
104
                                 * in string. */
105
 
106
    /*
107
     * Strip off leading blanks and check for a sign.
108
     */
109
 
110
    p = string;
111
    while (isspace(*p)) {
112
        p += 1;
113
    }
114
    if (*p == '-') {
115
        sign = TRUE;
116
        p += 1;
117
    } else {
118
        if (*p == '+') {
119
            p += 1;
120
        }
121
        sign = FALSE;
122
    }
123
 
124
    /*
125
     * Count the number of digits in the mantissa (including the decimal
126
     * point), and also locate the decimal point.
127
     */
128
 
129
    decPt = -1;
130
    for (mantSize = 0; ; mantSize += 1)
131
    {
132
        c = *p;
133
        if (!isdigit(c)) {
134
            if ((c != '.') || (decPt >= 0)) {
135
                break;
136
            }
137
            decPt = mantSize;
138
        }
139
        p += 1;
140
    }
141
 
142
    /*
143
     * Now suck up the digits in the mantissa.  Use two integers to
144
     * collect 9 digits each (this is faster than using floating-point).
145
     * If the mantissa has more than 18 digits, ignore the extras, since
146
     * they can't affect the value anyway.
147
     */
148
 
149
    pExp  = p;
150
    p -= mantSize;
151
    if (decPt < 0) {
152
        decPt = mantSize;
153
    } else {
154
        mantSize -= 1;                  /* One of the digits was the point. */
155
    }
156
    if (mantSize > 18) {
157
        fracExp = decPt - 18;
158
        mantSize = 18;
159
    } else {
160
        fracExp = decPt - mantSize;
161
    }
162
    if (mantSize == 0) {
163
        fraction = 0.0;
164
        p = string;
165
        goto done;
166
    } else {
167
        int frac1, frac2;
168
        frac1 = 0;
169
        for ( ; mantSize > 9; mantSize -= 1)
170
        {
171
            c = *p;
172
            p += 1;
173
            if (c == '.') {
174
                c = *p;
175
                p += 1;
176
            }
177
            frac1 = 10*frac1 + (c - '0');
178
        }
179
        frac2 = 0;
180
        for (; mantSize > 0; mantSize -= 1)
181
        {
182
            c = *p;
183
            p += 1;
184
            if (c == '.') {
185
                c = *p;
186
                p += 1;
187
            }
188
            frac2 = 10*frac2 + (c - '0');
189
        }
190
        fraction = (1.0e9 * frac1) + frac2;
191
    }
192
 
193
    /*
194
     * Skim off the exponent.
195
     */
196
 
197
    p = pExp;
198
    if ((*p == 'E') || (*p == 'e')) {
199
        p += 1;
200
        if (*p == '-') {
201
            expSign = TRUE;
202
            p += 1;
203
        } else {
204
            if (*p == '+') {
205
                p += 1;
206
            }
207
            expSign = FALSE;
208
        }
209
        while (isdigit(*p)) {
210
            exp = exp * 10 + (*p - '0');
211
            p += 1;
212
        }
213
    }
214
    if (expSign) {
215
        exp = fracExp - exp;
216
    } else {
217
        exp = fracExp + exp;
218
    }
219
 
220
    /*
221
     * Generate a floating-point number that represents the exponent.
222
     * Do this by processing the exponent one bit at a time to combine
223
     * many powers of 2 of 10. Then combine the exponent with the
224
     * fraction.
225
     */
226
 
227
    if (exp < 0) {
228
        expSign = TRUE;
229
        exp = -exp;
230
    } else {
231
        expSign = FALSE;
232
    }
233
    if (exp > maxExponent) {
234
        exp = maxExponent;
235
    }
236
    dblExp = 1.0;
237
    for (d = powersOf10; exp != 0; exp >>= 1, d += 1) {
238
        if (exp & 01) {
239
            dblExp *= *d;
240
        }
241
    }
242
    if (expSign) {
243
        fraction /= dblExp;
244
    } else {
245
        fraction *= dblExp;
246
    }
247
 
248
done:
249
    if (endPtr != NULL) {
250
        *endPtr = (char *) p;
251
    }
252
 
253
    if (sign) {
254
        return -fraction;
255
    }
256
    return fraction;
257
}

powered by: WebSVN 2.1.0

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