429 lines
		
	
	
		
			16 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
		
		
			
		
	
	
			429 lines
		
	
	
		
			16 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
| 
								 | 
							
								//  (C) Copyright Jeremy William Murphy 2016.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								//  Use, modification and distribution are subject to the
							 | 
						||
| 
								 | 
							
								//  Boost Software License, Version 1.0. (See accompanying file
							 | 
						||
| 
								 | 
							
								//  LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#ifndef BOOST_MATH_COMMON_FACTOR_RT_HPP
							 | 
						||
| 
								 | 
							
								#define BOOST_MATH_COMMON_FACTOR_RT_HPP
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#include <boost/assert.hpp>
							 | 
						||
| 
								 | 
							
								#include <boost/core/enable_if.hpp>
							 | 
						||
| 
								 | 
							
								#include <boost/mpl/and.hpp>
							 | 
						||
| 
								 | 
							
								#include <boost/type_traits.hpp>
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#include <boost/config.hpp>  // for BOOST_NESTED_TEMPLATE, etc.
							 | 
						||
| 
								 | 
							
								#include <boost/limits.hpp>  // for std::numeric_limits
							 | 
						||
| 
								 | 
							
								#include <climits>           // for CHAR_MIN
							 | 
						||
| 
								 | 
							
								#include <boost/detail/workaround.hpp>
							 | 
						||
| 
								 | 
							
								#include <iterator>
							 | 
						||
| 
								 | 
							
								#include <algorithm>
							 | 
						||
| 
								 | 
							
								#include <limits>
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#if (defined(BOOST_MSVC) || (defined(__clang__) && defined(__c2__)) || (defined(BOOST_INTEL) && defined(_MSC_VER))) && (defined(_M_IX86) || defined(_M_X64))
							 | 
						||
| 
								 | 
							
								#include <intrin.h>
							 | 
						||
| 
								 | 
							
								#endif
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#ifdef BOOST_MSVC
							 | 
						||
| 
								 | 
							
								#pragma warning(push)
							 | 
						||
| 
								 | 
							
								#pragma warning(disable:4127 4244)  // Conditional expression is constant
							 | 
						||
