| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| |
|
| | |
| | |
| | |
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| |
|
| | |
| |
|
| | #ifdef HAVE_CONFIG_H |
| | #include "config.h" |
| | #endif |
| |
|
| | #include <errno.h> |
| | #include <string.h> |
| | #include <assert.h> |
| | #include <stdio.h> |
| |
|
| | #include <pocketsphinx/prim_type.h> |
| | #include "util/ckd_alloc.h" |
| |
|
| | #ifdef WORDS_BIGENDIAN |
| | #define IEEE_MC68k |
| | #else |
| | #define IEEE_8087 |
| | #endif |
| |
|
| | #define Long int32 |
| | #define ULong uint32 |
| | #ifdef HAVE_LONG_LONG |
| | #define ULLong uint64 |
| | #endif |
| |
|
| | #define MALLOC ckd_malloc |
| | #define FREE ckd_free |
| |
|
| | #define DBL_DIG 15 |
| | #define DBL_MAX_10_EXP 308 |
| | #define DBL_MAX_EXP 1024 |
| | #define FLT_RADIX 2 |
| |
|
| | |
| | |
| | |
| | #ifndef MAX_ABS_EXP |
| | #define MAX_ABS_EXP 1100000000U |
| | #endif |
| | |
| | |
| | |
| | |
| | |
| | #ifndef MAX_DIGITS |
| | #define MAX_DIGITS 1000000000U |
| | #endif |
| |
|
| | |
| |
|
| | #ifdef DEBUG |
| | #define Bug(x) {fprintf(stderr, "%s\n", x); exit(1);} |
| | #endif |
| |
|
| |
|
| | #ifdef __cplusplus |
| | extern "C" { |
| | #endif |
| |
|
| | typedef union { double d; ULong L[2]; } U; |
| |
|
| | #ifdef IEEE_8087 |
| | #define word0(x) (x)->L[1] |
| | #define word1(x) (x)->L[0] |
| | #else |
| | #define word0(x) (x)->L[0] |
| | #define word1(x) (x)->L[1] |
| | #endif |
| | #define dval(x) (x)->d |
| |
|
| | #ifndef STRTOD_DIGLIM |
| | #define STRTOD_DIGLIM 40 |
| | #endif |
| |
|
| | |
| | |
| | |
| | #ifndef MAX_ABS_EXP |
| | #define MAX_ABS_EXP 1100000000U |
| | #endif |
| | |
| | |
| | |
| | |
| | |
| | #ifndef MAX_DIGITS |
| | #define MAX_DIGITS 1000000000U |
| | #endif |
| |
|
| | |
| | |
| | #if MAX_ABS_EXP > 0x7fffffff |
| | #error "MAX_ABS_EXP should fit in an int" |
| | #endif |
| | #if MAX_DIGITS > 0x7fffffff |
| | #error "MAX_DIGITS should fit in an int" |
| | #endif |
| |
|
| | |
| | |
| | |
| | |
| | #if defined(IEEE_8087) |
| | #define Storeinc(a,b,c) (((unsigned short *)a)[1] = (unsigned short)b, \ |
| | ((unsigned short *)a)[0] = (unsigned short)c, a++) |
| | #else |
| | #define Storeinc(a,b,c) (((unsigned short *)a)[0] = (unsigned short)b, \ |
| | ((unsigned short *)a)[1] = (unsigned short)c, a++) |
| | #endif |
| |
|
| | |
| | |
| | |
| | |
| | |
| |
|
| | #define Exp_shift 20 |
| | #define Exp_shift1 20 |
| | #define Exp_msk1 0x100000 |
| | #define Exp_msk11 0x100000 |
| | #define Exp_mask 0x7ff00000 |
| | #define P 53 |
| | #define Nbits 53 |
| | #define Bias 1023 |
| | #define Emax 1023 |
| | #define Emin (-1022) |
| | #define Etiny (-1074) |
| | #define Exp_1 0x3ff00000 |
| | #define Exp_11 0x3ff00000 |
| | #define Ebits 11 |
| | #define Frac_mask 0xfffff |
| | #define Frac_mask1 0xfffff |
| | #define Ten_pmax 22 |
| | #define Bletch 0x10 |
| | #define Bndry_mask 0xfffff |
| | #define Bndry_mask1 0xfffff |
| | #define Sign_bit 0x80000000 |
| | #define Log2P 1 |
| | #define Tiny0 0 |
| | #define Tiny1 1 |
| | #define Quick_max 14 |
| | #define Int_max 14 |
| |
|
| | #ifndef Flt_Rounds |
| | #ifdef FLT_ROUNDS |
| | #define Flt_Rounds FLT_ROUNDS |
| | #else |
| | #define Flt_Rounds 1 |
| | #endif |
| | #endif |
| |
|
| | #define Rounding Flt_Rounds |
| |
|
| | #define Big0 (Frac_mask1 | Exp_msk1*(DBL_MAX_EXP+Bias-1)) |
| | #define Big1 0xffffffff |
| |
|
| | |
| |
|
| | #define NAN_WORD0 0x7ff80000 |
| | #define NAN_WORD1 0 |
| |
|
| | |
| |
|
| | #define POSINF_WORD0 0x7ff00000 |
| | #define POSINF_WORD1 0 |
| |
|
| | |
| |
|
| | typedef struct BCinfo BCinfo; |
| | struct |
| | BCinfo { |
| | int e0, nd, nd0, scale; |
| | }; |
| |
|
| | #define FFFFFFFF 0xffffffffUL |
| |
|
| | #define Kmax 7 |
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| |
|
| | struct |
| | Bigint { |
| | struct Bigint *next; |
| | int k, maxwds, sign, wds; |
| | ULong x[1]; |
| | }; |
| |
|
| | typedef struct Bigint Bigint; |
| |
|
| | #define SPHINXBASE_USING_MEMORY_DEBUGGER 1 |
| |
|
| | #ifndef SPHINXBASE_USING_MEMORY_DEBUGGER |
| |
|
| | #ifndef PRIVATE_MEM |
| | #define PRIVATE_MEM 2304 |
| | #endif |
| | #define PRIVATE_mem ((PRIVATE_MEM+sizeof(double)-1)/sizeof(double)) |
| | static double private_mem[PRIVATE_mem], *pmem_next = private_mem; |
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| |
|
| | static Bigint *freelist[Kmax+1]; |
| |
|
| | |
| |
|
| | static Bigint * |
| | Balloc(int k) |
| | { |
| | int x; |
| | Bigint *rv; |
| | unsigned int len; |
| |
|
| | if (k <= Kmax && (rv = freelist[k])) |
| | freelist[k] = rv->next; |
| | else { |
| | x = 1 << k; |
| | len = (sizeof(Bigint) + (x-1)*sizeof(ULong) + sizeof(double) - 1) |
| | /sizeof(double); |
| | if (k <= Kmax && pmem_next - private_mem + len <= PRIVATE_mem) { |
| | rv = (Bigint*)pmem_next; |
| | pmem_next += len; |
| | } |
| | else { |
| | rv = (Bigint*)MALLOC(len*sizeof(double)); |
| | if (rv == NULL) |
| | return NULL; |
| | } |
| | rv->k = k; |
| | rv->maxwds = x; |
| | } |
| | rv->sign = rv->wds = 0; |
| | return rv; |
| | } |
| |
|
| | |
| |
|
| | static void |
| | Bfree(Bigint *v) |
| | { |
| | if (v) { |
| | if (v->k > Kmax) |
| | FREE((void*)v); |
| | else { |
| | v->next = freelist[v->k]; |
| | freelist[v->k] = v; |
| | } |
| | } |
| | } |
| |
|
| | #else |
| |
|
| | |
| | |
| | |
| | |
| |
|
| | |
| |
|
| | static Bigint * |
| | Balloc(int k) |
| | { |
| | int x; |
| | Bigint *rv; |
| | unsigned int len; |
| |
|
| | x = 1 << k; |
| | len = (sizeof(Bigint) + (x-1)*sizeof(ULong) + sizeof(double) - 1) |
| | /sizeof(double); |
| |
|
| | rv = (Bigint*)MALLOC(len*sizeof(double)); |
| | if (rv == NULL) |
| | return NULL; |
| |
|
| | rv->k = k; |
| | rv->maxwds = x; |
| | rv->sign = rv->wds = 0; |
| | return rv; |
| | } |
| |
|
| | |
| |
|
| | static void |
| | Bfree(Bigint *v) |
| | { |
| | if (v) { |
| | FREE((void*)v); |
| | } |
| | } |
| |
|
| | #endif |
| |
|
| | #define Bcopy(x,y) memcpy((char *)&x->sign, (char *)&y->sign, \ |
| | y->wds*sizeof(Long) + 2*sizeof(int)) |
| |
|
| | |
| | |
| | |
| |
|
| | static Bigint * |
| | multadd(Bigint *b, int m, int a) |
| | { |
| | int i, wds; |
| | #ifdef ULLong |
| | ULong *x; |
| | ULLong carry, y; |
| | #else |
| | ULong carry, *x, y; |
| | ULong xi, z; |
| | #endif |
| | Bigint *b1; |
| |
|
| | wds = b->wds; |
| | x = b->x; |
| | i = 0; |
| | carry = a; |
| | do { |
| | #ifdef ULLong |
| | y = *x * (ULLong)m + carry; |
| | carry = y >> 32; |
| | *x++ = (ULong)(y & FFFFFFFF); |
| | #else |
| | xi = *x; |
| | y = (xi & 0xffff) * m + carry; |
| | z = (xi >> 16) * m + (y >> 16); |
| | carry = z >> 16; |
| | *x++ = (z << 16) + (y & 0xffff); |
| | #endif |
| | } |
| | while(++i < wds); |
| | if (carry) { |
| | if (wds >= b->maxwds) { |
| | b1 = Balloc(b->k+1); |
| | if (b1 == NULL){ |
| | Bfree(b); |
| | return NULL; |
| | } |
| | Bcopy(b1, b); |
| | Bfree(b); |
| | b = b1; |
| | } |
| | b->x[wds++] = (ULong)carry; |
| | b->wds = wds; |
| | } |
| | return b; |
| | } |
| |
|
| | |
| | |
| | |
| | |
| | |
| |
|
| | static Bigint * |
| | s2b(const char *s, int nd0, int nd, ULong y9) |
| | { |
| | Bigint *b; |
| | int i, k; |
| | Long x, y; |
| |
|
| | x = (nd + 8) / 9; |
| | for(k = 0, y = 1; x > y; y <<= 1, k++) ; |
| | b = Balloc(k); |
| | if (b == NULL) |
| | return NULL; |
| | b->x[0] = y9; |
| | b->wds = 1; |
| |
|
| | if (nd <= 9) |
| | return b; |
| |
|
| | s += 9; |
| | for (i = 9; i < nd0; i++) { |
| | b = multadd(b, 10, *s++ - '0'); |
| | if (b == NULL) |
| | return NULL; |
| | } |
| | s++; |
| | for(; i < nd; i++) { |
| | b = multadd(b, 10, *s++ - '0'); |
| | if (b == NULL) |
| | return NULL; |
| | } |
| | return b; |
| | } |
| |
|
| | |
| |
|
| | static int |
| | hi0bits(ULong x) |
| | { |
| | int k = 0; |
| |
|
| | if (!(x & 0xffff0000)) { |
| | k = 16; |
| | x <<= 16; |
| | } |
| | if (!(x & 0xff000000)) { |
| | k += 8; |
| | x <<= 8; |
| | } |
| | if (!(x & 0xf0000000)) { |
| | k += 4; |
| | x <<= 4; |
| | } |
| | if (!(x & 0xc0000000)) { |
| | k += 2; |
| | x <<= 2; |
| | } |
| | if (!(x & 0x80000000)) { |
| | k++; |
| | if (!(x & 0x40000000)) |
| | return 32; |
| | } |
| | return k; |
| | } |
| |
|
| | |
| | |
| |
|
| | static int |
| | lo0bits(ULong *y) |
| | { |
| | int k; |
| | ULong x = *y; |
| |
|
| | if (x & 7) { |
| | if (x & 1) |
| | return 0; |
| | if (x & 2) { |
| | *y = x >> 1; |
| | return 1; |
| | } |
| | *y = x >> 2; |
| | return 2; |
| | } |
| | k = 0; |
| | if (!(x & 0xffff)) { |
| | k = 16; |
| | x >>= 16; |
| | } |
| | if (!(x & 0xff)) { |
| | k += 8; |
| | x >>= 8; |
| | } |
| | if (!(x & 0xf)) { |
| | k += 4; |
| | x >>= 4; |
| | } |
| | if (!(x & 0x3)) { |
| | k += 2; |
| | x >>= 2; |
| | } |
| | if (!(x & 1)) { |
| | k++; |
| | x >>= 1; |
| | if (!x) |
| | return 32; |
| | } |
| | *y = x; |
| | return k; |
| | } |
| |
|
| | |
| |
|
| | static Bigint * |
| | i2b(int i) |
| | { |
| | Bigint *b; |
| |
|
| | b = Balloc(1); |
| | if (b == NULL) |
| | return NULL; |
| | b->x[0] = i; |
| | b->wds = 1; |
| | return b; |
| | } |
| |
|
| | |
| | |
| |
|
| | static Bigint * |
| | mult(Bigint *a, Bigint *b) |
| | { |
| | Bigint *c; |
| | int k, wa, wb, wc; |
| | ULong *x, *xa, *xae, *xb, *xbe, *xc, *xc0; |
| | ULong y; |
| | #ifdef ULLong |
| | ULLong carry, z; |
| | #else |
| | ULong carry, z; |
| | ULong z2; |
| | #endif |
| |
|
| | if ((!a->x[0] && a->wds == 1) || (!b->x[0] && b->wds == 1)) { |
| | c = Balloc(0); |
| | if (c == NULL) |
| | return NULL; |
| | c->wds = 1; |
| | c->x[0] = 0; |
| | return c; |
| | } |
| |
|
| | if (a->wds < b->wds) { |
| | c = a; |
| | a = b; |
| | b = c; |
| | } |
| | k = a->k; |
| | wa = a->wds; |
| | wb = b->wds; |
| | wc = wa + wb; |
| | if (wc > a->maxwds) |
| | k++; |
| | c = Balloc(k); |
| | if (c == NULL) |
| | return NULL; |
| | for(x = c->x, xa = x + wc; x < xa; x++) |
| | *x = 0; |
| | xa = a->x; |
| | xae = xa + wa; |
| | xb = b->x; |
| | xbe = xb + wb; |
| | xc0 = c->x; |
| | #ifdef ULLong |
| | for(; xb < xbe; xc0++) { |
| | if ((y = *xb++)) { |
| | x = xa; |
| | xc = xc0; |
| | carry = 0; |
| | do { |
| | z = *x++ * (ULLong)y + *xc + carry; |
| | carry = z >> 32; |
| | *xc++ = (ULong)(z & FFFFFFFF); |
| | } |
| | while(x < xae); |
| | *xc = (ULong)carry; |
| | } |
| | } |
| | #else |
| | for(; xb < xbe; xb++, xc0++) { |
| | if (y = *xb & 0xffff) { |
| | x = xa; |
| | xc = xc0; |
| | carry = 0; |
| | do { |
| | z = (*x & 0xffff) * y + (*xc & 0xffff) + carry; |
| | carry = z >> 16; |
| | z2 = (*x++ >> 16) * y + (*xc >> 16) + carry; |
| | carry = z2 >> 16; |
| | Storeinc(xc, z2, z); |
| | } |
| | while(x < xae); |
| | *xc = carry; |
| | } |
| | if (y = *xb >> 16) { |
| | x = xa; |
| | xc = xc0; |
| | carry = 0; |
| | z2 = *xc; |
| | do { |
| | z = (*x & 0xffff) * y + (*xc >> 16) + carry; |
| | carry = z >> 16; |
| | Storeinc(xc, z, z2); |
| | z2 = (*x++ >> 16) * y + (*xc & 0xffff) + carry; |
| | carry = z2 >> 16; |
| | } |
| | while(x < xae); |
| | *xc = z2; |
| | } |
| | } |
| | #endif |
| | for(xc0 = c->x, xc = xc0 + wc; wc > 0 && !*--xc; --wc) ; |
| | c->wds = wc; |
| | return c; |
| | } |
| |
|
| | #ifndef SPHINXBASE_USING_MEMORY_DEBUGGER |
| |
|
| | |
| |
|
| | static Bigint *p5s; |
| |
|
| | |
| | |
| | |
| |
|
| | static Bigint * |
| | pow5mult(Bigint *b, int k) |
| | { |
| | Bigint *b1, *p5, *p51; |
| | int i; |
| | static int p05[3] = { 5, 25, 125 }; |
| |
|
| | if ((i = k & 3)) { |
| | b = multadd(b, p05[i-1], 0); |
| | if (b == NULL) |
| | return NULL; |
| | } |
| |
|
| | if (!(k >>= 2)) |
| | return b; |
| | p5 = p5s; |
| | if (!p5) { |
| | |
| | p5 = i2b(625); |
| | if (p5 == NULL) { |
| | Bfree(b); |
| | return NULL; |
| | } |
| | p5s = p5; |
| | p5->next = 0; |
| | } |
| | for(;;) { |
| | if (k & 1) { |
| | b1 = mult(b, p5); |
| | Bfree(b); |
| | b = b1; |
| | if (b == NULL) |
| | return NULL; |
| | } |
| | if (!(k >>= 1)) |
| | break; |
| | p51 = p5->next; |
| | if (!p51) { |
| | p51 = mult(p5,p5); |
| | if (p51 == NULL) { |
| | Bfree(b); |
| | return NULL; |
| | } |
| | p51->next = 0; |
| | p5->next = p51; |
| | } |
| | p5 = p51; |
| | } |
| | return b; |
| | } |
| |
|
| | #else |
| |
|
| | |
| | |
| |
|
| | static Bigint * |
| | pow5mult(Bigint *b, int k) |
| | { |
| | Bigint *b1, *p5, *p51; |
| | int i; |
| | static int p05[3] = { 5, 25, 125 }; |
| |
|
| | if ((i = k & 3)) { |
| | b = multadd(b, p05[i-1], 0); |
| | if (b == NULL) |
| | return NULL; |
| | } |
| |
|
| | if (!(k >>= 2)) |
| | return b; |
| | p5 = i2b(625); |
| | if (p5 == NULL) { |
| | Bfree(b); |
| | return NULL; |
| | } |
| |
|
| | for(;;) { |
| | if (k & 1) { |
| | b1 = mult(b, p5); |
| | Bfree(b); |
| | b = b1; |
| | if (b == NULL) { |
| | Bfree(p5); |
| | return NULL; |
| | } |
| | } |
| | if (!(k >>= 1)) |
| | break; |
| | p51 = mult(p5, p5); |
| | Bfree(p5); |
| | p5 = p51; |
| | if (p5 == NULL) { |
| | Bfree(b); |
| | return NULL; |
| | } |
| | } |
| | Bfree(p5); |
| | return b; |
| | } |
| |
|
| | #endif |
| |
|
| | |
| | |
| | |
| |
|
| | static Bigint * |
| | lshift(Bigint *b, int k) |
| | { |
| | int i, k1, n, n1; |
| | Bigint *b1; |
| | ULong *x, *x1, *xe, z; |
| |
|
| | if (!k || (!b->x[0] && b->wds == 1)) |
| | return b; |
| |
|
| | n = k >> 5; |
| | k1 = b->k; |
| | n1 = n + b->wds + 1; |
| | for(i = b->maxwds; n1 > i; i <<= 1) |
| | k1++; |
| | b1 = Balloc(k1); |
| | if (b1 == NULL) { |
| | Bfree(b); |
| | return NULL; |
| | } |
| | x1 = b1->x; |
| | for(i = 0; i < n; i++) |
| | *x1++ = 0; |
| | x = b->x; |
| | xe = x + b->wds; |
| | if (k &= 0x1f) { |
| | k1 = 32 - k; |
| | z = 0; |
| | do { |
| | *x1++ = *x << k | z; |
| | z = *x++ >> k1; |
| | } |
| | while(x < xe); |
| | if ((*x1 = z)) |
| | ++n1; |
| | } |
| | else do |
| | *x1++ = *x++; |
| | while(x < xe); |
| | b1->wds = n1 - 1; |
| | Bfree(b); |
| | return b1; |
| | } |
| |
|
| | |
| | |
| |
|
| | static int |
| | cmp(Bigint *a, Bigint *b) |
| | { |
| | ULong *xa, *xa0, *xb, *xb0; |
| | int i, j; |
| |
|
| | i = a->wds; |
| | j = b->wds; |
| | #ifdef DEBUG |
| | if (i > 1 && !a->x[i-1]) |
| | Bug("cmp called with a->x[a->wds-1] == 0"); |
| | if (j > 1 && !b->x[j-1]) |
| | Bug("cmp called with b->x[b->wds-1] == 0"); |
| | #endif |
| | if (i -= j) |
| | return i; |
| | xa0 = a->x; |
| | xa = xa0 + j; |
| | xb0 = b->x; |
| | xb = xb0 + j; |
| | for(;;) { |
| | if (*--xa != *--xb) |
| | return *xa < *xb ? -1 : 1; |
| | if (xa <= xa0) |
| | break; |
| | } |
| | return 0; |
| | } |
| |
|
| | |
| | |
| | |
| |
|
| | static Bigint * |
| | diff(Bigint *a, Bigint *b) |
| | { |
| | Bigint *c; |
| | int i, wa, wb; |
| | ULong *xa, *xae, *xb, *xbe, *xc; |
| | #ifdef ULLong |
| | ULLong borrow, y; |
| | #else |
| | ULong borrow, y; |
| | ULong z; |
| | #endif |
| |
|
| | i = cmp(a,b); |
| | if (!i) { |
| | c = Balloc(0); |
| | if (c == NULL) |
| | return NULL; |
| | c->wds = 1; |
| | c->x[0] = 0; |
| | return c; |
| | } |
| | if (i < 0) { |
| | c = a; |
| | a = b; |
| | b = c; |
| | i = 1; |
| | } |
| | else |
| | i = 0; |
| | c = Balloc(a->k); |
| | if (c == NULL) |
| | return NULL; |
| | c->sign = i; |
| | wa = a->wds; |
| | xa = a->x; |
| | xae = xa + wa; |
| | wb = b->wds; |
| | xb = b->x; |
| | xbe = xb + wb; |
| | xc = c->x; |
| | borrow = 0; |
| | #ifdef ULLong |
| | do { |
| | y = (ULLong)*xa++ - *xb++ - borrow; |
| | borrow = y >> 32 & (ULong)1; |
| | *xc++ = (ULong)(y & FFFFFFFF); |
| | } |
| | while(xb < xbe); |
| | while(xa < xae) { |
| | y = *xa++ - borrow; |
| | borrow = y >> 32 & (ULong)1; |
| | *xc++ = (ULong)(y & FFFFFFFF); |
| | } |
| | #else |
| | do { |
| | y = (*xa & 0xffff) - (*xb & 0xffff) - borrow; |
| | borrow = (y & 0x10000) >> 16; |
| | z = (*xa++ >> 16) - (*xb++ >> 16) - borrow; |
| | borrow = (z & 0x10000) >> 16; |
| | Storeinc(xc, z, y); |
| | } |
| | while(xb < xbe); |
| | while(xa < xae) { |
| | y = (*xa & 0xffff) - borrow; |
| | borrow = (y & 0x10000) >> 16; |
| | z = (*xa++ >> 16) - borrow; |
| | borrow = (z & 0x10000) >> 16; |
| | Storeinc(xc, z, y); |
| | } |
| | #endif |
| | while(!*--xc) |
| | wa--; |
| | c->wds = wa; |
| | return c; |
| | } |
| |
|
| | |
| | |
| |
|
| | static double |
| | ulp(U *x) |
| | { |
| | Long L; |
| | U u; |
| |
|
| | L = (word0(x) & Exp_mask) - (P-1)*Exp_msk1; |
| | word0(&u) = L; |
| | word1(&u) = 0; |
| | return dval(&u); |
| | } |
| |
|
| | |
| |
|
| | static double |
| | b2d(Bigint *a, int *e) |
| | { |
| | ULong *xa, *xa0, w, y, z; |
| | int k; |
| | U d; |
| |
|
| | xa0 = a->x; |
| | xa = xa0 + a->wds; |
| | y = *--xa; |
| | #ifdef DEBUG |
| | if (!y) Bug("zero y in b2d"); |
| | #endif |
| | k = hi0bits(y); |
| | *e = 32 - k; |
| | if (k < Ebits) { |
| | word0(&d) = Exp_1 | y >> (Ebits - k); |
| | w = xa > xa0 ? *--xa : 0; |
| | word1(&d) = y << ((32-Ebits) + k) | w >> (Ebits - k); |
| | goto ret_d; |
| | } |
| | z = xa > xa0 ? *--xa : 0; |
| | if (k -= Ebits) { |
| | word0(&d) = Exp_1 | y << k | z >> (32 - k); |
| | y = xa > xa0 ? *--xa : 0; |
| | word1(&d) = z << k | y >> (32 - k); |
| | } |
| | else { |
| | word0(&d) = Exp_1 | y; |
| | word1(&d) = z; |
| | } |
| | ret_d: |
| | return dval(&d); |
| | } |
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| |
|
| | static Bigint * |
| | sd2b(U *d, int scale, int *e) |
| | { |
| | Bigint *b; |
| |
|
| | b = Balloc(1); |
| | if (b == NULL) |
| | return NULL; |
| | |
| | |
| | b->wds = 2; |
| | b->x[0] = word1(d); |
| | b->x[1] = word0(d) & Frac_mask; |
| | *e = Etiny - 1 + (int)((word0(d) & Exp_mask) >> Exp_shift); |
| | if (*e < Etiny) |
| | *e = Etiny; |
| | else |
| | b->x[1] |= Exp_msk1; |
| |
|
| | |
| | if (scale && (b->x[0] || b->x[1])) { |
| | *e -= scale; |
| | if (*e < Etiny) { |
| | scale = Etiny - *e; |
| | *e = Etiny; |
| | |
| | assert(0 < scale && scale <= P - 1); |
| | if (scale >= 32) { |
| | |
| | assert(b->x[0] == 0); |
| | b->x[0] = b->x[1]; |
| | b->x[1] = 0; |
| | scale -= 32; |
| | } |
| | if (scale) { |
| | |
| | assert(b->x[0] << (32 - scale) == 0); |
| | b->x[0] = (b->x[0] >> scale) | (b->x[1] << (32 - scale)); |
| | b->x[1] >>= scale; |
| | } |
| | } |
| | } |
| | |
| | if (!b->x[1]) |
| | b->wds = 1; |
| |
|
| | return b; |
| | } |
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| |
|
| | static Bigint * |
| | d2b(U *d, int *e, int *bits) |
| | { |
| | Bigint *b; |
| | int de, k; |
| | ULong *x, y, z; |
| | int i; |
| |
|
| | b = Balloc(1); |
| | if (b == NULL) |
| | return NULL; |
| | x = b->x; |
| |
|
| | z = word0(d) & Frac_mask; |
| | word0(d) &= 0x7fffffff; |
| | if ((de = (int)(word0(d) >> Exp_shift))) |
| | z |= Exp_msk1; |
| | if ((y = word1(d))) { |
| | if ((k = lo0bits(&y))) { |
| | x[0] = y | z << (32 - k); |
| | z >>= k; |
| | } |
| | else |
| | x[0] = y; |
| | i = |
| | b->wds = (x[1] = z) ? 2 : 1; |
| | } |
| | else { |
| | k = lo0bits(&z); |
| | x[0] = z; |
| | i = |
| | b->wds = 1; |
| | k += 32; |
| | } |
| | if (de) { |
| | *e = de - Bias - (P-1) + k; |
| | *bits = P - k; |
| | } |
| | else { |
| | *e = de - Bias - (P-1) + 1 + k; |
| | *bits = 32*i - hi0bits(x[i-1]); |
| | } |
| | return b; |
| | } |
| |
|
| | |
| | |
| |
|
| | static double |
| | ratio(Bigint *a, Bigint *b) |
| | { |
| | U da, db; |
| | int k, ka, kb; |
| |
|
| | dval(&da) = b2d(a, &ka); |
| | dval(&db) = b2d(b, &kb); |
| | k = ka - kb + 32*(a->wds - b->wds); |
| | if (k > 0) |
| | word0(&da) += k*Exp_msk1; |
| | else { |
| | k = -k; |
| | word0(&db) += k*Exp_msk1; |
| | } |
| | return dval(&da) / dval(&db); |
| | } |
| |
|
| | static const double |
| | tens[] = { |
| | 1e0, 1e1, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8, 1e9, |
| | 1e10, 1e11, 1e12, 1e13, 1e14, 1e15, 1e16, 1e17, 1e18, 1e19, |
| | 1e20, 1e21, 1e22 |
| | }; |
| |
|
| | static const double |
| | bigtens[] = { 1e16, 1e32, 1e64, 1e128, 1e256 }; |
| | static const double tinytens[] = { 1e-16, 1e-32, 1e-64, 1e-128, |
| | 9007199254740992.*9007199254740992.e-256 |
| | |
| | }; |
| | |
| | |
| | #define Scale_Bit 0x10 |
| | #define n_bigtens 5 |
| |
|
| | #define ULbits 32 |
| | #define kshift 5 |
| | #define kmask 31 |
| |
|
| |
|
| | static int |
| | dshift(Bigint *b, int p2) |
| | { |
| | int rv = hi0bits(b->x[b->wds-1]) - 4; |
| | if (p2 > 0) |
| | rv -= p2; |
| | return rv & kmask; |
| | } |
| |
|
| | |
| | |
| | |
| |
|
| | static int |
| | quorem(Bigint *b, Bigint *S) |
| | { |
| | int n; |
| | ULong *bx, *bxe, q, *sx, *sxe; |
| | #ifdef ULLong |
| | ULLong borrow, carry, y, ys; |
| | #else |
| | ULong borrow, carry, y, ys; |
| | ULong si, z, zs; |
| | #endif |
| |
|
| | n = S->wds; |
| | #ifdef DEBUG |
| | if (b->wds > n) |
| | Bug("oversize b in quorem"); |
| | #endif |
| | if (b->wds < n) |
| | return 0; |
| | sx = S->x; |
| | sxe = sx + --n; |
| | bx = b->x; |
| | bxe = bx + n; |
| | q = *bxe / (*sxe + 1); |
| | #ifdef DEBUG |
| | if (q > 9) |
| | Bug("oversized quotient in quorem"); |
| | #endif |
| | if (q) { |
| | borrow = 0; |
| | carry = 0; |
| | do { |
| | #ifdef ULLong |
| | ys = *sx++ * (ULLong)q + carry; |
| | carry = ys >> 32; |
| | y = *bx - (ys & FFFFFFFF) - borrow; |
| | borrow = y >> 32 & (ULong)1; |
| | *bx++ = (ULong)(y & FFFFFFFF); |
| | #else |
| | si = *sx++; |
| | ys = (si & 0xffff) * q + carry; |
| | zs = (si >> 16) * q + (ys >> 16); |
| | carry = zs >> 16; |
| | y = (*bx & 0xffff) - (ys & 0xffff) - borrow; |
| | borrow = (y & 0x10000) >> 16; |
| | z = (*bx >> 16) - (zs & 0xffff) - borrow; |
| | borrow = (z & 0x10000) >> 16; |
| | Storeinc(bx, z, y); |
| | #endif |
| | } |
| | while(sx <= sxe); |
| | if (!*bxe) { |
| | bx = b->x; |
| | while(--bxe > bx && !*bxe) |
| | --n; |
| | b->wds = n; |
| | } |
| | } |
| | if (cmp(b, S) >= 0) { |
| | q++; |
| | borrow = 0; |
| | carry = 0; |
| | bx = b->x; |
| | sx = S->x; |
| | do { |
| | #ifdef ULLong |
| | ys = *sx++ + carry; |
| | carry = ys >> 32; |
| | y = *bx - (ys & FFFFFFFF) - borrow; |
| | borrow = y >> 32 & (ULong)1; |
| | *bx++ = (ULong)(y & FFFFFFFF); |
| | #else |
| | si = *sx++; |
| | ys = (si & 0xffff) + carry; |
| | zs = (si >> 16) + (ys >> 16); |
| | carry = zs >> 16; |
| | y = (*bx & 0xffff) - (ys & 0xffff) - borrow; |
| | borrow = (y & 0x10000) >> 16; |
| | z = (*bx >> 16) - (zs & 0xffff) - borrow; |
| | borrow = (z & 0x10000) >> 16; |
| | Storeinc(bx, z, y); |
| | #endif |
| | } |
| | while(sx <= sxe); |
| | bx = b->x; |
| | bxe = bx + n; |
| | if (!*bxe) { |
| | while(--bxe > bx && !*bxe) |
| | --n; |
| | b->wds = n; |
| | } |
| | } |
| | return q; |
| | } |
| |
|
| | |
| | |
| | |
| | |
| | |
| |
|
| | static double |
| | sulp(U *x, BCinfo *bc) |
| | { |
| | U u; |
| |
|
| | if (bc->scale && 2*P + 1 > (int)((word0(x) & Exp_mask) >> Exp_shift)) { |
| | |
| | word0(&u) = (P+2)*Exp_msk1; |
| | word1(&u) = 0; |
| | return u.d; |
| | } |
| | else { |
| | assert(word0(x) || word1(x)); |
| | return ulp(x); |
| | } |
| | } |
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| |
|
| | static int |
| | bigcomp(U *rv, const char *s0, BCinfo *bc) |
| | { |
| | Bigint *b, *d; |
| | int b2, d2, dd, i, nd, nd0, odd, p2, p5; |
| |
|
| | nd = bc->nd; |
| | nd0 = bc->nd0; |
| | p5 = nd + bc->e0; |
| | b = sd2b(rv, bc->scale, &p2); |
| | if (b == NULL) |
| | return -1; |
| |
|
| | |
| | |
| | odd = b->x[0] & 1; |
| |
|
| | |
| | |
| | b = lshift(b, 1); |
| | if (b == NULL) |
| | return -1; |
| | b->x[0] |= 1; |
| | p2--; |
| |
|
| | p2 -= p5; |
| | d = i2b(1); |
| | if (d == NULL) { |
| | Bfree(b); |
| | return -1; |
| | } |
| | |
| | |
| | |
| | if (p5 > 0) { |
| | d = pow5mult(d, p5); |
| | if (d == NULL) { |
| | Bfree(b); |
| | return -1; |
| | } |
| | } |
| | else if (p5 < 0) { |
| | b = pow5mult(b, -p5); |
| | if (b == NULL) { |
| | Bfree(d); |
| | return -1; |
| | } |
| | } |
| | if (p2 > 0) { |
| | b2 = p2; |
| | d2 = 0; |
| | } |
| | else { |
| | b2 = 0; |
| | d2 = -p2; |
| | } |
| | i = dshift(d, d2); |
| | if ((b2 += i) > 0) { |
| | b = lshift(b, b2); |
| | if (b == NULL) { |
| | Bfree(d); |
| | return -1; |
| | } |
| | } |
| | if ((d2 += i) > 0) { |
| | d = lshift(d, d2); |
| | if (d == NULL) { |
| | Bfree(b); |
| | return -1; |
| | } |
| | } |
| |
|
| | |
| | |
| | |
| | if (cmp(b, d) >= 0) |
| | |
| | dd = -1; |
| | else { |
| | i = 0; |
| | for(;;) { |
| | b = multadd(b, 10, 0); |
| | if (b == NULL) { |
| | Bfree(d); |
| | return -1; |
| | } |
| | dd = s0[i < nd0 ? i : i+1] - '0' - quorem(b, d); |
| | i++; |
| |
|
| | if (dd) |
| | break; |
| | if (!b->x[0] && b->wds == 1) { |
| | |
| | dd = i < nd; |
| | break; |
| | } |
| | if (!(i < nd)) { |
| | |
| | dd = -1; |
| | break; |
| | } |
| | } |
| | } |
| | Bfree(b); |
| | Bfree(d); |
| | if (dd > 0 || (dd == 0 && odd)) |
| | dval(rv) += sulp(rv, bc); |
| | return 0; |
| | } |
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| |
|
| | double |
| | sb_stdnan(int sign) |
| | { |
| | U rv; |
| | word0(&rv) = NAN_WORD0; |
| | word1(&rv) = NAN_WORD1; |
| | if (sign) |
| | word0(&rv) |= Sign_bit; |
| | return dval(&rv); |
| | } |
| |
|
| | |
| | |
| |
|
| | double |
| | sb_infinity(int sign) |
| | { |
| | U rv; |
| | word0(&rv) = POSINF_WORD0; |
| | word1(&rv) = POSINF_WORD1; |
| | return sign ? -dval(&rv) : dval(&rv); |
| | } |
| |
|
| | double |
| | sb_strtod(const char *s00, char **se) |
| | { |
| | int bb2, bb5, bbe, bd2, bd5, bs2, c, dsign, e, e1, error; |
| | int esign, i, j, k, lz, nd, nd0, odd, sign; |
| | const char *s, *s0, *s1; |
| | double aadj, aadj1; |
| | U aadj2, adj, rv, rv0; |
| | ULong y, z, abs_exp; |
| | Long L; |
| | BCinfo bc; |
| | Bigint *bb, *bb1, *bd, *bd0, *bs, *delta; |
| | size_t ndigits, fraclen; |
| |
|
| | dval(&rv) = 0.; |
| |
|
| | |
| | c = *(s = s00); |
| |
|
| | |
| | sign = 0; |
| | switch (c) { |
| | case '-': |
| | sign = 1; |
| | |
| | case '+': |
| | c = *++s; |
| | } |
| |
|
| | |
| | s1 = s; |
| | while (c == '0') |
| | c = *++s; |
| | lz = s != s1; |
| |
|
| | |
| | |
| | |
| | |
| | s0 = s1 = s; |
| | while ('0' <= c && c <= '9') |
| | c = *++s; |
| | ndigits = s - s1; |
| | fraclen = 0; |
| |
|
| | |
| | if (c == '.') { |
| | c = *++s; |
| | if (!ndigits) { |
| | s1 = s; |
| | while (c == '0') |
| | c = *++s; |
| | lz = lz || s != s1; |
| | fraclen += (s - s1); |
| | s0 = s; |
| | } |
| | s1 = s; |
| | while ('0' <= c && c <= '9') |
| | c = *++s; |
| | ndigits += s - s1; |
| | fraclen += s - s1; |
| | } |
| |
|
| | |
| | |
| | |
| | if (!ndigits && !lz) { |
| | if (se) |
| | *se = (char *)s00; |
| | goto parse_error; |
| | } |
| |
|
| | |
| | |
| | if (ndigits > MAX_DIGITS || fraclen > MAX_DIGITS) { |
| | if (se) |
| | *se = (char *)s00; |
| | goto parse_error; |
| | } |
| | nd = (int)ndigits; |
| | nd0 = (int)ndigits - (int)fraclen; |
| |
|
| | |
| | e = 0; |
| | if (c == 'e' || c == 'E') { |
| | s00 = s; |
| | c = *++s; |
| |
|
| | |
| | esign = 0; |
| | switch (c) { |
| | case '-': |
| | esign = 1; |
| | |
| | case '+': |
| | c = *++s; |
| | } |
| |
|
| | |
| | s1 = s; |
| | while (c == '0') |
| | c = *++s; |
| | lz = s != s1; |
| |
|
| | |
| | s1 = s; |
| | abs_exp = 0; |
| | while ('0' <= c && c <= '9') { |
| | abs_exp = 10*abs_exp + (c - '0'); |
| | c = *++s; |
| | } |
| |
|
| | |
| | |
| | |
| | if (s - s1 > 9 || abs_exp > MAX_ABS_EXP) |
| | e = (int)MAX_ABS_EXP; |
| | else |
| | e = (int)abs_exp; |
| | if (esign) |
| | e = -e; |
| |
|
| | |
| | if (s == s1 && !lz) |
| | s = s00; |
| | } |
| |
|
| | |
| | e -= nd - nd0; |
| | if (nd0 <= 0) |
| | nd0 = nd; |
| |
|
| | |
| | if (se) |
| | *se = (char *)s; |
| |
|
| | |
| | |
| | if (!nd) |
| | goto ret; |
| | for (i = nd; i > 0; ) { |
| | --i; |
| | if (s0[i < nd0 ? i : i+1] != '0') { |
| | ++i; |
| | break; |
| | } |
| | } |
| | e += nd - i; |
| | nd = i; |
| | if (nd0 > nd) |
| | nd0 = nd; |
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| |
|
| | bc.e0 = e1 = e; |
| | y = z = 0; |
| | for (i = 0; i < nd; i++) { |
| | if (i < 9) |
| | y = 10*y + s0[i < nd0 ? i : i+1] - '0'; |
| | else if (i < DBL_DIG+1) |
| | z = 10*z + s0[i < nd0 ? i : i+1] - '0'; |
| | else |
| | break; |
| | } |
| |
|
| | k = nd < DBL_DIG + 1 ? nd : DBL_DIG + 1; |
| | dval(&rv) = y; |
| | if (k > 9) { |
| | dval(&rv) = tens[k - 9] * dval(&rv) + z; |
| | } |
| | bd0 = 0; |
| | if (nd <= DBL_DIG |
| | && Flt_Rounds == 1 |
| | ) { |
| | if (!e) |
| | goto ret; |
| | if (e > 0) { |
| | if (e <= Ten_pmax) { |
| | dval(&rv) *= tens[e]; |
| | goto ret; |
| | } |
| | i = DBL_DIG - nd; |
| | if (e <= Ten_pmax + i) { |
| | |
| | |
| | |
| | e -= i; |
| | dval(&rv) *= tens[i]; |
| | dval(&rv) *= tens[e]; |
| | goto ret; |
| | } |
| | } |
| | else if (e >= -Ten_pmax) { |
| | dval(&rv) /= tens[-e]; |
| | goto ret; |
| | } |
| | } |
| | e1 += nd - k; |
| |
|
| | bc.scale = 0; |
| |
|
| | |
| |
|
| | if (e1 > 0) { |
| | if ((i = e1 & 15)) |
| | dval(&rv) *= tens[i]; |
| | if (e1 &= ~15) { |
| | if (e1 > DBL_MAX_10_EXP) |
| | goto ovfl; |
| | e1 >>= 4; |
| | for(j = 0; e1 > 1; j++, e1 >>= 1) |
| | if (e1 & 1) |
| | dval(&rv) *= bigtens[j]; |
| | |
| | word0(&rv) -= P*Exp_msk1; |
| | dval(&rv) *= bigtens[j]; |
| | if ((z = word0(&rv) & Exp_mask) |
| | > Exp_msk1*(DBL_MAX_EXP+Bias-P)) |
| | goto ovfl; |
| | if (z > Exp_msk1*(DBL_MAX_EXP+Bias-1-P)) { |
| | |
| | |
| | word0(&rv) = Big0; |
| | word1(&rv) = Big1; |
| | } |
| | else |
| | word0(&rv) += P*Exp_msk1; |
| | } |
| | } |
| | else if (e1 < 0) { |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| |
|
| | e1 = -e1; |
| | if ((i = e1 & 15)) |
| | dval(&rv) /= tens[i]; |
| | if (e1 >>= 4) { |
| | if (e1 >= 1 << n_bigtens) |
| | goto undfl; |
| | if (e1 & Scale_Bit) |
| | bc.scale = 2*P; |
| | for(j = 0; e1 > 0; j++, e1 >>= 1) |
| | if (e1 & 1) |
| | dval(&rv) *= tinytens[j]; |
| | if (bc.scale && (j = 2*P + 1 - ((word0(&rv) & Exp_mask) |
| | >> Exp_shift)) > 0) { |
| | |
| | if (j >= 32) { |
| | word1(&rv) = 0; |
| | if (j >= 53) |
| | word0(&rv) = (P+2)*Exp_msk1; |
| | else |
| | word0(&rv) &= 0xffffffff << (j-32); |
| | } |
| | else |
| | word1(&rv) &= 0xffffffff << j; |
| | } |
| | if (!dval(&rv)) |
| | goto undfl; |
| | } |
| | } |
| |
|
| | |
| |
|
| | |
| |
|
| | bc.nd = nd; |
| | bc.nd0 = nd0; |
| | |
| | |
| | if (nd > STRTOD_DIGLIM) { |
| | |
| | |
| | |
| |
|
| | |
| | |
| | |
| | for (i = 18; i > 0; ) { |
| | |
| | |
| | --i; |
| | if (s0[i < nd0 ? i : i+1] != '0') { |
| | ++i; |
| | break; |
| | } |
| | } |
| | e += nd - i; |
| | nd = i; |
| | if (nd0 > nd) |
| | nd0 = nd; |
| | if (nd < 9) { |
| | y = 0; |
| | for(i = 0; i < nd0; ++i) |
| | y = 10*y + s0[i] - '0'; |
| | for(; i < nd; ++i) |
| | y = 10*y + s0[i+1] - '0'; |
| | } |
| | } |
| | bd0 = s2b(s0, nd0, nd, y); |
| | if (bd0 == NULL) |
| | goto failed_malloc; |
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| |
|
| | for(;;) { |
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| |
|
| | bd = Balloc(bd0->k); |
| | if (bd == NULL) { |
| | Bfree(bd0); |
| | goto failed_malloc; |
| | } |
| | Bcopy(bd, bd0); |
| | bb = sd2b(&rv, bc.scale, &bbe); |
| | if (bb == NULL) { |
| | Bfree(bd); |
| | Bfree(bd0); |
| | goto failed_malloc; |
| | } |
| | |
| | |
| | odd = bb->x[0] & 1; |
| |
|
| | |
| | bs = i2b(1); |
| | if (bs == NULL) { |
| | Bfree(bb); |
| | Bfree(bd); |
| | Bfree(bd0); |
| | goto failed_malloc; |
| | } |
| |
|
| | if (e >= 0) { |
| | bb2 = bb5 = 0; |
| | bd2 = bd5 = e; |
| | } |
| | else { |
| | bb2 = bb5 = -e; |
| | bd2 = bd5 = 0; |
| | } |
| | if (bbe >= 0) |
| | bb2 += bbe; |
| | else |
| | bd2 -= bbe; |
| | bs2 = bb2; |
| | bb2++; |
| | bd2++; |
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| |
|
| | |
| | i = bb2 < bd2 ? bb2 : bd2; |
| | if (i > bs2) |
| | i = bs2; |
| | if (i > 0) { |
| | bb2 -= i; |
| | bd2 -= i; |
| | bs2 -= i; |
| | } |
| |
|
| | |
| | if (bb5 > 0) { |
| | bs = pow5mult(bs, bb5); |
| | if (bs == NULL) { |
| | Bfree(bb); |
| | Bfree(bd); |
| | Bfree(bd0); |
| | goto failed_malloc; |
| | } |
| | bb1 = mult(bs, bb); |
| | Bfree(bb); |
| | bb = bb1; |
| | if (bb == NULL) { |
| | Bfree(bs); |
| | Bfree(bd); |
| | Bfree(bd0); |
| | goto failed_malloc; |
| | } |
| | } |
| | if (bb2 > 0) { |
| | bb = lshift(bb, bb2); |
| | if (bb == NULL) { |
| | Bfree(bs); |
| | Bfree(bd); |
| | Bfree(bd0); |
| | goto failed_malloc; |
| | } |
| | } |
| | if (bd5 > 0) { |
| | bd = pow5mult(bd, bd5); |
| | if (bd == NULL) { |
| | Bfree(bb); |
| | Bfree(bs); |
| | Bfree(bd0); |
| | goto failed_malloc; |
| | } |
| | } |
| | if (bd2 > 0) { |
| | bd = lshift(bd, bd2); |
| | if (bd == NULL) { |
| | Bfree(bb); |
| | Bfree(bs); |
| | Bfree(bd0); |
| | goto failed_malloc; |
| | } |
| | } |
| | if (bs2 > 0) { |
| | bs = lshift(bs, bs2); |
| | if (bs == NULL) { |
| | Bfree(bb); |
| | Bfree(bd); |
| | Bfree(bd0); |
| | goto failed_malloc; |
| | } |
| | } |
| |
|
| | |
| | |
| | |
| |
|
| | delta = diff(bb, bd); |
| | if (delta == NULL) { |
| | Bfree(bb); |
| | Bfree(bs); |
| | Bfree(bd); |
| | Bfree(bd0); |
| | goto failed_malloc; |
| | } |
| | dsign = delta->sign; |
| | delta->sign = 0; |
| | i = cmp(delta, bs); |
| | if (bc.nd > nd && i <= 0) { |
| | if (dsign) |
| | break; |
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| |
|
| | if (!word1(&rv) && !(word0(&rv) & Bndry_mask)) { |
| | |
| | |
| | j = (int)(word0(&rv) & Exp_mask) >> Exp_shift; |
| | |
| | |
| | if (j - bc.scale >= 2) { |
| | dval(&rv) -= 0.5 * sulp(&rv, &bc); |
| | break; |
| | } |
| | } |
| |
|
| | { |
| | bc.nd = nd; |
| | i = -1; |
| | } |
| | } |
| |
|
| | if (i < 0) { |
| | |
| | |
| | |
| | if (dsign || word1(&rv) || word0(&rv) & Bndry_mask |
| | || (word0(&rv) & Exp_mask) <= (2*P+1)*Exp_msk1 |
| | ) { |
| | break; |
| | } |
| | if (!delta->x[0] && delta->wds <= 1) { |
| | |
| | break; |
| | } |
| | delta = lshift(delta,Log2P); |
| | if (delta == NULL) { |
| | Bfree(bb); |
| | Bfree(bs); |
| | Bfree(bd); |
| | Bfree(bd0); |
| | goto failed_malloc; |
| | } |
| | if (cmp(delta, bs) > 0) |
| | goto drop_down; |
| | break; |
| | } |
| | if (i == 0) { |
| | |
| | if (dsign) { |
| | if ((word0(&rv) & Bndry_mask1) == Bndry_mask1 |
| | && word1(&rv) == ( |
| | (bc.scale && |
| | (y = word0(&rv) & Exp_mask) <= 2*P*Exp_msk1) ? |
| | (0xffffffff & (0xffffffff << (2*P+1-(y>>Exp_shift)))) : |
| | 0xffffffff)) { |
| | |
| | word0(&rv) = (word0(&rv) & Exp_mask) |
| | + Exp_msk1 |
| | ; |
| | word1(&rv) = 0; |
| | |
| | break; |
| | } |
| | } |
| | else if (!(word0(&rv) & Bndry_mask) && !word1(&rv)) { |
| | drop_down: |
| | |
| | if (bc.scale) { |
| | L = word0(&rv) & Exp_mask; |
| | if (L <= (2*P+1)*Exp_msk1) { |
| | if (L > (P+2)*Exp_msk1) |
| | |
| | |
| | break; |
| | |
| | if (bc.nd > nd) |
| | break; |
| | goto undfl; |
| | } |
| | } |
| | L = (word0(&rv) & Exp_mask) - Exp_msk1; |
| | word0(&rv) = L | Bndry_mask1; |
| | word1(&rv) = 0xffffffff; |
| | break; |
| | } |
| | if (!odd) |
| | break; |
| | if (dsign) |
| | dval(&rv) += sulp(&rv, &bc); |
| | else { |
| | dval(&rv) -= sulp(&rv, &bc); |
| | if (!dval(&rv)) { |
| | if (bc.nd >nd) |
| | break; |
| | goto undfl; |
| | } |
| | } |
| | |
| | break; |
| | } |
| | if ((aadj = ratio(delta, bs)) <= 2.) { |
| | if (dsign) |
| | aadj = aadj1 = 1.; |
| | else if (word1(&rv) || word0(&rv) & Bndry_mask) { |
| | if (word1(&rv) == Tiny1 && !word0(&rv)) { |
| | if (bc.nd >nd) |
| | break; |
| | goto undfl; |
| | } |
| | aadj = 1.; |
| | aadj1 = -1.; |
| | } |
| | else { |
| | |
| | |
| |
|
| | if (aadj < 2./FLT_RADIX) |
| | aadj = 1./FLT_RADIX; |
| | else |
| | aadj *= 0.5; |
| | aadj1 = -aadj; |
| | } |
| | } |
| | else { |
| | aadj *= 0.5; |
| | aadj1 = dsign ? aadj : -aadj; |
| | if (Flt_Rounds == 0) |
| | aadj1 += 0.5; |
| | } |
| | y = word0(&rv) & Exp_mask; |
| |
|
| | |
| |
|
| | if (y == Exp_msk1*(DBL_MAX_EXP+Bias-1)) { |
| | dval(&rv0) = dval(&rv); |
| | word0(&rv) -= P*Exp_msk1; |
| | adj.d = aadj1 * ulp(&rv); |
| | dval(&rv) += adj.d; |
| | if ((word0(&rv) & Exp_mask) >= |
| | Exp_msk1*(DBL_MAX_EXP+Bias-P)) { |
| | if (word0(&rv0) == Big0 && word1(&rv0) == Big1) { |
| | Bfree(bb); |
| | Bfree(bd); |
| | Bfree(bs); |
| | Bfree(bd0); |
| | Bfree(delta); |
| | goto ovfl; |
| | } |
| | word0(&rv) = Big0; |
| | word1(&rv) = Big1; |
| | goto cont; |
| | } |
| | else |
| | word0(&rv) += P*Exp_msk1; |
| | } |
| | else { |
| | if (bc.scale && y <= 2*P*Exp_msk1) { |
| | if (aadj <= 0x7fffffff) { |
| | if ((z = (ULong)aadj) <= 0) |
| | z = 1; |
| | aadj = z; |
| | aadj1 = dsign ? aadj : -aadj; |
| | } |
| | dval(&aadj2) = aadj1; |
| | word0(&aadj2) += (2*P+1)*Exp_msk1 - y; |
| | aadj1 = dval(&aadj2); |
| | } |
| | adj.d = aadj1 * ulp(&rv); |
| | dval(&rv) += adj.d; |
| | } |
| | z = word0(&rv) & Exp_mask; |
| | if (bc.nd == nd) { |
| | if (!bc.scale) |
| | if (y == z) { |
| | |
| | L = (Long)aadj; |
| | aadj -= L; |
| | |
| | if (dsign || word1(&rv) || word0(&rv) & Bndry_mask) { |
| | if (aadj < .4999999 || aadj > .5000001) |
| | break; |
| | } |
| | else if (aadj < .4999999/FLT_RADIX) |
| | break; |
| | } |
| | } |
| | cont: |
| | Bfree(bb); |
| | Bfree(bd); |
| | Bfree(bs); |
| | Bfree(delta); |
| | } |
| | Bfree(bb); |
| | Bfree(bd); |
| | Bfree(bs); |
| | Bfree(bd0); |
| | Bfree(delta); |
| | if (bc.nd > nd) { |
| | error = bigcomp(&rv, s0, &bc); |
| | if (error) |
| | goto failed_malloc; |
| | } |
| |
|
| | if (bc.scale) { |
| | word0(&rv0) = Exp_1 - 2*P*Exp_msk1; |
| | word1(&rv0) = 0; |
| | dval(&rv) *= dval(&rv0); |
| | } |
| |
|
| | ret: |
| | return sign ? -dval(&rv) : dval(&rv); |
| |
|
| | parse_error: |
| | return 0.0; |
| |
|
| | failed_malloc: |
| | errno = ENOMEM; |
| | return -1.0; |
| |
|
| | undfl: |
| | return sign ? -0.0 : 0.0; |
| |
|
| | ovfl: |
| | errno = ERANGE; |
| | |
| | word0(&rv) = Exp_mask; |
| | word1(&rv) = 0; |
| | return sign ? -dval(&rv) : dval(&rv); |
| |
|
| | } |
| |
|
| | static char * |
| | rv_alloc(int i) |
| | { |
| | int j, k, *r; |
| |
|
| | j = sizeof(ULong); |
| | for(k = 0; |
| | sizeof(Bigint) - sizeof(ULong) - sizeof(int) + j <= (unsigned)i; |
| | j <<= 1) |
| | k++; |
| | r = (int*)Balloc(k); |
| | if (r == NULL) |
| | return NULL; |
| | *r = k; |
| | return (char *)(r+1); |
| | } |
| |
|
| | static char * |
| | nrv_alloc(char *s, char **rve, int n) |
| | { |
| | char *rv, *t; |
| |
|
| | rv = rv_alloc(n); |
| | if (rv == NULL) |
| | return NULL; |
| | t = rv; |
| | while((*t = *s++)) t++; |
| | if (rve) |
| | *rve = t; |
| | return rv; |
| | } |
| |
|
| | |
| | |
| | |
| | |
| | |
| |
|
| | void |
| | sb_freedtoa(char *s) |
| | { |
| | Bigint *b = (Bigint *)((int *)s - 1); |
| | b->maxwds = 1 << (b->k = *(int*)b); |
| | Bfree(b); |
| | } |
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| |
|
| | |
| | |
| | |
| |
|
| | char * |
| | sb_dtoa(double dd, int mode, int ndigits, |
| | int *decpt, int *sign, char **rve) |
| | { |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| |
|
| | int bbits, b2, b5, be, dig, i, ieps, ilim, ilim0, ilim1, |
| | j, j1, k, k0, k_check, leftright, m2, m5, s2, s5, |
| | spec_case, try_quick; |
| | Long L; |
| | int denorm; |
| | ULong x; |
| | Bigint *b, *b1, *delta, *mlo, *mhi, *S; |
| | U d2, eps, u; |
| | double ds; |
| | char *s, *s0; |
| |
|
| | |
| | |
| | mlo = mhi = S = 0; |
| | s0 = 0; |
| |
|
| | u.d = dd; |
| | if (word0(&u) & Sign_bit) { |
| | |
| | *sign = 1; |
| | word0(&u) &= ~Sign_bit; |
| | } |
| | else |
| | *sign = 0; |
| |
|
| | |
| | if ((word0(&u) & Exp_mask) == Exp_mask) |
| | { |
| | |
| | *decpt = 9999; |
| | if (!word1(&u) && !(word0(&u) & 0xfffff)) |
| | return nrv_alloc("Infinity", rve, 8); |
| | return nrv_alloc("NaN", rve, 3); |
| | } |
| | if (!dval(&u)) { |
| | *decpt = 1; |
| | return nrv_alloc("0", rve, 1); |
| | } |
| |
|
| | |
| | |
| | b = d2b(&u, &be, &bbits); |
| | if (b == NULL) |
| | goto failed_malloc; |
| | if ((i = (int)(word0(&u) >> Exp_shift1 & (Exp_mask>>Exp_shift1)))) { |
| | dval(&d2) = dval(&u); |
| | word0(&d2) &= Frac_mask1; |
| | word0(&d2) |= Exp_11; |
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| |
|
| | i -= Bias; |
| | denorm = 0; |
| | } |
| | else { |
| | |
| |
|
| | i = bbits + be + (Bias + (P-1) - 1); |
| | x = i > 32 ? word0(&u) << (64 - i) | word1(&u) >> (i - 32) |
| | : word1(&u) << (32 - i); |
| | dval(&d2) = x; |
| | word0(&d2) -= 31*Exp_msk1; |
| | i -= (Bias + (P-1) - 1) + 1; |
| | denorm = 1; |
| | } |
| | ds = (dval(&d2)-1.5)*0.289529654602168 + 0.1760912590558 + |
| | i*0.301029995663981; |
| | k = (int)ds; |
| | if (ds < 0. && ds != k) |
| | k--; |
| | k_check = 1; |
| | if (k >= 0 && k <= Ten_pmax) { |
| | if (dval(&u) < tens[k]) |
| | k--; |
| | k_check = 0; |
| | } |
| | j = bbits - i - 1; |
| | if (j >= 0) { |
| | b2 = 0; |
| | s2 = j; |
| | } |
| | else { |
| | b2 = -j; |
| | s2 = 0; |
| | } |
| | if (k >= 0) { |
| | b5 = 0; |
| | s5 = k; |
| | s2 += k; |
| | } |
| | else { |
| | b2 -= k; |
| | b5 = -k; |
| | s5 = 0; |
| | } |
| | if (mode < 0 || mode > 9) |
| | mode = 0; |
| |
|
| | try_quick = 1; |
| |
|
| | if (mode > 5) { |
| | mode -= 4; |
| | try_quick = 0; |
| | } |
| | leftright = 1; |
| | ilim = ilim1 = -1; |
| | |
| | switch(mode) { |
| | case 0: |
| | case 1: |
| | i = 18; |
| | ndigits = 0; |
| | break; |
| | case 2: |
| | leftright = 0; |
| | |
| | case 4: |
| | if (ndigits <= 0) |
| | ndigits = 1; |
| | ilim = ilim1 = i = ndigits; |
| | break; |
| | case 3: |
| | leftright = 0; |
| | |
| | case 5: |
| | i = ndigits + k + 1; |
| | ilim = i; |
| | ilim1 = i - 1; |
| | if (i <= 0) |
| | i = 1; |
| | } |
| | s0 = rv_alloc(i); |
| | if (s0 == NULL) |
| | goto failed_malloc; |
| | s = s0; |
| |
|
| |
|
| | if (ilim >= 0 && ilim <= Quick_max && try_quick) { |
| |
|
| | |
| |
|
| | i = 0; |
| | dval(&d2) = dval(&u); |
| | k0 = k; |
| | ilim0 = ilim; |
| | ieps = 2; |
| | if (k > 0) { |
| | ds = tens[k&0xf]; |
| | j = k >> 4; |
| | if (j & Bletch) { |
| | |
| | j &= Bletch - 1; |
| | dval(&u) /= bigtens[n_bigtens-1]; |
| | ieps++; |
| | } |
| | for(; j; j >>= 1, i++) |
| | if (j & 1) { |
| | ieps++; |
| | ds *= bigtens[i]; |
| | } |
| | dval(&u) /= ds; |
| | } |
| | else if ((j1 = -k)) { |
| | dval(&u) *= tens[j1 & 0xf]; |
| | for(j = j1 >> 4; j; j >>= 1, i++) |
| | if (j & 1) { |
| | ieps++; |
| | dval(&u) *= bigtens[i]; |
| | } |
| | } |
| | if (k_check && dval(&u) < 1. && ilim > 0) { |
| | if (ilim1 <= 0) |
| | goto fast_failed; |
| | ilim = ilim1; |
| | k--; |
| | dval(&u) *= 10.; |
| | ieps++; |
| | } |
| | dval(&eps) = ieps*dval(&u) + 7.; |
| | word0(&eps) -= (P-1)*Exp_msk1; |
| | if (ilim == 0) { |
| | S = mhi = 0; |
| | dval(&u) -= 5.; |
| | if (dval(&u) > dval(&eps)) |
| | goto one_digit; |
| | if (dval(&u) < -dval(&eps)) |
| | goto no_digits; |
| | goto fast_failed; |
| | } |
| | if (leftright) { |
| | |
| | |
| | |
| | dval(&eps) = 0.5/tens[ilim-1] - dval(&eps); |
| | for(i = 0;;) { |
| | L = (Long)dval(&u); |
| | dval(&u) -= L; |
| | *s++ = '0' + (int)L; |
| | if (dval(&u) < dval(&eps)) |
| | goto ret1; |
| | if (1. - dval(&u) < dval(&eps)) |
| | goto bump_up; |
| | if (++i >= ilim) |
| | break; |
| | dval(&eps) *= 10.; |
| | dval(&u) *= 10.; |
| | } |
| | } |
| | else { |
| | |
| | dval(&eps) *= tens[ilim-1]; |
| | for(i = 1;; i++, dval(&u) *= 10.) { |
| | L = (Long)(dval(&u)); |
| | if (!(dval(&u) -= L)) |
| | ilim = i; |
| | *s++ = '0' + (int)L; |
| | if (i == ilim) { |
| | if (dval(&u) > 0.5 + dval(&eps)) |
| | goto bump_up; |
| | else if (dval(&u) < 0.5 - dval(&eps)) { |
| | while(*--s == '0'); |
| | s++; |
| | goto ret1; |
| | } |
| | break; |
| | } |
| | } |
| | } |
| | fast_failed: |
| | s = s0; |
| | dval(&u) = dval(&d2); |
| | k = k0; |
| | ilim = ilim0; |
| | } |
| |
|
| | |
| |
|
| | if (be >= 0 && k <= Int_max) { |
| | |
| | ds = tens[k]; |
| | if (ndigits < 0 && ilim <= 0) { |
| | S = mhi = 0; |
| | if (ilim < 0 || dval(&u) <= 5*ds) |
| | goto no_digits; |
| | goto one_digit; |
| | } |
| | for(i = 1;; i++, dval(&u) *= 10.) { |
| | L = (Long)(dval(&u) / ds); |
| | dval(&u) -= L*ds; |
| | *s++ = '0' + (int)L; |
| | if (!dval(&u)) { |
| | break; |
| | } |
| | if (i == ilim) { |
| | dval(&u) += dval(&u); |
| | if (dval(&u) > ds || (dval(&u) == ds && L & 1)) { |
| | bump_up: |
| | while(*--s == '9') |
| | if (s == s0) { |
| | k++; |
| | *s = '0'; |
| | break; |
| | } |
| | ++*s++; |
| | } |
| | break; |
| | } |
| | } |
| | goto ret1; |
| | } |
| |
|
| | m2 = b2; |
| | m5 = b5; |
| | if (leftright) { |
| | i = |
| | denorm ? be + (Bias + (P-1) - 1 + 1) : |
| | 1 + P - bbits; |
| | b2 += i; |
| | s2 += i; |
| | mhi = i2b(1); |
| | if (mhi == NULL) |
| | goto failed_malloc; |
| | } |
| | if (m2 > 0 && s2 > 0) { |
| | i = m2 < s2 ? m2 : s2; |
| | b2 -= i; |
| | m2 -= i; |
| | s2 -= i; |
| | } |
| | if (b5 > 0) { |
| | if (leftright) { |
| | if (m5 > 0) { |
| | mhi = pow5mult(mhi, m5); |
| | if (mhi == NULL) |
| | goto failed_malloc; |
| | b1 = mult(mhi, b); |
| | Bfree(b); |
| | b = b1; |
| | if (b == NULL) |
| | goto failed_malloc; |
| | } |
| | if ((j = b5 - m5)) { |
| | b = pow5mult(b, j); |
| | if (b == NULL) |
| | goto failed_malloc; |
| | } |
| | } |
| | else { |
| | b = pow5mult(b, b5); |
| | if (b == NULL) |
| | goto failed_malloc; |
| | } |
| | } |
| | S = i2b(1); |
| | if (S == NULL) |
| | goto failed_malloc; |
| | if (s5 > 0) { |
| | S = pow5mult(S, s5); |
| | if (S == NULL) |
| | goto failed_malloc; |
| | } |
| |
|
| | |
| |
|
| | spec_case = 0; |
| | if ((mode < 2 || leftright) |
| | ) { |
| | if (!word1(&u) && !(word0(&u) & Bndry_mask) |
| | && word0(&u) & (Exp_mask & ~Exp_msk1) |
| | ) { |
| | |
| | b2 += Log2P; |
| | s2 += Log2P; |
| | spec_case = 1; |
| | } |
| | } |
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | #define iInc 28 |
| | i = dshift(S, s2); |
| | b2 += i; |
| | m2 += i; |
| | s2 += i; |
| | if (b2 > 0) { |
| | b = lshift(b, b2); |
| | if (b == NULL) |
| | goto failed_malloc; |
| | } |
| | if (s2 > 0) { |
| | S = lshift(S, s2); |
| | if (S == NULL) |
| | goto failed_malloc; |
| | } |
| | if (k_check) { |
| | if (cmp(b,S) < 0) { |
| | k--; |
| | b = multadd(b, 10, 0); |
| | if (b == NULL) |
| | goto failed_malloc; |
| | if (leftright) { |
| | mhi = multadd(mhi, 10, 0); |
| | if (mhi == NULL) |
| | goto failed_malloc; |
| | } |
| | ilim = ilim1; |
| | } |
| | } |
| | if (ilim <= 0 && (mode == 3 || mode == 5)) { |
| | if (ilim < 0) { |
| | |
| | no_digits: |
| | k = -1 - ndigits; |
| | goto ret; |
| | } |
| | else { |
| | S = multadd(S, 5, 0); |
| | if (S == NULL) |
| | goto failed_malloc; |
| | if (cmp(b, S) <= 0) |
| | goto no_digits; |
| | } |
| | one_digit: |
| | *s++ = '1'; |
| | k++; |
| | goto ret; |
| | } |
| | if (leftright) { |
| | if (m2 > 0) { |
| | mhi = lshift(mhi, m2); |
| | if (mhi == NULL) |
| | goto failed_malloc; |
| | } |
| |
|
| | |
| | |
| | |
| |
|
| | mlo = mhi; |
| | if (spec_case) { |
| | mhi = Balloc(mhi->k); |
| | if (mhi == NULL) |
| | goto failed_malloc; |
| | Bcopy(mhi, mlo); |
| | mhi = lshift(mhi, Log2P); |
| | if (mhi == NULL) |
| | goto failed_malloc; |
| | } |
| |
|
| | for(i = 1;;i++) { |
| | dig = quorem(b,S) + '0'; |
| | |
| | |
| | |
| | j = cmp(b, mlo); |
| | delta = diff(S, mhi); |
| | if (delta == NULL) |
| | goto failed_malloc; |
| | j1 = delta->sign ? 1 : cmp(b, delta); |
| | Bfree(delta); |
| | if (j1 == 0 && mode != 1 && !(word1(&u) & 1) |
| | ) { |
| | if (dig == '9') |
| | goto round_9_up; |
| | if (j > 0) |
| | dig++; |
| | *s++ = dig; |
| | goto ret; |
| | } |
| | if (j < 0 || (j == 0 && mode != 1 |
| | && !(word1(&u) & 1) |
| | )) { |
| | if (!b->x[0] && b->wds <= 1) { |
| | goto accept_dig; |
| | } |
| | if (j1 > 0) { |
| | b = lshift(b, 1); |
| | if (b == NULL) |
| | goto failed_malloc; |
| | j1 = cmp(b, S); |
| | if ((j1 > 0 || (j1 == 0 && dig & 1)) |
| | && dig++ == '9') |
| | goto round_9_up; |
| | } |
| | accept_dig: |
| | *s++ = dig; |
| | goto ret; |
| | } |
| | if (j1 > 0) { |
| | if (dig == '9') { |
| | round_9_up: |
| | *s++ = '9'; |
| | goto roundoff; |
| | } |
| | *s++ = dig + 1; |
| | goto ret; |
| | } |
| | *s++ = dig; |
| | if (i == ilim) |
| | break; |
| | b = multadd(b, 10, 0); |
| | if (b == NULL) |
| | goto failed_malloc; |
| | if (mlo == mhi) { |
| | mlo = mhi = multadd(mhi, 10, 0); |
| | if (mlo == NULL) |
| | goto failed_malloc; |
| | } |
| | else { |
| | mlo = multadd(mlo, 10, 0); |
| | if (mlo == NULL) |
| | goto failed_malloc; |
| | mhi = multadd(mhi, 10, 0); |
| | if (mhi == NULL) |
| | goto failed_malloc; |
| | } |
| | } |
| | } |
| | else |
| | for(i = 1;; i++) { |
| | *s++ = dig = quorem(b,S) + '0'; |
| | if (!b->x[0] && b->wds <= 1) { |
| | goto ret; |
| | } |
| | if (i >= ilim) |
| | break; |
| | b = multadd(b, 10, 0); |
| | if (b == NULL) |
| | goto failed_malloc; |
| | } |
| |
|
| | |
| |
|
| | b = lshift(b, 1); |
| | if (b == NULL) |
| | goto failed_malloc; |
| | j = cmp(b, S); |
| | if (j > 0 || (j == 0 && dig & 1)) { |
| | roundoff: |
| | while(*--s == '9') |
| | if (s == s0) { |
| | k++; |
| | *s++ = '1'; |
| | goto ret; |
| | } |
| | ++*s++; |
| | } |
| | else { |
| | while(*--s == '0'); |
| | s++; |
| | } |
| | ret: |
| | Bfree(S); |
| | if (mhi) { |
| | if (mlo && mlo != mhi) |
| | Bfree(mlo); |
| | Bfree(mhi); |
| | } |
| | ret1: |
| | Bfree(b); |
| | *s = 0; |
| | *decpt = k + 1; |
| | if (rve) |
| | *rve = s; |
| | return s0; |
| | failed_malloc: |
| | if (S) |
| | Bfree(S); |
| | if (mlo && mlo != mhi) |
| | Bfree(mlo); |
| | if (mhi) |
| | Bfree(mhi); |
| | if (b) |
| | Bfree(b); |
| | if (s0) |
| | sb_freedtoa(s0); |
| | return NULL; |
| | } |
| | #ifdef __cplusplus |
| | } |
| | #endif |
| |
|