123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530 |
- // Boost common_factor_rt.hpp header file ----------------------------------//
- // (C) Copyright Daryle Walker and Paul Moore 2001-2002. Permission to copy,
- // use, modify, sell and distribute this software is granted provided this
- // copyright notice appears in all copies. This software is provided "as is"
- // without express or implied warranty, and with no claim as to its suitability
- // for any purpose.
- // boostinspect:nolicense (don't complain about the lack of a Boost license)
- // (Paul Moore hasn't been in contact for years, so there's no way to change the
- // license.)
- // See http://www.boost.org for updates, documentation, and revision history.
- #ifndef BOOST_MATH_COMMON_FACTOR_RT_HPP
- #define BOOST_MATH_COMMON_FACTOR_RT_HPP
- #include <boost/math_fwd.hpp> // self include
- #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>
- #ifdef BOOST_MSVC
- #pragma warning(push)
- #pragma warning(disable:4127 4244) // Conditional expression is constant
- #endif
- namespace boost
- {
- namespace math
- {
- // Forward declarations for function templates -----------------------------//
- template < typename IntegerType >
- IntegerType gcd( IntegerType const &a, IntegerType const &b );
- template < typename IntegerType >
- IntegerType lcm( IntegerType const &a, IntegerType const &b );
- // Greatest common divisor evaluator class declaration ---------------------//
- template < typename IntegerType >
- class gcd_evaluator
- {
- public:
- // Types
- typedef IntegerType result_type, first_argument_type, second_argument_type;
- // Function object interface
- result_type operator ()( first_argument_type const &a,
- second_argument_type const &b ) const;
- }; // boost::math::gcd_evaluator
- // Least common multiple evaluator class declaration -----------------------//
- template < typename IntegerType >
- class lcm_evaluator
- {
- public:
- // Types
- typedef IntegerType result_type, first_argument_type, second_argument_type;
- // Function object interface
- result_type operator ()( first_argument_type const &a,
- second_argument_type const &b ) const;
- }; // boost::math::lcm_evaluator
- // Implementation details --------------------------------------------------//
- namespace detail
- {
- // Greatest common divisor for rings (including unsigned integers)
- template < typename RingType >
- RingType
- gcd_euclidean
- (
- RingType a,
- RingType b
- )
- {
- // Avoid repeated construction
- #ifndef __BORLANDC__
- RingType const zero = static_cast<RingType>( 0 );
- #else
- RingType zero = static_cast<RingType>( 0 );
- #endif
- // Reduce by GCD-remainder property [GCD(a,b) == GCD(b,a MOD b)]
- while ( true )
- {
- if ( a == zero )
- return b;
- b %= a;
- if ( b == zero )
- return a;
- a %= b;
- }
- }
- // Greatest common divisor for (signed) integers
- template < typename IntegerType >
- inline
- IntegerType
- gcd_integer
- (
- IntegerType const & a,
- IntegerType const & b
- )
- {
- // Avoid repeated construction
- IntegerType const zero = static_cast<IntegerType>( 0 );
- IntegerType const result = gcd_euclidean( a, b );
- return ( result < zero ) ? static_cast<IntegerType>(-result) : result;
- }
- // Greatest common divisor for unsigned binary integers
- template < typename BuiltInUnsigned >
- BuiltInUnsigned
- gcd_binary
- (
- BuiltInUnsigned u,
- BuiltInUnsigned v
- )
- {
- if ( u && v )
- {
- // Shift out common factors of 2
- unsigned shifts = 0;
- while ( !(u & 1u) && !(v & 1u) )
- {
- ++shifts;
- u >>= 1;
- v >>= 1;
- }
- // Start with the still-even one, if any
- BuiltInUnsigned r[] = { u, v };
- unsigned which = static_cast<bool>( u & 1u );
- // Whittle down the values via their differences
- do
- {
- #if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x582))
- while ( !(r[ which ] & 1u) )
- {
- r[ which ] = (r[which] >> 1);
- }
- #else
- // Remove factors of two from the even one
- while ( !(r[ which ] & 1u) )
- {
- r[ which ] >>= 1;
- }
- #endif
- // Replace the larger of the two with their difference
- if ( r[!which] > r[which] )
- {
- which ^= 1u;
- }
- r[ which ] -= r[ !which ];
- }
- while ( r[which] );
- // Shift-in the common factor of 2 to the residues' GCD
- return r[ !which ] << shifts;
- }
- else
- {
- // At least one input is zero, return the other
- // (adding since zero is the additive identity)
- // or zero if both are zero.
- return u + v;
- }
- }
- // Least common multiple for rings (including unsigned integers)
- template < typename RingType >
- inline
- RingType
- lcm_euclidean
- (
- RingType const & a,
- RingType const & b
- )
- {
- RingType const zero = static_cast<RingType>( 0 );
- RingType const temp = gcd_euclidean( a, b );
- return ( temp != zero ) ? ( a / temp * b ) : zero;
- }
- // Least common multiple for (signed) integers
- template < typename IntegerType >
- inline
- IntegerType
- lcm_integer
- (
- IntegerType const & a,
- IntegerType const & b
- )
- {
- // Avoid repeated construction
- IntegerType const zero = static_cast<IntegerType>( 0 );
- IntegerType const result = lcm_euclidean( a, b );
- return ( result < zero ) ? static_cast<IntegerType>(-result) : result;
- }
- // Function objects to find the best way of computing GCD or LCM
- #ifndef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS
- #ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
- template < typename T, bool IsSpecialized, bool IsSigned >
- struct gcd_optimal_evaluator_helper_t
- {
- T operator ()( T const &a, T const &b )
- {
- return gcd_euclidean( a, b );
- }
- };
- template < typename T >
- struct gcd_optimal_evaluator_helper_t< T, true, true >
- {
- T operator ()( T const &a, T const &b )
- {
- return gcd_integer( a, b );
- }
- };
- #else
- template < bool IsSpecialized, bool IsSigned >
- struct gcd_optimal_evaluator_helper2_t
- {
- template < typename T >
- struct helper
- {
- T operator ()( T const &a, T const &b )
- {
- return gcd_euclidean( a, b );
- }
- };
- };
- template < >
- struct gcd_optimal_evaluator_helper2_t< true, true >
- {
- template < typename T >
- struct helper
- {
- T operator ()( T const &a, T const &b )
- {
- return gcd_integer( a, b );
- }
- };
- };
- template < typename T, bool IsSpecialized, bool IsSigned >
- struct gcd_optimal_evaluator_helper_t
- : gcd_optimal_evaluator_helper2_t<IsSpecialized, IsSigned>
- ::BOOST_NESTED_TEMPLATE helper<T>
- {
- };
- #endif
- template < typename T >
- struct gcd_optimal_evaluator
- {
- T operator ()( T const &a, T const &b )
- {
- typedef ::std::numeric_limits<T> limits_type;
- typedef gcd_optimal_evaluator_helper_t<T,
- limits_type::is_specialized, limits_type::is_signed> helper_type;
- helper_type solver;
- return solver( a, b );
- }
- };
- #else // BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS
- template < typename T >
- struct gcd_optimal_evaluator
- {
- T operator ()( T const &a, T const &b )
- {
- return gcd_integer( a, b );
- }
- };
- #endif
- // Specialize for the built-in integers
- #define BOOST_PRIVATE_GCD_UF( Ut ) \
- template < > struct gcd_optimal_evaluator<Ut> \
- { Ut operator ()( Ut a, Ut b ) const { return gcd_binary( a, b ); } }
- BOOST_PRIVATE_GCD_UF( unsigned char );
- BOOST_PRIVATE_GCD_UF( unsigned short );
- BOOST_PRIVATE_GCD_UF( unsigned );
- BOOST_PRIVATE_GCD_UF( unsigned long );
- #ifdef BOOST_HAS_LONG_LONG
- BOOST_PRIVATE_GCD_UF( boost::ulong_long_type );
- #elif defined(BOOST_HAS_MS_INT64)
- BOOST_PRIVATE_GCD_UF( unsigned __int64 );
- #endif
- #if CHAR_MIN == 0
- BOOST_PRIVATE_GCD_UF( char ); // char is unsigned
- #endif
- #undef BOOST_PRIVATE_GCD_UF
- #define BOOST_PRIVATE_GCD_SF( St, Ut ) \
- template < > struct gcd_optimal_evaluator<St> \
- { St operator ()( St a, St b ) const { Ut const a_abs = \
- static_cast<Ut>( a < 0 ? -a : +a ), b_abs = static_cast<Ut>( \
- b < 0 ? -b : +b ); return static_cast<St>( \
- gcd_optimal_evaluator<Ut>()(a_abs, b_abs) ); } }
- BOOST_PRIVATE_GCD_SF( signed char, unsigned char );
- BOOST_PRIVATE_GCD_SF( short, unsigned short );
- BOOST_PRIVATE_GCD_SF( int, unsigned );
- BOOST_PRIVATE_GCD_SF( long, unsigned long );
- #if CHAR_MIN < 0
- BOOST_PRIVATE_GCD_SF( char, unsigned char ); // char is signed
- #endif
- #ifdef BOOST_HAS_LONG_LONG
- BOOST_PRIVATE_GCD_SF( boost::long_long_type, boost::ulong_long_type );
- #elif defined(BOOST_HAS_MS_INT64)
- BOOST_PRIVATE_GCD_SF( __int64, unsigned __int64 );
- #endif
- #undef BOOST_PRIVATE_GCD_SF
- #ifndef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS
- #ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
- template < typename T, bool IsSpecialized, bool IsSigned >
- struct lcm_optimal_evaluator_helper_t
- {
- T operator ()( T const &a, T const &b )
- {
- return lcm_euclidean( a, b );
- }
- };
- template < typename T >
- struct lcm_optimal_evaluator_helper_t< T, true, true >
- {
- T operator ()( T const &a, T const &b )
- {
- return lcm_integer( a, b );
- }
- };
- #else
- template < bool IsSpecialized, bool IsSigned >
- struct lcm_optimal_evaluator_helper2_t
- {
- template < typename T >
- struct helper
- {
- T operator ()( T const &a, T const &b )
- {
- return lcm_euclidean( a, b );
- }
- };
- };
- template < >
- struct lcm_optimal_evaluator_helper2_t< true, true >
- {
- template < typename T >
- struct helper
- {
- T operator ()( T const &a, T const &b )
- {
- return lcm_integer( a, b );
- }
- };
- };
- template < typename T, bool IsSpecialized, bool IsSigned >
- struct lcm_optimal_evaluator_helper_t
- : lcm_optimal_evaluator_helper2_t<IsSpecialized, IsSigned>
- ::BOOST_NESTED_TEMPLATE helper<T>
- {
- };
- #endif
- template < typename T >
- struct lcm_optimal_evaluator
- {
- T operator ()( T const &a, T const &b )
- {
- typedef ::std::numeric_limits<T> limits_type;
- typedef lcm_optimal_evaluator_helper_t<T,
- limits_type::is_specialized, limits_type::is_signed> helper_type;
- helper_type solver;
- return solver( a, b );
- }
- };
- #else // BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS
- template < typename T >
- struct lcm_optimal_evaluator
- {
- T operator ()( T const &a, T const &b )
- {
- return lcm_integer( a, b );
- }
- };
- #endif
- // Functions to find the GCD or LCM in the best way
- template < typename T >
- inline
- T
- gcd_optimal
- (
- T const & a,
- T const & b
- )
- {
- gcd_optimal_evaluator<T> solver;
- return solver( a, b );
- }
- template < typename T >
- inline
- T
- lcm_optimal
- (
- T const & a,
- T const & b
- )
- {
- lcm_optimal_evaluator<T> solver;
- return solver( a, b );
- }
- } // namespace detail
- // Greatest common divisor evaluator member function definition ------------//
- template < typename IntegerType >
- inline
- typename gcd_evaluator<IntegerType>::result_type
- gcd_evaluator<IntegerType>::operator ()
- (
- first_argument_type const & a,
- second_argument_type const & b
- ) const
- {
- return detail::gcd_optimal( a, b );
- }
- // Least common multiple evaluator member function definition --------------//
- template < typename IntegerType >
- inline
- typename lcm_evaluator<IntegerType>::result_type
- lcm_evaluator<IntegerType>::operator ()
- (
- first_argument_type const & a,
- second_argument_type const & b
- ) const
- {
- return detail::lcm_optimal( a, b );
- }
- // Greatest common divisor and least common multiple function definitions --//
- template < typename IntegerType >
- inline
- IntegerType
- gcd
- (
- IntegerType const & a,
- IntegerType const & b
- )
- {
- gcd_evaluator<IntegerType> solver;
- return solver( a, b );
- }
- template < typename IntegerType >
- inline
- IntegerType
- lcm
- (
- IntegerType const & a,
- IntegerType const & b
- )
- {
- lcm_evaluator<IntegerType> solver;
- return solver( a, b );
- }
- } // namespace math
- } // namespace boost
- #ifdef BOOST_MSVC
- #pragma warning(pop)
- #endif
- #endif // BOOST_MATH_COMMON_FACTOR_RT_HPP
|