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
|