1 /* Print floating point number in hexadecimal notation according to ISO C99.
2 Copyright (C) 1997-2022 Free Software Foundation, Inc.
3 This file is part of the GNU C Library.
4
5 The GNU C Library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Lesser General Public
7 License as published by the Free Software Foundation; either
8 version 2.1 of the License, or (at your option) any later version.
9
10 The GNU C Library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Lesser General Public License for more details.
14
15 You should have received a copy of the GNU Lesser General Public
16 License along with the GNU C Library; if not, see
17 <https://www.gnu.org/licenses/>. */
18
19 #include <array_length.h>
20 #include <ctype.h>
21 #include <ieee754.h>
22 #include <math.h>
23 #include <printf.h>
24 #include <stdlib.h>
25 #include <stdio.h>
26 #include <string.h>
27 #include <wchar.h>
28 #include <_itoa.h>
29 #include <_itowa.h>
30 #include <locale/localeinfo.h>
31 #include <stdbool.h>
32 #include <rounding-mode.h>
33
34 #if __HAVE_DISTINCT_FLOAT128
35 # include "ieee754_float128.h"
36 # include <ldbl-128/printf_fphex_macros.h>
37 # define PRINT_FPHEX_FLOAT128 \
38 PRINT_FPHEX (_Float128, fpnum.flt128, ieee854_float128, \
39 IEEE854_FLOAT128_BIAS)
40 #endif
41
42 /* #define NDEBUG 1*/ /* Undefine this for debugging assertions. */
43 #include <assert.h>
44
45 #include <libioP.h>
46 #define PUT(f, s, n) _IO_sputn (f, s, n)
47 #define PAD(f, c, n) (wide ? _IO_wpadn (f, c, n) : _IO_padn (f, c, n))
48 #undef putc
49 #define putc(c, f) (wide \
50 ? (int)_IO_putwc_unlocked (c, f) : _IO_putc_unlocked (c, f))
51
52
53 /* Macros for doing the actual output. */
54
55 #define outchar(ch) \
56 do \
57 { \
58 const int outc = (ch); \
59 if (putc (outc, fp) == EOF) \
60 return -1; \
61 ++done; \
62 } while (0)
63
64 #define PRINT(ptr, wptr, len) \
65 do \
66 { \
67 size_t outlen = (len); \
68 if (wide) \
69 while (outlen-- > 0) \
70 outchar (*wptr++); \
71 else \
72 while (outlen-- > 0) \
73 outchar (*ptr++); \
74 } while (0)
75
76 #define PADN(ch, len) \
77 do \
78 { \
79 if (PAD (fp, ch, len) != len) \
80 return -1; \
81 done += len; \
82 } \
83 while (0)
84
85 #ifndef MIN
86 # define MIN(a,b) ((a)<(b)?(a):(b))
87 #endif
88
89
90 int
__printf_fphex(FILE * fp,const struct printf_info * info,const void * const * args)91 __printf_fphex (FILE *fp,
92 const struct printf_info *info,
93 const void *const *args)
94 {
95 /* The floating-point value to output. */
96 union
97 {
98 union ieee754_double dbl;
99 long double ldbl;
100 #if __HAVE_DISTINCT_FLOAT128
101 _Float128 flt128;
102 #endif
103 }
104 fpnum;
105
106 /* This function always uses LC_NUMERIC. */
107 assert (info->extra == 0);
108
109 /* Locale-dependent representation of decimal point. Hexadecimal
110 formatting always using LC_NUMERIC (disregarding info->extra). */
111 const char *decimal = _NL_CURRENT (LC_NUMERIC, DECIMAL_POINT);
112 wchar_t decimalwc = _NL_CURRENT_WORD (LC_NUMERIC,
113 _NL_NUMERIC_DECIMAL_POINT_WC);
114
115 /* The decimal point character must never be zero. */
116 assert (*decimal != '\0' && decimalwc != L'\0');
117
118 /* "NaN" or "Inf" for the special cases. */
119 const char *special = NULL;
120 const wchar_t *wspecial = NULL;
121
122 /* Buffer for the generated number string for the mantissa. The
123 maximal size for the mantissa is 128 bits. */
124 char numbuf[32];
125 char *numstr;
126 char *numend;
127 wchar_t wnumbuf[32];
128 wchar_t *wnumstr;
129 wchar_t *wnumend;
130 int negative;
131
132 /* The maximal exponent of two in decimal notation has 5 digits. */
133 char expbuf[5];
134 char *expstr;
135 wchar_t wexpbuf[5];
136 wchar_t *wexpstr;
137 int expnegative;
138 int exponent;
139
140 /* Non-zero is mantissa is zero. */
141 int zero_mantissa;
142
143 /* The leading digit before the decimal point. */
144 char leading;
145
146 /* Precision. */
147 int precision = info->prec;
148
149 /* Width. */
150 int width = info->width;
151
152 /* Number of characters written. */
153 int done = 0;
154
155 /* Nonzero if this is output on a wide character stream. */
156 int wide = info->wide;
157
158 #define PRINTF_FPHEX_FETCH(FLOAT, VAR) \
159 { \
160 (VAR) = *(const FLOAT *) args[0]; \
161 \
162 /* Check for special values: not a number or infinity. */ \
163 if (isnan (VAR)) \
164 { \
165 if (isupper (info->spec)) \
166 { \
167 special = "NAN"; \
168 wspecial = L"NAN"; \
169 } \
170 else \
171 { \
172 special = "nan"; \
173 wspecial = L"nan"; \
174 } \
175 } \
176 else \
177 { \
178 if (isinf (VAR)) \
179 { \
180 if (isupper (info->spec)) \
181 { \
182 special = "INF"; \
183 wspecial = L"INF"; \
184 } \
185 else \
186 { \
187 special = "inf"; \
188 wspecial = L"inf"; \
189 } \
190 } \
191 } \
192 negative = signbit (VAR); \
193 }
194
195 /* Fetch the argument value. */
196 #if __HAVE_DISTINCT_FLOAT128
197 if (info->is_binary128)
198 PRINTF_FPHEX_FETCH (_Float128, fpnum.flt128)
199 else
200 #endif
201 #ifndef __NO_LONG_DOUBLE_MATH
202 if (info->is_long_double && sizeof (long double) > sizeof (double))
203 PRINTF_FPHEX_FETCH (long double, fpnum.ldbl)
204 else
205 #endif
206 PRINTF_FPHEX_FETCH (double, fpnum.dbl.d)
207
208 #undef PRINTF_FPHEX_FETCH
209
210 if (special)
211 {
212 int width = info->width;
213
214 if (negative || info->showsign || info->space)
215 --width;
216 width -= 3;
217
218 if (!info->left && width > 0)
219 PADN (' ', width);
220
221 if (negative)
222 outchar ('-');
223 else if (info->showsign)
224 outchar ('+');
225 else if (info->space)
226 outchar (' ');
227
228 PRINT (special, wspecial, 3);
229
230 if (info->left && width > 0)
231 PADN (' ', width);
232
233 return done;
234 }
235
236 #if __HAVE_DISTINCT_FLOAT128
237 if (info->is_binary128)
238 PRINT_FPHEX_FLOAT128;
239 else
240 #endif
241 if (info->is_long_double == 0 || sizeof (double) == sizeof (long double))
242 {
243 /* We have 52 bits of mantissa plus one implicit digit. Since
244 52 bits are representable without rest using hexadecimal
245 digits we use only the implicit digits for the number before
246 the decimal point. */
247 unsigned long long int num;
248
249 num = (((unsigned long long int) fpnum.dbl.ieee.mantissa0) << 32
250 | fpnum.dbl.ieee.mantissa1);
251
252 zero_mantissa = num == 0;
253
254 if (sizeof (unsigned long int) > 6)
255 {
256 wnumstr = _itowa_word (num, wnumbuf + (sizeof wnumbuf) / sizeof (wchar_t), 16,
257 info->spec == 'A');
258 numstr = _itoa_word (num, numbuf + sizeof numbuf, 16,
259 info->spec == 'A');
260 }
261 else
262 {
263 wnumstr = _itowa (num, wnumbuf + sizeof wnumbuf / sizeof (wchar_t), 16,
264 info->spec == 'A');
265 numstr = _itoa (num, numbuf + sizeof numbuf, 16,
266 info->spec == 'A');
267 }
268
269 /* Fill with zeroes. */
270 while (wnumstr > wnumbuf + (sizeof wnumbuf - 52) / sizeof (wchar_t))
271 {
272 *--wnumstr = L'0';
273 *--numstr = '0';
274 }
275
276 leading = fpnum.dbl.ieee.exponent == 0 ? '0' : '1';
277
278 exponent = fpnum.dbl.ieee.exponent;
279
280 if (exponent == 0)
281 {
282 if (zero_mantissa)
283 expnegative = 0;
284 else
285 {
286 /* This is a denormalized number. */
287 expnegative = 1;
288 exponent = IEEE754_DOUBLE_BIAS - 1;
289 }
290 }
291 else if (exponent >= IEEE754_DOUBLE_BIAS)
292 {
293 expnegative = 0;
294 exponent -= IEEE754_DOUBLE_BIAS;
295 }
296 else
297 {
298 expnegative = 1;
299 exponent = -(exponent - IEEE754_DOUBLE_BIAS);
300 }
301 }
302 #ifdef PRINT_FPHEX_LONG_DOUBLE
303 else
304 PRINT_FPHEX_LONG_DOUBLE;
305 #endif
306
307 /* Look for trailing zeroes. */
308 if (! zero_mantissa)
309 {
310 wnumend = array_end (wnumbuf);
311 numend = array_end (numbuf);
312 while (wnumend[-1] == L'0')
313 {
314 --wnumend;
315 --numend;
316 }
317
318 bool do_round_away = false;
319
320 if (precision != -1 && precision < numend - numstr)
321 {
322 char last_digit = precision > 0 ? numstr[precision - 1] : leading;
323 char next_digit = numstr[precision];
324 int last_digit_value = (last_digit >= 'A' && last_digit <= 'F'
325 ? last_digit - 'A' + 10
326 : (last_digit >= 'a' && last_digit <= 'f'
327 ? last_digit - 'a' + 10
328 : last_digit - '0'));
329 int next_digit_value = (next_digit >= 'A' && next_digit <= 'F'
330 ? next_digit - 'A' + 10
331 : (next_digit >= 'a' && next_digit <= 'f'
332 ? next_digit - 'a' + 10
333 : next_digit - '0'));
334 bool more_bits = ((next_digit_value & 7) != 0
335 || precision + 1 < numend - numstr);
336 int rounding_mode = get_rounding_mode ();
337 do_round_away = round_away (negative, last_digit_value & 1,
338 next_digit_value >= 8, more_bits,
339 rounding_mode);
340 }
341
342 if (precision == -1)
343 precision = numend - numstr;
344 else if (do_round_away)
345 {
346 /* Round up. */
347 int cnt = precision;
348 while (--cnt >= 0)
349 {
350 char ch = numstr[cnt];
351 /* We assume that the digits and the letters are ordered
352 like in ASCII. This is true for the rest of GNU, too. */
353 if (ch == '9')
354 {
355 wnumstr[cnt] = (wchar_t) info->spec;
356 numstr[cnt] = info->spec; /* This is tricky,
357 think about it! */
358 break;
359 }
360 else if (tolower (ch) < 'f')
361 {
362 ++numstr[cnt];
363 ++wnumstr[cnt];
364 break;
365 }
366 else
367 {
368 numstr[cnt] = '0';
369 wnumstr[cnt] = L'0';
370 }
371 }
372 if (cnt < 0)
373 {
374 /* The mantissa so far was fff...f Now increment the
375 leading digit. Here it is again possible that we
376 get an overflow. */
377 if (leading == '9')
378 leading = info->spec;
379 else if (tolower (leading) < 'f')
380 ++leading;
381 else
382 {
383 leading = '1';
384 if (expnegative)
385 {
386 exponent -= 4;
387 if (exponent <= 0)
388 {
389 exponent = -exponent;
390 expnegative = 0;
391 }
392 }
393 else
394 exponent += 4;
395 }
396 }
397 }
398 }
399 else
400 {
401 if (precision == -1)
402 precision = 0;
403 numend = numstr;
404 wnumend = wnumstr;
405 }
406
407 /* Now we can compute the exponent string. */
408 expstr = _itoa_word (exponent, expbuf + sizeof expbuf, 10, 0);
409 wexpstr = _itowa_word (exponent,
410 wexpbuf + sizeof wexpbuf / sizeof (wchar_t), 10, 0);
411
412 /* Now we have all information to compute the size. */
413 width -= ((negative || info->showsign || info->space)
414 /* Sign. */
415 + 2 + 1 + 0 + precision + 1 + 1
416 /* 0x h . hhh P ExpoSign. */
417 + ((expbuf + sizeof expbuf) - expstr));
418 /* Exponent. */
419
420 /* Count the decimal point.
421 A special case when the mantissa or the precision is zero and the `#'
422 is not given. In this case we must not print the decimal point. */
423 if (precision > 0 || info->alt)
424 width -= wide ? 1 : strlen (decimal);
425
426 if (!info->left && info->pad != '0' && width > 0)
427 PADN (' ', width);
428
429 if (negative)
430 outchar ('-');
431 else if (info->showsign)
432 outchar ('+');
433 else if (info->space)
434 outchar (' ');
435
436 outchar ('0');
437 if ('X' - 'A' == 'x' - 'a')
438 outchar (info->spec + ('x' - 'a'));
439 else
440 outchar (info->spec == 'A' ? 'X' : 'x');
441
442 if (!info->left && info->pad == '0' && width > 0)
443 PADN ('0', width);
444
445 outchar (leading);
446
447 if (precision > 0 || info->alt)
448 {
449 const wchar_t *wtmp = &decimalwc;
450 PRINT (decimal, wtmp, wide ? 1 : strlen (decimal));
451 }
452
453 if (precision > 0)
454 {
455 ssize_t tofill = precision - (numend - numstr);
456 PRINT (numstr, wnumstr, MIN (numend - numstr, precision));
457 if (tofill > 0)
458 PADN ('0', tofill);
459 }
460
461 if ('P' - 'A' == 'p' - 'a')
462 outchar (info->spec + ('p' - 'a'));
463 else
464 outchar (info->spec == 'A' ? 'P' : 'p');
465
466 outchar (expnegative ? '-' : '+');
467
468 PRINT (expstr, wexpstr, (expbuf + sizeof expbuf) - expstr);
469
470 if (info->left && info->pad != '0' && width > 0)
471 PADN (info->pad, width);
472
473 return done;
474 }
475