OLD | NEW |
1 #include <stdint.h> | 1 #include <stdint.h> |
2 #include <stdio.h> | 2 #include <stdio.h> |
3 #include <math.h> | 3 #include <math.h> |
4 #include <float.h> | 4 #include <float.h> |
5 #include <limits.h> | 5 #include <limits.h> |
6 #include <errno.h> | 6 #include <errno.h> |
7 #include <ctype.h> | 7 #include <ctype.h> |
8 | 8 |
9 #include "shgetc.h" | 9 #include "shgetc.h" |
10 #include "floatscan.h" | 10 #include "floatscan.h" |
(...skipping 13 matching lines...) Expand all Loading... |
24 #elif LDBL_MANT_DIG == 113 && LDBL_MAX_EXP == 16384 | 24 #elif LDBL_MANT_DIG == 113 && LDBL_MAX_EXP == 16384 |
25 | 25 |
26 #define LD_B1B_DIG 4 | 26 #define LD_B1B_DIG 4 |
27 #define LD_B1B_MAX 10384593, 717069655, 257060992, 658440191 | 27 #define LD_B1B_MAX 10384593, 717069655, 257060992, 658440191 |
28 #define KMAX 2048 | 28 #define KMAX 2048 |
29 | 29 |
30 #else | 30 #else |
31 #error Unsupported long double representation | 31 #error Unsupported long double representation |
32 #endif | 32 #endif |
33 | 33 |
34 #define MASK (KMAX-1) | 34 #define MASK (KMAX - 1) |
35 | 35 |
36 #define CONCAT2(x,y) x ## y | 36 #define CONCAT2(x, y) x##y |
37 #define CONCAT(x,y) CONCAT2(x,y) | 37 #define CONCAT(x, y) CONCAT2(x, y) |
38 | 38 |
39 static long long scanexp(FILE *f, int pok) | 39 static long long scanexp(FILE* f, int pok) { |
40 { | 40 int c; |
41 » int c; | 41 int x; |
42 » int x; | 42 long long y; |
43 » long long y; | 43 int neg = 0; |
44 » int neg = 0; | 44 |
45 » | 45 c = shgetc(f); |
46 » c = shgetc(f); | 46 if (c == '+' || c == '-') { |
47 » if (c=='+' || c=='-') { | 47 neg = (c == '-'); |
48 » » neg = (c=='-'); | 48 c = shgetc(f); |
49 » » c = shgetc(f); | 49 if (c - '0' >= 10U && pok) |
50 » » if (c-'0'>=10U && pok) shunget(f); | 50 shunget(f); |
51 » } | 51 } |
52 » if (c-'0'>=10U) { | 52 if (c - '0' >= 10U) { |
53 » » shunget(f); | 53 shunget(f); |
54 » » return LLONG_MIN; | 54 return LLONG_MIN; |
55 » } | 55 } |
56 » for (x=0; c-'0'<10U && x<INT_MAX/10; c = shgetc(f)) | 56 for (x = 0; c - '0' < 10U && x < INT_MAX / 10; c = shgetc(f)) |
57 » » x = 10*x + c-'0'; | 57 x = 10 * x + c - '0'; |
58 » for (y=x; c-'0'<10U && y<LLONG_MAX/100; c = shgetc(f)) | 58 for (y = x; c - '0' < 10U && y < LLONG_MAX / 100; c = shgetc(f)) |
59 » » y = 10*y + c-'0'; | 59 y = 10 * y + c - '0'; |
60 » for (; c-'0'<10U; c = shgetc(f)); | 60 for (; c - '0' < 10U; c = shgetc(f)) |
61 » shunget(f); | 61 ; |
62 » return neg ? -y : y; | 62 shunget(f); |
| 63 return neg ? -y : y; |
63 } | 64 } |
64 | 65 |
65 | 66 static long double decfloat(FILE* f, |
66 static long double decfloat(FILE *f, int c, int bits, int emin, int sign, int po
k) | 67 int c, |
67 { | 68 int bits, |
68 uint32_t x[KMAX]; | 69 int emin, |
69 static const uint32_t th[] = { LD_B1B_MAX }; | 70 int sign, |
70 int i, j, k, a, z; | 71 int pok) { |
71 long long lrp=0, dc=0; | 72 uint32_t x[KMAX]; |
72 long long e10=0; | 73 static const uint32_t th[] = {LD_B1B_MAX}; |
73 int lnz = 0; | 74 int i, j, k, a, z; |
74 int gotdig = 0, gotrad = 0; | 75 long long lrp = 0, dc = 0; |
75 int rp; | 76 long long e10 = 0; |
76 int e2; | 77 int lnz = 0; |
77 int emax = -emin-bits+3; | 78 int gotdig = 0, gotrad = 0; |
78 int denormal = 0; | 79 int rp; |
79 long double y; | 80 int e2; |
80 long double frac=0; | 81 int emax = -emin - bits + 3; |
81 long double bias=0; | 82 int denormal = 0; |
82 static const int p10s[] = { 10, 100, 1000, 10000, | 83 long double y; |
83 100000, 1000000, 10000000, 100000000 }; | 84 long double frac = 0; |
84 | 85 long double bias = 0; |
85 j=0; | 86 static const int p10s[] = {10, 100, 1000, 10000, |
86 k=0; | 87 100000, 1000000, 10000000, 100000000}; |
87 | 88 |
88 /* Don't let leading zeros consume buffer space */ | 89 j = 0; |
89 for (; c=='0'; c = shgetc(f)) gotdig=1; | 90 k = 0; |
90 if (c=='.') { | 91 |
91 gotrad = 1; | 92 /* Don't let leading zeros consume buffer space */ |
92 for (c = shgetc(f); c=='0'; c = shgetc(f)) gotdig=1, lrp--; | 93 for (; c == '0'; c = shgetc(f)) |
93 } | 94 gotdig = 1; |
94 | 95 if (c == '.') { |
95 x[0] = 0; | 96 gotrad = 1; |
96 for (; c-'0'<10U || c=='.'; c = shgetc(f)) { | 97 for (c = shgetc(f); c == '0'; c = shgetc(f)) |
97 if (c == '.') { | 98 gotdig = 1, lrp--; |
98 if (gotrad) break; | 99 } |
99 gotrad = 1; | 100 |
100 lrp = dc; | 101 x[0] = 0; |
101 } else if (k < KMAX-3) { | 102 for (; c - '0' < 10U || c == '.'; c = shgetc(f)) { |
102 dc++; | 103 if (c == '.') { |
103 if (c!='0') lnz = dc; | 104 if (gotrad) |
104 if (j) x[k] = x[k]*10 + c-'0'; | 105 break; |
105 else x[k] = c-'0'; | 106 gotrad = 1; |
106 if (++j==9) { | 107 lrp = dc; |
107 k++; | 108 } else if (k < KMAX - 3) { |
108 j=0; | 109 dc++; |
109 } | 110 if (c != '0') |
110 gotdig=1; | 111 lnz = dc; |
111 } else { | 112 if (j) |
112 dc++; | 113 x[k] = x[k] * 10 + c - '0'; |
113 if (c!='0') x[KMAX-4] |= 1; | 114 else |
114 } | 115 x[k] = c - '0'; |
115 } | 116 if (++j == 9) { |
116 if (!gotrad) lrp=dc; | 117 k++; |
117 | 118 j = 0; |
118 if (gotdig && (c|32)=='e') { | 119 } |
119 e10 = scanexp(f, pok); | 120 gotdig = 1; |
120 if (e10 == LLONG_MIN) { | 121 } else { |
121 if (pok) { | 122 dc++; |
122 shunget(f); | 123 if (c != '0') |
123 } else { | 124 x[KMAX - 4] |= 1; |
124 shlim(f, 0); | 125 } |
125 return 0; | 126 } |
126 } | 127 if (!gotrad) |
127 e10 = 0; | 128 lrp = dc; |
128 } | 129 |
129 lrp += e10; | 130 if (gotdig && (c | 32) == 'e') { |
130 } else if (c>=0) { | 131 e10 = scanexp(f, pok); |
131 shunget(f); | 132 if (e10 == LLONG_MIN) { |
132 } | 133 if (pok) { |
133 if (!gotdig) { | 134 shunget(f); |
134 errno = EINVAL; | 135 } else { |
135 shlim(f, 0); | 136 shlim(f, 0); |
136 return 0; | 137 return 0; |
137 } | 138 } |
138 | 139 e10 = 0; |
139 /* Handle zero specially to avoid nasty special cases later */ | 140 } |
140 if (!x[0]) return sign * 0.0; | 141 lrp += e10; |
141 | 142 } else if (c >= 0) { |
142 /* Optimize small integers (w/no exponent) and over/under-flow */ | 143 shunget(f); |
143 if (lrp==dc && dc<10 && (bits>30 || x[0]>>bits==0)) | 144 } |
144 return sign * (long double)x[0]; | 145 if (!gotdig) { |
145 if (lrp > -emin/2) { | 146 errno = EINVAL; |
146 errno = ERANGE; | 147 shlim(f, 0); |
147 return sign * LDBL_MAX * LDBL_MAX; | 148 return 0; |
148 } | 149 } |
149 if (lrp < emin-2*LDBL_MANT_DIG) { | 150 |
150 errno = ERANGE; | 151 /* Handle zero specially to avoid nasty special cases later */ |
151 return sign * LDBL_MIN * LDBL_MIN; | 152 if (!x[0]) |
152 } | 153 return sign * 0.0; |
153 | 154 |
154 /* Align incomplete final B1B digit */ | 155 /* Optimize small integers (w/no exponent) and over/under-flow */ |
155 if (j) { | 156 if (lrp == dc && dc < 10 && (bits > 30 || x[0] >> bits == 0)) |
156 for (; j<9; j++) x[k]*=10; | 157 return sign * (long double)x[0]; |
157 k++; | 158 if (lrp > -emin / 2) { |
158 j=0; | 159 errno = ERANGE; |
159 } | 160 return sign * LDBL_MAX * LDBL_MAX; |
160 | 161 } |
161 a = 0; | 162 if (lrp < emin - 2 * LDBL_MANT_DIG) { |
162 z = k; | 163 errno = ERANGE; |
163 e2 = 0; | 164 return sign * LDBL_MIN * LDBL_MIN; |
164 rp = lrp; | 165 } |
165 | 166 |
166 /* Optimize small to mid-size integers (even in exp. notation) */ | 167 /* Align incomplete final B1B digit */ |
167 if (lnz<9 && lnz<=rp && rp < 18) { | 168 if (j) { |
168 if (rp == 9) return sign * (long double)x[0]; | 169 for (; j < 9; j++) |
169 if (rp < 9) return sign * (long double)x[0] / p10s[8-rp]; | 170 x[k] *= 10; |
170 int bitlim = bits-3*(int)(rp-9); | 171 k++; |
171 if (bitlim>30 || x[0]>>bitlim==0) | 172 j = 0; |
172 return sign * (long double)x[0] * p10s[rp-10]; | 173 } |
173 } | 174 |
174 | 175 a = 0; |
175 /* Align radix point to B1B digit boundary */ | 176 z = k; |
176 if (rp % 9) { | 177 e2 = 0; |
177 int rpm9 = rp>=0 ? rp%9 : rp%9+9; | 178 rp = lrp; |
178 int p10 = p10s[8-rpm9]; | 179 |
179 uint32_t carry = 0; | 180 /* Optimize small to mid-size integers (even in exp. notation) */ |
180 for (k=a; k!=z; k++) { | 181 if (lnz < 9 && lnz <= rp && rp < 18) { |
181 uint32_t tmp = x[k] % p10; | 182 if (rp == 9) |
182 x[k] = x[k]/p10 + carry; | 183 return sign * (long double)x[0]; |
183 carry = 1000000000/p10 * tmp; | 184 if (rp < 9) |
184 if (k==a && !x[k]) { | 185 return sign * (long double)x[0] / p10s[8 - rp]; |
185 a = (a+1 & MASK); | 186 int bitlim = bits - 3 * (int)(rp - 9); |
186 rp -= 9; | 187 if (bitlim > 30 || x[0] >> bitlim == 0) |
187 } | 188 return sign * (long double)x[0] * p10s[rp - 10]; |
188 } | 189 } |
189 if (carry) x[z++] = carry; | 190 |
190 rp += 9-rpm9; | 191 /* Align radix point to B1B digit boundary */ |
191 } | 192 if (rp % 9) { |
192 | 193 int rpm9 = rp >= 0 ? rp % 9 : rp % 9 + 9; |
193 /* Upscale until desired number of bits are left of radix point */ | 194 int p10 = p10s[8 - rpm9]; |
194 while (rp < 9*LD_B1B_DIG || (rp == 9*LD_B1B_DIG && x[a]<th[0])) { | 195 uint32_t carry = 0; |
195 uint32_t carry = 0; | 196 for (k = a; k != z; k++) { |
196 e2 -= 29; | 197 uint32_t tmp = x[k] % p10; |
197 for (k=(z-1 & MASK); ; k=(k-1 & MASK)) { | 198 x[k] = x[k] / p10 + carry; |
198 uint64_t tmp = ((uint64_t)x[k] << 29) + carry; | 199 carry = 1000000000 / p10 * tmp; |
199 if (tmp > 1000000000) { | 200 if (k == a && !x[k]) { |
200 carry = tmp / 1000000000; | 201 a = (a + 1 & MASK); |
201 x[k] = tmp % 1000000000; | 202 rp -= 9; |
202 } else { | 203 } |
203 carry = 0; | 204 } |
204 x[k] = tmp; | 205 if (carry) |
205 } | 206 x[z++] = carry; |
206 if (k==(z-1 & MASK) && k!=a && !x[k]) z = k; | 207 rp += 9 - rpm9; |
207 if (k==a) break; | 208 } |
208 } | 209 |
209 if (carry) { | 210 /* Upscale until desired number of bits are left of radix point */ |
210 rp += 9; | 211 while (rp < 9 * LD_B1B_DIG || (rp == 9 * LD_B1B_DIG && x[a] < th[0])) { |
211 a = (a-1 & MASK); | 212 uint32_t carry = 0; |
212 if (a == z) { | 213 e2 -= 29; |
213 z = (z-1 & MASK); | 214 for (k = (z - 1 & MASK);; k = (k - 1 & MASK)) { |
214 x[z-1 & MASK] |= x[z]; | 215 uint64_t tmp = ((uint64_t)x[k] << 29) + carry; |
215 } | 216 if (tmp > 1000000000) { |
216 x[a] = carry; | 217 carry = tmp / 1000000000; |
217 } | 218 x[k] = tmp % 1000000000; |
218 } | 219 } else { |
219 | 220 carry = 0; |
220 /* Downscale until exactly number of bits are left of radix point */ | 221 x[k] = tmp; |
221 for (;;) { | 222 } |
222 uint32_t carry = 0; | 223 if (k == (z - 1 & MASK) && k != a && !x[k]) |
223 int sh = 1; | 224 z = k; |
224 for (i=0; i<LD_B1B_DIG; i++) { | 225 if (k == a) |
225 k = (a+i & MASK); | 226 break; |
226 if (k == z || x[k] < th[i]) { | 227 } |
227 i=LD_B1B_DIG; | 228 if (carry) { |
228 break; | 229 rp += 9; |
229 } | 230 a = (a - 1 & MASK); |
230 if (x[a+i & MASK] > th[i]) break; | 231 if (a == z) { |
231 } | 232 z = (z - 1 & MASK); |
232 if (i==LD_B1B_DIG && rp==9*LD_B1B_DIG) break; | 233 x[z - 1 & MASK] |= x[z]; |
233 /* FIXME: find a way to compute optimal sh */ | 234 } |
234 if (rp > 9+9*LD_B1B_DIG) sh = 9; | 235 x[a] = carry; |
235 e2 += sh; | 236 } |
236 for (k=a; k!=z; k=(k+1 & MASK)) { | 237 } |
237 uint32_t tmp = x[k] & (1<<sh)-1; | 238 |
238 x[k] = (x[k]>>sh) + carry; | 239 /* Downscale until exactly number of bits are left of radix point */ |
239 carry = (1000000000>>sh) * tmp; | 240 for (;;) { |
240 if (k==a && !x[k]) { | 241 uint32_t carry = 0; |
241 a = (a+1 & MASK); | 242 int sh = 1; |
242 i--; | 243 for (i = 0; i < LD_B1B_DIG; i++) { |
243 rp -= 9; | 244 k = (a + i & MASK); |
244 } | 245 if (k == z || x[k] < th[i]) { |
245 } | 246 i = LD_B1B_DIG; |
246 if (carry) { | 247 break; |
247 if ((z+1 & MASK) != a) { | 248 } |
248 x[z] = carry; | 249 if (x[a + i & MASK] > th[i]) |
249 z = (z+1 & MASK); | 250 break; |
250 } else x[z-1 & MASK] |= 1; | 251 } |
251 } | 252 if (i == LD_B1B_DIG && rp == 9 * LD_B1B_DIG) |
252 } | 253 break; |
253 | 254 /* FIXME: find a way to compute optimal sh */ |
254 /* Assemble desired bits into floating point variable */ | 255 if (rp > 9 + 9 * LD_B1B_DIG) |
255 for (y=i=0; i<LD_B1B_DIG; i++) { | 256 sh = 9; |
256 if ((a+i & MASK)==z) x[(z=(z+1 & MASK))-1] = 0; | 257 e2 += sh; |
257 y = 1000000000.0L * y + x[a+i & MASK]; | 258 for (k = a; k != z; k = (k + 1 & MASK)) { |
258 } | 259 uint32_t tmp = x[k] & (1 << sh) - 1; |
259 | 260 x[k] = (x[k] >> sh) + carry; |
260 y *= sign; | 261 carry = (1000000000 >> sh) * tmp; |
261 | 262 if (k == a && !x[k]) { |
262 /* Limit precision for denormal results */ | 263 a = (a + 1 & MASK); |
263 if (bits > LDBL_MANT_DIG+e2-emin) { | 264 i--; |
264 bits = LDBL_MANT_DIG+e2-emin; | 265 rp -= 9; |
265 if (bits<0) bits=0; | 266 } |
266 denormal = 1; | 267 } |
267 } | 268 if (carry) { |
268 | 269 if ((z + 1 & MASK) != a) { |
269 /* Calculate bias term to force rounding, move out lower bits */ | 270 x[z] = carry; |
270 if (bits < LDBL_MANT_DIG) { | 271 z = (z + 1 & MASK); |
271 bias = copysignl(scalbn(1, 2*LDBL_MANT_DIG-bits-1), y); | 272 } else |
272 frac = fmodl(y, scalbn(1, LDBL_MANT_DIG-bits)); | 273 x[z - 1 & MASK] |= 1; |
273 y -= frac; | 274 } |
274 y += bias; | 275 } |
275 } | 276 |
276 | 277 /* Assemble desired bits into floating point variable */ |
277 /* Process tail of decimal input so it can affect rounding */ | 278 for (y = i = 0; i < LD_B1B_DIG; i++) { |
278 if ((a+i & MASK) != z) { | 279 if ((a + i & MASK) == z) |
279 uint32_t t = x[a+i & MASK]; | 280 x[(z = (z + 1 & MASK)) - 1] = 0; |
280 if (t < 500000000 && (t || (a+i+1 & MASK) != z)) | 281 y = 1000000000.0L * y + x[a + i & MASK]; |
281 frac += 0.25*sign; | 282 } |
282 else if (t > 500000000) | 283 |
283 frac += 0.75*sign; | 284 y *= sign; |
284 else if (t == 500000000) { | 285 |
285 if ((a+i+1 & MASK) == z) | 286 /* Limit precision for denormal results */ |
286 frac += 0.5*sign; | 287 if (bits > LDBL_MANT_DIG + e2 - emin) { |
287 else | 288 bits = LDBL_MANT_DIG + e2 - emin; |
288 frac += 0.75*sign; | 289 if (bits < 0) |
289 } | 290 bits = 0; |
290 if (LDBL_MANT_DIG-bits >= 2 && !fmodl(frac, 1)) | 291 denormal = 1; |
291 frac++; | 292 } |
292 } | 293 |
293 | 294 /* Calculate bias term to force rounding, move out lower bits */ |
294 y += frac; | 295 if (bits < LDBL_MANT_DIG) { |
295 y -= bias; | 296 bias = copysignl(scalbn(1, 2 * LDBL_MANT_DIG - bits - 1), y); |
296 | 297 frac = fmodl(y, scalbn(1, LDBL_MANT_DIG - bits)); |
297 if ((e2+LDBL_MANT_DIG & INT_MAX) > emax-5) { | 298 y -= frac; |
298 if (fabs(y) >= CONCAT(0x1p, LDBL_MANT_DIG)) { | 299 y += bias; |
299 if (denormal && bits==LDBL_MANT_DIG+e2-emin) | 300 } |
300 denormal = 0; | 301 |
301 y *= 0.5; | 302 /* Process tail of decimal input so it can affect rounding */ |
302 e2++; | 303 if ((a + i & MASK) != z) { |
303 } | 304 uint32_t t = x[a + i & MASK]; |
304 if (e2+LDBL_MANT_DIG>emax || (denormal && frac)) | 305 if (t < 500000000 && (t || (a + i + 1 & MASK) != z)) |
305 errno = ERANGE; | 306 frac += 0.25 * sign; |
306 } | 307 else if (t > 500000000) |
307 | 308 frac += 0.75 * sign; |
308 return scalbnl(y, e2); | 309 else if (t == 500000000) { |
| 310 if ((a + i + 1 & MASK) == z) |
| 311 frac += 0.5 * sign; |
| 312 else |
| 313 frac += 0.75 * sign; |
| 314 } |
| 315 if (LDBL_MANT_DIG - bits >= 2 && !fmodl(frac, 1)) |
| 316 frac++; |
| 317 } |
| 318 |
| 319 y += frac; |
| 320 y -= bias; |
| 321 |
| 322 if ((e2 + LDBL_MANT_DIG & INT_MAX) > emax - 5) { |
| 323 if (fabs(y) >= CONCAT(0x1p, LDBL_MANT_DIG)) { |
| 324 if (denormal && bits == LDBL_MANT_DIG + e2 - emin) |
| 325 denormal = 0; |
| 326 y *= 0.5; |
| 327 e2++; |
| 328 } |
| 329 if (e2 + LDBL_MANT_DIG > emax || (denormal && frac)) |
| 330 errno = ERANGE; |
| 331 } |
| 332 |
| 333 return scalbnl(y, e2); |
309 } | 334 } |
310 | 335 |
311 static long double hexfloat(FILE *f, int bits, int emin, int sign, int pok) | 336 static long double hexfloat(FILE* f, int bits, int emin, int sign, int pok) { |
312 { | 337 uint32_t x = 0; |
313 » uint32_t x = 0; | 338 long double y = 0; |
314 » long double y = 0; | 339 long double scale = 1; |
315 » long double scale = 1; | 340 long double bias = 0; |
316 » long double bias = 0; | 341 int gottail = 0, gotrad = 0, gotdig = 0; |
317 » int gottail = 0, gotrad = 0, gotdig = 0; | 342 long long rp = 0; |
318 » long long rp = 0; | 343 long long dc = 0; |
319 » long long dc = 0; | 344 long long e2 = 0; |
320 » long long e2 = 0; | 345 int d; |
321 » int d; | 346 int c; |
322 » int c; | 347 |
323 | 348 c = shgetc(f); |
324 » c = shgetc(f); | 349 |
325 | 350 /* Skip leading zeros */ |
326 » /* Skip leading zeros */ | 351 for (; c == '0'; c = shgetc(f)) |
327 » for (; c=='0'; c = shgetc(f)) gotdig = 1; | 352 gotdig = 1; |
328 | 353 |
329 » if (c=='.') { | 354 if (c == '.') { |
330 » » gotrad = 1; | 355 gotrad = 1; |
331 » » c = shgetc(f); | 356 c = shgetc(f); |
332 » » /* Count zeros after the radix point before significand */ | 357 /* Count zeros after the radix point before significand */ |
333 » » for (rp=0; c=='0'; c = shgetc(f), rp--) gotdig = 1; | 358 for (rp = 0; c == '0'; c = shgetc(f), rp--) |
334 » } | 359 gotdig = 1; |
335 | 360 } |
336 » for (; c-'0'<10U || (c|32)-'a'<6U || c=='.'; c = shgetc(f)) { | 361 |
337 » » if (c=='.') { | 362 for (; c - '0' < 10U || (c | 32) - 'a' < 6U || c == '.'; c = shgetc(f)) { |
338 » » » if (gotrad) break; | 363 if (c == '.') { |
339 » » » rp = dc; | 364 if (gotrad) |
340 » » » gotrad = 1; | 365 break; |
341 » » } else { | 366 rp = dc; |
342 » » » gotdig = 1; | 367 gotrad = 1; |
343 » » » if (c > '9') d = (c|32)+10-'a'; | 368 } else { |
344 » » » else d = c-'0'; | 369 gotdig = 1; |
345 » » » if (dc<8) { | 370 if (c > '9') |
346 » » » » x = x*16 + d; | 371 d = (c | 32) + 10 - 'a'; |
347 » » » } else if (dc < LDBL_MANT_DIG/4+1) { | 372 else |
348 » » » » y += d*(scale/=16); | 373 d = c - '0'; |
349 » » » } else if (d && !gottail) { | 374 if (dc < 8) { |
350 » » » » y += 0.5*scale; | 375 x = x * 16 + d; |
351 » » » » gottail = 1; | 376 } else if (dc < LDBL_MANT_DIG / 4 + 1) { |
352 » » » } | 377 y += d * (scale /= 16); |
353 » » » dc++; | 378 } else if (d && !gottail) { |
354 » » } | 379 y += 0.5 * scale; |
355 » } | 380 gottail = 1; |
356 » if (!gotdig) { | 381 } |
357 » » shunget(f); | 382 dc++; |
358 » » if (pok) { | 383 } |
359 » » » shunget(f); | 384 } |
360 » » » if (gotrad) shunget(f); | 385 if (!gotdig) { |
361 » » } else { | 386 shunget(f); |
362 » » » shlim(f, 0); | 387 if (pok) { |
363 » » } | 388 shunget(f); |
364 » » return sign * 0.0; | 389 if (gotrad) |
365 » } | 390 shunget(f); |
366 » if (!gotrad) rp = dc; | 391 } else { |
367 » while (dc<8) x *= 16, dc++; | 392 shlim(f, 0); |
368 » if ((c|32)=='p') { | 393 } |
369 » » e2 = scanexp(f, pok); | 394 return sign * 0.0; |
370 » » if (e2 == LLONG_MIN) { | 395 } |
371 » » » if (pok) { | 396 if (!gotrad) |
372 » » » » shunget(f); | 397 rp = dc; |
373 » » » } else { | 398 while (dc < 8) |
374 » » » » shlim(f, 0); | 399 x *= 16, dc++; |
375 » » » » return 0; | 400 if ((c | 32) == 'p') { |
376 » » » } | 401 e2 = scanexp(f, pok); |
377 » » » e2 = 0; | 402 if (e2 == LLONG_MIN) { |
378 » » } | 403 if (pok) { |
379 » } else { | 404 shunget(f); |
380 » » shunget(f); | 405 } else { |
381 » } | 406 shlim(f, 0); |
382 » e2 += 4*rp - 32; | 407 return 0; |
383 | 408 } |
384 » if (!x) return sign * 0.0; | 409 e2 = 0; |
385 » if (e2 > -emin) { | 410 } |
386 » » errno = ERANGE; | 411 } else { |
387 » » return sign * LDBL_MAX * LDBL_MAX; | 412 shunget(f); |
388 » } | 413 } |
389 » if (e2 < emin-2*LDBL_MANT_DIG) { | 414 e2 += 4 * rp - 32; |
390 » » errno = ERANGE; | 415 |
391 » » return sign * LDBL_MIN * LDBL_MIN; | 416 if (!x) |
392 » } | 417 return sign * 0.0; |
393 | 418 if (e2 > -emin) { |
394 » while (x < 0x80000000) { | 419 errno = ERANGE; |
395 » » if (y>=0.5) { | 420 return sign * LDBL_MAX * LDBL_MAX; |
396 » » » x += x + 1; | 421 } |
397 » » » y += y - 1; | 422 if (e2 < emin - 2 * LDBL_MANT_DIG) { |
398 » » } else { | 423 errno = ERANGE; |
399 » » » x += x; | 424 return sign * LDBL_MIN * LDBL_MIN; |
400 » » » y += y; | 425 } |
401 » » } | 426 |
402 » » e2--; | 427 while (x < 0x80000000) { |
403 » } | 428 if (y >= 0.5) { |
404 | 429 x += x + 1; |
405 » if (bits > 32+e2-emin) { | 430 y += y - 1; |
406 » » bits = 32+e2-emin; | 431 } else { |
407 » » if (bits<0) bits=0; | 432 x += x; |
408 » } | 433 y += y; |
409 | 434 } |
410 » if (bits < LDBL_MANT_DIG) | 435 e2--; |
411 » » bias = copysignl(scalbn(1, 32+LDBL_MANT_DIG-bits-1), sign); | 436 } |
412 | 437 |
413 » if (bits<32 && y && !(x&1)) x++, y=0; | 438 if (bits > 32 + e2 - emin) { |
414 | 439 bits = 32 + e2 - emin; |
415 » y = bias + sign*(long double)x + sign*y; | 440 if (bits < 0) |
416 » y -= bias; | 441 bits = 0; |
417 | 442 } |
418 » if (!y) errno = ERANGE; | 443 |
419 | 444 if (bits < LDBL_MANT_DIG) |
420 » return scalbnl(y, e2); | 445 bias = copysignl(scalbn(1, 32 + LDBL_MANT_DIG - bits - 1), sign); |
| 446 |
| 447 if (bits < 32 && y && !(x & 1)) |
| 448 x++, y = 0; |
| 449 |
| 450 y = bias + sign * (long double)x + sign * y; |
| 451 y -= bias; |
| 452 |
| 453 if (!y) |
| 454 errno = ERANGE; |
| 455 |
| 456 return scalbnl(y, e2); |
421 } | 457 } |
422 | 458 |
423 long double __floatscan(FILE *f, int prec, int pok) | 459 long double __floatscan(FILE* f, int prec, int pok) { |
424 { | 460 int sign = 1; |
425 » int sign = 1; | 461 size_t i; |
426 » size_t i; | 462 int bits; |
427 » int bits; | 463 int emin; |
428 » int emin; | 464 int c; |
429 » int c; | 465 |
430 | 466 switch (prec) { |
431 » switch (prec) { | 467 case 0: |
432 » case 0: | 468 bits = FLT_MANT_DIG; |
433 » » bits = FLT_MANT_DIG; | 469 emin = FLT_MIN_EXP - bits; |
434 » » emin = FLT_MIN_EXP-bits; | 470 break; |
435 » » break; | 471 case 1: |
436 » case 1: | 472 bits = DBL_MANT_DIG; |
437 » » bits = DBL_MANT_DIG; | 473 emin = DBL_MIN_EXP - bits; |
438 » » emin = DBL_MIN_EXP-bits; | 474 break; |
439 » » break; | 475 case 2: |
440 » case 2: | 476 bits = LDBL_MANT_DIG; |
441 » » bits = LDBL_MANT_DIG; | 477 emin = LDBL_MIN_EXP - bits; |
442 » » emin = LDBL_MIN_EXP-bits; | 478 break; |
443 » » break; | 479 default: |
444 » default: | 480 return 0; |
445 » » return 0; | 481 } |
446 » } | 482 |
447 | 483 while (isspace((c = shgetc(f)))) |
448 » while (isspace((c=shgetc(f)))); | 484 ; |
449 | 485 |
450 » if (c=='+' || c=='-') { | 486 if (c == '+' || c == '-') { |
451 » » sign -= 2*(c=='-'); | 487 sign -= 2 * (c == '-'); |
452 » » c = shgetc(f); | 488 c = shgetc(f); |
453 » } | 489 } |
454 | 490 |
455 » for (i=0; i<8 && (c|32)=="infinity"[i]; i++) | 491 for (i = 0; i < 8 && (c | 32) == "infinity"[i]; i++) |
456 » » if (i<7) c = shgetc(f); | 492 if (i < 7) |
457 » if (i==3 || i==8 || (i>3 && pok)) { | 493 c = shgetc(f); |
458 » » if (i!=8) { | 494 if (i == 3 || i == 8 || (i > 3 && pok)) { |
459 » » » shunget(f); | 495 if (i != 8) { |
460 » » » if (pok) for (; i>3; i--) shunget(f); | 496 shunget(f); |
461 » » } | 497 if (pok) |
462 » » return sign * INFINITY; | 498 for (; i > 3; i--) |
463 » } | 499 shunget(f); |
464 » if (!i) for (i=0; i<3 && (c|32)=="nan"[i]; i++) | 500 } |
465 » » if (i<2) c = shgetc(f); | 501 return sign * INFINITY; |
466 » if (i==3) { | 502 } |
467 » » if (shgetc(f) != '(') { | 503 if (!i) |
468 » » » shunget(f); | 504 for (i = 0; i < 3 && (c | 32) == "nan"[i]; i++) |
469 » » » return NAN; | 505 if (i < 2) |
470 » » } | 506 c = shgetc(f); |
471 » » for (i=1; ; i++) { | 507 if (i == 3) { |
472 » » » c = shgetc(f); | 508 if (shgetc(f) != '(') { |
473 » » » if (c-'0'<10U || c-'A'<26U || c-'a'<26U || c=='_') | 509 shunget(f); |
474 » » » » continue; | 510 return NAN; |
475 » » » if (c==')') return NAN; | 511 } |
476 » » » shunget(f); | 512 for (i = 1;; i++) { |
477 » » » if (!pok) { | 513 c = shgetc(f); |
478 » » » » errno = EINVAL; | 514 if (c - '0' < 10U || c - 'A' < 26U || c - 'a' < 26U || c == '_') |
479 » » » » shlim(f, 0); | 515 continue; |
480 » » » » return 0; | 516 if (c == ')') |
481 » » » } | 517 return NAN; |
482 » » » while (i--) shunget(f); | 518 shunget(f); |
483 » » » return NAN; | 519 if (!pok) { |
484 » » } | 520 errno = EINVAL; |
485 » » return NAN; | 521 shlim(f, 0); |
486 » } | 522 return 0; |
487 | 523 } |
488 » if (i) { | 524 while (i--) |
489 » » shunget(f); | 525 shunget(f); |
490 » » errno = EINVAL; | 526 return NAN; |
491 » » shlim(f, 0); | 527 } |
492 » » return 0; | 528 return NAN; |
493 » } | 529 } |
494 | 530 |
495 » if (c=='0') { | 531 if (i) { |
496 » » c = shgetc(f); | 532 shunget(f); |
497 » » if ((c|32) == 'x') | 533 errno = EINVAL; |
498 » » » return hexfloat(f, bits, emin, sign, pok); | 534 shlim(f, 0); |
499 » » shunget(f); | 535 return 0; |
500 » » c = '0'; | 536 } |
501 » } | 537 |
502 | 538 if (c == '0') { |
503 » return decfloat(f, c, bits, emin, sign, pok); | 539 c = shgetc(f); |
| 540 if ((c | 32) == 'x') |
| 541 return hexfloat(f, bits, emin, sign, pok); |
| 542 shunget(f); |
| 543 c = '0'; |
| 544 } |
| 545 |
| 546 return decfloat(f, c, bits, emin, sign, pok); |
504 } | 547 } |
OLD | NEW |