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