Adding upstream version 3.30~pre4.
[syslinux-debian/hramrach.git] / com32 / lib / math / strtod.c
blobf0b500cbbbe41564d27d2dad6f3351a7860a39ba
1 //
2 // strtod.c
3 //
4 // Convert string to double
5 //
6 // Copyright (C) 2002 Michael Ringgaard. All rights reserved.
7 // Copyright (C) 2006 H. Peter Anvin.
8 //
9 // Redistribution and use in source and binary forms, with or without
10 // modification, are permitted provided that the following conditions
11 // are met:
12 //
13 // 1. Redistributions of source code must retain the above copyright
14 // notice, this list of conditions and the following disclaimer.
15 // 2. Redistributions in binary form must reproduce the above copyright
16 // notice, this list of conditions and the following disclaimer in the
17 // documentation and/or other materials provided with the distribution.
18 // 3. Neither the name of the project nor the names of its contributors
19 // may be used to endorse or promote products derived from this software
20 // without specific prior written permission.
21 //
22 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
23 // ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25 // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
26 // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27 // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28 // OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29 // HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30 // LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31 // OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32 // SUCH DAMAGE.
33 //
35 #include <errno.h>
36 #include <ctype.h>
37 #include <stdlib.h>
39 static inline int is_real(double x)
41 const double Inf = 1.0/0.0;
42 return (x < Inf) && (x >= -Inf);
45 double strtod(const char *str, char **endptr)
47 double number;
48 int exponent;
49 int negative;
50 char *p = (char *) str;
51 double p10;
52 int n;
53 int num_digits;
54 int num_decimals;
55 const double Inf = 1.0/0.0;
57 // Skip leading whitespace
58 while (isspace(*p)) p++;
60 // Handle optional sign
61 negative = 0;
62 switch (*p)
64 case '-': negative = 1; // Fall through to increment position
65 case '+': p++;
68 number = 0.;
69 exponent = 0;
70 num_digits = 0;
71 num_decimals = 0;
73 // Process string of digits
74 while (isdigit(*p))
76 number = number * 10. + (*p - '0');
77 p++;
78 num_digits++;
81 // Process decimal part
82 if (*p == '.')
84 p++;
86 while (isdigit(*p))
88 number = number * 10. + (*p - '0');
89 p++;
90 num_digits++;
91 num_decimals++;
94 exponent -= num_decimals;
97 if (num_digits == 0)
99 errno = ERANGE;
100 return 0.0;
103 // Correct for sign
104 if (negative) number = -number;
106 // Process an exponent string
107 if (*p == 'e' || *p == 'E')
109 // Handle optional sign
110 negative = 0;
111 switch(*++p)
113 case '-': negative = 1; // Fall through to increment pos
114 case '+': p++;
117 // Process string of digits
118 n = 0;
119 while (isdigit(*p))
121 n = n * 10 + (*p - '0');
122 p++;
125 if (negative)
126 exponent -= n;
127 else
128 exponent += n;
131 if (exponent < __DBL_MIN_EXP__ ||
132 exponent > __DBL_MAX_EXP__)
134 errno = ERANGE;
135 return Inf;
138 // Scale the result
139 p10 = 10.;
140 n = exponent;
141 if (n < 0) n = -n;
142 while (n)
144 if (n & 1)
146 if (exponent < 0)
147 number /= p10;
148 else
149 number *= p10;
151 n >>= 1;
152 p10 *= p10;
155 if (!is_real(number)) errno = ERANGE;
156 if (endptr) *endptr = p;
158 return number;