1*4887Schin /*********************************************************************** 2*4887Schin * * 3*4887Schin * This software is part of the ast package * 4*4887Schin * Copyright (c) 1985-2007 AT&T Knowledge Ventures * 5*4887Schin * and is licensed under the * 6*4887Schin * Common Public License, Version 1.0 * 7*4887Schin * by AT&T Knowledge Ventures * 8*4887Schin * * 9*4887Schin * A copy of the License is available at * 10*4887Schin * http://www.opensource.org/licenses/cpl1.0.txt * 11*4887Schin * (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) * 12*4887Schin * * 13*4887Schin * Information and Software Systems Research * 14*4887Schin * AT&T Research * 15*4887Schin * Florham Park NJ * 16*4887Schin * * 17*4887Schin * Glenn Fowler <gsf@research.att.com> * 18*4887Schin * David Korn <dgk@research.att.com> * 19*4887Schin * Phong Vo <kpv@research.att.com> * 20*4887Schin * * 21*4887Schin ***********************************************************************/ 22*4887Schin #include "sfhdr.h" 23*4887Schin 24*4887Schin /* Convert a floating point value to ASCII. 25*4887Schin ** 26*4887Schin ** Written by Kiem-Phong Vo and Glenn Fowler (SFFMT_AFORMAT) 27*4887Schin */ 28*4887Schin 29*4887Schin static char *lc_inf = "inf", *uc_inf = "INF"; 30*4887Schin static char *lc_nan = "nan", *uc_nan = "NAN"; 31*4887Schin static char *Zero = "0"; 32*4887Schin #define SF_INF ((_Sfi = 3), strncpy(buf, (format & SFFMT_UPPER) ? uc_inf : lc_inf, size)) 33*4887Schin #define SF_NAN ((_Sfi = 3), strncpy(buf, (format & SFFMT_UPPER) ? uc_nan : lc_nan, size)) 34*4887Schin #define SF_ZERO ((_Sfi = 1), strncpy(buf, Zero, size)) 35*4887Schin #define SF_INTPART (SF_IDIGITS/2) 36*4887Schin 37*4887Schin #if ! _lib_isnan 38*4887Schin #if _lib_fpclassify 39*4887Schin #define isnan(n) (fpclassify(n)==FP_NAN) 40*4887Schin #define isnanl(n) (fpclassify(n)==FP_NAN) 41*4887Schin #else 42*4887Schin #define isnan(n) (memcmp((void*)&n,(void*)&_Sfdnan,sizeof(n))==0) 43*4887Schin #define isnanl(n) (memcmp((void*)&n,(void*)&_Sflnan,sizeof(n))==0) 44*4887Schin #endif 45*4887Schin #else 46*4887Schin #if ! _lib_isnanl 47*4887Schin #define isnanl(n) isnan(n) 48*4887Schin #endif 49*4887Schin #endif 50*4887Schin 51*4887Schin #if __STD_C 52*4887Schin char* _sfcvt(Sfdouble_t dv, char* buf, size_t size, int n_digit, 53*4887Schin int* decpt, int* sign, int* len, int format) 54*4887Schin #else 55*4887Schin char* _sfcvt(dv,buf,size,n_digit,decpt,sign,len,format) 56*4887Schin Sfdouble_t dv; /* value to convert */ 57*4887Schin char* buf; /* conversion goes here */ 58*4887Schin size_t size; /* size of buf */ 59*4887Schin int n_digit; /* number of digits wanted */ 60*4887Schin int* decpt; /* to return decimal point */ 61*4887Schin int* sign; /* to return sign */ 62*4887Schin int* len; /* return string length */ 63*4887Schin int format; /* conversion format */ 64*4887Schin #endif 65*4887Schin { 66*4887Schin reg char *sp; 67*4887Schin reg long n, v; 68*4887Schin reg char *ep, *b, *endsp; 69*4887Schin _ast_flt_unsigned_max_t m; 70*4887Schin 71*4887Schin static char lx[] = "0123456789abcdef"; 72*4887Schin static char ux[] = "0123456789ABCDEF"; 73*4887Schin 74*4887Schin *sign = *decpt = 0; 75*4887Schin 76*4887Schin if(isnanl(dv)) 77*4887Schin return SF_NAN; 78*4887Schin #if _lib_isinf 79*4887Schin if (n = isinf(dv)) 80*4887Schin { if (n < 0) 81*4887Schin *sign = 1; 82*4887Schin return SF_INF; 83*4887Schin } 84*4887Schin #endif 85*4887Schin #if !_ast_fltmax_double 86*4887Schin if(format&SFFMT_LDOUBLE) 87*4887Schin { Sfdouble_t f = dv; 88*4887Schin #if _c99_in_the_wild 89*4887Schin #if _lib_signbit 90*4887Schin if (signbit(f)) 91*4887Schin #else 92*4887Schin #if _lib_copysignl 93*4887Schin if (copysignl(1.0, f) < 0.0) 94*4887Schin #else 95*4887Schin #if _lib_copysign 96*4887Schin if (copysign(1.0, (double)f) < 0.0) 97*4887Schin #else 98*4887Schin if (f < 0.0) 99*4887Schin #endif 100*4887Schin #endif 101*4887Schin #endif 102*4887Schin { f = -f; 103*4887Schin *sign = 1; 104*4887Schin } 105*4887Schin #if _lib_fpclassify 106*4887Schin switch (fpclassify(f)) 107*4887Schin { 108*4887Schin case FP_INFINITE: 109*4887Schin return SF_INF; 110*4887Schin case FP_NAN: 111*4887Schin return SF_NAN; 112*4887Schin case FP_ZERO: 113*4887Schin return SF_ZERO; 114*4887Schin } 115*4887Schin #endif 116*4887Schin #else 117*4887Schin if (f < 0.0) 118*4887Schin { f = -f; 119*4887Schin *sign = 1; 120*4887Schin } 121*4887Schin #endif 122*4887Schin if(f < LDBL_MIN) 123*4887Schin return SF_ZERO; 124*4887Schin if(f > LDBL_MAX) 125*4887Schin return SF_INF; 126*4887Schin 127*4887Schin if(format & SFFMT_AFORMAT) 128*4887Schin { Sfdouble_t g; 129*4887Schin int x; 130*4887Schin b = sp = buf; 131*4887Schin ep = (format & SFFMT_UPPER) ? ux : lx; 132*4887Schin if(n_digit <= 0 || n_digit >= (size - 9)) 133*4887Schin n_digit = size - 9; 134*4887Schin endsp = sp + n_digit + 1; 135*4887Schin 136*4887Schin g = frexpl(f, &x); 137*4887Schin *decpt = x; 138*4887Schin f = ldexpl(g, 8 * sizeof(m) - 3); 139*4887Schin 140*4887Schin for (;;) 141*4887Schin { m = f; 142*4887Schin x = 8 * sizeof(m); 143*4887Schin while ((x -= 4) >= 0) 144*4887Schin { *sp++ = ep[(m >> x) & 0xf]; 145*4887Schin if (sp >= endsp) 146*4887Schin { ep = sp + 1; 147*4887Schin goto done; 148*4887Schin } 149*4887Schin } 150*4887Schin f -= m; 151*4887Schin f = ldexpl(f, 8 * sizeof(m)); 152*4887Schin } 153*4887Schin } 154*4887Schin 155*4887Schin n = 0; 156*4887Schin if(f >= (Sfdouble_t)SF_MAXLONG) 157*4887Schin { /* scale to a small enough number to fit an int */ 158*4887Schin v = SF_MAXEXP10-1; 159*4887Schin do 160*4887Schin { if(f < _Sfpos10[v]) 161*4887Schin v -= 1; 162*4887Schin else 163*4887Schin { 164*4887Schin f *= _Sfneg10[v]; 165*4887Schin if((n += (1<<v)) >= SF_IDIGITS) 166*4887Schin return SF_INF; 167*4887Schin } 168*4887Schin } while(f >= (Sfdouble_t)SF_MAXLONG); 169*4887Schin } 170*4887Schin *decpt = (int)n; 171*4887Schin 172*4887Schin b = sp = buf + SF_INTPART; 173*4887Schin if((v = (long)f) != 0) 174*4887Schin { /* translate the integer part */ 175*4887Schin f -= (Sfdouble_t)v; 176*4887Schin 177*4887Schin sfucvt(v,sp,n,ep,long,ulong); 178*4887Schin 179*4887Schin n = b-sp; 180*4887Schin if((*decpt += (int)n) >= SF_IDIGITS) 181*4887Schin return SF_INF; 182*4887Schin b = sp; 183*4887Schin sp = buf + SF_INTPART; 184*4887Schin } 185*4887Schin else n = 0; 186*4887Schin 187*4887Schin /* remaining number of digits to compute; add 1 for later rounding */ 188*4887Schin n = (((format&SFFMT_EFORMAT) || *decpt <= 0) ? 1 : *decpt+1) - n; 189*4887Schin if(n_digit > 0) 190*4887Schin { if(n_digit > LDBL_DIG) 191*4887Schin n_digit = LDBL_DIG; 192*4887Schin n += n_digit; 193*4887Schin } 194*4887Schin 195*4887Schin if((ep = (sp+n)) > (endsp = buf+(size-2))) 196*4887Schin ep = endsp; 197*4887Schin if(sp > ep) 198*4887Schin sp = ep; 199*4887Schin else 200*4887Schin { 201*4887Schin if((format&SFFMT_EFORMAT) && *decpt == 0 && f > 0.) 202*4887Schin { Sfdouble_t d; 203*4887Schin while((long)(d = f*10.) == 0) 204*4887Schin { f = d; 205*4887Schin *decpt -= 1; 206*4887Schin } 207*4887Schin } 208*4887Schin 209*4887Schin while(sp < ep) 210*4887Schin { /* generate fractional digits */ 211*4887Schin if(f <= 0.) 212*4887Schin { /* fill with 0's */ 213*4887Schin do { *sp++ = '0'; } while(sp < ep); 214*4887Schin goto done; 215*4887Schin } 216*4887Schin else if((n = (long)(f *= 10.)) < 10) 217*4887Schin { *sp++ = '0' + n; 218*4887Schin f -= n; 219*4887Schin } 220*4887Schin else /* n == 10 */ 221*4887Schin { do { *sp++ = '9'; } while(sp < ep); 222*4887Schin } 223*4887Schin } 224*4887Schin } 225*4887Schin } else 226*4887Schin #endif 227*4887Schin { double f = (double)dv; 228*4887Schin 229*4887Schin #if _lib_isinf 230*4887Schin if (n = isinf(f)) 231*4887Schin { if (n < 0) 232*4887Schin *sign = 1; 233*4887Schin return SF_INF; 234*4887Schin } 235*4887Schin #endif 236*4887Schin #if _c99_in_the_wild 237*4887Schin #if _lib_signbit 238*4887Schin if (signbit(f)) 239*4887Schin #else 240*4887Schin #if _lib_copysign 241*4887Schin if (copysign(1.0, f) < 0.0) 242*4887Schin #else 243*4887Schin if (f < 0.0) 244*4887Schin #endif 245*4887Schin #endif 246*4887Schin { f = -f; 247*4887Schin *sign = 1; 248*4887Schin } 249*4887Schin #if _lib_fpclassify 250*4887Schin switch (fpclassify(f)) 251*4887Schin { 252*4887Schin case FP_INFINITE: 253*4887Schin return SF_INF; 254*4887Schin case FP_NAN: 255*4887Schin return SF_NAN; 256*4887Schin case FP_ZERO: 257*4887Schin return SF_ZERO; 258*4887Schin } 259*4887Schin #endif 260*4887Schin #else 261*4887Schin if (f < 0.0) 262*4887Schin { f = -f; 263*4887Schin *sign = 1; 264*4887Schin } 265*4887Schin #endif 266*4887Schin if(f < DBL_MIN) 267*4887Schin return SF_ZERO; 268*4887Schin if(f > DBL_MAX) 269*4887Schin return SF_INF; 270*4887Schin 271*4887Schin if(format & SFFMT_AFORMAT) 272*4887Schin { double g; 273*4887Schin int x; 274*4887Schin b = sp = buf; 275*4887Schin ep = (format & SFFMT_UPPER) ? ux : lx; 276*4887Schin if(n_digit <= 0 || n_digit >= (size - 9)) 277*4887Schin n_digit = size - 9; 278*4887Schin endsp = sp + n_digit; 279*4887Schin 280*4887Schin g = frexp(f, &x); 281*4887Schin *decpt = x; 282*4887Schin f = ldexp(g, 8 * sizeof(m) - 3); 283*4887Schin 284*4887Schin for (;;) 285*4887Schin { m = f; 286*4887Schin x = 8 * sizeof(m); 287*4887Schin while ((x -= 4) >= 0) 288*4887Schin { *sp++ = ep[(m >> x) & 0xf]; 289*4887Schin if (sp >= endsp) 290*4887Schin { ep = sp + 1; 291*4887Schin goto done; 292*4887Schin } 293*4887Schin } 294*4887Schin f -= m; 295*4887Schin f = ldexp(f, 8 * sizeof(m)); 296*4887Schin } 297*4887Schin } 298*4887Schin n = 0; 299*4887Schin if(f >= (double)SF_MAXLONG) 300*4887Schin { /* scale to a small enough number to fit an int */ 301*4887Schin v = SF_MAXEXP10-1; 302*4887Schin do 303*4887Schin { if(f < _Sfpos10[v]) 304*4887Schin v -= 1; 305*4887Schin else 306*4887Schin { f *= _Sfneg10[v]; 307*4887Schin if((n += (1<<v)) >= SF_IDIGITS) 308*4887Schin return SF_INF; 309*4887Schin } 310*4887Schin } while(f >= (double)SF_MAXLONG); 311*4887Schin } 312*4887Schin *decpt = (int)n; 313*4887Schin 314*4887Schin b = sp = buf + SF_INTPART; 315*4887Schin if((v = (long)f) != 0) 316*4887Schin { /* translate the integer part */ 317*4887Schin f -= (double)v; 318*4887Schin 319*4887Schin sfucvt(v,sp,n,ep,long,ulong); 320*4887Schin 321*4887Schin n = b-sp; 322*4887Schin if((*decpt += (int)n) >= SF_IDIGITS) 323*4887Schin return SF_INF; 324*4887Schin b = sp; 325*4887Schin sp = buf + SF_INTPART; 326*4887Schin } 327*4887Schin else n = 0; 328*4887Schin 329*4887Schin /* remaining number of digits to compute; add 1 for later rounding */ 330*4887Schin n = (((format&SFFMT_EFORMAT) || *decpt <= 0) ? 1 : *decpt+1) - n; 331*4887Schin if(n_digit > 0) 332*4887Schin { if(n_digit > DBL_DIG) 333*4887Schin n_digit = DBL_DIG; 334*4887Schin n += n_digit; 335*4887Schin } 336*4887Schin 337*4887Schin if((ep = (sp+n)) > (endsp = buf+(size-2))) 338*4887Schin ep = endsp; 339*4887Schin if(sp > ep) 340*4887Schin sp = ep; 341*4887Schin else 342*4887Schin { 343*4887Schin if((format&SFFMT_EFORMAT) && *decpt == 0 && f > 0.) 344*4887Schin { reg double d; 345*4887Schin while((long)(d = f*10.) == 0) 346*4887Schin { f = d; 347*4887Schin *decpt -= 1; 348*4887Schin } 349*4887Schin } 350*4887Schin 351*4887Schin while(sp < ep) 352*4887Schin { /* generate fractional digits */ 353*4887Schin if(f <= 0.) 354*4887Schin { /* fill with 0's */ 355*4887Schin do { *sp++ = '0'; } while(sp < ep); 356*4887Schin goto done; 357*4887Schin } 358*4887Schin else if((n = (long)(f *= 10.)) < 10) 359*4887Schin { *sp++ = (char)('0' + n); 360*4887Schin f -= n; 361*4887Schin } 362*4887Schin else /* n == 10 */ 363*4887Schin { do { *sp++ = '9'; } while(sp < ep); 364*4887Schin } 365*4887Schin } 366*4887Schin } 367*4887Schin } 368*4887Schin 369*4887Schin if(ep <= b) 370*4887Schin ep = b+1; 371*4887Schin else if(ep < endsp) 372*4887Schin { /* round the last digit */ 373*4887Schin *--sp += 5; 374*4887Schin while(*sp > '9') 375*4887Schin { *sp = '0'; 376*4887Schin if(sp > b) 377*4887Schin *--sp += 1; 378*4887Schin else 379*4887Schin { /* next power of 10 */ 380*4887Schin *sp = '1'; 381*4887Schin *decpt += 1; 382*4887Schin if(!(format&SFFMT_EFORMAT)) 383*4887Schin { /* add one more 0 for %f precision */ 384*4887Schin ep[-1] = '0'; 385*4887Schin ep += 1; 386*4887Schin } 387*4887Schin } 388*4887Schin } 389*4887Schin } 390*4887Schin 391*4887Schin done: 392*4887Schin *--ep = '\0'; 393*4887Schin if(len) 394*4887Schin *len = ep-b; 395*4887Schin return b; 396*4887Schin } 397