| 
								 | 
							
								#endif
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								namespace boost {
							 | 
						||
| 
								 | 
							
								   namespace math {
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      template <class T, bool a = is_unsigned<T>::value || (std::numeric_limits<T>::is_specialized && !std::numeric_limits<T>::is_signed)>
							 | 
						||
| 
								 | 
							
								      struct gcd_traits_abs_defaults
							 | 
						||
| 
								 | 
							
								      {
							 | 
						||
| 
								 | 
							
								         inline static const T& abs(const T& val) { return val; }
							 | 
						||
| 
								 | 
							
								      };
							 | 
						||
| 
								 | 
							
								      template <class T>
							 | 
						||
| 
								 | 
							
								      struct gcd_traits_abs_defaults<T, false>
							 | 
						||
| 
								 | 
							
								      {
							 | 
						||
| 
								 | 
							
								         inline static T abs(const T& val)
							 | 
						||
| 
								 | 
							
								         {
							 | 
						||
| 
								 | 
							
								            using std::abs;
							 | 
						||
| 
								 | 
							
								            return abs(val);
							 | 
						||
| 
								 | 
							
								         }
							 | 
						||
| 
								 | 
							
								      };
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      template <class T>
							 | 
						||
| 
								 | 
							
								      struct gcd_traits_defaults : public gcd_traits_abs_defaults<T>
							 | 
						||
| 
								 | 
							
								      {
							 | 
						||
| 
								 | 
							
								         BOOST_FORCEINLINE static unsigned make_odd(T& val)
							 | 
						||
| 
								 | 
							
								         {
							 | 
						||
| 
								 | 
							
								            unsigned r = 0;
							 | 
						||
| 
								 | 
							
								            while(!(val & 1u))
							 | 
						||
| 
								 | 
							
								            {
							 | 
						||
| 
								 | 
							
								               val >>= 1;
							 | 
						||
| 
								 | 
							
								               ++r;
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								            return r;
							 | 
						||
| 
								 | 
							
								         }
							 | 
						||
| 
								 | 
							
								         inline static bool less(const T& a, const T& b)
							 | 
						||
| 
								 | 
							
								         {
							 | 
						||
| 
								 | 
							
								            return a < b;
							 | 
						||
| 
								 | 
							
								         }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								         enum method_type
							 | 
						||
| 
								 | 
							
								         {
							 | 
						||
| 
								 | 
							
								            method_euclid = 0,
							 | 
						||
| 
								 | 
							
								            method_binary = 1,
							 | 
						||
| 
								 | 
							
								            method_mixed = 2,
							 | 
						||
| 
								 | 
							
								         };
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								         static const method_type method =
							 | 
						||
| 
								 | 
							
								            boost::has_right_shift_assign<T>::value && boost::has_left_shift_assign<T>::value && boost::has_less<T>::value && boost::has_modulus<T>::value
							 | 
						||
| 
								 | 
							
								            ? method_mixed :
							 | 
						||
| 
								 | 
							
								            boost::has_right_shift_assign<T>::value && boost::has_left_shift_assign<T>::value && boost::has_less<T>::value
							 | 
						||
| 
								 | 
							
								            ? method_binary : method_euclid;
							 | 
						||
| 
								 | 
							
								      };
							 | 
						||
| 
								 | 
							
								      //
							 | 
						||
| 
								 | 
							
								      // Default gcd_traits just inherits from defaults:
							 | 
						||
| 
								 | 
							
								      //
							 | 
						||
| 
								 | 
							
								      template <class T>
							 | 
						||
| 
								 | 
							
								      struct gcd_traits : public gcd_traits_defaults<T> {};
							 | 
						||
| 
								 | 
							
								      //
							 | 
						||
| 
								 | 
							
								      // Special handling for polynomials:
							 | 
						||
| 
								 | 
							
								      //
							 | 
						||
| 
								 | 
							
								      namespace tools {
							 | 
						||
| 
								 | 
							
								         template <class T>
							 | 
						||
| 
								 | 
							
								         class polynomial;
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      template <class T>
							 | 
						||
| 
								 | 
							
								      struct gcd_traits<boost::math::tools::polynomial<T> > : public gcd_traits_defaults<T>
							 | 
						||
| 
								 | 
							
								      {
							 | 
						||
| 
								 | 
							
								         static const boost::math::tools::polynomial<T>& abs(const boost::math::tools::polynomial<T>& val) { return val; }
							 | 
						||
| 
								 | 
							
								      };
							 | 
						||
| 
								 | 
							
								      //
							 | 
						||
| 
								 | 
							
								      // Some platforms have fast bitscan operations, that allow us to implement
							 | 
						||
| 
								 | 
							
								      // make_odd much more efficiently:
							 | 
						||
| 
								 | 
							
								      //
							 | 
						||
| 
								 | 
							
								#if (defined(BOOST_MSVC) || (defined(__clang__) && defined(__c2__)) || (defined(BOOST_INTEL) && defined(_MSC_VER))) && (defined(_M_IX86) || defined(_M_X64))
							 | 
						||
| 
								 | 
							
								#pragma intrinsic(_BitScanForward,)
							 | 
						||
| 
								 | 
							
								      template <>
							 | 
						||
| 
								 | 
							
								      struct gcd_traits<unsigned long> : public gcd_traits_defaults<unsigned long>
							 | 
						||
| 
								 | 
							
								      {
							 | 
						||
| 
								 | 
							
								         BOOST_FORCEINLINE static unsigned find_lsb(unsigned long val)
							 | 
						||
| 
								 | 
							
								         {
							 | 
						||
| 
								 | 
							
								            unsigned long result;
							 | 
						||
| 
								 | 
							
								            _BitScanForward(&result, val);
							 | 
						||
| 
								 | 
							
								            return result;
							 | 
						||
| 
								 | 
							
								         }
							 | 
						||
| 
								 | 
							
								         BOOST_FORCEINLINE static unsigned make_odd(unsigned long& val)
							 | 
						||
| 
								 | 
							
								         {
							 | 
						||
| 
								 | 
							
								            unsigned result = find_lsb(val);
							 | 
						||
| 
								 | 
							
								            val >>= result;
							 | 
						||
| 
								 | 
							
								            return result;
							 | 
						||
| 
								 | 
							
								         }
							 | 
						||
| 
								 | 
							
								      };
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#ifdef _M_X64
							 | 
						||
| 
								 | 
							
								#pragma intrinsic(_BitScanForward64)
							 | 
						||
| 
								 | 
							
								      template <>
							 | 
						||
| 
								 | 
							
								      struct gcd_traits<unsigned __int64> : public gcd_traits_defaults<unsigned __int64>
							 | 
						||
| 
								 | 
							
								      {
							 | 
						||
| 
								 | 
							
								         BOOST_FORCEINLINE static unsigned find_lsb(unsigned __int64 mask)
							 | 
						||
| 
								 | 
							
								         {
							 | 
						||
| 
								 | 
							
								            unsigned long result;
							 | 
						||
| 
								 | 
							
								            _BitScanForward64(&result, mask);
							 | 
						||
| 
								 | 
							
								            return result;
							 | 
						||
| 
								 | 
							
								         }
							 | 
						||
| 
								 | 
							
								         BOOST_FORCEINLINE static unsigned make_odd(unsigned __int64& val)
							 | 
						||
| 
								 | 
							
								         {
							 | 
						||
| 
								 | 
							
								            unsigned result = find_lsb(val);
							 | 
						||
| 
								 | 
							
								            val >>= result;
							 | 
						||
| 
								 | 
							
								            return result;
							 | 
						||
| 
								 | 
							
								         }
							 | 
						||
| 
								 | 
							
								      };
							 | 
						||
| 
								 | 
							
								#endif
							 | 
						||
| 
								 | 
							
								      //
							 | 
						||
| 
								 | 
							
								      // Other integer type are trivial adaptations of the above,
							 | 
						||
| 
								 | 
							
								      // this works for signed types too, as by the time these functions
							 | 
						||
| 
								 | 
							
								      // are called, all values are > 0.
							 | 
						||
| 
								 | 
							
								      //
							 | 
						||
| 
								 | 
							
								      template <> struct gcd_traits<long> : public gcd_traits_defaults<long> 
							 | 
						||
| 
								 | 
							
								      { BOOST_FORCEINLINE static unsigned make_odd(long& val){ unsigned result = gcd_traits<unsigned long>::find_lsb(val); val >>= result; return result; } };
							 | 
						||
| 
								 | 
							
								      template <> struct gcd_traits<unsigned int> : public gcd_traits_defaults<unsigned int> 
							 | 
						||
| 
								 | 
							
								      { BOOST_FORCEINLINE static unsigned make_odd(unsigned int& val){ unsigned result = gcd_traits<unsigned long>::find_lsb(val); val >>= result; return result; } };
							 | 
						||
| 
								 | 
							
								      template <> struct gcd_traits<int> : public gcd_traits_defaults<int> 
							 | 
						||
| 
								 | 
							
								      { BOOST_FORCEINLINE static unsigned make_odd(int& val){ unsigned result = gcd_traits<unsigned long>::find_lsb(val); val >>= result; return result; } };
							 | 
						||
| 
								 | 
							
								      template <> struct gcd_traits<unsigned short> : public gcd_traits_defaults<unsigned short> 
							 | 
						||
| 
								 | 
							
								      { BOOST_FORCEINLINE static unsigned make_odd(unsigned short& val){ unsigned result = gcd_traits<unsigned long>::find_lsb(val); val >>= result; return result; } };
							 | 
						||
| 
								 | 
							
								      template <> struct gcd_traits<short> : public gcd_traits_defaults<short> 
							 | 
						||
| 
								 | 
							
								      { BOOST_FORCEINLINE static unsigned make_odd(short& val){ unsigned result = gcd_traits<unsigned long>::find_lsb(val); val >>= result; return result; } };
							 | 
						||
| 
								 | 
							
								      template <> struct gcd_traits<unsigned char> : public gcd_traits_defaults<unsigned char> 
							 | 
						||
| 
								 | 
							
								      { BOOST_FORCEINLINE static unsigned make_odd(unsigned char& val){ unsigned result = gcd_traits<unsigned long>::find_lsb(val); val >>= result; return result; } };
							 | 
						||
| 
								 | 
							
								      template <> struct gcd_traits<signed char> : public gcd_traits_defaults<signed char> 
							 | 
						||
| 
								 | 
							
								      { BOOST_FORCEINLINE static signed make_odd(signed char& val){ signed result = gcd_traits<unsigned long>::find_lsb(val); val >>= result; return result; } };
							 | 
						||
| 
								 | 
							
								      template <> struct gcd_traits<char> : public gcd_traits_defaults<char> 
							 | 
						||
| 
								 | 
							
								      { BOOST_FORCEINLINE static unsigned make_odd(char& val){ unsigned result = gcd_traits<unsigned long>::find_lsb(val); val >>= result; return result; } };
							 | 
						||
| 
								 | 
							
								      template <> struct gcd_traits<wchar_t> : public gcd_traits_defaults<wchar_t> 
							 | 
						||
| 
								 | 
							
								      { BOOST_FORCEINLINE static unsigned make_odd(wchar_t& val){ unsigned result = gcd_traits<unsigned long>::find_lsb(val); val >>= result; return result; } };
							 | 
						||
| 
								 | 
							
								#ifdef _M_X64
							 | 
						||
| 
								 | 
							
								      template <> struct gcd_traits<__int64> : public gcd_traits_defaults<__int64> 
							 | 
						||
| 
								 | 
							
								      { BOOST_FORCEINLINE static unsigned make_odd(__int64& val){ unsigned result = gcd_traits<unsigned __int64>::find_lsb(val); val >>= result; return result; } };
							 | 
						||
| 
								 | 
							
								#endif
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#elif defined(BOOST_GCC) || defined(__clang__) || (defined(BOOST_INTEL) && defined(__GNUC__))
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      template <>
							 | 
						||
| 
								 | 
							
								      struct gcd_traits<unsigned> : public gcd_traits_defaults<unsigned>
							 | 
						||
| 
								 | 
							
								      {
							 | 
						||
| 
								 | 
							
								         BOOST_FORCEINLINE static unsigned find_lsb(unsigned mask)
							 | 
						||
| 
								 | 
							
								         {
							 | 
						||
| 
								 | 
							
								            return __builtin_ctz(mask);
							 | 
						||
| 
								 | 
							
								         }
							 | 
						||
| 
								 | 
							
								         BOOST_FORCEINLINE static unsigned make_odd(unsigned& val)
							 | 
						||
| 
								 | 
							
								         {
							 | 
						||
| 
								 | 
							
								            unsigned result = find_lsb(val);
							 | 
						||
| 
								 | 
							
								            val >>= result;
							 | 
						||
| 
								 | 
							
								            return result;
							 | 
						||
| 
								 | 
							
								         }
							 | 
						||
| 
								 | 
							
								      };
							 | 
						||
| 
								 | 
							
								      template <>
							 | 
						||
| 
								 | 
							
								      struct gcd_traits<unsigned long> : public gcd_traits_defaults<unsigned long>
							 | 
						||
| 
								 | 
							
								      {
							 | 
						||
| 
								 | 
							
								         BOOST_FORCEINLINE static unsigned find_lsb(unsigned long mask)
							 | 
						||
| 
								 | 
							
								         {
							 | 
						||
| 
								 | 
							
								            return __builtin_ctzl(mask);
							 | 
						||
| 
								 | 
							
								         }
							 | 
						||
| 
								 | 
							
								         BOOST_FORCEINLINE static unsigned make_odd(unsigned long& val)
							 | 
						||
| 
								 | 
							
								         {
							 | 
						||
| 
								 | 
							
								            unsigned result = find_lsb(val);
							 | 
						||
| 
								 | 
							
								            val >>= result;
							 | 
						||
| 
								 | 
							
								            return result;
							 | 
						||
| 
								 | 
							
								         }
							 | 
						||
| 
								 | 
							
								      };
							 | 
						||
| 
								 | 
							
								      template <>
							 | 
						||
| 
								 | 
							
								      struct gcd_traits<boost::ulong_long_type> : public gcd_traits_defaults<boost::ulong_long_type>
							 | 
						||
| 
								 | 
							
								      {
							 | 
						||
| 
								 | 
							
								         BOOST_FORCEINLINE static unsigned find_lsb(boost::ulong_long_type mask)
							 | 
						||
| 
								 | 
							
								         {
							 | 
						||
| 
								 | 
							
								            return __builtin_ctzll(mask);
							 | 
						||
| 
								 | 
							
								         }
							 | 
						||
| 
								 | 
							
								         BOOST_FORCEINLINE static unsigned make_odd(boost::ulong_long_type& val)
							 | 
						||
| 
								 | 
							
								         {
							 | 
						||
| 
								 | 
							
								            unsigned result = find_lsb(val);
							 | 
						||
| 
								 | 
							
								            val >>= result;
							 | 
						||
| 
								 | 
							
								            return result;
							 | 
						||
| 
								 | 
							
								         }
							 | 
						||
| 
								 | 
							
								      };
							 | 
						||
| 
								 | 
							
								      //
							 | 
						||
| 
								 | 
							
								      // Other integer type are trivial adaptations of the above,
							 | 
						||
| 
								 | 
							
								      // this works for signed types too, as by the time these functions
							 | 
						||
| 
								 | 
							
								      // are called, all values are > 0.
							 | 
						||
| 
								 | 
							
								      //
							 | 
						||
| 
								 | 
							
								      template <> struct gcd_traits<boost::long_long_type> : public gcd_traits_defaults<boost::long_long_type>
							 | 
						||
| 
								 | 
							
								      {
							 | 
						||
| 
								 | 
							
								         BOOST_FORCEINLINE static unsigned make_odd(boost::long_long_type& val) { unsigned result = gcd_traits<boost::ulong_long_type>::find_lsb(val); val >>= result; return result; }
							 | 
						||
| 
								 | 
							
								      };
							 | 
						||
| 
								 | 
							
								      template <> struct gcd_traits<long> : public gcd_traits_defaults<long>
							 | 
						||
| 
								 | 
							
								      {
							 | 
						||
| 
								 | 
							
								         BOOST_FORCEINLINE static unsigned make_odd(long& val) { unsigned result = gcd_traits<unsigned long>::find_lsb(val); val >>= result; return result; }
							 | 
						||
| 
								 | 
							
								      };
							 | 
						||
| 
								 | 
							
								      template <> struct gcd_traits<int> : public gcd_traits_defaults<int>
							 | 
						||
| 
								 | 
							
								      {
							 | 
						||
| 
								 | 
							
								         BOOST_FORCEINLINE static unsigned make_odd(int& val) { unsigned result = gcd_traits<unsigned long>::find_lsb(val); val >>= result; return result; }
							 | 
						||
| 
								 | 
							
								      };
							 | 
						||
| 
								 | 
							
								      template <> struct gcd_traits<unsigned short> : public gcd_traits_defaults<unsigned short>
							 | 
						||
| 
								 | 
							
								      {
							 | 
						||
| 
								 | 
							
								         BOOST_FORCEINLINE static unsigned make_odd(unsigned short& val) { unsigned result = gcd_traits<unsigned>::find_lsb(val); val >>= result; return result; }
							 | 
						||
| 
								 | 
							
								      };
							 | 
						||
| 
								 | 
							
								      template <> struct gcd_traits<short> : public gcd_traits_defaults<short>
							 | 
						||
| 
								 | 
							
								      {
							 | 
						||
| 
								 | 
							
								         BOOST_FORCEINLINE static unsigned make_odd(short& val) { unsigned result = gcd_traits<unsigned>::find_lsb(val); val >>= result; return result; }
							 | 
						||
| 
								 | 
							
								      };
							 | 
						||
| 
								 | 
							
								      template <> struct gcd_traits<unsigned char> : public gcd_traits_defaults<unsigned char>
							 | 
						||
| 
								 | 
							
								      {
							 | 
						||
| 
								 | 
							
								         BOOST_FORCEINLINE static unsigned make_odd(unsigned char& val) { unsigned result = gcd_traits<unsigned>::find_lsb(val); val >>= result; return result; }
							 | 
						||
| 
								 | 
							
								      };
							 | 
						||
| 
								 | 
							
								      template <> struct gcd_traits<signed char> : public gcd_traits_defaults<signed char>
							 | 
						||
| 
								 | 
							
								      {
							 | 
						||
| 
								 | 
							
								         BOOST_FORCEINLINE static signed make_odd(signed char& val) { signed result = gcd_traits<unsigned>::find_lsb(val); val >>= result; return result; }
							 | 
						||
| 
								 | 
							
								      };
							 | 
						||
| 
								 | 
							
								      template <> struct gcd_traits<char> : public gcd_traits_defaults<char>
							 | 
						||
| 
								 | 
							
								      {
							 | 
						||
| 
								 | 
							
								         BOOST_FORCEINLINE static unsigned make_odd(char& val) { unsigned result = gcd_traits<unsigned>::find_lsb(val); val >>= result; return result; }
							 | 
						||
| 
								 | 
							
								      };
							 | 
						||
| 
								 | 
							
								      template <> struct gcd_traits<wchar_t> : public gcd_traits_defaults<wchar_t>
							 | 
						||
| 
								 | 
							
								      {
							 | 
						||
| 
								 | 
							
								         BOOST_FORCEINLINE static unsigned make_odd(wchar_t& val) { unsigned result = gcd_traits<unsigned>::find_lsb(val); val >>= result; return result; }
							 | 
						||
| 
								 | 
							
								      };
							 | 
						||
| 
								 | 
							
								#endif
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								namespace detail
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    
							 | 
						||
| 
								 | 
							
								   //
							 | 
						||
| 
								 | 
							
								   // The Mixed Binary Euclid Algorithm
							 | 
						||
| 
								 | 
							
								   // Sidi Mohamed Sedjelmaci
							 | 
						||
| 
								 | 
							
								   // Electronic Notes in Discrete Mathematics 35 (2009) 169-176
							 | 
						||
| 
								 | 
							
								   //
							 | 
						||
| 
								 | 
							
								   template <class T>
							 | 
						||
| 
								 | 
							
								   T mixed_binary_gcd(T u, T v)
							 | 
						||
| 
								 | 
							
								   {
							 | 
						||
| 
								 | 
							
								      using std::swap;
							 | 
						||
| 
								 | 
							
								      if(gcd_traits<T>::less(u, v))
							 | 
						||
| 
								 | 
							
								         swap(u, v);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      unsigned shifts = 0;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      if(!u)
							 | 
						||
| 
								 | 
							
								         return v;
							 | 
						||
| 
								 | 
							
								      if(!v)
							 | 
						||
| 
								 | 
							
								         return u;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      shifts = (std::min)(gcd_traits<T>::make_odd(u), gcd_traits<T>::make_odd(v));
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      while(gcd_traits<T>::less(1, v))
							 | 
						||
| 
								 | 
							
								      {
							 | 
						||
| 
								 | 
							
								         u %= v;
							 | 
						||
| 
								 | 
							
								         v -= u;
							 | 
						||
| 
								 | 
							
								         if(!u)
							 | 
						||
| 
								 | 
							
								            return v << shifts;
							 | 
						||
| 
								 | 
							
								         if(!v)
							 | 
						||
| 
								 | 
							
								            return u << shifts;
							 | 
						||
| 
								 | 
							
								         gcd_traits<T>::make_odd(u);
							 | 
						||
| 
								 | 
							
								         gcd_traits<T>::make_odd(v);
							 | 
						||
| 
								 | 
							
								         if(gcd_traits<T>::less(u, v))
							 | 
						||
| 
								 | 
							
								            swap(u, v);
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								      return (v == 1 ? v : u) << shifts;
							 | 
						||
| 
								 | 
							
								   }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    /** Stein gcd (aka 'binary gcd')
							 | 
						||
| 
								 | 
							
								     * 
							 | 
						||
| 
								 | 
							
								     * From Mathematics to Generic Programming, Alexander Stepanov, Daniel Rose
							 | 
						||
| 
								 | 
							
								     */
							 | 
						||
| 
								 | 
							
								    template <typename SteinDomain>
							 | 
						||
| 
								 | 
							
								    SteinDomain Stein_gcd(SteinDomain m, SteinDomain n)
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								        using std::swap;
							 | 
						||
| 
								 | 
							
								        BOOST_ASSERT(m >= 0);
							 | 
						||
| 
								 | 
							
								        BOOST_ASSERT(n >= 0);
							 | 
						||
| 
								 | 
							
								        if (m == SteinDomain(0))
							 | 
						||
| 
								 | 
							
								            return n;
							 | 
						||
| 
								 | 
							
								        if (n == SteinDomain(0))
							 | 
						||
| 
								 | 
							
								            return m;
							 | 
						||
| 
								 | 
							
								        // m > 0 && n > 0
							 | 
						||
| 
								 | 
							
								        int d_m = gcd_traits<SteinDomain>::make_odd(m);
							 | 
						||
| 
								 | 
							
								        int d_n = gcd_traits<SteinDomain>::make_odd(n);
							 | 
						||
| 
								 | 
							
								        // odd(m) && odd(n)
							 | 
						||
| 
								 | 
							
								        while (m != n)
							 | 
						||
| 
								 | 
							
								        {
							 | 
						||
| 
								 | 
							
								            if (n > m)
							 | 
						||
| 
								 | 
							
								                swap(n, m);
							 | 
						||
| 
								 | 
							
								            m -= n;
							 | 
						||
| 
								 | 
							
								            gcd_traits<SteinDomain>::make_odd(m);
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								        // m == n
							 | 
						||
| 
								 | 
							
								        m <<= (std::min)(d_m, d_n);
							 | 
						||
| 
								 | 
							
								        return m;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    
							 | 
						||
| 
								 | 
							
								    /** Euclidean algorithm
							 | 
						||
| 
								 | 
							
								     * 
							 | 
						||
| 
								 | 
							
								     * From Mathematics to Generic Programming, Alexander Stepanov, Daniel Rose
							 | 
						||
| 
								 | 
							
								     * 
							 | 
						||
| 
								 | 
							
								     */
							 | 
						||
| 
								 | 
							
								    template <typename EuclideanDomain>
							 | 
						||
| 
								 | 
							
								    inline EuclideanDomain Euclid_gcd(EuclideanDomain a, EuclideanDomain b)
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								        using std::swap;
							 | 
						||
| 
								 | 
							
								        while (b != EuclideanDomain(0))
							 | 
						||
| 
								 | 
							
								        {
							 | 
						||
| 
								 | 
							
								            a %= b;
							 | 
						||
| 
								 | 
							
								            swap(a, b);
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								        return a;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    template <typename T>
							 | 
						||
| 
								 | 
							
								    inline BOOST_DEDUCED_TYPENAME enable_if_c<gcd_traits<T>::method == gcd_traits<T>::method_mixed, T>::type
							 | 
						||
| 
								 | 
							
								       optimal_gcd_select(T const &a, T const &b)
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								       return detail::mixed_binary_gcd(a, b);
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    template <typename T>
							 | 
						||
| 
								 | 
							
								    inline BOOST_DEDUCED_TYPENAME enable_if_c<gcd_traits<T>::method == gcd_traits<T>::method_binary, T>::type
							 | 
						||
| 
								 | 
							
								       optimal_gcd_select(T const &a, T const &b)
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								       return detail::Stein_gcd(a, b);
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    template <typename T>
							 | 
						||
| 
								 | 
							
								    inline BOOST_DEDUCED_TYPENAME enable_if_c<gcd_traits<T>::method == gcd_traits<T>::method_euclid, T>::type
							 | 
						||
| 
								 | 
							
								       optimal_gcd_select(T const &a, T const &b)
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								       return detail::Euclid_gcd(a, b);
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    template <class T>
							 | 
						||
| 
								 | 
							
								    inline T lcm_imp(const T& a, const T& b)
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								       T temp = boost::math::detail::optimal_gcd_select(a, b);
							 | 
						||
| 
								 | 
							
								#if BOOST_WORKAROUND(BOOST_GCC_VERSION, < 40500)
							 | 
						||
| 
								 | 
							
								       return (temp != T(0)) ? T(a / temp * b) : T(0);
							 | 
						||
| 
								 | 
							
								#else
							 | 
						||
| 
								 | 
							
								       return temp ? T(a / temp * b) : T(0);
							 | 
						||
| 
								 | 
							
								#endif
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								} // namespace detail
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								template <typename Integer>
							 | 
						||
| 
								 | 
							
								inline Integer gcd(Integer const &a, Integer const &b)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    return detail::optimal_gcd_select(static_cast<Integer>(gcd_traits<Integer>::abs(a)), static_cast<Integer>(gcd_traits<Integer>::abs(b)));
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								template <typename Integer>
							 | 
						||
| 
								 | 
							
								inline Integer lcm(Integer const &a, Integer const &b)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								   return detail::lcm_imp(static_cast<Integer>(gcd_traits<Integer>::abs(a)), static_cast<Integer>(gcd_traits<Integer>::abs(b)));
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/**
							 | 
						||
| 
								 | 
							
								 * Knuth, The Art of Computer Programming: Volume 2, Third edition, 1998
							 | 
						||
| 
								 | 
							
								 * Chapter 4.5.2, Algorithm C: Greatest common divisor of n integers.
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * Knuth counts down from n to zero but we naturally go from first to last.
							 | 
						||
| 
								 | 
							
								 * We also return the termination position because it might be useful to know.
							 | 
						||
| 
								 | 
							
								 * 
							 | 
						||
| 
								 | 
							
								 * Partly by quirk, partly by design, this algorithm is defined for n = 1, 
							 | 
						||
| 
								 | 
							
								 * because the gcd of {x} is x. It is not defined for n = 0.
							 | 
						||
| 
								 | 
							
								 * 
							 | 
						||
| 
								 | 
							
								 * @tparam  I   Input iterator.
							 | 
						||
| 
								 | 
							
								 * @return  The gcd of the range and the iterator position at termination.
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								template <typename I>
							 | 
						||
| 
								 | 
							
								std::pair<typename std::iterator_traits<I>::value_type, I>
							 | 
						||
| 
								 | 
							
								gcd_range(I first, I last)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    BOOST_ASSERT(first != last);
							 | 
						||
| 
								 | 
							
								    typedef typename std::iterator_traits<I>::value_type T;
							 | 
						||
| 
								 | 
							
								    
							 | 
						||
| 
								 | 
							
								    T d = *first++;
							 | 
						||
| 
								 | 
							
								    while (d != T(1) && first != last)
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								        d = gcd(d, *first);
							 | 
						||
| 
								 | 
							
								        first++;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								    return std::make_pair(d, first);
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								}  // namespace math
							 | 
						||
| 
								 | 
							
								}  // namespace boost
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#ifdef BOOST_MSVC
							 | 
						||
| 
								 | 
							
								#pragma warning(pop)
							 | 
						||
| 
								 | 
							
								#endif
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#endif  // BOOST_MATH_COMMON_FACTOR_RT_HPP
							 |