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