forked from boostorg/integer
Changed GCD for built-in integer types to use the binary-GCD algorithm
[SVN r35850]
This commit is contained in:
committed by
Peter Dimov
parent
56b287a590
commit
1f5f827a5e
@ -114,6 +114,62 @@ namespace detail
|
|||||||
return ( result < zero ) ? -result : result;
|
return ( result < zero ) ? -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
|
||||||
|
{
|
||||||
|
// Remove factors of two from the even one
|
||||||
|
while ( !(r[ which ] & 1u) )
|
||||||
|
{
|
||||||
|
r[ which ] >>= 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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)
|
// Least common multiple for rings (including unsigned integers)
|
||||||
template < typename RingType >
|
template < typename RingType >
|
||||||
inline
|
inline
|
||||||
@ -228,6 +284,50 @@ namespace detail
|
|||||||
};
|
};
|
||||||
#endif
|
#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( unsigned long long );
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef BOOST_HAS_MS_INT64
|
||||||
|
BOOST_PRIVATE_GCD_UF( unsigned __int64 );
|
||||||
|
#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 );
|
||||||
|
|
||||||
|
BOOST_PRIVATE_GCD_SF( char, unsigned char ); // should work even if unsigned
|
||||||
|
|
||||||
|
#ifdef BOOST_HAS_LONG_LONG
|
||||||
|
BOOST_PRIVATE_GCD_SF( long long, unsigned long long );
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef 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_LIMITS_COMPILE_TIME_CONSTANTS
|
||||||
#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
|
#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
|
||||||
template < typename T, bool IsSpecialized, bool IsSigned >
|
template < typename T, bool IsSpecialized, bool IsSigned >
|
||||||
|
@ -8,6 +8,7 @@
|
|||||||
// See http://www.boost.org for most recent version including documentation.
|
// See http://www.boost.org for most recent version including documentation.
|
||||||
|
|
||||||
// Revision History
|
// Revision History
|
||||||
|
// 04 Nov 2006 Use more built-in numeric types, binary-GCD (Daryle Walker)
|
||||||
// 03 Nov 2006 Use custom numeric types (Daryle Walker)
|
// 03 Nov 2006 Use custom numeric types (Daryle Walker)
|
||||||
// 02 Nov 2006 Change to Boost.Test's unit test system (Daryle Walker)
|
// 02 Nov 2006 Change to Boost.Test's unit test system (Daryle Walker)
|
||||||
// 07 Nov 2001 Initial version (Daryle Walker)
|
// 07 Nov 2001 Initial version (Daryle Walker)
|
||||||
@ -104,13 +105,23 @@ typedef my_wrapped_integer<int, 1> MyInt2;
|
|||||||
typedef my_wrapped_integer<unsigned, 1> MyUnsigned2;
|
typedef my_wrapped_integer<unsigned, 1> MyUnsigned2;
|
||||||
|
|
||||||
// Various types to test with each GCD/LCM
|
// Various types to test with each GCD/LCM
|
||||||
typedef ::boost::mpl::list<short, int, long> builtin_signed_test_types;
|
typedef ::boost::mpl::list<signed char, short, int, long,
|
||||||
typedef ::boost::mpl::list<unsigned short, unsigned, unsigned long>
|
#ifdef BOOST_HAS_LONG_LONG
|
||||||
builtin_unsigned_test_types;
|
long long,
|
||||||
|
#endif
|
||||||
typedef ::boost::mpl::list<short, int, long, MyInt1> signed_test_types;
|
#ifdef BOOST_HAS_MS_INT64
|
||||||
typedef ::boost::mpl::list<unsigned short, unsigned, unsigned long, MyUnsigned1,
|
__int64,
|
||||||
MyUnsigned2> unsigned_test_types;
|
#endif
|
||||||
|
MyInt1> signed_test_types;
|
||||||
|
typedef ::boost::mpl::list<unsigned char, unsigned short, unsigned,
|
||||||
|
unsigned long,
|
||||||
|
#ifdef BOOST_HAS_LONG_LONG
|
||||||
|
unsigned long long,
|
||||||
|
#endif
|
||||||
|
#ifdef BOOST_HAS_MS_INT64
|
||||||
|
unsigned __int64,
|
||||||
|
#endif
|
||||||
|
MyUnsigned1, MyUnsigned2> unsigned_test_types;
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user