1 /***********************************************************************
3 * This software is part of the ast package *
4 * Copyright (c) 1985-2010 AT&T Intellectual Property *
5 * and is licensed under the *
6 * Common Public License, Version 1.0 *
7 * by AT&T Intellectual Property *
9 * A copy of the License is available at *
10 * http://www.opensource.org/licenses/cpl1.0.txt *
11 * (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) *
13 * Information and Software Systems Research *
17 * Glenn Fowler <gsf@research.att.com> *
18 * David Korn <dgk@research.att.com> *
19 * Phong Vo <kpv@research.att.com> *
21 ***********************************************************************/
23 #include "FEATURE/isoc99"
27 /* Convert a floating point value to ASCII.
29 ** Written by Kiem-Phong Vo and Glenn Fowler (SFFMT_AFORMAT)
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)
42 #define isnan(n) (fpclassify(n)==FP_NAN)
43 #define isnanl(n) (fpclassify(n)==FP_NAN)
45 #define isnan(n) (memcmp((void*)&n,(void*)&_Sfdnan,sizeof(n))==0)
46 #define isnanl(n) (memcmp((void*)&n,(void*)&_Sflnan,sizeof(n))==0)
50 #define isnanl(n) isnan(n)
54 #if ! _lib_signbit && defined(signbit)
56 #define _lib_signbit 1
60 #if ! _ast_fltmax_double
61 static int neg0ld(Sfdouble_t f
)
64 return !memcmp(&f
, &z
, sizeof(f
));
67 static int neg0d(double f
)
70 return !memcmp(&f
, &z
, sizeof(f
));
74 #if ULONG_DIG && ULONG_DIG < (DBL_DIG-1)
75 #define CVT_LDBL_INT long
76 #define CVT_LDBL_MAXINT LONG_MAX
78 #if UINT_DIG && UINT_DIG < (DBL_DIG-1)
79 #define CVT_LDBL_INT int
80 #define CVT_LDBL_MAXINT INT_MAX
82 #define CVT_LDBL_INT long
83 #define CVT_LDBL_MAXINT SF_MAXLONG
87 #if ULONG_DIG && ULONG_DIG < (DBL_DIG-1)
88 #define CVT_DBL_INT long
89 #define CVT_DBL_MAXINT LONG_MAX
91 #if UINT_DIG && UINT_DIG < (DBL_DIG-1)
92 #define CVT_DBL_INT int
93 #define CVT_DBL_MAXINT INT_MAX
95 #define CVT_DBL_INT long
96 #define CVT_DBL_MAXINT SF_MAXLONG
101 char* _sfcvt(Void_t
* vp
, char* buf
, size_t size
, int n_digit
,
102 int* decpt
, int* sign
, int* len
, int format
)
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 */
117 reg
char *ep
, *b
, *endsp
, *t
;
119 _ast_flt_unsigned_max_t m
;
121 static char lx
[] = "0123456789abcdef";
122 static char ux
[] = "0123456789ABCDEF";
126 #if !_ast_fltmax_double
127 if(format
&SFFMT_LDOUBLE
)
128 { Sfdouble_t f
= *(Sfdouble_t
*)vp
;
152 # if _c99_in_the_wild
157 if (copysignl(1.0, f
) < 0.0)
160 if (copysign(1.0, (double)f
) < 0.0)
170 switch (fpclassify(f
))
184 if (f
< 0.0 || f
== 0.0 && neg0ld(f
))
195 if(format
& SFFMT_AFORMAT
)
198 ep
= (format
& SFFMT_UPPER
) ? ux
: lx
;
199 if(n_digit
<= 0 || n_digit
>= (size
- 9))
201 endsp
= sp
+ n_digit
+ 1;
205 f
= ldexpl(g
, 8 * sizeof(m
) - 3);
210 while ((x
-= 4) >= 0)
211 { *sp
++ = ep
[(m
>> x
) & 0xf];
216 f
= ldexpl(f
, 8 * sizeof(m
));
221 if(f
>= (Sfdouble_t
)CVT_LDBL_MAXINT
)
222 { /* scale to a small enough number to fit an int */
225 { if(f
< _Sfpos10
[v
])
230 if((n
+= (1<<v
)) >= SF_IDIGITS
)
233 } while(f
>= (Sfdouble_t
)CVT_LDBL_MAXINT
);
235 else if(f
> 0.0 && f
< 0.1)
236 { /* scale to avoid excessive multiply by 10 below */
239 { if(f
<= _Sfneg10
[v
])
241 if((n
+= (1<<v
)) >= SF_IDIGITS
)
251 b
= sp
= buf
+ SF_INTPART
;
252 if((v
= (CVT_LDBL_INT
)f
) != 0)
253 { /* translate the integer part */
256 sfucvt(v
,sp
,n
,ep
,CVT_LDBL_INT
,unsigned CVT_LDBL_INT
);
259 if((*decpt
+= (int)n
) >= SF_IDIGITS
)
262 sp
= buf
+ SF_INTPART
;
266 /* remaining number of digits to compute; add 1 for later rounding */
267 n
= (((format
&SFFMT_EFORMAT
) || *decpt
<= 0) ? 1 : *decpt
+1) - n
;
269 { if(n_digit
> LDBL_DIG
)
274 if((ep
= (sp
+n
)) > (endsp
= buf
+(size
-2)))
280 if((format
&SFFMT_EFORMAT
) && *decpt
== 0 && f
> 0.)
282 while((long)(d
= f
*10.) == 0)
289 { /* generate fractional digits */
291 { /* fill with 0's */
292 do { *sp
++ = '0'; } while(sp
< ep
);
295 else if((n
= (long)(f
*= 10.)) < 10)
300 { do { *sp
++ = '9'; } while(sp
< ep
);
306 { double f
= *(double*)vp
;
335 if (copysign(1.0, f
) < 0.0)
344 switch (fpclassify(f
))
358 if (f
< 0.0 || f
== 0.0 && neg0d(f
))
369 if(format
& SFFMT_AFORMAT
)
372 ep
= (format
& SFFMT_UPPER
) ? ux
: lx
;
373 if(n_digit
<= 0 || n_digit
>= (size
- 9))
375 endsp
= sp
+ n_digit
+ 1;
379 f
= ldexp(g
, 8 * sizeof(m
) - 3);
384 while ((x
-= 4) >= 0)
385 { *sp
++ = ep
[(m
>> x
) & 0xf];
390 f
= ldexp(f
, 8 * sizeof(m
));
394 if(f
>= (double)CVT_DBL_MAXINT
)
395 { /* scale to a small enough number to fit an int */
398 { if(f
< _Sfpos10
[v
])
402 if((n
+= (1<<v
)) >= SF_IDIGITS
)
405 } while(f
>= (double)CVT_DBL_MAXINT
);
407 else if(f
> 0.0 && f
< 1e-8)
408 { /* scale to avoid excessive multiply by 10 below */
411 { if(f
<= _Sfneg10
[v
])
413 if((n
+= (1<<v
)) >= SF_IDIGITS
)
423 b
= sp
= buf
+ SF_INTPART
;
424 if((v
= (CVT_DBL_INT
)f
) != 0)
425 { /* translate the integer part */
428 sfucvt(v
,sp
,n
,ep
,CVT_DBL_INT
,unsigned CVT_DBL_INT
);
431 if((*decpt
+= (int)n
) >= SF_IDIGITS
)
434 sp
= buf
+ SF_INTPART
;
438 /* remaining number of digits to compute; add 1 for later rounding */
439 n
= (((format
&SFFMT_EFORMAT
) || *decpt
<= 0) ? 1 : *decpt
+1) - n
;
441 { if(n_digit
> DBL_DIG
)
446 if((ep
= (sp
+n
)) > (endsp
= buf
+(size
-2)))
452 if((format
&SFFMT_EFORMAT
) && *decpt
== 0 && f
> 0.)
454 while((long)(d
= f
*10.) == 0)
461 { /* generate fractional digits */
463 { /* fill with 0's */
464 do { *sp
++ = '0'; } while(sp
< ep
);
467 else if((n
= (long)(f
*= 10.)) < 10)
468 { *sp
++ = (char)('0' + n
);
472 { do { *sp
++ = '9'; } while(sp
< ep
);
482 { /* round the last digit */
489 { /* next power of 10 */
492 if(!(format
&SFFMT_EFORMAT
))
493 { /* add one more 0 for %f precision */
507 if (((m
>> x
) & 0xf) >= 8)