bid128_quantize.c 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275
  1. /* Copyright (C) 2007-2015 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. #define BID_128RES
  19. #include "bid_internal.h"
  20. BID128_FUNCTION_ARG2 (bid128_quantize, x, y)
  21. UINT256 CT;
  22. UINT128 CX, CY, T, CX2, CR, Stemp, res, REM_H, C2N;
  23. UINT64 sign_x, sign_y, remainder_h, carry, CY64, valid_x;
  24. int_float tempx;
  25. int exponent_x, exponent_y, digits_x, extra_digits, amount;
  26. int expon_diff, total_digits, bin_expon_cx, rmode, status;
  27. valid_x = unpack_BID128_value (&sign_x, &exponent_x, &CX, x);
  28. // unpack arguments, check for NaN or Infinity
  29. if (!unpack_BID128_value (&sign_y, &exponent_y, &CY, y)) {
  30. // y is Inf. or NaN
  31. #ifdef SET_STATUS_FLAGS
  32. if ((x.w[1] & SNAN_MASK64) == SNAN_MASK64) // y is sNaN
  33. __set_status_flags (pfpsf, INVALID_EXCEPTION);
  34. #endif
  35. // test if y is NaN
  36. if ((y.w[1] & 0x7c00000000000000ull) == 0x7c00000000000000ull) {
  37. #ifdef SET_STATUS_FLAGS
  38. if ((y.w[1] & 0x7e00000000000000ull) == 0x7e00000000000000ull) {
  39. // set status flags
  40. __set_status_flags (pfpsf, INVALID_EXCEPTION);
  41. }
  42. #endif
  43. if ((x.w[1] & 0x7c00000000000000ull) != 0x7c00000000000000ull) {
  44. res.w[1] = CY.w[1] & QUIET_MASK64;
  45. res.w[0] = CY.w[0];
  46. } else {
  47. res.w[1] = CX.w[1] & QUIET_MASK64;
  48. res.w[0] = CX.w[0];
  49. }
  50. BID_RETURN (res);
  51. }
  52. // y is Infinity?
  53. if ((y.w[1] & 0x7800000000000000ull) == 0x7800000000000000ull) {
  54. // check if x is not Inf.
  55. if (((x.w[1] & 0x7c00000000000000ull) < 0x7800000000000000ull)) {
  56. // return NaN
  57. #ifdef SET_STATUS_FLAGS
  58. // set status flags
  59. __set_status_flags (pfpsf, INVALID_EXCEPTION);
  60. #endif
  61. res.w[1] = 0x7c00000000000000ull;
  62. res.w[0] = 0;
  63. BID_RETURN (res);
  64. } else
  65. if (((x.w[1] & 0x7c00000000000000ull) <= 0x7800000000000000ull)) {
  66. res.w[1] = CX.w[1] & QUIET_MASK64;
  67. res.w[0] = CX.w[0];
  68. BID_RETURN (res);
  69. }
  70. }
  71. }
  72. if (!valid_x) {
  73. // test if x is NaN or Inf
  74. if ((x.w[1] & 0x7c00000000000000ull) == 0x7800000000000000ull) {
  75. #ifdef SET_STATUS_FLAGS
  76. // set status flags
  77. __set_status_flags (pfpsf, INVALID_EXCEPTION);
  78. #endif
  79. res.w[1] = 0x7c00000000000000ull;
  80. res.w[0] = 0;
  81. BID_RETURN (res);
  82. } else if ((x.w[1] & 0x7c00000000000000ull) == 0x7c00000000000000ull) {
  83. if ((x.w[1] & 0x7e00000000000000ull) == 0x7e00000000000000ull) {
  84. #ifdef SET_STATUS_FLAGS
  85. // set status flags
  86. __set_status_flags (pfpsf, INVALID_EXCEPTION);
  87. #endif
  88. }
  89. res.w[1] = CX.w[1] & QUIET_MASK64;
  90. res.w[0] = CX.w[0];
  91. BID_RETURN (res);
  92. }
  93. if (!CX.w[1] && !CX.w[0]) {
  94. get_BID128_very_fast (&res, sign_x, exponent_y, CX);
  95. BID_RETURN (res);
  96. }
  97. }
  98. // get number of decimal digits in coefficient_x
  99. if (CX.w[1]) {
  100. tempx.d = (float) CX.w[1];
  101. bin_expon_cx = ((tempx.i >> 23) & 0xff) - 0x7f + 64;
  102. } else {
  103. tempx.d = (float) CX.w[0];
  104. bin_expon_cx = ((tempx.i >> 23) & 0xff) - 0x7f;
  105. }
  106. digits_x = estimate_decimal_digits[bin_expon_cx];
  107. if (CX.w[1] > power10_table_128[digits_x].w[1]
  108. || (CX.w[1] == power10_table_128[digits_x].w[1]
  109. && CX.w[0] >= power10_table_128[digits_x].w[0]))
  110. digits_x++;
  111. expon_diff = exponent_x - exponent_y;
  112. total_digits = digits_x + expon_diff;
  113. if ((UINT32) total_digits <= 34) {
  114. if (expon_diff >= 0) {
  115. T = power10_table_128[expon_diff];
  116. __mul_128x128_low (CX2, T, CX);
  117. get_BID128_very_fast (&res, sign_x, exponent_y, CX2);
  118. BID_RETURN (res);
  119. }
  120. #ifndef IEEE_ROUND_NEAREST_TIES_AWAY
  121. #ifndef IEEE_ROUND_NEAREST
  122. rmode = rnd_mode;
  123. if (sign_x && (unsigned) (rmode - 1) < 2)
  124. rmode = 3 - rmode;
  125. #else
  126. rmode = 0;
  127. #endif
  128. #else
  129. rmode = 0;
  130. #endif
  131. // must round off -expon_diff digits
  132. extra_digits = -expon_diff;
  133. __add_128_128 (CX, CX, round_const_table_128[rmode][extra_digits]);
  134. // get P*(2^M[extra_digits])/10^extra_digits
  135. __mul_128x128_to_256 (CT, CX, reciprocals10_128[extra_digits]);
  136. // now get P/10^extra_digits: shift C64 right by M[extra_digits]-128
  137. amount = recip_scale[extra_digits];
  138. CX2.w[0] = CT.w[2];
  139. CX2.w[1] = CT.w[3];
  140. if (amount >= 64) {
  141. CR.w[1] = 0;
  142. CR.w[0] = CX2.w[1] >> (amount - 64);
  143. } else {
  144. __shr_128 (CR, CX2, amount);
  145. }
  146. #ifndef IEEE_ROUND_NEAREST_TIES_AWAY
  147. #ifndef IEEE_ROUND_NEAREST
  148. if (rnd_mode == 0)
  149. #endif
  150. if (CR.w[0] & 1) {
  151. // check whether fractional part of initial_P/10^extra_digits is
  152. // exactly .5 this is the same as fractional part of
  153. // (initial_P + 0.5*10^extra_digits)/10^extra_digits is exactly zero
  154. // get remainder
  155. if (amount >= 64) {
  156. remainder_h = CX2.w[0] | (CX2.w[1] << (128 - amount));
  157. } else
  158. remainder_h = CX2.w[0] << (64 - amount);
  159. // test whether fractional part is 0
  160. if (!remainder_h
  161. && (CT.w[1] < reciprocals10_128[extra_digits].w[1]
  162. || (CT.w[1] == reciprocals10_128[extra_digits].w[1]
  163. && CT.w[0] < reciprocals10_128[extra_digits].w[0]))) {
  164. CR.w[0]--;
  165. }
  166. }
  167. #endif
  168. #ifdef SET_STATUS_FLAGS
  169. status = INEXACT_EXCEPTION;
  170. // get remainder
  171. if (amount >= 64) {
  172. REM_H.w[1] = (CX2.w[1] << (128 - amount));
  173. REM_H.w[0] = CX2.w[0];
  174. } else {
  175. REM_H.w[1] = CX2.w[0] << (64 - amount);
  176. REM_H.w[0] = 0;
  177. }
  178. switch (rmode) {
  179. case ROUNDING_TO_NEAREST:
  180. case ROUNDING_TIES_AWAY:
  181. // test whether fractional part is 0
  182. if (REM_H.w[1] == 0x8000000000000000ull && !REM_H.w[0]
  183. && (CT.w[1] < reciprocals10_128[extra_digits].w[1]
  184. || (CT.w[1] == reciprocals10_128[extra_digits].w[1]
  185. && CT.w[0] < reciprocals10_128[extra_digits].w[0])))
  186. status = EXACT_STATUS;
  187. break;
  188. case ROUNDING_DOWN:
  189. case ROUNDING_TO_ZERO:
  190. if (!(REM_H.w[1] | REM_H.w[0])
  191. && (CT.w[1] < reciprocals10_128[extra_digits].w[1]
  192. || (CT.w[1] == reciprocals10_128[extra_digits].w[1]
  193. && CT.w[0] < reciprocals10_128[extra_digits].w[0])))
  194. status = EXACT_STATUS;
  195. break;
  196. default:
  197. // round up
  198. __add_carry_out (Stemp.w[0], CY64, CT.w[0],
  199. reciprocals10_128[extra_digits].w[0]);
  200. __add_carry_in_out (Stemp.w[1], carry, CT.w[1],
  201. reciprocals10_128[extra_digits].w[1], CY64);
  202. if (amount < 64) {
  203. C2N.w[1] = 0;
  204. C2N.w[0] = ((UINT64) 1) << amount;
  205. REM_H.w[0] = REM_H.w[1] >> (64 - amount);
  206. REM_H.w[1] = 0;
  207. } else {
  208. C2N.w[1] = ((UINT64) 1) << (amount - 64);
  209. C2N.w[0] = 0;
  210. REM_H.w[1] >>= (128 - amount);
  211. }
  212. REM_H.w[0] += carry;
  213. if (REM_H.w[0] < carry)
  214. REM_H.w[1]++;
  215. if (__unsigned_compare_ge_128 (REM_H, C2N))
  216. status = EXACT_STATUS;
  217. }
  218. __set_status_flags (pfpsf, status);
  219. #endif
  220. get_BID128_very_fast (&res, sign_x, exponent_y, CR);
  221. BID_RETURN (res);
  222. }
  223. if (total_digits < 0) {
  224. CR.w[1] = CR.w[0] = 0;
  225. #ifndef IEEE_ROUND_NEAREST_TIES_AWAY
  226. #ifndef IEEE_ROUND_NEAREST
  227. rmode = rnd_mode;
  228. if (sign_x && (unsigned) (rmode - 1) < 2)
  229. rmode = 3 - rmode;
  230. if (rmode == ROUNDING_UP)
  231. CR.w[0] = 1;
  232. #endif
  233. #endif
  234. #ifdef SET_STATUS_FLAGS
  235. __set_status_flags (pfpsf, INEXACT_EXCEPTION);
  236. #endif
  237. get_BID128_very_fast (&res, sign_x, exponent_y, CR);
  238. BID_RETURN (res);
  239. }
  240. // else more than 34 digits in coefficient
  241. #ifdef SET_STATUS_FLAGS
  242. __set_status_flags (pfpsf, INVALID_EXCEPTION);
  243. #endif
  244. res.w[1] = 0x7c00000000000000ull;
  245. res.w[0] = 0;
  246. BID_RETURN (res);
  247. }