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