1 /* Print floating point number in hexadecimal notation according to ISO C99.
2 Copyright (C) 1997-2017 Free Software Foundation, Inc.
3 This file is part of the GNU C Library.
4 Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997.
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.
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.
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/>. */
20 #include <array_length.h>
31 #include <locale/localeinfo.h>
33 #include <rounding-mode.h>
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)
43 /* #define NDEBUG 1*/ /* Undefine this for debugging assertions. */
46 /* This defines make it possible to use the same code for GNU C library and
47 the GNU I/O library. */
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
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
59 /* Macros for doing the actual output. */
64 const int outc = (ch); \
65 if (putc (outc, fp) == EOF) \
70 #define PRINT(ptr, wptr, len) \
73 size_t outlen = (len); \
75 while (outlen-- > 0) \
78 while (outlen-- > 0) \
82 #define PADN(ch, len) \
85 if (PAD (fp, ch, len) != len) \
92 # define MIN(a,b) ((a)<(b)?(a):(b))
97 __printf_fphex (FILE *fp
,
98 const struct printf_info
*info
,
99 const void *const *args
)
101 /* The floating-point value to output. */
104 union ieee754_double dbl
;
106 #if __HAVE_DISTINCT_FLOAT128
112 /* Locale-dependent representation of decimal point. */
116 /* "NaN" or "Inf" for the special cases. */
117 const char *special
= NULL
;
118 const wchar_t *wspecial
= NULL
;
120 /* Buffer for the generated number string for the mantissa. The
121 maximal size for the mantissa is 128 bits. */
130 /* The maximal exponent of two in decimal notation has 5 digits. */
138 /* Non-zero is mantissa is zero. */
141 /* The leading digit before the decimal point. */
145 int precision
= info
->prec
;
148 int width
= info
->width
;
150 /* Number of characters written. */
153 /* Nonzero if this is output on a wide character stream. */
154 int wide
= info
->wide
;
157 /* Figure out the decimal point character. */
158 if (info
->extra
== 0)
160 decimal
= _NL_CURRENT (LC_NUMERIC
, DECIMAL_POINT
);
161 decimalwc
= _NL_CURRENT_WORD (LC_NUMERIC
, _NL_NUMERIC_DECIMAL_POINT_WC
);
165 decimal
= _NL_CURRENT (LC_MONETARY
, MON_DECIMAL_POINT
);
166 decimalwc
= _NL_CURRENT_WORD (LC_MONETARY
,
167 _NL_MONETARY_DECIMAL_POINT_WC
);
169 /* The decimal point character must never be zero. */
170 assert (*decimal
!= '\0' && decimalwc
!= L
'\0');
172 #define PRINTF_FPHEX_FETCH(FLOAT, VAR) \
174 (VAR) = *(const FLOAT *) args[0]; \
176 /* Check for special values: not a number or infinity. */ \
179 if (isupper (info->spec)) \
194 if (isupper (info->spec)) \
206 negative = signbit (VAR); \
209 /* Fetch the argument value. */
210 #if __HAVE_DISTINCT_FLOAT128
211 if (info
->is_binary128
)
212 PRINTF_FPHEX_FETCH (_Float128
, fpnum
.flt128
)
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
)
220 PRINTF_FPHEX_FETCH (double, fpnum
.dbl
.d
)
222 #undef PRINTF_FPHEX_FETCH
226 int width
= info
->width
;
228 if (negative
|| info
->showsign
|| info
->space
)
232 if (!info
->left
&& width
> 0)
237 else if (info
->showsign
)
239 else if (info
->space
)
242 PRINT (special
, wspecial
, 3);
244 if (info
->left
&& width
> 0)
250 #if __HAVE_DISTINCT_FLOAT128
251 if (info
->is_binary128
)
252 PRINT_FPHEX_FLOAT128
;
255 if (info
->is_long_double
== 0 || sizeof (double) == sizeof (long double))
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
;
263 num
= (((unsigned long long int) fpnum
.dbl
.ieee
.mantissa0
) << 32
264 | fpnum
.dbl
.ieee
.mantissa1
);
266 zero_mantissa
= num
== 0;
268 if (sizeof (unsigned long int) > 6)
270 wnumstr
= _itowa_word (num
, wnumbuf
+ (sizeof wnumbuf
) / sizeof (wchar_t), 16,
272 numstr
= _itoa_word (num
, numbuf
+ sizeof numbuf
, 16,
277 wnumstr
= _itowa (num
, wnumbuf
+ sizeof wnumbuf
/ sizeof (wchar_t), 16,
279 numstr
= _itoa (num
, numbuf
+ sizeof numbuf
, 16,
283 /* Fill with zeroes. */
284 while (wnumstr
> wnumbuf
+ (sizeof wnumbuf
- 52) / sizeof (wchar_t))
290 leading
= fpnum
.dbl
.ieee
.exponent
== 0 ? '0' : '1';
292 exponent
= fpnum
.dbl
.ieee
.exponent
;
300 /* This is a denormalized number. */
302 exponent
= IEEE754_DOUBLE_BIAS
- 1;
305 else if (exponent
>= IEEE754_DOUBLE_BIAS
)
308 exponent
-= IEEE754_DOUBLE_BIAS
;
313 exponent
= -(exponent
- IEEE754_DOUBLE_BIAS
);
316 #ifdef PRINT_FPHEX_LONG_DOUBLE
318 PRINT_FPHEX_LONG_DOUBLE
;
321 /* Look for trailing zeroes. */
324 wnumend
= array_end (wnumbuf
);
325 numend
= array_end (numbuf
);
326 while (wnumend
[-1] == L
'0')
332 bool do_round_away
= false;
334 if (precision
!= -1 && precision
< numend
- numstr
)
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
,
357 precision
= numend
- numstr
;
358 else if (do_round_away
)
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. */
369 wnumstr
[cnt
] = (wchar_t) info
->spec
;
370 numstr
[cnt
] = info
->spec
; /* This is tricky,
374 else if (tolower (ch
) < 'f')
388 /* The mantissa so far was fff...f Now increment the
389 leading digit. Here it is again possible that we
392 leading
= info
->spec
;
393 else if (tolower (leading
) < 'f')
403 exponent
= -exponent
;
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);
426 /* Now we have all information to compute the size. */
427 width
-= ((negative
|| info
->showsign
|| info
->space
)
429 + 2 + 1 + 0 + precision
+ 1 + 1
430 /* 0x h . hhh P ExpoSign. */
431 + ((expbuf
+ sizeof expbuf
) - expstr
));
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
);
440 if (!info
->left
&& info
->pad
!= '0' && width
> 0)
445 else if (info
->showsign
)
447 else if (info
->space
)
451 if ('X' - 'A' == 'x' - 'a')
452 outchar (info
->spec
+ ('x' - 'a'));
454 outchar (info
->spec
== 'A' ? 'X' : 'x');
456 if (!info
->left
&& info
->pad
== '0' && width
> 0)
461 if (precision
> 0 || info
->alt
)
463 const wchar_t *wtmp
= &decimalwc
;
464 PRINT (decimal
, wtmp
, wide
? 1 : strlen (decimal
));
469 ssize_t tofill
= precision
- (numend
- numstr
);
470 PRINT (numstr
, wnumstr
, MIN (numend
- numstr
, precision
));
475 if ('P' - 'A' == 'p' - 'a')
476 outchar (info
->spec
+ ('p' - 'a'));
478 outchar (info
->spec
== 'A' ? 'P' : 'p');
480 outchar (expnegative
? '-' : '+');
482 PRINT (expstr
, wexpstr
, (expbuf
+ sizeof expbuf
) - expstr
);
484 if (info
->left
&& info
->pad
!= '0' && width
> 0)
485 PADN (info
->pad
, width
);