diff options
| author | Andrew Kelley <andrew@ziglang.org> | 2019-03-23 13:46:50 -0400 |
|---|---|---|
| committer | Andrew Kelley <andrew@ziglang.org> | 2019-03-23 13:46:50 -0400 |
| commit | 14d416f83b4dabeb714d7001f6efa4fcbac180d5 (patch) | |
| tree | 371888af9ae971b839a0f7af51a6d2fd49385206 /src/parse_f128.c | |
| parent | d83836825f1d386e0872fd87bacfaa6f545783a9 (diff) | |
| download | zig-14d416f83b4dabeb714d7001f6efa4fcbac180d5.tar.gz zig-14d416f83b4dabeb714d7001f6efa4fcbac180d5.zip | |
parse_f128.c: fix whitespace
Diffstat (limited to 'src/parse_f128.c')
| -rw-r--r-- | src/parse_f128.c | 1244 |
1 files changed, 622 insertions, 622 deletions
diff --git a/src/parse_f128.c b/src/parse_f128.c index acaf0a5ce0..cffb3796b4 100644 --- a/src/parse_f128.c +++ b/src/parse_f128.c @@ -16,7 +16,7 @@ #define shunget(f) ((f)->shlim>=0 ? (void)(f)->rpos-- : (void)0) #define sh_fromstring(f, s) \ - ((f)->buf = (f)->rpos = (void *)(s), (f)->rend = (void*)-1) + ((f)->buf = (f)->rpos = (void *)(s), (f)->rend = (void*)-1) #define LD_B1B_DIG 4 #define LD_B1B_MAX 10384593, 717069655, 257060992, 658440191 @@ -50,147 +50,147 @@ #if __BYTE_ORDER == __LITTLE_ENDIAN union ldshape { - float128_t f; - struct { - uint64_t lo; - uint32_t mid; - uint16_t top; - uint16_t se; - } i; - struct { - uint64_t lo; - uint64_t hi; - } i2; + float128_t f; + struct { + uint64_t lo; + uint32_t mid; + uint16_t top; + uint16_t se; + } i; + struct { + uint64_t lo; + uint64_t hi; + } i2; }; #elif __BYTE_ORDER == __BIG_ENDIAN union ldshape { - float128_t f; - struct { - uint16_t se; - uint16_t top; - uint32_t mid; - uint64_t lo; - } i; - struct { - uint64_t hi; - uint64_t lo; - } i2; + float128_t f; + struct { + uint16_t se; + uint16_t top; + uint32_t mid; + uint64_t lo; + } i; + struct { + uint64_t hi; + uint64_t lo; + } i2; }; #error Unsupported endian #endif struct MuslFILE { - unsigned flags; - unsigned char *rpos, *rend; - int (*close)(struct MuslFILE *); - unsigned char *wend, *wpos; - unsigned char *mustbezero_1; - unsigned char *wbase; - size_t (*read)(struct MuslFILE *, unsigned char *, size_t); - size_t (*write)(struct MuslFILE *, const unsigned char *, size_t); - off_t (*seek)(struct MuslFILE *, off_t, int); - unsigned char *buf; - size_t buf_size; - struct MuslFILE *prev, *next; - int fd; - int pipe_pid; - long lockcount; - int mode; - volatile int lock; - int lbf; - void *cookie; - off_t off; - char *getln_buf; - void *mustbezero_2; - unsigned char *shend; - off_t shlim, shcnt; - struct MuslFILE *prev_locked, *next_locked; - struct __locale_struct *locale; + unsigned flags; + unsigned char *rpos, *rend; + int (*close)(struct MuslFILE *); + unsigned char *wend, *wpos; + unsigned char *mustbezero_1; + unsigned char *wbase; + size_t (*read)(struct MuslFILE *, unsigned char *, size_t); + size_t (*write)(struct MuslFILE *, const unsigned char *, size_t); + off_t (*seek)(struct MuslFILE *, off_t, int); + unsigned char *buf; + size_t buf_size; + struct MuslFILE *prev, *next; + int fd; + int pipe_pid; + long lockcount; + int mode; + volatile int lock; + int lbf; + void *cookie; + off_t off; + char *getln_buf; + void *mustbezero_2; + unsigned char *shend; + off_t shlim, shcnt; + struct MuslFILE *prev_locked, *next_locked; + struct __locale_struct *locale; }; static void __shlim(struct MuslFILE *f, off_t lim) { - f->shlim = lim; - f->shcnt = f->buf - f->rpos; - /* If lim is nonzero, rend must be a valid pointer. */ - if (lim && f->rend - f->rpos > lim) - f->shend = f->rpos + lim; - else - f->shend = f->rend; + f->shlim = lim; + f->shcnt = f->buf - f->rpos; + /* If lim is nonzero, rend must be a valid pointer. */ + if (lim && f->rend - f->rpos > lim) + f->shend = f->rpos + lim; + else + f->shend = f->rend; } static int __toread(struct MuslFILE *f) { - f->mode |= f->mode-1; - if (f->wpos != f->wbase) f->write(f, 0, 0); - f->wpos = f->wbase = f->wend = 0; - if (f->flags & F_NORD) { - f->flags |= F_ERR; - return EOF; - } - f->rpos = f->rend = f->buf + f->buf_size; - return (f->flags & F_EOF) ? EOF : 0; + f->mode |= f->mode-1; + if (f->wpos != f->wbase) f->write(f, 0, 0); + f->wpos = f->wbase = f->wend = 0; + if (f->flags & F_NORD) { + f->flags |= F_ERR; + return EOF; + } + f->rpos = f->rend = f->buf + f->buf_size; + return (f->flags & F_EOF) ? EOF : 0; } static int __uflow(struct MuslFILE *f) { - unsigned char c; - if (!__toread(f) && f->read(f, &c, 1)==1) return c; - return EOF; + unsigned char c; + if (!__toread(f) && f->read(f, &c, 1)==1) return c; + return EOF; } static int __shgetc(struct MuslFILE *f) { - int c; - off_t cnt = shcnt(f); - if ((f->shlim && cnt >= f->shlim) || (c=__uflow(f)) < 0) { - f->shcnt = f->buf - f->rpos + cnt; - f->shend = f->rpos; - f->shlim = -1; - return EOF; - } - cnt++; - if (f->shlim && f->rend - f->rpos > f->shlim - cnt) - f->shend = f->rpos + (f->shlim - cnt); - else - f->shend = f->rend; - f->shcnt = f->buf - f->rpos + cnt; - if (f->rpos[-1] != c) f->rpos[-1] = c; - return c; + int c; + off_t cnt = shcnt(f); + if ((f->shlim && cnt >= f->shlim) || (c=__uflow(f)) < 0) { + f->shcnt = f->buf - f->rpos + cnt; + f->shend = f->rpos; + f->shlim = -1; + return EOF; + } + cnt++; + if (f->shlim && f->rend - f->rpos > f->shlim - cnt) + f->shend = f->rpos + (f->shlim - cnt); + else + f->shend = f->rend; + f->shcnt = f->buf - f->rpos + cnt; + if (f->rpos[-1] != c) f->rpos[-1] = c; + return c; } static long long scanexp(struct MuslFILE *f, int pok) { - int c; - int x; - long long y; - int neg = 0; - - c = shgetc(f); - if (c=='+' || c=='-') { - neg = (c=='-'); - c = shgetc(f); - if (c-'0'>=10U && pok) shunget(f); - } - if (c-'0'>=10U) { - shunget(f); - return LLONG_MIN; - } - for (x=0; c-'0'<10U && x<INT_MAX/10; c = shgetc(f)) - x = 10*x + c-'0'; - for (y=x; c-'0'<10U && y<LLONG_MAX/100; c = shgetc(f)) - y = 10*y + c-'0'; - for (; c-'0'<10U; c = shgetc(f)); - shunget(f); - return neg ? -y : y; + int c; + int x; + long long y; + int neg = 0; + + c = shgetc(f); + if (c=='+' || c=='-') { + neg = (c=='-'); + c = shgetc(f); + if (c-'0'>=10U && pok) shunget(f); + } + if (c-'0'>=10U) { + shunget(f); + return LLONG_MIN; + } + for (x=0; c-'0'<10U && x<INT_MAX/10; c = shgetc(f)) + x = 10*x + c-'0'; + for (y=x; c-'0'<10U && y<LLONG_MAX/100; c = shgetc(f)) + y = 10*y + c-'0'; + for (; c-'0'<10U; c = shgetc(f)); + shunget(f); + return neg ? -y : y; } static float128_t copysignf128(float128_t x, float128_t y) { - union ldshape ux = {x}, uy = {y}; - ux.i.se &= 0x7fff; - ux.i.se |= uy.i.se & 0x8000; - return ux.f; + union ldshape ux = {x}, uy = {y}; + ux.i.se &= 0x7fff; + ux.i.se |= uy.i.se & 0x8000; + return ux.f; } static void mul_eq_f128_float(float128_t *x, float op_float) { @@ -214,101 +214,101 @@ static float128_t dbl_to_f128(double x) { static float128_t fmodf128(float128_t x, float128_t y) { - union ldshape ux = {x}, uy = {y}; - int ex = ux.i.se & 0x7fff; - int ey = uy.i.se & 0x7fff; - int sx = ux.i.se & 0x8000; + union ldshape ux = {x}, uy = {y}; + int ex = ux.i.se & 0x7fff; + int ey = uy.i.se & 0x7fff; + int sx = ux.i.se & 0x8000; float128_t zero; ui32_to_f128M(0, &zero); // if (y == 0 || isnan(y) || ex == 0x7fff) - if (f128M_eq(&y, &zero) || f128M_isSignalingNaN(&y) || ex == 0x7fff) { - //return (x*y)/(x*y); + if (f128M_eq(&y, &zero) || f128M_isSignalingNaN(&y) || ex == 0x7fff) { + //return (x*y)/(x*y); float128_t x_times_y; f128M_mul(&x, &y, &x_times_y); float128_t result; f128M_div(&x_times_y, &x_times_y, &result); return result; } - ux.i.se = ex; - uy.i.se = ey; - //if (ux.f <= uy.f) { + ux.i.se = ex; + uy.i.se = ey; + //if (ux.f <= uy.f) { if (f128M_le(&ux.f, &uy.f)) { - //if (ux.f == uy.f) { - if (f128M_eq(&ux.f, &uy.f)) { - //return 0*x; + //if (ux.f == uy.f) { + if (f128M_eq(&ux.f, &uy.f)) { + //return 0*x; float128_t result; f128M_mul(&zero, &x, &result); return result; } - return x; - } + return x; + } - /* normalize x and y */ - if (!ex) { - //ux.f *= 0x1p120f; + /* normalize x and y */ + if (!ex) { + //ux.f *= 0x1p120f; mul_eq_f128_float(&ux.f, 0x1p120f); - ex = ux.i.se - 120; - } - if (!ey) { - //uy.f *= 0x1p120f; + ex = ux.i.se - 120; + } + if (!ey) { + //uy.f *= 0x1p120f; mul_eq_f128_float(&uy.f, 0x1p120f); - ey = uy.i.se - 120; - } - - /* x mod y */ - uint64_t hi, lo, xhi, xlo, yhi, ylo; - xhi = (ux.i2.hi & -1ULL>>16) | 1ULL<<48; - yhi = (uy.i2.hi & -1ULL>>16) | 1ULL<<48; - xlo = ux.i2.lo; - ylo = uy.i2.lo; - for (; ex > ey; ex--) { - hi = xhi - yhi; - lo = xlo - ylo; - if (xlo < ylo) - hi -= 1; - if (hi >> 63 == 0) { - if ((hi|lo) == 0) { - //return 0*x; + ey = uy.i.se - 120; + } + + /* x mod y */ + uint64_t hi, lo, xhi, xlo, yhi, ylo; + xhi = (ux.i2.hi & -1ULL>>16) | 1ULL<<48; + yhi = (uy.i2.hi & -1ULL>>16) | 1ULL<<48; + xlo = ux.i2.lo; + ylo = uy.i2.lo; + for (; ex > ey; ex--) { + hi = xhi - yhi; + lo = xlo - ylo; + if (xlo < ylo) + hi -= 1; + if (hi >> 63 == 0) { + if ((hi|lo) == 0) { + //return 0*x; float128_t result; f128M_mul(&zero, &x, &result); return result; } - xhi = 2*hi + (lo>>63); - xlo = 2*lo; - } else { - xhi = 2*xhi + (xlo>>63); - xlo = 2*xlo; - } - } - hi = xhi - yhi; - lo = xlo - ylo; - if (xlo < ylo) - hi -= 1; - if (hi >> 63 == 0) { - if ((hi|lo) == 0) { - //return 0*x; + xhi = 2*hi + (lo>>63); + xlo = 2*lo; + } else { + xhi = 2*xhi + (xlo>>63); + xlo = 2*xlo; + } + } + hi = xhi - yhi; + lo = xlo - ylo; + if (xlo < ylo) + hi -= 1; + if (hi >> 63 == 0) { + if ((hi|lo) == 0) { + //return 0*x; float128_t result; f128M_mul(&zero, &x, &result); return result; } - xhi = hi; - xlo = lo; - } - for (; xhi >> 48 == 0; xhi = 2*xhi + (xlo>>63), xlo = 2*xlo, ex--); - ux.i2.hi = xhi; - ux.i2.lo = xlo; - - /* scale result */ - if (ex <= 0) { - ux.i.se = (ex+120)|sx; - //ux.f *= 0x1p-120f; - mul_eq_f128_float(&ux.f, 0x1p-120f); - } else - ux.i.se = ex|sx; - return ux.f; + xhi = hi; + xlo = lo; + } + for (; xhi >> 48 == 0; xhi = 2*xhi + (xlo>>63), xlo = 2*xlo, ex--); + ux.i2.hi = xhi; + ux.i2.lo = xlo; + + /* scale result */ + if (ex <= 0) { + ux.i.se = (ex+120)|sx; + //ux.f *= 0x1p-120f; + mul_eq_f128_float(&ux.f, 0x1p-120f); + } else + ux.i.se = ex|sx; + return ux.f; } static float128_t int_mul_f128_cast_u32(int sign, uint32_t x0) { @@ -348,7 +348,7 @@ static void mul_eq_f128_int(float128_t *y, int sign) { } static float128_t make_f128(uint64_t hi, uint64_t lo) { - union ldshape ux; + union ldshape ux; ux.i2.hi = hi; ux.i2.lo = lo; return ux.f; @@ -374,21 +374,21 @@ static void add_eq_f128_dbl(float128_t *a, double b) { static float128_t scalbnf128(float128_t x, int n) { - union ldshape u; + union ldshape u; - if (n > 16383) { - //x *= 0x1p16383q; + if (n > 16383) { + //x *= 0x1p16383q; mul_eq_f128_f128(&x, make_f128(0x7ffe000000000000, 0x0000000000000000)); - n -= 16383; - if (n > 16383) { - //x *= 0x1p16383q; + n -= 16383; + if (n > 16383) { + //x *= 0x1p16383q; mul_eq_f128_f128(&x, make_f128(0x7ffe000000000000, 0x0000000000000000)); - n -= 16383; - if (n > 16383) - n = 16383; - } - } else if (n < -16382) { - //x *= 0x1p-16382q * 0x1p113q; + n -= 16383; + if (n > 16383) + n = 16383; + } + } else if (n < -16382) { + //x *= 0x1p-16382q * 0x1p113q; { float128_t mul_result; float128_t a = make_f128(0x0001000000000000, 0x0000000000000000); @@ -396,9 +396,9 @@ static float128_t scalbnf128(float128_t x, int n) f128M_mul(&a, &b, &mul_result); mul_eq_f128_f128(&x, mul_result); } - n += 16382 - 113; - if (n < -16382) { - //x *= 0x1p-16382q * 0x1p113q; + n += 16382 - 113; + if (n < -16382) { + //x *= 0x1p-16382q * 0x1p113q; { float128_t mul_result; float128_t a = make_f128(0x0001000000000000, 0x0000000000000000); @@ -406,113 +406,113 @@ static float128_t scalbnf128(float128_t x, int n) f128M_mul(&a, &b, &mul_result); mul_eq_f128_f128(&x, mul_result); } - n += 16382 - 113; - if (n < -16382) - n = -16382; - } - } - //u.f = 1.0; + n += 16382 - 113; + if (n < -16382) + n = -16382; + } + } + //u.f = 1.0; ui32_to_f128M(1, &u.f); - u.i.se = 0x3fff + n; + u.i.se = 0x3fff + n; mul_eq_f128_f128(&x, u.f); return x; } static float128_t fabsf128(float128_t x) { - union ldshape u = {x}; + union ldshape u = {x}; - u.i.se &= 0x7fff; - return u.f; + u.i.se &= 0x7fff; + return u.f; } static float128_t decfloat(struct MuslFILE *f, int c, int bits, int emin, int sign, int pok) { - uint32_t x[KMAX]; - static const uint32_t th[] = { LD_B1B_MAX }; - int i, j, k, a, z; - long long lrp=0, dc=0; - long long e10=0; - int lnz = 0; - int gotdig = 0, gotrad = 0; - int rp; - int e2; - int emax = -emin-bits+3; - int denormal = 0; - float128_t y; + uint32_t x[KMAX]; + static const uint32_t th[] = { LD_B1B_MAX }; + int i, j, k, a, z; + long long lrp=0, dc=0; + long long e10=0; + int lnz = 0; + int gotdig = 0, gotrad = 0; + int rp; + int e2; + int emax = -emin-bits+3; + int denormal = 0; + float128_t y; float128_t zero; ui32_to_f128M(0, &zero); - float128_t frac=zero; - float128_t bias=zero; - static const int p10s[] = { 10, 100, 1000, 10000, - 100000, 1000000, 10000000, 100000000 }; - - j=0; - k=0; - - /* Don't let leading zeros consume buffer space */ - for (; c=='0'; c = shgetc(f)) gotdig=1; - if (c=='.') { - gotrad = 1; - for (c = shgetc(f); c=='0'; c = shgetc(f)) gotdig=1, lrp--; - } - - x[0] = 0; - for (; c-'0'<10U || c=='.'; c = shgetc(f)) { - if (c == '.') { - if (gotrad) break; - gotrad = 1; - lrp = dc; - } else if (k < KMAX-3) { - dc++; - if (c!='0') lnz = dc; - if (j) x[k] = x[k]*10 + c-'0'; - else x[k] = c-'0'; - if (++j==9) { - k++; - j=0; - } - gotdig=1; - } else { - dc++; - if (c!='0') { - lnz = (KMAX-4)*9; - x[KMAX-4] |= 1; - } - } - } - if (!gotrad) lrp=dc; - - if (gotdig && (c|32)=='e') { - e10 = scanexp(f, pok); - if (e10 == LLONG_MIN) { - if (pok) { - shunget(f); - } else { - shlim(f, 0); - return zero; - } - e10 = 0; - } - lrp += e10; - } else if (c>=0) { - shunget(f); - } - if (!gotdig) { - errno = EINVAL; - shlim(f, 0); - return zero; - } - - /* Handle zero specially to avoid nasty special cases later */ - if (!x[0]) { + float128_t frac=zero; + float128_t bias=zero; + static const int p10s[] = { 10, 100, 1000, 10000, + 100000, 1000000, 10000000, 100000000 }; + + j=0; + k=0; + + /* Don't let leading zeros consume buffer space */ + for (; c=='0'; c = shgetc(f)) gotdig=1; + if (c=='.') { + gotrad = 1; + for (c = shgetc(f); c=='0'; c = shgetc(f)) gotdig=1, lrp--; + } + + x[0] = 0; + for (; c-'0'<10U || c=='.'; c = shgetc(f)) { + if (c == '.') { + if (gotrad) break; + gotrad = 1; + lrp = dc; + } else if (k < KMAX-3) { + dc++; + if (c!='0') lnz = dc; + if (j) x[k] = x[k]*10 + c-'0'; + else x[k] = c-'0'; + if (++j==9) { + k++; + j=0; + } + gotdig=1; + } else { + dc++; + if (c!='0') { + lnz = (KMAX-4)*9; + x[KMAX-4] |= 1; + } + } + } + if (!gotrad) lrp=dc; + + if (gotdig && (c|32)=='e') { + e10 = scanexp(f, pok); + if (e10 == LLONG_MIN) { + if (pok) { + shunget(f); + } else { + shlim(f, 0); + return zero; + } + e10 = 0; + } + lrp += e10; + } else if (c>=0) { + shunget(f); + } + if (!gotdig) { + errno = EINVAL; + shlim(f, 0); + return zero; + } + + /* Handle zero specially to avoid nasty special cases later */ + if (!x[0]) { //return sign * 0.0; return dbl_to_f128(sign * 0.0); } - /* Optimize small integers (w/no exponent) and over/under-flow */ - if (lrp==dc && dc<10 && (bits>30 || x[0]>>bits==0)) { - //return sign * (float128_t)x[0]; + /* Optimize small integers (w/no exponent) and over/under-flow */ + if (lrp==dc && dc<10 && (bits>30 || x[0]>>bits==0)) { + //return sign * (float128_t)x[0]; float128_t sign_f128; i32_to_f128M(sign, &sign_f128); float128_t x0_f128; @@ -521,131 +521,131 @@ static float128_t decfloat(struct MuslFILE *f, int c, int bits, int emin, int si f128M_mul(&sign_f128, &x0_f128, &result); return result; } - if (lrp > -emin/2) { - errno = ERANGE; - //return sign * LDBL_MAX * LDBL_MAX; - return zero; - } - if (lrp < emin-2*LDBL_MANT_DIG) { - errno = ERANGE; - //return sign * LDBL_MIN * LDBL_MIN; - return zero; - } - - /* Align incomplete final B1B digit */ - if (j) { - for (; j<9; j++) x[k]*=10; - k++; - j=0; - } - - a = 0; - z = k; - e2 = 0; - rp = lrp; - - /* Optimize small to mid-size integers (even in exp. notation) */ - if (lnz<9 && lnz<=rp && rp < 18) { - if (rp == 9) { + if (lrp > -emin/2) { + errno = ERANGE; + //return sign * LDBL_MAX * LDBL_MAX; + return zero; + } + if (lrp < emin-2*LDBL_MANT_DIG) { + errno = ERANGE; + //return sign * LDBL_MIN * LDBL_MIN; + return zero; + } + + /* Align incomplete final B1B digit */ + if (j) { + for (; j<9; j++) x[k]*=10; + k++; + j=0; + } + + a = 0; + z = k; + e2 = 0; + rp = lrp; + + /* Optimize small to mid-size integers (even in exp. notation) */ + if (lnz<9 && lnz<=rp && rp < 18) { + if (rp == 9) { //return sign * (float128_t)(x[0]); return int_mul_f128_cast_u32(sign, x[0]); } - if (rp < 9) { + if (rp < 9) { //return sign * (float128_t)(x[0]) / p10s[8-rp]; return triple_divide(sign, x[0], p10s[8-rp]); } - int bitlim = bits-3*(int)(rp-9); - if (bitlim>30 || x[0]>>bitlim==0) - //return sign * (float128_t)(x[0]) * p10s[rp-10]; - return triple_multiply(sign, x[0], p10s[rp-10]); - } - - /* Drop trailing zeros */ - for (; !x[z-1]; z--); - - /* Align radix point to B1B digit boundary */ - if (rp % 9) { - int rpm9 = rp>=0 ? rp%9 : rp%9+9; - int p10 = p10s[8-rpm9]; - uint32_t carry = 0; - for (k=a; k!=z; k++) { - 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; - } - } - if (carry) x[z++] = carry; - rp += 9-rpm9; - } - - /* Upscale until desired number of bits are left of radix point */ - while (rp < 9*LD_B1B_DIG || (rp == 9*LD_B1B_DIG && x[a]<th[0])) { - 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; - a = (a-1 & MASK); - if (a == z) { - z = (z-1 & MASK); - x[z-1 & MASK] |= x[z]; - } - x[a] = carry; - } - } - - /* Downscale until exactly number of bits are left of radix point */ - 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; - for (k=a; k!=z; k=(k+1 & MASK)) { - 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); - i--; - rp -= 9; - } - } - if (carry) { - if ((z+1 & MASK) != a) { - x[z] = carry; - z = (z+1 & MASK); - } else x[z-1 & MASK] |= 1; - } - } - - /* Assemble desired bits into floating point variable */ - for (y=zero,i=0; i<LD_B1B_DIG; i++) { - if ((a+i & MASK)==z) x[(z=(z+1 & MASK))-1] = 0; - //y = 1000000000.0L * y + x[a+i & MASK]; + int bitlim = bits-3*(int)(rp-9); + if (bitlim>30 || x[0]>>bitlim==0) + //return sign * (float128_t)(x[0]) * p10s[rp-10]; + return triple_multiply(sign, x[0], p10s[rp-10]); + } + + /* Drop trailing zeros */ + for (; !x[z-1]; z--); + + /* Align radix point to B1B digit boundary */ + if (rp % 9) { + int rpm9 = rp>=0 ? rp%9 : rp%9+9; + int p10 = p10s[8-rpm9]; + uint32_t carry = 0; + for (k=a; k!=z; k++) { + 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; + } + } + if (carry) x[z++] = carry; + rp += 9-rpm9; + } + + /* Upscale until desired number of bits are left of radix point */ + while (rp < 9*LD_B1B_DIG || (rp == 9*LD_B1B_DIG && x[a]<th[0])) { + 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; + a = (a-1 & MASK); + if (a == z) { + z = (z-1 & MASK); + x[z-1 & MASK] |= x[z]; + } + x[a] = carry; + } + } + + /* Downscale until exactly number of bits are left of radix point */ + 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; + for (k=a; k!=z; k=(k+1 & MASK)) { + 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); + i--; + rp -= 9; + } + } + if (carry) { + if ((z+1 & MASK) != a) { + x[z] = carry; + z = (z+1 & MASK); + } else x[z-1 & MASK] |= 1; + } + } + + /* Assemble desired bits into floating point variable */ + for (y=zero,i=0; i<LD_B1B_DIG; i++) { + if ((a+i & MASK)==z) x[(z=(z+1 & MASK))-1] = 0; + //y = 1000000000.0L * y + x[a+i & MASK]; float128_t const_f128; ui64_to_f128M(1000000000, &const_f128); float128_t mul_y; @@ -653,56 +653,56 @@ static float128_t decfloat(struct MuslFILE *f, int c, int bits, int emin, int si float128_t x_f128; ui32_to_f128M(x[a+i & MASK], &x_f128); f128M_add(&mul_y, &x_f128, &y); - } + } - //y *= sign; + //y *= sign; mul_eq_f128_int(&y, sign); - /* Limit precision for denormal results */ - if (bits > LDBL_MANT_DIG+e2-emin) { - bits = LDBL_MANT_DIG+e2-emin; - if (bits<0) bits=0; - denormal = 1; - } - - /* Calculate bias term to force rounding, move out lower bits */ - if (bits < LDBL_MANT_DIG) { - bias = copysignf128(dbl_to_f128(scalbn(1, 2*LDBL_MANT_DIG-bits-1)), y); - frac = fmodf128(y, dbl_to_f128(scalbn(1, LDBL_MANT_DIG-bits))); - //y -= frac; + /* Limit precision for denormal results */ + if (bits > LDBL_MANT_DIG+e2-emin) { + bits = LDBL_MANT_DIG+e2-emin; + if (bits<0) bits=0; + denormal = 1; + } + + /* Calculate bias term to force rounding, move out lower bits */ + if (bits < LDBL_MANT_DIG) { + bias = copysignf128(dbl_to_f128(scalbn(1, 2*LDBL_MANT_DIG-bits-1)), y); + frac = fmodf128(y, dbl_to_f128(scalbn(1, LDBL_MANT_DIG-bits))); + //y -= frac; { float128_t new_value; f128M_sub(&y, &frac, &new_value); y = new_value; } - //y += bias; + //y += bias; { float128_t new_value; f128M_add(&y, &frac, &new_value); y = new_value; } - } + } - /* Process tail of decimal input so it can affect rounding */ - 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; + /* Process tail of decimal input so it can affect rounding */ + 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; add_eq_f128_dbl(&frac, 0.25*sign); } else if (t > 500000000) { - //frac += 0.75*sign; + //frac += 0.75*sign; add_eq_f128_dbl(&frac, 0.75*sign); } else if (t == 500000000) { - if ((a+i+1 & MASK) == z) { - //frac += 0.5*sign; + if ((a+i+1 & MASK) == z) { + //frac += 0.5*sign; add_eq_f128_dbl(&frac, 0.5*sign); } else { - //frac += 0.75*sign; + //frac += 0.75*sign; add_eq_f128_dbl(&frac, 0.75*sign); } - } - //if (LDBL_MANT_DIG-bits >= 2 && !fmodf128(frac, 1)) - if (LDBL_MANT_DIG-bits >= 2) { + } + //if (LDBL_MANT_DIG-bits >= 2 && !fmodf128(frac, 1)) + if (LDBL_MANT_DIG-bits >= 2) { float128_t one; ui32_to_f128M(1, &one); float128_t mod_result = fmodf128(frac, one); @@ -711,29 +711,29 @@ static float128_t decfloat(struct MuslFILE *f, int c, int bits, int emin, int si add_eq_f128_dbl(&frac, 1.0); } } - } + } - //y += frac; + //y += frac; { float128_t new_value; f128M_add(&y, &frac, &new_value); y = new_value; } - //y -= bias; + //y -= bias; { float128_t new_value; f128M_sub(&y, &bias, &new_value); y = new_value; } - if ((e2+LDBL_MANT_DIG & INT_MAX) > emax-5) { - //if (fabsf128(y) >= 0x1p113) + if ((e2+LDBL_MANT_DIG & INT_MAX) > emax-5) { + //if (fabsf128(y) >= 0x1p113) float128_t abs_y = fabsf128(y); float128_t mant_f128 = make_f128(0x4070000000000000, 0x0000000000000000); - if (!f128M_lt(&abs_y, &mant_f128)) { - if (denormal && bits==LDBL_MANT_DIG+e2-emin) - denormal = 0; - //y *= 0.5; + if (!f128M_lt(&abs_y, &mant_f128)) { + if (denormal && bits==LDBL_MANT_DIG+e2-emin) + denormal = 0; + //y *= 0.5; { float128_t point_5 = dbl_to_f128(0.5); float128_t new_value; @@ -741,13 +741,13 @@ static float128_t decfloat(struct MuslFILE *f, int c, int bits, int emin, int si y = new_value; } - e2++; - } - if (e2+LDBL_MANT_DIG>emax || (denormal && !f128M_eq(&frac, &zero))) - errno = ERANGE; - } + e2++; + } + if (e2+LDBL_MANT_DIG>emax || (denormal && !f128M_eq(&frac, &zero))) + errno = ERANGE; + } - return scalbnf128(y, e2); + return scalbnf128(y, e2); } static float128_t hexfloat(struct MuslFILE *f, int bits, int emin, int sign, int pok) @@ -760,42 +760,42 @@ static float128_t hexfloat(struct MuslFILE *f, int bits, int emin, int sign, int ui32_to_f128M(16, &sixteen); float128_t point_5 = dbl_to_f128(0.5); - uint32_t x = 0; - float128_t y = zero; - float128_t scale = one; - float128_t bias = zero; - int gottail = 0, gotrad = 0, gotdig = 0; - long long rp = 0; - long long dc = 0; - long long e2 = 0; - int d; - int c; - - c = shgetc(f); - - /* Skip leading zeros */ - for (; c=='0'; c = shgetc(f)) gotdig = 1; - - if (c=='.') { - gotrad = 1; - c = shgetc(f); - /* Count zeros after the radix point before significand */ - for (rp=0; c=='0'; c = shgetc(f), rp--) gotdig = 1; - } - - for (; c-'0'<10U || (c|32)-'a'<6U || c=='.'; c = shgetc(f)) { - 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); + uint32_t x = 0; + float128_t y = zero; + float128_t scale = one; + float128_t bias = zero; + int gottail = 0, gotrad = 0, gotdig = 0; + long long rp = 0; + long long dc = 0; + long long e2 = 0; + int d; + int c; + + c = shgetc(f); + + /* Skip leading zeros */ + for (; c=='0'; c = shgetc(f)) gotdig = 1; + + if (c=='.') { + gotrad = 1; + c = shgetc(f); + /* Count zeros after the radix point before significand */ + for (rp=0; c=='0'; c = shgetc(f), rp--) gotdig = 1; + } + + for (; c-'0'<10U || (c|32)-'a'<6U || c=='.'; c = shgetc(f)) { + 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); { float128_t divided; f128M_div(&scale, &sixteen, ÷d); @@ -808,8 +808,8 @@ static float128_t hexfloat(struct MuslFILE *f, int bits, int emin, int sign, int f128M_add(&y, &add_op, &new_y); y = new_y; } - } else if (d && !gottail) { - //y += 0.5*scale; + } else if (d && !gottail) { + //y += 0.5*scale; { float128_t add_op; f128M_mul(&point_5, &scale, &add_op); @@ -817,60 +817,60 @@ static float128_t hexfloat(struct MuslFILE *f, int bits, int emin, int sign, int f128M_add(&y, &add_op, &new_y); y = new_y; } - gottail = 1; - } - dc++; - } - } - if (!gotdig) { - shunget(f); - if (pok) { - shunget(f); - if (gotrad) shunget(f); - } else { - shlim(f, 0); - } - //return sign * 0.0; + gottail = 1; + } + dc++; + } + } + if (!gotdig) { + shunget(f); + if (pok) { + shunget(f); + if (gotrad) shunget(f); + } else { + shlim(f, 0); + } + //return sign * 0.0; return dbl_to_f128(sign * 0.0); - } - if (!gotrad) rp = dc; - while (dc<8) x *= 16, dc++; - if ((c|32)=='p') { - e2 = scanexp(f, pok); - if (e2 == LLONG_MIN) { - if (pok) { - shunget(f); - } else { - shlim(f, 0); - return zero; - } - e2 = 0; - } - } else { - shunget(f); - } - e2 += 4*rp - 32; - - if (!x) { + } + if (!gotrad) rp = dc; + while (dc<8) x *= 16, dc++; + if ((c|32)=='p') { + e2 = scanexp(f, pok); + if (e2 == LLONG_MIN) { + if (pok) { + shunget(f); + } else { + shlim(f, 0); + return zero; + } + e2 = 0; + } + } else { + shunget(f); + } + e2 += 4*rp - 32; + + if (!x) { //return sign * 0.0; return dbl_to_f128(sign * 0.0); } - if (e2 > -emin) { - errno = ERANGE; - //return sign * LDBL_MAX * LDBL_MAX; - return zero; - } - if (e2 < emin-2*LDBL_MANT_DIG) { - errno = ERANGE; - //return sign * LDBL_MIN * LDBL_MIN; - return zero; - } - - while (x < 0x80000000) { - //if (y>=0.5) - if (!f128M_lt(&y, &point_5)) { - x += x + 1; - //y += y - 1; + if (e2 > -emin) { + errno = ERANGE; + //return sign * LDBL_MAX * LDBL_MAX; + return zero; + } + if (e2 < emin-2*LDBL_MANT_DIG) { + errno = ERANGE; + //return sign * LDBL_MIN * LDBL_MIN; + return zero; + } + + while (x < 0x80000000) { + //if (y>=0.5) + if (!f128M_lt(&y, &point_5)) { + x += x + 1; + //y += y - 1; { float128_t minus_one; f128M_sub(&y, &one, &minus_one); @@ -878,33 +878,33 @@ static float128_t hexfloat(struct MuslFILE *f, int bits, int emin, int sign, int f128M_add(&y, &minus_one, &new_y); y = new_y; } - } else { - x += x; - //y += y; + } else { + x += x; + //y += y; { float128_t new_y; f128M_add(&y, &y, &new_y); y = new_y; } - } - e2--; - } + } + e2--; + } - if (bits > 32+e2-emin) { - bits = 32+e2-emin; - if (bits<0) bits=0; - } + if (bits > 32+e2-emin) { + bits = 32+e2-emin; + if (bits<0) bits=0; + } - if (bits < LDBL_MANT_DIG) { + if (bits < LDBL_MANT_DIG) { float128_t sign_f128; i32_to_f128M(sign, &sign_f128); - bias = copysignf128(dbl_to_f128(scalbn(1, 32+LDBL_MANT_DIG-bits-1)), sign_f128); + bias = copysignf128(dbl_to_f128(scalbn(1, 32+LDBL_MANT_DIG-bits-1)), sign_f128); } - //if (bits<32 && y && !(x&1)) x++, y=0; - if (bits<32 && !f128M_eq(&y, &zero) && !(x&1)) x++, y=zero; + //if (bits<32 && y && !(x&1)) x++, y=0; + if (bits<32 && !f128M_eq(&y, &zero) && !(x&1)) x++, y=zero; - //y = bias + sign*(float128_t)x + sign*y; + //y = bias + sign*(float128_t)x + sign*y; { float128_t x_f128; ui32_to_f128M(x, &x_f128); @@ -920,25 +920,25 @@ static float128_t hexfloat(struct MuslFILE *f, int bits, int emin, int sign, int f128M_add(&bias_op, &sign_mul_y, &new_y); y = new_y; } - //y -= bias; + //y -= bias; { float128_t new_y; f128M_sub(&y, &bias, &new_y); y = new_y; } - if (f128M_eq(&y, &zero)) errno = ERANGE; + if (f128M_eq(&y, &zero)) errno = ERANGE; - return scalbnf128(y, e2); + return scalbnf128(y, e2); } static int isspace(int c) { - return c == ' ' || (unsigned)c-'\t' < 5; + return c == ' ' || (unsigned)c-'\t' < 5; } static inline float128_t makeInf128() { - union ldshape ux; + union ldshape ux; ux.i2.hi = 0x7fff000000000000UL; ux.i2.lo = 0x0UL; return ux.f; @@ -946,7 +946,7 @@ static inline float128_t makeInf128() { static inline float128_t makeNaN128() { uint64_t rand = 0UL; - union ldshape ux; + union ldshape ux; ux.i2.hi = 0x7fff000000000000UL | (rand & 0xffffffffffffUL); ux.i2.lo = 0x0UL; return ux.f; @@ -954,86 +954,86 @@ static inline float128_t makeNaN128() { float128_t __floatscan(struct MuslFILE *f, int prec, int pok) { - int sign = 1; - size_t i; - int bits = LDBL_MANT_DIG; - int emin = LDBL_MIN_EXP-bits; - int c; - - while (isspace((c=shgetc(f)))); - - if (c=='+' || c=='-') { - sign -= 2*(c=='-'); - c = shgetc(f); - } - - for (i=0; i<8 && (c|32)=="infinity"[i]; i++) - if (i<7) c = shgetc(f); - if (i==3 || i==8 || (i>3 && pok)) { - if (i!=8) { - shunget(f); - if (pok) for (; i>3; i--) shunget(f); - } - //return sign * INFINITY; + int sign = 1; + size_t i; + int bits = LDBL_MANT_DIG; + int emin = LDBL_MIN_EXP-bits; + int c; + + while (isspace((c=shgetc(f)))); + + if (c=='+' || c=='-') { + sign -= 2*(c=='-'); + c = shgetc(f); + } + + for (i=0; i<8 && (c|32)=="infinity"[i]; i++) + if (i<7) c = shgetc(f); + if (i==3 || i==8 || (i>3 && pok)) { + if (i!=8) { + shunget(f); + if (pok) for (; i>3; i--) shunget(f); + } + //return sign * INFINITY; float128_t sign_f128; i32_to_f128M(sign, &sign_f128); float128_t infinity_f128 = makeInf128(); float128_t result; f128M_mul(&sign_f128, &infinity_f128, &result); return result; - } - if (!i) for (i=0; i<3 && (c|32)=="nan"[i]; i++) - if (i<2) c = shgetc(f); - if (i==3) { - if (shgetc(f) != '(') { - shunget(f); - return makeNaN128(); - } - for (i=1; ; i++) { - c = shgetc(f); - if (c-'0'<10U || c-'A'<26U || c-'a'<26U || c=='_') - continue; - if (c==')') return makeNaN128(); - shunget(f); - if (!pok) { - errno = EINVAL; - shlim(f, 0); + } + if (!i) for (i=0; i<3 && (c|32)=="nan"[i]; i++) + if (i<2) c = shgetc(f); + if (i==3) { + if (shgetc(f) != '(') { + shunget(f); + return makeNaN128(); + } + for (i=1; ; i++) { + c = shgetc(f); + if (c-'0'<10U || c-'A'<26U || c-'a'<26U || c=='_') + continue; + if (c==')') return makeNaN128(); + shunget(f); + if (!pok) { + errno = EINVAL; + shlim(f, 0); float128_t zero; ui32_to_f128M(0, &zero); - return zero; - } - while (i--) shunget(f); - return makeNaN128(); - } - return makeNaN128(); - } - - if (i) { - shunget(f); - errno = EINVAL; - shlim(f, 0); + return zero; + } + while (i--) shunget(f); + return makeNaN128(); + } + return makeNaN128(); + } + + if (i) { + shunget(f); + errno = EINVAL; + shlim(f, 0); float128_t zero; ui32_to_f128M(0, &zero); - return zero; - } - - if (c=='0') { - c = shgetc(f); - if ((c|32) == 'x') - return hexfloat(f, bits, emin, sign, pok); - shunget(f); - c = '0'; - } - - return decfloat(f, c, bits, emin, sign, pok); + return zero; + } + + if (c=='0') { + c = shgetc(f); + if ((c|32) == 'x') + return hexfloat(f, bits, emin, sign, pok); + shunget(f); + c = '0'; + } + + return decfloat(f, c, bits, emin, sign, pok); } float128_t parse_f128(const char *s, char **p) { - struct MuslFILE f; - sh_fromstring(&f, s); - shlim(&f, 0); - float128_t y = __floatscan(&f, 2, 1); - off_t cnt = shcnt(&f); - if (p) *p = cnt ? (char *)s + cnt : (char *)s; - return y; + struct MuslFILE f; + sh_fromstring(&f, s); + shlim(&f, 0); + float128_t y = __floatscan(&f, 2, 1); + off_t cnt = shcnt(&f); + if (p) *p = cnt ? (char *)s + cnt : (char *)s; + return y; } |
