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