printf-frexp.c 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190
  1. /* Split a double into fraction and mantissa, for hexadecimal printf.
  2. Copyright (C) 2007, 2009-2013 Free Software Foundation, Inc.
  3. This program is free software: you can redistribute it and/or modify
  4. it under the terms of the GNU General Public License as published by
  5. the Free Software Foundation; either version 3 of the License, or
  6. (at your option) any later version.
  7. This program is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  10. GNU General Public License for more details.
  11. You should have received a copy of the GNU General Public License
  12. along with this program. If not, see <http://www.gnu.org/licenses/>. */
  13. #if ! defined USE_LONG_DOUBLE
  14. # include <config.h>
  15. #endif
  16. /* Specification. */
  17. #ifdef USE_LONG_DOUBLE
  18. # include "printf-frexpl.h"
  19. #else
  20. # include "printf-frexp.h"
  21. #endif
  22. #include <float.h>
  23. #include <math.h>
  24. #ifdef USE_LONG_DOUBLE
  25. # include "fpucw.h"
  26. #endif
  27. /* This file assumes FLT_RADIX = 2. If FLT_RADIX is a power of 2 greater
  28. than 2, or not even a power of 2, some rounding errors can occur, so that
  29. then the returned mantissa is only guaranteed to be <= 2.0, not < 2.0. */
  30. #ifdef USE_LONG_DOUBLE
  31. # define FUNC printf_frexpl
  32. # define DOUBLE long double
  33. # define MIN_EXP LDBL_MIN_EXP
  34. # if HAVE_FREXPL_IN_LIBC && HAVE_LDEXPL_IN_LIBC
  35. # define USE_FREXP_LDEXP
  36. # define FREXP frexpl
  37. # define LDEXP ldexpl
  38. # endif
  39. # define DECL_ROUNDING DECL_LONG_DOUBLE_ROUNDING
  40. # define BEGIN_ROUNDING() BEGIN_LONG_DOUBLE_ROUNDING ()
  41. # define END_ROUNDING() END_LONG_DOUBLE_ROUNDING ()
  42. # define L_(literal) literal##L
  43. #else
  44. # define FUNC printf_frexp
  45. # define DOUBLE double
  46. # define MIN_EXP DBL_MIN_EXP
  47. # if HAVE_FREXP_IN_LIBC && HAVE_LDEXP_IN_LIBC
  48. # define USE_FREXP_LDEXP
  49. # define FREXP frexp
  50. # define LDEXP ldexp
  51. # endif
  52. # define DECL_ROUNDING
  53. # define BEGIN_ROUNDING()
  54. # define END_ROUNDING()
  55. # define L_(literal) literal
  56. #endif
  57. DOUBLE
  58. FUNC (DOUBLE x, int *expptr)
  59. {
  60. int exponent;
  61. DECL_ROUNDING
  62. BEGIN_ROUNDING ();
  63. #ifdef USE_FREXP_LDEXP
  64. /* frexp and ldexp are usually faster than the loop below. */
  65. x = FREXP (x, &exponent);
  66. x = x + x;
  67. exponent -= 1;
  68. if (exponent < MIN_EXP - 1)
  69. {
  70. x = LDEXP (x, exponent - (MIN_EXP - 1));
  71. exponent = MIN_EXP - 1;
  72. }
  73. #else
  74. {
  75. /* Since the exponent is an 'int', it fits in 64 bits. Therefore the
  76. loops are executed no more than 64 times. */
  77. DOUBLE pow2[64]; /* pow2[i] = 2^2^i */
  78. DOUBLE powh[64]; /* powh[i] = 2^-2^i */
  79. int i;
  80. exponent = 0;
  81. if (x >= L_(1.0))
  82. {
  83. /* A nonnegative exponent. */
  84. {
  85. DOUBLE pow2_i; /* = pow2[i] */
  86. DOUBLE powh_i; /* = powh[i] */
  87. /* Invariants: pow2_i = 2^2^i, powh_i = 2^-2^i,
  88. x * 2^exponent = argument, x >= 1.0. */
  89. for (i = 0, pow2_i = L_(2.0), powh_i = L_(0.5);
  90. ;
  91. i++, pow2_i = pow2_i * pow2_i, powh_i = powh_i * powh_i)
  92. {
  93. if (x >= pow2_i)
  94. {
  95. exponent += (1 << i);
  96. x *= powh_i;
  97. }
  98. else
  99. break;
  100. pow2[i] = pow2_i;
  101. powh[i] = powh_i;
  102. }
  103. }
  104. /* Here 1.0 <= x < 2^2^i. */
  105. }
  106. else
  107. {
  108. /* A negative exponent. */
  109. {
  110. DOUBLE pow2_i; /* = pow2[i] */
  111. DOUBLE powh_i; /* = powh[i] */
  112. /* Invariants: pow2_i = 2^2^i, powh_i = 2^-2^i,
  113. x * 2^exponent = argument, x < 1.0, exponent >= MIN_EXP - 1. */
  114. for (i = 0, pow2_i = L_(2.0), powh_i = L_(0.5);
  115. ;
  116. i++, pow2_i = pow2_i * pow2_i, powh_i = powh_i * powh_i)
  117. {
  118. if (exponent - (1 << i) < MIN_EXP - 1)
  119. break;
  120. exponent -= (1 << i);
  121. x *= pow2_i;
  122. if (x >= L_(1.0))
  123. break;
  124. pow2[i] = pow2_i;
  125. powh[i] = powh_i;
  126. }
  127. }
  128. /* Here either x < 1.0 and exponent - 2^i < MIN_EXP - 1 <= exponent,
  129. or 1.0 <= x < 2^2^i and exponent >= MIN_EXP - 1. */
  130. if (x < L_(1.0))
  131. /* Invariants: x * 2^exponent = argument, x < 1.0 and
  132. exponent - 2^i < MIN_EXP - 1 <= exponent. */
  133. while (i > 0)
  134. {
  135. i--;
  136. if (exponent - (1 << i) >= MIN_EXP - 1)
  137. {
  138. exponent -= (1 << i);
  139. x *= pow2[i];
  140. if (x >= L_(1.0))
  141. break;
  142. }
  143. }
  144. /* Here either x < 1.0 and exponent = MIN_EXP - 1,
  145. or 1.0 <= x < 2^2^i and exponent >= MIN_EXP - 1. */
  146. }
  147. /* Invariants: x * 2^exponent = argument, and
  148. either x < 1.0 and exponent = MIN_EXP - 1,
  149. or 1.0 <= x < 2^2^i and exponent >= MIN_EXP - 1. */
  150. while (i > 0)
  151. {
  152. i--;
  153. if (x >= pow2[i])
  154. {
  155. exponent += (1 << i);
  156. x *= powh[i];
  157. }
  158. }
  159. /* Here either x < 1.0 and exponent = MIN_EXP - 1,
  160. or 1.0 <= x < 2.0 and exponent >= MIN_EXP - 1. */
  161. }
  162. #endif
  163. END_ROUNDING ();
  164. *expptr = exponent;
  165. return x;
  166. }