common_factor_test.cpp 29 KB

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