summaryrefslogtreecommitdiff
path: root/src/third_party/boost-1.60.0/boost/multiprecision/integer.hpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/third_party/boost-1.60.0/boost/multiprecision/integer.hpp')
-rw-r--r--src/third_party/boost-1.60.0/boost/multiprecision/integer.hpp251
1 files changed, 251 insertions, 0 deletions
diff --git a/src/third_party/boost-1.60.0/boost/multiprecision/integer.hpp b/src/third_party/boost-1.60.0/boost/multiprecision/integer.hpp
new file mode 100644
index 00000000000..e4c8bf8b6cb
--- /dev/null
+++ b/src/third_party/boost-1.60.0/boost/multiprecision/integer.hpp
@@ -0,0 +1,251 @@
+///////////////////////////////////////////////////////////////
+// Copyright 2012 John Maddock. Distributed under the Boost
+// Software License, Version 1.0. (See accompanying file
+// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_
+
+#ifndef BOOST_MP_INTEGER_HPP
+#define BOOST_MP_INTEGER_HPP
+
+#include <boost/multiprecision/cpp_int.hpp>
+#include <boost/multiprecision/detail/bitscan.hpp>
+
+namespace boost{
+namespace multiprecision{
+
+template <class Integer, class I2>
+typename enable_if_c<is_integral<Integer>::value && is_integral<I2>::value, Integer&>::type
+ multiply(Integer& result, const I2& a, const I2& b)
+{
+ return result = static_cast<Integer>(a) * static_cast<Integer>(b);
+}
+template <class Integer, class I2>
+typename enable_if_c<is_integral<Integer>::value && is_integral<I2>::value, Integer&>::type
+ add(Integer& result, const I2& a, const I2& b)
+{
+ return result = static_cast<Integer>(a) + static_cast<Integer>(b);
+}
+template <class Integer, class I2>
+typename enable_if_c<is_integral<Integer>::value && is_integral<I2>::value, Integer&>::type
+ subtract(Integer& result, const I2& a, const I2& b)
+{
+ return result = static_cast<Integer>(a) - static_cast<Integer>(b);
+}
+
+template <class Integer>
+typename enable_if_c<is_integral<Integer>::value>::type divide_qr(const Integer& x, const Integer& y, Integer& q, Integer& r)
+{
+ q = x / y;
+ r = x % y;
+}
+
+template <class I1, class I2>
+typename enable_if_c<is_integral<I1>::value && is_integral<I2>::value, I2>::type integer_modulus(const I1& x, I2 val)
+{
+ return static_cast<I2>(x % val);
+}
+
+namespace detail{
+//
+// Figure out the kind of integer that has twice as many bits as some builtin
+// integer type I. Use a native type if we can (including types which may not
+// be recognised by boost::int_t because they're larger than boost::long_long_type),
+// otherwise synthesize a cpp_int to do the job.
+//
+template <class I>
+struct double_integer
+{
+ static const unsigned int_t_digits =
+ 2 * sizeof(I) <= sizeof(boost::long_long_type) ? std::numeric_limits<I>::digits * 2 : 1;
+
+ typedef typename mpl::if_c<
+ 2 * sizeof(I) <= sizeof(boost::long_long_type),
+ typename mpl::if_c<
+ is_signed<I>::value,
+ typename boost::int_t<int_t_digits>::least,
+ typename boost::uint_t<int_t_digits>::least
+ >::type,
+ typename mpl::if_c<
+ 2 * sizeof(I) <= sizeof(double_limb_type),
+ typename mpl::if_c<
+ is_signed<I>::value,
+ signed_double_limb_type,
+ double_limb_type
+ >::type,
+ number<cpp_int_backend<sizeof(I)*CHAR_BIT*2, sizeof(I)*CHAR_BIT*2, (is_signed<I>::value ? signed_magnitude : unsigned_magnitude), unchecked, void> >
+ >::type
+ >::type type;
+};
+
+}
+
+template <class I1, class I2, class I3>
+typename enable_if_c<is_integral<I1>::value && is_unsigned<I2>::value && is_integral<I3>::value, I1>::type
+ powm(const I1& a, I2 b, I3 c)
+{
+ typedef typename detail::double_integer<I1>::type double_type;
+
+ I1 x(1), y(a);
+ double_type result;
+
+ while(b > 0)
+ {
+ if(b & 1)
+ {
+ multiply(result, x, y);
+ x = integer_modulus(result, c);
+ }
+ multiply(result, y, y);
+ y = integer_modulus(result, c);
+ b >>= 1;
+ }
+ return x % c;
+}
+
+template <class I1, class I2, class I3>
+inline typename enable_if_c<is_integral<I1>::value && is_signed<I2>::value && is_integral<I3>::value, I1>::type
+ powm(const I1& a, I2 b, I3 c)
+{
+ if(b < 0)
+ {
+ BOOST_THROW_EXCEPTION(std::runtime_error("powm requires a positive exponent."));
+ }
+ return powm(a, static_cast<typename make_unsigned<I2>::type>(b), c);
+}
+
+template <class Integer>
+typename enable_if_c<is_integral<Integer>::value, unsigned>::type lsb(const Integer& val)
+{
+ if(val <= 0)
+ {
+ if(val == 0)
+ {
+ BOOST_THROW_EXCEPTION(std::range_error("No bits were set in the operand."));
+ }
+ else
+ {
+ BOOST_THROW_EXCEPTION(std::range_error("Testing individual bits in negative values is not supported - results are undefined."));
+ }
+ }
+ return detail::find_lsb(val);
+}
+
+template <class Integer>
+typename enable_if_c<is_integral<Integer>::value, unsigned>::type msb(Integer val)
+{
+ if(val <= 0)
+ {
+ if(val == 0)
+ {
+ BOOST_THROW_EXCEPTION(std::range_error("No bits were set in the operand."));
+ }
+ else
+ {
+ BOOST_THROW_EXCEPTION(std::range_error("Testing individual bits in negative values is not supported - results are undefined."));
+ }
+ }
+ return detail::find_msb(val);
+}
+
+template <class Integer>
+typename enable_if_c<is_integral<Integer>::value, bool>::type bit_test(const Integer& val, unsigned index)
+{
+ Integer mask = 1;
+ if(index >= sizeof(Integer) * CHAR_BIT)
+ return 0;
+ if(index)
+ mask <<= index;
+ return val & mask ? true : false;
+}
+
+template <class Integer>
+typename enable_if_c<is_integral<Integer>::value, Integer&>::type bit_set(Integer& val, unsigned index)
+{
+ Integer mask = 1;
+ if(index >= sizeof(Integer) * CHAR_BIT)
+ return val;
+ if(index)
+ mask <<= index;
+ val |= mask;
+ return val;
+}
+
+template <class Integer>
+typename enable_if_c<is_integral<Integer>::value, Integer&>::type bit_unset(Integer& val, unsigned index)
+{
+ Integer mask = 1;
+ if(index >= sizeof(Integer) * CHAR_BIT)
+ return val;
+ if(index)
+ mask <<= index;
+ val &= ~mask;
+ return val;
+}
+
+template <class Integer>
+typename enable_if_c<is_integral<Integer>::value, Integer&>::type bit_flip(Integer& val, unsigned index)
+{
+ Integer mask = 1;
+ if(index >= sizeof(Integer) * CHAR_BIT)
+ return val;
+ if(index)
+ mask <<= index;
+ val ^= mask;
+ return val;
+}
+
+template <class Integer>
+typename enable_if_c<is_integral<Integer>::value, Integer>::type sqrt(const Integer& x, Integer& r)
+{
+ //
+ // This is slow bit-by-bit integer square root, see for example
+ // http://en.wikipedia.org/wiki/Methods_of_computing_square_roots#Binary_numeral_system_.28base_2.29
+ // There are better methods such as http://hal.inria.fr/docs/00/07/28/54/PDF/RR-3805.pdf
+ // and http://hal.inria.fr/docs/00/07/21/13/PDF/RR-4475.pdf which should be implemented
+ // at some point.
+ //
+ Integer s = 0;
+ if(x == 0)
+ {
+ r = 0;
+ return s;
+ }
+ int g = msb(x);
+ if(g == 0)
+ {
+ r = 1;
+ return s;
+ }
+
+ Integer t = 0;
+ r = x;
+ g /= 2;
+ bit_set(s, g);
+ bit_set(t, 2 * g);
+ r = x - t;
+ --g;
+ do
+ {
+ t = s;
+ t <<= g + 1;
+ bit_set(t, 2 * g);
+ if(t <= r)
+ {
+ bit_set(s, g);
+ r -= t;
+ }
+ --g;
+ }
+ while(g >= 0);
+ return s;
+}
+
+template <class Integer>
+typename enable_if_c<is_integral<Integer>::value, Integer>::type sqrt(const Integer& x)
+{
+ Integer r;
+ return sqrt(x, r);
+}
+
+}} // namespaces
+
+#endif