bid64_quantize.c 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236
  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. #include "bid_internal.h"
  19. #define MAX_FORMAT_DIGITS 16
  20. #define DECIMAL_EXPONENT_BIAS 398
  21. #define MAX_DECIMAL_EXPONENT 767
  22. #if DECIMAL_CALL_BY_REFERENCE
  23. void
  24. bid64_quantize (UINT64 * pres, UINT64 * px,
  25. UINT64 *
  26. py _RND_MODE_PARAM _EXC_FLAGS_PARAM _EXC_MASKS_PARAM
  27. _EXC_INFO_PARAM) {
  28. UINT64 x, y;
  29. #else
  30. UINT64
  31. bid64_quantize (UINT64 x,
  32. UINT64 y _RND_MODE_PARAM _EXC_FLAGS_PARAM
  33. _EXC_MASKS_PARAM _EXC_INFO_PARAM) {
  34. #endif
  35. UINT128 CT;
  36. UINT64 sign_x, sign_y, coefficient_x, coefficient_y, remainder_h, C64,
  37. valid_x;
  38. UINT64 tmp, carry, res;
  39. int_float tempx;
  40. int exponent_x, exponent_y, digits_x, extra_digits, amount, amount2;
  41. int expon_diff, total_digits, bin_expon_cx;
  42. unsigned rmode, status;
  43. #if DECIMAL_CALL_BY_REFERENCE
  44. #if !DECIMAL_GLOBAL_ROUNDING
  45. _IDEC_round rnd_mode = *prnd_mode;
  46. #endif
  47. x = *px;
  48. y = *py;
  49. #endif
  50. valid_x = unpack_BID64 (&sign_x, &exponent_x, &coefficient_x, x);
  51. // unpack arguments, check for NaN or Infinity
  52. if (!unpack_BID64 (&sign_y, &exponent_y, &coefficient_y, y)) {
  53. // Inf. or NaN or 0
  54. #ifdef SET_STATUS_FLAGS
  55. if ((x & SNAN_MASK64) == SNAN_MASK64) // y is sNaN
  56. __set_status_flags (pfpsf, INVALID_EXCEPTION);
  57. #endif
  58. // x=Inf, y=Inf?
  59. if (((coefficient_x << 1) == 0xf000000000000000ull)
  60. && ((coefficient_y << 1) == 0xf000000000000000ull)) {
  61. res = coefficient_x;
  62. BID_RETURN (res);
  63. }
  64. // Inf or NaN?
  65. if ((y & 0x7800000000000000ull) == 0x7800000000000000ull) {
  66. #ifdef SET_STATUS_FLAGS
  67. if (((y & 0x7e00000000000000ull) == 0x7e00000000000000ull) // sNaN
  68. || (((y & 0x7c00000000000000ull) == 0x7800000000000000ull) && //Inf
  69. ((x & 0x7c00000000000000ull) < 0x7800000000000000ull)))
  70. __set_status_flags (pfpsf, INVALID_EXCEPTION);
  71. #endif
  72. if ((y & NAN_MASK64) != NAN_MASK64)
  73. coefficient_y = 0;
  74. if ((x & NAN_MASK64) != NAN_MASK64) {
  75. res = 0x7c00000000000000ull | (coefficient_y & QUIET_MASK64);
  76. if (((y & NAN_MASK64) != NAN_MASK64) && ((x & NAN_MASK64) == 0x7800000000000000ull))
  77. res = x;
  78. BID_RETURN (res);
  79. }
  80. }
  81. }
  82. // unpack arguments, check for NaN or Infinity
  83. if (!valid_x) {
  84. // x is Inf. or NaN or 0
  85. // Inf or NaN?
  86. if ((x & 0x7800000000000000ull) == 0x7800000000000000ull) {
  87. #ifdef SET_STATUS_FLAGS
  88. if (((x & 0x7e00000000000000ull) == 0x7e00000000000000ull) // sNaN
  89. || ((x & 0x7c00000000000000ull) == 0x7800000000000000ull)) //Inf
  90. __set_status_flags (pfpsf, INVALID_EXCEPTION);
  91. #endif
  92. if ((x & NAN_MASK64) != NAN_MASK64)
  93. coefficient_x = 0;
  94. res = 0x7c00000000000000ull | (coefficient_x & QUIET_MASK64);
  95. BID_RETURN (res);
  96. }
  97. res = very_fast_get_BID64_small_mantissa (sign_x, exponent_y, 0);
  98. BID_RETURN (res);
  99. }
  100. // get number of decimal digits in coefficient_x
  101. tempx.d = (float) coefficient_x;
  102. bin_expon_cx = ((tempx.i >> 23) & 0xff) - 0x7f;
  103. digits_x = estimate_decimal_digits[bin_expon_cx];
  104. if (coefficient_x >= power10_table_128[digits_x].w[0])
  105. digits_x++;
  106. expon_diff = exponent_x - exponent_y;
  107. total_digits = digits_x + expon_diff;
  108. // check range of scaled coefficient
  109. if ((UINT32) (total_digits + 1) <= 17) {
  110. if (expon_diff >= 0) {
  111. coefficient_x *= power10_table_128[expon_diff].w[0];
  112. res = very_fast_get_BID64 (sign_x, exponent_y, coefficient_x);
  113. BID_RETURN (res);
  114. }
  115. // must round off -expon_diff digits
  116. extra_digits = -expon_diff;
  117. #ifndef IEEE_ROUND_NEAREST_TIES_AWAY
  118. #ifndef IEEE_ROUND_NEAREST
  119. rmode = rnd_mode;
  120. if (sign_x && (unsigned) (rmode - 1) < 2)
  121. rmode = 3 - rmode;
  122. #else
  123. rmode = 0;
  124. #endif
  125. #else
  126. rmode = 0;
  127. #endif
  128. coefficient_x += round_const_table[rmode][extra_digits];
  129. // get P*(2^M[extra_digits])/10^extra_digits
  130. __mul_64x64_to_128 (CT, coefficient_x,
  131. reciprocals10_64[extra_digits]);
  132. // now get P/10^extra_digits: shift C64 right by M[extra_digits]-128
  133. amount = short_recip_scale[extra_digits];
  134. C64 = CT.w[1] >> amount;
  135. #ifndef IEEE_ROUND_NEAREST_TIES_AWAY
  136. #ifndef IEEE_ROUND_NEAREST
  137. if (rnd_mode == 0)
  138. #endif
  139. if (C64 & 1) {
  140. // check whether fractional part of initial_P/10^extra_digits
  141. // is exactly .5
  142. // this is the same as fractional part of
  143. // (initial_P + 0.5*10^extra_digits)/10^extra_digits is exactly zero
  144. // get remainder
  145. amount2 = 64 - amount;
  146. remainder_h = 0;
  147. remainder_h--;
  148. remainder_h >>= amount2;
  149. remainder_h = remainder_h & CT.w[1];
  150. // test whether fractional part is 0
  151. if (!remainder_h && (CT.w[0] < reciprocals10_64[extra_digits])) {
  152. C64--;
  153. }
  154. }
  155. #endif
  156. #ifdef SET_STATUS_FLAGS
  157. status = INEXACT_EXCEPTION;
  158. // get remainder
  159. remainder_h = CT.w[1] << (64 - amount);
  160. switch (rmode) {
  161. case ROUNDING_TO_NEAREST:
  162. case ROUNDING_TIES_AWAY:
  163. // test whether fractional part is 0
  164. if ((remainder_h == 0x8000000000000000ull)
  165. && (CT.w[0] < reciprocals10_64[extra_digits]))
  166. status = EXACT_STATUS;
  167. break;
  168. case ROUNDING_DOWN:
  169. case ROUNDING_TO_ZERO:
  170. if (!remainder_h && (CT.w[0] < reciprocals10_64[extra_digits]))
  171. status = EXACT_STATUS;
  172. //if(!C64 && rmode==ROUNDING_DOWN) sign_s=sign_y;
  173. break;
  174. default:
  175. // round up
  176. __add_carry_out (tmp, carry, CT.w[0],
  177. reciprocals10_64[extra_digits]);
  178. if ((remainder_h >> (64 - amount)) + carry >=
  179. (((UINT64) 1) << amount))
  180. status = EXACT_STATUS;
  181. break;
  182. }
  183. __set_status_flags (pfpsf, status);
  184. #endif
  185. res = very_fast_get_BID64_small_mantissa (sign_x, exponent_y, C64);
  186. BID_RETURN (res);
  187. }
  188. if (total_digits < 0) {
  189. #ifdef SET_STATUS_FLAGS
  190. __set_status_flags (pfpsf, INEXACT_EXCEPTION);
  191. #endif
  192. C64 = 0;
  193. #ifndef IEEE_ROUND_NEAREST_TIES_AWAY
  194. #ifndef IEEE_ROUND_NEAREST
  195. rmode = rnd_mode;
  196. if (sign_x && (unsigned) (rmode - 1) < 2)
  197. rmode = 3 - rmode;
  198. if (rmode == ROUNDING_UP)
  199. C64 = 1;
  200. #endif
  201. #endif
  202. res = very_fast_get_BID64_small_mantissa (sign_x, exponent_y, C64);
  203. BID_RETURN (res);
  204. }
  205. // else more than 16 digits in coefficient
  206. #ifdef SET_STATUS_FLAGS
  207. __set_status_flags (pfpsf, INVALID_EXCEPTION);
  208. #endif
  209. res = 0x7c00000000000000ull;
  210. BID_RETURN (res);
  211. }