/* __ldtoa: wrapper for long double conversion using gdtoa() NOTE: This only works for IEEE extended precision long doubles. Input: ld - a pointer to the value to convert The rest of the parameters are the analogous to the corresponding parameters to gdtoa(). Returns: This function returns a string that is to be free'd with freedtoa(). */ char * __ldtoa(long double *ld, int mode, int ndigits, int *decpt, int *sign, char **rve) { FPI fpi = { 64, /* nbits */ 1 - 16383 - 63, /* emin */ 32766 - 16383 - 63, /* emax */ 1, /* rounding */ 0 /* sudden_underflow */ }; union ieee_ext *l; uint32_t bits[2]; int exp, kind; char *ret; l = (union ieee_ext *) ld; *sign = l->ieee.sgn; exp = l->ieee.exp; bits[0] = l->ieee.mt0; bits[1] = l->ieee.mt1; if (isnan(*ld)) /* NaN */ kind = STRTOG_NaN; else if (isinf(*ld)) /* Infinity */ kind = STRTOG_Infinite; else if (exp == 0) /* Denormalized */ { kind = STRTOG_Denormal; exp = 1; } else /* Normalized or zero */ { if (bits[0] | bits[1]) kind = STRTOG_Normal; else kind = STRTOG_Zero; } exp -= 16383 + 63; ret = gdtoa(&fpi, exp, &bits[0], &kind, mode, ndigits, decpt, rve); if (*decpt == -32768) *decpt = INT_MAX; return ret; }
g_xfmt(char *buf, void *V, int ndig, size_t bufsize) #endif { static FPI fpi0 = { 64, 1-16383-64+1, 32766 - 16383 - 64 + 1, 1, 0 }; char *b, *s, *se; ULong bits[2], sign; UShort *L; int decpt, ex, i, mode; #ifdef Honor_FLT_ROUNDS #include "gdtoa_fltrnds.h" #else #define fpi &fpi0 #endif if (ndig < 0) ndig = 0; if (bufsize < ndig + 10) return 0; L = (UShort *)V; sign = L[_0] & 0x8000; bits[1] = (L[_1] << 16) | L[_2]; bits[0] = (L[_3] << 16) | L[_4]; if ( (ex = L[_0] & 0x7fff) !=0) { if (ex == 0x7fff) { /* Infinity or NaN */ if (bits[0] | bits[1]) b = strcp(buf, "NaN"); else { b = buf; if (sign) *b++ = '-'; b = strcp(b, "Infinity"); } return b; } i = STRTOG_Normal; } else if (bits[0] | bits[1]) { i = STRTOG_Denormal; ex = 1; } else { b = buf; #ifndef IGNORE_ZERO_SIGN if (sign) *b++ = '-'; #endif *b++ = '0'; *b = 0; return b; } ex -= 0x3fff + 63; mode = 2; if (ndig <= 0) { if (bufsize < 32) return 0; mode = 0; } s = gdtoa(fpi, ex, bits, &i, mode, ndig, &decpt, &se); return g__fmt(buf, s, se, decpt, sign, bufsize); }
/* * ldtoa() is a wrapper for gdtoa() that makes it smell like dtoa(), * except that the floating point argument is passed by reference. * When dtoa() is passed a NaN or infinity, it sets expt to 9999. * However, a long double could have a valid exponent of 9999, so we * use INT_MAX in ldtoa() instead. */ char * __ldtoa(long double *ld, int mode, int ndigits, int *decpt, int *sign, char **rve) { FPI fpi = { LDBL_MANT_DIG, /* nbits */ LDBL_MIN_EXP - LDBL_MANT_DIG, /* emin */ LDBL_MAX_EXP - LDBL_MANT_DIG, /* emax */ FLT_ROUNDS, /* rounding */ #ifdef Sudden_Underflow /* unused, but correct anyway */ 1 #else 0 #endif }; int be, kind; char *ret; struct ieee_ext *p = (struct ieee_ext *)ld; uint32_t bits[(LDBL_MANT_DIG + 31) / 32]; void *vbits = bits; /* * gdtoa doesn't know anything about the sign of the number, so * if the number is negative, we need to swap rounding modes of * 2 (upwards) and 3 (downwards). */ *sign = p->ext_sign; fpi.rounding ^= (fpi.rounding >> 1) & p->ext_sign; be = p->ext_exp - (LDBL_MAX_EXP - 1) - (LDBL_MANT_DIG - 1); EXT_TO_ARRAY32(p, bits); switch (fpclassify(*ld)) { case FP_NORMAL: kind = STRTOG_Normal; #ifdef EXT_IMPLICIT_NBIT bits[LDBL_MANT_DIG / 32] |= 1 << ((LDBL_MANT_DIG - 1) % 32); #endif /* EXT_IMPLICIT_NBIT */ break; case FP_ZERO: kind = STRTOG_Zero; break; case FP_SUBNORMAL: kind = STRTOG_Denormal; be++; break; case FP_INFINITE: kind = STRTOG_Infinite; break; case FP_NAN: kind = STRTOG_NaN; break; default: abort(); } ret = gdtoa(&fpi, be, vbits, &kind, mode, ndigits, decpt, rve); if (*decpt == -32768) *decpt = INT_MAX; return ret; }
g_ddfmt(char *buf, double *dd0, int ndig, size_t bufsize) #endif { FPI fpi; char *b, *s, *se; ULong *L, bits0[4], *bits, *zx; int bx, by, decpt, ex, ey, i, j, mode; Bigint *x, *y, *z; U *dd, ddx[2]; #ifdef Honor_FLT_ROUNDS /*{{*/ int Rounding; #ifdef Trust_FLT_ROUNDS /*{{ only define this if FLT_ROUNDS really works! */ Rounding = Flt_Rounds; #else /*}{*/ Rounding = 1; switch(fegetround()) { case FE_TOWARDZERO: Rounding = 0; break; case FE_UPWARD: Rounding = 2; break; case FE_DOWNWARD: Rounding = 3; } #endif /*}}*/ #else /*}{*/ #define Rounding FPI_Round_near #endif /*}}*/ if (bufsize < 10 || bufsize < ndig + 8) return 0; dd = (U*)dd0; L = dd->L; if ((L[_0] & 0x7ff00000L) == 0x7ff00000L) { /* Infinity or NaN */ if (L[_0] & 0xfffff || L[_1]) { nanret: return strcp(buf, "NaN"); } if ((L[2+_0] & 0x7ff00000) == 0x7ff00000) { if (L[2+_0] & 0xfffff || L[2+_1]) goto nanret; if ((L[_0] ^ L[2+_0]) & 0x80000000L) goto nanret; /* Infinity - Infinity */ } infret: b = buf; if (L[_0] & 0x80000000L) *b++ = '-'; return strcp(b, "Infinity"); } if ((L[2+_0] & 0x7ff00000) == 0x7ff00000) { L += 2; if (L[_0] & 0xfffff || L[_1]) goto nanret; goto infret; } if (dval(&dd[0]) + dval(&dd[1]) == 0.) { b = buf; #ifndef IGNORE_ZERO_SIGN if (L[_0] & L[2+_0] & 0x80000000L) *b++ = '-'; #endif *b++ = '0'; *b = 0; return b; } if ((L[_0] & 0x7ff00000L) < (L[2+_0] & 0x7ff00000L)) { dval(&ddx[1]) = dval(&dd[0]); dval(&ddx[0]) = dval(&dd[1]); dd = ddx; L = dd->L; } z = d2b(dval(&dd[0]), &ex, &bx); if (dval(&dd[1]) == 0.) goto no_y; x = z; y = d2b(dval(&dd[1]), &ey, &by); if ( (i = ex - ey) !=0) { if (i > 0) { x = lshift(x, i); ex = ey; } else y = lshift(y, -i); } if ((L[_0] ^ L[2+_0]) & 0x80000000L) { z = diff(x, y); if (L[_0] & 0x80000000L) z->sign = 1 - z->sign; } else { z = sum(x, y); if (L[_0] & 0x80000000L) z->sign = 1; } Bfree(x); Bfree(y); no_y: bits = zx = z->x; for(i = 0; !*zx; zx++) i += 32; i += lo0bits(zx); if (i) { rshift(z, i); ex += i; } fpi.nbits = z->wds * 32 - hi0bits(z->x[j = z->wds-1]); if (fpi.nbits < 106) { fpi.nbits = 106; if (j < 3) { for(i = 0; i <= j; i++) bits0[i] = bits[i]; while(i < 4) bits0[i++] = 0; bits = bits0; } } mode = 2; if (ndig <= 0) { if (bufsize < (int)(fpi.nbits * .301029995664) + 10) { Bfree(z); return 0; } mode = 0; } fpi.emin = 1-1023-53+1; fpi.emax = 2046-1023-106+1; fpi.rounding = Rounding; fpi.sudden_underflow = 0; i = STRTOG_Normal; s = gdtoa(&fpi, ex, bits, &i, mode, ndig, &decpt, &se); b = g__fmt(buf, s, se, decpt, z->sign, bufsize); Bfree(z); return b; }
/* * ldtoa() is a wrapper for gdtoa() that makes it smell like dtoa(), * except that the floating point argument is passed by reference. * When dtoa() is passed a NaN or infinity, it sets expt to 9999. * However, a long double could have a valid exponent of 9999, so we * use INT_MAX in ldtoa() instead. */ char * __ldtoa(long double *ld, int mode, int ndigits, int *decpt, int *sign, char **rve) { #if defined(__arm__) /* On arm, double == long double, so short circuit this */ char * ret = __dtoa((double)*ld, mode, ndigits, decpt, sign, rve); if (*decpt == 9999) *decpt = INT_MAX; return ret; #else FPI fpi = { LDBL_MANT_DIG, /* nbits */ LDBL_MIN_EXP - LDBL_MANT_DIG, /* emin */ LDBL_MAX_EXP - LDBL_MANT_DIG, /* emax */ FLT_ROUNDS, /* rounding */ #ifdef Sudden_Underflow /* unused, but correct anyway */ 1 #else 0 #endif }; int be, kind; char *ret; union IEEEl2bits u; uint32_t bits[(LDBL_MANT_DIG + 31) / 32]; void *vbits = bits; int type; u.e = *ld; type = fpclassify(u.e); /* * gdtoa doesn't know anything about the sign of the number, so * if the number is negative, we need to swap rounding modes of * 2 (upwards) and 3 (downwards). */ *sign = u.bits.sign; fpi.rounding ^= (fpi.rounding >> 1) & u.bits.sign; be = u.bits.exp - (LDBL_MAX_EXP - 1) - (LDBL_MANT_DIG - 1); LDBL_TO_ARRAY32(u, bits); switch (type) { case FP_NORMAL: case FP_SUPERNORMAL: kind = STRTOG_Normal; #ifdef LDBL_IMPLICIT_NBIT bits[LDBL_MANT_DIG / 32] |= 1 << ((LDBL_MANT_DIG - 1) % 32); #endif /* LDBL_IMPLICIT_NBIT */ break; case FP_ZERO: kind = STRTOG_Zero; break; case FP_SUBNORMAL: kind = STRTOG_Denormal; be++; break; case FP_INFINITE: kind = STRTOG_Infinite; break; case FP_NAN: kind = STRTOG_NaN; break; default: LIBC_ABORT("fpclassify returned %d", type); } ret = gdtoa(&fpi, be, vbits, &kind, mode, ndigits, decpt, rve); if (*decpt == -32768) *decpt = INT_MAX; return ret; #endif }