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
#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
226
template < typename T, bool IsSpecialized, bool IsSigned >
227
struct gcd_optimal_evaluator_helper_t
229
T operator ()( T const &a, T const &b )
231
return gcd_euclidean( a, b );
235
template < typename T >
236
struct gcd_optimal_evaluator_helper_t< T, true, true >
238
T operator ()( T const &a, T const &b )
240
return gcd_integer( a, b );
244
template < bool IsSpecialized, bool IsSigned >
245
struct gcd_optimal_evaluator_helper2_t
247
template < typename T >
250
T operator ()( T const &a, T const &b )
252
return gcd_euclidean( a, b );
258
struct gcd_optimal_evaluator_helper2_t< true, true >
260
template < typename T >
263
T operator ()( T const &a, T const &b )
265
return gcd_integer( a, b );
270
template < typename T, bool IsSpecialized, bool IsSigned >
271
struct gcd_optimal_evaluator_helper_t
272
: gcd_optimal_evaluator_helper2_t<IsSpecialized, IsSigned>
273
::BOOST_NESTED_TEMPLATE helper<T>
278
template < typename T >
279
struct gcd_optimal_evaluator
281
T operator ()( T const &a, T const &b )
283
typedef ::std::numeric_limits<T> limits_type;
285
typedef gcd_optimal_evaluator_helper_t<T,
286
limits_type::is_specialized, limits_type::is_signed> helper_type;
290
return solver( a, b );
293
#else // BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS
294
template < typename T >
295
struct gcd_optimal_evaluator
297
T operator ()( T const &a, T const &b )
299
return gcd_integer( a, b );
304
// Specialize for the built-in integers
305
#define BOOST_PRIVATE_GCD_UF( Ut ) \
306
template < > struct gcd_optimal_evaluator<Ut> \
307
{ Ut operator ()( Ut a, Ut b ) const { return gcd_binary( a, b ); } }
309
BOOST_PRIVATE_GCD_UF( unsigned char );
310
BOOST_PRIVATE_GCD_UF( unsigned short );
311
BOOST_PRIVATE_GCD_UF( unsigned );
312
BOOST_PRIVATE_GCD_UF( unsigned long );
314
#ifdef BOOST_HAS_LONG_LONG
315
BOOST_PRIVATE_GCD_UF( boost::ulong_long_type );
316
#elif defined(BOOST_HAS_MS_INT64)
317
BOOST_PRIVATE_GCD_UF( unsigned __int64 );
321
BOOST_PRIVATE_GCD_UF( char ); // char is unsigned
324
#undef BOOST_PRIVATE_GCD_UF
326
#define BOOST_PRIVATE_GCD_SF( St, Ut ) \
327
template < > struct gcd_optimal_evaluator<St> \
328
{ St operator ()( St a, St b ) const { Ut const a_abs = \
329
static_cast<Ut>( a < 0 ? -a : +a ), b_abs = static_cast<Ut>( \
330
b < 0 ? -b : +b ); return static_cast<St>( \
331
gcd_optimal_evaluator<Ut>()(a_abs, b_abs) ); } }
333
BOOST_PRIVATE_GCD_SF( signed char, unsigned char );
334
BOOST_PRIVATE_GCD_SF( short, unsigned short );
335
BOOST_PRIVATE_GCD_SF( int, unsigned );
336
BOOST_PRIVATE_GCD_SF( long, unsigned long );
339
BOOST_PRIVATE_GCD_SF( char, unsigned char ); // char is signed
342
#ifdef BOOST_HAS_LONG_LONG
343
BOOST_PRIVATE_GCD_SF( boost::long_long_type, boost::ulong_long_type );
344
#elif defined(BOOST_HAS_MS_INT64)
345
BOOST_PRIVATE_GCD_SF( __int64, unsigned __int64 );
348
#undef BOOST_PRIVATE_GCD_SF
350
#ifndef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS
351
#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
352
template < typename T, bool IsSpecialized, bool IsSigned >
353
struct lcm_optimal_evaluator_helper_t
355
T operator ()( T const &a, T const &b )
357
return lcm_euclidean( a, b );
361
template < typename T >
362
struct lcm_optimal_evaluator_helper_t< T, true, true >
364
T operator ()( T const &a, T const &b )
366
return lcm_integer( a, b );
370
template < bool IsSpecialized, bool IsSigned >
371
struct lcm_optimal_evaluator_helper2_t
373
template < typename T >
376
T operator ()( T const &a, T const &b )
378
return lcm_euclidean( a, b );
384
struct lcm_optimal_evaluator_helper2_t< true, true >
386
template < typename T >
389
T operator ()( T const &a, T const &b )
391
return lcm_integer( a, b );
396
template < typename T, bool IsSpecialized, bool IsSigned >
397
struct lcm_optimal_evaluator_helper_t
398
: lcm_optimal_evaluator_helper2_t<IsSpecialized, IsSigned>
399
::BOOST_NESTED_TEMPLATE helper<T>
404
template < typename T >
405
struct lcm_optimal_evaluator
407
T operator ()( T const &a, T const &b )
409
typedef ::std::numeric_limits<T> limits_type;
411
typedef lcm_optimal_evaluator_helper_t<T,
412
limits_type::is_specialized, limits_type::is_signed> helper_type;
416
return solver( a, b );
419
#else // BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS
420
template < typename T >
421
struct lcm_optimal_evaluator
423
T operator ()( T const &a, T const &b )
425
return lcm_integer( a, b );
430
// Functions to find the GCD or LCM in the best way
431
template < typename T >
440
gcd_optimal_evaluator<T> solver;
442
return solver( a, b );
445
template < typename T >
454
lcm_optimal_evaluator<T> solver;
456
return solver( a, b );
459
} // namespace detail
462
// Greatest common divisor evaluator member function definition ------------//
464
template < typename IntegerType >
466
typename gcd_evaluator<IntegerType>::result_type
467
gcd_evaluator<IntegerType>::operator ()
469
first_argument_type const & a,
470
second_argument_type const & b
473
return detail::gcd_optimal( a, b );
477
// Least common multiple evaluator member function definition --------------//
479
template < typename IntegerType >
481
typename lcm_evaluator<IntegerType>::result_type
482
lcm_evaluator<IntegerType>::operator ()
484
first_argument_type const & a,
485
second_argument_type const & b
488
return detail::lcm_optimal( a, b );
492
// Greatest common divisor and least common multiple function definitions --//
494
template < typename IntegerType >
499
IntegerType const & a,
500
IntegerType const & b
503
gcd_evaluator<IntegerType> solver;
505
return solver( a, b );
508
template < typename IntegerType >
513
IntegerType const & a,
514
IntegerType const & b
517
lcm_evaluator<IntegerType> solver;
519
return solver( a, b );
530
#endif // BOOST_MATH_COMMON_FACTOR_RT_HPP