| 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 |