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 results of truncated left shift to gmp, see: 8 // https://svn.boost.org/trac/boost/ticket/12790 9 // 10 11 #ifdef _MSC_VER 12 #define _SCL_SECURE_NO_WARNINGS 13 #endif 14 15 #include <boost/multiprecision/gmp.hpp> 16 #include <boost/multiprecision/cpp_int.hpp> 17 #include <boost/random/mersenne_twister.hpp> 18 #include <boost/random/uniform_int.hpp> 19 #include <boost/timer.hpp> 20 #include "test.hpp" 21 22 #if !defined(TEST1) && !defined(TEST2) && !defined(TEST3) 23 #define TEST1 24 #define TEST2 25 #define TEST3 26 #endif 27 28 template <class T> generate_random(unsigned bits_wanted)29T generate_random(unsigned bits_wanted) 30 { 31 static boost::random::mt19937 gen; 32 typedef boost::random::mt19937::result_type random_type; 33 34 T max_val; 35 unsigned digits; 36 if (std::numeric_limits<T>::is_bounded && (bits_wanted == (unsigned)std::numeric_limits<T>::digits)) 37 { 38 max_val = (std::numeric_limits<T>::max)(); 39 digits = std::numeric_limits<T>::digits; 40 } 41 else 42 { 43 max_val = T(1) << bits_wanted; 44 digits = bits_wanted; 45 } 46 47 unsigned bits_per_r_val = std::numeric_limits<random_type>::digits - 1; 48 while ((random_type(1) << bits_per_r_val) > (gen.max)()) 49 --bits_per_r_val; 50 51 unsigned terms_needed = digits / bits_per_r_val + 1; 52 53 T val = 0; 54 for (unsigned i = 0; i < terms_needed; ++i) 55 { 56 val *= (gen.max)(); 57 val += gen(); 58 } 59 val %= max_val; 60 return val; 61 } 62 63 template <class T> test_value(const T & val)64void test_value(const T& val) 65 { 66 boost::multiprecision::mpz_int z(val.str()), mask(1); 67 mask <<= std::numeric_limits<T>::digits; 68 --mask; 69 70 for (unsigned i = 0; i <= std::numeric_limits<T>::digits + 2; ++i) 71 { 72 BOOST_CHECK_EQUAL((val << i).str(), boost::multiprecision::mpz_int(((z << i) & mask)).str()); 73 } 74 } 75 test(const boost::mpl::int_<200> &)76void test(const boost::mpl::int_<200>&) {} 77 78 template <int N> test(boost::mpl::int_<N> const &)79void test(boost::mpl::int_<N> const&) 80 { 81 test(boost::mpl::int_<N + 4>()); 82 83 typedef boost::multiprecision::number<boost::multiprecision::cpp_int_backend<N, N, boost::multiprecision::unsigned_magnitude>, boost::multiprecision::et_off> mp_type; 84 85 std::cout << "Running tests for precision: " << N << std::endl; 86 87 mp_type mp(-1); 88 test_value(mp); 89 90 for (unsigned i = 0; i < 1000; ++i) 91 test_value(generate_random<mp_type>(std::numeric_limits<mp_type>::digits)); 92 } 93 main()94int main() 95 { 96 test(boost::mpl::int_<24>()); 97 return boost::report_errors(); 98 } 99