bid64_rem.c 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228
  1. /* Copyright (C) 2007-2022 Free Software Foundation, Inc.
  2. This file is part of GCC.
  3. GCC is free software; you can redistribute it and/or modify it under
  4. the terms of the GNU General Public License as published by the Free
  5. Software Foundation; either version 3, or (at your option) any later
  6. version.
  7. GCC is distributed in the hope that it will be useful, but WITHOUT ANY
  8. WARRANTY; without even the implied warranty of MERCHANTABILITY or
  9. FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
  10. for more details.
  11. Under Section 7 of GPL version 3, you are granted additional
  12. permissions described in the GCC Runtime Library Exception, version
  13. 3.1, as published by the Free Software Foundation.
  14. You should have received a copy of the GNU General Public License and
  15. a copy of the GCC Runtime Library Exception along with this program;
  16. see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
  17. <http://www.gnu.org/licenses/>. */
  18. /*****************************************************************************
  19. * BID64 remainder
  20. *****************************************************************************
  21. *
  22. * Algorithm description:
  23. *
  24. * if(exponent_x < exponent_y)
  25. * scale coefficient_y so exponents are aligned
  26. * perform coefficient divide (64-bit integer divide), unless
  27. * coefficient_y is longer than 64 bits (clearly larger
  28. * than coefficient_x)
  29. * else // exponent_x > exponent_y
  30. * use a loop to scale coefficient_x to 18_digits, divide by
  31. * coefficient_y (64-bit integer divide), calculate remainder
  32. * as new_coefficient_x and repeat until final remainder is obtained
  33. * (when new_exponent_x < exponent_y)
  34. *
  35. ****************************************************************************/
  36. #include "bid_internal.h"
  37. #define MAX_FORMAT_DIGITS 16
  38. #define DECIMAL_EXPONENT_BIAS 398
  39. #define MASK_BINARY_EXPONENT 0x7ff0000000000000ull
  40. #define BINARY_EXPONENT_BIAS 0x3ff
  41. #define UPPER_EXPON_LIMIT 51
  42. #if DECIMAL_CALL_BY_REFERENCE
  43. void
  44. bid64_rem (UINT64 * pres, UINT64 * px,
  45. UINT64 *
  46. py _EXC_FLAGS_PARAM _EXC_MASKS_PARAM _EXC_INFO_PARAM) {
  47. UINT64 x, y;
  48. #else
  49. UINT64
  50. bid64_rem (UINT64 x,
  51. UINT64 y _EXC_FLAGS_PARAM _EXC_MASKS_PARAM _EXC_INFO_PARAM) {
  52. #endif
  53. UINT128 CY;
  54. UINT64 sign_x, sign_y, coefficient_x, coefficient_y, res;
  55. UINT64 Q, R, R2, T, valid_y, valid_x;
  56. int_float tempx;
  57. int exponent_x, exponent_y, bin_expon, e_scale;
  58. int digits_x, diff_expon;
  59. #if DECIMAL_CALL_BY_REFERENCE
  60. x = *px;
  61. y = *py;
  62. #endif
  63. valid_y = unpack_BID64 (&sign_y, &exponent_y, &coefficient_y, y);
  64. valid_x = unpack_BID64 (&sign_x, &exponent_x, &coefficient_x, x);
  65. // unpack arguments, check for NaN or Infinity
  66. if (!valid_x) {
  67. // x is Inf. or NaN or 0
  68. #ifdef SET_STATUS_FLAGS
  69. if ((y & SNAN_MASK64) == SNAN_MASK64) // y is sNaN
  70. __set_status_flags (pfpsf, INVALID_EXCEPTION);
  71. #endif
  72. // test if x is NaN
  73. if ((x & 0x7c00000000000000ull) == 0x7c00000000000000ull) {
  74. #ifdef SET_STATUS_FLAGS
  75. if (((x & SNAN_MASK64) == SNAN_MASK64))
  76. __set_status_flags (pfpsf, INVALID_EXCEPTION);
  77. #endif
  78. res = coefficient_x & QUIET_MASK64;;
  79. BID_RETURN (res);
  80. }
  81. // x is Infinity?
  82. if ((x & 0x7800000000000000ull) == 0x7800000000000000ull) {
  83. if (((y & NAN_MASK64) != NAN_MASK64)) {
  84. #ifdef SET_STATUS_FLAGS
  85. __set_status_flags (pfpsf, INVALID_EXCEPTION);
  86. #endif
  87. // return NaN
  88. res = 0x7c00000000000000ull;
  89. BID_RETURN (res);
  90. }
  91. }
  92. // x is 0
  93. // return x if y != 0
  94. if (((y & 0x7800000000000000ull) < 0x7800000000000000ull) &&
  95. coefficient_y) {
  96. if ((y & 0x6000000000000000ull) == 0x6000000000000000ull)
  97. exponent_y = (y >> 51) & 0x3ff;
  98. else
  99. exponent_y = (y >> 53) & 0x3ff;
  100. if (exponent_y < exponent_x)
  101. exponent_x = exponent_y;
  102. x = exponent_x;
  103. x <<= 53;
  104. res = x | sign_x;
  105. BID_RETURN (res);
  106. }
  107. }
  108. if (!valid_y) {
  109. // y is Inf. or NaN
  110. // test if y is NaN
  111. if ((y & 0x7c00000000000000ull) == 0x7c00000000000000ull) {
  112. #ifdef SET_STATUS_FLAGS
  113. if (((y & SNAN_MASK64) == SNAN_MASK64))
  114. __set_status_flags (pfpsf, INVALID_EXCEPTION);
  115. #endif
  116. res = coefficient_y & QUIET_MASK64;;
  117. BID_RETURN (res);
  118. }
  119. // y is Infinity?
  120. if ((y & 0x7800000000000000ull) == 0x7800000000000000ull) {
  121. res = very_fast_get_BID64 (sign_x, exponent_x, coefficient_x);
  122. BID_RETURN (res);
  123. }
  124. // y is 0, return NaN
  125. {
  126. #ifdef SET_STATUS_FLAGS
  127. __set_status_flags (pfpsf, INVALID_EXCEPTION);
  128. #endif
  129. res = 0x7c00000000000000ull;
  130. BID_RETURN (res);
  131. }
  132. }
  133. diff_expon = exponent_x - exponent_y;
  134. if (diff_expon <= 0) {
  135. diff_expon = -diff_expon;
  136. if (diff_expon > 16) {
  137. // |x|<|y| in this case
  138. res = x;
  139. BID_RETURN (res);
  140. }
  141. // set exponent of y to exponent_x, scale coefficient_y
  142. T = power10_table_128[diff_expon].w[0];
  143. __mul_64x64_to_128 (CY, coefficient_y, T);
  144. if (CY.w[1] || CY.w[0] > (coefficient_x << 1)) {
  145. res = x;
  146. BID_RETURN (res);
  147. }
  148. Q = coefficient_x / CY.w[0];
  149. R = coefficient_x - Q * CY.w[0];
  150. R2 = R + R;
  151. if (R2 > CY.w[0] || (R2 == CY.w[0] && (Q & 1))) {
  152. R = CY.w[0] - R;
  153. sign_x ^= 0x8000000000000000ull;
  154. }
  155. res = very_fast_get_BID64 (sign_x, exponent_x, R);
  156. BID_RETURN (res);
  157. }
  158. while (diff_expon > 0) {
  159. // get number of digits in coeff_x
  160. tempx.d = (float) coefficient_x;
  161. bin_expon = ((tempx.i >> 23) & 0xff) - 0x7f;
  162. digits_x = estimate_decimal_digits[bin_expon];
  163. // will not use this test, dividend will have 18 or 19 digits
  164. //if(coefficient_x >= power10_table_128[digits_x].w[0])
  165. // digits_x++;
  166. e_scale = 18 - digits_x;
  167. if (diff_expon >= e_scale) {
  168. diff_expon -= e_scale;
  169. } else {
  170. e_scale = diff_expon;
  171. diff_expon = 0;
  172. }
  173. // scale dividend to 18 or 19 digits
  174. coefficient_x *= power10_table_128[e_scale].w[0];
  175. // quotient
  176. Q = coefficient_x / coefficient_y;
  177. // remainder
  178. coefficient_x -= Q * coefficient_y;
  179. // check for remainder == 0
  180. if (!coefficient_x) {
  181. res = very_fast_get_BID64_small_mantissa (sign_x, exponent_y, 0);
  182. BID_RETURN (res);
  183. }
  184. }
  185. R2 = coefficient_x + coefficient_x;
  186. if (R2 > coefficient_y || (R2 == coefficient_y && (Q & 1))) {
  187. coefficient_x = coefficient_y - coefficient_x;
  188. sign_x ^= 0x8000000000000000ull;
  189. }
  190. res = very_fast_get_BID64 (sign_x, exponent_y, coefficient_x);
  191. BID_RETURN (res);
  192. }