1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21: #include <math.h>
22: #include <stdio.h>
23: #include <stdlib.h>
24: #include <sys/param.h>
25: #include <float.h>
26: #include <bits/libc-lock.h>
27: #include <math_ldbl_opt.h>
28:
29: #ifndef FLOAT_TYPE
30: # define FLOAT_TYPE double
31: # define FUNC_PREFIX
32: # define FLOAT_FMT_FLAG
33:
34:
35: # define MAXDIG (NDIGIT_MAX + 3)
36: # define FCVT_MAXDIG (DBL_MAX_10_EXP + MAXDIG)
37: # if DBL_MANT_DIG == 53
38: # define NDIGIT_MAX 17
39: # elif DBL_MANT_DIG == 24
40: # define NDIGIT_MAX 9
41: # elif DBL_MANT_DIG == 56
42: # define NDIGIT_MAX 18
43: # else
44:
45:
46: # error "NDIGIT_MAX must be precomputed"
47: # define NDIGIT_MAX (lrint (ceil (M_LN2 / M_LN10 * DBL_MANT_DIG + 1.0)))
48: # endif
49: #else
50: # define LONG_DOUBLE_CVT
51: #endif
52:
53: #define APPEND(a, b) APPEND2 (a, b)
54: #define APPEND2(a, b) a##b
55: #define __APPEND(a, b) __APPEND2 (a, b)
56: #define __APPEND2(a, b) __##a##b
57:
58:
59: #define FCVT_BUFFER APPEND (FUNC_PREFIX, fcvt_buffer)
60: #define FCVT_BUFPTR APPEND (FUNC_PREFIX, fcvt_bufptr)
61: #define ECVT_BUFFER APPEND (FUNC_PREFIX, ecvt_buffer)
62:
63:
64: static char FCVT_BUFFER[MAXDIG];
65: static char ECVT_BUFFER[MAXDIG];
66: libc_freeres_ptr (static char *FCVT_BUFPTR);
67:
68: char *
69: __APPEND (FUNC_PREFIX, fcvt) (value, ndigit, decpt, sign)
70: FLOAT_TYPE value;
71: int ndigit, *decpt, *sign;
72: {
73: if (FCVT_BUFPTR == NULL)
74: {
75: if (__APPEND (FUNC_PREFIX, fcvt_r) (value, ndigit, decpt, sign,
76: FCVT_BUFFER, MAXDIG) != -1)
77: return FCVT_BUFFER;
78:
79: FCVT_BUFPTR = (char *) malloc (FCVT_MAXDIG);
80: if (FCVT_BUFPTR == NULL)
81: return FCVT_BUFFER;
82: }
83:
84: (void) __APPEND (FUNC_PREFIX, fcvt_r) (value, ndigit, decpt, sign,
85: FCVT_BUFPTR, FCVT_MAXDIG);
86:
87: return FCVT_BUFPTR;
88: }
89:
90:
91: char *
92: __APPEND (FUNC_PREFIX, ecvt) (value, ndigit, decpt, sign)
93: FLOAT_TYPE value;
94: int ndigit, *decpt, *sign;
95: {
96: (void) __APPEND (FUNC_PREFIX, ecvt_r) (value, ndigit, decpt, sign,
97: ECVT_BUFFER, MAXDIG);
98:
99: return ECVT_BUFFER;
100: }
101:
102: char *
103: __APPEND (FUNC_PREFIX, gcvt) (value, ndigit, buf)
104: FLOAT_TYPE value;
105: int ndigit;
106: char *buf;
107: {
108: sprintf (buf, "%.*" FLOAT_FMT_FLAG "g", MIN (ndigit, NDIGIT_MAX), value);
109: return buf;
110: }
111:
112: #if LONG_DOUBLE_COMPAT (libc, GLIBC_2_0)
113: # ifdef LONG_DOUBLE_CVT
114: # define cvt_symbol(symbol) \
115: cvt_symbol_1 (libc, __APPEND (FUNC_PREFIX, symbol), \
116: APPEND (FUNC_PREFIX, symbol), GLIBC_2_4)
117: # define cvt_symbol_1(lib, local, symbol, version) \
118: versioned_symbol (lib, local, symbol, version)
119: # else
120: # define cvt_symbol(symbol) \
121: cvt_symbol_1 (libc, __APPEND (FUNC_PREFIX, symbol), \
122: APPEND (q, symbol), GLIBC_2_0); \
123: strong_alias (__APPEND (FUNC_PREFIX, symbol), APPEND (FUNC_PREFIX, symbol))
124: # define cvt_symbol_1(lib, local, symbol, version) \
125: compat_symbol (lib, local, symbol, version)
126: # endif
127: #else
128: # define cvt_symbol(symbol) \
129: strong_alias (__APPEND (FUNC_PREFIX, symbol), APPEND (FUNC_PREFIX, symbol))
130: #endif
131: cvt_symbol(fcvt);
132: cvt_symbol(ecvt);
133: cvt_symbol(gcvt);