1 /*********************************************************************** 2 * * 3 * This software is part of the ast package * 4 * Copyright (c) 1985-2008 AT&T Intellectual Property * 5 * and is licensed under the * 6 * Common Public License, Version 1.0 * 7 * by AT&T Intellectual Property * 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 #if __STDC__ 23 #include "FEATURE/isoc99" 24 #endif 25 #include "sfhdr.h" 26 27 /* Convert a floating point value to ASCII. 28 ** 29 ** Written by Kiem-Phong Vo and Glenn Fowler (SFFMT_AFORMAT) 30 */ 31 32 static char *lc_inf = "inf", *uc_inf = "INF"; 33 static char *lc_nan = "nan", *uc_nan = "NAN"; 34 static char *Zero = "0"; 35 #define SF_INF ((_Sfi = 3), strncpy(buf, (format & SFFMT_UPPER) ? uc_inf : lc_inf, size)) 36 #define SF_NAN ((_Sfi = 3), strncpy(buf, (format & SFFMT_UPPER) ? uc_nan : lc_nan, size)) 37 #define SF_ZERO ((_Sfi = 1), strncpy(buf, Zero, size)) 38 #define SF_INTPART (SF_IDIGITS/2) 39 40 #if ! _lib_isnan 41 #if _lib_fpclassify 42 #define isnan(n) (fpclassify(n)==FP_NAN) 43 #define isnanl(n) (fpclassify(n)==FP_NAN) 44 #else 45 #define isnan(n) (memcmp((void*)&n,(void*)&_Sfdnan,sizeof(n))==0) 46 #define isnanl(n) (memcmp((void*)&n,(void*)&_Sflnan,sizeof(n))==0) 47 #endif 48 #else 49 #if ! _lib_isnanl 50 #define isnanl(n) isnan(n) 51 #endif 52 #endif 53 54 #if ! _lib_signbit && defined(signbit) 55 #undef _lib_signbit 56 #define _lib_signbit 1 57 #endif 58 59 #if ! _lib_signbit 60 #if ! _ast_fltmax_double 61 static int neg0ld(Sfdouble_t f) 62 { 63 Sfdouble_t z = -0.0; 64 return !memcmp(&f, &z, sizeof(f)); 65 } 66 #endif 67 static int neg0d(double f) 68 { 69 double z = -0.0; 70 return !memcmp(&f, &z, sizeof(f)); 71 } 72 #endif 73 74 #if ULONG_DIG && ULONG_DIG < (DBL_DIG-1) 75 #define CVT_LDBL_INT long 76 #define CVT_LDBL_MAXINT LONG_MAX 77 #else 78 #if UINT_DIG && UINT_DIG < (DBL_DIG-1) 79 #define CVT_LDBL_INT int 80 #define CVT_LDBL_MAXINT INT_MAX 81 #else 82 #define CVT_LDBL_INT long 83 #define CVT_LDBL_MAXINT SF_MAXLONG 84 #endif 85 #endif 86 87 #if ULONG_DIG && ULONG_DIG < (DBL_DIG-1) 88 #define CVT_DBL_INT long 89 #define CVT_DBL_MAXINT LONG_MAX 90 #else 91 #if UINT_DIG && UINT_DIG < (DBL_DIG-1) 92 #define CVT_DBL_INT int 93 #define CVT_DBL_MAXINT INT_MAX 94 #else 95 #define CVT_DBL_INT long 96 #define CVT_DBL_MAXINT SF_MAXLONG 97 #endif 98 #endif 99 100 #if __STD_C 101 char* _sfcvt(Void_t* vp, char* buf, size_t size, int n_digit, 102 int* decpt, int* sign, int* len, int format) 103 #else 104 char* _sfcvt(vp,buf,size,n_digit,decpt,sign,len,format) 105 Void_t* vp; /* pointer to value to convert */ 106 char* buf; /* conversion goes here */ 107 size_t size; /* size of buf */ 108 int n_digit; /* number of digits wanted */ 109 int* decpt; /* to return decimal point */ 110 int* sign; /* to return sign */ 111 int* len; /* return string length */ 112 int format; /* conversion format */ 113 #endif 114 { 115 reg char *sp; 116 reg long n, v; 117 reg char *ep, *b, *endsp; 118 _ast_flt_unsigned_max_t m; 119 120 static char lx[] = "0123456789abcdef"; 121 static char ux[] = "0123456789ABCDEF"; 122 123 *sign = *decpt = 0; 124 125 #if !_ast_fltmax_double 126 if(format&SFFMT_LDOUBLE) 127 { Sfdouble_t f = *(Sfdouble_t*)vp; 128 129 if(isnanl(f)) 130 { 131 #if _lib_signbit 132 if (signbit(f)) 133 #else 134 if (f < 0) 135 #endif 136 *sign = 1; 137 return SF_NAN; 138 } 139 #if _lib_isinf 140 if (n = isinf(f)) 141 { 142 #if _lib_signbit 143 if (signbit(f)) 144 #else 145 if (n < 0 || f < 0) 146 #endif 147 *sign = 1; 148 return SF_INF; 149 } 150 #endif 151 # if _c99_in_the_wild 152 # if _lib_signbit 153 if (signbit(f)) 154 # else 155 # if _lib_copysignl 156 if (copysignl(1.0, f) < 0.0) 157 # else 158 # if _lib_copysign 159 if (copysign(1.0, (double)f) < 0.0) 160 # else 161 if (f < 0.0) 162 # endif 163 # endif 164 # endif 165 { f = -f; 166 *sign = 1; 167 } 168 # if _lib_fpclassify 169 switch (fpclassify(f)) 170 { 171 case FP_INFINITE: 172 return SF_INF; 173 case FP_NAN: 174 return SF_NAN; 175 case FP_ZERO: 176 return SF_ZERO; 177 } 178 # endif 179 # else 180 # if _lib_signbit 181 if (signbit(f)) 182 # else 183 if (f < 0.0 || f == 0.0 && neg0ld(f)) 184 # endif 185 { f = -f; 186 *sign = 1; 187 } 188 # endif 189 if(f < LDBL_MIN) 190 return SF_ZERO; 191 if(f > LDBL_MAX) 192 return SF_INF; 193 194 if(format & SFFMT_AFORMAT) 195 { Sfdouble_t g; 196 int x; 197 b = sp = buf; 198 ep = (format & SFFMT_UPPER) ? ux : lx; 199 if(n_digit <= 0 || n_digit >= (size - 9)) 200 n_digit = size - 9; 201 endsp = sp + n_digit + 1; 202 203 g = frexpl(f, &x); 204 *decpt = x; 205 f = ldexpl(g, 8 * sizeof(m) - 3); 206 207 for (;;) 208 { m = f; 209 x = 8 * sizeof(m); 210 while ((x -= 4) >= 0) 211 { *sp++ = ep[(m >> x) & 0xf]; 212 if (sp >= endsp) 213 { ep = sp + 1; 214 goto done; 215 } 216 } 217 f -= m; 218 f = ldexpl(f, 8 * sizeof(m)); 219 } 220 } 221 222 n = 0; 223 if(f >= (Sfdouble_t)CVT_LDBL_MAXINT) 224 { /* scale to a small enough number to fit an int */ 225 v = SF_MAXEXP10-1; 226 do 227 { if(f < _Sfpos10[v]) 228 v -= 1; 229 else 230 { 231 f *= _Sfneg10[v]; 232 if((n += (1<<v)) >= SF_IDIGITS) 233 return SF_INF; 234 } 235 } while(f >= (Sfdouble_t)CVT_LDBL_MAXINT); 236 } 237 else if(f > 0.0 && f < 0.1) 238 { /* scale to avoid excessive multiply by 10 below */ 239 v = SF_MAXEXP10-1; 240 do 241 { if(f <= _Sfneg10[v]) 242 { f *= _Sfpos10[v]; 243 if((n += (1<<v)) >= SF_IDIGITS) 244 return SF_INF; 245 } 246 else if (--v < 0) 247 break; 248 } while(f < 0.1); 249 n = -n; 250 } 251 *decpt = (int)n; 252 253 b = sp = buf + SF_INTPART; 254 if((v = (CVT_LDBL_INT)f) != 0) 255 { /* translate the integer part */ 256 f -= (Sfdouble_t)v; 257 258 sfucvt(v,sp,n,ep,CVT_LDBL_INT,unsigned CVT_LDBL_INT); 259 260 n = b-sp; 261 if((*decpt += (int)n) >= SF_IDIGITS) 262 return SF_INF; 263 b = sp; 264 sp = buf + SF_INTPART; 265 } 266 else n = 0; 267 268 /* remaining number of digits to compute; add 1 for later rounding */ 269 n = (((format&SFFMT_EFORMAT) || *decpt <= 0) ? 1 : *decpt+1) - n; 270 if(n_digit > 0) 271 { if(n_digit > LDBL_DIG) 272 n_digit = LDBL_DIG; 273 n += n_digit; 274 } 275 276 if((ep = (sp+n)) > (endsp = buf+(size-2))) 277 ep = endsp; 278 if(sp > ep) 279 sp = ep; 280 else 281 { 282 if((format&SFFMT_EFORMAT) && *decpt == 0 && f > 0.) 283 { Sfdouble_t d; 284 while((long)(d = f*10.) == 0) 285 { f = d; 286 *decpt -= 1; 287 } 288 } 289 290 while(sp < ep) 291 { /* generate fractional digits */ 292 if(f <= 0.) 293 { /* fill with 0's */ 294 do { *sp++ = '0'; } while(sp < ep); 295 goto done; 296 } 297 else if((n = (long)(f *= 10.)) < 10) 298 { *sp++ = '0' + n; 299 f -= n; 300 } 301 else /* n == 10 */ 302 { do { *sp++ = '9'; } while(sp < ep); 303 } 304 } 305 } 306 } else 307 #endif 308 { double f = *(double*)vp; 309 310 if(isnan(f)) 311 { 312 #if _lib_signbit 313 if (signbit(f)) 314 #else 315 if (f < 0) 316 #endif 317 *sign = 1; 318 return SF_NAN; 319 } 320 #if _lib_isinf 321 if (n = isinf(f)) 322 { 323 #if _lib_signbit 324 if (signbit(f)) 325 #else 326 if (n < 0 || f < 0) 327 #endif 328 *sign = 1; 329 return SF_INF; 330 } 331 #endif 332 #if _c99_in_the_wild 333 # if _lib_signbit 334 if (signbit(f)) 335 # else 336 # if _lib_copysign 337 if (copysign(1.0, f) < 0.0) 338 # else 339 if (f < 0.0) 340 # endif 341 # endif 342 { f = -f; 343 *sign = 1; 344 } 345 # if _lib_fpclassify 346 switch (fpclassify(f)) 347 { 348 case FP_INFINITE: 349 return SF_INF; 350 case FP_NAN: 351 return SF_NAN; 352 case FP_ZERO: 353 return SF_ZERO; 354 } 355 # endif 356 #else 357 # if _lib_signbit 358 if (signbit(f)) 359 # else 360 if (f < 0.0 || f == 0.0 && neg0d(f)) 361 # endif 362 { f = -f; 363 *sign = 1; 364 } 365 #endif 366 if(f < DBL_MIN) 367 return SF_ZERO; 368 if(f > DBL_MAX) 369 return SF_INF; 370 371 if(format & SFFMT_AFORMAT) 372 { double g; 373 int x; 374 b = sp = buf; 375 ep = (format & SFFMT_UPPER) ? ux : lx; 376 if(n_digit <= 0 || n_digit >= (size - 9)) 377 n_digit = size - 9; 378 endsp = sp + n_digit; 379 380 g = frexp(f, &x); 381 *decpt = x; 382 f = ldexp(g, 8 * sizeof(m) - 3); 383 384 for (;;) 385 { m = f; 386 x = 8 * sizeof(m); 387 while ((x -= 4) >= 0) 388 { *sp++ = ep[(m >> x) & 0xf]; 389 if (sp >= endsp) 390 { ep = sp + 1; 391 goto done; 392 } 393 } 394 f -= m; 395 f = ldexp(f, 8 * sizeof(m)); 396 } 397 } 398 n = 0; 399 if(f >= (double)CVT_DBL_MAXINT) 400 { /* scale to a small enough number to fit an int */ 401 v = SF_MAXEXP10-1; 402 do 403 { if(f < _Sfpos10[v]) 404 v -= 1; 405 else 406 { f *= _Sfneg10[v]; 407 if((n += (1<<v)) >= SF_IDIGITS) 408 return SF_INF; 409 } 410 } while(f >= (double)CVT_DBL_MAXINT); 411 } 412 else if(f > 0.0 && f < 1e-8) 413 { /* scale to avoid excessive multiply by 10 below */ 414 v = SF_MAXEXP10-1; 415 do 416 { if(f <= _Sfneg10[v]) 417 { f *= _Sfpos10[v]; 418 if((n += (1<<v)) >= SF_IDIGITS) 419 return SF_INF; 420 } 421 else if(--v < 0) 422 break; 423 } while(f < 0.1); 424 n = -n; 425 } 426 *decpt = (int)n; 427 428 b = sp = buf + SF_INTPART; 429 if((v = (CVT_DBL_INT)f) != 0) 430 { /* translate the integer part */ 431 f -= (double)v; 432 433 sfucvt(v,sp,n,ep,CVT_DBL_INT,unsigned CVT_DBL_INT); 434 435 n = b-sp; 436 if((*decpt += (int)n) >= SF_IDIGITS) 437 return SF_INF; 438 b = sp; 439 sp = buf + SF_INTPART; 440 } 441 else n = 0; 442 443 /* remaining number of digits to compute; add 1 for later rounding */ 444 n = (((format&SFFMT_EFORMAT) || *decpt <= 0) ? 1 : *decpt+1) - n; 445 if(n_digit > 0) 446 { if(n_digit > DBL_DIG) 447 n_digit = DBL_DIG; 448 n += n_digit; 449 } 450 451 if((ep = (sp+n)) > (endsp = buf+(size-2))) 452 ep = endsp; 453 if(sp > ep) 454 sp = ep; 455 else 456 { 457 if((format&SFFMT_EFORMAT) && *decpt == 0 && f > 0.) 458 { reg double d; 459 while((long)(d = f*10.) == 0) 460 { f = d; 461 *decpt -= 1; 462 } 463 } 464 465 while(sp < ep) 466 { /* generate fractional digits */ 467 if(f <= 0.) 468 { /* fill with 0's */ 469 do { *sp++ = '0'; } while(sp < ep); 470 goto done; 471 } 472 else if((n = (long)(f *= 10.)) < 10) 473 { *sp++ = (char)('0' + n); 474 f -= n; 475 } 476 else /* n == 10 */ 477 { do { *sp++ = '9'; } while(sp < ep); 478 break; 479 } 480 } 481 } 482 } 483 484 if(ep <= b) 485 ep = b+1; 486 else if(ep < endsp) 487 { /* round the last digit */ 488 *--sp += 5; 489 while(*sp > '9') 490 { *sp = '0'; 491 if(sp > b) 492 *--sp += 1; 493 else 494 { /* next power of 10 */ 495 *sp = '1'; 496 *decpt += 1; 497 if(!(format&SFFMT_EFORMAT)) 498 { /* add one more 0 for %f precision */ 499 ep[-1] = '0'; 500 ep += 1; 501 } 502 } 503 } 504 } 505 506 done: 507 *--ep = '\0'; 508 if(len) 509 *len = ep-b; 510 return b; 511 } 512