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