]> git.proxmox.com Git - ceph.git/blobdiff - ceph/src/boost/libs/multiprecision/test/test_cpp_int_karatsuba.cpp
update source to Ceph Pacific 16.2.2
[ceph.git] / ceph / src / boost / libs / multiprecision / test / test_cpp_int_karatsuba.cpp
diff --git a/ceph/src/boost/libs/multiprecision/test/test_cpp_int_karatsuba.cpp b/ceph/src/boost/libs/multiprecision/test/test_cpp_int_karatsuba.cpp
new file mode 100644 (file)
index 0000000..06b89c0
--- /dev/null
@@ -0,0 +1,289 @@
+///////////////////////////////////////////////////////////////
+//  Copyright 2012 John Maddock. Distributed under the Boost
+//  Software License, Version 1.0. (See accompanying file
+//  LICENSE_1_0.txt or copy at https://www.boost.org/LICENSE_1_0.txt
+
+//
+// Compare arithmetic results using fixed_int to GMP results.
+//
+
+#ifdef _MSC_VER
+#define _SCL_SECURE_NO_WARNINGS
+#endif
+
+//
+// This ensures all our code gets tested, even though it may
+// not be the fastest configuration in normal use:
+//
+#define BOOST_MP_USE_LIMB_SHIFT
+
+#include <boost/multiprecision/gmp.hpp>
+#include <boost/multiprecision/cpp_int.hpp>
+#include <boost/random/mersenne_twister.hpp>
+#include <boost/random/uniform_int.hpp>
+#include <boost/timer.hpp>
+#include "test.hpp"
+
+#ifdef _MSC_VER
+#pragma warning(disable : 4127) //  Conditional expression is constant
+#endif
+
+#ifndef TEST
+#define TEST 0
+#endif
+
+template <class T>
+T generate_random(unsigned bits_wanted)
+{
+   static boost::random::mt19937               gen;
+   typedef boost::random::mt19937::result_type random_type;
+
+   T        max_val;
+   unsigned digits;
+   if (std::numeric_limits<T>::is_bounded && (bits_wanted == (unsigned)std::numeric_limits<T>::digits))
+   {
+      max_val = (std::numeric_limits<T>::max)();
+      digits  = std::numeric_limits<T>::digits;
+   }
+   else
+   {
+      max_val = T(1) << bits_wanted;
+      digits  = bits_wanted;
+   }
+
+   unsigned bits_per_r_val = std::numeric_limits<random_type>::digits - 1;
+   while ((random_type(1) << bits_per_r_val) > (gen.max)())
+      --bits_per_r_val;
+
+   unsigned terms_needed = digits / bits_per_r_val + 1;
+
+   T val = 0;
+   for (unsigned i = 0; i < terms_needed; ++i)
+   {
+      val *= (gen.max)();
+      val += gen();
+   }
+   val %= max_val;
+   return val;
+}
+
+template <class T>
+struct is_checked_cpp_int : public boost::mpl::false_
+{};
+template <unsigned MinBits, unsigned MaxBits, boost::multiprecision::cpp_integer_type SignType, class Allocator, boost::multiprecision::expression_template_option ET>
+struct is_checked_cpp_int<boost::multiprecision::number<boost::multiprecision::cpp_int_backend<MinBits, MaxBits, SignType, boost::multiprecision::checked, Allocator>, ET> > : public boost::mpl::true_
+{};
+
+template <class N>
+typename boost::enable_if_c<boost::multiprecision::backends::is_fixed_precision<typename N::backend_type>::value && !is_checked_cpp_int<N>::value>::type test(const N&)
+{
+   using namespace boost::multiprecision;
+
+   static unsigned last_error_count = 0;
+
+   boost::timer tim;
+
+   do
+   {
+      // Test modular arithmetic by filling all the bits of our test type:
+      mpz_int f = generate_random<mpz_int>(std::numeric_limits<N>::digits + 2);
+      mpz_int g = generate_random<mpz_int>(std::numeric_limits<N>::digits + 2);
+      mpz_int mask(1);
+      mask <<= std::numeric_limits<N>::digits;
+      --mask;
+      f &= mask;
+      g &= mask;
+      mpz_int r = (f * g) & mask;
+
+      N f1(f);
+      N g1(g);
+      N r1 = f1 * g1;
+      BOOST_CHECK_EQUAL(r1.str(), r.str());
+
+      if (last_error_count != (unsigned)boost::detail::test_errors())
+      {
+         last_error_count = boost::detail::test_errors();
+         std::cout << std::hex << std::showbase;
+         std::cout << f1 << std::endl;
+         std::cout << f << std::endl;
+         std::cout << g1 << std::endl;
+         std::cout << g << std::endl;
+         std::cout << r1 << std::endl;
+         std::cout << r << std::endl;
+      }
+
+      static boost::random::mt19937             gen;
+      boost::random::uniform_int_distribution<> d(12, std::numeric_limits<N>::digits);
+      f = generate_random<mpz_int>(d(gen));
+      g = generate_random<mpz_int>(d(gen));
+      r = (f * g) & mask;
+
+      f1 = N(f);
+      g1 = N(g);
+      r1 = f1 * g1;
+      BOOST_CHECK_EQUAL(r1.str(), r.str());
+
+      if (last_error_count != (unsigned)boost::detail::test_errors())
+      {
+         last_error_count = boost::detail::test_errors();
+         std::cout << std::hex << std::showbase;
+         std::cout << f1 << std::endl;
+         std::cout << f << std::endl;
+         std::cout << g1 << std::endl;
+         std::cout << g << std::endl;
+         std::cout << r1 << std::endl;
+         std::cout << r << std::endl;
+      }
+
+#ifndef CI_SUPPRESS_KNOWN_ISSUES
+      if (tim.elapsed() > 200)
+#else
+      if (tim.elapsed() > 25)
+#endif
+      {
+         std::cout << "Timeout reached, aborting tests now....\n";
+         break;
+      }
+
+   } while (true);
+   //
+   // Special cases:
+   //
+   mpz_int mask;
+   if (std::numeric_limits<N>::is_bounded)
+      mask = mpz_int((std::numeric_limits<N>::max)());
+   mpz_int a, b;
+   N       x, y;
+
+   unsigned upper_limit = std::numeric_limits<N>::is_bounded ? std::numeric_limits<N>::digits - 1 : 8192 * 2;
+   for (unsigned i = 1024; i < upper_limit; i *= 2)
+   {
+      a = 1;
+      a <<= i;
+      --a;
+      x = 1;
+      x <<= i;
+      --x;
+
+      b = a * a;
+      if (std::numeric_limits<N>::is_bounded)
+         b &= mask;
+      y = x * x;
+
+      BOOST_CHECK_EQUAL(y.str(), b.str());
+
+      if (last_error_count != (unsigned)boost::detail::test_errors())
+      {
+         last_error_count = boost::detail::test_errors();
+         std::cout << std::hex << std::showbase;
+         std::cout << a << std::endl;
+         std::cout << x << std::endl;
+         std::cout << b << std::endl;
+         std::cout << y << std::endl;
+      }
+   }
+}
+template <class N>
+typename boost::disable_if_c<boost::multiprecision::backends::is_fixed_precision<typename N::backend_type>::value && !is_checked_cpp_int<N>::value>::type test(const N&)
+{
+   using namespace boost::multiprecision;
+
+   static unsigned last_error_count = 0;
+
+   boost::timer tim;
+
+   mpz_int mask;
+   if (std::numeric_limits<N>::is_bounded)
+      mask = mpz_int((std::numeric_limits<N>::max)());
+   do
+   {
+      // Test modular arithmetic by filling all the bits of our test type:
+      static boost::random::mt19937             gen;
+      boost::random::uniform_int_distribution<> d(12, std::numeric_limits<N>::is_bounded ? std::numeric_limits<N>::digits : 100000);
+      mpz_int                                   f = generate_random<mpz_int>(d(gen));
+      mpz_int                                   g = generate_random<mpz_int>(d(gen));
+      mpz_int                                   r = f * g;
+      if (std::numeric_limits<N>::is_bounded)
+         r &= mask;
+
+      N f1(f);
+      N g1(g);
+      N r1 = f1 * g1;
+      BOOST_CHECK_EQUAL(r1.str(), r.str());
+
+      if (last_error_count != (unsigned)boost::detail::test_errors())
+      {
+         last_error_count = boost::detail::test_errors();
+         std::cout << std::hex << std::showbase;
+         std::cout << f1 << std::endl;
+         std::cout << f << std::endl;
+         std::cout << g1 << std::endl;
+         std::cout << g << std::endl;
+         std::cout << r1 << std::endl;
+         std::cout << r << std::endl;
+      }
+
+#ifndef CI_SUPPRESS_KNOWN_ISSUES
+      if (tim.elapsed() > 200)
+#else
+      if (tim.elapsed() > 25)
+#endif
+      {
+         std::cout << "Timeout reached, aborting tests now....\n";
+         break;
+      }
+
+   } while (true);
+   //
+   // Special cases:
+   //
+   mpz_int a, b;
+   N       x, y;
+
+   unsigned upper_limit = std::numeric_limits<N>::is_bounded ? std::numeric_limits<N>::digits - 1 : 8192 * 2;
+   for (unsigned i = 1024; i < upper_limit; i *= 2)
+   {
+      a = 1;
+      a <<= i;
+      --a;
+      x = 1;
+      x <<= i;
+      --x;
+
+      b = a * a;
+      if (std::numeric_limits<N>::is_bounded)
+         b &= mask;
+      y = x * x;
+
+      BOOST_CHECK_EQUAL(y.str(), b.str());
+
+      if (last_error_count != (unsigned)boost::detail::test_errors())
+      {
+         last_error_count = boost::detail::test_errors();
+         std::cout << std::hex << std::showbase;
+         std::cout << a << std::endl;
+         std::cout << x << std::endl;
+         std::cout << b << std::endl;
+         std::cout << y << std::endl;
+      }
+   }
+}
+
+int main()
+{
+   using namespace boost::multiprecision;
+
+#if (TEST == 1) || (TEST == 0)
+   test(cpp_int());
+#endif
+#if (TEST == 2) || (TEST == 0)
+   test(number<cpp_int_backend<8192, 8192, signed_magnitude, unchecked, void> >());
+#endif
+#if (TEST == 3) || (TEST == 0)
+   test(number<cpp_int_backend<8192, 8192, signed_magnitude, unchecked, std::allocator<char> > >());
+#endif
+#if (TEST == 4) || (TEST == 0)
+   test(number<cpp_int_backend<8192, 8192, unsigned_magnitude, unchecked> >());
+#endif
+   return boost::report_errors();
+}