constexpr_test_cpp_int_5.cpp 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294
  1. // (C) Copyright John Maddock 2019.
  2. // Use, modification and distribution are subject to the
  3. // Boost Software License, Version 1.0. (See accompanying file
  4. // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  5. #include "constexpr_arithmetric_test.hpp"
  6. #include "boost/multiprecision/cpp_int.hpp"
  7. #include "boost/multiprecision/integer.hpp"
  8. #include "test.hpp"
  9. template <class F, class V>
  10. decltype(std::declval<F>()(std::declval<V>())) non_constexpr_invoke(F f, V v)
  11. {
  12. return f(v);
  13. }
  14. //[factorial_decl
  15. template <class T>
  16. constexpr T factorial(const T& a)
  17. {
  18. return a ? a * factorial(a - 1) : 1;
  19. }
  20. //]
  21. template <class T, class U>
  22. constexpr T big_mul(const U& a, const U& b)
  23. {
  24. using boost::multiprecision::multiply;
  25. T result = T();
  26. multiply(result, a, b);
  27. return result;
  28. }
  29. template <class T, class U>
  30. constexpr T big_add(const U& a, const U& b)
  31. {
  32. using boost::multiprecision::add;
  33. T result = T();
  34. add(result, a, b);
  35. return result;
  36. }
  37. template <class T, class U>
  38. constexpr T big_sub(const U& a, const U& b)
  39. {
  40. using boost::multiprecision::subtract;
  41. T result = T();
  42. subtract(result, a, b);
  43. return result;
  44. }
  45. template <class U>
  46. constexpr U div_qr_d(const U& a, const U& b)
  47. {
  48. using boost::multiprecision::divide_qr;
  49. U result = U();
  50. U r = U();
  51. divide_qr(a, b, result, r);
  52. return result;
  53. }
  54. template <class U>
  55. constexpr U div_qr_r(const U& a, const U& b)
  56. {
  57. using boost::multiprecision::divide_qr;
  58. U result = U();
  59. U r = U();
  60. divide_qr(a, b, result, r);
  61. return r;
  62. }
  63. template <class T>
  64. constexpr T do_bit_set(T val, unsigned pos)
  65. {
  66. using boost::multiprecision::bit_set;
  67. bit_set(val, pos);
  68. return val;
  69. }
  70. template <class T>
  71. constexpr T do_bit_unset(T val, unsigned pos)
  72. {
  73. using boost::multiprecision::bit_unset;
  74. bit_unset(val, pos);
  75. return val;
  76. }
  77. template <class T>
  78. constexpr T do_bit_flip(T val, unsigned pos)
  79. {
  80. using boost::multiprecision::bit_flip;
  81. bit_flip(val, pos);
  82. return val;
  83. }
  84. template <class T>
  85. constexpr T test_swap(T a, T b)
  86. {
  87. swap(a, b);
  88. a.swap(b);
  89. return a;
  90. }
  91. int main()
  92. {
  93. using namespace boost::multiprecision::literals;
  94. typedef boost::multiprecision::checked_int1024_t int_backend;
  95. typedef boost::multiprecision::checked_int512_t small_int_backend;
  96. typedef boost::multiprecision::checked_uint1024_t unsigned_backend;
  97. constexpr int_backend f1 = factorial(int_backend(31));
  98. static_assert(f1 == 0x1956ad0aae33a4560c5cd2c000000_cppi);
  99. constexpr unsigned_backend f2 = factorial(unsigned_backend(31));
  100. static_assert(f2 == 0x1956ad0aae33a4560c5cd2c000000_cppui);
  101. //
  102. // Test integer non-member functions:
  103. //
  104. constexpr small_int_backend si1 = (std::numeric_limits<small_int_backend>::max)();
  105. constexpr small_int_backend si2 = 239876;
  106. constexpr std::int32_t i = (std::numeric_limits<int>::max)();
  107. constexpr std::int32_t j = 239876;
  108. // Multiply:
  109. {
  110. constexpr int_backend i1 = big_mul<int_backend>(si1, si2);
  111. int_backend nc;
  112. multiply(nc, si1, si2);
  113. BOOST_CHECK_EQUAL(nc, i1);
  114. constexpr std::int64_t k = big_mul<std::int64_t>(i, j);
  115. std::int64_t ii;
  116. boost::multiprecision::multiply(ii, i, j);
  117. BOOST_CHECK_EQUAL(ii, k);
  118. }
  119. // Add:
  120. {
  121. constexpr int_backend i1 = big_add<int_backend>(si1, si2);
  122. int_backend nc;
  123. add(nc, si1, si2);
  124. BOOST_CHECK_EQUAL(nc, i1);
  125. constexpr std::int64_t k = big_add<std::int64_t>(i, j);
  126. std::int64_t ii;
  127. boost::multiprecision::add(ii, i, j);
  128. BOOST_CHECK_EQUAL(ii, k);
  129. }
  130. // Subtract:
  131. {
  132. constexpr int_backend i1 = big_sub<int_backend>(si1, -si2);
  133. int_backend nc;
  134. subtract(nc, si1, -si2);
  135. BOOST_CHECK_EQUAL(nc, i1);
  136. constexpr std::int64_t k = big_sub<std::int64_t>(i, -j);
  137. std::int64_t ii;
  138. boost::multiprecision::subtract(ii, i, -j);
  139. BOOST_CHECK_EQUAL(ii, k);
  140. }
  141. // divide_qr:
  142. {
  143. constexpr small_int_backend i1 = div_qr_d(si1, si2);
  144. small_int_backend nc, nc2;
  145. divide_qr(si1, si2, nc, nc2);
  146. BOOST_CHECK_EQUAL(nc, i1);
  147. constexpr std::int64_t k = div_qr_d(i, j);
  148. std::int32_t ii, ij;
  149. boost::multiprecision::divide_qr(i, j, ii, ij);
  150. BOOST_CHECK_EQUAL(ii, k);
  151. }
  152. // divide_qr:
  153. {
  154. constexpr small_int_backend i1 = div_qr_r(si1, si2);
  155. small_int_backend nc, nc2;
  156. divide_qr(si1, si2, nc, nc2);
  157. BOOST_CHECK_EQUAL(nc2, i1);
  158. constexpr std::int64_t k = div_qr_r(i, j);
  159. std::int32_t ii, ij;
  160. boost::multiprecision::divide_qr(i, j, ii, ij);
  161. BOOST_CHECK_EQUAL(ij, k);
  162. }
  163. // integer_modulus:
  164. {
  165. constexpr int i1 = integer_modulus(si1, 67);
  166. small_int_backend nc(si1);
  167. int r = integer_modulus(nc, 67);
  168. BOOST_CHECK_EQUAL(r, i1);
  169. constexpr std::int32_t k = boost::multiprecision::integer_modulus(i, j);
  170. std::int32_t ii(i);
  171. r = boost::multiprecision::integer_modulus(ii, j);
  172. BOOST_CHECK_EQUAL(r, k);
  173. }
  174. // powm:
  175. {
  176. constexpr small_int_backend i1 = powm(si1, si2, si2);
  177. small_int_backend nc(si1);
  178. nc = powm(nc, si2, si2);
  179. BOOST_CHECK_EQUAL(nc, i1);
  180. constexpr std::int32_t k = boost::multiprecision::powm(i, j, j);
  181. std::int32_t ii(i);
  182. ii = boost::multiprecision::powm(ii, j, j);
  183. BOOST_CHECK_EQUAL(ii, k);
  184. }
  185. // lsb:
  186. {
  187. constexpr int i1 = lsb(si1);
  188. small_int_backend nc(si1);
  189. int nci = lsb(nc);
  190. BOOST_CHECK_EQUAL(nci, i1);
  191. constexpr std::int32_t k = boost::multiprecision::lsb(i);
  192. std::int32_t ii(i);
  193. ii = boost::multiprecision::lsb(ii);
  194. BOOST_CHECK_EQUAL(ii, k);
  195. }
  196. // msb:
  197. {
  198. constexpr int i1 = msb(si1);
  199. small_int_backend nc(si1);
  200. int nci = msb(nc);
  201. BOOST_CHECK_EQUAL(nci, i1);
  202. constexpr std::int32_t k = boost::multiprecision::msb(i);
  203. std::int32_t ii(i);
  204. ii = boost::multiprecision::msb(ii);
  205. BOOST_CHECK_EQUAL(ii, k);
  206. }
  207. // bit_test:
  208. {
  209. constexpr bool b = bit_test(si1, 1);
  210. static_assert(b);
  211. constexpr bool k = boost::multiprecision::bit_test(i, 1);
  212. static_assert(k);
  213. }
  214. // bit_set:
  215. {
  216. constexpr int_backend i(0);
  217. constexpr int_backend j = do_bit_set(i, 20);
  218. static_assert(bit_test(j, 20));
  219. constexpr int ii(0);
  220. constexpr int jj = do_bit_set(ii, 20);
  221. static_assert(boost::multiprecision::bit_test(jj, 20));
  222. }
  223. // bit_unset:
  224. {
  225. constexpr int_backend r = do_bit_unset(si1, 20);
  226. static_assert(bit_test(r, 20) == false);
  227. constexpr int jj = do_bit_unset(i, 20);
  228. static_assert(boost::multiprecision::bit_test(jj, 20) == false);
  229. }
  230. // bit_unset:
  231. {
  232. constexpr int_backend r = do_bit_flip(si1, 20);
  233. static_assert(bit_test(r, 20) == false);
  234. constexpr int jj = do_bit_flip(i, 20);
  235. static_assert(boost::multiprecision::bit_test(jj, 20) == false);
  236. }
  237. // sqrt:
  238. {
  239. constexpr int_backend r = sqrt(si1);
  240. small_int_backend nc(si1);
  241. nc = sqrt(nc);
  242. BOOST_CHECK_EQUAL(nc, r);
  243. constexpr int jj = boost::multiprecision::sqrt(i);
  244. int k = i;
  245. k = boost::multiprecision::sqrt(k);
  246. BOOST_CHECK_EQUAL(jj, k);
  247. }
  248. {
  249. // swap:
  250. constexpr small_int_backend r = test_swap(si1, si2);
  251. static_assert(si1 == r);
  252. }
  253. {
  254. // gcd:
  255. constexpr int_backend i(si1), j(si1 / 3);
  256. constexpr int_backend k = gcd(i, j);
  257. int_backend ii(i), jj(j);
  258. BOOST_CHECK_EQUAL(k, gcd(ii, jj));
  259. constexpr unsigned_backend ui(i), uj(j);
  260. constexpr unsigned_backend uk = gcd(ui, uj);
  261. unsigned_backend uii(ui), ujj(uj);
  262. BOOST_CHECK_EQUAL(uk, gcd(uii, ujj));
  263. constexpr int_backend l = lcm(i, j);
  264. BOOST_CHECK_EQUAL(l, lcm(ii, jj));
  265. constexpr unsigned_backend ul = lcm(ui, uj);
  266. BOOST_CHECK_EQUAL(ul, lcm(uii, ujj));
  267. }
  268. return boost::report_errors();
  269. }