1 // Boost GCD & LCM common_factor.hpp test program --------------------------//
2
3 // (C) Copyright Daryle Walker 2001, 2006.
4 // Distributed under the Boost Software License, Version 1.0. (See
5 // accompanying file LICENSE_1_0.txt or copy at
6 // http://www.boost.org/LICENSE_1_0.txt)
7
8 // See http://www.boost.org for most recent version including documentation.
9
10 // Revision History
11 // 01 Dec 2006 Various fixes for old compilers (Joaquin M Lopez Munoz)
12 // 10 Nov 2006 Make long long and __int64 mutually exclusive (Daryle Walker)
13 // 04 Nov 2006 Use more built-in numeric types, binary-GCD (Daryle Walker)
14 // 03 Nov 2006 Use custom numeric types (Daryle Walker)
15 // 02 Nov 2006 Change to Boost.Test's unit test system (Daryle Walker)
16 // 07 Nov 2001 Initial version (Daryle Walker)
17
18 #define BOOST_TEST_MAIN "Boost.Math GCD & LCM unit tests"
19
20 #include <boost/integer/common_factor.hpp>
21
22 #include <boost/config.hpp> // for BOOST_MSVC, etc.
23 #include <boost/detail/workaround.hpp>
24 #include <boost/operators.hpp>
25 #include <boost/core/lightweight_test.hpp>
26
27 #include <istream> // for std::basic_istream
28 #include <limits> // for std::numeric_limits
29 #include <ostream> // for std::basic_ostream
30
31
32 namespace {
33
34 // TODO: add polynominal/non-real type; especially after any switch to the
35 // binary-GCD algorithm for built-in types
36
37 // Custom integer class (template)
38 template < typename IntType, int ID = 0 >
39 class my_wrapped_integer
40 : private ::boost::shiftable1<my_wrapped_integer<IntType, ID>,
41 ::boost::operators<my_wrapped_integer<IntType, ID> > >
42 {
43 // Helper type-aliases
44 typedef my_wrapped_integer self_type;
45 typedef IntType self_type::* bool_type;
46
47 // Member data
48 IntType v_;
49
50 public:
51 // Template parameters
52 typedef IntType int_type;
53
54 BOOST_STATIC_CONSTANT(int,id = ID);
55
56 // Lifetime management (use automatic destructor and copy constructor)
my_wrapped_integer(int_type const & v=int_type ())57 my_wrapped_integer( int_type const &v = int_type() ) : v_( v ) {}
58
59 // Accessors
value() const60 int_type value() const { return this->v_; }
61
62 // Operators (use automatic copy assignment)
operator bool_type() const63 operator bool_type() const { return this->v_ ? &self_type::v_ : 0; }
64
operator ++()65 self_type & operator ++() { ++this->v_; return *this; }
operator --()66 self_type & operator --() { --this->v_; return *this; }
67
operator ~() const68 self_type operator ~() const { return self_type( ~this->v_ ); }
operator !() const69 self_type operator !() const { return self_type( !this->v_ ); }
operator +() const70 self_type operator +() const { return self_type( +this->v_ ); }
operator -() const71 self_type operator -() const { return self_type( -this->v_ ); }
72
operator <(self_type const & r) const73 bool operator <( self_type const &r ) const { return this->v_ < r.v_; }
operator ==(self_type const & r) const74 bool operator ==( self_type const &r ) const { return this->v_ == r.v_; }
75
operator *=(self_type const & r)76 self_type &operator *=(self_type const &r) {this->v_ *= r.v_; return *this;}
operator /=(self_type const & r)77 self_type &operator /=(self_type const &r) {this->v_ /= r.v_; return *this;}
operator %=(self_type const & r)78 self_type &operator %=(self_type const &r) {this->v_ %= r.v_; return *this;}
operator +=(self_type const & r)79 self_type &operator +=(self_type const &r) {this->v_ += r.v_; return *this;}
operator -=(self_type const & r)80 self_type &operator -=(self_type const &r) {this->v_ -= r.v_; return *this;}
operator <<=(self_type const & r)81 self_type &operator<<=(self_type const &r){this->v_ <<= r.v_; return *this;}
operator >>=(self_type const & r)82 self_type &operator>>=(self_type const &r){this->v_ >>= r.v_; return *this;}
operator &=(self_type const & r)83 self_type &operator &=(self_type const &r) {this->v_ &= r.v_; return *this;}
operator |=(self_type const & r)84 self_type &operator |=(self_type const &r) {this->v_ |= r.v_; return *this;}
operator ^=(self_type const & r)85 self_type &operator ^=(self_type const &r) {this->v_ ^= r.v_; return *this;}
86
87 // Input & output
operator >>(std::istream & i,self_type & x)88 friend std::istream & operator >>( std::istream &i, self_type &x )
89 { return i >> x.v_; }
90
operator <<(std::ostream & o,self_type const & x)91 friend std::ostream & operator <<( std::ostream &o, self_type const &x )
92 { return o << x.v_; }
93
94 }; // my_wrapped_integer
95
96 template < typename IntType, int ID >
abs(my_wrapped_integer<IntType,ID> const & x)97 my_wrapped_integer<IntType, ID> abs( my_wrapped_integer<IntType, ID> const &x )
98 { return ( x < my_wrapped_integer<IntType, ID>(0) ) ? -x : +x; }
99
100 typedef my_wrapped_integer<int> MyInt1;
101 typedef my_wrapped_integer<unsigned> MyUnsigned1;
102 typedef my_wrapped_integer<int, 1> MyInt2;
103 typedef my_wrapped_integer<unsigned, 1> MyUnsigned2;
104
105 // Without these explicit instantiations, MSVC++ 6.5/7.0 does not find
106 // some friend operators in certain contexts.
107 MyInt1 dummy1;
108 MyUnsigned1 dummy2;
109 MyInt2 dummy3;
110 MyUnsigned2 dummy4;
111
112 } // namespace
113
114 #define BOOST_NO_MACRO_EXPAND /**/
115
116 // Specialize numeric_limits for _some_ of our types
117 namespace std
118 {
119
120 template < >
121 class numeric_limits< MyInt1 >
122 {
123 typedef MyInt1::int_type int_type;
124 typedef numeric_limits<int_type> limits_type;
125
126 public:
127 BOOST_STATIC_CONSTANT(bool, is_specialized = limits_type::is_specialized);
128
BOOST_NO_MACRO_EXPAND()129 static MyInt1 min BOOST_NO_MACRO_EXPAND() throw() { return (limits_type::min)(); }
BOOST_NO_MACRO_EXPAND()130 static MyInt1 max BOOST_NO_MACRO_EXPAND() throw() { return (limits_type::max)(); }
131
132 BOOST_STATIC_CONSTANT(int, digits = limits_type::digits);
133 BOOST_STATIC_CONSTANT(int, digits10 = limits_type::digits10);
134 #ifndef BOOST_NO_CXX11_NUMERIC_LIMITS
135 BOOST_STATIC_CONSTANT(int, max_digits10 = limits_type::max_digits10);
136 #endif
137 BOOST_STATIC_CONSTANT(bool, is_signed = limits_type::is_signed);
138 BOOST_STATIC_CONSTANT(bool, is_integer = limits_type::is_integer);
139 BOOST_STATIC_CONSTANT(bool, is_exact = limits_type::is_exact);
140 BOOST_STATIC_CONSTANT(int, radix = limits_type::radix);
epsilon()141 static MyInt1 epsilon() throw() { return limits_type::epsilon(); }
round_error()142 static MyInt1 round_error() throw() { return limits_type::round_error(); }
143
144 BOOST_STATIC_CONSTANT(int, min_exponent = limits_type::min_exponent);
145 BOOST_STATIC_CONSTANT(int, min_exponent10 = limits_type::min_exponent10);
146 BOOST_STATIC_CONSTANT(int, max_exponent = limits_type::max_exponent);
147 BOOST_STATIC_CONSTANT(int, max_exponent10 = limits_type::max_exponent10);
148
149 BOOST_STATIC_CONSTANT(bool, has_infinity = limits_type::has_infinity);
150 BOOST_STATIC_CONSTANT(bool, has_quiet_NaN = limits_type::has_quiet_NaN);
151 BOOST_STATIC_CONSTANT(bool, has_signaling_NaN = limits_type::has_signaling_NaN);
152 BOOST_STATIC_CONSTANT(float_denorm_style, has_denorm = limits_type::has_denorm);
153 BOOST_STATIC_CONSTANT(bool, has_denorm_loss = limits_type::has_denorm_loss);
154
infinity()155 static MyInt1 infinity() throw() { return limits_type::infinity(); }
quiet_NaN()156 static MyInt1 quiet_NaN() throw() { return limits_type::quiet_NaN(); }
signaling_NaN()157 static MyInt1 signaling_NaN() throw() {return limits_type::signaling_NaN();}
denorm_min()158 static MyInt1 denorm_min() throw() { return limits_type::denorm_min(); }
159
160 BOOST_STATIC_CONSTANT(bool, is_iec559 = limits_type::is_iec559);
161 BOOST_STATIC_CONSTANT(bool, is_bounded = limits_type::is_bounded);
162 BOOST_STATIC_CONSTANT(bool, is_modulo = limits_type::is_modulo);
163
164 BOOST_STATIC_CONSTANT(bool, traps = limits_type::traps);
165 BOOST_STATIC_CONSTANT(bool, tinyness_before = limits_type::tinyness_before);
166 BOOST_STATIC_CONSTANT(float_round_style, round_style = limits_type::round_style);
167
168 }; // std::numeric_limits<MyInt1>
169
170 template < >
171 class numeric_limits< MyUnsigned1 >
172 {
173 typedef MyUnsigned1::int_type int_type;
174 typedef numeric_limits<int_type> limits_type;
175
176 public:
177 BOOST_STATIC_CONSTANT(bool, is_specialized = limits_type::is_specialized);
178
BOOST_NO_MACRO_EXPAND()179 static MyUnsigned1 min BOOST_NO_MACRO_EXPAND() throw() { return (limits_type::min)(); }
BOOST_NO_MACRO_EXPAND()180 static MyUnsigned1 max BOOST_NO_MACRO_EXPAND() throw() { return (limits_type::max)(); }
181
182 BOOST_STATIC_CONSTANT(int, digits = limits_type::digits);
183 BOOST_STATIC_CONSTANT(int, digits10 = limits_type::digits10);
184 #ifndef BOOST_NO_CXX11_NUMERIC_LIMITS
185 BOOST_STATIC_CONSTANT(int, max_digits10 = limits_type::max_digits10);
186 #endif
187 BOOST_STATIC_CONSTANT(bool, is_signed = limits_type::is_signed);
188 BOOST_STATIC_CONSTANT(bool, is_integer = limits_type::is_integer);
189 BOOST_STATIC_CONSTANT(bool, is_exact = limits_type::is_exact);
190 BOOST_STATIC_CONSTANT(int, radix = limits_type::radix);
epsilon()191 static MyUnsigned1 epsilon() throw() { return limits_type::epsilon(); }
round_error()192 static MyUnsigned1 round_error() throw(){return limits_type::round_error();}
193
194 BOOST_STATIC_CONSTANT(int, min_exponent = limits_type::min_exponent);
195 BOOST_STATIC_CONSTANT(int, min_exponent10 = limits_type::min_exponent10);
196 BOOST_STATIC_CONSTANT(int, max_exponent = limits_type::max_exponent);
197 BOOST_STATIC_CONSTANT(int, max_exponent10 = limits_type::max_exponent10);
198
199 BOOST_STATIC_CONSTANT(bool, has_infinity = limits_type::has_infinity);
200 BOOST_STATIC_CONSTANT(bool, has_quiet_NaN = limits_type::has_quiet_NaN);
201 BOOST_STATIC_CONSTANT(bool, has_signaling_NaN = limits_type::has_signaling_NaN);
202 BOOST_STATIC_CONSTANT(float_denorm_style, has_denorm = limits_type::has_denorm);
203 BOOST_STATIC_CONSTANT(bool, has_denorm_loss = limits_type::has_denorm_loss);
204
infinity()205 static MyUnsigned1 infinity() throw() { return limits_type::infinity(); }
quiet_NaN()206 static MyUnsigned1 quiet_NaN() throw() { return limits_type::quiet_NaN(); }
signaling_NaN()207 static MyUnsigned1 signaling_NaN() throw()
208 { return limits_type::signaling_NaN(); }
denorm_min()209 static MyUnsigned1 denorm_min() throw(){ return limits_type::denorm_min(); }
210
211 BOOST_STATIC_CONSTANT(bool, is_iec559 = limits_type::is_iec559);
212 BOOST_STATIC_CONSTANT(bool, is_bounded = limits_type::is_bounded);
213 BOOST_STATIC_CONSTANT(bool, is_modulo = limits_type::is_modulo);
214
215 BOOST_STATIC_CONSTANT(bool, traps = limits_type::traps);
216 BOOST_STATIC_CONSTANT(bool, tinyness_before = limits_type::tinyness_before);
217 BOOST_STATIC_CONSTANT(float_round_style, round_style = limits_type::round_style);
218
219 }; // std::numeric_limits<MyUnsigned1>
220
221 #if BOOST_WORKAROUND(BOOST_MSVC,<1300)
222 // MSVC 6.0 lacks operator<< for __int64, see
223 // http://support.microsoft.com/default.aspx?scid=kb;en-us;168440
224
operator <<(ostream & os,__int64 i)225 inline ostream& operator<<(ostream& os, __int64 i)
226 {
227 char buf[20];
228 sprintf(buf,"%I64d", i);
229 os << buf;
230 return os;
231 }
232
operator <<(ostream & os,unsigned __int64 i)233 inline ostream& operator<<(ostream& os, unsigned __int64 i)
234 {
235 char buf[20];
236 sprintf(buf,"%I64u", i);
237 os << buf;
238 return os;
239 }
240 #endif
241
242 } // namespace std
243
244 // GCD tests
245
246 // GCD on signed integer types
gcd_int_test()247 template< class T > void gcd_int_test() // signed_test_types
248 {
249 using boost::integer::gcd;
250
251 // Originally from Boost.Rational tests
252 BOOST_TEST_EQ( gcd<T>( 1, -1), static_cast<T>( 1) );
253 BOOST_TEST_EQ( gcd<T>( -1, 1), static_cast<T>( 1) );
254 BOOST_TEST_EQ( gcd<T>( 1, 1), static_cast<T>( 1) );
255 BOOST_TEST_EQ( gcd<T>( -1, -1), static_cast<T>( 1) );
256 BOOST_TEST_EQ( gcd<T>( 0, 0), static_cast<T>( 0) );
257 BOOST_TEST_EQ( gcd<T>( 7, 0), static_cast<T>( 7) );
258 BOOST_TEST_EQ( gcd<T>( 0, 9), static_cast<T>( 9) );
259 BOOST_TEST_EQ( gcd<T>( -7, 0), static_cast<T>( 7) );
260 BOOST_TEST_EQ( gcd<T>( 0, -9), static_cast<T>( 9) );
261 BOOST_TEST_EQ( gcd<T>( 42, 30), static_cast<T>( 6) );
262 BOOST_TEST_EQ( gcd<T>( 6, -9), static_cast<T>( 3) );
263 BOOST_TEST_EQ( gcd<T>(-10, -10), static_cast<T>(10) );
264 BOOST_TEST_EQ( gcd<T>(-25, -10), static_cast<T>( 5) );
265 BOOST_TEST_EQ( gcd<T>( 3, 7), static_cast<T>( 1) );
266 BOOST_TEST_EQ( gcd<T>( 8, 9), static_cast<T>( 1) );
267 BOOST_TEST_EQ( gcd<T>( 7, 49), static_cast<T>( 7) );
268 }
269
270 // GCD on unmarked signed integer type
gcd_unmarked_int_test()271 void gcd_unmarked_int_test()
272 {
273 using boost::integer::gcd;
274
275 // The regular signed-integer GCD function performs the unsigned version,
276 // then does an absolute-value on the result. Signed types that are not
277 // marked as such (due to no std::numeric_limits specialization) may be off
278 // by a sign.
279 BOOST_TEST_EQ( abs(gcd<MyInt2>( 1, -1 )), MyInt2( 1) );
280 BOOST_TEST_EQ( abs(gcd<MyInt2>( -1, 1 )), MyInt2( 1) );
281 BOOST_TEST_EQ( abs(gcd<MyInt2>( 1, 1 )), MyInt2( 1) );
282 BOOST_TEST_EQ( abs(gcd<MyInt2>( -1, -1 )), MyInt2( 1) );
283 BOOST_TEST_EQ( abs(gcd<MyInt2>( 0, 0 )), MyInt2( 0) );
284 BOOST_TEST_EQ( abs(gcd<MyInt2>( 7, 0 )), MyInt2( 7) );
285 BOOST_TEST_EQ( abs(gcd<MyInt2>( 0, 9 )), MyInt2( 9) );
286 BOOST_TEST_EQ( abs(gcd<MyInt2>( -7, 0 )), MyInt2( 7) );
287 BOOST_TEST_EQ( abs(gcd<MyInt2>( 0, -9 )), MyInt2( 9) );
288 BOOST_TEST_EQ( abs(gcd<MyInt2>( 42, 30 )), MyInt2( 6) );
289 BOOST_TEST_EQ( abs(gcd<MyInt2>( 6, -9 )), MyInt2( 3) );
290 BOOST_TEST_EQ( abs(gcd<MyInt2>( -10, -10 )), MyInt2(10) );
291 BOOST_TEST_EQ( abs(gcd<MyInt2>( -25, -10 )), MyInt2( 5) );
292 BOOST_TEST_EQ( abs(gcd<MyInt2>( 3, 7 )), MyInt2( 1) );
293 BOOST_TEST_EQ( abs(gcd<MyInt2>( 8, 9 )), MyInt2( 1) );
294 BOOST_TEST_EQ( abs(gcd<MyInt2>( 7, 49 )), MyInt2( 7) );
295 }
296
297 // GCD on unsigned integer types
gcd_unsigned_test()298 template< class T > void gcd_unsigned_test() // unsigned_test_types
299 {
300 using boost::integer::gcd;
301
302 // Note that unmarked types (i.e. have no std::numeric_limits
303 // specialization) are treated like non/unsigned types
304 BOOST_TEST_EQ( gcd<T>( 1u, 1u), static_cast<T>( 1u) );
305 BOOST_TEST_EQ( gcd<T>( 0u, 0u), static_cast<T>( 0u) );
306 BOOST_TEST_EQ( gcd<T>( 7u, 0u), static_cast<T>( 7u) );
307 BOOST_TEST_EQ( gcd<T>( 0u, 9u), static_cast<T>( 9u) );
308 BOOST_TEST_EQ( gcd<T>(42u, 30u), static_cast<T>( 6u) );
309 BOOST_TEST_EQ( gcd<T>( 3u, 7u), static_cast<T>( 1u) );
310 BOOST_TEST_EQ( gcd<T>( 8u, 9u), static_cast<T>( 1u) );
311 BOOST_TEST_EQ( gcd<T>( 7u, 49u), static_cast<T>( 7u) );
312 }
313
314 // GCD at compile-time
gcd_static_test()315 void gcd_static_test()
316 {
317 using boost::integer::static_gcd;
318
319 BOOST_TEST_EQ( (static_gcd< 1, 1>::value), 1 );
320 BOOST_TEST_EQ( (static_gcd< 0, 0>::value), 0 );
321 BOOST_TEST_EQ( (static_gcd< 7, 0>::value), 7 );
322 BOOST_TEST_EQ( (static_gcd< 0, 9>::value), 9 );
323 BOOST_TEST_EQ( (static_gcd<42, 30>::value), 6 );
324 BOOST_TEST_EQ( (static_gcd< 3, 7>::value), 1 );
325 BOOST_TEST_EQ( (static_gcd< 8, 9>::value), 1 );
326 BOOST_TEST_EQ( (static_gcd< 7, 49>::value), 7 );
327 }
328
329 // TODO: non-built-in signed and unsigned integer tests, with and without
330 // numeric_limits specialization; polynominal tests; note any changes if
331 // built-ins switch to binary-GCD algorithm
332
333
334 // LCM tests
335
336 // LCM on signed integer types
lcm_int_test()337 template< class T > void lcm_int_test() // signed_test_types
338 {
339 using boost::integer::lcm;
340
341 // Originally from Boost.Rational tests
342 BOOST_TEST_EQ( lcm<T>( 1, -1), static_cast<T>( 1) );
343 BOOST_TEST_EQ( lcm<T>( -1, 1), static_cast<T>( 1) );
344 BOOST_TEST_EQ( lcm<T>( 1, 1), static_cast<T>( 1) );
345 BOOST_TEST_EQ( lcm<T>( -1, -1), static_cast<T>( 1) );
346 BOOST_TEST_EQ( lcm<T>( 0, 0), static_cast<T>( 0) );
347 BOOST_TEST_EQ( lcm<T>( 6, 0), static_cast<T>( 0) );
348 BOOST_TEST_EQ( lcm<T>( 0, 7), static_cast<T>( 0) );
349 BOOST_TEST_EQ( lcm<T>( -5, 0), static_cast<T>( 0) );
350 BOOST_TEST_EQ( lcm<T>( 0, -4), static_cast<T>( 0) );
351 BOOST_TEST_EQ( lcm<T>( 18, 30), static_cast<T>(90) );
352 BOOST_TEST_EQ( lcm<T>( -6, 9), static_cast<T>(18) );
353 BOOST_TEST_EQ( lcm<T>(-10, -10), static_cast<T>(10) );
354 BOOST_TEST_EQ( lcm<T>( 25, -10), static_cast<T>(50) );
355 BOOST_TEST_EQ( lcm<T>( 3, 7), static_cast<T>(21) );
356 BOOST_TEST_EQ( lcm<T>( 8, 9), static_cast<T>(72) );
357 BOOST_TEST_EQ( lcm<T>( 7, 49), static_cast<T>(49) );
358 }
359
360 // LCM on unmarked signed integer type
lcm_unmarked_int_test()361 void lcm_unmarked_int_test()
362 {
363 using boost::integer::lcm;
364
365 // The regular signed-integer LCM function performs the unsigned version,
366 // then does an absolute-value on the result. Signed types that are not
367 // marked as such (due to no std::numeric_limits specialization) may be off
368 // by a sign.
369 BOOST_TEST_EQ( abs(lcm<MyInt2>( 1, -1 )), MyInt2( 1) );
370 BOOST_TEST_EQ( abs(lcm<MyInt2>( -1, 1 )), MyInt2( 1) );
371 BOOST_TEST_EQ( abs(lcm<MyInt2>( 1, 1 )), MyInt2( 1) );
372 BOOST_TEST_EQ( abs(lcm<MyInt2>( -1, -1 )), MyInt2( 1) );
373 BOOST_TEST_EQ( abs(lcm<MyInt2>( 0, 0 )), MyInt2( 0) );
374 BOOST_TEST_EQ( abs(lcm<MyInt2>( 6, 0 )), MyInt2( 0) );
375 BOOST_TEST_EQ( abs(lcm<MyInt2>( 0, 7 )), MyInt2( 0) );
376 BOOST_TEST_EQ( abs(lcm<MyInt2>( -5, 0 )), MyInt2( 0) );
377 BOOST_TEST_EQ( abs(lcm<MyInt2>( 0, -4 )), MyInt2( 0) );
378 BOOST_TEST_EQ( abs(lcm<MyInt2>( 18, 30 )), MyInt2(90) );
379 BOOST_TEST_EQ( abs(lcm<MyInt2>( -6, 9 )), MyInt2(18) );
380 BOOST_TEST_EQ( abs(lcm<MyInt2>( -10, -10 )), MyInt2(10) );
381 BOOST_TEST_EQ( abs(lcm<MyInt2>( 25, -10 )), MyInt2(50) );
382 BOOST_TEST_EQ( abs(lcm<MyInt2>( 3, 7 )), MyInt2(21) );
383 BOOST_TEST_EQ( abs(lcm<MyInt2>( 8, 9 )), MyInt2(72) );
384 BOOST_TEST_EQ( abs(lcm<MyInt2>( 7, 49 )), MyInt2(49) );
385 }
386
387 // LCM on unsigned integer types
lcm_unsigned_test()388 template< class T > void lcm_unsigned_test() // unsigned_test_types
389 {
390 using boost::integer::lcm;
391
392 // Note that unmarked types (i.e. have no std::numeric_limits
393 // specialization) are treated like non/unsigned types
394 BOOST_TEST_EQ( lcm<T>( 1u, 1u), static_cast<T>( 1u) );
395 BOOST_TEST_EQ( lcm<T>( 0u, 0u), static_cast<T>( 0u) );
396 BOOST_TEST_EQ( lcm<T>( 6u, 0u), static_cast<T>( 0u) );
397 BOOST_TEST_EQ( lcm<T>( 0u, 7u), static_cast<T>( 0u) );
398 BOOST_TEST_EQ( lcm<T>(18u, 30u), static_cast<T>(90u) );
399 BOOST_TEST_EQ( lcm<T>( 3u, 7u), static_cast<T>(21u) );
400 BOOST_TEST_EQ( lcm<T>( 8u, 9u), static_cast<T>(72u) );
401 BOOST_TEST_EQ( lcm<T>( 7u, 49u), static_cast<T>(49u) );
402 }
403
404 // LCM at compile-time
lcm_static_test()405 void lcm_static_test()
406 {
407 using boost::integer::static_lcm;
408
409 BOOST_TEST_EQ( (static_lcm< 1, 1>::value), 1 );
410 BOOST_TEST_EQ( (static_lcm< 0, 0>::value), 0 );
411 BOOST_TEST_EQ( (static_lcm< 6, 0>::value), 0 );
412 BOOST_TEST_EQ( (static_lcm< 0, 7>::value), 0 );
413 BOOST_TEST_EQ( (static_lcm<18, 30>::value), 90 );
414 BOOST_TEST_EQ( (static_lcm< 3, 7>::value), 21 );
415 BOOST_TEST_EQ( (static_lcm< 8, 9>::value), 72 );
416 BOOST_TEST_EQ( (static_lcm< 7, 49>::value), 49 );
417 }
418
419 // TODO: see GCD to-do
420
421 // main
422
423 // Various types to test with each GCD/LCM
424
425 #define TEST_SIGNED_( test ) \
426 test<signed char>(); \
427 test<short>(); \
428 test<int>(); \
429 test<long>(); \
430 test<MyInt1>();
431
432 #ifdef BOOST_HAS_LONG_LONG
433 # define TEST_SIGNED( test ) \
434 TEST_SIGNED_( test ) \
435 test<boost::long_long_type>();
436 #elif defined(BOOST_HAS_MS_INT64)
437 # define TEST_SIGNED( test ) \
438 TEST_SIGNED_( test ) \
439 test<__int64>();
440 #endif
441
442 #define TEST_UNSIGNED_( test ) \
443 test<unsigned char>(); \
444 test<unsigned short>(); \
445 test<unsigned>(); \
446 test<unsigned long>(); \
447 test<MyUnsigned1>(); \
448 test<MyUnsigned2>();
449
450 #ifdef BOOST_HAS_LONG_LONG
451 # define TEST_UNSIGNED( test ) \
452 TEST_UNSIGNED_( test ) \
453 test<boost::ulong_long_type>();
454 #elif defined(BOOST_HAS_MS_INT64)
455 # define TEST_UNSIGNED( test ) \
456 TEST_UNSIGNED_( test ) \
457 test<unsigned __int64>();
458 #endif
459
main()460 int main()
461 {
462 TEST_SIGNED( gcd_int_test )
463 gcd_unmarked_int_test();
464 TEST_UNSIGNED( gcd_unsigned_test )
465 gcd_static_test();
466
467 TEST_SIGNED( lcm_int_test )
468 lcm_unmarked_int_test();
469 TEST_UNSIGNED( lcm_unsigned_test )
470 lcm_static_test();
471
472 return boost::report_errors();
473 }
474