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