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