Adding upstream version 4.00~pre54+dfsg.
[syslinux-debian/hramrach.git] / com32 / lib / math / strtod.c
blobf99531ac61687eded354965cbf1c5a6b4b9a3bb0
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))
61 p++;
63 // Handle optional sign
64 negative = 0;
65 switch (*p) {
66 case '-':
67 negative = 1; // Fall through to increment position
68 case '+':
69 p++;
72 number = 0.;
73 exponent = 0;
74 num_digits = 0;
75 num_decimals = 0;
77 // Process string of digits
78 while (isdigit(*p)) {
79 number = number * 10. + (*p - '0');
80 p++;
81 num_digits++;
84 // Process decimal part
85 if (*p == '.') {
86 p++;
88 while (isdigit(*p)) {
89 number = number * 10. + (*p - '0');
90 p++;
91 num_digits++;
92 num_decimals++;
95 exponent -= num_decimals;
98 if (num_digits == 0) {
99 errno = ERANGE;
100 return 0.0;
102 // Correct for sign
103 if (negative)
104 number = -number;
106 // Process an exponent string
107 if (*p == 'e' || *p == 'E') {
108 // Handle optional sign
109 negative = 0;
110 switch (*++p) {
111 case '-':
112 negative = 1; // Fall through to increment pos
113 case '+':
114 p++;
117 // Process string of digits
118 n = 0;
119 while (isdigit(*p)) {
120 n = n * 10 + (*p - '0');
121 p++;
124 if (negative)
125 exponent -= n;
126 else
127 exponent += n;
130 if (exponent < __DBL_MIN_EXP__ || exponent > __DBL_MAX_EXP__) {
131 errno = ERANGE;
132 return Inf;
134 // Scale the result
135 p10 = 10.;
136 n = exponent;
137 if (n < 0)
138 n = -n;
139 while (n) {
140 if (n & 1) {
141 if (exponent < 0)
142 number /= p10;
143 else
144 number *= p10;
146 n >>= 1;
147 p10 *= p10;
150 if (!is_real(number))
151 errno = ERANGE;
152 if (endptr)
153 *endptr = p;
155 return number;