annotate DEPENDENCIES/generic/include/boost/math/common_factor_rt.hpp @ 133:4acb5d8d80b6 tip

Don't fail environmental check if README.md exists (but .txt and no-suffix don't)
author Chris Cannam
date Tue, 30 Jul 2019 12:25:44 +0100
parents c530137014c0
children
rev   line source
Chris@16 1 // Boost common_factor_rt.hpp header file ----------------------------------//
Chris@16 2
Chris@16 3 // (C) Copyright Daryle Walker and Paul Moore 2001-2002. Permission to copy,
Chris@16 4 // use, modify, sell and distribute this software is granted provided this
Chris@16 5 // copyright notice appears in all copies. This software is provided "as is"
Chris@16 6 // without express or implied warranty, and with no claim as to its suitability
Chris@16 7 // for any purpose.
Chris@16 8
Chris@16 9 // boostinspect:nolicense (don't complain about the lack of a Boost license)
Chris@16 10 // (Paul Moore hasn't been in contact for years, so there's no way to change the
Chris@16 11 // license.)
Chris@16 12
Chris@16 13 // See http://www.boost.org for updates, documentation, and revision history.
Chris@16 14
Chris@16 15 #ifndef BOOST_MATH_COMMON_FACTOR_RT_HPP
Chris@16 16 #define BOOST_MATH_COMMON_FACTOR_RT_HPP
Chris@16 17
Chris@16 18 #include <boost/math_fwd.hpp> // self include
Chris@16 19
Chris@16 20 #include <boost/config.hpp> // for BOOST_NESTED_TEMPLATE, etc.
Chris@16 21 #include <boost/limits.hpp> // for std::numeric_limits
Chris@16 22 #include <climits> // for CHAR_MIN
Chris@16 23 #include <boost/detail/workaround.hpp>
Chris@16 24
Chris@16 25 #ifdef BOOST_MSVC
Chris@16 26 #pragma warning(push)
Chris@16 27 #pragma warning(disable:4127 4244) // Conditional expression is constant
Chris@16 28 #endif
Chris@16 29
Chris@16 30 namespace boost
Chris@16 31 {
Chris@16 32 namespace math
Chris@16 33 {
Chris@16 34
Chris@16 35
Chris@16 36 // Forward declarations for function templates -----------------------------//
Chris@16 37
Chris@16 38 template < typename IntegerType >
Chris@16 39 IntegerType gcd( IntegerType const &a, IntegerType const &b );
Chris@16 40
Chris@16 41 template < typename IntegerType >
Chris@16 42 IntegerType lcm( IntegerType const &a, IntegerType const &b );
Chris@16 43
Chris@16 44
Chris@16 45 // Greatest common divisor evaluator class declaration ---------------------//
Chris@16 46
Chris@16 47 template < typename IntegerType >
Chris@16 48 class gcd_evaluator
Chris@16 49 {
Chris@16 50 public:
Chris@16 51 // Types
Chris@16 52 typedef IntegerType result_type, first_argument_type, second_argument_type;
Chris@16 53
Chris@16 54 // Function object interface
Chris@16 55 result_type operator ()( first_argument_type const &a,
Chris@16 56 second_argument_type const &b ) const;
Chris@16 57
Chris@16 58 }; // boost::math::gcd_evaluator
Chris@16 59
Chris@16 60
Chris@16 61 // Least common multiple evaluator class declaration -----------------------//
Chris@16 62
Chris@16 63 template < typename IntegerType >
Chris@16 64 class lcm_evaluator
Chris@16 65 {
Chris@16 66 public:
Chris@16 67 // Types
Chris@16 68 typedef IntegerType result_type, first_argument_type, second_argument_type;
Chris@16 69
Chris@16 70 // Function object interface
Chris@16 71 result_type operator ()( first_argument_type const &a,
Chris@16 72 second_argument_type const &b ) const;
Chris@16 73
Chris@16 74 }; // boost::math::lcm_evaluator
Chris@16 75
Chris@16 76
Chris@16 77 // Implementation details --------------------------------------------------//
Chris@16 78
Chris@16 79 namespace detail
Chris@16 80 {
Chris@16 81 // Greatest common divisor for rings (including unsigned integers)
Chris@16 82 template < typename RingType >
Chris@16 83 RingType
Chris@16 84 gcd_euclidean
Chris@16 85 (
Chris@16 86 RingType a,
Chris@16 87 RingType b
Chris@16 88 )
Chris@16 89 {
Chris@16 90 // Avoid repeated construction
Chris@16 91 #ifndef __BORLANDC__
Chris@16 92 RingType const zero = static_cast<RingType>( 0 );
Chris@16 93 #else
Chris@16 94 RingType zero = static_cast<RingType>( 0 );
Chris@16 95 #endif
Chris@16 96
Chris@16 97 // Reduce by GCD-remainder property [GCD(a,b) == GCD(b,a MOD b)]
Chris@16 98 while ( true )
Chris@16 99 {
Chris@16 100 if ( a == zero )
Chris@16 101 return b;
Chris@16 102 b %= a;
Chris@16 103
Chris@16 104 if ( b == zero )
Chris@16 105 return a;
Chris@16 106 a %= b;
Chris@16 107 }
Chris@16 108 }
Chris@16 109
Chris@16 110 // Greatest common divisor for (signed) integers
Chris@16 111 template < typename IntegerType >
Chris@16 112 inline
Chris@16 113 IntegerType
Chris@16 114 gcd_integer
Chris@16 115 (
Chris@16 116 IntegerType const & a,
Chris@16 117 IntegerType const & b
Chris@16 118 )
Chris@16 119 {
Chris@16 120 // Avoid repeated construction
Chris@16 121 IntegerType const zero = static_cast<IntegerType>( 0 );
Chris@16 122 IntegerType const result = gcd_euclidean( a, b );
Chris@16 123
Chris@16 124 return ( result < zero ) ? static_cast<IntegerType>(-result) : result;
Chris@16 125 }
Chris@16 126
Chris@16 127 // Greatest common divisor for unsigned binary integers
Chris@16 128 template < typename BuiltInUnsigned >
Chris@16 129 BuiltInUnsigned
Chris@16 130 gcd_binary
Chris@16 131 (
Chris@16 132 BuiltInUnsigned u,
Chris@16 133 BuiltInUnsigned v
Chris@16 134 )
Chris@16 135 {
Chris@16 136 if ( u && v )
Chris@16 137 {
Chris@16 138 // Shift out common factors of 2
Chris@16 139 unsigned shifts = 0;
Chris@16 140
Chris@16 141 while ( !(u & 1u) && !(v & 1u) )
Chris@16 142 {
Chris@16 143 ++shifts;
Chris@16 144 u >>= 1;
Chris@16 145 v >>= 1;
Chris@16 146 }
Chris@16 147
Chris@16 148 // Start with the still-even one, if any
Chris@16 149 BuiltInUnsigned r[] = { u, v };
Chris@16 150 unsigned which = static_cast<bool>( u & 1u );
Chris@16 151
Chris@16 152 // Whittle down the values via their differences
Chris@16 153 do
Chris@16 154 {
Chris@16 155 #if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x582))
Chris@16 156 while ( !(r[ which ] & 1u) )
Chris@16 157 {
Chris@16 158 r[ which ] = (r[which] >> 1);
Chris@16 159 }
Chris@16 160 #else
Chris@16 161 // Remove factors of two from the even one
Chris@16 162 while ( !(r[ which ] & 1u) )
Chris@16 163 {
Chris@16 164 r[ which ] >>= 1;
Chris@16 165 }
Chris@16 166 #endif
Chris@16 167
Chris@16 168 // Replace the larger of the two with their difference
Chris@16 169 if ( r[!which] > r[which] )
Chris@16 170 {
Chris@16 171 which ^= 1u;
Chris@16 172 }
Chris@16 173
Chris@16 174 r[ which ] -= r[ !which ];
Chris@16 175 }
Chris@16 176 while ( r[which] );
Chris@16 177
Chris@16 178 // Shift-in the common factor of 2 to the residues' GCD
Chris@16 179 return r[ !which ] << shifts;
Chris@16 180 }
Chris@16 181 else
Chris@16 182 {
Chris@16 183 // At least one input is zero, return the other
Chris@16 184 // (adding since zero is the additive identity)
Chris@16 185 // or zero if both are zero.
Chris@16 186 return u + v;
Chris@16 187 }
Chris@16 188 }
Chris@16 189
Chris@16 190 // Least common multiple for rings (including unsigned integers)
Chris@16 191 template < typename RingType >
Chris@16 192 inline
Chris@16 193 RingType
Chris@16 194 lcm_euclidean
Chris@16 195 (
Chris@16 196 RingType const & a,
Chris@16 197 RingType const & b
Chris@16 198 )
Chris@16 199 {
Chris@16 200 RingType const zero = static_cast<RingType>( 0 );
Chris@16 201 RingType const temp = gcd_euclidean( a, b );
Chris@16 202
Chris@16 203 return ( temp != zero ) ? ( a / temp * b ) : zero;
Chris@16 204 }
Chris@16 205
Chris@16 206 // Least common multiple for (signed) integers
Chris@16 207 template < typename IntegerType >
Chris@16 208 inline
Chris@16 209 IntegerType
Chris@16 210 lcm_integer
Chris@16 211 (
Chris@16 212 IntegerType const & a,
Chris@16 213 IntegerType const & b
Chris@16 214 )
Chris@16 215 {
Chris@16 216 // Avoid repeated construction
Chris@16 217 IntegerType const zero = static_cast<IntegerType>( 0 );
Chris@16 218 IntegerType const result = lcm_euclidean( a, b );
Chris@16 219
Chris@16 220 return ( result < zero ) ? static_cast<IntegerType>(-result) : result;
Chris@16 221 }
Chris@16 222
Chris@16 223 // Function objects to find the best way of computing GCD or LCM
Chris@16 224 #ifndef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS
Chris@16 225 template < typename T, bool IsSpecialized, bool IsSigned >
Chris@16 226 struct gcd_optimal_evaluator_helper_t
Chris@16 227 {
Chris@16 228 T operator ()( T const &a, T const &b )
Chris@16 229 {
Chris@16 230 return gcd_euclidean( a, b );
Chris@16 231 }
Chris@16 232 };
Chris@16 233
Chris@16 234 template < typename T >
Chris@16 235 struct gcd_optimal_evaluator_helper_t< T, true, true >
Chris@16 236 {
Chris@16 237 T operator ()( T const &a, T const &b )
Chris@16 238 {
Chris@16 239 return gcd_integer( a, b );
Chris@16 240 }
Chris@16 241 };
Chris@16 242
Chris@16 243 template < typename T >
Chris@16 244 struct gcd_optimal_evaluator
Chris@16 245 {
Chris@16 246 T operator ()( T const &a, T const &b )
Chris@16 247 {
Chris@16 248 typedef ::std::numeric_limits<T> limits_type;
Chris@16 249
Chris@16 250 typedef gcd_optimal_evaluator_helper_t<T,
Chris@16 251 limits_type::is_specialized, limits_type::is_signed> helper_type;
Chris@16 252
Chris@16 253 helper_type solver;
Chris@16 254
Chris@16 255 return solver( a, b );
Chris@16 256 }
Chris@16 257 };
Chris@16 258 #else // BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS
Chris@16 259 template < typename T >
Chris@16 260 struct gcd_optimal_evaluator
Chris@16 261 {
Chris@16 262 T operator ()( T const &a, T const &b )
Chris@16 263 {
Chris@16 264 return gcd_integer( a, b );
Chris@16 265 }
Chris@16 266 };
Chris@16 267 #endif
Chris@16 268
Chris@16 269 // Specialize for the built-in integers
Chris@16 270 #define BOOST_PRIVATE_GCD_UF( Ut ) \
Chris@16 271 template < > struct gcd_optimal_evaluator<Ut> \
Chris@16 272 { Ut operator ()( Ut a, Ut b ) const { return gcd_binary( a, b ); } }
Chris@16 273
Chris@16 274 BOOST_PRIVATE_GCD_UF( unsigned char );
Chris@16 275 BOOST_PRIVATE_GCD_UF( unsigned short );
Chris@16 276 BOOST_PRIVATE_GCD_UF( unsigned );
Chris@16 277 BOOST_PRIVATE_GCD_UF( unsigned long );
Chris@16 278
Chris@16 279 #ifdef BOOST_HAS_LONG_LONG
Chris@16 280 BOOST_PRIVATE_GCD_UF( boost::ulong_long_type );
Chris@16 281 #elif defined(BOOST_HAS_MS_INT64)
Chris@16 282 BOOST_PRIVATE_GCD_UF( unsigned __int64 );
Chris@16 283 #endif
Chris@16 284
Chris@16 285 #if CHAR_MIN == 0
Chris@16 286 BOOST_PRIVATE_GCD_UF( char ); // char is unsigned
Chris@16 287 #endif
Chris@16 288
Chris@16 289 #undef BOOST_PRIVATE_GCD_UF
Chris@16 290
Chris@16 291 #define BOOST_PRIVATE_GCD_SF( St, Ut ) \
Chris@16 292 template < > struct gcd_optimal_evaluator<St> \
Chris@16 293 { St operator ()( St a, St b ) const { Ut const a_abs = \
Chris@16 294 static_cast<Ut>( a < 0 ? -a : +a ), b_abs = static_cast<Ut>( \
Chris@16 295 b < 0 ? -b : +b ); return static_cast<St>( \
Chris@16 296 gcd_optimal_evaluator<Ut>()(a_abs, b_abs) ); } }
Chris@16 297
Chris@16 298 BOOST_PRIVATE_GCD_SF( signed char, unsigned char );
Chris@16 299 BOOST_PRIVATE_GCD_SF( short, unsigned short );
Chris@16 300 BOOST_PRIVATE_GCD_SF( int, unsigned );
Chris@16 301 BOOST_PRIVATE_GCD_SF( long, unsigned long );
Chris@16 302
Chris@16 303 #if CHAR_MIN < 0
Chris@16 304 BOOST_PRIVATE_GCD_SF( char, unsigned char ); // char is signed
Chris@16 305 #endif
Chris@16 306
Chris@16 307 #ifdef BOOST_HAS_LONG_LONG
Chris@16 308 BOOST_PRIVATE_GCD_SF( boost::long_long_type, boost::ulong_long_type );
Chris@16 309 #elif defined(BOOST_HAS_MS_INT64)
Chris@16 310 BOOST_PRIVATE_GCD_SF( __int64, unsigned __int64 );
Chris@16 311 #endif
Chris@16 312
Chris@16 313 #undef BOOST_PRIVATE_GCD_SF
Chris@16 314
Chris@16 315 #ifndef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS
Chris@16 316 template < typename T, bool IsSpecialized, bool IsSigned >
Chris@16 317 struct lcm_optimal_evaluator_helper_t
Chris@16 318 {
Chris@16 319 T operator ()( T const &a, T const &b )
Chris@16 320 {
Chris@16 321 return lcm_euclidean( a, b );
Chris@16 322 }
Chris@16 323 };
Chris@16 324
Chris@16 325 template < typename T >
Chris@16 326 struct lcm_optimal_evaluator_helper_t< T, true, true >
Chris@16 327 {
Chris@16 328 T operator ()( T const &a, T const &b )
Chris@16 329 {
Chris@16 330 return lcm_integer( a, b );
Chris@16 331 }
Chris@16 332 };
Chris@16 333
Chris@16 334 template < typename T >
Chris@16 335 struct lcm_optimal_evaluator
Chris@16 336 {
Chris@16 337 T operator ()( T const &a, T const &b )
Chris@16 338 {
Chris@16 339 typedef ::std::numeric_limits<T> limits_type;
Chris@16 340
Chris@16 341 typedef lcm_optimal_evaluator_helper_t<T,
Chris@16 342 limits_type::is_specialized, limits_type::is_signed> helper_type;
Chris@16 343
Chris@16 344 helper_type solver;
Chris@16 345
Chris@16 346 return solver( a, b );
Chris@16 347 }
Chris@16 348 };
Chris@16 349 #else // BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS
Chris@16 350 template < typename T >
Chris@16 351 struct lcm_optimal_evaluator
Chris@16 352 {
Chris@16 353 T operator ()( T const &a, T const &b )
Chris@16 354 {
Chris@16 355 return lcm_integer( a, b );
Chris@16 356 }
Chris@16 357 };
Chris@16 358 #endif
Chris@16 359
Chris@16 360 // Functions to find the GCD or LCM in the best way
Chris@16 361 template < typename T >
Chris@16 362 inline
Chris@16 363 T
Chris@16 364 gcd_optimal
Chris@16 365 (
Chris@16 366 T const & a,
Chris@16 367 T const & b
Chris@16 368 )
Chris@16 369 {
Chris@16 370 gcd_optimal_evaluator<T> solver;
Chris@16 371
Chris@16 372 return solver( a, b );
Chris@16 373 }
Chris@16 374
Chris@16 375 template < typename T >
Chris@16 376 inline
Chris@16 377 T
Chris@16 378 lcm_optimal
Chris@16 379 (
Chris@16 380 T const & a,
Chris@16 381 T const & b
Chris@16 382 )
Chris@16 383 {
Chris@16 384 lcm_optimal_evaluator<T> solver;
Chris@16 385
Chris@16 386 return solver( a, b );
Chris@16 387 }
Chris@16 388
Chris@16 389 } // namespace detail
Chris@16 390
Chris@16 391
Chris@16 392 // Greatest common divisor evaluator member function definition ------------//
Chris@16 393
Chris@16 394 template < typename IntegerType >
Chris@16 395 inline
Chris@16 396 typename gcd_evaluator<IntegerType>::result_type
Chris@16 397 gcd_evaluator<IntegerType>::operator ()
Chris@16 398 (
Chris@16 399 first_argument_type const & a,
Chris@16 400 second_argument_type const & b
Chris@16 401 ) const
Chris@16 402 {
Chris@16 403 return detail::gcd_optimal( a, b );
Chris@16 404 }
Chris@16 405
Chris@16 406
Chris@16 407 // Least common multiple evaluator member function definition --------------//
Chris@16 408
Chris@16 409 template < typename IntegerType >
Chris@16 410 inline
Chris@16 411 typename lcm_evaluator<IntegerType>::result_type
Chris@16 412 lcm_evaluator<IntegerType>::operator ()
Chris@16 413 (
Chris@16 414 first_argument_type const & a,
Chris@16 415 second_argument_type const & b
Chris@16 416 ) const
Chris@16 417 {
Chris@16 418 return detail::lcm_optimal( a, b );
Chris@16 419 }
Chris@16 420
Chris@16 421
Chris@16 422 // Greatest common divisor and least common multiple function definitions --//
Chris@16 423
Chris@16 424 template < typename IntegerType >
Chris@16 425 inline
Chris@16 426 IntegerType
Chris@16 427 gcd
Chris@16 428 (
Chris@16 429 IntegerType const & a,
Chris@16 430 IntegerType const & b
Chris@16 431 )
Chris@16 432 {
Chris@16 433 gcd_evaluator<IntegerType> solver;
Chris@16 434
Chris@16 435 return solver( a, b );
Chris@16 436 }
Chris@16 437
Chris@16 438 template < typename IntegerType >
Chris@16 439 inline
Chris@16 440 IntegerType
Chris@16 441 lcm
Chris@16 442 (
Chris@16 443 IntegerType const & a,
Chris@16 444 IntegerType const & b
Chris@16 445 )
Chris@16 446 {
Chris@16 447 lcm_evaluator<IntegerType> solver;
Chris@16 448
Chris@16 449 return solver( a, b );
Chris@16 450 }
Chris@16 451
Chris@16 452
Chris@16 453 } // namespace math
Chris@16 454 } // namespace boost
Chris@16 455
Chris@16 456 #ifdef BOOST_MSVC
Chris@16 457 #pragma warning(pop)
Chris@16 458 #endif
Chris@16 459
Chris@16 460 #endif // BOOST_MATH_COMMON_FACTOR_RT_HPP