Adding upstream version 3.61.
[syslinux-debian/hramrach.git] / com32 / lib / math / strtod.c
blobf4e35ace6cef1c4b1c7e9ebb74ed17be343cfb10
1 /*
2 * strtod.c
4 * Convert string to double
6 * Copyright (C) 2002 Michael Ringgaard. All rights reserved.
7 * Copyright 2006-2008 H. Peter Anvin - All Rights Reserved
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
11 * are met:
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.
22 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
23 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
24 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
25 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
26 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
27 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
28 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
29 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
31 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
32 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
33 * OF THE POSSIBILITY OF SUCH DAMAGE.
36 #include <errno.h>
37 #include <ctype.h>
38 #include <stdlib.h>
39 #include <math.h>
41 static inline int is_real(double x)
43 const double Inf = 1.0/0.0;
44 return (x < Inf) && (x >= -Inf);
47 double strtod(const char *str, char **endptr)
49 double number;
50 int exponent;
51 int negative;
52 char *p = (char *) str;
53 double p10;
54 int n;
55 int num_digits;
56 int num_decimals;
57 const double Inf = 1.0/0.0;
59 // Skip leading whitespace
60 while (isspace(*p)) p++;
62 // Handle optional sign
63 negative = 0;
64 switch (*p)
66 case '-': negative = 1; // Fall through to increment position
67 case '+': p++;
70 number = 0.;
71 exponent = 0;
72 num_digits = 0;
73 num_decimals = 0;
75 // Process string of digits
76 while (isdigit(*p))
78 number = number * 10. + (*p - '0');
79 p++;
80 num_digits++;
83 // Process decimal part
84 if (*p == '.')
86 p++;
88 while (isdigit(*p))
90 number = number * 10. + (*p - '0');
91 p++;
92 num_digits++;
93 num_decimals++;
96 exponent -= num_decimals;
99 if (num_digits == 0)
101 errno = ERANGE;
102 return 0.0;
105 // Correct for sign
106 if (negative) number = -number;
108 // Process an exponent string
109 if (*p == 'e' || *p == 'E')
111 // Handle optional sign
112 negative = 0;
113 switch(*++p)
115 case '-': negative = 1; // Fall through to increment pos
116 case '+': p++;
119 // Process string of digits
120 n = 0;
121 while (isdigit(*p))
123 n = n * 10 + (*p - '0');
124 p++;
127 if (negative)
128 exponent -= n;
129 else
130 exponent += n;
133 if (exponent < __DBL_MIN_EXP__ ||
134 exponent > __DBL_MAX_EXP__)
136 errno = ERANGE;
137 return Inf;
140 // Scale the result
141 p10 = 10.;
142 n = exponent;
143 if (n < 0) n = -n;
144 while (n)
146 if (n & 1)
148 if (exponent < 0)
149 number /= p10;
150 else
151 number *= p10;
153 n >>= 1;
154 p10 *= p10;
157 if (!is_real(number)) errno = ERANGE;
158 if (endptr) *endptr = p;
160 return number;