• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 ///////////////////////////////////////////////////////////////
2 //  Copyright 2012 John Maddock. Distributed under the Boost
3 //  Software License, Version 1.0. (See accompanying file
4 //  LICENSE_1_0.txt or copy at https://www.boost.org/LICENSE_1_0.txt
5 
6 //
7 // Compare arithmetic results using fixed_int to GMP results.
8 //
9 
10 #ifdef _MSC_VER
11 #define _SCL_SECURE_NO_WARNINGS
12 #endif
13 
14 #include <boost/multiprecision/gmp.hpp>
15 #include <boost/multiprecision/fixed_int.hpp>
16 #include <boost/random/mersenne_twister.hpp>
17 #include <boost/random/uniform_int.hpp>
18 #include "test.hpp"
19 
20 template <class T>
generate_random(unsigned bits_wanted)21 T generate_random(unsigned bits_wanted)
22 {
23    static boost::random::mt19937               gen;
24    typedef boost::random::mt19937::result_type random_type;
25 
26    T        max_val;
27    unsigned digits;
28    if (std::numeric_limits<T>::is_bounded && (bits_wanted == std::numeric_limits<T>::digits))
29    {
30       max_val = (std::numeric_limits<T>::max)();
31       digits  = std::numeric_limits<T>::digits;
32    }
33    else
34    {
35       max_val = T(1) << bits_wanted;
36       digits  = bits_wanted;
37    }
38 
39    unsigned bits_per_r_val = std::numeric_limits<random_type>::digits - 1;
40    while ((random_type(1) << bits_per_r_val) > (gen.max)())
41       --bits_per_r_val;
42 
43    unsigned terms_needed = digits / bits_per_r_val + 1;
44 
45    T val = 0;
46    for (unsigned i = 0; i < terms_needed; ++i)
47    {
48       val *= (gen.max)();
49       val += gen();
50    }
51    val %= max_val;
52    return val;
53 }
54 
main()55 int main()
56 {
57    using namespace boost::multiprecision;
58    typedef number<fixed_int<1024, true> > packed_type;
59    unsigned                               last_error_count = 0;
60    for (int i = 0; i < 1000; ++i)
61    {
62       mpz_int a = generate_random<mpz_int>(1000);
63       mpz_int b = generate_random<mpz_int>(512);
64       mpz_int c = generate_random<mpz_int>(256);
65       mpz_int d = generate_random<mpz_int>(32);
66 
67       int si = d.convert_to<int>();
68 
69       packed_type a1 = a.str();
70       packed_type b1 = b.str();
71       packed_type c1 = c.str();
72       packed_type d1 = d.str();
73 
74       BOOST_CHECK_EQUAL(a.str(), a1.str());
75       BOOST_CHECK_EQUAL(b.str(), b1.str());
76       BOOST_CHECK_EQUAL(c.str(), c1.str());
77       BOOST_CHECK_EQUAL(d.str(), d1.str());
78       BOOST_CHECK_EQUAL(mpz_int(a + b).str(), packed_type(a1 + b1).str());
79       BOOST_CHECK_EQUAL(mpz_int(a - b).str(), packed_type(a1 - b1).str());
80       BOOST_CHECK_EQUAL(mpz_int(mpz_int(-a) + b).str(), packed_type(packed_type(-a1) + b1).str());
81       BOOST_CHECK_EQUAL(mpz_int(mpz_int(-a) - b).str(), packed_type(packed_type(-a1) - b1).str());
82       BOOST_CHECK_EQUAL(mpz_int(c * d).str(), packed_type(c1 * d1).str());
83       BOOST_CHECK_EQUAL(mpz_int(c * -d).str(), packed_type(c1 * -d1).str());
84       BOOST_CHECK_EQUAL(mpz_int(-c * d).str(), packed_type(-c1 * d1).str());
85       BOOST_CHECK_EQUAL(mpz_int(b * c).str(), packed_type(b1 * c1).str());
86       BOOST_CHECK_EQUAL(mpz_int(a / b).str(), packed_type(a1 / b1).str());
87       BOOST_CHECK_EQUAL(mpz_int(a / -b).str(), packed_type(a1 / -b1).str());
88       BOOST_CHECK_EQUAL(mpz_int(-a / b).str(), packed_type(-a1 / b1).str());
89       BOOST_CHECK_EQUAL(mpz_int(a / d).str(), packed_type(a1 / d1).str());
90       BOOST_CHECK_EQUAL(mpz_int(a % b).str(), packed_type(a1 % b1).str());
91       BOOST_CHECK_EQUAL(mpz_int(a % -b).str(), packed_type(a1 % -b1).str());
92       BOOST_CHECK_EQUAL(mpz_int(-a % b).str(), packed_type(-a1 % b1).str());
93       BOOST_CHECK_EQUAL(mpz_int(a % d).str(), packed_type(a1 % d1).str());
94       // bitwise ops:
95       BOOST_CHECK_EQUAL(mpz_int(a | b).str(), packed_type(a1 | b1).str());
96       BOOST_CHECK_EQUAL(mpz_int(a & b).str(), packed_type(a1 & b1).str());
97       BOOST_CHECK_EQUAL(mpz_int(a ^ b).str(), packed_type(a1 ^ b1).str());
98       // Now check operations involving integers:
99       BOOST_CHECK_EQUAL(mpz_int(a + si).str(), packed_type(a1 + si).str());
100       BOOST_CHECK_EQUAL(mpz_int(a + -si).str(), packed_type(a1 + -si).str());
101       BOOST_CHECK_EQUAL(mpz_int(-a + si).str(), packed_type(-a1 + si).str());
102       BOOST_CHECK_EQUAL(mpz_int(si + a).str(), packed_type(si + a1).str());
103       BOOST_CHECK_EQUAL(mpz_int(a - si).str(), packed_type(a1 - si).str());
104       BOOST_CHECK_EQUAL(mpz_int(a - -si).str(), packed_type(a1 - -si).str());
105       BOOST_CHECK_EQUAL(mpz_int(-a - si).str(), packed_type(-a1 - si).str());
106       BOOST_CHECK_EQUAL(mpz_int(si - a).str(), packed_type(si - a1).str());
107       BOOST_CHECK_EQUAL(mpz_int(b * si).str(), packed_type(b1 * si).str());
108       BOOST_CHECK_EQUAL(mpz_int(b * -si).str(), packed_type(b1 * -si).str());
109       BOOST_CHECK_EQUAL(mpz_int(-b * si).str(), packed_type(-b1 * si).str());
110       BOOST_CHECK_EQUAL(mpz_int(si * b).str(), packed_type(si * b1).str());
111       BOOST_CHECK_EQUAL(mpz_int(a / si).str(), packed_type(a1 / si).str());
112       BOOST_CHECK_EQUAL(mpz_int(a / -si).str(), packed_type(a1 / -si).str());
113       BOOST_CHECK_EQUAL(mpz_int(-a / si).str(), packed_type(-a1 / si).str());
114       BOOST_CHECK_EQUAL(mpz_int(a % si).str(), packed_type(a1 % si).str());
115       BOOST_CHECK_EQUAL(mpz_int(a % -si).str(), packed_type(a1 % -si).str());
116       BOOST_CHECK_EQUAL(mpz_int(-a % si).str(), packed_type(-a1 % si).str());
117       BOOST_CHECK_EQUAL(mpz_int(a | si).str(), packed_type(a1 | si).str());
118       BOOST_CHECK_EQUAL(mpz_int(a & si).str(), packed_type(a1 & si).str());
119       BOOST_CHECK_EQUAL(mpz_int(a ^ si).str(), packed_type(a1 ^ si).str());
120       BOOST_CHECK_EQUAL(mpz_int(si | a).str(), packed_type(si | a1).str());
121       BOOST_CHECK_EQUAL(mpz_int(si & a).str(), packed_type(si & a1).str());
122       BOOST_CHECK_EQUAL(mpz_int(si ^ a).str(), packed_type(si ^ a1).str());
123       BOOST_CHECK_EQUAL(mpz_int(gcd(a, b)).str(), packed_type(gcd(a1, b1)).str());
124       BOOST_CHECK_EQUAL(mpz_int(lcm(c, d)).str(), packed_type(lcm(c1, d1)).str());
125 
126       if (last_error_count != boost::detail::test_errors())
127       {
128          last_error_count = boost::detail::test_errors();
129          std::cout << std::hex << std::showbase;
130 
131          std::cout << "a    = " << a << std::endl;
132          std::cout << "a1   = " << a1 << std::endl;
133          std::cout << "b    = " << b << std::endl;
134          std::cout << "b1   = " << b1 << std::endl;
135          std::cout << "c    = " << c << std::endl;
136          std::cout << "c1   = " << c1 << std::endl;
137          std::cout << "d    = " << d << std::endl;
138          std::cout << "d1   = " << d1 << std::endl;
139          std::cout << "a + b   = " << a + b << std::endl;
140          std::cout << "a1 + b1 = " << a1 + b1 << std::endl;
141          std::cout << std::dec;
142          std::cout << "a - b   = " << a - b << std::endl;
143          std::cout << "a1 - b1 = " << a1 - b1 << std::endl;
144          std::cout << "-a + b   = " << mpz_int(-a) + b << std::endl;
145          std::cout << "-a1 + b1 = " << packed_type(-a1) + b1 << std::endl;
146          std::cout << "-a - b   = " << mpz_int(-a) - b << std::endl;
147          std::cout << "-a1 - b1 = " << packed_type(-a1) - b1 << std::endl;
148          std::cout << "c*d    = " << c * d << std::endl;
149          std::cout << "c1*d1  = " << c1 * d1 << std::endl;
150          std::cout << "b*c    = " << b * c << std::endl;
151          std::cout << "b1*c1  = " << b1 * c1 << std::endl;
152          std::cout << "a/b    = " << a / b << std::endl;
153          std::cout << "a1/b1  = " << a1 / b1 << std::endl;
154          std::cout << "a/d    = " << a / d << std::endl;
155          std::cout << "a1/d1  = " << a1 / d1 << std::endl;
156          std::cout << "a%b    = " << a % b << std::endl;
157          std::cout << "a1%b1  = " << a1 % b1 << std::endl;
158          std::cout << "a%d    = " << a % d << std::endl;
159          std::cout << "a1%d1  = " << a1 % d1 << std::endl;
160       }
161    }
162    return boost::report_errors();
163 }
164