sreal.c 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236
  1. /* Simple data type for real numbers for the GNU compiler.
  2. Copyright (C) 2002-2015 Free Software Foundation, Inc.
  3. This file is part of GCC.
  4. GCC is free software; you can redistribute it and/or modify it under
  5. the terms of the GNU General Public License as published by the Free
  6. Software Foundation; either version 3, or (at your option) any later
  7. version.
  8. GCC is distributed in the hope that it will be useful, but WITHOUT ANY
  9. WARRANTY; without even the implied warranty of MERCHANTABILITY or
  10. FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
  11. for more details.
  12. You should have received a copy of the GNU General Public License
  13. along with GCC; see the file COPYING3. If not see
  14. <http://www.gnu.org/licenses/>. */
  15. /* This library supports real numbers;
  16. inf and nan are NOT supported.
  17. It is written to be simple and fast.
  18. Value of sreal is
  19. x = sig * 2 ^ exp
  20. where
  21. sig = significant
  22. (for < 64-bit machines sig = sig_lo + sig_hi * 2 ^ SREAL_PART_BITS)
  23. exp = exponent
  24. One uint64_t is used for the significant.
  25. Only a half of significant bits is used (in normalized sreals) so that we do
  26. not have problems with overflow, for example when c->sig = a->sig * b->sig.
  27. So the precision is 32-bit.
  28. Invariant: The numbers are normalized before and after each call of sreal_*.
  29. Normalized sreals:
  30. All numbers (except zero) meet following conditions:
  31. SREAL_MIN_SIG <= sig && sig <= SREAL_MAX_SIG
  32. -SREAL_MAX_EXP <= exp && exp <= SREAL_MAX_EXP
  33. If the number would be too large, it is set to upper bounds of these
  34. conditions.
  35. If the number is zero or would be too small it meets following conditions:
  36. sig == 0 && exp == -SREAL_MAX_EXP
  37. */
  38. #include "config.h"
  39. #include "system.h"
  40. #include <math.h>
  41. #include "coretypes.h"
  42. #include "sreal.h"
  43. /* Print the content of struct sreal. */
  44. void
  45. sreal::dump (FILE *file) const
  46. {
  47. fprintf (file, "(%" PRIi64 " * 2^%d)", m_sig, m_exp);
  48. }
  49. DEBUG_FUNCTION void
  50. debug (const sreal &ref)
  51. {
  52. ref.dump (stderr);
  53. }
  54. DEBUG_FUNCTION void
  55. debug (const sreal *ptr)
  56. {
  57. if (ptr)
  58. debug (*ptr);
  59. else
  60. fprintf (stderr, "<nil>\n");
  61. }
  62. /* Shift this right by S bits. Needed: 0 < S <= SREAL_BITS.
  63. When the most significant bit shifted out is 1, add 1 to this (rounding).
  64. */
  65. void
  66. sreal::shift_right (int s)
  67. {
  68. gcc_checking_assert (s > 0);
  69. gcc_checking_assert (s <= SREAL_BITS);
  70. /* Exponent should never be so large because shift_right is used only by
  71. sreal_add and sreal_sub ant thus the number cannot be shifted out from
  72. exponent range. */
  73. gcc_checking_assert (m_exp + s <= SREAL_MAX_EXP);
  74. m_exp += s;
  75. m_sig += (int64_t) 1 << (s - 1);
  76. m_sig >>= s;
  77. }
  78. /* Return integer value of *this. */
  79. int64_t
  80. sreal::to_int () const
  81. {
  82. int64_t sign = m_sig < 0 ? -1 : 1;
  83. if (m_exp <= -SREAL_BITS)
  84. return 0;
  85. if (m_exp >= SREAL_PART_BITS)
  86. return sign * INTTYPE_MAXIMUM (int64_t);
  87. if (m_exp > 0)
  88. return m_sig << m_exp;
  89. if (m_exp < 0)
  90. return m_sig >> -m_exp;
  91. return m_sig;
  92. }
  93. /* Return value of *this as double.
  94. This should be used for debug output only. */
  95. double
  96. sreal::to_double () const
  97. {
  98. double val = m_sig;
  99. if (m_exp)
  100. val = ldexp (val, m_exp);
  101. return val;
  102. }
  103. /* Return *this + other. */
  104. sreal
  105. sreal::operator+ (const sreal &other) const
  106. {
  107. int dexp;
  108. sreal tmp, r;
  109. const sreal *a_p = this, *b_p = &other, *bb;
  110. if (a_p->m_exp < b_p->m_exp)
  111. std::swap (a_p, b_p);
  112. dexp = a_p->m_exp - b_p->m_exp;
  113. r.m_exp = a_p->m_exp;
  114. if (dexp > SREAL_BITS)
  115. {
  116. r.m_sig = a_p->m_sig;
  117. return r;
  118. }
  119. if (dexp == 0)
  120. bb = b_p;
  121. else
  122. {
  123. tmp = *b_p;
  124. tmp.shift_right (dexp);
  125. bb = &tmp;
  126. }
  127. r.m_sig = a_p->m_sig + bb->m_sig;
  128. r.normalize ();
  129. return r;
  130. }
  131. /* Return *this - other. */
  132. sreal
  133. sreal::operator- (const sreal &other) const
  134. {
  135. int dexp;
  136. sreal tmp, r;
  137. const sreal *bb;
  138. const sreal *a_p = this, *b_p = &other;
  139. int64_t sign = 1;
  140. if (a_p->m_exp < b_p->m_exp)
  141. {
  142. sign = -1;
  143. std::swap (a_p, b_p);
  144. }
  145. dexp = a_p->m_exp - b_p->m_exp;
  146. r.m_exp = a_p->m_exp;
  147. if (dexp > SREAL_BITS)
  148. {
  149. r.m_sig = sign * a_p->m_sig;
  150. return r;
  151. }
  152. if (dexp == 0)
  153. bb = b_p;
  154. else
  155. {
  156. tmp = *b_p;
  157. tmp.shift_right (dexp);
  158. bb = &tmp;
  159. }
  160. r.m_sig = sign * (a_p->m_sig - bb->m_sig);
  161. r.normalize ();
  162. return r;
  163. }
  164. /* Return *this * other. */
  165. sreal
  166. sreal::operator* (const sreal &other) const
  167. {
  168. sreal r;
  169. if (absu_hwi (m_sig) < SREAL_MIN_SIG || absu_hwi (other.m_sig) < SREAL_MIN_SIG)
  170. {
  171. r.m_sig = 0;
  172. r.m_exp = -SREAL_MAX_EXP;
  173. }
  174. else
  175. {
  176. r.m_sig = m_sig * other.m_sig;
  177. r.m_exp = m_exp + other.m_exp;
  178. r.normalize ();
  179. }
  180. return r;
  181. }
  182. /* Return *this / other. */
  183. sreal
  184. sreal::operator/ (const sreal &other) const
  185. {
  186. gcc_checking_assert (other.m_sig != 0);
  187. sreal r;
  188. r.m_sig = (m_sig << SREAL_PART_BITS) / other.m_sig;
  189. r.m_exp = m_exp - other.m_exp - SREAL_PART_BITS;
  190. r.normalize ();
  191. return r;
  192. }