File indexing completed on 2025-01-18 09:38:23
0001
0002
0003
0004
0005
0006
0007 #ifndef BOOST_INTEGER_COMMON_FACTOR_RT_HPP
0008 #define BOOST_INTEGER_COMMON_FACTOR_RT_HPP
0009
0010 #include <boost/assert.hpp>
0011 #include <boost/core/enable_if.hpp>
0012
0013 #include <boost/config.hpp> // for BOOST_NESTED_TEMPLATE, etc.
0014 #include <boost/limits.hpp> // for std::numeric_limits
0015 #include <climits> // for CHAR_MIN
0016 #include <boost/detail/workaround.hpp>
0017 #include <iterator>
0018 #include <algorithm>
0019 #include <limits>
0020 #ifndef BOOST_NO_CXX11_HDR_TYPE_TRAITS
0021 #include <type_traits>
0022 #endif
0023 #ifdef BOOST_NO_CXX11_HDR_FUNCTIONAL
0024 #include <functional>
0025 #endif
0026
0027 #if ((defined(BOOST_MSVC) && (BOOST_MSVC >= 1600)) || (defined(__clang__) && defined(__c2__)) || (defined(BOOST_INTEL) && defined(_MSC_VER))) && (defined(_M_IX86) || defined(_M_X64))
0028 #include <intrin.h>
0029 #endif
0030
0031 #ifdef BOOST_MSVC
0032 #pragma warning(push)
0033 #pragma warning(disable:4127 4244)
0034 #endif
0035
0036 #if !defined(BOOST_NO_CXX11_HDR_TYPE_TRAITS) && !defined(BOOST_NO_CXX11_NOEXCEPT)
0037 #define BOOST_GCD_NOEXCEPT(T) noexcept(std::is_arithmetic<T>::value)
0038 #else
0039 #define BOOST_GCD_NOEXCEPT(T)
0040 #endif
0041
0042 namespace boost {
0043
0044 template <class I>
0045 class rational;
0046
0047 namespace integer {
0048
0049 namespace gcd_detail{
0050
0051
0052
0053
0054 #ifndef BOOST_NO_CXX14_CONSTEXPR
0055 template <class T>
0056 inline constexpr T constexpr_min(T const& a, T const& b) BOOST_GCD_NOEXCEPT(T)
0057 {
0058 return a < b ? a : b;
0059 }
0060 template <class T>
0061 inline constexpr auto constexpr_swap(T&a, T& b) BOOST_GCD_NOEXCEPT(T) -> decltype(a.swap(b))
0062 {
0063 return a.swap(b);
0064 }
0065 template <class T, class U>
0066 inline constexpr void constexpr_swap(T&a, U& b...) BOOST_GCD_NOEXCEPT(T)
0067 {
0068 T t(static_cast<T&&>(a));
0069 a = static_cast<T&&>(b);
0070 b = static_cast<T&&>(t);
0071 }
0072 #else
0073 template <class T>
0074 inline T constexpr_min(T const& a, T const& b) BOOST_GCD_NOEXCEPT(T)
0075 {
0076 return a < b ? a : b;
0077 }
0078 template <class T>
0079 inline void constexpr_swap(T&a, T& b) BOOST_GCD_NOEXCEPT(T)
0080 {
0081 using std::swap;
0082 swap(a, b);
0083 }
0084 #endif
0085
0086 template <class T, bool a =
0087 #ifndef BOOST_NO_CXX11_HDR_TYPE_TRAITS
0088 std::is_unsigned<T>::value ||
0089 #endif
0090 (std::numeric_limits<T>::is_specialized && !std::numeric_limits<T>::is_signed)>
0091 struct gcd_traits_abs_defaults
0092 {
0093 inline static BOOST_CXX14_CONSTEXPR const T& abs(const T& val) BOOST_GCD_NOEXCEPT(T) { return val; }
0094 };
0095 template <class T>
0096 struct gcd_traits_abs_defaults<T, false>
0097 {
0098 inline static T BOOST_CXX14_CONSTEXPR abs(const T& val) BOOST_GCD_NOEXCEPT(T)
0099 {
0100
0101 return val < T(0) ? -val : val;
0102 }
0103 };
0104
0105 enum method_type
0106 {
0107 method_euclid = 0,
0108 method_binary = 1,
0109 method_mixed = 2
0110 };
0111
0112 struct any_convert
0113 {
0114 template <class T>
0115 any_convert(const T&);
0116 };
0117
0118 struct unlikely_size
0119 {
0120 char buf[9973];
0121 };
0122
0123 unlikely_size operator <<= (any_convert, any_convert);
0124 unlikely_size operator >>= (any_convert, any_convert);
0125
0126 template <class T>
0127 struct gcd_traits_defaults : public gcd_traits_abs_defaults<T>
0128 {
0129 BOOST_FORCEINLINE static BOOST_CXX14_CONSTEXPR unsigned make_odd(T& val) BOOST_GCD_NOEXCEPT(T)
0130 {
0131 unsigned r = 0;
0132 while (T(0) == (val & 1u))
0133 {
0134 #ifdef _MSC_VER
0135 val = val >> 1;
0136 #else
0137 val >>= 1;
0138 #endif
0139 ++r;
0140 }
0141 return r;
0142 }
0143 inline static BOOST_CXX14_CONSTEXPR bool less(const T& a, const T& b) BOOST_GCD_NOEXCEPT(T)
0144 {
0145 return a < b;
0146 }
0147
0148 static T& get_value();
0149
0150 #ifndef BOOST_NO_SFINAE
0151 static const bool has_operator_left_shift_equal = sizeof(get_value() <<= 2) != sizeof(unlikely_size);
0152 static const bool has_operator_right_shift_equal = sizeof(get_value() >>= 2) != sizeof(unlikely_size);
0153 #else
0154 static const bool has_operator_left_shift_equal = true;
0155 static const bool has_operator_right_shift_equal = true;
0156 #endif
0157 static const method_type method = std::numeric_limits<T>::is_specialized && std::numeric_limits<T>::is_integer && has_operator_left_shift_equal && has_operator_right_shift_equal ? method_mixed : method_euclid;
0158 };
0159
0160
0161
0162 template <class T>
0163 struct gcd_traits : public gcd_traits_defaults<T> {};
0164
0165
0166
0167
0168
0169
0170 #if defined(BOOST_NO_CXX14_CONSTEXPR) && ((defined(BOOST_MSVC) && (BOOST_MSVC >= 1600)) || (defined(__clang__) && defined(__c2__)) || (defined(BOOST_INTEL) && defined(_MSC_VER))) && (defined(_M_IX86) || defined(_M_X64))
0171 #pragma intrinsic(_BitScanForward,)
0172 template <>
0173 struct gcd_traits<unsigned long> : public gcd_traits_defaults<unsigned long>
0174 {
0175 BOOST_FORCEINLINE static unsigned find_lsb(unsigned long val) BOOST_NOEXCEPT
0176 {
0177 unsigned long result;
0178 _BitScanForward(&result, val);
0179 return result;
0180 }
0181 BOOST_FORCEINLINE static unsigned make_odd(unsigned long& val) BOOST_NOEXCEPT
0182 {
0183 unsigned result = find_lsb(val);
0184 val >>= result;
0185 return result;
0186 }
0187 };
0188
0189 #ifdef _M_X64
0190 #pragma intrinsic(_BitScanForward64)
0191 template <>
0192 struct gcd_traits<unsigned __int64> : public gcd_traits_defaults<unsigned __int64>
0193 {
0194 BOOST_FORCEINLINE static unsigned find_lsb(unsigned __int64 mask) BOOST_NOEXCEPT
0195 {
0196 unsigned long result;
0197 _BitScanForward64(&result, mask);
0198 return result;
0199 }
0200 BOOST_FORCEINLINE static unsigned make_odd(unsigned __int64& val) BOOST_NOEXCEPT
0201 {
0202 unsigned result = find_lsb(val);
0203 val >>= result;
0204 return result;
0205 }
0206 };
0207 #endif
0208
0209
0210
0211
0212
0213 template <> struct gcd_traits<long> : public gcd_traits_defaults<long>
0214 { BOOST_FORCEINLINE static unsigned make_odd(long& val)BOOST_NOEXCEPT{ unsigned result = gcd_traits<unsigned long>::find_lsb(val); val >>= result; return result; } };
0215 template <> struct gcd_traits<unsigned int> : public gcd_traits_defaults<unsigned int>
0216 { BOOST_FORCEINLINE static unsigned make_odd(unsigned int& val)BOOST_NOEXCEPT{ unsigned result = gcd_traits<unsigned long>::find_lsb(val); val >>= result; return result; } };
0217 template <> struct gcd_traits<int> : public gcd_traits_defaults<int>
0218 { BOOST_FORCEINLINE static unsigned make_odd(int& val)BOOST_NOEXCEPT{ unsigned result = gcd_traits<unsigned long>::find_lsb(val); val >>= result; return result; } };
0219 template <> struct gcd_traits<unsigned short> : public gcd_traits_defaults<unsigned short>
0220 { BOOST_FORCEINLINE static unsigned make_odd(unsigned short& val)BOOST_NOEXCEPT{ unsigned result = gcd_traits<unsigned long>::find_lsb(val); val >>= result; return result; } };
0221 template <> struct gcd_traits<short> : public gcd_traits_defaults<short>
0222 { BOOST_FORCEINLINE static unsigned make_odd(short& val)BOOST_NOEXCEPT{ unsigned result = gcd_traits<unsigned long>::find_lsb(val); val >>= result; return result; } };
0223 template <> struct gcd_traits<unsigned char> : public gcd_traits_defaults<unsigned char>
0224 { BOOST_FORCEINLINE static unsigned make_odd(unsigned char& val)BOOST_NOEXCEPT{ unsigned result = gcd_traits<unsigned long>::find_lsb(val); val >>= result; return result; } };
0225 template <> struct gcd_traits<signed char> : public gcd_traits_defaults<signed char>
0226 { BOOST_FORCEINLINE static unsigned make_odd(signed char& val)BOOST_NOEXCEPT{ unsigned result = gcd_traits<unsigned long>::find_lsb(val); val >>= result; return result; } };
0227 template <> struct gcd_traits<char> : public gcd_traits_defaults<char>
0228 { BOOST_FORCEINLINE static unsigned make_odd(char& val)BOOST_NOEXCEPT{ unsigned result = gcd_traits<unsigned long>::find_lsb(val); val >>= result; return result; } };
0229 #ifndef BOOST_NO_INTRINSIC_WCHAR_T
0230 template <> struct gcd_traits<wchar_t> : public gcd_traits_defaults<wchar_t>
0231 { BOOST_FORCEINLINE static unsigned make_odd(wchar_t& val)BOOST_NOEXCEPT{ unsigned result = gcd_traits<unsigned long>::find_lsb(val); val >>= result; return result; } };
0232 #endif
0233 #ifdef _M_X64
0234 template <> struct gcd_traits<__int64> : public gcd_traits_defaults<__int64>
0235 { BOOST_FORCEINLINE static unsigned make_odd(__int64& val)BOOST_NOEXCEPT{ unsigned result = gcd_traits<unsigned __int64>::find_lsb(val); val >>= result; return result; } };
0236 #endif
0237
0238 #elif defined(BOOST_GCC) || defined(__clang__) || (defined(BOOST_INTEL) && defined(__GNUC__))
0239
0240 template <>
0241 struct gcd_traits<unsigned> : public gcd_traits_defaults<unsigned>
0242 {
0243 BOOST_FORCEINLINE static BOOST_CXX14_CONSTEXPR unsigned find_lsb(unsigned mask)BOOST_NOEXCEPT
0244 {
0245 return __builtin_ctz(mask);
0246 }
0247 BOOST_FORCEINLINE static BOOST_CXX14_CONSTEXPR unsigned make_odd(unsigned& val)BOOST_NOEXCEPT
0248 {
0249 unsigned result = find_lsb(val);
0250 val >>= result;
0251 return result;
0252 }
0253 };
0254 template <>
0255 struct gcd_traits<unsigned long> : public gcd_traits_defaults<unsigned long>
0256 {
0257 BOOST_FORCEINLINE static BOOST_CXX14_CONSTEXPR unsigned find_lsb(unsigned long mask)BOOST_NOEXCEPT
0258 {
0259 return __builtin_ctzl(mask);
0260 }
0261 BOOST_FORCEINLINE static BOOST_CXX14_CONSTEXPR unsigned make_odd(unsigned long& val)BOOST_NOEXCEPT
0262 {
0263 unsigned result = find_lsb(val);
0264 val >>= result;
0265 return result;
0266 }
0267 };
0268 template <>
0269 struct gcd_traits<boost::ulong_long_type> : public gcd_traits_defaults<boost::ulong_long_type>
0270 {
0271 BOOST_FORCEINLINE static BOOST_CXX14_CONSTEXPR unsigned find_lsb(boost::ulong_long_type mask)BOOST_NOEXCEPT
0272 {
0273 return __builtin_ctzll(mask);
0274 }
0275 BOOST_FORCEINLINE static BOOST_CXX14_CONSTEXPR unsigned make_odd(boost::ulong_long_type& val)BOOST_NOEXCEPT
0276 {
0277 unsigned result = find_lsb(val);
0278 val >>= result;
0279 return result;
0280 }
0281 };
0282
0283
0284
0285
0286
0287 template <> struct gcd_traits<boost::long_long_type> : public gcd_traits_defaults<boost::long_long_type>
0288 {
0289 BOOST_FORCEINLINE static BOOST_CXX14_CONSTEXPR unsigned make_odd(boost::long_long_type& val)BOOST_NOEXCEPT { unsigned result = gcd_traits<boost::ulong_long_type>::find_lsb(val); val >>= result; return result; }
0290 };
0291 template <> struct gcd_traits<long> : public gcd_traits_defaults<long>
0292 {
0293 BOOST_FORCEINLINE static BOOST_CXX14_CONSTEXPR unsigned make_odd(long& val)BOOST_NOEXCEPT { unsigned result = gcd_traits<unsigned long>::find_lsb(val); val >>= result; return result; }
0294 };
0295 template <> struct gcd_traits<int> : public gcd_traits_defaults<int>
0296 {
0297 BOOST_FORCEINLINE static BOOST_CXX14_CONSTEXPR unsigned make_odd(int& val)BOOST_NOEXCEPT { unsigned result = gcd_traits<unsigned long>::find_lsb(val); val >>= result; return result; }
0298 };
0299 template <> struct gcd_traits<unsigned short> : public gcd_traits_defaults<unsigned short>
0300 {
0301 BOOST_FORCEINLINE static BOOST_CXX14_CONSTEXPR unsigned make_odd(unsigned short& val)BOOST_NOEXCEPT { unsigned result = gcd_traits<unsigned>::find_lsb(val); val >>= result; return result; }
0302 };
0303 template <> struct gcd_traits<short> : public gcd_traits_defaults<short>
0304 {
0305 BOOST_FORCEINLINE static BOOST_CXX14_CONSTEXPR unsigned make_odd(short& val)BOOST_NOEXCEPT { unsigned result = gcd_traits<unsigned>::find_lsb(val); val >>= result; return result; }
0306 };
0307 template <> struct gcd_traits<unsigned char> : public gcd_traits_defaults<unsigned char>
0308 {
0309 BOOST_FORCEINLINE static BOOST_CXX14_CONSTEXPR unsigned make_odd(unsigned char& val)BOOST_NOEXCEPT { unsigned result = gcd_traits<unsigned>::find_lsb(val); val >>= result; return result; }
0310 };
0311 template <> struct gcd_traits<signed char> : public gcd_traits_defaults<signed char>
0312 {
0313 BOOST_FORCEINLINE static BOOST_CXX14_CONSTEXPR unsigned make_odd(signed char& val)BOOST_NOEXCEPT { unsigned result = gcd_traits<unsigned>::find_lsb(val); val >>= result; return result; }
0314 };
0315 template <> struct gcd_traits<char> : public gcd_traits_defaults<char>
0316 {
0317 BOOST_FORCEINLINE static BOOST_CXX14_CONSTEXPR unsigned make_odd(char& val)BOOST_NOEXCEPT { unsigned result = gcd_traits<unsigned>::find_lsb(val); val >>= result; return result; }
0318 };
0319 #ifndef BOOST_NO_INTRINSIC_WCHAR_T
0320 template <> struct gcd_traits<wchar_t> : public gcd_traits_defaults<wchar_t>
0321 {
0322 BOOST_FORCEINLINE static BOOST_CXX14_CONSTEXPR unsigned make_odd(wchar_t& val)BOOST_NOEXCEPT { unsigned result = gcd_traits<unsigned>::find_lsb(val); val >>= result; return result; }
0323 };
0324 #endif
0325 #endif
0326
0327
0328
0329
0330
0331 template <class T>
0332 BOOST_CXX14_CONSTEXPR T mixed_binary_gcd(T u, T v) BOOST_GCD_NOEXCEPT(T)
0333 {
0334 if(gcd_traits<T>::less(u, v))
0335 constexpr_swap(u, v);
0336
0337 unsigned shifts = 0;
0338
0339 if(u == T(0))
0340 return v;
0341 if(v == T(0))
0342 return u;
0343
0344 shifts = constexpr_min(gcd_traits<T>::make_odd(u), gcd_traits<T>::make_odd(v));
0345
0346 while(gcd_traits<T>::less(1, v))
0347 {
0348 u %= v;
0349 v -= u;
0350 if(u == T(0))
0351 return v << shifts;
0352 if(v == T(0))
0353 return u << shifts;
0354 gcd_traits<T>::make_odd(u);
0355 gcd_traits<T>::make_odd(v);
0356 if(gcd_traits<T>::less(u, v))
0357 constexpr_swap(u, v);
0358 }
0359 return (v == 1 ? v : u) << shifts;
0360 }
0361
0362
0363
0364
0365
0366 template <typename SteinDomain>
0367 BOOST_CXX14_CONSTEXPR SteinDomain Stein_gcd(SteinDomain m, SteinDomain n) BOOST_GCD_NOEXCEPT(SteinDomain)
0368 {
0369 BOOST_ASSERT(m >= 0);
0370 BOOST_ASSERT(n >= 0);
0371 if (m == SteinDomain(0))
0372 return n;
0373 if (n == SteinDomain(0))
0374 return m;
0375
0376 unsigned d_m = gcd_traits<SteinDomain>::make_odd(m);
0377 unsigned d_n = gcd_traits<SteinDomain>::make_odd(n);
0378
0379 while (m != n)
0380 {
0381 if (n > m)
0382 constexpr_swap(n, m);
0383 m -= n;
0384 gcd_traits<SteinDomain>::make_odd(m);
0385 }
0386
0387 m <<= constexpr_min(d_m, d_n);
0388 return m;
0389 }
0390
0391
0392
0393
0394
0395
0396
0397 template <typename EuclideanDomain>
0398 inline BOOST_CXX14_CONSTEXPR EuclideanDomain Euclid_gcd(EuclideanDomain a, EuclideanDomain b) BOOST_GCD_NOEXCEPT(EuclideanDomain)
0399 {
0400 while (b != EuclideanDomain(0))
0401 {
0402 a %= b;
0403 constexpr_swap(a, b);
0404 }
0405 return a;
0406 }
0407
0408
0409 template <typename T>
0410 inline BOOST_CXX14_CONSTEXPR BOOST_DEDUCED_TYPENAME enable_if_c<gcd_traits<T>::method == method_mixed, T>::type
0411 optimal_gcd_select(T const &a, T const &b) BOOST_GCD_NOEXCEPT(T)
0412 {
0413 return gcd_detail::mixed_binary_gcd(a, b);
0414 }
0415
0416 template <typename T>
0417 inline BOOST_CXX14_CONSTEXPR BOOST_DEDUCED_TYPENAME enable_if_c<gcd_traits<T>::method == method_binary, T>::type
0418 optimal_gcd_select(T const &a, T const &b) BOOST_GCD_NOEXCEPT(T)
0419 {
0420 return gcd_detail::Stein_gcd(a, b);
0421 }
0422
0423 template <typename T>
0424 inline BOOST_CXX14_CONSTEXPR BOOST_DEDUCED_TYPENAME enable_if_c<gcd_traits<T>::method == method_euclid, T>::type
0425 optimal_gcd_select(T const &a, T const &b) BOOST_GCD_NOEXCEPT(T)
0426 {
0427 return gcd_detail::Euclid_gcd(a, b);
0428 }
0429
0430 template <class T>
0431 inline BOOST_CXX14_CONSTEXPR T lcm_imp(const T& a, const T& b) BOOST_GCD_NOEXCEPT(T)
0432 {
0433 T temp = boost::integer::gcd_detail::optimal_gcd_select(a, b);
0434 #if BOOST_WORKAROUND(BOOST_GCC_VERSION, < 40500)
0435 return (temp != T(0)) ? T(a / temp * b) : T(0);
0436 #else
0437 return temp != T(0) ? T(a / temp * b) : T(0);
0438 #endif
0439 }
0440
0441 }
0442
0443
0444 template <typename Integer>
0445 inline BOOST_CXX14_CONSTEXPR Integer gcd(Integer const &a, Integer const &b) BOOST_GCD_NOEXCEPT(Integer)
0446 {
0447 if(a == (std::numeric_limits<Integer>::min)())
0448 return a == static_cast<Integer>(0) ? gcd_detail::gcd_traits<Integer>::abs(b) : boost::integer::gcd(static_cast<Integer>(a % b), b);
0449 else if (b == (std::numeric_limits<Integer>::min)())
0450 return b == static_cast<Integer>(0) ? gcd_detail::gcd_traits<Integer>::abs(a) : boost::integer::gcd(a, static_cast<Integer>(b % a));
0451 return gcd_detail::optimal_gcd_select(static_cast<Integer>(gcd_detail::gcd_traits<Integer>::abs(a)), static_cast<Integer>(gcd_detail::gcd_traits<Integer>::abs(b)));
0452 }
0453
0454 template <typename Integer>
0455 inline BOOST_CXX14_CONSTEXPR Integer lcm(Integer const &a, Integer const &b) BOOST_GCD_NOEXCEPT(Integer)
0456 {
0457 return gcd_detail::lcm_imp(static_cast<Integer>(gcd_detail::gcd_traits<Integer>::abs(a)), static_cast<Integer>(gcd_detail::gcd_traits<Integer>::abs(b)));
0458 }
0459 #ifndef BOOST_NO_CXX11_VARIADIC_TEMPLATES
0460
0461
0462
0463
0464 template <typename Integer, typename... Args>
0465 inline BOOST_CXX14_CONSTEXPR Integer gcd(Integer const &a, Integer const &b, const Integer& c, Args const&... args) BOOST_GCD_NOEXCEPT(Integer)
0466 {
0467 Integer t = gcd(b, c, args...);
0468 return t == 1 ? 1 : gcd(a, t);
0469 }
0470
0471 template <typename Integer, typename... Args>
0472 inline BOOST_CXX14_CONSTEXPR Integer lcm(Integer const &a, Integer const &b, Integer const& c, Args const&... args) BOOST_GCD_NOEXCEPT(Integer)
0473 {
0474 return lcm(a, lcm(b, c, args...));
0475 }
0476 #endif
0477
0478
0479
0480 template <typename Integer>
0481 inline typename boost::enable_if_c<std::numeric_limits<Integer>::is_specialized, boost::rational<Integer> >::type gcd(boost::rational<Integer> const &a, boost::rational<Integer> const &b)
0482 {
0483 return boost::rational<Integer>(static_cast<Integer>(gcd(a.numerator(), b.numerator())), static_cast<Integer>(lcm(a.denominator(), b.denominator())));
0484 }
0485
0486 template <typename Integer>
0487 inline typename boost::enable_if_c<std::numeric_limits<Integer>::is_specialized, boost::rational<Integer> >::type lcm(boost::rational<Integer> const &a, boost::rational<Integer> const &b)
0488 {
0489 return boost::rational<Integer>(static_cast<Integer>(lcm(a.numerator(), b.numerator())), static_cast<Integer>(gcd(a.denominator(), b.denominator())));
0490 }
0491
0492
0493
0494
0495
0496
0497
0498
0499
0500
0501
0502
0503
0504 template <typename I>
0505 std::pair<typename std::iterator_traits<I>::value_type, I>
0506 gcd_range(I first, I last) BOOST_GCD_NOEXCEPT(I)
0507 {
0508 BOOST_ASSERT(first != last);
0509 typedef typename std::iterator_traits<I>::value_type T;
0510
0511 T d = *first;
0512 ++first;
0513 while (d != T(1) && first != last)
0514 {
0515 d = gcd(d, *first);
0516 ++first;
0517 }
0518 return std::make_pair(d, first);
0519 }
0520 template <typename I>
0521 std::pair<typename std::iterator_traits<I>::value_type, I>
0522 lcm_range(I first, I last) BOOST_GCD_NOEXCEPT(I)
0523 {
0524 BOOST_ASSERT(first != last);
0525 typedef typename std::iterator_traits<I>::value_type T;
0526
0527 T d = *first;
0528 ++first;
0529 while (d != T(0) && first != last)
0530 {
0531 d = lcm(d, *first);
0532 ++first;
0533 }
0534 return std::make_pair(d, first);
0535 }
0536
0537 template < typename IntegerType >
0538 class gcd_evaluator
0539 #ifdef BOOST_NO_CXX11_HDR_FUNCTIONAL
0540 : public std::binary_function<IntegerType, IntegerType, IntegerType>
0541 #endif
0542 {
0543 public:
0544 #ifndef BOOST_NO_CXX11_HDR_FUNCTIONAL
0545 typedef IntegerType first_argument_type;
0546 typedef IntegerType second_argument_type;
0547 typedef IntegerType result_type;
0548 #endif
0549 IntegerType operator()(IntegerType const &a, IntegerType const &b) const
0550 {
0551 return boost::integer::gcd(a, b);
0552 }
0553 };
0554
0555 template < typename IntegerType >
0556 class lcm_evaluator
0557 #ifdef BOOST_NO_CXX11_HDR_FUNCTIONAL
0558 : public std::binary_function<IntegerType, IntegerType, IntegerType>
0559 #endif
0560 {
0561 public:
0562 #ifndef BOOST_NO_CXX11_HDR_FUNCTIONAL
0563 typedef IntegerType first_argument_type;
0564 typedef IntegerType second_argument_type;
0565 typedef IntegerType result_type;
0566 #endif
0567 IntegerType operator()(IntegerType const &a, IntegerType const &b)const
0568 {
0569 return boost::integer::lcm(a, b);
0570 }
0571 };
0572
0573 }
0574 }
0575
0576 #ifdef BOOST_MSVC
0577 #pragma warning(pop)
0578 #endif
0579
0580 #endif