10 #include "floatscan.h"
12 #if LDBL_MANT_DIG == 53 && LDBL_MAX_EXP == 1024
15 #define LD_B1B_MAX 9007199, 254740991
18 #elif LDBL_MANT_DIG == 64 && LDBL_MAX_EXP == 16384
21 #define LD_B1B_MAX 18, 446744073, 709551615
24 #elif LDBL_MANT_DIG == 113 && LDBL_MAX_EXP == 16384
27 #define LD_B1B_MAX 10384593, 717069655, 257060992, 658440191
31 #error Unsupported long double representation
36 static long long scanexp(FILE *f
, int pok
)
44 if (c
=='+' || c
=='-') {
47 if (c
-'0'>=10U && pok
) shunget(f
);
53 for (x
=0; c
-'0'<10U && x
<INT_MAX
/10; c
= shgetc(f
))
55 for (y
=x
; c
-'0'<10U && y
<LLONG_MAX
/100; c
= shgetc(f
))
57 for (; c
-'0'<10U; c
= shgetc(f
));
63 static long double decfloat(FILE *f
, int c
, int bits
, int emin
, int sign
, int pok
)
66 static const uint32_t th
[] = { LD_B1B_MAX
};
68 long long lrp
=0, dc
=0;
71 int gotdig
= 0, gotrad
= 0;
74 int emax
= -emin
-bits
+3;
79 static const int p10s
[] = { 10, 100, 1000, 10000,
80 100000, 1000000, 10000000, 100000000 };
85 /* Don't let leading zeros consume buffer space */
86 for (; c
=='0'; c
= shgetc(f
)) gotdig
=1;
89 for (c
= shgetc(f
); c
=='0'; c
= shgetc(f
)) gotdig
=1, lrp
--;
93 for (; c
-'0'<10U || c
=='.'; c
= shgetc(f
)) {
98 } else if (k
< KMAX
-3) {
100 if (c
!='0') lnz
= dc
;
101 if (j
) x
[k
] = x
[k
]*10 + c
-'0';
118 if (gotdig
&& (c
|32)=='e') {
119 e10
= scanexp(f
, pok
);
120 if (e10
== LLONG_MIN
) {
139 /* Handle zero specially to avoid nasty special cases later */
140 if (!x
[0]) return sign
* 0.0;
142 /* Optimize small integers (w/no exponent) and over/under-flow */
143 if (lrp
==dc
&& dc
<10 && (bits
>30 || x
[0]>>bits
==0))
144 return sign
* (long double)x
[0];
147 return sign
* LDBL_MAX
* LDBL_MAX
;
149 if (lrp
< emin
-2*LDBL_MANT_DIG
) {
151 return sign
* LDBL_MIN
* LDBL_MIN
;
154 /* Align incomplete final B1B digit */
156 for (; j
<9; j
++) x
[k
]*=10;
166 /* Optimize small to mid-size integers (even in exp. notation) */
167 if (lnz
<9 && lnz
<=rp
&& rp
< 18) {
168 if (rp
== 9) return sign
* (long double)x
[0];
169 if (rp
< 9) return sign
* (long double)x
[0] / p10s
[8-rp
];
170 int bitlim
= bits
-3*(int)(rp
-9);
171 if (bitlim
>30 || x
[0]>>bitlim
==0)
172 return sign
* (long double)x
[0] * p10s
[rp
-10];
175 /* Drop trailing zeros */
176 for (; !x
[z
-1]; z
--);
178 /* Align radix point to B1B digit boundary */
180 int rpm9
= rp
>=0 ? rp
%9 : rp
%9+9;
181 int p10
= p10s
[8-rpm9
];
183 for (k
=a
; k
!=z
; k
++) {
184 uint32_t tmp
= x
[k
] % p10
;
185 x
[k
] = x
[k
]/p10
+ carry
;
186 carry
= 1000000000/p10
* tmp
;
192 if (carry
) x
[z
++] = carry
;
196 /* Upscale until desired number of bits are left of radix point */
197 while (rp
< 9*LD_B1B_DIG
|| (rp
== 9*LD_B1B_DIG
&& x
[a
]<th
[0])) {
200 for (k
=(z
-1 & MASK
); ; k
=(k
-1 & MASK
)) {
201 uint64_t tmp
= ((uint64_t)x
[k
] << 29) + carry
;
202 if (tmp
> 1000000000) {
203 carry
= tmp
/ 1000000000;
204 x
[k
] = tmp
% 1000000000;
209 if (k
==(z
-1 & MASK
) && k
!=a
&& !x
[k
]) z
= k
;
217 x
[z
-1 & MASK
] |= x
[z
];
223 /* Downscale until exactly number of bits are left of radix point */
227 for (i
=0; i
<LD_B1B_DIG
; i
++) {
229 if (k
== z
|| x
[k
] < th
[i
]) {
233 if (x
[a
+i
& MASK
] > th
[i
]) break;
235 if (i
==LD_B1B_DIG
&& rp
==9*LD_B1B_DIG
) break;
236 /* FIXME: find a way to compute optimal sh */
237 if (rp
> 9+9*LD_B1B_DIG
) sh
= 9;
239 for (k
=a
; k
!=z
; k
=(k
+1 & MASK
)) {
240 uint32_t tmp
= x
[k
] & (1<<sh
)-1;
241 x
[k
] = (x
[k
]>>sh
) + carry
;
242 carry
= (1000000000>>sh
) * tmp
;
250 if ((z
+1 & MASK
) != a
) {
253 } else x
[z
-1 & MASK
] |= 1;
257 /* Assemble desired bits into floating point variable */
258 for (y
=i
=0; i
<LD_B1B_DIG
; i
++) {
259 if ((a
+i
& MASK
)==z
) x
[(z
=(z
+1 & MASK
))-1] = 0;
260 y
= 1000000000.0L * y
+ x
[a
+i
& MASK
];
265 /* Limit precision for denormal results */
266 if (bits
> LDBL_MANT_DIG
+e2
-emin
) {
267 bits
= LDBL_MANT_DIG
+e2
-emin
;
272 /* Calculate bias term to force rounding, move out lower bits */
273 if (bits
< LDBL_MANT_DIG
) {
274 bias
= copysignl(scalbn(1, 2*LDBL_MANT_DIG
-bits
-1), y
);
275 frac
= fmodl(y
, scalbn(1, LDBL_MANT_DIG
-bits
));
280 /* Process tail of decimal input so it can affect rounding */
281 if ((a
+i
& MASK
) != z
) {
282 uint32_t t
= x
[a
+i
& MASK
];
283 if (t
< 500000000 && (t
|| (a
+i
+1 & MASK
) != z
))
285 else if (t
> 500000000)
287 else if (t
== 500000000) {
288 if ((a
+i
+1 & MASK
) == z
)
293 if (LDBL_MANT_DIG
-bits
>= 2 && !fmodl(frac
, 1))
300 if ((e2
+LDBL_MANT_DIG
& INT_MAX
) > emax
-5) {
301 if (fabsl(y
) >= 2/LDBL_EPSILON
) {
302 if (denormal
&& bits
==LDBL_MANT_DIG
+e2
-emin
)
307 if (e2
+LDBL_MANT_DIG
>emax
|| (denormal
&& frac
))
311 return scalbnl(y
, e2
);
314 static long double hexfloat(FILE *f
, int bits
, int emin
, int sign
, int pok
)
318 long double scale
= 1;
319 long double bias
= 0;
320 int gottail
= 0, gotrad
= 0, gotdig
= 0;
329 /* Skip leading zeros */
330 for (; c
=='0'; c
= shgetc(f
)) gotdig
= 1;
335 /* Count zeros after the radix point before significand */
336 for (rp
=0; c
=='0'; c
= shgetc(f
), rp
--) gotdig
= 1;
339 for (; c
-'0'<10U || (c
|32)-'a'<6U || c
=='.'; c
= shgetc(f
)) {
346 if (c
> '9') d
= (c
|32)+10-'a';
350 } else if (dc
< LDBL_MANT_DIG
/4+1) {
352 } else if (d
&& !gottail
) {
363 if (gotrad
) shunget(f
);
369 if (!gotrad
) rp
= dc
;
370 while (dc
<8) x
*= 16, dc
++;
372 e2
= scanexp(f
, pok
);
373 if (e2
== LLONG_MIN
) {
387 if (!x
) return sign
* 0.0;
390 return sign
* LDBL_MAX
* LDBL_MAX
;
392 if (e2
< emin
-2*LDBL_MANT_DIG
) {
394 return sign
* LDBL_MIN
* LDBL_MIN
;
397 while (x
< 0x80000000) {
408 if (bits
> 32+e2
-emin
) {
413 if (bits
< LDBL_MANT_DIG
)
414 bias
= copysignl(scalbn(1, 32+LDBL_MANT_DIG
-bits
-1), sign
);
416 if (bits
<32 && y
&& !(x
&1)) x
++, y
=0;
418 y
= bias
+ sign
*(long double)x
+ sign
*y
;
421 if (!y
) errno
= ERANGE
;
423 return scalbnl(y
, e2
);
426 long double __floatscan(FILE *f
, int prec
, int pok
)
437 emin
= FLT_MIN_EXP
-bits
;
441 emin
= DBL_MIN_EXP
-bits
;
444 bits
= LDBL_MANT_DIG
;
445 emin
= LDBL_MIN_EXP
-bits
;
451 while (isspace((c
=shgetc(f
))));
453 if (c
=='+' || c
=='-') {
458 for (i
=0; i
<8 && (c
|32)=="infinity"[i
]; i
++)
459 if (i
<7) c
= shgetc(f
);
460 if (i
==3 || i
==8 || (i
>3 && pok
)) {
463 if (pok
) for (; i
>3; i
--) shunget(f
);
465 return sign
* INFINITY
;
467 if (!i
) for (i
=0; i
<3 && (c
|32)=="nan"[i
]; i
++)
468 if (i
<2) c
= shgetc(f
);
470 if (shgetc(f
) != '(') {
476 if (c
-'0'<10U || c
-'A'<26U || c
-'a'<26U || c
=='_')
478 if (c
==')') return NAN
;
485 while (i
--) shunget(f
);
501 return hexfloat(f
, bits
, emin
, sign
, pok
);
506 return decfloat(f
, c
, bits
, emin
, sign
, pok
);