| 1 | //  Boost common_factor_rt.hpp header file  ----------------------------------// | 
|---|
| 2 |  | 
|---|
| 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.  | 
|---|
| 8 |  | 
|---|
| 9 | //  See http://www.boost.org for updates, documentation, and revision history.  | 
|---|
| 10 |  | 
|---|
| 11 | #ifndef BOOST_MATH_COMMON_FACTOR_RT_HPP | 
|---|
| 12 | #define BOOST_MATH_COMMON_FACTOR_RT_HPP | 
|---|
| 13 |  | 
|---|
| 14 | #include <boost/math_fwd.hpp>  // self include | 
|---|
| 15 |  | 
|---|
| 16 | #include <boost/config.hpp>  // for BOOST_NESTED_TEMPLATE, etc. | 
|---|
| 17 | #include <boost/limits.hpp>  // for std::numeric_limits | 
|---|
| 18 |  | 
|---|
| 19 |  | 
|---|
| 20 | namespace boost | 
|---|
| 21 | { | 
|---|
| 22 | namespace math | 
|---|
| 23 | { | 
|---|
| 24 |  | 
|---|
| 25 |  | 
|---|
| 26 | //  Forward declarations for function templates  -----------------------------// | 
|---|
| 27 |  | 
|---|
| 28 | template < typename IntegerType > | 
|---|
| 29 |     IntegerType  gcd( IntegerType const &a, IntegerType const &b ); | 
|---|
| 30 |  | 
|---|
| 31 | template < typename IntegerType > | 
|---|
| 32 |     IntegerType  lcm( IntegerType const &a, IntegerType const &b ); | 
|---|
| 33 |  | 
|---|
| 34 |  | 
|---|
| 35 | //  Greatest common divisor evaluator class declaration  ---------------------// | 
|---|
| 36 |  | 
|---|
| 37 | template < typename IntegerType > | 
|---|
| 38 | class gcd_evaluator | 
|---|
| 39 | { | 
|---|
| 40 | public: | 
|---|
| 41 |     // Types | 
|---|
| 42 |     typedef IntegerType  result_type, first_argument_type, second_argument_type; | 
|---|
| 43 |  | 
|---|
| 44 |     // Function object interface | 
|---|
| 45 |     result_type  operator ()( first_argument_type const &a, | 
|---|
| 46 |      second_argument_type const &b ) const; | 
|---|
| 47 |  | 
|---|
| 48 | };  // boost::math::gcd_evaluator | 
|---|
| 49 |  | 
|---|
| 50 |  | 
|---|
| 51 | //  Least common multiple evaluator class declaration  -----------------------// | 
|---|
| 52 |  | 
|---|
| 53 | template < typename IntegerType > | 
|---|
| 54 | class lcm_evaluator | 
|---|
| 55 | { | 
|---|
| 56 | public: | 
|---|
| 57 |     // Types | 
|---|
| 58 |     typedef IntegerType  result_type, first_argument_type, second_argument_type; | 
|---|
| 59 |  | 
|---|
| 60 |     // Function object interface | 
|---|
| 61 |     result_type  operator ()( first_argument_type const &a, | 
|---|
| 62 |      second_argument_type const &b ) const; | 
|---|
| 63 |  | 
|---|
| 64 | };  // boost::math::lcm_evaluator | 
|---|
| 65 |  | 
|---|
| 66 |  | 
|---|
| 67 | //  Implementation details  --------------------------------------------------// | 
|---|
| 68 |  | 
|---|
| 69 | namespace detail | 
|---|
| 70 | { | 
|---|
| 71 |     // Greatest common divisor for rings (including unsigned integers) | 
|---|
| 72 |     template < typename RingType > | 
|---|
| 73 |     RingType | 
|---|
| 74 |     gcd_euclidean | 
|---|
| 75 |     ( | 
|---|
| 76 |         RingType  a, | 
|---|
| 77 |         RingType  b | 
|---|
| 78 |     ) | 
|---|
| 79 |     { | 
|---|
| 80 |         // Avoid repeated construction | 
|---|
| 81 |         #ifndef __BORLANDC__ | 
|---|
| 82 |         RingType const  zero = static_cast<RingType>( 0 ); | 
|---|
| 83 |         #else | 
|---|
| 84 |         RingType  zero = static_cast<RingType>( 0 ); | 
|---|
| 85 |         #endif | 
|---|
| 86 |  | 
|---|
| 87 |         // Reduce by GCD-remainder property [GCD(a,b) == GCD(b,a MOD b)] | 
|---|
| 88 |         while ( true ) | 
|---|
| 89 |         { | 
|---|
| 90 |             if ( a == zero ) | 
|---|
| 91 |                 return b; | 
|---|
| 92 |             b %= a; | 
|---|
| 93 |  | 
|---|
| 94 |             if ( b == zero ) | 
|---|
| 95 |                 return a; | 
|---|
| 96 |             a %= b; | 
|---|
| 97 |         } | 
|---|
| 98 |     } | 
|---|
| 99 |  | 
|---|
| 100 |     // Greatest common divisor for (signed) integers | 
|---|
| 101 |     template < typename IntegerType > | 
|---|
| 102 |     inline | 
|---|
| 103 |     IntegerType | 
|---|
| 104 |     gcd_integer | 
|---|
| 105 |     ( | 
|---|
| 106 |         IntegerType const &  a, | 
|---|
| 107 |         IntegerType const &  b | 
|---|
| 108 |     ) | 
|---|
| 109 |     { | 
|---|
| 110 |         // Avoid repeated construction | 
|---|
| 111 |         IntegerType const  zero = static_cast<IntegerType>( 0 ); | 
|---|
| 112 |         IntegerType const  result = gcd_euclidean( a, b ); | 
|---|
| 113 |  | 
|---|
| 114 |         return ( result < zero ) ? -result : result; | 
|---|
| 115 |     } | 
|---|
| 116 |  | 
|---|
| 117 |     // Least common multiple for rings (including unsigned integers) | 
|---|
| 118 |     template < typename RingType > | 
|---|
| 119 |     inline | 
|---|
| 120 |     RingType | 
|---|
| 121 |     lcm_euclidean | 
|---|
| 122 |     ( | 
|---|
| 123 |         RingType const &  a, | 
|---|
| 124 |         RingType const &  b | 
|---|
| 125 |     ) | 
|---|
| 126 |     { | 
|---|
| 127 |         RingType const  zero = static_cast<RingType>( 0 ); | 
|---|
| 128 |         RingType const  temp = gcd_euclidean( a, b ); | 
|---|
| 129 |  | 
|---|
| 130 |         return ( temp != zero ) ? ( a / temp * b ) : zero; | 
|---|
| 131 |     } | 
|---|
| 132 |  | 
|---|
| 133 |     // Least common multiple for (signed) integers | 
|---|
| 134 |     template < typename IntegerType > | 
|---|
| 135 |     inline | 
|---|
| 136 |     IntegerType | 
|---|
| 137 |     lcm_integer | 
|---|
| 138 |     ( | 
|---|
| 139 |         IntegerType const &  a, | 
|---|
| 140 |         IntegerType const &  b | 
|---|
| 141 |     ) | 
|---|
| 142 |     { | 
|---|
| 143 |         // Avoid repeated construction | 
|---|
| 144 |         IntegerType const  zero = static_cast<IntegerType>( 0 ); | 
|---|
| 145 |         IntegerType const  result = lcm_euclidean( a, b ); | 
|---|
| 146 |  | 
|---|
| 147 |         return ( result < zero ) ? -result : result; | 
|---|
| 148 |     } | 
|---|
| 149 |  | 
|---|
| 150 |     // Function objects to find the best way of computing GCD or LCM | 
|---|
| 151 | #ifndef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS | 
|---|
| 152 | #ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION | 
|---|
| 153 |     template < typename T, bool IsSpecialized, bool IsSigned > | 
|---|
| 154 |     struct gcd_optimal_evaluator_helper_t | 
|---|
| 155 |     { | 
|---|
| 156 |         T  operator ()( T const &a, T const &b ) | 
|---|
| 157 |         { | 
|---|
| 158 |             return gcd_euclidean( a, b ); | 
|---|
| 159 |         } | 
|---|
| 160 |     }; | 
|---|
| 161 |  | 
|---|
| 162 |     template < typename T > | 
|---|
| 163 |     struct gcd_optimal_evaluator_helper_t< T, true, true > | 
|---|
| 164 |     { | 
|---|
| 165 |         T  operator ()( T const &a, T const &b ) | 
|---|
| 166 |         { | 
|---|
| 167 |             return gcd_integer( a, b ); | 
|---|
| 168 |         } | 
|---|
| 169 |     }; | 
|---|
| 170 | #else | 
|---|
| 171 |     template < bool IsSpecialized, bool IsSigned > | 
|---|
| 172 |     struct gcd_optimal_evaluator_helper2_t | 
|---|
| 173 |     { | 
|---|
| 174 |         template < typename T > | 
|---|
| 175 |         struct helper | 
|---|
| 176 |         { | 
|---|
| 177 |             T  operator ()( T const &a, T const &b ) | 
|---|
| 178 |             { | 
|---|
| 179 |                 return gcd_euclidean( a, b ); | 
|---|
| 180 |             } | 
|---|
| 181 |         }; | 
|---|
| 182 |     }; | 
|---|
| 183 |  | 
|---|
| 184 |     template < > | 
|---|
| 185 |     struct gcd_optimal_evaluator_helper2_t< true, true > | 
|---|
| 186 |     { | 
|---|
| 187 |         template < typename T > | 
|---|
| 188 |         struct helper | 
|---|
| 189 |         { | 
|---|
| 190 |             T  operator ()( T const &a, T const &b ) | 
|---|
| 191 |             { | 
|---|
| 192 |                 return gcd_integer( a, b ); | 
|---|
| 193 |             } | 
|---|
| 194 |         }; | 
|---|
| 195 |     }; | 
|---|
| 196 |  | 
|---|
| 197 |     template < typename T, bool IsSpecialized, bool IsSigned > | 
|---|
| 198 |     struct gcd_optimal_evaluator_helper_t | 
|---|
| 199 |         : gcd_optimal_evaluator_helper2_t<IsSpecialized, IsSigned> | 
|---|
| 200 |            ::BOOST_NESTED_TEMPLATE helper<T> | 
|---|
| 201 |     { | 
|---|
| 202 |     }; | 
|---|
| 203 | #endif | 
|---|
| 204 |  | 
|---|
| 205 |     template < typename T > | 
|---|
| 206 |     struct gcd_optimal_evaluator | 
|---|
| 207 |     { | 
|---|
| 208 |         T  operator ()( T const &a, T const &b ) | 
|---|
| 209 |         { | 
|---|
| 210 |             typedef ::std::numeric_limits<T>  limits_type; | 
|---|
| 211 |  | 
|---|
| 212 |             typedef gcd_optimal_evaluator_helper_t<T, | 
|---|
| 213 |              limits_type::is_specialized, limits_type::is_signed>  helper_type; | 
|---|
| 214 |  | 
|---|
| 215 |             helper_type  solver; | 
|---|
| 216 |  | 
|---|
| 217 |             return solver( a, b ); | 
|---|
| 218 |         } | 
|---|
| 219 |     }; | 
|---|
| 220 | #else // BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS | 
|---|
| 221 |     template < typename T > | 
|---|
| 222 |     struct gcd_optimal_evaluator | 
|---|
| 223 |     { | 
|---|
| 224 |         T  operator ()( T const &a, T const &b ) | 
|---|
| 225 |         { | 
|---|
| 226 |             return gcd_integer( a, b ); | 
|---|
| 227 |         } | 
|---|
| 228 |     }; | 
|---|
| 229 | #endif | 
|---|
| 230 |  | 
|---|
| 231 | #ifndef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS | 
|---|
| 232 | #ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION | 
|---|
| 233 |     template < typename T, bool IsSpecialized, bool IsSigned > | 
|---|
| 234 |     struct lcm_optimal_evaluator_helper_t | 
|---|
| 235 |     { | 
|---|
| 236 |         T  operator ()( T const &a, T const &b ) | 
|---|
| 237 |         { | 
|---|
| 238 |             return lcm_euclidean( a, b ); | 
|---|
| 239 |         } | 
|---|
| 240 |     }; | 
|---|
| 241 |  | 
|---|
| 242 |     template < typename T > | 
|---|
| 243 |     struct lcm_optimal_evaluator_helper_t< T, true, true > | 
|---|
| 244 |     { | 
|---|
| 245 |         T  operator ()( T const &a, T const &b ) | 
|---|
| 246 |         { | 
|---|
| 247 |             return lcm_integer( a, b ); | 
|---|
| 248 |         } | 
|---|
| 249 |     }; | 
|---|
| 250 | #else | 
|---|
| 251 |     template < bool IsSpecialized, bool IsSigned > | 
|---|
| 252 |     struct lcm_optimal_evaluator_helper2_t | 
|---|
| 253 |     { | 
|---|
| 254 |         template < typename T > | 
|---|
| 255 |         struct helper | 
|---|
| 256 |         { | 
|---|
| 257 |             T  operator ()( T const &a, T const &b ) | 
|---|
| 258 |             { | 
|---|
| 259 |                 return lcm_euclidean( a, b ); | 
|---|
| 260 |             } | 
|---|
| 261 |         }; | 
|---|
| 262 |     }; | 
|---|
| 263 |  | 
|---|
| 264 |     template < > | 
|---|
| 265 |     struct lcm_optimal_evaluator_helper2_t< true, true > | 
|---|
| 266 |     { | 
|---|
| 267 |         template < typename T > | 
|---|
| 268 |         struct helper | 
|---|
| 269 |         { | 
|---|
| 270 |             T  operator ()( T const &a, T const &b ) | 
|---|
| 271 |             { | 
|---|
| 272 |                 return lcm_integer( a, b ); | 
|---|
| 273 |             } | 
|---|
| 274 |         }; | 
|---|
| 275 |     }; | 
|---|
| 276 |  | 
|---|
| 277 |     template < typename T, bool IsSpecialized, bool IsSigned > | 
|---|
| 278 |     struct lcm_optimal_evaluator_helper_t | 
|---|
| 279 |         : lcm_optimal_evaluator_helper2_t<IsSpecialized, IsSigned> | 
|---|
| 280 |            ::BOOST_NESTED_TEMPLATE helper<T> | 
|---|
| 281 |     { | 
|---|
| 282 |     }; | 
|---|
| 283 | #endif | 
|---|
| 284 |  | 
|---|
| 285 |     template < typename T > | 
|---|
| 286 |     struct lcm_optimal_evaluator | 
|---|
| 287 |     { | 
|---|
| 288 |         T  operator ()( T const &a, T const &b ) | 
|---|
| 289 |         { | 
|---|
| 290 |             typedef ::std::numeric_limits<T>  limits_type; | 
|---|
| 291 |  | 
|---|
| 292 |             typedef lcm_optimal_evaluator_helper_t<T, | 
|---|
| 293 |              limits_type::is_specialized, limits_type::is_signed>  helper_type; | 
|---|
| 294 |  | 
|---|
| 295 |             helper_type  solver; | 
|---|
| 296 |  | 
|---|
| 297 |             return solver( a, b ); | 
|---|
| 298 |         } | 
|---|
| 299 |     }; | 
|---|
| 300 | #else // BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS | 
|---|
| 301 |     template < typename T > | 
|---|
| 302 |     struct lcm_optimal_evaluator | 
|---|
| 303 |     { | 
|---|
| 304 |         T  operator ()( T const &a, T const &b ) | 
|---|
| 305 |         { | 
|---|
| 306 |             return lcm_integer( a, b ); | 
|---|
| 307 |         } | 
|---|
| 308 |     }; | 
|---|
| 309 | #endif | 
|---|
| 310 |  | 
|---|
| 311 |     // Functions to find the GCD or LCM in the best way | 
|---|
| 312 |     template < typename T > | 
|---|
| 313 |     inline | 
|---|
| 314 |     T | 
|---|
| 315 |     gcd_optimal | 
|---|
| 316 |     ( | 
|---|
| 317 |         T const &  a, | 
|---|
| 318 |         T const &  b | 
|---|
| 319 |     ) | 
|---|
| 320 |     { | 
|---|
| 321 |         gcd_optimal_evaluator<T>  solver; | 
|---|
| 322 |  | 
|---|
| 323 |         return solver( a, b ); | 
|---|
| 324 |     } | 
|---|
| 325 |  | 
|---|
| 326 |     template < typename T > | 
|---|
| 327 |     inline | 
|---|
| 328 |     T | 
|---|
| 329 |     lcm_optimal | 
|---|
| 330 |     ( | 
|---|
| 331 |         T const &  a, | 
|---|
| 332 |         T const &  b | 
|---|
| 333 |     ) | 
|---|
| 334 |     { | 
|---|
| 335 |         lcm_optimal_evaluator<T>  solver; | 
|---|
| 336 |  | 
|---|
| 337 |         return solver( a, b ); | 
|---|
| 338 |     } | 
|---|
| 339 |  | 
|---|
| 340 | }  // namespace detail | 
|---|
| 341 |  | 
|---|
| 342 |  | 
|---|
| 343 | //  Greatest common divisor evaluator member function definition  ------------// | 
|---|
| 344 |  | 
|---|
| 345 | template < typename IntegerType > | 
|---|
| 346 | inline | 
|---|
| 347 | typename gcd_evaluator<IntegerType>::result_type | 
|---|
| 348 | gcd_evaluator<IntegerType>::operator () | 
|---|
| 349 | ( | 
|---|
| 350 |     first_argument_type const &   a, | 
|---|
| 351 |     second_argument_type const &  b | 
|---|
| 352 | ) const | 
|---|
| 353 | { | 
|---|
| 354 |     return detail::gcd_optimal( a, b ); | 
|---|
| 355 | } | 
|---|
| 356 |  | 
|---|
| 357 |  | 
|---|
| 358 | //  Least common multiple evaluator member function definition  --------------// | 
|---|
| 359 |  | 
|---|
| 360 | template < typename IntegerType > | 
|---|
| 361 | inline | 
|---|
| 362 | typename lcm_evaluator<IntegerType>::result_type | 
|---|
| 363 | lcm_evaluator<IntegerType>::operator () | 
|---|
| 364 | ( | 
|---|
| 365 |     first_argument_type const &   a, | 
|---|
| 366 |     second_argument_type const &  b | 
|---|
| 367 | ) const | 
|---|
| 368 | { | 
|---|
| 369 |     return detail::lcm_optimal( a, b ); | 
|---|
| 370 | } | 
|---|
| 371 |  | 
|---|
| 372 |  | 
|---|
| 373 | //  Greatest common divisor and least common multiple function definitions  --// | 
|---|
| 374 |  | 
|---|
| 375 | template < typename IntegerType > | 
|---|
| 376 | inline | 
|---|
| 377 | IntegerType | 
|---|
| 378 | gcd | 
|---|
| 379 | ( | 
|---|
| 380 |     IntegerType const &  a, | 
|---|
| 381 |     IntegerType const &  b | 
|---|
| 382 | ) | 
|---|
| 383 | { | 
|---|
| 384 |     gcd_evaluator<IntegerType>  solver; | 
|---|
| 385 |  | 
|---|
| 386 |     return solver( a, b ); | 
|---|
| 387 | } | 
|---|
| 388 |  | 
|---|
| 389 | template < typename IntegerType > | 
|---|
| 390 | inline | 
|---|
| 391 | IntegerType | 
|---|
| 392 | lcm | 
|---|
| 393 | ( | 
|---|
| 394 |     IntegerType const &  a, | 
|---|
| 395 |     IntegerType const &  b | 
|---|
| 396 | ) | 
|---|
| 397 | { | 
|---|
| 398 |     lcm_evaluator<IntegerType>  solver; | 
|---|
| 399 |  | 
|---|
| 400 |     return solver( a, b ); | 
|---|
| 401 | } | 
|---|
| 402 |  | 
|---|
| 403 |  | 
|---|
| 404 | }  // namespace math | 
|---|
| 405 | }  // namespace boost | 
|---|
| 406 |  | 
|---|
| 407 |  | 
|---|
| 408 | #endif  // BOOST_MATH_COMMON_FACTOR_RT_HPP | 
|---|