1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21: #include <errno.h>
22: #include <float.h>
23: #include <stdio.h>
24: #include <string.h>
25: #include <ctype.h>
26: #include <math.h>
27: #include <stdlib.h>
28: #include <sys/param.h>
29: #include <math_ldbl_opt.h>
30:
31: #ifndef FLOAT_TYPE
32: # define FLOAT_TYPE double
33: # define FUNC_PREFIX
34: # define FLOAT_FMT_FLAG
35: # define FLOAT_NAME_EXT
36: # define FLOAT_MIN_10_EXP DBL_MIN_10_EXP
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: # if DBL_MIN_10_EXP == -37
50: # define FLOAT_MIN_10_NORM 1.0e-37
51: # elif DBL_MIN_10_EXP == -307
52: # define FLOAT_MIN_10_NORM 1.0e-307
53: # elif DBL_MIN_10_EXP == -4931
54: # define FLOAT_MIN_10_NORM 1.0e-4931
55: # else
56:
57: # error "FLOAT_MIN_10_NORM must be precomputed"
58: # define FLOAT_MIN_10_NORM exp10 (DBL_MIN_10_EXP)
59: # endif
60: #else
61: # define LONG_DOUBLE_CVT
62: #endif
63:
64: #define APPEND(a, b) APPEND2 (a, b)
65: #define APPEND2(a, b) a##b
66: #define __APPEND(a, b) __APPEND2 (a, b)
67: #define __APPEND2(a, b) __##a##b
68:
69: #define FLOOR APPEND(floor, FLOAT_NAME_EXT)
70: #define FABS APPEND(fabs, FLOAT_NAME_EXT)
71: #define LOG10 APPEND(log10, FLOAT_NAME_EXT)
72: #define EXP APPEND(exp, FLOAT_NAME_EXT)
73:
74:
75: int
76: __APPEND (FUNC_PREFIX, fcvt_r) (value, ndigit, decpt, sign, buf, len)
77: FLOAT_TYPE value;
78: int ndigit, *decpt, *sign;
79: char *buf;
80: size_t len;
81: {
82: ssize_t n;
83: ssize_t i;
84: int left;
85:
86: if (buf == NULL)
87: {
88: __set_errno (EINVAL);
89: return -1;
90: }
91:
92: left = 0;
93: if (isfinite (value))
94: {
95: *sign = signbit (value) != 0;
96: if (*sign)
97: value = -value;
98:
99: if (ndigit < 0)
100: {
101:
102: while (ndigit < 0)
103: {
104: FLOAT_TYPE new_value = value * 0.1;
105:
106: if (new_value < 1.0)
107: {
108: ndigit = 0;
109: break;
110: }
111:
112: value = new_value;
113: ++left;
114: ++ndigit;
115: }
116: }
117: }
118: else
119:
120: *sign = 0;
121:
122: n = __snprintf (buf, len, "%.*" FLOAT_FMT_FLAG "f", MIN (ndigit, NDIGIT_MAX),
123: value);
124:
125: if (n >= (ssize_t) len)
126: return -1;
127:
128: i = 0;
129: while (i < n && isdigit (buf[i]))
130: ++i;
131: *decpt = i;
132:
133: if (i == 0)
134:
135: return 0;
136:
137: if (i < n)
138: {
139: do
140: ++i;
141: while (i < n && !isdigit (buf[i]));
142:
143: if (*decpt == 1 && buf[0] == '0' && value != 0.0)
144: {
145:
146:
147: --*decpt;
148: while (i < n && buf[i] == '0')
149: {
150: --*decpt;
151: ++i;
152: }
153: }
154:
155: memmove (&buf[MAX (*decpt, 0)], &buf[i], n - i);
156: buf[n - (i - MAX (*decpt, 0))] = '\0';
157: }
158:
159: if (left)
160: {
161: *decpt += left;
162: if ((ssize_t) --len > n)
163: {
164: while (left-- > 0 && n < (ssize_t) len)
165: buf[n++] = '0';
166: buf[n] = '\0';
167: }
168: }
169:
170: return 0;
171: }
172:
173: int
174: __APPEND (FUNC_PREFIX, ecvt_r) (value, ndigit, decpt, sign, buf, len)
175: FLOAT_TYPE value;
176: int ndigit, *decpt, *sign;
177: char *buf;
178: size_t len;
179: {
180: int exponent = 0;
181:
182: if (isfinite (value) && value != 0.0)
183: {
184:
185: FLOAT_TYPE d;
186: FLOAT_TYPE f = 1.0;
187: if (value < 0.0)
188: d = -value;
189: else
190: d = value;
191:
192:
193: if (d < FLOAT_MIN_10_NORM)
194: {
195: value /= FLOAT_MIN_10_NORM;
196: if (value < 0.0)
197: d = -value;
198: else
199: d = value;
200: exponent += FLOAT_MIN_10_EXP;
201: }
202: if (d < 1.0)
203: {
204: do
205: {
206: f *= 10.0;
207: --exponent;
208: }
209: while (d * f < 1.0);
210:
211: value *= f;
212: }
213: else if (d >= 10.0)
214: {
215: do
216: {
217: f *= 10;
218: ++exponent;
219: }
220: while (d >= f * 10.0);
221:
222: value /= f;
223: }
224: }
225: else if (value == 0.0)
226:
227:
228: exponent = 0;
229:
230: if (ndigit <= 0 && len > 0)
231: {
232: buf[0] = '\0';
233: *decpt = 1;
234: *sign = isfinite (value) ? signbit (value) != 0 : 0;
235: }
236: else
237: if (__APPEND (FUNC_PREFIX, fcvt_r) (value, MIN (ndigit, NDIGIT_MAX) - 1,
238: decpt, sign, buf, len))
239: return -1;
240:
241: *decpt += exponent;
242: return 0;
243: }
244:
245: #if LONG_DOUBLE_COMPAT (libc, GLIBC_2_0)
246: # ifdef LONG_DOUBLE_CVT
247: # define cvt_symbol(symbol) \
248: cvt_symbol_1 (libc, __APPEND (FUNC_PREFIX, symbol), \
249: APPEND (FUNC_PREFIX, symbol), GLIBC_2_4)
250: # define cvt_symbol_1(lib, local, symbol, version) \
251: versioned_symbol (lib, local, symbol, version)
252: # else
253: # define cvt_symbol(symbol) \
254: cvt_symbol_1 (libc, __APPEND (FUNC_PREFIX, symbol), \
255: APPEND (q, symbol), GLIBC_2_0); \
256: strong_alias (__APPEND (FUNC_PREFIX, symbol), APPEND (FUNC_PREFIX, symbol))
257: # define cvt_symbol_1(lib, local, symbol, version) \
258: compat_symbol (lib, local, symbol, version)
259: # endif
260: #else
261: # define cvt_symbol(symbol) \
262: strong_alias (__APPEND (FUNC_PREFIX, symbol), APPEND (FUNC_PREFIX, symbol))
263: #endif
264: cvt_symbol(fcvt_r);
265: cvt_symbol(ecvt_r);