PageRenderTime 1791ms CodeModel.GetById 29ms RepoModel.GetById 0ms app.codeStats 0ms

/contrib/gcc/double-int.c

https://github.com/okuoku/freebsd-head
C | 401 lines | 253 code | 76 blank | 72 comment | 26 complexity | aea1d9e5c4a990beb01dad441295c628 MD5 | raw file
  1. /* Operations with long integers.
  2. Copyright (C) 2006 Free Software Foundation, Inc.
  3. This file is part of GCC.
  4. GCC is free software; you can redistribute it and/or modify it
  5. under the terms of the GNU General Public License as published by the
  6. Free Software Foundation; either version 2, or (at your option) any
  7. later version.
  8. GCC is distributed in the hope that it will be useful, but WITHOUT
  9. ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  10. FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
  11. for more details.
  12. You should have received a copy of the GNU General Public License
  13. along with GCC; see the file COPYING. If not, write to the Free
  14. Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
  15. 02110-1301, USA. */
  16. #include "config.h"
  17. #include "system.h"
  18. #include "coretypes.h"
  19. #include "tm.h"
  20. #include "tree.h"
  21. /* Returns mask for PREC bits. */
  22. static inline double_int
  23. double_int_mask (unsigned prec)
  24. {
  25. unsigned HOST_WIDE_INT m;
  26. double_int mask;
  27. if (prec > HOST_BITS_PER_WIDE_INT)
  28. {
  29. prec -= HOST_BITS_PER_WIDE_INT;
  30. m = ((unsigned HOST_WIDE_INT) 2 << (prec - 1)) - 1;
  31. mask.high = (HOST_WIDE_INT) m;
  32. mask.low = ALL_ONES;
  33. }
  34. else
  35. {
  36. mask.high = 0;
  37. mask.low = ((unsigned HOST_WIDE_INT) 2 << (prec - 1)) - 1;
  38. }
  39. return mask;
  40. }
  41. /* Clears the bits of CST over the precision PREC. If UNS is false, the bits
  42. outside of the precision are set to the sign bit (i.e., the PREC-th one),
  43. otherwise they are set to zero.
  44. This corresponds to returning the value represented by PREC lowermost bits
  45. of CST, with the given signedness. */
  46. double_int
  47. double_int_ext (double_int cst, unsigned prec, bool uns)
  48. {
  49. if (uns)
  50. return double_int_zext (cst, prec);
  51. else
  52. return double_int_sext (cst, prec);
  53. }
  54. /* The same as double_int_ext with UNS = true. */
  55. double_int
  56. double_int_zext (double_int cst, unsigned prec)
  57. {
  58. double_int mask = double_int_mask (prec);
  59. double_int r;
  60. r.low = cst.low & mask.low;
  61. r.high = cst.high & mask.high;
  62. return r;
  63. }
  64. /* The same as double_int_ext with UNS = false. */
  65. double_int
  66. double_int_sext (double_int cst, unsigned prec)
  67. {
  68. double_int mask = double_int_mask (prec);
  69. double_int r;
  70. unsigned HOST_WIDE_INT snum;
  71. if (prec <= HOST_BITS_PER_WIDE_INT)
  72. snum = cst.low;
  73. else
  74. {
  75. prec -= HOST_BITS_PER_WIDE_INT;
  76. snum = (unsigned HOST_WIDE_INT) cst.high;
  77. }
  78. if (((snum >> (prec - 1)) & 1) == 1)
  79. {
  80. r.low = cst.low | ~mask.low;
  81. r.high = cst.high | ~mask.high;
  82. }
  83. else
  84. {
  85. r.low = cst.low & mask.low;
  86. r.high = cst.high & mask.high;
  87. }
  88. return r;
  89. }
  90. /* Constructs long integer from tree CST. The extra bits over the precision of
  91. the number are filled with sign bit if CST is signed, and with zeros if it
  92. is unsigned. */
  93. double_int
  94. tree_to_double_int (tree cst)
  95. {
  96. /* We do not need to call double_int_restrict here to ensure the semantics as
  97. described, as this is the default one for trees. */
  98. return TREE_INT_CST (cst);
  99. }
  100. /* Returns true if CST fits in unsigned HOST_WIDE_INT. */
  101. bool
  102. double_int_fits_in_uhwi_p (double_int cst)
  103. {
  104. return cst.high == 0;
  105. }
  106. /* Returns true if CST fits in signed HOST_WIDE_INT. */
  107. bool
  108. double_int_fits_in_shwi_p (double_int cst)
  109. {
  110. if (cst.high == 0)
  111. return (HOST_WIDE_INT) cst.low >= 0;
  112. else if (cst.high == -1)
  113. return (HOST_WIDE_INT) cst.low < 0;
  114. else
  115. return false;
  116. }
  117. /* Returns true if CST fits in HOST_WIDE_INT if UNS is false, or in
  118. unsigned HOST_WIDE_INT if UNS is true. */
  119. bool
  120. double_int_fits_in_hwi_p (double_int cst, bool uns)
  121. {
  122. if (uns)
  123. return double_int_fits_in_uhwi_p (cst);
  124. else
  125. return double_int_fits_in_shwi_p (cst);
  126. }
  127. /* Returns value of CST as a signed number. CST must satisfy
  128. double_int_fits_in_shwi_p. */
  129. HOST_WIDE_INT
  130. double_int_to_shwi (double_int cst)
  131. {
  132. return (HOST_WIDE_INT) cst.low;
  133. }
  134. /* Returns value of CST as an unsigned number. CST must satisfy
  135. double_int_fits_in_uhwi_p. */
  136. unsigned HOST_WIDE_INT
  137. double_int_to_uhwi (double_int cst)
  138. {
  139. return cst.low;
  140. }
  141. /* Returns A * B. */
  142. double_int
  143. double_int_mul (double_int a, double_int b)
  144. {
  145. double_int ret;
  146. mul_double (a.low, a.high, b.low, b.high, &ret.low, &ret.high);
  147. return ret;
  148. }
  149. /* Returns A + B. */
  150. double_int
  151. double_int_add (double_int a, double_int b)
  152. {
  153. double_int ret;
  154. add_double (a.low, a.high, b.low, b.high, &ret.low, &ret.high);
  155. return ret;
  156. }
  157. /* Returns -A. */
  158. double_int
  159. double_int_neg (double_int a)
  160. {
  161. double_int ret;
  162. neg_double (a.low, a.high, &ret.low, &ret.high);
  163. return ret;
  164. }
  165. /* Returns A / B (computed as unsigned depending on UNS, and rounded as
  166. specified by CODE). CODE is enum tree_code in fact, but double_int.h
  167. must be included before tree.h. The remainder after the division is
  168. stored to MOD. */
  169. double_int
  170. double_int_divmod (double_int a, double_int b, bool uns, unsigned code,
  171. double_int *mod)
  172. {
  173. double_int ret;
  174. div_and_round_double (code, uns, a.low, a.high, b.low, b.high,
  175. &ret.low, &ret.high, &mod->low, &mod->high);
  176. return ret;
  177. }
  178. /* The same as double_int_divmod with UNS = false. */
  179. double_int
  180. double_int_sdivmod (double_int a, double_int b, unsigned code, double_int *mod)
  181. {
  182. return double_int_divmod (a, b, false, code, mod);
  183. }
  184. /* The same as double_int_divmod with UNS = true. */
  185. double_int
  186. double_int_udivmod (double_int a, double_int b, unsigned code, double_int *mod)
  187. {
  188. return double_int_divmod (a, b, true, code, mod);
  189. }
  190. /* Returns A / B (computed as unsigned depending on UNS, and rounded as
  191. specified by CODE). CODE is enum tree_code in fact, but double_int.h
  192. must be included before tree.h. */
  193. double_int
  194. double_int_div (double_int a, double_int b, bool uns, unsigned code)
  195. {
  196. double_int mod;
  197. return double_int_divmod (a, b, uns, code, &mod);
  198. }
  199. /* The same as double_int_div with UNS = false. */
  200. double_int
  201. double_int_sdiv (double_int a, double_int b, unsigned code)
  202. {
  203. return double_int_div (a, b, false, code);
  204. }
  205. /* The same as double_int_div with UNS = true. */
  206. double_int
  207. double_int_udiv (double_int a, double_int b, unsigned code)
  208. {
  209. return double_int_div (a, b, true, code);
  210. }
  211. /* Returns A % B (computed as unsigned depending on UNS, and rounded as
  212. specified by CODE). CODE is enum tree_code in fact, but double_int.h
  213. must be included before tree.h. */
  214. double_int
  215. double_int_mod (double_int a, double_int b, bool uns, unsigned code)
  216. {
  217. double_int mod;
  218. double_int_divmod (a, b, uns, code, &mod);
  219. return mod;
  220. }
  221. /* The same as double_int_mod with UNS = false. */
  222. double_int
  223. double_int_smod (double_int a, double_int b, unsigned code)
  224. {
  225. return double_int_mod (a, b, false, code);
  226. }
  227. /* The same as double_int_mod with UNS = true. */
  228. double_int
  229. double_int_umod (double_int a, double_int b, unsigned code)
  230. {
  231. return double_int_mod (a, b, true, code);
  232. }
  233. /* Constructs tree in type TYPE from with value given by CST. */
  234. tree
  235. double_int_to_tree (tree type, double_int cst)
  236. {
  237. cst = double_int_ext (cst, TYPE_PRECISION (type), TYPE_UNSIGNED (type));
  238. return build_int_cst_wide (type, cst.low, cst.high);
  239. }
  240. /* Returns true if CST is negative. Of course, CST is considered to
  241. be signed. */
  242. bool
  243. double_int_negative_p (double_int cst)
  244. {
  245. return cst.high < 0;
  246. }
  247. /* Returns -1 if A < B, 0 if A == B and 1 if A > B. Signedness of the
  248. comparison is given by UNS. */
  249. int
  250. double_int_cmp (double_int a, double_int b, bool uns)
  251. {
  252. if (uns)
  253. return double_int_ucmp (a, b);
  254. else
  255. return double_int_scmp (a, b);
  256. }
  257. /* Compares two unsigned values A and B. Returns -1 if A < B, 0 if A == B,
  258. and 1 if A > B. */
  259. int
  260. double_int_ucmp (double_int a, double_int b)
  261. {
  262. if ((unsigned HOST_WIDE_INT) a.high < (unsigned HOST_WIDE_INT) b.high)
  263. return -1;
  264. if ((unsigned HOST_WIDE_INT) a.high > (unsigned HOST_WIDE_INT) b.high)
  265. return 1;
  266. if (a.low < b.low)
  267. return -1;
  268. if (a.low > b.low)
  269. return 1;
  270. return 0;
  271. }
  272. /* Compares two signed values A and B. Returns -1 if A < B, 0 if A == B,
  273. and 1 if A > B. */
  274. int
  275. double_int_scmp (double_int a, double_int b)
  276. {
  277. if (a.high < b.high)
  278. return -1;
  279. if (a.high > b.high)
  280. return 1;
  281. if ((HOST_WIDE_INT) a.low < (HOST_WIDE_INT) b.low)
  282. return -1;
  283. if ((HOST_WIDE_INT) a.low > (HOST_WIDE_INT) b.low)
  284. return 1;
  285. return 0;
  286. }
  287. /* Splits last digit of *CST (taken as unsigned) in BASE and returns it. */
  288. static unsigned
  289. double_int_split_digit (double_int *cst, unsigned base)
  290. {
  291. unsigned HOST_WIDE_INT resl, reml;
  292. HOST_WIDE_INT resh, remh;
  293. div_and_round_double (FLOOR_DIV_EXPR, true, cst->low, cst->high, base, 0,
  294. &resl, &resh, &reml, &remh);
  295. cst->high = resh;
  296. cst->low = resl;
  297. return reml;
  298. }
  299. /* Dumps CST to FILE. If UNS is true, CST is considered to be unsigned,
  300. otherwise it is signed. */
  301. void
  302. dump_double_int (FILE *file, double_int cst, bool uns)
  303. {
  304. unsigned digits[100], n;
  305. int i;
  306. if (double_int_zero_p (cst))
  307. {
  308. fprintf (file, "0");
  309. return;
  310. }
  311. if (!uns && double_int_negative_p (cst))
  312. {
  313. fprintf (file, "-");
  314. cst = double_int_neg (cst);
  315. }
  316. for (n = 0; !double_int_zero_p (cst); n++)
  317. digits[n] = double_int_split_digit (&cst, 10);
  318. for (i = n - 1; i >= 0; i--)
  319. fprintf (file, "%u", digits[i]);
  320. }