bid_from_int.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349
  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. /*****************************************************************************
  20. * BID64_round_integral_exact
  21. ****************************************************************************/
  22. #if DECIMAL_CALL_BY_REFERENCE
  23. void
  24. bid64_from_int32 (UINT64 * pres,
  25. int *px _EXC_MASKS_PARAM _EXC_INFO_PARAM) {
  26. int x = *px;
  27. #else
  28. UINT64
  29. bid64_from_int32 (int x _EXC_MASKS_PARAM _EXC_INFO_PARAM) {
  30. #endif
  31. UINT64 res;
  32. // if integer is negative, put the absolute value
  33. // in the lowest 32bits of the result
  34. if ((x & SIGNMASK32) == SIGNMASK32) {
  35. // negative int32
  36. x = ~x + 1; // 2's complement of x
  37. res = (unsigned int) x | 0xb1c0000000000000ull;
  38. // (exp << 53)) = biased exp. is 0
  39. } else { // positive int32
  40. res = x | 0x31c0000000000000ull; // (exp << 53)) = biased exp. is 0
  41. }
  42. BID_RETURN (res);
  43. }
  44. #if DECIMAL_CALL_BY_REFERENCE
  45. void
  46. bid64_from_uint32 (UINT64 * pres, unsigned int *px
  47. _EXC_MASKS_PARAM _EXC_INFO_PARAM) {
  48. unsigned int x = *px;
  49. #else
  50. UINT64
  51. bid64_from_uint32 (unsigned int x _EXC_MASKS_PARAM _EXC_INFO_PARAM) {
  52. #endif
  53. UINT64 res;
  54. res = x | 0x31c0000000000000ull; // (exp << 53)) = biased exp. is 0
  55. BID_RETURN (res);
  56. }
  57. #if DECIMAL_CALL_BY_REFERENCE
  58. void
  59. bid64_from_int64 (UINT64 * pres, SINT64 * px
  60. _RND_MODE_PARAM _EXC_FLAGS_PARAM _EXC_MASKS_PARAM
  61. _EXC_INFO_PARAM) {
  62. SINT64 x = *px;
  63. #if !DECIMAL_GLOBAL_ROUNDING
  64. unsigned int rnd_mode = *prnd_mode;
  65. #endif
  66. #else
  67. UINT64
  68. bid64_from_int64 (SINT64 x
  69. _RND_MODE_PARAM _EXC_FLAGS_PARAM _EXC_MASKS_PARAM
  70. _EXC_INFO_PARAM) {
  71. #endif
  72. UINT64 res;
  73. UINT64 x_sign, C;
  74. unsigned int q, ind;
  75. int incr_exp = 0;
  76. int is_midpoint_lt_even = 0, is_midpoint_gt_even = 0;
  77. int is_inexact_lt_midpoint = 0, is_inexact_gt_midpoint = 0;
  78. x_sign = x & 0x8000000000000000ull;
  79. // if the integer is negative, use the absolute value
  80. if (x_sign)
  81. C = ~((UINT64) x) + 1;
  82. else
  83. C = x;
  84. if (C <= BID64_SIG_MAX) { // |C| <= 10^16-1 and the result is exact
  85. if (C < 0x0020000000000000ull) { // C < 2^53
  86. res = x_sign | 0x31c0000000000000ull | C;
  87. } else { // C >= 2^53
  88. res =
  89. x_sign | 0x6c70000000000000ull | (C & 0x0007ffffffffffffull);
  90. }
  91. } else { // |C| >= 10^16 and the result may be inexact
  92. // the smallest |C| is 10^16 which has 17 decimal digits
  93. // the largest |C| is 0x8000000000000000 = 9223372036854775808 w/ 19 digits
  94. if (C < 0x16345785d8a0000ull) { // x < 10^17
  95. q = 17;
  96. ind = 1; // number of digits to remove for q = 17
  97. } else if (C < 0xde0b6b3a7640000ull) { // C < 10^18
  98. q = 18;
  99. ind = 2; // number of digits to remove for q = 18
  100. } else { // C < 10^19
  101. q = 19;
  102. ind = 3; // number of digits to remove for q = 19
  103. }
  104. // overflow and underflow are not possible
  105. // Note: performace can be improved by inlining this call
  106. round64_2_18 ( // will work for 19 digits too if C fits in 64 bits
  107. q, ind, C, &res, &incr_exp,
  108. &is_midpoint_lt_even, &is_midpoint_gt_even,
  109. &is_inexact_lt_midpoint, &is_inexact_gt_midpoint);
  110. if (incr_exp)
  111. ind++;
  112. // set the inexact flag
  113. if (is_inexact_lt_midpoint || is_inexact_gt_midpoint ||
  114. is_midpoint_lt_even || is_midpoint_gt_even)
  115. *pfpsf |= INEXACT_EXCEPTION;
  116. // general correction from RN to RA, RM, RP, RZ; result uses ind for exp
  117. if (rnd_mode != ROUNDING_TO_NEAREST) {
  118. if ((!x_sign
  119. && ((rnd_mode == ROUNDING_UP && is_inexact_lt_midpoint)
  120. ||
  121. ((rnd_mode == ROUNDING_TIES_AWAY
  122. || rnd_mode == ROUNDING_UP) && is_midpoint_gt_even)))
  123. || (x_sign
  124. && ((rnd_mode == ROUNDING_DOWN && is_inexact_lt_midpoint)
  125. ||
  126. ((rnd_mode == ROUNDING_TIES_AWAY
  127. || rnd_mode == ROUNDING_DOWN)
  128. && is_midpoint_gt_even)))) {
  129. res = res + 1;
  130. if (res == 0x002386f26fc10000ull) { // res = 10^16 => rounding overflow
  131. res = 0x00038d7ea4c68000ull; // 10^15
  132. ind = ind + 1;
  133. }
  134. } else if ((is_midpoint_lt_even || is_inexact_gt_midpoint) &&
  135. ((x_sign && (rnd_mode == ROUNDING_UP ||
  136. rnd_mode == ROUNDING_TO_ZERO)) ||
  137. (!x_sign && (rnd_mode == ROUNDING_DOWN ||
  138. rnd_mode == ROUNDING_TO_ZERO)))) {
  139. res = res - 1;
  140. // check if we crossed into the lower decade
  141. if (res == 0x00038d7ea4c67fffull) { // 10^15 - 1
  142. res = 0x002386f26fc0ffffull; // 10^16 - 1
  143. ind = ind - 1;
  144. }
  145. } else {
  146. ; // exact, the result is already correct
  147. }
  148. }
  149. if (res < 0x0020000000000000ull) { // res < 2^53
  150. res = x_sign | (((UINT64) ind + 398) << 53) | res;
  151. } else { // res >= 2^53
  152. res =
  153. x_sign | 0x6000000000000000ull | (((UINT64) ind + 398) << 51) |
  154. (res & 0x0007ffffffffffffull);
  155. }
  156. }
  157. BID_RETURN (res);
  158. }
  159. #if DECIMAL_CALL_BY_REFERENCE
  160. void
  161. bid64_from_uint64 (UINT64 * pres, UINT64 * px
  162. _RND_MODE_PARAM _EXC_FLAGS_PARAM _EXC_MASKS_PARAM
  163. _EXC_INFO_PARAM) {
  164. UINT64 x = *px;
  165. #if !DECIMAL_GLOBAL_ROUNDING
  166. unsigned int rnd_mode = *prnd_mode;
  167. #endif
  168. #else
  169. UINT64
  170. bid64_from_uint64 (UINT64 x
  171. _RND_MODE_PARAM _EXC_FLAGS_PARAM _EXC_MASKS_PARAM
  172. _EXC_INFO_PARAM) {
  173. #endif
  174. UINT64 res;
  175. UINT128 x128, res128;
  176. unsigned int q, ind;
  177. int incr_exp = 0;
  178. int is_midpoint_lt_even = 0, is_midpoint_gt_even = 0;
  179. int is_inexact_lt_midpoint = 0, is_inexact_gt_midpoint = 0;
  180. if (x <= BID64_SIG_MAX) { // x <= 10^16-1 and the result is exact
  181. if (x < 0x0020000000000000ull) { // x < 2^53
  182. res = 0x31c0000000000000ull | x;
  183. } else { // x >= 2^53
  184. res = 0x6c70000000000000ull | (x & 0x0007ffffffffffffull);
  185. }
  186. } else { // x >= 10^16 and the result may be inexact
  187. // the smallest x is 10^16 which has 17 decimal digits
  188. // the largest x is 0xffffffffffffffff = 18446744073709551615 w/ 20 digits
  189. if (x < 0x16345785d8a0000ull) { // x < 10^17
  190. q = 17;
  191. ind = 1; // number of digits to remove for q = 17
  192. } else if (x < 0xde0b6b3a7640000ull) { // x < 10^18
  193. q = 18;
  194. ind = 2; // number of digits to remove for q = 18
  195. } else if (x < 0x8ac7230489e80000ull) { // x < 10^19
  196. q = 19;
  197. ind = 3; // number of digits to remove for q = 19
  198. } else { // x < 10^20
  199. q = 20;
  200. ind = 4; // number of digits to remove for q = 20
  201. }
  202. // overflow and underflow are not possible
  203. // Note: performace can be improved by inlining this call
  204. if (q <= 19) {
  205. round64_2_18 ( // will work for 20 digits too if x fits in 64 bits
  206. q, ind, x, &res, &incr_exp,
  207. &is_midpoint_lt_even, &is_midpoint_gt_even,
  208. &is_inexact_lt_midpoint, &is_inexact_gt_midpoint);
  209. } else { // q = 20
  210. x128.w[1] = 0x0;
  211. x128.w[0] = x;
  212. round128_19_38 (q, ind, x128, &res128, &incr_exp,
  213. &is_midpoint_lt_even, &is_midpoint_gt_even,
  214. &is_inexact_lt_midpoint, &is_inexact_gt_midpoint);
  215. res = res128.w[0]; // res.w[1] is 0
  216. }
  217. if (incr_exp)
  218. ind++;
  219. // set the inexact flag
  220. if (is_inexact_lt_midpoint || is_inexact_gt_midpoint ||
  221. is_midpoint_lt_even || is_midpoint_gt_even)
  222. *pfpsf |= INEXACT_EXCEPTION;
  223. // general correction from RN to RA, RM, RP, RZ; result uses ind for exp
  224. if (rnd_mode != ROUNDING_TO_NEAREST) {
  225. if ((rnd_mode == ROUNDING_UP && is_inexact_lt_midpoint) ||
  226. ((rnd_mode == ROUNDING_TIES_AWAY || rnd_mode == ROUNDING_UP)
  227. && is_midpoint_gt_even)) {
  228. res = res + 1;
  229. if (res == 0x002386f26fc10000ull) { // res = 10^16 => rounding overflow
  230. res = 0x00038d7ea4c68000ull; // 10^15
  231. ind = ind + 1;
  232. }
  233. } else if ((is_midpoint_lt_even || is_inexact_gt_midpoint) &&
  234. (rnd_mode == ROUNDING_DOWN ||
  235. rnd_mode == ROUNDING_TO_ZERO)) {
  236. res = res - 1;
  237. // check if we crossed into the lower decade
  238. if (res == 0x00038d7ea4c67fffull) { // 10^15 - 1
  239. res = 0x002386f26fc0ffffull; // 10^16 - 1
  240. ind = ind - 1;
  241. }
  242. } else {
  243. ; // exact, the result is already correct
  244. }
  245. }
  246. if (res < 0x0020000000000000ull) { // res < 2^53
  247. res = (((UINT64) ind + 398) << 53) | res;
  248. } else { // res >= 2^53
  249. res = 0x6000000000000000ull | (((UINT64) ind + 398) << 51) |
  250. (res & 0x0007ffffffffffffull);
  251. }
  252. }
  253. BID_RETURN (res);
  254. }
  255. #if DECIMAL_CALL_BY_REFERENCE
  256. void
  257. bid128_from_int32 (UINT128 * pres,
  258. int *px _EXC_MASKS_PARAM _EXC_INFO_PARAM) {
  259. int x = *px;
  260. #else
  261. UINT128
  262. bid128_from_int32 (int x _EXC_MASKS_PARAM _EXC_INFO_PARAM) {
  263. #endif
  264. UINT128 res;
  265. // if integer is negative, use the absolute value
  266. if ((x & SIGNMASK32) == SIGNMASK32) {
  267. res.w[HIGH_128W] = 0xb040000000000000ull;
  268. res.w[LOW_128W] = ~((unsigned int) x) + 1; // 2's complement of x
  269. } else {
  270. res.w[HIGH_128W] = 0x3040000000000000ull;
  271. res.w[LOW_128W] = (unsigned int) x;
  272. }
  273. BID_RETURN (res);
  274. }
  275. #if DECIMAL_CALL_BY_REFERENCE
  276. void
  277. bid128_from_uint32 (UINT128 * pres, unsigned int *px
  278. _EXC_MASKS_PARAM _EXC_INFO_PARAM) {
  279. unsigned int x = *px;
  280. #else
  281. UINT128
  282. bid128_from_uint32 (unsigned int x _EXC_MASKS_PARAM _EXC_INFO_PARAM) {
  283. #endif
  284. UINT128 res;
  285. res.w[HIGH_128W] = 0x3040000000000000ull;
  286. res.w[LOW_128W] = x;
  287. BID_RETURN (res);
  288. }
  289. #if DECIMAL_CALL_BY_REFERENCE
  290. void
  291. bid128_from_int64 (UINT128 * pres, SINT64 * px
  292. _EXC_MASKS_PARAM _EXC_INFO_PARAM) {
  293. SINT64 x = *px;
  294. #else
  295. UINT128
  296. bid128_from_int64 (SINT64 x _EXC_MASKS_PARAM _EXC_INFO_PARAM) {
  297. #endif
  298. UINT128 res;
  299. // if integer is negative, use the absolute value
  300. if ((x & SIGNMASK64) == SIGNMASK64) {
  301. res.w[HIGH_128W] = 0xb040000000000000ull;
  302. res.w[LOW_128W] = ~x + 1; // 2's complement of x
  303. } else {
  304. res.w[HIGH_128W] = 0x3040000000000000ull;
  305. res.w[LOW_128W] = x;
  306. }
  307. BID_RETURN (res);
  308. }
  309. #if DECIMAL_CALL_BY_REFERENCE
  310. void
  311. bid128_from_uint64 (UINT128 * pres, UINT64 * px
  312. _EXC_MASKS_PARAM _EXC_INFO_PARAM) {
  313. UINT64 x = *px;
  314. #else
  315. UINT128
  316. bid128_from_uint64 (UINT64 x _EXC_MASKS_PARAM _EXC_INFO_PARAM) {
  317. #endif
  318. UINT128 res;
  319. res.w[HIGH_128W] = 0x3040000000000000ull;
  320. res.w[LOW_128W] = x;
  321. BID_RETURN (res);
  322. }