BSPrecision.h 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239
  1. // David Eberly, Geometric Tools, Redmond WA 98052
  2. // Copyright (c) 1998-2020
  3. // Distributed under the Boost Software License, Version 1.0.
  4. // https://www.boost.org/LICENSE_1_0.txt
  5. // https://www.geometrictools.com/License/Boost/LICENSE_1_0.txt
  6. // Version: 4.0.2019.09.25
  7. #pragma once
  8. #include <algorithm>
  9. #include <cstdint>
  10. #include <limits>
  11. // Support for determining the number of bits of precision required to compute
  12. // an expression using BSNumber or BSRational.
  13. namespace WwiseGTE
  14. {
  15. class BSPrecision
  16. {
  17. public:
  18. enum Type
  19. {
  20. IS_FLOAT,
  21. IS_DOUBLE,
  22. IS_INT32,
  23. IS_INT64,
  24. IS_UINT32,
  25. IS_UINT64
  26. };
  27. struct Parameters
  28. {
  29. Parameters()
  30. :
  31. minExponent(0),
  32. maxExponent(0),
  33. maxBits(0),
  34. maxWords(0)
  35. {
  36. }
  37. Parameters(int inMinExponent, int inMaxExponent, int inMaxBits)
  38. :
  39. minExponent(inMinExponent),
  40. maxExponent(inMaxExponent),
  41. maxBits(inMaxBits),
  42. maxWords(GetMaxWords())
  43. {
  44. }
  45. inline int GetMaxWords() const
  46. {
  47. return maxBits / 32 + ((maxBits % 32) > 0 ? 1 : 0);
  48. }
  49. int minExponent, maxExponent, maxBits, maxWords;
  50. };
  51. Parameters bsn, bsr;
  52. BSPrecision() = default;
  53. BSPrecision(Type type)
  54. {
  55. switch (type)
  56. {
  57. case IS_FLOAT:
  58. bsn = Parameters(-149, 127, 24);
  59. break;
  60. case IS_DOUBLE:
  61. bsn = Parameters(-1074, 1023, 53);
  62. break;
  63. case IS_INT32:
  64. bsn = Parameters(0, 30, 31);
  65. break;
  66. case IS_INT64:
  67. bsn = Parameters(0, 62, 63);
  68. break;
  69. case IS_UINT32:
  70. bsn = Parameters(0, 31, 32);
  71. break;
  72. case IS_UINT64:
  73. bsn = Parameters(0, 63, 64);
  74. break;
  75. }
  76. bsr = bsn;
  77. }
  78. BSPrecision(int minExponent, int maxExponent, int maxBits)
  79. :
  80. bsn(minExponent, maxExponent, maxBits),
  81. bsr(minExponent, maxExponent, maxBits)
  82. {
  83. }
  84. };
  85. inline BSPrecision operator+(BSPrecision const& bsp0, BSPrecision const& bsp1)
  86. {
  87. BSPrecision result;
  88. result.bsn.minExponent = std::min(bsp0.bsn.minExponent, bsp1.bsn.minExponent);
  89. if (bsp0.bsn.maxExponent >= bsp1.bsn.maxExponent)
  90. {
  91. result.bsn.maxExponent = bsp0.bsn.maxExponent;
  92. if (bsp0.bsn.maxExponent - bsp0.bsn.maxBits + 1 <= bsp1.bsn.maxExponent)
  93. {
  94. ++result.bsn.maxExponent;
  95. }
  96. result.bsn.maxBits = bsp0.bsn.maxExponent - bsp1.bsn.minExponent + 1;
  97. if (result.bsn.maxBits <= bsp0.bsn.maxBits + bsp1.bsn.maxBits - 1)
  98. {
  99. ++result.bsn.maxBits;
  100. }
  101. }
  102. else
  103. {
  104. result.bsn.maxExponent = bsp1.bsn.maxExponent;
  105. if (bsp1.bsn.maxExponent - bsp1.bsn.maxBits + 1 <= bsp0.bsn.maxExponent)
  106. {
  107. ++result.bsn.maxExponent;
  108. }
  109. result.bsn.maxBits = bsp1.bsn.maxExponent - bsp0.bsn.minExponent + 1;
  110. if (result.bsn.maxBits <= bsp0.bsn.maxBits + bsp1.bsn.maxBits - 1)
  111. {
  112. ++result.bsn.maxBits;
  113. }
  114. }
  115. result.bsn.maxWords = result.bsn.GetMaxWords();
  116. // Addition is n0/d0 + n1/d1 = (n0*d1 + n1*d0)/(d0*d1). The numerator
  117. // and denominator of a number are assumed to have the same
  118. // parameters, so for the addition, the numerator is used for the
  119. // parameter computations.
  120. // Compute the parameters for the multiplication.
  121. int mulMinExponent = bsp0.bsr.minExponent + bsp1.bsr.minExponent;
  122. int mulMaxExponent = bsp0.bsr.maxExponent + bsp1.bsr.maxExponent + 1;
  123. int mulMaxBits = bsp0.bsr.maxBits + bsp1.bsr.maxBits;
  124. // Compute the parameters for the addition. The number n0*d1 and n1*d0
  125. // are in the same arbitrary-precision set.
  126. result.bsr.minExponent = mulMinExponent;
  127. result.bsr.maxExponent = mulMaxExponent + 1; // Always a carry-out.
  128. result.bsr.maxBits = mulMaxExponent - mulMinExponent + 1;
  129. if (result.bsr.maxBits <= 2 * mulMaxBits - 1)
  130. {
  131. ++result.bsr.maxBits;
  132. }
  133. result.bsr.maxWords = result.bsr.GetMaxWords();
  134. return result;
  135. }
  136. inline BSPrecision operator-(BSPrecision const& bsp0, BSPrecision const& bsp1)
  137. {
  138. return bsp0 + bsp1;
  139. }
  140. inline BSPrecision operator*(BSPrecision const& bsp0, BSPrecision const& bsp1)
  141. {
  142. BSPrecision result;
  143. result.bsn.minExponent = bsp0.bsn.minExponent + bsp1.bsn.minExponent;
  144. result.bsn.maxExponent = bsp0.bsn.maxExponent + bsp1.bsn.maxExponent + 1;
  145. result.bsn.maxBits = bsp0.bsn.maxBits + bsp1.bsn.maxBits;
  146. result.bsn.maxWords = result.bsn.GetMaxWords();
  147. // Multiplication is (n0/d0) * (n1/d1) = (n0 * n1) / (d0 * d1). The
  148. // parameters are the same as for bsn.
  149. result.bsr = result.bsn;
  150. return result;
  151. }
  152. inline BSPrecision operator/(BSPrecision const& bsp0, BSPrecision const& bsp1)
  153. {
  154. BSPrecision result;
  155. // BSNumber does not support division, so result.bsr has all members
  156. // set to zero.
  157. // Division is (n0/d0) / (n1/d1) = (n0 * d1) / (n1 * d0). The
  158. // parameters are the same as for multiplication.
  159. result.bsr.minExponent = bsp0.bsr.minExponent + bsp1.bsr.minExponent;
  160. result.bsr.maxExponent = bsp0.bsr.maxExponent + bsp1.bsr.maxExponent + 1;
  161. result.bsr.maxBits = bsp0.bsr.maxBits + bsp1.bsr.maxBits;
  162. result.bsr.maxWords = result.bsr.GetMaxWords();
  163. return result;
  164. }
  165. // Comparisons for BSNumber do not involve dynamic allocations, so
  166. // the results are the extremes of the inputs. Comparisons for BSRational
  167. // involve multiplications of numerators and denominators.
  168. inline BSPrecision operator==(BSPrecision const& bsp0, BSPrecision const& bsp1)
  169. {
  170. BSPrecision result;
  171. result.bsn.minExponent = std::min(bsp0.bsn.minExponent, bsp1.bsn.minExponent);
  172. result.bsn.maxExponent = std::max(bsp0.bsn.maxExponent, bsp1.bsn.maxExponent);
  173. result.bsn.maxBits = std::max(bsp0.bsn.maxBits, bsp1.bsn.maxBits);
  174. result.bsn.maxWords = result.bsn.GetMaxWords();
  175. result.bsr.minExponent = bsp0.bsr.minExponent + bsp1.bsr.minExponent;
  176. result.bsr.maxExponent = bsp0.bsr.maxExponent + bsp1.bsr.maxExponent + 1;
  177. result.bsr.maxBits = bsp0.bsr.maxBits + bsp1.bsr.maxBits;
  178. result.bsr.maxWords = result.bsr.GetMaxWords();
  179. return result;
  180. }
  181. inline BSPrecision operator!=(BSPrecision const& bsp0, BSPrecision const& bsp1)
  182. {
  183. return operator==(bsp0, bsp1);
  184. }
  185. inline BSPrecision operator<(BSPrecision const& bsp0, BSPrecision const& bsp1)
  186. {
  187. return operator==(bsp0, bsp1);
  188. }
  189. inline BSPrecision operator<=(BSPrecision const& bsp0, BSPrecision const& bsp1)
  190. {
  191. return operator==(bsp0, bsp1);
  192. }
  193. inline BSPrecision operator>(BSPrecision const& bsp0, BSPrecision const& bsp1)
  194. {
  195. return operator==(bsp0, bsp1);
  196. }
  197. inline BSPrecision operator>=(BSPrecision const& bsp0, BSPrecision const& bsp1)
  198. {
  199. return operator==(bsp0, bsp1);
  200. }
  201. }