1:
2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26:
27:
28: #include <sys/types.h>
29: #include <machine/ieee.h>
30: #include <float.h>
31: #include <limits.h>
32: #include <math.h>
33:
34: #include "gdtoaimp.h"
35:
36:
37: #define INFSTR "Infinity"
38: #define NANSTR "NaN"
39:
40: #define DBL_ADJ (DBL_MAX_EXP - 2 + ((DBL_MANT_DIG - 1) % 4))
41: #define LDBL_ADJ (LDBL_MAX_EXP - 2 + ((LDBL_MANT_DIG - 1) % 4))
42:
43: 44: 45: 46: 47:
48: static int
49: roundup(char *s0, int ndigits)
50: {
51: char *s;
52:
53: for (s = s0 + ndigits - 1; *s == 0xf; s--) {
54: if (s == s0) {
55: *s = 1;
56: return (1);
57: }
58: *s = 0;
59: }
60: ++*s;
61: return (0);
62: }
63:
64: 65: 66: 67: 68: 69:
70: static void
71: dorounding(char *s0, int ndigits, int sign, int *decpt)
72: {
73: int adjust = 0;
74:
75: switch (FLT_ROUNDS) {
76: case 0:
77: default:
78: break;
79: case 1:
80: if ((s0[ndigits] > 8) ||
81: (s0[ndigits] == 8 && s0[ndigits + 1] & 1))
82: adjust = roundup(s0, ndigits);
83: break;
84: case 2:
85: if (sign == 0)
86: adjust = roundup(s0, ndigits);
87: break;
88: case 3:
89: if (sign != 0)
90: adjust = roundup(s0, ndigits);
91: break;
92: }
93:
94: if (adjust)
95: *decpt += 4;
96: }
97:
98: 99: 100: 101: 102: 103: 104: 105: 106: 107: 108: 109: 110: 111: 112: 113: 114: 115: 116: 117: 118: 119: 120: 121:
122: char *
123: __hdtoa(double d, const char *xdigs, int ndigits, int *decpt, int *sign,
124: char **rve)
125: {
126: static const int sigfigs = (DBL_MANT_DIG + 3) / 4;
127: struct ieee_double *p = (struct ieee_double *)&d;
128: char *s, *s0;
129: int bufsize;
130:
131: *sign = p->dbl_sign;
132:
133: switch (fpclassify(d)) {
134: case FP_NORMAL:
135: *decpt = p->dbl_exp - DBL_ADJ;
136: break;
137: case FP_ZERO:
138: *decpt = 1;
139: return (nrv_alloc("0", rve, 1));
140: case FP_SUBNORMAL:
141: d *= 0x1p514;
142: *decpt = p->dbl_exp - (514 + DBL_ADJ);
143: break;
144: case FP_INFINITE:
145: *decpt = INT_MAX;
146: return (nrv_alloc(INFSTR, rve, sizeof(INFSTR) - 1));
147: case FP_NAN:
148: *decpt = INT_MAX;
149: return (nrv_alloc(NANSTR, rve, sizeof(NANSTR) - 1));
150: default:
151: ;
152: }
153:
154:
155:
156: if (ndigits == 0)
157: ndigits = 1;
158:
159: 160: 161: 162:
163: bufsize = (sigfigs > ndigits) ? sigfigs : ndigits;
164: s0 = rv_alloc(bufsize);
165: if (s0 == NULL)
166: return (NULL);
167:
168: 169: 170: 171: 172: 173: 174: 175:
176: for (s = s0 + bufsize - 1; s > s0 + sigfigs - 1; s--)
177: *s = 0;
178: for (; s > s0 + sigfigs - (DBL_FRACLBITS / 4) - 1 && s > s0; s--) {
179: *s = p->dbl_fracl & 0xf;
180: p->dbl_fracl >>= 4;
181: }
182: for (; s > s0; s--) {
183: *s = p->dbl_frach & 0xf;
184: p->dbl_frach >>= 4;
185: }
186:
187: 188: 189: 190: 191: 192:
193: *s = p->dbl_frach | (1U << ((DBL_MANT_DIG - 1) % 4));
194:
195:
196: if (ndigits < 0) {
197: for (ndigits = sigfigs; s0[ndigits - 1] == 0; ndigits--)
198: ;
199: }
200:
201: if (sigfigs > ndigits && s0[ndigits] != 0)
202: dorounding(s0, ndigits, p->dbl_sign, decpt);
203:
204: s = s0 + ndigits;
205: if (rve != NULL)
206: *rve = s;
207: *s-- = '\0';
208: for (; s >= s0; s--)
209: *s = xdigs[(unsigned int)*s];
210:
211: return (s0);
212: }
213:
214: #if (LDBL_MANT_DIG > DBL_MANT_DIG)
215:
216: 217: 218:
219: char *
220: __hldtoa(long double e, const char *xdigs, int ndigits, int *decpt, int *sign,
221: char **rve)
222: {
223: static const int sigfigs = (LDBL_MANT_DIG + 3) / 4;
224: struct ieee_ext *p = (struct ieee_ext *)&e;
225: char *s, *s0;
226: int bufsize;
227:
228: *sign = p->ext_sign;
229:
230: switch (fpclassify(e)) {
231: case FP_NORMAL:
232: *decpt = p->ext_exp - LDBL_ADJ;
233: break;
234: case FP_ZERO:
235: *decpt = 1;
236: return (nrv_alloc("0", rve, 1));
237: case FP_SUBNORMAL:
238: e *= 0x1p514L;
239: *decpt = p->ext_exp - (514 + LDBL_ADJ);
240: break;
241: case FP_INFINITE:
242: *decpt = INT_MAX;
243: return (nrv_alloc(INFSTR, rve, sizeof(INFSTR) - 1));
244: case FP_NAN:
245: *decpt = INT_MAX;
246: return (nrv_alloc(NANSTR, rve, sizeof(NANSTR) - 1));
247: default:
248: ;
249: }
250:
251:
252:
253: if (ndigits == 0)
254: ndigits = 1;
255:
256: 257: 258: 259:
260: bufsize = (sigfigs > ndigits) ? sigfigs : ndigits;
261: s0 = rv_alloc(bufsize);
262: if (s0 == NULL)
263: return (NULL);
264:
265: 266: 267: 268: 269: 270: 271: 272:
273: for (s = s0 + bufsize - 1; s > s0 + sigfigs - 1; s--)
274: *s = 0;
275: for (; s > s0 + sigfigs - (EXT_FRACLBITS / 4) - 1 && s > s0; s--) {
276: *s = p->ext_fracl & 0xf;
277: p->ext_fracl >>= 4;
278: }
279: #ifdef EXT_FRACHMBITS
280: for (; s > s0; s--) {
281: *s = p->ext_frachm & 0xf;
282: p->ext_frachm >>= 4;
283: }
284: #endif
285: #ifdef EXT_FRACLMBITS
286: for (; s > s0; s--) {
287: *s = p->ext_fraclm & 0xf;
288: p->ext_fraclm >>= 4;
289: }
290: #endif
291: for (; s > s0; s--) {
292: *s = p->ext_frach & 0xf;
293: p->ext_frach >>= 4;
294: }
295:
296: 297: 298: 299: 300: 301:
302: *s = p->ext_frach | (1U << ((LDBL_MANT_DIG - 1) % 4));
303:
304:
305: if (ndigits < 0) {
306: for (ndigits = sigfigs; s0[ndigits - 1] == 0; ndigits--)
307: ;
308: }
309:
310: if (sigfigs > ndigits && s0[ndigits] != 0)
311: dorounding(s0, ndigits, p->ext_sign, decpt);
312:
313: s = s0 + ndigits;
314: if (rve != NULL)
315: *rve = s;
316: *s-- = '\0';
317: for (; s >= s0; s--)
318: *s = xdigs[(unsigned int)*s];
319:
320: return (s0);
321: }
322:
323: #else
324:
325: char *
326: __hldtoa(long double e, const char *xdigs, int ndigits, int *decpt, int *sign,
327: char **rve)
328: {
329: return (__hdtoa((double)e, xdigs, ndigits, decpt, sign, rve));
330: }
331:
332: #endif