fix doc example typo
[boost.git] / boost / math / common_factor_rt.hpp
blobf45f3a029538814b5450bbf08c2f7efd3983e02f
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
7 // for any purpose.
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
11 // license.)
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 <boost/detail/workaround.hpp>
25 namespace boost
27 namespace math
31 // Forward declarations for function templates -----------------------------//
33 template < typename IntegerType >
34 IntegerType gcd( IntegerType const &a, IntegerType const &b );
36 template < typename IntegerType >
37 IntegerType lcm( IntegerType const &a, IntegerType const &b );
40 // Greatest common divisor evaluator class declaration ---------------------//
42 template < typename IntegerType >
43 class gcd_evaluator
45 public:
46 // Types
47 typedef IntegerType result_type, first_argument_type, second_argument_type;
49 // Function object interface
50 result_type operator ()( first_argument_type const &a,
51 second_argument_type const &b ) const;
53 }; // boost::math::gcd_evaluator
56 // Least common multiple evaluator class declaration -----------------------//
58 template < typename IntegerType >
59 class lcm_evaluator
61 public:
62 // Types
63 typedef IntegerType result_type, first_argument_type, second_argument_type;
65 // Function object interface
66 result_type operator ()( first_argument_type const &a,
67 second_argument_type const &b ) const;
69 }; // boost::math::lcm_evaluator
72 // Implementation details --------------------------------------------------//
74 namespace detail
76 // Greatest common divisor for rings (including unsigned integers)
77 template < typename RingType >
78 RingType
79 gcd_euclidean
81 RingType a,
82 RingType b
85 // Avoid repeated construction
86 #ifndef __BORLANDC__
87 RingType const zero = static_cast<RingType>( 0 );
88 #else
89 RingType zero = static_cast<RingType>( 0 );
90 #endif
92 // Reduce by GCD-remainder property [GCD(a,b) == GCD(b,a MOD b)]
93 while ( true )
95 if ( a == zero )
96 return b;
97 b %= a;
99 if ( b == zero )
100 return a;
101 a %= b;
105 // Greatest common divisor for (signed) integers
106 template < typename IntegerType >
107 inline
108 IntegerType
109 gcd_integer
111 IntegerType const & a,
112 IntegerType const & b
115 // Avoid repeated construction
116 IntegerType const zero = static_cast<IntegerType>( 0 );
117 IntegerType const result = gcd_euclidean( a, b );
119 return ( result < zero ) ? -result : result;
122 // Greatest common divisor for unsigned binary integers
123 template < typename BuiltInUnsigned >
124 BuiltInUnsigned
125 gcd_binary
127 BuiltInUnsigned u,
128 BuiltInUnsigned v
131 if ( u && v )
133 // Shift out common factors of 2
134 unsigned shifts = 0;
136 while ( !(u & 1u) && !(v & 1u) )
138 ++shifts;
139 u >>= 1;
140 v >>= 1;
143 // Start with the still-even one, if any
144 BuiltInUnsigned r[] = { u, v };
145 unsigned which = static_cast<bool>( u & 1u );
147 // Whittle down the values via their differences
150 #if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x582))
151 while ( !(r[ which ] & 1u) )
153 r[ which ] = (r[which] >> 1);
155 #else
156 // Remove factors of two from the even one
157 while ( !(r[ which ] & 1u) )
159 r[ which ] >>= 1;
161 #endif
163 // Replace the larger of the two with their difference
164 if ( r[!which] > r[which] )
166 which ^= 1u;
169 r[ which ] -= r[ !which ];
171 while ( r[which] );
173 // Shift-in the common factor of 2 to the residues' GCD
174 return r[ !which ] << shifts;
176 else
178 // At least one input is zero, return the other
179 // (adding since zero is the additive identity)
180 // or zero if both are zero.
181 return u + v;
185 // Least common multiple for rings (including unsigned integers)
186 template < typename RingType >
187 inline
188 RingType
189 lcm_euclidean
191 RingType const & a,
192 RingType const & b
195 RingType const zero = static_cast<RingType>( 0 );
196 RingType const temp = gcd_euclidean( a, b );
198 return ( temp != zero ) ? ( a / temp * b ) : zero;
201 // Least common multiple for (signed) integers
202 template < typename IntegerType >
203 inline
204 IntegerType
205 lcm_integer
207 IntegerType const & a,
208 IntegerType const & b
211 // Avoid repeated construction
212 IntegerType const zero = static_cast<IntegerType>( 0 );
213 IntegerType const result = lcm_euclidean( a, b );
215 return ( result < zero ) ? -result : result;
218 // Function objects to find the best way of computing GCD or LCM
219 #ifndef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS
220 #ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
221 template < typename T, bool IsSpecialized, bool IsSigned >
222 struct gcd_optimal_evaluator_helper_t
224 T operator ()( T const &a, T const &b )
226 return gcd_euclidean( a, b );
230 template < typename T >
231 struct gcd_optimal_evaluator_helper_t< T, true, true >
233 T operator ()( T const &a, T const &b )
235 return gcd_integer( a, b );
238 #else
239 template < bool IsSpecialized, bool IsSigned >
240 struct gcd_optimal_evaluator_helper2_t
242 template < typename T >
243 struct helper
245 T operator ()( T const &a, T const &b )
247 return gcd_euclidean( a, b );
252 template < >
253 struct gcd_optimal_evaluator_helper2_t< true, true >
255 template < typename T >
256 struct helper
258 T operator ()( T const &a, T const &b )
260 return gcd_integer( a, b );
265 template < typename T, bool IsSpecialized, bool IsSigned >
266 struct gcd_optimal_evaluator_helper_t
267 : gcd_optimal_evaluator_helper2_t<IsSpecialized, IsSigned>
268 ::BOOST_NESTED_TEMPLATE helper<T>
271 #endif
273 template < typename T >
274 struct gcd_optimal_evaluator
276 T operator ()( T const &a, T const &b )
278 typedef ::std::numeric_limits<T> limits_type;
280 typedef gcd_optimal_evaluator_helper_t<T,
281 limits_type::is_specialized, limits_type::is_signed> helper_type;
283 helper_type solver;
285 return solver( a, b );
288 #else // BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS
289 template < typename T >
290 struct gcd_optimal_evaluator
292 T operator ()( T const &a, T const &b )
294 return gcd_integer( a, b );
297 #endif
299 // Specialize for the built-in integers
300 #define BOOST_PRIVATE_GCD_UF( Ut ) \
301 template < > struct gcd_optimal_evaluator<Ut> \
302 { Ut operator ()( Ut a, Ut b ) const { return gcd_binary( a, b ); } }
304 BOOST_PRIVATE_GCD_UF( unsigned char );
305 BOOST_PRIVATE_GCD_UF( unsigned short );
306 BOOST_PRIVATE_GCD_UF( unsigned );
307 BOOST_PRIVATE_GCD_UF( unsigned long );
309 #ifdef BOOST_HAS_LONG_LONG
310 BOOST_PRIVATE_GCD_UF( boost::ulong_long_type );
311 #elif defined(BOOST_HAS_MS_INT64)
312 BOOST_PRIVATE_GCD_UF( unsigned __int64 );
313 #endif
315 #undef BOOST_PRIVATE_GCD_UF
317 #define BOOST_PRIVATE_GCD_SF( St, Ut ) \
318 template < > struct gcd_optimal_evaluator<St> \
319 { St operator ()( St a, St b ) const { Ut const a_abs = \
320 static_cast<Ut>( a < 0 ? -a : +a ), b_abs = static_cast<Ut>( \
321 b < 0 ? -b : +b ); return static_cast<St>( \
322 gcd_optimal_evaluator<Ut>()(a_abs, b_abs) ); } }
324 BOOST_PRIVATE_GCD_SF( signed char, unsigned char );
325 BOOST_PRIVATE_GCD_SF( short, unsigned short );
326 BOOST_PRIVATE_GCD_SF( int, unsigned );
327 BOOST_PRIVATE_GCD_SF( long, unsigned long );
329 BOOST_PRIVATE_GCD_SF( char, unsigned char ); // should work even if unsigned
331 #ifdef BOOST_HAS_LONG_LONG
332 BOOST_PRIVATE_GCD_SF( boost::long_long_type, boost::ulong_long_type );
333 #elif defined(BOOST_HAS_MS_INT64)
334 BOOST_PRIVATE_GCD_SF( __int64, unsigned __int64 );
335 #endif
337 #undef BOOST_PRIVATE_GCD_SF
339 #ifndef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS
340 #ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
341 template < typename T, bool IsSpecialized, bool IsSigned >
342 struct lcm_optimal_evaluator_helper_t
344 T operator ()( T const &a, T const &b )
346 return lcm_euclidean( a, b );
350 template < typename T >
351 struct lcm_optimal_evaluator_helper_t< T, true, true >
353 T operator ()( T const &a, T const &b )
355 return lcm_integer( a, b );
358 #else
359 template < bool IsSpecialized, bool IsSigned >
360 struct lcm_optimal_evaluator_helper2_t
362 template < typename T >
363 struct helper
365 T operator ()( T const &a, T const &b )
367 return lcm_euclidean( a, b );
372 template < >
373 struct lcm_optimal_evaluator_helper2_t< true, true >
375 template < typename T >
376 struct helper
378 T operator ()( T const &a, T const &b )
380 return lcm_integer( a, b );
385 template < typename T, bool IsSpecialized, bool IsSigned >
386 struct lcm_optimal_evaluator_helper_t
387 : lcm_optimal_evaluator_helper2_t<IsSpecialized, IsSigned>
388 ::BOOST_NESTED_TEMPLATE helper<T>
391 #endif
393 template < typename T >
394 struct lcm_optimal_evaluator
396 T operator ()( T const &a, T const &b )
398 typedef ::std::numeric_limits<T> limits_type;
400 typedef lcm_optimal_evaluator_helper_t<T,
401 limits_type::is_specialized, limits_type::is_signed> helper_type;
403 helper_type solver;
405 return solver( a, b );
408 #else // BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS
409 template < typename T >
410 struct lcm_optimal_evaluator
412 T operator ()( T const &a, T const &b )
414 return lcm_integer( a, b );
417 #endif
419 // Functions to find the GCD or LCM in the best way
420 template < typename T >
421 inline
423 gcd_optimal
425 T const & a,
426 T const & b
429 gcd_optimal_evaluator<T> solver;
431 return solver( a, b );
434 template < typename T >
435 inline
437 lcm_optimal
439 T const & a,
440 T const & b
443 lcm_optimal_evaluator<T> solver;
445 return solver( a, b );
448 } // namespace detail
451 // Greatest common divisor evaluator member function definition ------------//
453 template < typename IntegerType >
454 inline
455 typename gcd_evaluator<IntegerType>::result_type
456 gcd_evaluator<IntegerType>::operator ()
458 first_argument_type const & a,
459 second_argument_type const & b
460 ) const
462 return detail::gcd_optimal( a, b );
466 // Least common multiple evaluator member function definition --------------//
468 template < typename IntegerType >
469 inline
470 typename lcm_evaluator<IntegerType>::result_type
471 lcm_evaluator<IntegerType>::operator ()
473 first_argument_type const & a,
474 second_argument_type const & b
475 ) const
477 return detail::lcm_optimal( a, b );
481 // Greatest common divisor and least common multiple function definitions --//
483 template < typename IntegerType >
484 inline
485 IntegerType
488 IntegerType const & a,
489 IntegerType const & b
492 gcd_evaluator<IntegerType> solver;
494 return solver( a, b );
497 template < typename IntegerType >
498 inline
499 IntegerType
502 IntegerType const & a,
503 IntegerType const & b
506 lcm_evaluator<IntegerType> solver;
508 return solver( a, b );
512 } // namespace math
513 } // namespace boost
516 #endif // BOOST_MATH_COMMON_FACTOR_RT_HPP