1 // Boost common_factor_rt.hpp header file ----------------------------------//
3 // (C) Copyright Daryle Walker and Paul Moore 2001-2002. Permission to copy,
4 // use, modify, sell and distribute this software is granted provided this
5 // copyright notice appears in all copies. This software is provided "as is"
6 // without express or implied warranty, and with no claim as to its suitability
9 // boostinspect:nolicense (don't complain about the lack of a Boost license)
10 // (Paul Moore hasn't been in contact for years, so there's no way to change the
13 // See http://www.boost.org for updates, documentation, and revision history.
15 #ifndef BOOST_MATH_COMMON_FACTOR_RT_HPP
16 #define BOOST_MATH_COMMON_FACTOR_RT_HPP
18 #include <boost/math_fwd.hpp> // self include
20 #include <boost/config.hpp> // for BOOST_NESTED_TEMPLATE, etc.
21 #include <boost/limits.hpp> // for std::numeric_limits
22 #include <climits> // for CHAR_MIN
23 #include <boost/detail/workaround.hpp>
27 #pragma warning(disable:4127 4244) // Conditional expression is constant
36 // Forward declarations for function templates -----------------------------//
38 template < typename IntegerType >
39 IntegerType gcd( IntegerType const &a, IntegerType const &b );
41 template < typename IntegerType >
42 IntegerType lcm( IntegerType const &a, IntegerType const &b );
45 // Greatest common divisor evaluator class declaration ---------------------//
47 template < typename IntegerType >
52 typedef IntegerType result_type, first_argument_type, second_argument_type;
54 // Function object interface
55 result_type operator ()( first_argument_type const &a,
56 second_argument_type const &b ) const;
58 }; // boost::math::gcd_evaluator
61 // Least common multiple evaluator class declaration -----------------------//
63 template < typename IntegerType >
68 typedef IntegerType result_type, first_argument_type, second_argument_type;
70 // Function object interface
71 result_type operator ()( first_argument_type const &a,
72 second_argument_type const &b ) const;
74 }; // boost::math::lcm_evaluator
77 // Implementation details --------------------------------------------------//
81 // Greatest common divisor for rings (including unsigned integers)
82 template < typename RingType >
90 // Avoid repeated construction
92 RingType const zero = static_cast<RingType>( 0 );
94 RingType zero = static_cast<RingType>( 0 );
97 // Reduce by GCD-remainder property [GCD(a,b) == GCD(b,a MOD b)]
110 // Greatest common divisor for (signed) integers
111 template < typename IntegerType >
116 IntegerType const & a,
117 IntegerType const & b
120 // Avoid repeated construction
121 IntegerType const zero = static_cast<IntegerType>( 0 );
122 IntegerType const result = gcd_euclidean( a, b );
124 return ( result < zero ) ? static_cast<IntegerType>(-result) : result;
127 // Greatest common divisor for unsigned binary integers
128 template < typename BuiltInUnsigned >
138 // Shift out common factors of 2
141 while ( !(u & 1u) && !(v & 1u) )
148 // Start with the still-even one, if any
149 BuiltInUnsigned r[] = { u, v };
150 unsigned which = static_cast<bool>( u & 1u );
152 // Whittle down the values via their differences
155 #if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x582))
156 while ( !(r[ which ] & 1u) )
158 r[ which ] = (r[which] >> 1);
161 // Remove factors of two from the even one
162 while ( !(r[ which ] & 1u) )
168 // Replace the larger of the two with their difference
169 if ( r[!which] > r[which] )
174 r[ which ] -= r[ !which ];
178 // Shift-in the common factor of 2 to the residues' GCD
179 return r[ !which ] << shifts;
183 // At least one input is zero, return the other
184 // (adding since zero is the additive identity)
185 // or zero if both are zero.
190 // Least common multiple for rings (including unsigned integers)
191 template < typename RingType >
200 RingType const zero = static_cast<RingType>( 0 );
201 RingType const temp = gcd_euclidean( a, b );
203 return ( temp != zero ) ? ( a / temp * b ) : zero;
206 // Least common multiple for (signed) integers
207 template < typename IntegerType >
212 IntegerType const & a,
213 IntegerType const & b
216 // Avoid repeated construction
217 IntegerType const zero = static_cast<IntegerType>( 0 );
218 IntegerType const result = lcm_euclidean( a, b );
220 return ( result < zero ) ? static_cast<IntegerType>(-result) : result;
223 // Function objects to find the best way of computing GCD or LCM
224 #ifndef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS
225 template < typename T, bool IsSpecialized, bool IsSigned >
226 struct gcd_optimal_evaluator_helper_t
228 T operator ()( T const &a, T const &b )
230 return gcd_euclidean( a, b );
234 template < typename T >
235 struct gcd_optimal_evaluator_helper_t< T, true, true >
237 T operator ()( T const &a, T const &b )
239 return gcd_integer( a, b );
243 template < typename T >
244 struct gcd_optimal_evaluator
246 T operator ()( T const &a, T const &b )
248 typedef ::std::numeric_limits<T> limits_type;
250 typedef gcd_optimal_evaluator_helper_t<T,
251 limits_type::is_specialized, limits_type::is_signed> helper_type;
255 return solver( a, b );
258 #else // BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS
259 template < typename T >
260 struct gcd_optimal_evaluator
262 T operator ()( T const &a, T const &b )
264 return gcd_integer( a, b );
269 // Specialize for the built-in integers
270 #define BOOST_PRIVATE_GCD_UF( Ut ) \
271 template < > struct gcd_optimal_evaluator<Ut> \
272 { Ut operator ()( Ut a, Ut b ) const { return gcd_binary( a, b ); } }
274 BOOST_PRIVATE_GCD_UF( unsigned char );
275 BOOST_PRIVATE_GCD_UF( unsigned short );
276 BOOST_PRIVATE_GCD_UF( unsigned );
277 BOOST_PRIVATE_GCD_UF( unsigned long );
279 #ifdef BOOST_HAS_LONG_LONG
280 BOOST_PRIVATE_GCD_UF( boost::ulong_long_type );
281 #elif defined(BOOST_HAS_MS_INT64)
282 BOOST_PRIVATE_GCD_UF( unsigned __int64 );
286 BOOST_PRIVATE_GCD_UF( char ); // char is unsigned
289 #undef BOOST_PRIVATE_GCD_UF
291 #define BOOST_PRIVATE_GCD_SF( St, Ut ) \
292 template < > struct gcd_optimal_evaluator<St> \
293 { St operator ()( St a, St b ) const { Ut const a_abs = \
294 static_cast<Ut>( a < 0 ? -a : +a ), b_abs = static_cast<Ut>( \
295 b < 0 ? -b : +b ); return static_cast<St>( \
296 gcd_optimal_evaluator<Ut>()(a_abs, b_abs) ); } }
298 BOOST_PRIVATE_GCD_SF( signed char, unsigned char );
299 BOOST_PRIVATE_GCD_SF( short, unsigned short );
300 BOOST_PRIVATE_GCD_SF( int, unsigned );
301 BOOST_PRIVATE_GCD_SF( long, unsigned long );
304 BOOST_PRIVATE_GCD_SF( char, unsigned char ); // char is signed
307 #ifdef BOOST_HAS_LONG_LONG
308 BOOST_PRIVATE_GCD_SF( boost::long_long_type, boost::ulong_long_type );
309 #elif defined(BOOST_HAS_MS_INT64)
310 BOOST_PRIVATE_GCD_SF( __int64, unsigned __int64 );
313 #undef BOOST_PRIVATE_GCD_SF
315 #ifndef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS
316 template < typename T, bool IsSpecialized, bool IsSigned >
317 struct lcm_optimal_evaluator_helper_t
319 T operator ()( T const &a, T const &b )
321 return lcm_euclidean( a, b );
325 template < typename T >
326 struct lcm_optimal_evaluator_helper_t< T, true, true >
328 T operator ()( T const &a, T const &b )
330 return lcm_integer( a, b );
334 template < typename T >
335 struct lcm_optimal_evaluator
337 T operator ()( T const &a, T const &b )
339 typedef ::std::numeric_limits<T> limits_type;
341 typedef lcm_optimal_evaluator_helper_t<T,
342 limits_type::is_specialized, limits_type::is_signed> helper_type;
346 return solver( a, b );
349 #else // BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS
350 template < typename T >
351 struct lcm_optimal_evaluator
353 T operator ()( T const &a, T const &b )
355 return lcm_integer( a, b );
360 // Functions to find the GCD or LCM in the best way
361 template < typename T >
370 gcd_optimal_evaluator<T> solver;
372 return solver( a, b );
375 template < typename T >
384 lcm_optimal_evaluator<T> solver;
386 return solver( a, b );
389 } // namespace detail
392 // Greatest common divisor evaluator member function definition ------------//
394 template < typename IntegerType >
396 typename gcd_evaluator<IntegerType>::result_type
397 gcd_evaluator<IntegerType>::operator ()
399 first_argument_type const & a,
400 second_argument_type const & b
403 return detail::gcd_optimal( a, b );
407 // Least common multiple evaluator member function definition --------------//
409 template < typename IntegerType >
411 typename lcm_evaluator<IntegerType>::result_type
412 lcm_evaluator<IntegerType>::operator ()
414 first_argument_type const & a,
415 second_argument_type const & b
418 return detail::lcm_optimal( a, b );
422 // Greatest common divisor and least common multiple function definitions --//
424 template < typename IntegerType >
429 IntegerType const & a,
430 IntegerType const & b
433 gcd_evaluator<IntegerType> solver;
435 return solver( a, b );
438 template < typename IntegerType >
443 IntegerType const & a,
444 IntegerType const & b
447 lcm_evaluator<IntegerType> solver;
449 return solver( a, b );
460 #endif // BOOST_MATH_COMMON_FACTOR_RT_HPP