252 lines
		
	
	
		
			6.9 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
		
		
			
		
	
	
			252 lines
		
	
	
		
			6.9 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
| 
								 | 
							
								///////////////////////////////////////////////////////////////
							 | 
						||
| 
								 | 
							
								//  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
							 |