Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
att
GitHub Repository: att/ast
Path: blob/master/src/lib/libast/sfio/sfcvt.c
1810 views
1
/***********************************************************************
2
* *
3
* This software is part of the ast package *
4
* Copyright (c) 1985-2012 AT&T Intellectual Property *
5
* and is licensed under the *
6
* Eclipse Public License, Version 1.0 *
7
* by AT&T Intellectual Property *
8
* *
9
* A copy of the License is available at *
10
* http://www.eclipse.org/org/documents/epl-v10.html *
11
* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
12
* *
13
* Information and Software Systems Research *
14
* AT&T Research *
15
* Florham Park NJ *
16
* *
17
* Glenn Fowler <[email protected]> *
18
* David Korn <[email protected]> *
19
* Phong Vo <[email protected]> *
20
* *
21
***********************************************************************/
22
#if __STDC__
23
#include "FEATURE/standards"
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), 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
#undef isnan
42
#undef isnanl
43
#if _lib_fpclassify
44
#define isnan(n) (fpclassify(n)==FP_NAN)
45
#define isnanl(n) (fpclassify(n)==FP_NAN)
46
#else
47
#define isnan(n) (memcmp((void*)&n,(void*)&_Sfdnan,sizeof(n))==0)
48
#define isnanl(n) (memcmp((void*)&n,(void*)&_Sflnan,sizeof(n))==0)
49
#endif
50
#else
51
#if !_lib_isnanl
52
#undef isnanl
53
#define isnanl(n) isnan(n)
54
#endif
55
#endif
56
57
#if !_lib_signbit
58
#if !_ast_fltmax_double
59
static int neg0ld(Sfdouble_t f)
60
{
61
Sfdouble_t z = 0;
62
z = -z;
63
return !memcmp(&f, &z, sizeof(f));
64
}
65
#endif
66
static int neg0d(double f)
67
{
68
double z = 0;
69
z = -z;
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, *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
534