new floating point parser/converter
this version is intended to be fully conformant to the ISO C, POSIX,
and IEEE standards for conversion of decimal/hex floating point
strings to float, double, and long double (ld64 or ld80 only at
present) values. in particular, all results are intended to be rounded
correctly according to the current rounding mode. further, this
implementation aims to set the floating point underflow, overflow, and
inexact flags to reflect the conversion performed.
a moderate amount of testing has been performed (by nsz and myself)
prior to integration of the code in musl, but it still may have bugs.
so far, only strto(d|ld|f) use the new code. scanf integration will be
done as a separate commit, and i will add implementations of the wide
character functions later.
2012-04-10 11:52:55 -04:00
|
|
|
#include <stdint.h>
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <math.h>
|
|
|
|
#include <float.h>
|
|
|
|
#include <limits.h>
|
2012-04-10 22:38:21 -04:00
|
|
|
#include <errno.h>
|
new floating point parser/converter
this version is intended to be fully conformant to the ISO C, POSIX,
and IEEE standards for conversion of decimal/hex floating point
strings to float, double, and long double (ld64 or ld80 only at
present) values. in particular, all results are intended to be rounded
correctly according to the current rounding mode. further, this
implementation aims to set the floating point underflow, overflow, and
inexact flags to reflect the conversion performed.
a moderate amount of testing has been performed (by nsz and myself)
prior to integration of the code in musl, but it still may have bugs.
so far, only strto(d|ld|f) use the new code. scanf integration will be
done as a separate commit, and i will add implementations of the wide
character functions later.
2012-04-10 11:52:55 -04:00
|
|
|
|
2012-04-10 21:47:37 -04:00
|
|
|
#include "shgetc.h"
|
new floating point parser/converter
this version is intended to be fully conformant to the ISO C, POSIX,
and IEEE standards for conversion of decimal/hex floating point
strings to float, double, and long double (ld64 or ld80 only at
present) values. in particular, all results are intended to be rounded
correctly according to the current rounding mode. further, this
implementation aims to set the floating point underflow, overflow, and
inexact flags to reflect the conversion performed.
a moderate amount of testing has been performed (by nsz and myself)
prior to integration of the code in musl, but it still may have bugs.
so far, only strto(d|ld|f) use the new code. scanf integration will be
done as a separate commit, and i will add implementations of the wide
character functions later.
2012-04-10 11:52:55 -04:00
|
|
|
#include "floatscan.h"
|
|
|
|
|
|
|
|
#if LDBL_MANT_DIG == 53 && LDBL_MAX_EXP == 1024
|
|
|
|
|
|
|
|
#define LD_B1B_DIG 2
|
|
|
|
#define LD_B1B_MAX 9007199, 254740991
|
|
|
|
#define KMAX 128
|
|
|
|
|
|
|
|
#else /* LDBL_MANT_DIG == 64 && LDBL_MAX_EXP == 16384 */
|
|
|
|
|
|
|
|
#define LD_B1B_DIG 3
|
|
|
|
#define LD_B1B_MAX 18, 446744073, 709551615
|
|
|
|
#define KMAX 2048
|
|
|
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#define MASK (KMAX-1)
|
|
|
|
|
|
|
|
|
2012-04-10 21:47:37 -04:00
|
|
|
static long long scanexp(FILE *f, int pok)
|
new floating point parser/converter
this version is intended to be fully conformant to the ISO C, POSIX,
and IEEE standards for conversion of decimal/hex floating point
strings to float, double, and long double (ld64 or ld80 only at
present) values. in particular, all results are intended to be rounded
correctly according to the current rounding mode. further, this
implementation aims to set the floating point underflow, overflow, and
inexact flags to reflect the conversion performed.
a moderate amount of testing has been performed (by nsz and myself)
prior to integration of the code in musl, but it still may have bugs.
so far, only strto(d|ld|f) use the new code. scanf integration will be
done as a separate commit, and i will add implementations of the wide
character functions later.
2012-04-10 11:52:55 -04:00
|
|
|
{
|
|
|
|
int c;
|
|
|
|
int x;
|
|
|
|
long long y;
|
|
|
|
int neg = 0;
|
|
|
|
|
2012-04-10 21:47:37 -04:00
|
|
|
c = shgetc(f);
|
new floating point parser/converter
this version is intended to be fully conformant to the ISO C, POSIX,
and IEEE standards for conversion of decimal/hex floating point
strings to float, double, and long double (ld64 or ld80 only at
present) values. in particular, all results are intended to be rounded
correctly according to the current rounding mode. further, this
implementation aims to set the floating point underflow, overflow, and
inexact flags to reflect the conversion performed.
a moderate amount of testing has been performed (by nsz and myself)
prior to integration of the code in musl, but it still may have bugs.
so far, only strto(d|ld|f) use the new code. scanf integration will be
done as a separate commit, and i will add implementations of the wide
character functions later.
2012-04-10 11:52:55 -04:00
|
|
|
if (c=='+' || c=='-') {
|
|
|
|
neg = (c=='-');
|
2012-04-10 21:47:37 -04:00
|
|
|
c = shgetc(f);
|
|
|
|
if (c-'0'>=10U && pok) shunget(f);
|
|
|
|
}
|
|
|
|
if (c-'0'>=10U) {
|
|
|
|
shunget(f);
|
|
|
|
return LLONG_MIN;
|
new floating point parser/converter
this version is intended to be fully conformant to the ISO C, POSIX,
and IEEE standards for conversion of decimal/hex floating point
strings to float, double, and long double (ld64 or ld80 only at
present) values. in particular, all results are intended to be rounded
correctly according to the current rounding mode. further, this
implementation aims to set the floating point underflow, overflow, and
inexact flags to reflect the conversion performed.
a moderate amount of testing has been performed (by nsz and myself)
prior to integration of the code in musl, but it still may have bugs.
so far, only strto(d|ld|f) use the new code. scanf integration will be
done as a separate commit, and i will add implementations of the wide
character functions later.
2012-04-10 11:52:55 -04:00
|
|
|
}
|
2012-04-10 21:47:37 -04:00
|
|
|
for (x=0; c-'0'<10U && x<INT_MAX/10; c = shgetc(f))
|
new floating point parser/converter
this version is intended to be fully conformant to the ISO C, POSIX,
and IEEE standards for conversion of decimal/hex floating point
strings to float, double, and long double (ld64 or ld80 only at
present) values. in particular, all results are intended to be rounded
correctly according to the current rounding mode. further, this
implementation aims to set the floating point underflow, overflow, and
inexact flags to reflect the conversion performed.
a moderate amount of testing has been performed (by nsz and myself)
prior to integration of the code in musl, but it still may have bugs.
so far, only strto(d|ld|f) use the new code. scanf integration will be
done as a separate commit, and i will add implementations of the wide
character functions later.
2012-04-10 11:52:55 -04:00
|
|
|
x = 10*x + c-'0';
|
2012-04-10 23:05:16 -04:00
|
|
|
for (y=x; c-'0'<10U && x<LLONG_MAX/100; c = shgetc(f))
|
new floating point parser/converter
this version is intended to be fully conformant to the ISO C, POSIX,
and IEEE standards for conversion of decimal/hex floating point
strings to float, double, and long double (ld64 or ld80 only at
present) values. in particular, all results are intended to be rounded
correctly according to the current rounding mode. further, this
implementation aims to set the floating point underflow, overflow, and
inexact flags to reflect the conversion performed.
a moderate amount of testing has been performed (by nsz and myself)
prior to integration of the code in musl, but it still may have bugs.
so far, only strto(d|ld|f) use the new code. scanf integration will be
done as a separate commit, and i will add implementations of the wide
character functions later.
2012-04-10 11:52:55 -04:00
|
|
|
y = 10*y + c-'0';
|
2012-04-10 21:47:37 -04:00
|
|
|
for (; c-'0'<10U; c = shgetc(f));
|
|
|
|
shunget(f);
|
new floating point parser/converter
this version is intended to be fully conformant to the ISO C, POSIX,
and IEEE standards for conversion of decimal/hex floating point
strings to float, double, and long double (ld64 or ld80 only at
present) values. in particular, all results are intended to be rounded
correctly according to the current rounding mode. further, this
implementation aims to set the floating point underflow, overflow, and
inexact flags to reflect the conversion performed.
a moderate amount of testing has been performed (by nsz and myself)
prior to integration of the code in musl, but it still may have bugs.
so far, only strto(d|ld|f) use the new code. scanf integration will be
done as a separate commit, and i will add implementations of the wide
character functions later.
2012-04-10 11:52:55 -04:00
|
|
|
return neg ? -y : y;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-04-11 00:18:57 -04:00
|
|
|
static long double decfloat(FILE *f, int c, int bits, int emin, int sign, int pok)
|
new floating point parser/converter
this version is intended to be fully conformant to the ISO C, POSIX,
and IEEE standards for conversion of decimal/hex floating point
strings to float, double, and long double (ld64 or ld80 only at
present) values. in particular, all results are intended to be rounded
correctly according to the current rounding mode. further, this
implementation aims to set the floating point underflow, overflow, and
inexact flags to reflect the conversion performed.
a moderate amount of testing has been performed (by nsz and myself)
prior to integration of the code in musl, but it still may have bugs.
so far, only strto(d|ld|f) use the new code. scanf integration will be
done as a separate commit, and i will add implementations of the wide
character functions later.
2012-04-10 11:52:55 -04:00
|
|
|
{
|
|
|
|
uint32_t x[KMAX];
|
|
|
|
static const uint32_t th[] = { LD_B1B_MAX };
|
|
|
|
int i, j, k, a, z;
|
|
|
|
long long lrp=-1, dc=0;
|
2012-04-10 21:47:37 -04:00
|
|
|
long long e10=0;
|
2012-04-12 00:16:01 -04:00
|
|
|
int lnz = 0;
|
new floating point parser/converter
this version is intended to be fully conformant to the ISO C, POSIX,
and IEEE standards for conversion of decimal/hex floating point
strings to float, double, and long double (ld64 or ld80 only at
present) values. in particular, all results are intended to be rounded
correctly according to the current rounding mode. further, this
implementation aims to set the floating point underflow, overflow, and
inexact flags to reflect the conversion performed.
a moderate amount of testing has been performed (by nsz and myself)
prior to integration of the code in musl, but it still may have bugs.
so far, only strto(d|ld|f) use the new code. scanf integration will be
done as a separate commit, and i will add implementations of the wide
character functions later.
2012-04-10 11:52:55 -04:00
|
|
|
int gotdig = 0;
|
|
|
|
int rp;
|
|
|
|
int e2;
|
|
|
|
long double y;
|
|
|
|
long double frac=0;
|
|
|
|
long double bias=0;
|
2012-04-12 00:16:01 -04:00
|
|
|
static const int p10s[] = { 10, 100, 1000, 10000,
|
|
|
|
100000, 1000000, 10000000, 100000000 };
|
new floating point parser/converter
this version is intended to be fully conformant to the ISO C, POSIX,
and IEEE standards for conversion of decimal/hex floating point
strings to float, double, and long double (ld64 or ld80 only at
present) values. in particular, all results are intended to be rounded
correctly according to the current rounding mode. further, this
implementation aims to set the floating point underflow, overflow, and
inexact flags to reflect the conversion performed.
a moderate amount of testing has been performed (by nsz and myself)
prior to integration of the code in musl, but it still may have bugs.
so far, only strto(d|ld|f) use the new code. scanf integration will be
done as a separate commit, and i will add implementations of the wide
character functions later.
2012-04-10 11:52:55 -04:00
|
|
|
|
|
|
|
j=0;
|
|
|
|
k=0;
|
|
|
|
|
|
|
|
/* Don't let leading zeros consume buffer space */
|
2012-04-10 21:47:37 -04:00
|
|
|
for (; c=='0'; c = shgetc(f)) gotdig=1;
|
new floating point parser/converter
this version is intended to be fully conformant to the ISO C, POSIX,
and IEEE standards for conversion of decimal/hex floating point
strings to float, double, and long double (ld64 or ld80 only at
present) values. in particular, all results are intended to be rounded
correctly according to the current rounding mode. further, this
implementation aims to set the floating point underflow, overflow, and
inexact flags to reflect the conversion performed.
a moderate amount of testing has been performed (by nsz and myself)
prior to integration of the code in musl, but it still may have bugs.
so far, only strto(d|ld|f) use the new code. scanf integration will be
done as a separate commit, and i will add implementations of the wide
character functions later.
2012-04-10 11:52:55 -04:00
|
|
|
|
|
|
|
x[0] = 0;
|
2012-04-10 21:47:37 -04:00
|
|
|
for (; c-'0'<10U || c=='.'; c = shgetc(f)) {
|
new floating point parser/converter
this version is intended to be fully conformant to the ISO C, POSIX,
and IEEE standards for conversion of decimal/hex floating point
strings to float, double, and long double (ld64 or ld80 only at
present) values. in particular, all results are intended to be rounded
correctly according to the current rounding mode. further, this
implementation aims to set the floating point underflow, overflow, and
inexact flags to reflect the conversion performed.
a moderate amount of testing has been performed (by nsz and myself)
prior to integration of the code in musl, but it still may have bugs.
so far, only strto(d|ld|f) use the new code. scanf integration will be
done as a separate commit, and i will add implementations of the wide
character functions later.
2012-04-10 11:52:55 -04:00
|
|
|
if (c == '.') {
|
|
|
|
if (lrp!=-1) break;
|
|
|
|
lrp = dc;
|
2012-04-11 14:20:45 -04:00
|
|
|
} else if (k < KMAX-2) {
|
new floating point parser/converter
this version is intended to be fully conformant to the ISO C, POSIX,
and IEEE standards for conversion of decimal/hex floating point
strings to float, double, and long double (ld64 or ld80 only at
present) values. in particular, all results are intended to be rounded
correctly according to the current rounding mode. further, this
implementation aims to set the floating point underflow, overflow, and
inexact flags to reflect the conversion performed.
a moderate amount of testing has been performed (by nsz and myself)
prior to integration of the code in musl, but it still may have bugs.
so far, only strto(d|ld|f) use the new code. scanf integration will be
done as a separate commit, and i will add implementations of the wide
character functions later.
2012-04-10 11:52:55 -04:00
|
|
|
dc++;
|
2012-04-16 01:53:52 -04:00
|
|
|
if (c!='0') lnz = dc;
|
new floating point parser/converter
this version is intended to be fully conformant to the ISO C, POSIX,
and IEEE standards for conversion of decimal/hex floating point
strings to float, double, and long double (ld64 or ld80 only at
present) values. in particular, all results are intended to be rounded
correctly according to the current rounding mode. further, this
implementation aims to set the floating point underflow, overflow, and
inexact flags to reflect the conversion performed.
a moderate amount of testing has been performed (by nsz and myself)
prior to integration of the code in musl, but it still may have bugs.
so far, only strto(d|ld|f) use the new code. scanf integration will be
done as a separate commit, and i will add implementations of the wide
character functions later.
2012-04-10 11:52:55 -04:00
|
|
|
if (j) x[k] = x[k]*10 + c-'0';
|
|
|
|
else x[k] = c-'0';
|
|
|
|
if (++j==9) {
|
|
|
|
k++;
|
|
|
|
j=0;
|
|
|
|
}
|
|
|
|
gotdig=1;
|
|
|
|
} else {
|
|
|
|
dc++;
|
2012-04-11 14:20:45 -04:00
|
|
|
if (c!='0') x[KMAX-3] |= 1;
|
new floating point parser/converter
this version is intended to be fully conformant to the ISO C, POSIX,
and IEEE standards for conversion of decimal/hex floating point
strings to float, double, and long double (ld64 or ld80 only at
present) values. in particular, all results are intended to be rounded
correctly according to the current rounding mode. further, this
implementation aims to set the floating point underflow, overflow, and
inexact flags to reflect the conversion performed.
a moderate amount of testing has been performed (by nsz and myself)
prior to integration of the code in musl, but it still may have bugs.
so far, only strto(d|ld|f) use the new code. scanf integration will be
done as a separate commit, and i will add implementations of the wide
character functions later.
2012-04-10 11:52:55 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
if (lrp==-1) lrp=dc;
|
|
|
|
|
|
|
|
if (gotdig && (c|32)=='e') {
|
2012-04-10 21:47:37 -04:00
|
|
|
e10 = scanexp(f, pok);
|
new floating point parser/converter
this version is intended to be fully conformant to the ISO C, POSIX,
and IEEE standards for conversion of decimal/hex floating point
strings to float, double, and long double (ld64 or ld80 only at
present) values. in particular, all results are intended to be rounded
correctly according to the current rounding mode. further, this
implementation aims to set the floating point underflow, overflow, and
inexact flags to reflect the conversion performed.
a moderate amount of testing has been performed (by nsz and myself)
prior to integration of the code in musl, but it still may have bugs.
so far, only strto(d|ld|f) use the new code. scanf integration will be
done as a separate commit, and i will add implementations of the wide
character functions later.
2012-04-10 11:52:55 -04:00
|
|
|
if (e10 == LLONG_MIN) {
|
2012-04-10 21:47:37 -04:00
|
|
|
if (pok) {
|
|
|
|
shunget(f);
|
|
|
|
} else {
|
|
|
|
shlim(f, 0);
|
new floating point parser/converter
this version is intended to be fully conformant to the ISO C, POSIX,
and IEEE standards for conversion of decimal/hex floating point
strings to float, double, and long double (ld64 or ld80 only at
present) values. in particular, all results are intended to be rounded
correctly according to the current rounding mode. further, this
implementation aims to set the floating point underflow, overflow, and
inexact flags to reflect the conversion performed.
a moderate amount of testing has been performed (by nsz and myself)
prior to integration of the code in musl, but it still may have bugs.
so far, only strto(d|ld|f) use the new code. scanf integration will be
done as a separate commit, and i will add implementations of the wide
character functions later.
2012-04-10 11:52:55 -04:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
e10 = 0;
|
|
|
|
}
|
|
|
|
lrp += e10;
|
|
|
|
} else if (c>=0) {
|
2012-04-10 21:47:37 -04:00
|
|
|
shunget(f);
|
new floating point parser/converter
this version is intended to be fully conformant to the ISO C, POSIX,
and IEEE standards for conversion of decimal/hex floating point
strings to float, double, and long double (ld64 or ld80 only at
present) values. in particular, all results are intended to be rounded
correctly according to the current rounding mode. further, this
implementation aims to set the floating point underflow, overflow, and
inexact flags to reflect the conversion performed.
a moderate amount of testing has been performed (by nsz and myself)
prior to integration of the code in musl, but it still may have bugs.
so far, only strto(d|ld|f) use the new code. scanf integration will be
done as a separate commit, and i will add implementations of the wide
character functions later.
2012-04-10 11:52:55 -04:00
|
|
|
}
|
|
|
|
if (!gotdig) {
|
2012-04-10 22:38:21 -04:00
|
|
|
errno = EINVAL;
|
2012-04-10 21:47:37 -04:00
|
|
|
shlim(f, 0);
|
new floating point parser/converter
this version is intended to be fully conformant to the ISO C, POSIX,
and IEEE standards for conversion of decimal/hex floating point
strings to float, double, and long double (ld64 or ld80 only at
present) values. in particular, all results are intended to be rounded
correctly according to the current rounding mode. further, this
implementation aims to set the floating point underflow, overflow, and
inexact flags to reflect the conversion performed.
a moderate amount of testing has been performed (by nsz and myself)
prior to integration of the code in musl, but it still may have bugs.
so far, only strto(d|ld|f) use the new code. scanf integration will be
done as a separate commit, and i will add implementations of the wide
character functions later.
2012-04-10 11:52:55 -04:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2012-04-12 00:16:01 -04:00
|
|
|
/* Handle zero specially to avoid nasty special cases later */
|
|
|
|
if (!x[0]) return sign * 0.0;
|
|
|
|
|
|
|
|
/* Optimize small integers (w/no exponent) and over/under-flow */
|
|
|
|
if (lrp==dc && dc<10 && (bits>30 || x[0]>>bits==0))
|
new floating point parser/converter
this version is intended to be fully conformant to the ISO C, POSIX,
and IEEE standards for conversion of decimal/hex floating point
strings to float, double, and long double (ld64 or ld80 only at
present) values. in particular, all results are intended to be rounded
correctly according to the current rounding mode. further, this
implementation aims to set the floating point underflow, overflow, and
inexact flags to reflect the conversion performed.
a moderate amount of testing has been performed (by nsz and myself)
prior to integration of the code in musl, but it still may have bugs.
so far, only strto(d|ld|f) use the new code. scanf integration will be
done as a separate commit, and i will add implementations of the wide
character functions later.
2012-04-10 11:52:55 -04:00
|
|
|
return sign * (long double)x[0];
|
2012-04-10 22:38:21 -04:00
|
|
|
if (lrp > -emin/2) {
|
|
|
|
errno = ERANGE;
|
new floating point parser/converter
this version is intended to be fully conformant to the ISO C, POSIX,
and IEEE standards for conversion of decimal/hex floating point
strings to float, double, and long double (ld64 or ld80 only at
present) values. in particular, all results are intended to be rounded
correctly according to the current rounding mode. further, this
implementation aims to set the floating point underflow, overflow, and
inexact flags to reflect the conversion performed.
a moderate amount of testing has been performed (by nsz and myself)
prior to integration of the code in musl, but it still may have bugs.
so far, only strto(d|ld|f) use the new code. scanf integration will be
done as a separate commit, and i will add implementations of the wide
character functions later.
2012-04-10 11:52:55 -04:00
|
|
|
return sign * LDBL_MAX * LDBL_MAX;
|
2012-04-10 22:38:21 -04:00
|
|
|
}
|
|
|
|
if (lrp < emin-2*LDBL_MANT_DIG) {
|
|
|
|
errno = ERANGE;
|
new floating point parser/converter
this version is intended to be fully conformant to the ISO C, POSIX,
and IEEE standards for conversion of decimal/hex floating point
strings to float, double, and long double (ld64 or ld80 only at
present) values. in particular, all results are intended to be rounded
correctly according to the current rounding mode. further, this
implementation aims to set the floating point underflow, overflow, and
inexact flags to reflect the conversion performed.
a moderate amount of testing has been performed (by nsz and myself)
prior to integration of the code in musl, but it still may have bugs.
so far, only strto(d|ld|f) use the new code. scanf integration will be
done as a separate commit, and i will add implementations of the wide
character functions later.
2012-04-10 11:52:55 -04:00
|
|
|
return sign * LDBL_MIN * LDBL_MIN;
|
2012-04-10 22:38:21 -04:00
|
|
|
}
|
new floating point parser/converter
this version is intended to be fully conformant to the ISO C, POSIX,
and IEEE standards for conversion of decimal/hex floating point
strings to float, double, and long double (ld64 or ld80 only at
present) values. in particular, all results are intended to be rounded
correctly according to the current rounding mode. further, this
implementation aims to set the floating point underflow, overflow, and
inexact flags to reflect the conversion performed.
a moderate amount of testing has been performed (by nsz and myself)
prior to integration of the code in musl, but it still may have bugs.
so far, only strto(d|ld|f) use the new code. scanf integration will be
done as a separate commit, and i will add implementations of the wide
character functions later.
2012-04-10 11:52:55 -04:00
|
|
|
|
2012-04-12 00:16:01 -04:00
|
|
|
/* Align incomplete final B1B digit */
|
new floating point parser/converter
this version is intended to be fully conformant to the ISO C, POSIX,
and IEEE standards for conversion of decimal/hex floating point
strings to float, double, and long double (ld64 or ld80 only at
present) values. in particular, all results are intended to be rounded
correctly according to the current rounding mode. further, this
implementation aims to set the floating point underflow, overflow, and
inexact flags to reflect the conversion performed.
a moderate amount of testing has been performed (by nsz and myself)
prior to integration of the code in musl, but it still may have bugs.
so far, only strto(d|ld|f) use the new code. scanf integration will be
done as a separate commit, and i will add implementations of the wide
character functions later.
2012-04-10 11:52:55 -04:00
|
|
|
if (k<KMAX && j) {
|
|
|
|
for (; j<9; j++) x[k]*=10;
|
|
|
|
k++;
|
|
|
|
j=0;
|
|
|
|
}
|
|
|
|
|
|
|
|
a = 0;
|
|
|
|
z = k;
|
|
|
|
e2 = 0;
|
|
|
|
rp = lrp;
|
|
|
|
|
2012-04-12 00:16:01 -04:00
|
|
|
/* Optimize small to mid-size integers (even in exp. notation) */
|
|
|
|
if (lnz<9 && lnz<=rp && rp < 18) {
|
|
|
|
if (rp == 9) return sign * (long double)x[0];
|
|
|
|
if (rp < 9) return sign * (long double)x[0] / p10s[8-rp];
|
|
|
|
int bitlim = bits-3*(int)(rp-9);
|
|
|
|
if (bitlim>30 || x[0]>>bitlim==0)
|
|
|
|
return sign * (long double)x[0] * p10s[rp-10];
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Align radix point to B1B digit boundary */
|
new floating point parser/converter
this version is intended to be fully conformant to the ISO C, POSIX,
and IEEE standards for conversion of decimal/hex floating point
strings to float, double, and long double (ld64 or ld80 only at
present) values. in particular, all results are intended to be rounded
correctly according to the current rounding mode. further, this
implementation aims to set the floating point underflow, overflow, and
inexact flags to reflect the conversion performed.
a moderate amount of testing has been performed (by nsz and myself)
prior to integration of the code in musl, but it still may have bugs.
so far, only strto(d|ld|f) use the new code. scanf integration will be
done as a separate commit, and i will add implementations of the wide
character functions later.
2012-04-10 11:52:55 -04:00
|
|
|
if (rp % 9) {
|
2012-04-11 14:11:47 -04:00
|
|
|
int rpm9 = rp>=0 ? rp%9 : rp%9+9;
|
2012-04-12 00:16:01 -04:00
|
|
|
int p10 = p10s[8-rpm9];
|
new floating point parser/converter
this version is intended to be fully conformant to the ISO C, POSIX,
and IEEE standards for conversion of decimal/hex floating point
strings to float, double, and long double (ld64 or ld80 only at
present) values. in particular, all results are intended to be rounded
correctly according to the current rounding mode. further, this
implementation aims to set the floating point underflow, overflow, and
inexact flags to reflect the conversion performed.
a moderate amount of testing has been performed (by nsz and myself)
prior to integration of the code in musl, but it still may have bugs.
so far, only strto(d|ld|f) use the new code. scanf integration will be
done as a separate commit, and i will add implementations of the wide
character functions later.
2012-04-10 11:52:55 -04:00
|
|
|
uint32_t carry = 0;
|
2012-04-11 14:20:45 -04:00
|
|
|
for (k=a; k!=z; k++) {
|
new floating point parser/converter
this version is intended to be fully conformant to the ISO C, POSIX,
and IEEE standards for conversion of decimal/hex floating point
strings to float, double, and long double (ld64 or ld80 only at
present) values. in particular, all results are intended to be rounded
correctly according to the current rounding mode. further, this
implementation aims to set the floating point underflow, overflow, and
inexact flags to reflect the conversion performed.
a moderate amount of testing has been performed (by nsz and myself)
prior to integration of the code in musl, but it still may have bugs.
so far, only strto(d|ld|f) use the new code. scanf integration will be
done as a separate commit, and i will add implementations of the wide
character functions later.
2012-04-10 11:52:55 -04:00
|
|
|
uint32_t tmp = x[k] % p10;
|
|
|
|
x[k] = x[k]/p10 + carry;
|
|
|
|
carry = 1000000000/p10 * tmp;
|
|
|
|
if (k==a && !x[k]) {
|
|
|
|
a = (a+1 & MASK);
|
|
|
|
rp -= 9;
|
|
|
|
}
|
|
|
|
}
|
2012-04-11 14:20:45 -04:00
|
|
|
if (carry) x[z++] = carry;
|
new floating point parser/converter
this version is intended to be fully conformant to the ISO C, POSIX,
and IEEE standards for conversion of decimal/hex floating point
strings to float, double, and long double (ld64 or ld80 only at
present) values. in particular, all results are intended to be rounded
correctly according to the current rounding mode. further, this
implementation aims to set the floating point underflow, overflow, and
inexact flags to reflect the conversion performed.
a moderate amount of testing has been performed (by nsz and myself)
prior to integration of the code in musl, but it still may have bugs.
so far, only strto(d|ld|f) use the new code. scanf integration will be
done as a separate commit, and i will add implementations of the wide
character functions later.
2012-04-10 11:52:55 -04:00
|
|
|
rp += 9-rpm9;
|
|
|
|
}
|
|
|
|
|
2012-04-12 00:16:01 -04:00
|
|
|
/* Upscale until desired number of bits are left of radix point */
|
2012-04-11 21:29:12 -04:00
|
|
|
while (rp < 9*LD_B1B_DIG || (rp == 9*LD_B1B_DIG && x[a]<th[0])) {
|
2012-04-11 14:11:47 -04:00
|
|
|
uint32_t carry = 0;
|
|
|
|
e2 -= 29;
|
|
|
|
for (k=(z-1 & MASK); ; k=(k-1 & MASK)) {
|
|
|
|
uint64_t tmp = ((uint64_t)x[k] << 29) + carry;
|
|
|
|
if (tmp > 1000000000) {
|
|
|
|
carry = tmp / 1000000000;
|
|
|
|
x[k] = tmp % 1000000000;
|
|
|
|
} else {
|
|
|
|
carry = 0;
|
|
|
|
x[k] = tmp;
|
|
|
|
}
|
|
|
|
if (k==(z-1 & MASK) && k!=a && !x[k]) z = k;
|
|
|
|
if (k==a) break;
|
|
|
|
}
|
|
|
|
if (carry) {
|
|
|
|
rp += 9;
|
|
|
|
if (a == z) {
|
|
|
|
z = (z-1 & MASK);
|
|
|
|
x[z-1 & MASK] |= x[z];
|
|
|
|
}
|
|
|
|
a = (a-1 & MASK);
|
|
|
|
x[a] = carry;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-04-12 00:16:01 -04:00
|
|
|
/* Downscale until exactly number of bits are left of radix point */
|
new floating point parser/converter
this version is intended to be fully conformant to the ISO C, POSIX,
and IEEE standards for conversion of decimal/hex floating point
strings to float, double, and long double (ld64 or ld80 only at
present) values. in particular, all results are intended to be rounded
correctly according to the current rounding mode. further, this
implementation aims to set the floating point underflow, overflow, and
inexact flags to reflect the conversion performed.
a moderate amount of testing has been performed (by nsz and myself)
prior to integration of the code in musl, but it still may have bugs.
so far, only strto(d|ld|f) use the new code. scanf integration will be
done as a separate commit, and i will add implementations of the wide
character functions later.
2012-04-10 11:52:55 -04:00
|
|
|
for (;;) {
|
|
|
|
uint32_t carry = 0;
|
|
|
|
int sh = 1;
|
|
|
|
for (i=0; i<LD_B1B_DIG; i++) {
|
|
|
|
k = (a+i & MASK);
|
|
|
|
if (k == z || x[k] < th[i]) {
|
|
|
|
i=LD_B1B_DIG;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (x[a+i & MASK] > th[i]) break;
|
|
|
|
}
|
|
|
|
if (i==LD_B1B_DIG && rp==9*LD_B1B_DIG) break;
|
|
|
|
/* FIXME: find a way to compute optimal sh */
|
|
|
|
if (rp > 9+9*LD_B1B_DIG) sh = 9;
|
|
|
|
e2 += sh;
|
2012-04-11 23:08:50 -04:00
|
|
|
for (k=a; k!=z; k=(k+1 & MASK)) {
|
new floating point parser/converter
this version is intended to be fully conformant to the ISO C, POSIX,
and IEEE standards for conversion of decimal/hex floating point
strings to float, double, and long double (ld64 or ld80 only at
present) values. in particular, all results are intended to be rounded
correctly according to the current rounding mode. further, this
implementation aims to set the floating point underflow, overflow, and
inexact flags to reflect the conversion performed.
a moderate amount of testing has been performed (by nsz and myself)
prior to integration of the code in musl, but it still may have bugs.
so far, only strto(d|ld|f) use the new code. scanf integration will be
done as a separate commit, and i will add implementations of the wide
character functions later.
2012-04-10 11:52:55 -04:00
|
|
|
uint32_t tmp = x[k] & (1<<sh)-1;
|
|
|
|
x[k] = (x[k]>>sh) + carry;
|
|
|
|
carry = (1000000000>>sh) * tmp;
|
|
|
|
if (k==a && !x[k]) {
|
|
|
|
a = (a+1 & MASK);
|
2012-04-11 14:51:08 -04:00
|
|
|
i--;
|
new floating point parser/converter
this version is intended to be fully conformant to the ISO C, POSIX,
and IEEE standards for conversion of decimal/hex floating point
strings to float, double, and long double (ld64 or ld80 only at
present) values. in particular, all results are intended to be rounded
correctly according to the current rounding mode. further, this
implementation aims to set the floating point underflow, overflow, and
inexact flags to reflect the conversion performed.
a moderate amount of testing has been performed (by nsz and myself)
prior to integration of the code in musl, but it still may have bugs.
so far, only strto(d|ld|f) use the new code. scanf integration will be
done as a separate commit, and i will add implementations of the wide
character functions later.
2012-04-10 11:52:55 -04:00
|
|
|
rp -= 9;
|
|
|
|
}
|
|
|
|
}
|
2012-04-11 23:08:50 -04:00
|
|
|
if (carry) {
|
new floating point parser/converter
this version is intended to be fully conformant to the ISO C, POSIX,
and IEEE standards for conversion of decimal/hex floating point
strings to float, double, and long double (ld64 or ld80 only at
present) values. in particular, all results are intended to be rounded
correctly according to the current rounding mode. further, this
implementation aims to set the floating point underflow, overflow, and
inexact flags to reflect the conversion performed.
a moderate amount of testing has been performed (by nsz and myself)
prior to integration of the code in musl, but it still may have bugs.
so far, only strto(d|ld|f) use the new code. scanf integration will be
done as a separate commit, and i will add implementations of the wide
character functions later.
2012-04-10 11:52:55 -04:00
|
|
|
if ((z+1 & MASK) != a) {
|
|
|
|
x[z] = carry;
|
|
|
|
z = (z+1 & MASK);
|
|
|
|
} else x[z-1 & MASK] |= 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-04-12 00:16:01 -04:00
|
|
|
/* Assemble desired bits into floating point variable */
|
2012-04-10 23:41:54 -04:00
|
|
|
for (y=i=0; i<LD_B1B_DIG; i++) {
|
|
|
|
if ((a+i & MASK)==z) x[z=(z+1 & MASK)] = 0;
|
new floating point parser/converter
this version is intended to be fully conformant to the ISO C, POSIX,
and IEEE standards for conversion of decimal/hex floating point
strings to float, double, and long double (ld64 or ld80 only at
present) values. in particular, all results are intended to be rounded
correctly according to the current rounding mode. further, this
implementation aims to set the floating point underflow, overflow, and
inexact flags to reflect the conversion performed.
a moderate amount of testing has been performed (by nsz and myself)
prior to integration of the code in musl, but it still may have bugs.
so far, only strto(d|ld|f) use the new code. scanf integration will be
done as a separate commit, and i will add implementations of the wide
character functions later.
2012-04-10 11:52:55 -04:00
|
|
|
y = 1000000000.0L * y + x[a+i & MASK];
|
2012-04-10 23:41:54 -04:00
|
|
|
}
|
new floating point parser/converter
this version is intended to be fully conformant to the ISO C, POSIX,
and IEEE standards for conversion of decimal/hex floating point
strings to float, double, and long double (ld64 or ld80 only at
present) values. in particular, all results are intended to be rounded
correctly according to the current rounding mode. further, this
implementation aims to set the floating point underflow, overflow, and
inexact flags to reflect the conversion performed.
a moderate amount of testing has been performed (by nsz and myself)
prior to integration of the code in musl, but it still may have bugs.
so far, only strto(d|ld|f) use the new code. scanf integration will be
done as a separate commit, and i will add implementations of the wide
character functions later.
2012-04-10 11:52:55 -04:00
|
|
|
|
|
|
|
y *= sign;
|
|
|
|
|
2012-04-12 00:16:01 -04:00
|
|
|
/* Limit precision for denormal results */
|
new floating point parser/converter
this version is intended to be fully conformant to the ISO C, POSIX,
and IEEE standards for conversion of decimal/hex floating point
strings to float, double, and long double (ld64 or ld80 only at
present) values. in particular, all results are intended to be rounded
correctly according to the current rounding mode. further, this
implementation aims to set the floating point underflow, overflow, and
inexact flags to reflect the conversion performed.
a moderate amount of testing has been performed (by nsz and myself)
prior to integration of the code in musl, but it still may have bugs.
so far, only strto(d|ld|f) use the new code. scanf integration will be
done as a separate commit, and i will add implementations of the wide
character functions later.
2012-04-10 11:52:55 -04:00
|
|
|
if (bits > LDBL_MANT_DIG+e2-emin) {
|
|
|
|
bits = LDBL_MANT_DIG+e2-emin;
|
|
|
|
if (bits<0) bits=0;
|
|
|
|
}
|
|
|
|
|
2012-04-12 00:16:01 -04:00
|
|
|
/* Calculate bias term to force rounding, move out lower bits */
|
new floating point parser/converter
this version is intended to be fully conformant to the ISO C, POSIX,
and IEEE standards for conversion of decimal/hex floating point
strings to float, double, and long double (ld64 or ld80 only at
present) values. in particular, all results are intended to be rounded
correctly according to the current rounding mode. further, this
implementation aims to set the floating point underflow, overflow, and
inexact flags to reflect the conversion performed.
a moderate amount of testing has been performed (by nsz and myself)
prior to integration of the code in musl, but it still may have bugs.
so far, only strto(d|ld|f) use the new code. scanf integration will be
done as a separate commit, and i will add implementations of the wide
character functions later.
2012-04-10 11:52:55 -04:00
|
|
|
if (bits < LDBL_MANT_DIG) {
|
|
|
|
bias = copysignl(scalbn(1, 2*LDBL_MANT_DIG-bits-1), y);
|
|
|
|
frac = fmodl(y, scalbn(1, LDBL_MANT_DIG-bits));
|
|
|
|
y -= frac;
|
|
|
|
y += bias;
|
|
|
|
}
|
|
|
|
|
2012-04-12 00:16:01 -04:00
|
|
|
/* Process tail of decimal input so it can affect rounding */
|
new floating point parser/converter
this version is intended to be fully conformant to the ISO C, POSIX,
and IEEE standards for conversion of decimal/hex floating point
strings to float, double, and long double (ld64 or ld80 only at
present) values. in particular, all results are intended to be rounded
correctly according to the current rounding mode. further, this
implementation aims to set the floating point underflow, overflow, and
inexact flags to reflect the conversion performed.
a moderate amount of testing has been performed (by nsz and myself)
prior to integration of the code in musl, but it still may have bugs.
so far, only strto(d|ld|f) use the new code. scanf integration will be
done as a separate commit, and i will add implementations of the wide
character functions later.
2012-04-10 11:52:55 -04:00
|
|
|
if ((a+i & MASK) != z) {
|
|
|
|
uint32_t t = x[a+i & MASK];
|
|
|
|
if (t < 500000000 && (t || (a+i+1 & MASK) != z))
|
|
|
|
frac += 0.25*sign;
|
|
|
|
else if (t > 500000000)
|
|
|
|
frac += 0.75*sign;
|
|
|
|
else if (t == 500000000) {
|
|
|
|
if ((a+i+1 & MASK) == z)
|
|
|
|
frac += 0.5*sign;
|
|
|
|
else
|
|
|
|
frac += 0.75*sign;
|
|
|
|
}
|
|
|
|
if (LDBL_MANT_DIG-bits >= 2 && !fmodl(frac, 1))
|
|
|
|
frac++;
|
|
|
|
}
|
|
|
|
|
|
|
|
y += frac;
|
|
|
|
y -= bias;
|
|
|
|
|
|
|
|
y = scalbnl(y, e2);
|
|
|
|
|
2012-04-10 22:38:21 -04:00
|
|
|
if (!y) errno = ERANGE;
|
|
|
|
|
new floating point parser/converter
this version is intended to be fully conformant to the ISO C, POSIX,
and IEEE standards for conversion of decimal/hex floating point
strings to float, double, and long double (ld64 or ld80 only at
present) values. in particular, all results are intended to be rounded
correctly according to the current rounding mode. further, this
implementation aims to set the floating point underflow, overflow, and
inexact flags to reflect the conversion performed.
a moderate amount of testing has been performed (by nsz and myself)
prior to integration of the code in musl, but it still may have bugs.
so far, only strto(d|ld|f) use the new code. scanf integration will be
done as a separate commit, and i will add implementations of the wide
character functions later.
2012-04-10 11:52:55 -04:00
|
|
|
return y;
|
|
|
|
}
|
|
|
|
|
2012-04-10 21:47:37 -04:00
|
|
|
static long double hexfloat(FILE *f, int bits, int emin, int sign, int pok)
|
new floating point parser/converter
this version is intended to be fully conformant to the ISO C, POSIX,
and IEEE standards for conversion of decimal/hex floating point
strings to float, double, and long double (ld64 or ld80 only at
present) values. in particular, all results are intended to be rounded
correctly according to the current rounding mode. further, this
implementation aims to set the floating point underflow, overflow, and
inexact flags to reflect the conversion performed.
a moderate amount of testing has been performed (by nsz and myself)
prior to integration of the code in musl, but it still may have bugs.
so far, only strto(d|ld|f) use the new code. scanf integration will be
done as a separate commit, and i will add implementations of the wide
character functions later.
2012-04-10 11:52:55 -04:00
|
|
|
{
|
|
|
|
uint32_t x = 0;
|
|
|
|
long double y = 0;
|
|
|
|
long double scale = 1;
|
|
|
|
long double bias = 0;
|
|
|
|
int gottail = 0, gotrad = 0, gotdig = 0;
|
|
|
|
long long rp = 0;
|
|
|
|
long long dc = 0;
|
|
|
|
long long e2 = 0;
|
|
|
|
int d;
|
2012-04-10 21:47:37 -04:00
|
|
|
int c;
|
new floating point parser/converter
this version is intended to be fully conformant to the ISO C, POSIX,
and IEEE standards for conversion of decimal/hex floating point
strings to float, double, and long double (ld64 or ld80 only at
present) values. in particular, all results are intended to be rounded
correctly according to the current rounding mode. further, this
implementation aims to set the floating point underflow, overflow, and
inexact flags to reflect the conversion performed.
a moderate amount of testing has been performed (by nsz and myself)
prior to integration of the code in musl, but it still may have bugs.
so far, only strto(d|ld|f) use the new code. scanf integration will be
done as a separate commit, and i will add implementations of the wide
character functions later.
2012-04-10 11:52:55 -04:00
|
|
|
|
2012-04-10 21:47:37 -04:00
|
|
|
c = shgetc(f);
|
new floating point parser/converter
this version is intended to be fully conformant to the ISO C, POSIX,
and IEEE standards for conversion of decimal/hex floating point
strings to float, double, and long double (ld64 or ld80 only at
present) values. in particular, all results are intended to be rounded
correctly according to the current rounding mode. further, this
implementation aims to set the floating point underflow, overflow, and
inexact flags to reflect the conversion performed.
a moderate amount of testing has been performed (by nsz and myself)
prior to integration of the code in musl, but it still may have bugs.
so far, only strto(d|ld|f) use the new code. scanf integration will be
done as a separate commit, and i will add implementations of the wide
character functions later.
2012-04-10 11:52:55 -04:00
|
|
|
|
|
|
|
/* Skip leading zeros */
|
2012-04-10 21:47:37 -04:00
|
|
|
for (; c=='0'; c = shgetc(f)) gotdig = 1;
|
new floating point parser/converter
this version is intended to be fully conformant to the ISO C, POSIX,
and IEEE standards for conversion of decimal/hex floating point
strings to float, double, and long double (ld64 or ld80 only at
present) values. in particular, all results are intended to be rounded
correctly according to the current rounding mode. further, this
implementation aims to set the floating point underflow, overflow, and
inexact flags to reflect the conversion performed.
a moderate amount of testing has been performed (by nsz and myself)
prior to integration of the code in musl, but it still may have bugs.
so far, only strto(d|ld|f) use the new code. scanf integration will be
done as a separate commit, and i will add implementations of the wide
character functions later.
2012-04-10 11:52:55 -04:00
|
|
|
|
|
|
|
if (c=='.') {
|
|
|
|
gotrad = 1;
|
2012-04-10 21:47:37 -04:00
|
|
|
c = shgetc(f);
|
new floating point parser/converter
this version is intended to be fully conformant to the ISO C, POSIX,
and IEEE standards for conversion of decimal/hex floating point
strings to float, double, and long double (ld64 or ld80 only at
present) values. in particular, all results are intended to be rounded
correctly according to the current rounding mode. further, this
implementation aims to set the floating point underflow, overflow, and
inexact flags to reflect the conversion performed.
a moderate amount of testing has been performed (by nsz and myself)
prior to integration of the code in musl, but it still may have bugs.
so far, only strto(d|ld|f) use the new code. scanf integration will be
done as a separate commit, and i will add implementations of the wide
character functions later.
2012-04-10 11:52:55 -04:00
|
|
|
/* Count zeros after the radix point before significand */
|
2012-04-10 21:47:37 -04:00
|
|
|
for (rp=0; c=='0'; c = shgetc(f), rp--) gotdig = 1;
|
new floating point parser/converter
this version is intended to be fully conformant to the ISO C, POSIX,
and IEEE standards for conversion of decimal/hex floating point
strings to float, double, and long double (ld64 or ld80 only at
present) values. in particular, all results are intended to be rounded
correctly according to the current rounding mode. further, this
implementation aims to set the floating point underflow, overflow, and
inexact flags to reflect the conversion performed.
a moderate amount of testing has been performed (by nsz and myself)
prior to integration of the code in musl, but it still may have bugs.
so far, only strto(d|ld|f) use the new code. scanf integration will be
done as a separate commit, and i will add implementations of the wide
character functions later.
2012-04-10 11:52:55 -04:00
|
|
|
}
|
|
|
|
|
2012-04-10 21:47:37 -04:00
|
|
|
for (; c-'0'<10U || (c|32)-'a'<6U || c=='.'; c = shgetc(f)) {
|
new floating point parser/converter
this version is intended to be fully conformant to the ISO C, POSIX,
and IEEE standards for conversion of decimal/hex floating point
strings to float, double, and long double (ld64 or ld80 only at
present) values. in particular, all results are intended to be rounded
correctly according to the current rounding mode. further, this
implementation aims to set the floating point underflow, overflow, and
inexact flags to reflect the conversion performed.
a moderate amount of testing has been performed (by nsz and myself)
prior to integration of the code in musl, but it still may have bugs.
so far, only strto(d|ld|f) use the new code. scanf integration will be
done as a separate commit, and i will add implementations of the wide
character functions later.
2012-04-10 11:52:55 -04:00
|
|
|
if (c=='.') {
|
|
|
|
if (gotrad) break;
|
|
|
|
rp = dc;
|
|
|
|
gotrad = 1;
|
|
|
|
} else {
|
|
|
|
gotdig = 1;
|
|
|
|
if (c > '9') d = (c|32)+10-'a';
|
|
|
|
else d = c-'0';
|
|
|
|
if (dc<8) {
|
|
|
|
x = x*16 + d;
|
|
|
|
} else if (dc < LDBL_MANT_DIG/4+1) {
|
|
|
|
y += d*(scale/=16);
|
|
|
|
} else if (d && !gottail) {
|
|
|
|
y += 0.5*scale;
|
|
|
|
gottail = 1;
|
|
|
|
}
|
|
|
|
dc++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (!gotdig) {
|
2012-04-10 21:47:37 -04:00
|
|
|
shunget(f);
|
|
|
|
if (pok) {
|
|
|
|
shunget(f);
|
|
|
|
if (gotrad) shunget(f);
|
|
|
|
} else {
|
|
|
|
shlim(f, 0);
|
new floating point parser/converter
this version is intended to be fully conformant to the ISO C, POSIX,
and IEEE standards for conversion of decimal/hex floating point
strings to float, double, and long double (ld64 or ld80 only at
present) values. in particular, all results are intended to be rounded
correctly according to the current rounding mode. further, this
implementation aims to set the floating point underflow, overflow, and
inexact flags to reflect the conversion performed.
a moderate amount of testing has been performed (by nsz and myself)
prior to integration of the code in musl, but it still may have bugs.
so far, only strto(d|ld|f) use the new code. scanf integration will be
done as a separate commit, and i will add implementations of the wide
character functions later.
2012-04-10 11:52:55 -04:00
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
if (!gotrad) rp = dc;
|
|
|
|
while (dc<8) x *= 16, dc++;
|
|
|
|
if ((c|32)=='p') {
|
2012-04-10 21:47:37 -04:00
|
|
|
e2 = scanexp(f, pok);
|
new floating point parser/converter
this version is intended to be fully conformant to the ISO C, POSIX,
and IEEE standards for conversion of decimal/hex floating point
strings to float, double, and long double (ld64 or ld80 only at
present) values. in particular, all results are intended to be rounded
correctly according to the current rounding mode. further, this
implementation aims to set the floating point underflow, overflow, and
inexact flags to reflect the conversion performed.
a moderate amount of testing has been performed (by nsz and myself)
prior to integration of the code in musl, but it still may have bugs.
so far, only strto(d|ld|f) use the new code. scanf integration will be
done as a separate commit, and i will add implementations of the wide
character functions later.
2012-04-10 11:52:55 -04:00
|
|
|
if (e2 == LLONG_MIN) {
|
2012-04-10 21:47:37 -04:00
|
|
|
if (pok) {
|
|
|
|
shunget(f);
|
|
|
|
} else {
|
|
|
|
shlim(f, 0);
|
new floating point parser/converter
this version is intended to be fully conformant to the ISO C, POSIX,
and IEEE standards for conversion of decimal/hex floating point
strings to float, double, and long double (ld64 or ld80 only at
present) values. in particular, all results are intended to be rounded
correctly according to the current rounding mode. further, this
implementation aims to set the floating point underflow, overflow, and
inexact flags to reflect the conversion performed.
a moderate amount of testing has been performed (by nsz and myself)
prior to integration of the code in musl, but it still may have bugs.
so far, only strto(d|ld|f) use the new code. scanf integration will be
done as a separate commit, and i will add implementations of the wide
character functions later.
2012-04-10 11:52:55 -04:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
e2 = 0;
|
|
|
|
}
|
2012-04-11 00:18:57 -04:00
|
|
|
} else {
|
|
|
|
shunget(f);
|
new floating point parser/converter
this version is intended to be fully conformant to the ISO C, POSIX,
and IEEE standards for conversion of decimal/hex floating point
strings to float, double, and long double (ld64 or ld80 only at
present) values. in particular, all results are intended to be rounded
correctly according to the current rounding mode. further, this
implementation aims to set the floating point underflow, overflow, and
inexact flags to reflect the conversion performed.
a moderate amount of testing has been performed (by nsz and myself)
prior to integration of the code in musl, but it still may have bugs.
so far, only strto(d|ld|f) use the new code. scanf integration will be
done as a separate commit, and i will add implementations of the wide
character functions later.
2012-04-10 11:52:55 -04:00
|
|
|
}
|
|
|
|
e2 += 4*rp - 32;
|
|
|
|
|
|
|
|
if (!x) return sign * 0.0;
|
2012-04-10 22:38:21 -04:00
|
|
|
if (e2 > -emin) {
|
|
|
|
errno = ERANGE;
|
|
|
|
return sign * LDBL_MAX * LDBL_MAX;
|
|
|
|
}
|
|
|
|
if (e2 < emin-2*LDBL_MANT_DIG) {
|
|
|
|
errno = ERANGE;
|
|
|
|
return sign * LDBL_MIN * LDBL_MIN;
|
|
|
|
}
|
new floating point parser/converter
this version is intended to be fully conformant to the ISO C, POSIX,
and IEEE standards for conversion of decimal/hex floating point
strings to float, double, and long double (ld64 or ld80 only at
present) values. in particular, all results are intended to be rounded
correctly according to the current rounding mode. further, this
implementation aims to set the floating point underflow, overflow, and
inexact flags to reflect the conversion performed.
a moderate amount of testing has been performed (by nsz and myself)
prior to integration of the code in musl, but it still may have bugs.
so far, only strto(d|ld|f) use the new code. scanf integration will be
done as a separate commit, and i will add implementations of the wide
character functions later.
2012-04-10 11:52:55 -04:00
|
|
|
|
|
|
|
while (x < 0x80000000) {
|
|
|
|
if (y>=0.5) {
|
|
|
|
x += x + 1;
|
|
|
|
y += y - 1;
|
|
|
|
} else {
|
|
|
|
x += x;
|
|
|
|
y += y;
|
|
|
|
}
|
|
|
|
e2--;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (bits > 32+e2-emin) {
|
|
|
|
bits = 32+e2-emin;
|
|
|
|
if (bits<0) bits=0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (bits < LDBL_MANT_DIG)
|
|
|
|
bias = copysignl(scalbn(1, 32+LDBL_MANT_DIG-bits-1), sign);
|
|
|
|
|
|
|
|
if (bits<32 && y && !(x&1)) x++, y=0;
|
|
|
|
|
|
|
|
y = bias + sign*(long double)x + sign*y;
|
|
|
|
y -= bias;
|
|
|
|
|
2012-04-10 22:38:21 -04:00
|
|
|
if (!y) errno = ERANGE;
|
|
|
|
|
new floating point parser/converter
this version is intended to be fully conformant to the ISO C, POSIX,
and IEEE standards for conversion of decimal/hex floating point
strings to float, double, and long double (ld64 or ld80 only at
present) values. in particular, all results are intended to be rounded
correctly according to the current rounding mode. further, this
implementation aims to set the floating point underflow, overflow, and
inexact flags to reflect the conversion performed.
a moderate amount of testing has been performed (by nsz and myself)
prior to integration of the code in musl, but it still may have bugs.
so far, only strto(d|ld|f) use the new code. scanf integration will be
done as a separate commit, and i will add implementations of the wide
character functions later.
2012-04-10 11:52:55 -04:00
|
|
|
return scalbnl(y, e2);
|
|
|
|
}
|
|
|
|
|
2012-04-10 21:47:37 -04:00
|
|
|
long double __floatscan(FILE *f, int c, int prec, int pok)
|
new floating point parser/converter
this version is intended to be fully conformant to the ISO C, POSIX,
and IEEE standards for conversion of decimal/hex floating point
strings to float, double, and long double (ld64 or ld80 only at
present) values. in particular, all results are intended to be rounded
correctly according to the current rounding mode. further, this
implementation aims to set the floating point underflow, overflow, and
inexact flags to reflect the conversion performed.
a moderate amount of testing has been performed (by nsz and myself)
prior to integration of the code in musl, but it still may have bugs.
so far, only strto(d|ld|f) use the new code. scanf integration will be
done as a separate commit, and i will add implementations of the wide
character functions later.
2012-04-10 11:52:55 -04:00
|
|
|
{
|
|
|
|
int sign = 1;
|
|
|
|
int i;
|
|
|
|
int bits;
|
|
|
|
int emin;
|
|
|
|
|
|
|
|
switch (prec) {
|
|
|
|
case 0:
|
2012-04-12 00:25:52 -04:00
|
|
|
bits = FLT_MANT_DIG;
|
|
|
|
emin = FLT_MIN_EXP-bits;
|
new floating point parser/converter
this version is intended to be fully conformant to the ISO C, POSIX,
and IEEE standards for conversion of decimal/hex floating point
strings to float, double, and long double (ld64 or ld80 only at
present) values. in particular, all results are intended to be rounded
correctly according to the current rounding mode. further, this
implementation aims to set the floating point underflow, overflow, and
inexact flags to reflect the conversion performed.
a moderate amount of testing has been performed (by nsz and myself)
prior to integration of the code in musl, but it still may have bugs.
so far, only strto(d|ld|f) use the new code. scanf integration will be
done as a separate commit, and i will add implementations of the wide
character functions later.
2012-04-10 11:52:55 -04:00
|
|
|
break;
|
|
|
|
case 1:
|
2012-04-12 00:25:52 -04:00
|
|
|
bits = DBL_MANT_DIG;
|
|
|
|
emin = DBL_MIN_EXP-bits;
|
new floating point parser/converter
this version is intended to be fully conformant to the ISO C, POSIX,
and IEEE standards for conversion of decimal/hex floating point
strings to float, double, and long double (ld64 or ld80 only at
present) values. in particular, all results are intended to be rounded
correctly according to the current rounding mode. further, this
implementation aims to set the floating point underflow, overflow, and
inexact flags to reflect the conversion performed.
a moderate amount of testing has been performed (by nsz and myself)
prior to integration of the code in musl, but it still may have bugs.
so far, only strto(d|ld|f) use the new code. scanf integration will be
done as a separate commit, and i will add implementations of the wide
character functions later.
2012-04-10 11:52:55 -04:00
|
|
|
break;
|
|
|
|
case 2:
|
|
|
|
bits = LDBL_MANT_DIG;
|
2012-04-12 00:25:52 -04:00
|
|
|
emin = LDBL_MIN_EXP-bits;
|
new floating point parser/converter
this version is intended to be fully conformant to the ISO C, POSIX,
and IEEE standards for conversion of decimal/hex floating point
strings to float, double, and long double (ld64 or ld80 only at
present) values. in particular, all results are intended to be rounded
correctly according to the current rounding mode. further, this
implementation aims to set the floating point underflow, overflow, and
inexact flags to reflect the conversion performed.
a moderate amount of testing has been performed (by nsz and myself)
prior to integration of the code in musl, but it still may have bugs.
so far, only strto(d|ld|f) use the new code. scanf integration will be
done as a separate commit, and i will add implementations of the wide
character functions later.
2012-04-10 11:52:55 -04:00
|
|
|
break;
|
|
|
|
default:
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2012-04-10 21:47:37 -04:00
|
|
|
if (c<0) c = shgetc(f);
|
new floating point parser/converter
this version is intended to be fully conformant to the ISO C, POSIX,
and IEEE standards for conversion of decimal/hex floating point
strings to float, double, and long double (ld64 or ld80 only at
present) values. in particular, all results are intended to be rounded
correctly according to the current rounding mode. further, this
implementation aims to set the floating point underflow, overflow, and
inexact flags to reflect the conversion performed.
a moderate amount of testing has been performed (by nsz and myself)
prior to integration of the code in musl, but it still may have bugs.
so far, only strto(d|ld|f) use the new code. scanf integration will be
done as a separate commit, and i will add implementations of the wide
character functions later.
2012-04-10 11:52:55 -04:00
|
|
|
|
|
|
|
if (c=='+' || c=='-') {
|
|
|
|
sign -= 2*(c=='-');
|
2012-04-10 21:47:37 -04:00
|
|
|
c = shgetc(f);
|
new floating point parser/converter
this version is intended to be fully conformant to the ISO C, POSIX,
and IEEE standards for conversion of decimal/hex floating point
strings to float, double, and long double (ld64 or ld80 only at
present) values. in particular, all results are intended to be rounded
correctly according to the current rounding mode. further, this
implementation aims to set the floating point underflow, overflow, and
inexact flags to reflect the conversion performed.
a moderate amount of testing has been performed (by nsz and myself)
prior to integration of the code in musl, but it still may have bugs.
so far, only strto(d|ld|f) use the new code. scanf integration will be
done as a separate commit, and i will add implementations of the wide
character functions later.
2012-04-10 11:52:55 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
for (i=0; i<8 && (c|32)=="infinity"[i]; i++)
|
2012-04-10 21:47:37 -04:00
|
|
|
if (i<7) c = shgetc(f);
|
new floating point parser/converter
this version is intended to be fully conformant to the ISO C, POSIX,
and IEEE standards for conversion of decimal/hex floating point
strings to float, double, and long double (ld64 or ld80 only at
present) values. in particular, all results are intended to be rounded
correctly according to the current rounding mode. further, this
implementation aims to set the floating point underflow, overflow, and
inexact flags to reflect the conversion performed.
a moderate amount of testing has been performed (by nsz and myself)
prior to integration of the code in musl, but it still may have bugs.
so far, only strto(d|ld|f) use the new code. scanf integration will be
done as a separate commit, and i will add implementations of the wide
character functions later.
2012-04-10 11:52:55 -04:00
|
|
|
if (i==3 || i==8 || (i>3 && pok)) {
|
2012-04-10 21:47:37 -04:00
|
|
|
if (i==3) shunget(f);
|
|
|
|
if (pok) for (; i>3; i--) shunget(f);
|
|
|
|
else shlim(f, 0);
|
new floating point parser/converter
this version is intended to be fully conformant to the ISO C, POSIX,
and IEEE standards for conversion of decimal/hex floating point
strings to float, double, and long double (ld64 or ld80 only at
present) values. in particular, all results are intended to be rounded
correctly according to the current rounding mode. further, this
implementation aims to set the floating point underflow, overflow, and
inexact flags to reflect the conversion performed.
a moderate amount of testing has been performed (by nsz and myself)
prior to integration of the code in musl, but it still may have bugs.
so far, only strto(d|ld|f) use the new code. scanf integration will be
done as a separate commit, and i will add implementations of the wide
character functions later.
2012-04-10 11:52:55 -04:00
|
|
|
return sign * INFINITY;
|
|
|
|
}
|
|
|
|
if (!i) for (i=0; i<3 && (c|32)=="nan"[i]; i++)
|
2012-04-10 21:47:37 -04:00
|
|
|
if (i<3) c = shgetc(f);
|
new floating point parser/converter
this version is intended to be fully conformant to the ISO C, POSIX,
and IEEE standards for conversion of decimal/hex floating point
strings to float, double, and long double (ld64 or ld80 only at
present) values. in particular, all results are intended to be rounded
correctly according to the current rounding mode. further, this
implementation aims to set the floating point underflow, overflow, and
inexact flags to reflect the conversion performed.
a moderate amount of testing has been performed (by nsz and myself)
prior to integration of the code in musl, but it still may have bugs.
so far, only strto(d|ld|f) use the new code. scanf integration will be
done as a separate commit, and i will add implementations of the wide
character functions later.
2012-04-10 11:52:55 -04:00
|
|
|
if (i==3) {
|
2012-04-10 21:47:37 -04:00
|
|
|
return NAN;
|
new floating point parser/converter
this version is intended to be fully conformant to the ISO C, POSIX,
and IEEE standards for conversion of decimal/hex floating point
strings to float, double, and long double (ld64 or ld80 only at
present) values. in particular, all results are intended to be rounded
correctly according to the current rounding mode. further, this
implementation aims to set the floating point underflow, overflow, and
inexact flags to reflect the conversion performed.
a moderate amount of testing has been performed (by nsz and myself)
prior to integration of the code in musl, but it still may have bugs.
so far, only strto(d|ld|f) use the new code. scanf integration will be
done as a separate commit, and i will add implementations of the wide
character functions later.
2012-04-10 11:52:55 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
if (i) {
|
2012-04-10 21:47:37 -04:00
|
|
|
shunget(f);
|
2012-04-10 22:38:21 -04:00
|
|
|
errno = EINVAL;
|
2012-04-10 21:47:37 -04:00
|
|
|
shlim(f, 0);
|
new floating point parser/converter
this version is intended to be fully conformant to the ISO C, POSIX,
and IEEE standards for conversion of decimal/hex floating point
strings to float, double, and long double (ld64 or ld80 only at
present) values. in particular, all results are intended to be rounded
correctly according to the current rounding mode. further, this
implementation aims to set the floating point underflow, overflow, and
inexact flags to reflect the conversion performed.
a moderate amount of testing has been performed (by nsz and myself)
prior to integration of the code in musl, but it still may have bugs.
so far, only strto(d|ld|f) use the new code. scanf integration will be
done as a separate commit, and i will add implementations of the wide
character functions later.
2012-04-10 11:52:55 -04:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (c=='0') {
|
2012-04-10 21:47:37 -04:00
|
|
|
c = shgetc(f);
|
new floating point parser/converter
this version is intended to be fully conformant to the ISO C, POSIX,
and IEEE standards for conversion of decimal/hex floating point
strings to float, double, and long double (ld64 or ld80 only at
present) values. in particular, all results are intended to be rounded
correctly according to the current rounding mode. further, this
implementation aims to set the floating point underflow, overflow, and
inexact flags to reflect the conversion performed.
a moderate amount of testing has been performed (by nsz and myself)
prior to integration of the code in musl, but it still may have bugs.
so far, only strto(d|ld|f) use the new code. scanf integration will be
done as a separate commit, and i will add implementations of the wide
character functions later.
2012-04-10 11:52:55 -04:00
|
|
|
if ((c|32) == 'x')
|
2012-04-10 21:47:37 -04:00
|
|
|
return hexfloat(f, bits, emin, sign, pok);
|
2012-04-11 00:18:57 -04:00
|
|
|
shunget(f);
|
new floating point parser/converter
this version is intended to be fully conformant to the ISO C, POSIX,
and IEEE standards for conversion of decimal/hex floating point
strings to float, double, and long double (ld64 or ld80 only at
present) values. in particular, all results are intended to be rounded
correctly according to the current rounding mode. further, this
implementation aims to set the floating point underflow, overflow, and
inexact flags to reflect the conversion performed.
a moderate amount of testing has been performed (by nsz and myself)
prior to integration of the code in musl, but it still may have bugs.
so far, only strto(d|ld|f) use the new code. scanf integration will be
done as a separate commit, and i will add implementations of the wide
character functions later.
2012-04-10 11:52:55 -04:00
|
|
|
c = '0';
|
|
|
|
}
|
|
|
|
|
2012-04-11 00:18:57 -04:00
|
|
|
return decfloat(f, c, bits, emin, sign, pok);
|
new floating point parser/converter
this version is intended to be fully conformant to the ISO C, POSIX,
and IEEE standards for conversion of decimal/hex floating point
strings to float, double, and long double (ld64 or ld80 only at
present) values. in particular, all results are intended to be rounded
correctly according to the current rounding mode. further, this
implementation aims to set the floating point underflow, overflow, and
inexact flags to reflect the conversion performed.
a moderate amount of testing has been performed (by nsz and myself)
prior to integration of the code in musl, but it still may have bugs.
so far, only strto(d|ld|f) use the new code. scanf integration will be
done as a separate commit, and i will add implementations of the wide
character functions later.
2012-04-10 11:52:55 -04:00
|
|
|
}
|