rational_test.cpp 63 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608
  1. /*
  2. * A test program for boost/rational.hpp.
  3. * Change the typedef at the beginning of run_tests() to try out different
  4. * integer types. (These tests are designed only for signed integer
  5. * types. They should work for short, int and long.)
  6. *
  7. * (C) Copyright Stephen Silver, 2001. Permission to copy, use, modify, sell
  8. * and distribute this software is granted provided this copyright notice
  9. * appears in all copies. This software is provided "as is" without express or
  10. * implied warranty, and with no claim as to its suitability for any purpose.
  11. *
  12. * Incorporated into the boost rational number library, and modified and
  13. * extended, by Paul Moore, with permission.
  14. */
  15. // boostinspect:nolicense (don't complain about the lack of a Boost license)
  16. // (Stephen Silver hasn't been contacted yet for permission to change the
  17. // license. If Paul Moore's permission is also needed, then that's a problem
  18. // since he hasn't been in contact for years.)
  19. // Revision History
  20. // 30 Aug 13 Add bug-test of assignments holding the basic and/or strong
  21. // guarantees (Daryle Walker)
  22. // 27 Aug 13 Add test for cross-version constructor template (Daryle Walker)
  23. // 23 Aug 13 Add bug-test of narrowing conversions during order comparison;
  24. // spell logical-negation in it as "!" because MSVC won't accept
  25. // "not" (Daryle Walker)
  26. // 05 Nov 06 Add testing of zero-valued denominators & divisors; casting with
  27. // types that are not implicitly convertible (Daryle Walker)
  28. // 04 Nov 06 Resolve GCD issue with depreciation (Daryle Walker)
  29. // 02 Nov 06 Add testing for operator<(int_type) w/ unsigneds (Daryle Walker)
  30. // 31 Oct 06 Add testing for operator<(rational) overflow (Daryle Walker)
  31. // 18 Oct 06 Various fixes for old compilers (Joaquín M López Muñoz)
  32. // 27 Dec 05 Add testing for Boolean conversion operator (Daryle Walker)
  33. // 24 Dec 05 Change code to use Boost.Test (Daryle Walker)
  34. // 04 Mar 01 Patches for Intel C++ and GCC (David Abrahams)
  35. #define BOOST_TEST_MAIN "Boost::Rational unit tests"
  36. #include <boost/config.hpp>
  37. #include <boost/limits.hpp>
  38. #include <boost/mpl/list.hpp>
  39. #include <boost/operators.hpp>
  40. #include <boost/preprocessor/stringize.hpp>
  41. #include <boost/integer/common_factor_rt.hpp>
  42. #include <boost/cstdint.hpp>
  43. #include <boost/rational.hpp>
  44. #include <boost/test/unit_test.hpp>
  45. #include <climits>
  46. #include <iomanip>
  47. #include <ios>
  48. #include <iostream>
  49. #include <istream>
  50. #include <ostream>
  51. #include <sstream>
  52. #include <stdexcept>
  53. #include <string>
  54. #ifdef _MSC_VER
  55. #pragma warning(disable:4146)
  56. #endif
  57. // We can override this on the compile, as -DINT_TYPE=short or whatever.
  58. // The default test is against rational<long>.
  59. #ifndef INT_TYPE
  60. #define INT_TYPE long
  61. #endif
  62. namespace {
  63. class MyOverflowingUnsigned;
  64. // This is a trivial user-defined wrapper around the built in int type.
  65. // It can be used as a test type for rational<>
  66. class MyInt : boost::operators<MyInt>
  67. {
  68. friend class MyOverflowingUnsigned;
  69. int val;
  70. public:
  71. MyInt(int n = 0) : val(n) {}
  72. friend MyInt operator+ (const MyInt&);
  73. friend MyInt operator- (const MyInt&);
  74. MyInt& operator+= (const MyInt& rhs) { val += rhs.val; return *this; }
  75. MyInt& operator-= (const MyInt& rhs) { val -= rhs.val; return *this; }
  76. MyInt& operator*= (const MyInt& rhs) { val *= rhs.val; return *this; }
  77. MyInt& operator/= (const MyInt& rhs) { val /= rhs.val; return *this; }
  78. MyInt& operator%= (const MyInt& rhs) { val %= rhs.val; return *this; }
  79. MyInt& operator|= (const MyInt& rhs) { val |= rhs.val; return *this; }
  80. MyInt& operator&= (const MyInt& rhs) { val &= rhs.val; return *this; }
  81. MyInt& operator^= (const MyInt& rhs) { val ^= rhs.val; return *this; }
  82. const MyInt& operator++() { ++val; return *this; }
  83. const MyInt& operator--() { --val; return *this; }
  84. bool operator< (const MyInt& rhs) const { return val < rhs.val; }
  85. bool operator== (const MyInt& rhs) const { return val == rhs.val; }
  86. bool operator! () const { return !val; }
  87. friend std::istream& operator>>(std::istream&, MyInt&);
  88. friend std::ostream& operator<<(std::ostream&, const MyInt&);
  89. };
  90. inline MyInt operator+(const MyInt& rhs) { return rhs; }
  91. inline MyInt operator-(const MyInt& rhs) { return MyInt(-rhs.val); }
  92. inline std::istream& operator>>(std::istream& is, MyInt& i) { is >> i.val; return is; }
  93. inline std::ostream& operator<<(std::ostream& os, const MyInt& i) { os << i.val; return os; }
  94. inline MyInt abs(MyInt rhs) { if (rhs < MyInt()) rhs = -rhs; return rhs; }
  95. // This is an "unsigned" wrapper, that throws on overflow. It can be used to
  96. // test rational<> when an operation goes out of bounds.
  97. class MyOverflowingUnsigned
  98. : private boost::unit_steppable<MyOverflowingUnsigned>
  99. , private boost::ordered_euclidian_ring_operators1<MyOverflowingUnsigned>
  100. {
  101. // Helper type-aliases
  102. typedef MyOverflowingUnsigned self_type;
  103. typedef unsigned self_type::* bool_type;
  104. // Member data
  105. unsigned v_;
  106. public:
  107. // Exception base class
  108. class exception_base { protected: virtual ~exception_base() throw() {} };
  109. // Divide-by-zero exception class
  110. class divide_by_0_error
  111. : public virtual exception_base
  112. , public std::domain_error
  113. {
  114. public:
  115. explicit divide_by_0_error( std::string const &w )
  116. : std::domain_error( w ) {}
  117. virtual ~divide_by_0_error() throw() {}
  118. };
  119. // Overflow exception class
  120. class overflowing_error
  121. : public virtual exception_base
  122. , public std::overflow_error
  123. {
  124. public:
  125. explicit overflowing_error( std::string const &w )
  126. : std::overflow_error( w ) {}
  127. virtual ~overflowing_error() throw() {}
  128. };
  129. // Lifetime management (use automatic dtr & copy-ctr)
  130. MyOverflowingUnsigned( unsigned v = 0 ) : v_( v ) {}
  131. explicit MyOverflowingUnsigned( MyInt const &m ) : v_( m.val ) {}
  132. // Operators (use automatic copy-assignment); arithmetic & comparison only
  133. self_type & operator ++()
  134. {
  135. if ( this->v_ == UINT_MAX ) throw overflowing_error( "increment" );
  136. else ++this->v_;
  137. return *this;
  138. }
  139. self_type & operator --()
  140. {
  141. if ( !this->v_ ) throw overflowing_error( "decrement" );
  142. else --this->v_;
  143. return *this;
  144. }
  145. operator bool_type() const { return this->v_ ? &self_type::v_ : 0; }
  146. bool operator !() const { return !this->v_; }
  147. self_type operator +() const { return self_type( +this->v_ ); }
  148. self_type operator -() const { return self_type( -this->v_ ); }
  149. bool operator <(self_type const &r) const { return this->v_ < r.v_; }
  150. bool operator ==(self_type const &r) const { return this->v_ == r.v_; }
  151. self_type & operator *=( self_type const &r )
  152. {
  153. if ( r.v_ && this->v_ > UINT_MAX / r.v_ )
  154. {
  155. throw overflowing_error( "oversized factors" );
  156. }
  157. this->v_ *= r.v_;
  158. return *this;
  159. }
  160. self_type & operator /=( self_type const &r )
  161. {
  162. if ( !r.v_ ) throw divide_by_0_error( "division" );
  163. this->v_ /= r.v_;
  164. return *this;
  165. }
  166. self_type & operator %=( self_type const &r )
  167. {
  168. if ( !r.v_ ) throw divide_by_0_error( "modulus" );
  169. this->v_ %= r.v_;
  170. return *this;
  171. }
  172. self_type & operator +=( self_type const &r )
  173. {
  174. if ( this->v_ > UINT_MAX - r.v_ )
  175. {
  176. throw overflowing_error( "oversized addends" );
  177. }
  178. this->v_ += r.v_;
  179. return *this;
  180. }
  181. self_type & operator -=( self_type const &r )
  182. {
  183. if ( this->v_ < r.v_ )
  184. {
  185. throw overflowing_error( "oversized subtrahend" );
  186. }
  187. this->v_ -= r.v_;
  188. return *this;
  189. }
  190. // Input & output
  191. template < typename Ch, class Tr >
  192. friend std::basic_istream<Ch, Tr> &
  193. operator >>( std::basic_istream<Ch, Tr> &i, self_type &x )
  194. { return i >> x.v_; }
  195. template < typename Ch, class Tr >
  196. friend std::basic_ostream<Ch, Tr> &
  197. operator <<( std::basic_ostream<Ch, Tr> &o, self_type const &x )
  198. { return o << x.v_; }
  199. }; // MyOverflowingUnsigned
  200. inline MyOverflowingUnsigned abs( MyOverflowingUnsigned const &x ) { return x; }
  201. } // namespace
  202. // Specialize numeric_limits for the custom types
  203. namespace std
  204. {
  205. template < >
  206. class numeric_limits< MyInt >
  207. {
  208. typedef numeric_limits<int> limits_type;
  209. public:
  210. static const bool is_specialized = limits_type::is_specialized;
  211. static MyInt min BOOST_PREVENT_MACRO_SUBSTITUTION () throw() { return
  212. limits_type::min BOOST_PREVENT_MACRO_SUBSTITUTION (); }
  213. static MyInt max BOOST_PREVENT_MACRO_SUBSTITUTION () throw() { return
  214. limits_type::max BOOST_PREVENT_MACRO_SUBSTITUTION (); }
  215. static MyInt lowest() throw() { return min BOOST_PREVENT_MACRO_SUBSTITUTION
  216. (); } // C++11
  217. static const int digits = limits_type::digits;
  218. static const int digits10 = limits_type::digits10;
  219. static const int max_digits10 = 0; // C++11
  220. static const bool is_signed = limits_type::is_signed;
  221. static const bool is_integer = limits_type::is_integer;
  222. static const bool is_exact = limits_type::is_exact;
  223. static const int radix = limits_type::radix;
  224. static MyInt epsilon() throw() { return limits_type::epsilon(); }
  225. static MyInt round_error() throw() { return limits_type::round_error(); }
  226. static const int min_exponent = limits_type::min_exponent;
  227. static const int min_exponent10 = limits_type::min_exponent10;
  228. static const int max_exponent = limits_type::max_exponent;
  229. static const int max_exponent10 = limits_type::max_exponent10;
  230. static const bool has_infinity = limits_type::has_infinity;
  231. static const bool has_quiet_NaN = limits_type::has_quiet_NaN;
  232. static const bool has_signaling_NaN = limits_type::has_signaling_NaN;
  233. static const float_denorm_style has_denorm = limits_type::has_denorm;
  234. static const bool has_denorm_loss = limits_type::has_denorm_loss;
  235. static MyInt infinity() throw() { return limits_type::infinity(); }
  236. static MyInt quiet_NaN() throw() { return limits_type::quiet_NaN(); }
  237. static MyInt signaling_NaN() throw() {return limits_type::signaling_NaN();}
  238. static MyInt denorm_min() throw() { return limits_type::denorm_min(); }
  239. static const bool is_iec559 = limits_type::is_iec559;
  240. static const bool is_bounded = limits_type::is_bounded;
  241. static const bool is_modulo = limits_type::is_modulo;
  242. static const bool traps = limits_type::traps;
  243. static const bool tinyness_before = limits_type::tinyness_before;
  244. static const float_round_style round_style = limits_type::round_style;
  245. }; // std::numeric_limits<MyInt>
  246. template < >
  247. class numeric_limits< MyOverflowingUnsigned >
  248. {
  249. typedef numeric_limits<unsigned> limits_type;
  250. public:
  251. static const bool is_specialized = limits_type::is_specialized;
  252. static MyOverflowingUnsigned min BOOST_PREVENT_MACRO_SUBSTITUTION () throw()
  253. { return limits_type::min BOOST_PREVENT_MACRO_SUBSTITUTION (); }
  254. static MyOverflowingUnsigned max BOOST_PREVENT_MACRO_SUBSTITUTION () throw()
  255. { return limits_type::max BOOST_PREVENT_MACRO_SUBSTITUTION (); }
  256. static MyOverflowingUnsigned lowest() throw()
  257. { return min BOOST_PREVENT_MACRO_SUBSTITUTION (); } // C++11
  258. static const int digits = limits_type::digits;
  259. static const int digits10 = limits_type::digits10;
  260. static const int max_digits10 = 0; // C++11
  261. static const bool is_signed = limits_type::is_signed;
  262. static const bool is_integer = limits_type::is_integer;
  263. static const bool is_exact = limits_type::is_exact;
  264. static const int radix = limits_type::radix;
  265. static MyOverflowingUnsigned epsilon() throw()
  266. { return limits_type::epsilon(); }
  267. static MyOverflowingUnsigned round_error() throw()
  268. {return limits_type::round_error();}
  269. static const int min_exponent = limits_type::min_exponent;
  270. static const int min_exponent10 = limits_type::min_exponent10;
  271. static const int max_exponent = limits_type::max_exponent;
  272. static const int max_exponent10 = limits_type::max_exponent10;
  273. static const bool has_infinity = limits_type::has_infinity;
  274. static const bool has_quiet_NaN = limits_type::has_quiet_NaN;
  275. static const bool has_signaling_NaN = limits_type::has_signaling_NaN;
  276. static const float_denorm_style has_denorm = limits_type::has_denorm;
  277. static const bool has_denorm_loss = limits_type::has_denorm_loss;
  278. static MyOverflowingUnsigned infinity() throw()
  279. { return limits_type::infinity(); }
  280. static MyOverflowingUnsigned quiet_NaN() throw()
  281. { return limits_type::quiet_NaN(); }
  282. static MyOverflowingUnsigned signaling_NaN() throw()
  283. { return limits_type::signaling_NaN(); }
  284. static MyOverflowingUnsigned denorm_min() throw()
  285. { return limits_type::denorm_min(); }
  286. static const bool is_iec559 = limits_type::is_iec559;
  287. static const bool is_bounded = limits_type::is_bounded;
  288. static const bool is_modulo = limits_type::is_modulo;
  289. static const bool traps = limits_type::traps;
  290. static const bool tinyness_before = limits_type::tinyness_before;
  291. static const float_round_style round_style = limits_type::round_style;
  292. }; // std::numeric_limits<MyOverflowingUnsigned>
  293. } // namespace std
  294. namespace {
  295. // This fixture replaces the check of rational's packing at the start of main.
  296. class rational_size_check
  297. {
  298. typedef INT_TYPE int_type;
  299. typedef ::boost::rational<int_type> rational_type;
  300. public:
  301. rational_size_check()
  302. {
  303. using ::std::cout;
  304. char const * const int_name = BOOST_PP_STRINGIZE( INT_TYPE );
  305. cout << "Running tests for boost::rational<" << int_name << ">\n\n";
  306. cout << "Implementation issue: the minimal size for a rational\n"
  307. << "is twice the size of the underlying integer type.\n\n";
  308. cout << "Checking to see if space is being wasted.\n"
  309. << "\tsizeof(" << int_name << ") == " << sizeof( int_type )
  310. << "\n";
  311. cout << "\tsizeof(boost::rational<" << int_name << ">) == "
  312. << sizeof( rational_type ) << "\n\n";
  313. cout << "Implementation has "
  314. << (
  315. (sizeof( rational_type ) > 2u * sizeof( int_type ))
  316. ? "included padding bytes"
  317. : "minimal size"
  318. )
  319. << "\n\n";
  320. }
  321. };
  322. // This fixture groups all the common settings.
  323. class my_configuration
  324. {
  325. public:
  326. template < typename T >
  327. class hook
  328. {
  329. public:
  330. typedef ::boost::rational<T> rational_type;
  331. private:
  332. struct parts { rational_type parts_[ 9 ]; };
  333. static parts generate_rationals()
  334. {
  335. rational_type r1, r2( 0 ), r3( 1 ), r4( -3 ), r5( 7, 2 ),
  336. r6( 5, 15 ), r7( 14, -21 ), r8( -4, 6 ),
  337. r9( -14, -70 );
  338. parts result;
  339. result.parts_[0] = r1;
  340. result.parts_[1] = r2;
  341. result.parts_[2] = r3;
  342. result.parts_[3] = r4;
  343. result.parts_[4] = r5;
  344. result.parts_[5] = r6;
  345. result.parts_[6] = r7;
  346. result.parts_[7] = r8;
  347. result.parts_[8] = r9;
  348. return result;
  349. }
  350. parts p_; // Order Dependency
  351. public:
  352. rational_type ( &r_ )[ 9 ]; // Order Dependency
  353. hook() : p_( generate_rationals() ), r_( p_.parts_ ) {}
  354. };
  355. };
  356. // Instead of controlling the integer type needed with a #define, use a list of
  357. // all available types. Since the headers #included don't change because of the
  358. // integer #define, only the built-in types and MyInt are available. (Any other
  359. // arbitrary integer type introduced by the #define would get compiler errors
  360. // because its header can't be #included.)
  361. typedef ::boost::mpl::list<short, int, long> builtin_signed_test_types;
  362. typedef ::boost::mpl::list<short, int, long, MyInt> all_signed_test_types;
  363. // Without these explicit instantiations, MSVC++ 6.5/7.0 does not find
  364. // some friend operators in certain contexts.
  365. ::boost::rational<short> dummy1;
  366. ::boost::rational<int> dummy2;
  367. ::boost::rational<long> dummy3;
  368. ::boost::rational<MyInt> dummy4;
  369. ::boost::rational<MyOverflowingUnsigned> dummy5;
  370. ::boost::rational<unsigned> dummy6;
  371. // Should there be regular tests with unsigned integer types?
  372. } // namespace
  373. // Check if rational is the smallest size possible
  374. BOOST_GLOBAL_FIXTURE( rational_size_check );
  375. #if BOOST_CONTROL_RATIONAL_HAS_GCD
  376. // The factoring function template suite
  377. BOOST_AUTO_TEST_SUITE( factoring_suite )
  378. // GCD tests
  379. BOOST_AUTO_TEST_CASE_TEMPLATE( gcd_test, T, all_signed_test_types )
  380. {
  381. BOOST_CHECK_EQUAL( boost::gcd<T>( 1, -1), static_cast<T>( 1) );
  382. BOOST_CHECK_EQUAL( boost::gcd<T>( -1, 1), static_cast<T>( 1) );
  383. BOOST_CHECK_EQUAL( boost::gcd<T>( 1, 1), static_cast<T>( 1) );
  384. BOOST_CHECK_EQUAL( boost::gcd<T>( -1, -1), static_cast<T>( 1) );
  385. BOOST_CHECK_EQUAL( boost::gcd<T>( 0, 0), static_cast<T>( 0) );
  386. BOOST_CHECK_EQUAL( boost::gcd<T>( 7, 0), static_cast<T>( 7) );
  387. BOOST_CHECK_EQUAL( boost::gcd<T>( 0, 9), static_cast<T>( 9) );
  388. BOOST_CHECK_EQUAL( boost::gcd<T>( -7, 0), static_cast<T>( 7) );
  389. BOOST_CHECK_EQUAL( boost::gcd<T>( 0, -9), static_cast<T>( 9) );
  390. BOOST_CHECK_EQUAL( boost::gcd<T>( 42, 30), static_cast<T>( 6) );
  391. BOOST_CHECK_EQUAL( boost::gcd<T>( 6, -9), static_cast<T>( 3) );
  392. BOOST_CHECK_EQUAL( boost::gcd<T>(-10, -10), static_cast<T>(10) );
  393. BOOST_CHECK_EQUAL( boost::gcd<T>(-25, -10), static_cast<T>( 5) );
  394. }
  395. // LCM tests
  396. BOOST_AUTO_TEST_CASE_TEMPLATE( lcm_test, T, all_signed_test_types )
  397. {
  398. BOOST_CHECK_EQUAL( boost::lcm<T>( 1, -1), static_cast<T>( 1) );
  399. BOOST_CHECK_EQUAL( boost::lcm<T>( -1, 1), static_cast<T>( 1) );
  400. BOOST_CHECK_EQUAL( boost::lcm<T>( 1, 1), static_cast<T>( 1) );
  401. BOOST_CHECK_EQUAL( boost::lcm<T>( -1, -1), static_cast<T>( 1) );
  402. BOOST_CHECK_EQUAL( boost::lcm<T>( 0, 0), static_cast<T>( 0) );
  403. BOOST_CHECK_EQUAL( boost::lcm<T>( 6, 0), static_cast<T>( 0) );
  404. BOOST_CHECK_EQUAL( boost::lcm<T>( 0, 7), static_cast<T>( 0) );
  405. BOOST_CHECK_EQUAL( boost::lcm<T>( -5, 0), static_cast<T>( 0) );
  406. BOOST_CHECK_EQUAL( boost::lcm<T>( 0, -4), static_cast<T>( 0) );
  407. BOOST_CHECK_EQUAL( boost::lcm<T>( 18, 30), static_cast<T>(90) );
  408. BOOST_CHECK_EQUAL( boost::lcm<T>( -6, 9), static_cast<T>(18) );
  409. BOOST_CHECK_EQUAL( boost::lcm<T>(-10, -10), static_cast<T>(10) );
  410. BOOST_CHECK_EQUAL( boost::lcm<T>( 25, -10), static_cast<T>(50) );
  411. }
  412. BOOST_AUTO_TEST_SUITE_END()
  413. #endif // BOOST_CONTROL_RATIONAL_HAS_GCD
  414. // The basic test suite
  415. BOOST_FIXTURE_TEST_SUITE( basic_rational_suite, my_configuration )
  416. // Initialization tests
  417. BOOST_AUTO_TEST_CASE_TEMPLATE( rational_initialization_test, T,
  418. all_signed_test_types )
  419. {
  420. my_configuration::hook<T> h;
  421. boost::rational<T> &r1 = h.r_[ 0 ], &r2 = h.r_[ 1 ], &r3 = h.r_[ 2 ],
  422. &r4 = h.r_[ 3 ], &r5 = h.r_[ 4 ], &r6 = h.r_[ 5 ],
  423. &r7 = h.r_[ 6 ], &r8 = h.r_[ 7 ], &r9 = h.r_[ 8 ];
  424. BOOST_CHECK_EQUAL( r1.numerator(), static_cast<T>( 0) );
  425. BOOST_CHECK_EQUAL( r2.numerator(), static_cast<T>( 0) );
  426. BOOST_CHECK_EQUAL( r3.numerator(), static_cast<T>( 1) );
  427. BOOST_CHECK_EQUAL( r4.numerator(), static_cast<T>(-3) );
  428. BOOST_CHECK_EQUAL( r5.numerator(), static_cast<T>( 7) );
  429. BOOST_CHECK_EQUAL( r6.numerator(), static_cast<T>( 1) );
  430. BOOST_CHECK_EQUAL( r7.numerator(), static_cast<T>(-2) );
  431. BOOST_CHECK_EQUAL( r8.numerator(), static_cast<T>(-2) );
  432. BOOST_CHECK_EQUAL( r9.numerator(), static_cast<T>( 1) );
  433. BOOST_CHECK_EQUAL( r1.denominator(), static_cast<T>(1) );
  434. BOOST_CHECK_EQUAL( r2.denominator(), static_cast<T>(1) );
  435. BOOST_CHECK_EQUAL( r3.denominator(), static_cast<T>(1) );
  436. BOOST_CHECK_EQUAL( r4.denominator(), static_cast<T>(1) );
  437. BOOST_CHECK_EQUAL( r5.denominator(), static_cast<T>(2) );
  438. BOOST_CHECK_EQUAL( r6.denominator(), static_cast<T>(3) );
  439. BOOST_CHECK_EQUAL( r7.denominator(), static_cast<T>(3) );
  440. BOOST_CHECK_EQUAL( r8.denominator(), static_cast<T>(3) );
  441. BOOST_CHECK_EQUAL( r9.denominator(), static_cast<T>(5) );
  442. BOOST_CHECK_THROW( boost::rational<T>( 3, 0), boost::bad_rational );
  443. BOOST_CHECK_THROW( boost::rational<T>(-2, 0), boost::bad_rational );
  444. BOOST_CHECK_THROW( boost::rational<T>( 0, 0), boost::bad_rational );
  445. }
  446. // Assignment (non-operator) tests
  447. BOOST_AUTO_TEST_CASE_TEMPLATE( rational_assign_test, T, all_signed_test_types )
  448. {
  449. my_configuration::hook<T> h;
  450. boost::rational<T> & r = h.r_[ 0 ];
  451. r.assign( 6, 8 );
  452. BOOST_CHECK_EQUAL( r.numerator(), static_cast<T>(3) );
  453. BOOST_CHECK_EQUAL( r.denominator(), static_cast<T>(4) );
  454. r.assign( 0, -7 );
  455. BOOST_CHECK_EQUAL( r.numerator(), static_cast<T>(0) );
  456. BOOST_CHECK_EQUAL( r.denominator(), static_cast<T>(1) );
  457. BOOST_CHECK_THROW( r.assign( 4, 0), boost::bad_rational );
  458. BOOST_CHECK_THROW( r.assign( 0, 0), boost::bad_rational );
  459. BOOST_CHECK_THROW( r.assign(-7, 0), boost::bad_rational );
  460. }
  461. // Comparison tests
  462. BOOST_AUTO_TEST_CASE_TEMPLATE( rational_comparison_test, T,
  463. all_signed_test_types )
  464. {
  465. my_configuration::hook<T> h;
  466. const boost::rational<T> &r1 = h.r_[ 0 ], &r2 = h.r_[ 1 ], &r3 = h.r_[ 2 ],
  467. &r4 = h.r_[ 3 ], &r5 = h.r_[ 4 ], &r6 = h.r_[ 5 ],
  468. &r7 = h.r_[ 6 ], &r8 = h.r_[ 7 ], &r9 = h.r_[ 8 ];
  469. BOOST_CHECK( r1 == r2 );
  470. BOOST_CHECK( r2 != r3 );
  471. BOOST_CHECK( r4 < r3 );
  472. BOOST_CHECK( r4 <= r5 );
  473. BOOST_CHECK( r1 <= r2 );
  474. BOOST_CHECK( r5 > r6 );
  475. BOOST_CHECK( r5 >= r6 );
  476. BOOST_CHECK( r7 >= r8 );
  477. BOOST_CHECK( !(r3 == r2) );
  478. BOOST_CHECK( !(r1 != r2) );
  479. BOOST_CHECK( !(r1 < r2) );
  480. BOOST_CHECK( !(r5 < r6) );
  481. BOOST_CHECK( !(r9 <= r2) );
  482. BOOST_CHECK( !(r8 > r7) );
  483. BOOST_CHECK( !(r8 > r2) );
  484. BOOST_CHECK( !(r4 >= r6) );
  485. BOOST_CHECK( r1 == static_cast<T>( 0) );
  486. BOOST_CHECK( r2 != static_cast<T>(-1) );
  487. BOOST_CHECK( r3 < static_cast<T>( 2) );
  488. BOOST_CHECK( r4 <= static_cast<T>(-3) );
  489. BOOST_CHECK( r5 > static_cast<T>( 3) );
  490. BOOST_CHECK( r6 >= static_cast<T>( 0) );
  491. BOOST_CHECK( static_cast<T>( 0) == r2 );
  492. BOOST_CHECK( static_cast<T>( 0) != r7 );
  493. BOOST_CHECK( static_cast<T>(-1) < r8 );
  494. BOOST_CHECK( static_cast<T>(-2) <= r9 );
  495. BOOST_CHECK( static_cast<T>( 1) > r1 );
  496. BOOST_CHECK( static_cast<T>( 1) >= r3 );
  497. // Extra tests with values close in continued-fraction notation
  498. boost::rational<T> const x1( static_cast<T>(9), static_cast<T>(4) );
  499. boost::rational<T> const x2( static_cast<T>(61), static_cast<T>(27) );
  500. boost::rational<T> const x3( static_cast<T>(52), static_cast<T>(23) );
  501. boost::rational<T> const x4( static_cast<T>(70), static_cast<T>(31) );
  502. BOOST_CHECK( x1 < x2 );
  503. BOOST_CHECK( !(x1 < x1) );
  504. BOOST_CHECK( !(x2 < x2) );
  505. BOOST_CHECK( !(x2 < x1) );
  506. BOOST_CHECK( x2 < x3 );
  507. BOOST_CHECK( x4 < x2 );
  508. BOOST_CHECK( !(x3 < x4) );
  509. BOOST_CHECK( r7 < x1 ); // not actually close; wanted -ve v. +ve instead
  510. BOOST_CHECK( !(x2 < r7) );
  511. }
  512. // Increment & decrement tests
  513. BOOST_AUTO_TEST_CASE_TEMPLATE( rational_1step_test, T, all_signed_test_types )
  514. {
  515. my_configuration::hook<T> h;
  516. boost::rational<T> &r1 = h.r_[ 0 ], &r2 = h.r_[ 1 ], &r3 = h.r_[ 2 ],
  517. &r7 = h.r_[ 6 ], &r8 = h.r_[ 7 ];
  518. BOOST_CHECK( r1++ == r2 );
  519. BOOST_CHECK( r1 != r2 );
  520. BOOST_CHECK( r1 == r3 );
  521. BOOST_CHECK( --r1 == r2 );
  522. BOOST_CHECK( r8-- == r7 );
  523. BOOST_CHECK( r8 != r7 );
  524. BOOST_CHECK( ++r8 == r7 );
  525. }
  526. // Absolute value tests
  527. BOOST_AUTO_TEST_CASE_TEMPLATE( rational_abs_test, T, all_signed_test_types )
  528. {
  529. typedef my_configuration::hook<T> hook_type;
  530. typedef typename hook_type::rational_type rational_type;
  531. hook_type h;
  532. rational_type &r2 = h.r_[ 1 ], &r5 = h.r_[ 4 ], &r8 = h.r_[ 7 ];
  533. #ifdef BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP
  534. // This is a nasty hack, required because some compilers do not implement
  535. // "Koenig Lookup." Basically, if I call abs(r), the C++ standard says that
  536. // the compiler should look for a definition of abs in the namespace which
  537. // contains r's class (in this case boost)--among other places.
  538. using boost::abs;
  539. #endif
  540. BOOST_CHECK_EQUAL( abs(r2), r2 );
  541. BOOST_CHECK_EQUAL( abs(r5), r5 );
  542. BOOST_CHECK_EQUAL( abs(r8), rational_type(2, 3) );
  543. }
  544. // Unary operator tests
  545. BOOST_AUTO_TEST_CASE_TEMPLATE( rational_unary_test, T, all_signed_test_types )
  546. {
  547. my_configuration::hook<T> h;
  548. boost::rational<T> &r2 = h.r_[ 1 ], &r3 = h.r_[ 2 ],
  549. &r4 = h.r_[ 3 ], &r5 = h.r_[ 4 ];
  550. BOOST_CHECK_EQUAL( +r5, r5 );
  551. BOOST_CHECK( -r3 != r3 );
  552. BOOST_CHECK_EQUAL( -(-r3), r3 );
  553. BOOST_CHECK_EQUAL( -r4, static_cast<T>(3) );
  554. BOOST_CHECK( !r2 );
  555. BOOST_CHECK( !!r3 );
  556. BOOST_CHECK( ! static_cast<bool>(r2) );
  557. BOOST_CHECK( r3 );
  558. }
  559. BOOST_AUTO_TEST_SUITE_END()
  560. // The rational arithmetic operations suite
  561. BOOST_AUTO_TEST_SUITE( rational_arithmetic_suite )
  562. // Addition & subtraction tests
  563. BOOST_AUTO_TEST_CASE_TEMPLATE( rational_additive_test, T,
  564. all_signed_test_types )
  565. {
  566. typedef boost::rational<T> rational_type;
  567. BOOST_CHECK_EQUAL( rational_type( 1, 2) + rational_type(1, 2),
  568. static_cast<T>(1) );
  569. BOOST_CHECK_EQUAL( rational_type(11, 3) + rational_type(1, 2),
  570. rational_type( 25, 6) );
  571. BOOST_CHECK_EQUAL( rational_type(-8, 3) + rational_type(1, 5),
  572. rational_type(-37, 15) );
  573. BOOST_CHECK_EQUAL( rational_type(-7, 6) + rational_type(1, 7),
  574. rational_type( 1, 7) - rational_type(7, 6) );
  575. BOOST_CHECK_EQUAL( rational_type(13, 5) - rational_type(1, 2),
  576. rational_type( 21, 10) );
  577. BOOST_CHECK_EQUAL( rational_type(22, 3) + static_cast<T>(1),
  578. rational_type( 25, 3) );
  579. BOOST_CHECK_EQUAL( rational_type(12, 7) - static_cast<T>(2),
  580. rational_type( -2, 7) );
  581. BOOST_CHECK_EQUAL( static_cast<T>(3) + rational_type(4, 5),
  582. rational_type( 19, 5) );
  583. BOOST_CHECK_EQUAL( static_cast<T>(4) - rational_type(9, 2),
  584. rational_type( -1, 2) );
  585. rational_type r( 11 );
  586. r -= rational_type( 20, 3 );
  587. BOOST_CHECK_EQUAL( r, rational_type(13, 3) );
  588. r += rational_type( 1, 2 );
  589. BOOST_CHECK_EQUAL( r, rational_type(29, 6) );
  590. r -= static_cast<T>( 5 );
  591. BOOST_CHECK_EQUAL( r, rational_type( 1, -6) );
  592. r += rational_type( 1, 5 );
  593. BOOST_CHECK_EQUAL( r, rational_type( 1, 30) );
  594. r += static_cast<T>( 2 );
  595. BOOST_CHECK_EQUAL( r, rational_type(61, 30) );
  596. }
  597. // Assignment tests
  598. BOOST_AUTO_TEST_CASE_TEMPLATE( rational_assignment_test, T,
  599. all_signed_test_types )
  600. {
  601. typedef boost::rational<T> rational_type;
  602. rational_type r;
  603. r = rational_type( 1, 10 );
  604. BOOST_CHECK_EQUAL( r, rational_type( 1, 10) );
  605. r = static_cast<T>( -9 );
  606. BOOST_CHECK_EQUAL( r, rational_type(-9, 1) );
  607. }
  608. // Multiplication tests
  609. BOOST_AUTO_TEST_CASE_TEMPLATE( rational_multiplication_test, T,
  610. all_signed_test_types )
  611. {
  612. typedef boost::rational<T> rational_type;
  613. BOOST_CHECK_EQUAL( rational_type(1, 3) * rational_type(-3, 4),
  614. rational_type(-1, 4) );
  615. BOOST_CHECK_EQUAL( rational_type(2, 5) * static_cast<T>(7),
  616. rational_type(14, 5) );
  617. BOOST_CHECK_EQUAL( static_cast<T>(-2) * rational_type(1, 6),
  618. rational_type(-1, 3) );
  619. rational_type r = rational_type( 3, 7 );
  620. r *= static_cast<T>( 14 );
  621. BOOST_CHECK_EQUAL( r, static_cast<T>(6) );
  622. r *= rational_type( 3, 8 );
  623. BOOST_CHECK_EQUAL( r, rational_type(9, 4) );
  624. }
  625. // Division tests
  626. BOOST_AUTO_TEST_CASE_TEMPLATE( rational_division_test, T,
  627. all_signed_test_types )
  628. {
  629. typedef boost::rational<T> rational_type;
  630. BOOST_CHECK_EQUAL( rational_type(-1, 20) / rational_type(4, 5),
  631. rational_type(-1, 16) );
  632. BOOST_CHECK_EQUAL( rational_type( 5, 6) / static_cast<T>(7),
  633. rational_type( 5, 42) );
  634. BOOST_CHECK_EQUAL( static_cast<T>(8) / rational_type(2, 7),
  635. static_cast<T>(28) );
  636. BOOST_CHECK_THROW( rational_type(23, 17) / rational_type(),
  637. boost::bad_rational );
  638. BOOST_CHECK_THROW( rational_type( 4, 15) / static_cast<T>(0),
  639. boost::bad_rational );
  640. rational_type r = rational_type( 4, 3 );
  641. r /= rational_type( 5, 4 );
  642. BOOST_CHECK_EQUAL( r, rational_type(16, 15) );
  643. r /= static_cast<T>( 4 );
  644. BOOST_CHECK_EQUAL( r, rational_type( 4, 15) );
  645. BOOST_CHECK_THROW( r /= rational_type(), boost::bad_rational );
  646. BOOST_CHECK_THROW( r /= static_cast<T>(0), boost::bad_rational );
  647. BOOST_CHECK_EQUAL( rational_type(-1) / rational_type(-3),
  648. rational_type(1, 3) );
  649. }
  650. // Tests for operations on self
  651. BOOST_AUTO_TEST_CASE_TEMPLATE( rational_self_operations_test, T,
  652. all_signed_test_types )
  653. {
  654. typedef boost::rational<T> rational_type;
  655. rational_type r = rational_type( 4, 3 );
  656. r += r;
  657. BOOST_CHECK_EQUAL( r, rational_type( 8, 3) );
  658. r *= r;
  659. BOOST_CHECK_EQUAL( r, rational_type(64, 9) );
  660. r /= r;
  661. BOOST_CHECK_EQUAL( r, rational_type( 1, 1) );
  662. r -= r;
  663. BOOST_CHECK_EQUAL( r, rational_type( 0, 1) );
  664. BOOST_CHECK_THROW( r /= r, boost::bad_rational );
  665. }
  666. BOOST_AUTO_TEST_CASE_TEMPLATE( gcd_and_lcm_on_rationals, T, all_signed_test_types )
  667. {
  668. typedef boost::rational<T> rational;
  669. BOOST_CHECK_EQUAL(boost::integer::gcd(rational(1, 4), rational(1, 3)),
  670. rational(1, 12));
  671. BOOST_CHECK_EQUAL(boost::integer::lcm(rational(1, 4), rational(1, 3)),
  672. rational(1));
  673. }
  674. // Assignment tests
  675. BOOST_AUTO_TEST_CASE_TEMPLATE(rational_mixed_test, T,
  676. /*all_signed_test_types*/ builtin_signed_test_types)
  677. {
  678. {
  679. typedef boost::rational<boost::intmax_t> rational_type;
  680. T val1 = 20;
  681. boost::intmax_t val2 = 30;
  682. rational_type r(val1, val2);
  683. BOOST_CHECK_EQUAL(r, rational_type(20, 30));
  684. r.assign(val1, val2);
  685. BOOST_CHECK_EQUAL(r, rational_type(20, 30));
  686. }
  687. {
  688. typedef boost::rational<boost::uintmax_t> rational_type2;
  689. T val1 = 20;
  690. boost::uintmax_t val3 = 30;
  691. rational_type2 r2(val1, val3);
  692. BOOST_CHECK_EQUAL(r2, rational_type2(20, 30));
  693. r2.assign(val1, val3);
  694. BOOST_CHECK_EQUAL(r2, rational_type2(20, 30));
  695. }
  696. {
  697. typedef boost::rational<short> rational_type;
  698. T val1 = 20;
  699. short val2 = 30;
  700. rational_type r(val1, val2);
  701. BOOST_CHECK_EQUAL(r, rational_type(20, 30));
  702. r.assign(val1, val2);
  703. BOOST_CHECK_EQUAL(r, rational_type(20, 30));
  704. }
  705. {
  706. typedef boost::rational<unsigned short> rational_type;
  707. T val1 = 20;
  708. unsigned short val2 = 30;
  709. rational_type r(val1, val2);
  710. BOOST_CHECK_EQUAL(r, rational_type(20, 30));
  711. r.assign(val1, val2);
  712. BOOST_CHECK_EQUAL(r, rational_type(20, 30));
  713. }
  714. {
  715. typedef boost::rational<long> rational_type;
  716. T val1 = 20;
  717. long val2 = 30;
  718. rational_type r(val1, val2);
  719. BOOST_CHECK_EQUAL(r, rational_type(20, 30));
  720. r.assign(val1, val2);
  721. BOOST_CHECK_EQUAL(r, rational_type(20, 30));
  722. }
  723. {
  724. typedef boost::rational<unsigned long> rational_type;
  725. T val1 = 20;
  726. unsigned long val2 = 30;
  727. rational_type r(val1, val2);
  728. BOOST_CHECK_EQUAL(r, rational_type(20, 30));
  729. r.assign(val1, val2);
  730. BOOST_CHECK_EQUAL(r, rational_type(20, 30));
  731. }
  732. {
  733. typedef boost::rational<boost::intmax_t> rational_type;
  734. T val1 = 20;
  735. boost::intmax_t val2 = -30;
  736. rational_type r(val1, val2);
  737. BOOST_CHECK_EQUAL(r, rational_type(20, -30));
  738. r.assign(val1, val2);
  739. BOOST_CHECK_EQUAL(r, rational_type(20, -30));
  740. }
  741. {
  742. typedef boost::rational<short> rational_type;
  743. T val1 = -20;
  744. short val2 = -30;
  745. rational_type r(val1, val2);
  746. BOOST_CHECK_EQUAL(r, rational_type(-20, -30));
  747. r.assign(val1, val2);
  748. BOOST_CHECK_EQUAL(r, rational_type(-20, -30));
  749. }
  750. {
  751. typedef boost::rational<long> rational_type;
  752. T val1 = -20;
  753. long val2 = 30;
  754. rational_type r(val1, val2);
  755. BOOST_CHECK_EQUAL(r, rational_type(-20, 30));
  756. r.assign(val1, val2);
  757. BOOST_CHECK_EQUAL(r, rational_type(-20, 30));
  758. }
  759. }
  760. BOOST_AUTO_TEST_CASE(conversions)
  761. {
  762. typedef boost::rational<boost::int32_t> signed_rat;
  763. boost::int32_t signed_max = (std::numeric_limits<boost::int32_t>::max)();
  764. boost::int32_t signed_min = (std::numeric_limits<boost::int32_t>::min)();
  765. boost::int32_t signed_min_num = signed_min + 1;
  766. BOOST_CHECK_EQUAL(signed_rat(signed_max).numerator(), signed_max);
  767. BOOST_CHECK_EQUAL(signed_rat(signed_min).numerator(), signed_min);
  768. BOOST_CHECK_EQUAL(signed_rat(signed_max, 1).numerator(), signed_max);
  769. BOOST_CHECK_EQUAL(signed_rat(signed_min, 1).numerator(), signed_min);
  770. BOOST_CHECK_EQUAL(signed_rat(1, signed_max).denominator(), signed_max);
  771. BOOST_CHECK_EQUAL(signed_rat(1, signed_min_num).denominator(), -signed_min_num);
  772. // This throws because we can't negate signed_min:
  773. BOOST_CHECK_THROW(signed_rat(1, signed_min).denominator(), std::domain_error);
  774. signed_rat sr;
  775. BOOST_CHECK_EQUAL(sr.assign(signed_max, 1).numerator(), signed_max);
  776. BOOST_CHECK_EQUAL(sr.assign(1, signed_max).denominator(), signed_max);
  777. BOOST_CHECK_EQUAL(sr.assign(signed_min, 1).numerator(), signed_min);
  778. BOOST_CHECK_EQUAL(sr.assign(1, signed_min_num).denominator(), -signed_min_num);
  779. BOOST_CHECK_THROW(sr.assign(1, signed_min), std::domain_error);
  780. BOOST_CHECK_EQUAL((sr = signed_max).numerator(), signed_max);
  781. BOOST_CHECK_EQUAL((sr = signed_min).numerator(), signed_min);
  782. boost::int64_t big_signed_max = (std::numeric_limits<boost::int32_t>::max)();
  783. boost::int64_t big_signed_min = (std::numeric_limits<boost::int32_t>::min)();
  784. boost::int64_t big_signed_min_num = signed_min + 1;
  785. BOOST_CHECK_EQUAL(signed_rat(big_signed_max).numerator(), big_signed_max);
  786. BOOST_CHECK_EQUAL(signed_rat(big_signed_min).numerator(), big_signed_min);
  787. BOOST_CHECK_EQUAL(signed_rat(big_signed_max, 1).numerator(), big_signed_max);
  788. BOOST_CHECK_EQUAL(signed_rat(big_signed_min, 1).numerator(), big_signed_min);
  789. BOOST_CHECK_EQUAL(signed_rat(1, big_signed_max).denominator(), big_signed_max);
  790. BOOST_CHECK_EQUAL(signed_rat(1, big_signed_min_num).denominator(), -big_signed_min_num);
  791. // This throws because we can't negate big_signed_min:
  792. BOOST_CHECK_THROW(signed_rat(1, big_signed_min).denominator(), std::domain_error);
  793. BOOST_CHECK_EQUAL(sr.assign(big_signed_max, 1).numerator(), big_signed_max);
  794. BOOST_CHECK_EQUAL(sr.assign(1, big_signed_max).denominator(), big_signed_max);
  795. BOOST_CHECK_EQUAL(sr.assign(big_signed_min, 1).numerator(), big_signed_min);
  796. BOOST_CHECK_EQUAL(sr.assign(1, big_signed_min_num).denominator(), -big_signed_min_num);
  797. BOOST_CHECK_THROW(sr.assign(1, big_signed_min), std::domain_error);
  798. BOOST_CHECK_EQUAL((sr = big_signed_max).numerator(), big_signed_max);
  799. BOOST_CHECK_EQUAL((sr = big_signed_min).numerator(), big_signed_min);
  800. ++big_signed_max;
  801. --big_signed_min;
  802. BOOST_CHECK_THROW(signed_rat(big_signed_max).numerator(), std::domain_error);
  803. BOOST_CHECK_THROW(signed_rat(big_signed_min).numerator(), std::domain_error);
  804. BOOST_CHECK_THROW(signed_rat(big_signed_max, 1).numerator(), std::domain_error);
  805. BOOST_CHECK_THROW(signed_rat(big_signed_min, 1).numerator(), std::domain_error);
  806. BOOST_CHECK_THROW(signed_rat(1, big_signed_max).denominator(), std::domain_error);
  807. BOOST_CHECK_THROW(sr.assign(big_signed_max, 1).numerator(), std::domain_error);
  808. BOOST_CHECK_THROW(sr.assign(1, big_signed_max).denominator(), std::domain_error);
  809. BOOST_CHECK_THROW(sr.assign(big_signed_min, 1).numerator(), std::domain_error);
  810. BOOST_CHECK_THROW((sr = big_signed_max).numerator(), std::domain_error);
  811. BOOST_CHECK_THROW((sr = big_signed_min).numerator(), std::domain_error);
  812. boost::int16_t small_signed_max = (std::numeric_limits<boost::int16_t>::max)();
  813. boost::int16_t small_signed_min = (std::numeric_limits<boost::int16_t>::min)();
  814. BOOST_CHECK_EQUAL(signed_rat(small_signed_max).numerator(), small_signed_max);
  815. BOOST_CHECK_EQUAL(signed_rat(small_signed_min).numerator(), small_signed_min);
  816. BOOST_CHECK_EQUAL(signed_rat(small_signed_max, 1).numerator(), small_signed_max);
  817. BOOST_CHECK_EQUAL(signed_rat(small_signed_min, 1).numerator(), small_signed_min);
  818. BOOST_CHECK_EQUAL(signed_rat(1, small_signed_max).denominator(), small_signed_max);
  819. BOOST_CHECK_EQUAL(signed_rat(1, small_signed_min).denominator(), -static_cast<boost::int32_t>(small_signed_min));
  820. BOOST_CHECK_EQUAL(sr.assign(small_signed_max, 1).numerator(), small_signed_max);
  821. BOOST_CHECK_EQUAL(sr.assign(1, small_signed_max).denominator(), small_signed_max);
  822. BOOST_CHECK_EQUAL(sr.assign(small_signed_min, 1).numerator(), small_signed_min);
  823. BOOST_CHECK_EQUAL(sr.assign(1, small_signed_min).denominator(), -static_cast<boost::int32_t>(small_signed_min));
  824. BOOST_CHECK_EQUAL((sr = small_signed_max).numerator(), small_signed_max);
  825. BOOST_CHECK_EQUAL((sr = small_signed_min).numerator(), small_signed_min);
  826. boost::uint32_t unsigned_max = signed_max;
  827. BOOST_CHECK_EQUAL(signed_rat(unsigned_max).numerator(), signed_max);
  828. BOOST_CHECK_EQUAL(signed_rat(unsigned_max, 1).numerator(), signed_max);
  829. BOOST_CHECK_EQUAL(signed_rat(1, unsigned_max).denominator(), signed_max);
  830. BOOST_CHECK_EQUAL(sr.assign(unsigned_max, 1).numerator(), signed_max);
  831. BOOST_CHECK_EQUAL(sr.assign(1, unsigned_max).denominator(), signed_max);
  832. BOOST_CHECK_EQUAL((sr = unsigned_max).numerator(), signed_max);
  833. ++unsigned_max;
  834. BOOST_CHECK_THROW(signed_rat(unsigned_max).numerator(), std::domain_error);
  835. BOOST_CHECK_THROW(signed_rat(unsigned_max, 1).numerator(), std::domain_error);
  836. BOOST_CHECK_THROW(signed_rat(1, unsigned_max).denominator(), std::domain_error);
  837. BOOST_CHECK_THROW(sr.assign(unsigned_max, 1).numerator(), std::domain_error);
  838. BOOST_CHECK_THROW(sr.assign(1, unsigned_max).denominator(), std::domain_error);
  839. BOOST_CHECK_THROW((sr = unsigned_max).numerator(), std::domain_error);
  840. boost::uint64_t big_unsigned_max = signed_max;
  841. BOOST_CHECK_EQUAL(signed_rat(big_unsigned_max).numerator(), signed_max);
  842. BOOST_CHECK_EQUAL(signed_rat(big_unsigned_max, 1).numerator(), signed_max);
  843. BOOST_CHECK_EQUAL(signed_rat(1, big_unsigned_max).denominator(), signed_max);
  844. BOOST_CHECK_EQUAL(sr.assign(big_unsigned_max, 1).numerator(), signed_max);
  845. BOOST_CHECK_EQUAL(sr.assign(1, big_unsigned_max).denominator(), signed_max);
  846. BOOST_CHECK_EQUAL((sr = big_unsigned_max).numerator(), signed_max);
  847. ++big_unsigned_max;
  848. BOOST_CHECK_THROW(signed_rat(big_unsigned_max).numerator(), std::domain_error);
  849. BOOST_CHECK_THROW(signed_rat(big_unsigned_max, 1).numerator(), std::domain_error);
  850. BOOST_CHECK_THROW(signed_rat(1, big_unsigned_max).denominator(), std::domain_error);
  851. BOOST_CHECK_THROW(sr.assign(big_unsigned_max, 1).numerator(), std::domain_error);
  852. BOOST_CHECK_THROW(sr.assign(1, big_unsigned_max).denominator(), std::domain_error);
  853. BOOST_CHECK_THROW((sr = big_unsigned_max).numerator(), std::domain_error);
  854. boost::uint16_t small_unsigned_max = signed_max;
  855. BOOST_CHECK_EQUAL(signed_rat(small_unsigned_max).numerator(), small_unsigned_max);
  856. BOOST_CHECK_EQUAL(signed_rat(small_unsigned_max, 1).numerator(), small_unsigned_max);
  857. BOOST_CHECK_EQUAL(signed_rat(1, small_unsigned_max).denominator(), small_unsigned_max);
  858. BOOST_CHECK_EQUAL(sr.assign(small_unsigned_max, 1).numerator(), small_unsigned_max);
  859. BOOST_CHECK_EQUAL(sr.assign(1, small_unsigned_max).denominator(), small_unsigned_max);
  860. BOOST_CHECK_EQUAL((sr = small_unsigned_max).numerator(), small_unsigned_max);
  861. // Over again with unsigned rational type:
  862. typedef boost::rational<boost::uint32_t> unsigned_rat;
  863. unsigned_max = (std::numeric_limits<boost::uint32_t>::max)();
  864. BOOST_CHECK_EQUAL(unsigned_rat(unsigned_max).numerator(), unsigned_max);
  865. BOOST_CHECK_EQUAL(unsigned_rat(unsigned_max, 1).numerator(), unsigned_max);
  866. BOOST_CHECK_EQUAL(unsigned_rat(1, unsigned_max).denominator(), unsigned_max);
  867. unsigned_rat ur;
  868. BOOST_CHECK_EQUAL((ur = unsigned_max).numerator(), unsigned_max);
  869. BOOST_CHECK_EQUAL(ur.assign(unsigned_max, 1).numerator(), unsigned_max);
  870. BOOST_CHECK_EQUAL(ur.assign(1, unsigned_max).denominator(), unsigned_max);
  871. big_unsigned_max = unsigned_max;
  872. BOOST_CHECK_EQUAL(unsigned_rat(big_unsigned_max).numerator(), big_unsigned_max);
  873. BOOST_CHECK_EQUAL(unsigned_rat(big_unsigned_max, 1).numerator(), big_unsigned_max);
  874. BOOST_CHECK_EQUAL(unsigned_rat(1, big_unsigned_max).denominator(), big_unsigned_max);
  875. BOOST_CHECK_EQUAL((ur = big_unsigned_max).numerator(), big_unsigned_max);
  876. BOOST_CHECK_EQUAL(ur.assign(big_unsigned_max, 1).numerator(), big_unsigned_max);
  877. BOOST_CHECK_EQUAL(ur.assign(1, big_unsigned_max).denominator(), big_unsigned_max);
  878. ++big_unsigned_max;
  879. BOOST_CHECK_THROW(unsigned_rat(big_unsigned_max).numerator(), std::domain_error);
  880. BOOST_CHECK_THROW(unsigned_rat(big_unsigned_max, 1).numerator(), std::domain_error);
  881. BOOST_CHECK_THROW(unsigned_rat(1, big_unsigned_max).denominator(), std::domain_error);
  882. BOOST_CHECK_THROW((ur = big_unsigned_max).numerator(), std::domain_error);
  883. BOOST_CHECK_THROW(ur.assign(big_unsigned_max, 1).numerator(), std::domain_error);
  884. BOOST_CHECK_THROW(ur.assign(1, big_unsigned_max).denominator(), std::domain_error);
  885. BOOST_CHECK_EQUAL(unsigned_rat(small_unsigned_max).numerator(), small_unsigned_max);
  886. BOOST_CHECK_EQUAL(unsigned_rat(small_unsigned_max, 1).numerator(), small_unsigned_max);
  887. BOOST_CHECK_EQUAL(unsigned_rat(1, small_unsigned_max).denominator(), small_unsigned_max);
  888. BOOST_CHECK_EQUAL((ur = small_unsigned_max).numerator(), small_unsigned_max);
  889. BOOST_CHECK_EQUAL(ur.assign(small_unsigned_max, 1).numerator(), small_unsigned_max);
  890. BOOST_CHECK_EQUAL(ur.assign(1, small_unsigned_max).denominator(), small_unsigned_max);
  891. BOOST_CHECK_EQUAL(unsigned_rat(signed_max).numerator(), signed_max);
  892. BOOST_CHECK_EQUAL(unsigned_rat(signed_max, 1).numerator(), signed_max);
  893. BOOST_CHECK_EQUAL(unsigned_rat(1, signed_max).denominator(), signed_max);
  894. BOOST_CHECK_EQUAL((ur = signed_max).numerator(), signed_max);
  895. BOOST_CHECK_EQUAL(ur.assign(signed_max, 1).numerator(), signed_max);
  896. BOOST_CHECK_EQUAL(ur.assign(1, signed_max).denominator(), signed_max);
  897. BOOST_CHECK_THROW(unsigned_rat(signed_min).numerator(), std::domain_error);
  898. BOOST_CHECK_THROW(unsigned_rat(signed_min, 1).numerator(), std::domain_error);
  899. BOOST_CHECK_THROW(unsigned_rat(1, signed_min).denominator(), std::domain_error);
  900. BOOST_CHECK_THROW((ur = signed_min).numerator(), std::domain_error);
  901. BOOST_CHECK_THROW(ur.assign(signed_min, 1).numerator(), std::domain_error);
  902. BOOST_CHECK_THROW(ur.assign(1, signed_min).denominator(), std::domain_error);
  903. big_signed_max = unsigned_max;
  904. BOOST_CHECK_EQUAL(unsigned_rat(big_signed_max).numerator(), unsigned_max);
  905. BOOST_CHECK_EQUAL(unsigned_rat(big_signed_max, 1).numerator(), unsigned_max);
  906. BOOST_CHECK_EQUAL(unsigned_rat(1, big_signed_max).denominator(), unsigned_max);
  907. BOOST_CHECK_EQUAL((ur = big_signed_max).numerator(), unsigned_max);
  908. BOOST_CHECK_EQUAL(ur.assign(big_signed_max, 1).numerator(), unsigned_max);
  909. BOOST_CHECK_EQUAL(ur.assign(1, big_signed_max).denominator(), unsigned_max);
  910. ++big_signed_max;
  911. BOOST_CHECK_THROW(unsigned_rat(big_signed_max).numerator(), std::domain_error);
  912. BOOST_CHECK_THROW(unsigned_rat(big_signed_max, 1).numerator(), std::domain_error);
  913. BOOST_CHECK_THROW(unsigned_rat(1, big_signed_max).denominator(), std::domain_error);
  914. BOOST_CHECK_THROW((ur = big_signed_max).numerator(), std::domain_error);
  915. BOOST_CHECK_THROW(ur.assign(big_signed_max, 1).numerator(), std::domain_error);
  916. BOOST_CHECK_THROW(ur.assign(1, big_signed_max).denominator(), std::domain_error);
  917. big_signed_max = -1;
  918. BOOST_CHECK_THROW(unsigned_rat(big_signed_max).numerator(), std::domain_error);
  919. BOOST_CHECK_THROW(unsigned_rat(big_signed_max, 1).numerator(), std::domain_error);
  920. BOOST_CHECK_THROW(unsigned_rat(1, big_signed_max).denominator(), std::domain_error);
  921. BOOST_CHECK_THROW((ur = big_signed_max).numerator(), std::domain_error);
  922. BOOST_CHECK_THROW(ur.assign(big_signed_max, 1).numerator(), std::domain_error);
  923. BOOST_CHECK_THROW(ur.assign(1, big_signed_max).denominator(), std::domain_error);
  924. BOOST_CHECK_EQUAL(unsigned_rat(small_signed_max).numerator(), small_signed_max);
  925. BOOST_CHECK_EQUAL(unsigned_rat(small_signed_max, 1).numerator(), small_signed_max);
  926. BOOST_CHECK_EQUAL(unsigned_rat(1, small_signed_max).denominator(), small_signed_max);
  927. BOOST_CHECK_EQUAL((ur = small_signed_max).numerator(), small_signed_max);
  928. BOOST_CHECK_EQUAL(ur.assign(small_signed_max, 1).numerator(), small_signed_max);
  929. BOOST_CHECK_EQUAL(ur.assign(1, small_signed_max).denominator(), small_signed_max);
  930. small_signed_max = -1;
  931. BOOST_CHECK_THROW(unsigned_rat(small_signed_max).numerator(), std::domain_error);
  932. BOOST_CHECK_THROW(unsigned_rat(small_signed_max, 1).numerator(), std::domain_error);
  933. BOOST_CHECK_THROW(unsigned_rat(1, small_signed_max).denominator(), std::domain_error);
  934. BOOST_CHECK_THROW((ur = small_signed_max).numerator(), std::domain_error);
  935. BOOST_CHECK_THROW(ur.assign(small_signed_max, 1).numerator(), std::domain_error);
  936. BOOST_CHECK_THROW(ur.assign(1, small_signed_max).denominator(), std::domain_error);
  937. }
  938. BOOST_AUTO_TEST_SUITE_END()
  939. // The non-basic rational operations suite
  940. BOOST_AUTO_TEST_SUITE( rational_extras_suite )
  941. #ifndef BOOST_NO_IOSTREAM
  942. // Output test
  943. BOOST_AUTO_TEST_CASE_TEMPLATE( rational_output_test, T, all_signed_test_types )
  944. {
  945. using namespace std;
  946. typedef boost::rational<T> rational_type;
  947. // Basic test
  948. ostringstream oss;
  949. oss << rational_type( 44, 14 );
  950. BOOST_CHECK_EQUAL( oss.str(), "22/7" );
  951. // Width
  952. oss.clear(); oss.str( "" );
  953. oss << setw( 5 ) << setfill('*') << rational_type( 1, 2 ) << 'r';
  954. BOOST_CHECK_EQUAL( oss.str(), "**1/2r" ); // not "****1/2r"
  955. // Positive-sign
  956. oss.clear(); oss.str( "" );
  957. oss << showpos << rational_type( 2, 3 ) << noshowpos;
  958. BOOST_CHECK_EQUAL( oss.str(), "+2/3" ); // not "+2/+3"
  959. // Internal padding
  960. oss.clear(); oss.str( "" );
  961. oss << setw( 8 ) << internal << rational_type( 36, -15 ) << right << 'r';
  962. BOOST_CHECK_EQUAL( oss.str(), "-***12/5r" ); // not "-*****12/5r"
  963. // Showbase prefix
  964. oss.clear(); oss.str( "" );
  965. oss << showbase << hex << rational_type( 34, 987 ) << noshowbase << dec;
  966. BOOST_CHECK_EQUAL( oss.str(), "0x22/3db" ); // not "0x22/0x3db"
  967. }
  968. // Input test, failing
  969. BOOST_AUTO_TEST_CASE_TEMPLATE( rational_input_failing_test, T,
  970. all_signed_test_types )
  971. {
  972. std::istringstream iss( "" );
  973. boost::rational<T> r;
  974. iss >> r;
  975. BOOST_CHECK( !iss );
  976. BOOST_CHECK( !iss.bad() );
  977. iss.clear();
  978. iss.str( "42" );
  979. iss >> r;
  980. BOOST_CHECK( !iss );
  981. iss.clear();
  982. iss.str( "57A" );
  983. iss >> r;
  984. BOOST_CHECK( !iss );
  985. iss.clear();
  986. iss.str( "20-20" );
  987. iss >> r;
  988. BOOST_CHECK( !iss );
  989. iss.clear();
  990. iss.str( "1/" );
  991. iss >> r;
  992. BOOST_CHECK( !iss );
  993. iss.clear();
  994. iss.str( "1/ 2" );
  995. iss >> r;
  996. BOOST_CHECK( !iss );
  997. iss.clear();
  998. iss.str( "1 /2" );
  999. iss >> r;
  1000. BOOST_CHECK( !iss );
  1001. // Illegal value check(s)
  1002. typedef std::numeric_limits<T> limits_type;
  1003. iss.clear();
  1004. iss.str( "3/0" );
  1005. iss >> r;
  1006. BOOST_CHECK( !iss );
  1007. if ( limits_type::is_signed && limits_type::is_bounded &&
  1008. limits_type::min BOOST_PREVENT_MACRO_SUBSTITUTION () +
  1009. limits_type::max BOOST_PREVENT_MACRO_SUBSTITUTION () < T(0) )
  1010. {
  1011. std::ostringstream oss;
  1012. oss << 1 << '/' << limits_type::min BOOST_PREVENT_MACRO_SUBSTITUTION ();
  1013. iss.clear();
  1014. iss.str( oss.str() );
  1015. iss.exceptions( std::ios::failbit );
  1016. BOOST_CHECK( iss.good() );
  1017. BOOST_CHECK_THROW( iss >> r, boost::bad_rational );
  1018. BOOST_CHECK( iss.fail() && !iss.bad() );
  1019. iss.exceptions( std::ios::goodbit );
  1020. }
  1021. }
  1022. // Input test, passing
  1023. BOOST_AUTO_TEST_CASE_TEMPLATE( rational_input_passing_test, T,
  1024. all_signed_test_types )
  1025. {
  1026. typedef boost::rational<T> rational_type;
  1027. std::istringstream iss( "1/2 12" );
  1028. rational_type r;
  1029. int n = 0;
  1030. BOOST_CHECK( iss >> r >> n );
  1031. BOOST_CHECK_EQUAL( r, rational_type(1, 2) );
  1032. BOOST_CHECK_EQUAL( n, 12 );
  1033. iss.clear();
  1034. iss.str( "34/67" );
  1035. BOOST_CHECK( iss >> r );
  1036. BOOST_CHECK_EQUAL( r, rational_type(34, 67) );
  1037. iss.clear();
  1038. iss.str( "-3/-6" );
  1039. BOOST_CHECK( iss >> r );
  1040. BOOST_CHECK_EQUAL( r, rational_type(1, 2) );
  1041. }
  1042. #endif // BOOST_NO_IOSTREAM
  1043. // Conversion test
  1044. BOOST_AUTO_TEST_CASE( rational_cast_test )
  1045. {
  1046. // Note that these are not generic. The problem is that rational_cast<T>
  1047. // requires a conversion from IntType to T. However, for a user-defined
  1048. // IntType, it is not possible to define such a conversion except as an
  1049. // "operator T()". This causes problems with overloading resolution.
  1050. boost::rational<int> const half( 1, 2 );
  1051. BOOST_CHECK_CLOSE( boost::rational_cast<double>(half), 0.5, 0.01 );
  1052. BOOST_CHECK_EQUAL( boost::rational_cast<int>(half), 0 );
  1053. BOOST_CHECK_EQUAL( boost::rational_cast<MyInt>(half), MyInt() );
  1054. BOOST_CHECK_EQUAL( boost::rational_cast<boost::rational<MyInt> >(half),
  1055. boost::rational<MyInt>(1, 2) );
  1056. // Conversions via explicit-marked constructors
  1057. // (Note that the "explicit" mark prevents conversion to
  1058. // boost::rational<MyOverflowingUnsigned>.)
  1059. boost::rational<MyInt> const threehalves( 3, 2 );
  1060. BOOST_CHECK_EQUAL( boost::rational_cast<MyOverflowingUnsigned>(threehalves),
  1061. MyOverflowingUnsigned(1u) );
  1062. //
  1063. // Converting constructor should throw if a bad rational number results:
  1064. //
  1065. BOOST_CHECK_THROW(boost::rational<short>(boost::rational<long>(1, 1 << sizeof(short) * CHAR_BIT)), boost::bad_rational);
  1066. //
  1067. // New tests from checked narrowing conversions:
  1068. //
  1069. BOOST_CHECK_THROW(boost::rational<unsigned>(-1), boost::bad_rational);
  1070. BOOST_CHECK_THROW(boost::rational<unsigned>(-1, 1), boost::bad_rational);
  1071. BOOST_CHECK_THROW(boost::rational<unsigned>(1, -1), boost::bad_rational);
  1072. unsigned ui_max = (std::numeric_limits<unsigned>::max)();
  1073. BOOST_CHECK_THROW(boost::rational<int>(static_cast<unsigned>(ui_max)), boost::bad_rational);
  1074. BOOST_CHECK_THROW(boost::rational<int>(ui_max, 1u), boost::bad_rational);
  1075. BOOST_CHECK_THROW(boost::rational<int>(1u, ui_max), boost::bad_rational);
  1076. //
  1077. // Check assignments that should succeed from both wider and narrower types:
  1078. //
  1079. boost::rational<boost::int32_t> rat;
  1080. #ifndef BOOST_NO_INT64_T
  1081. boost::int64_t ll, ll1(1);
  1082. boost::uint64_t ull, ull1(1);
  1083. boost::int32_t imax = (std::numeric_limits<boost::int32_t>::max)();
  1084. boost::int32_t imin = (std::numeric_limits<boost::int32_t>::min)();
  1085. ll = imax;
  1086. rat.assign(ll, ll1);
  1087. BOOST_CHECK_EQUAL(rat.numerator(), imax);
  1088. BOOST_CHECK_EQUAL(rat.denominator(), 1);
  1089. ++ll;
  1090. BOOST_CHECK_THROW(rat.assign(ll, ll1), boost::bad_rational);
  1091. ll = imin;
  1092. rat.assign(ll, ll1);
  1093. BOOST_CHECK_EQUAL(rat.numerator(), imin);
  1094. BOOST_CHECK_EQUAL(rat.denominator(), 1);
  1095. --ll;
  1096. BOOST_CHECK_THROW(rat.assign(ll, ll1), boost::bad_rational);
  1097. ull = imax;
  1098. rat.assign(ull, ull1);
  1099. BOOST_CHECK_EQUAL(rat.numerator(), imax);
  1100. BOOST_CHECK_EQUAL(rat.denominator(), 1);
  1101. ++ull;
  1102. BOOST_CHECK_THROW(rat.assign(ull, ull1), boost::bad_rational);
  1103. ull = 0;
  1104. rat.assign(ull, ull1);
  1105. BOOST_CHECK_EQUAL(rat.numerator(), 0);
  1106. BOOST_CHECK_EQUAL(rat.denominator(), 1);
  1107. #endif
  1108. boost::int16_t smax = (std::numeric_limits<boost::int16_t>::max)();
  1109. boost::int16_t smin = (std::numeric_limits<boost::int16_t>::min)();
  1110. boost::int16_t s1 = 1;
  1111. rat.assign(smax, s1);
  1112. BOOST_CHECK_EQUAL(rat.numerator(), smax);
  1113. BOOST_CHECK_EQUAL(rat.denominator(), 1);
  1114. rat.assign(smin, s1);
  1115. BOOST_CHECK_EQUAL(rat.numerator(), smin);
  1116. BOOST_CHECK_EQUAL(rat.denominator(), 1);
  1117. boost::uint16_t usmax = (std::numeric_limits<boost::uint16_t>::max)();
  1118. boost::uint16_t usmin = (std::numeric_limits<boost::uint16_t>::min)();
  1119. boost::uint16_t us1 = 1;
  1120. rat.assign(usmax, us1);
  1121. BOOST_CHECK_EQUAL(rat.numerator(), usmax);
  1122. BOOST_CHECK_EQUAL(rat.denominator(), 1);
  1123. rat.assign(usmin, us1);
  1124. BOOST_CHECK_EQUAL(rat.numerator(), usmin);
  1125. BOOST_CHECK_EQUAL(rat.denominator(), 1);
  1126. //
  1127. // Over again with unsigned rational:
  1128. //
  1129. boost::rational<boost::uint32_t> urat;
  1130. unsigned uimax = (std::numeric_limits<boost::uint32_t>::max)();
  1131. unsigned uimin = (std::numeric_limits<boost::uint32_t>::min)();
  1132. #ifndef BOOST_NO_INT64_T
  1133. ll = uimax;
  1134. urat.assign(ll, ll1);
  1135. BOOST_CHECK_EQUAL(urat.numerator(), uimax);
  1136. BOOST_CHECK_EQUAL(urat.denominator(), 1);
  1137. ++ll;
  1138. BOOST_CHECK_THROW(urat.assign(ll, ll1), boost::bad_rational);
  1139. ll = uimin;
  1140. urat.assign(ll, ll1);
  1141. BOOST_CHECK_EQUAL(urat.numerator(), uimin);
  1142. BOOST_CHECK_EQUAL(urat.denominator(), 1);
  1143. --ll;
  1144. BOOST_CHECK_THROW(urat.assign(ll, ll1), boost::bad_rational);
  1145. ull = uimax;
  1146. urat.assign(ull, ull1);
  1147. BOOST_CHECK_EQUAL(urat.numerator(), uimax);
  1148. BOOST_CHECK_EQUAL(urat.denominator(), 1);
  1149. ++ull;
  1150. BOOST_CHECK_THROW(urat.assign(ull, ull1), boost::bad_rational);
  1151. ull = 0;
  1152. urat.assign(ull, ull1);
  1153. BOOST_CHECK_EQUAL(urat.numerator(), 0);
  1154. BOOST_CHECK_EQUAL(urat.denominator(), 1);
  1155. #endif
  1156. smin = 0;
  1157. s1 = 1;
  1158. urat.assign(smax, s1);
  1159. BOOST_CHECK_EQUAL(urat.numerator(), smax);
  1160. BOOST_CHECK_EQUAL(urat.denominator(), 1);
  1161. urat.assign(smin, s1);
  1162. BOOST_CHECK_EQUAL(urat.numerator(), smin);
  1163. BOOST_CHECK_EQUAL(urat.denominator(), 1);
  1164. urat.assign(usmax, us1);
  1165. BOOST_CHECK_EQUAL(urat.numerator(), usmax);
  1166. BOOST_CHECK_EQUAL(urat.denominator(), 1);
  1167. urat.assign(usmin, us1);
  1168. BOOST_CHECK_EQUAL(urat.numerator(), usmin);
  1169. BOOST_CHECK_EQUAL(urat.denominator(), 1);
  1170. //
  1171. // Conversions that must not be allowed:
  1172. //
  1173. BOOST_STATIC_ASSERT(!boost::is_convertible<float, boost::rational<int> >::value);
  1174. BOOST_STATIC_ASSERT(!boost::is_convertible<double, boost::rational<int> >::value);
  1175. BOOST_STATIC_ASSERT(!boost::is_convertible<long double, boost::rational<int> >::value);
  1176. // And ones that should:
  1177. BOOST_STATIC_ASSERT(boost::is_convertible<char, boost::rational<int> >::value);
  1178. BOOST_STATIC_ASSERT(boost::is_convertible<signed char, boost::rational<int> >::value);
  1179. BOOST_STATIC_ASSERT(boost::is_convertible<unsigned char, boost::rational<int> >::value);
  1180. BOOST_STATIC_ASSERT(boost::is_convertible<short, boost::rational<int> >::value);
  1181. BOOST_STATIC_ASSERT(boost::is_convertible<unsigned short, boost::rational<int> >::value);
  1182. BOOST_STATIC_ASSERT(boost::is_convertible<int, boost::rational<int> >::value);
  1183. BOOST_STATIC_ASSERT(boost::is_convertible<unsigned int, boost::rational<int> >::value);
  1184. BOOST_STATIC_ASSERT(boost::is_convertible<long, boost::rational<int> >::value);
  1185. BOOST_STATIC_ASSERT(boost::is_convertible<unsigned long, boost::rational<int> >::value);
  1186. }
  1187. #ifndef BOOST_NO_MEMBER_TEMPLATES
  1188. // Cross-conversion constructor test
  1189. BOOST_AUTO_TEST_CASE( rational_cross_constructor_test )
  1190. {
  1191. // This template will be repeated a lot.
  1192. using boost::rational;
  1193. // Create a bunch of explicit conversions.
  1194. rational<int> const half_i( 2, 4 );
  1195. rational<unsigned> const half_u( half_i );
  1196. rational<MyInt> const half_mi( half_i );
  1197. rational<MyOverflowingUnsigned> const half_mu1(half_u), half_mu2(half_mi);
  1198. BOOST_CHECK_EQUAL( half_u.numerator(), 1u );
  1199. BOOST_CHECK_EQUAL( half_u.denominator(), 2u );
  1200. BOOST_CHECK_EQUAL( half_mi.numerator(), MyInt(1) );
  1201. BOOST_CHECK_EQUAL( half_mi.denominator(), MyInt(2) );
  1202. BOOST_CHECK_EQUAL( half_mu1.numerator(), MyOverflowingUnsigned(1u) );
  1203. BOOST_CHECK_EQUAL( half_mu1.denominator(), MyOverflowingUnsigned(2u) );
  1204. BOOST_CHECK_EQUAL( half_mu2.numerator(), MyOverflowingUnsigned(1u) );
  1205. BOOST_CHECK_EQUAL( half_mu2.denominator(), MyOverflowingUnsigned(2u) );
  1206. #if 0
  1207. // This will fail since it needs an implicit conversion.
  1208. // (Try it if your compiler supports C++11 lambdas.)
  1209. BOOST_CHECK( [](rational<unsigned> x){return !!x;}(half_i) );
  1210. #endif
  1211. // Translation from a built-in unsigned type to a signed one is
  1212. // implementation-defined, so hopefully we won't get a trap value.
  1213. // (We're counting on static_cast<int>(UINT_MAX) being negative.)
  1214. rational<unsigned> const too_small( 1u, UINT_MAX );
  1215. rational<int> receiver;
  1216. BOOST_CHECK_THROW( receiver=rational<int>(too_small), boost::bad_rational );
  1217. }
  1218. #endif // BOOST_NO_MEMBER_TEMPLATES
  1219. // Dice tests (a non-main test)
  1220. BOOST_AUTO_TEST_CASE_TEMPLATE( dice_roll_test, T, all_signed_test_types )
  1221. {
  1222. typedef boost::rational<T> rational_type;
  1223. // Determine the mean number of times a fair six-sided die
  1224. // must be thrown until each side has appeared at least once.
  1225. rational_type r = T( 0 );
  1226. for ( int i = 1 ; i <= 6 ; ++i )
  1227. {
  1228. r += rational_type( 1, i );
  1229. }
  1230. r *= static_cast<T>( 6 );
  1231. BOOST_CHECK_EQUAL( r, rational_type(147, 10) );
  1232. }
  1233. BOOST_AUTO_TEST_SUITE_END()
  1234. // The bugs, patches, and requests checking suite
  1235. BOOST_AUTO_TEST_SUITE( bug_patch_request_suite )
  1236. // "rational operator< can overflow"
  1237. BOOST_AUTO_TEST_CASE( bug_798357_test )
  1238. {
  1239. // Choose values such that rational-number comparisons will overflow if
  1240. // the multiplication method (n1/d1 ? n2/d2 == n1*d2 ? n2*d1) is used.
  1241. // (And make sure that the large components are relatively prime, so they
  1242. // won't partially cancel to make smaller, more reasonable, values.)
  1243. unsigned const n1 = UINT_MAX - 2u, d1 = UINT_MAX - 1u;
  1244. unsigned const n2 = d1, d2 = UINT_MAX;
  1245. boost::rational<MyOverflowingUnsigned> const r1( n1, d1 ), r2( n2, d2 );
  1246. BOOST_REQUIRE_EQUAL( boost::integer::gcd(n1, d1), 1u );
  1247. BOOST_REQUIRE_EQUAL( boost::integer::gcd(n2, d2), 1u );
  1248. BOOST_REQUIRE( n1 > UINT_MAX / d2 );
  1249. BOOST_REQUIRE( n2 > UINT_MAX / d1 );
  1250. BOOST_CHECK( r1 < r2 );
  1251. BOOST_CHECK( !(r1 < r1) );
  1252. BOOST_CHECK( !(r2 < r1) );
  1253. }
  1254. // "rational::operator< fails for unsigned value types"
  1255. BOOST_AUTO_TEST_CASE( patch_1434821_test )
  1256. {
  1257. // If a zero-rational v. positive-integer comparison involves negation, then
  1258. // it may fail with unsigned types, which wrap around (for built-ins) or
  1259. // throw/be-undefined (for user-defined types).
  1260. boost::rational<unsigned> const r( 0u );
  1261. BOOST_CHECK( r < 1u );
  1262. }
  1263. // "rational.hpp::gcd returns a negative value sometimes"
  1264. BOOST_AUTO_TEST_CASE( patch_1438626_test )
  1265. {
  1266. // The issue only manifests with 2's-complement integers that use their
  1267. // entire range of bits. [This means that ln(-INT_MIN)/ln(2) is an integer
  1268. // and INT_MAX + INT_MIN == -1.] The common computer platforms match this.
  1269. #if (INT_MAX + INT_MIN == -1) && ((INT_MAX ^ INT_MIN) == -1)
  1270. // If a GCD routine takes the absolute value of an argument only before
  1271. // processing, it won't realize that -INT_MIN -> INT_MIN (i.e. no change
  1272. // from negation) and will propagate a negative sign to its result.
  1273. BOOST_REQUIRE_EQUAL( boost::integer::gcd(INT_MIN, 6), 2 );
  1274. // That is bad if the rational number type does not check for that
  1275. // possibility during normalization.
  1276. boost::rational<int> const r1( INT_MIN / 2 + 3, 6 ),
  1277. r2( INT_MIN / 2 - 3, 6 ), r3 = r1 + r2;
  1278. // If the error happens, the signs of the components will be switched.
  1279. // (The numerators' sum is INT_MIN, and its GCD with 6 would be negated.)
  1280. BOOST_CHECK_EQUAL( r3.numerator(), INT_MIN / 2 );
  1281. BOOST_CHECK_EQUAL( r3.denominator(), 3 );
  1282. #endif
  1283. }
  1284. // The bug/patch numbers for the above 3 tests are from our SourceForge repo
  1285. // before we moved to our own SVN & Trac server. At the time this note is
  1286. // written, it seems that SourceForge has reset their tracking numbers at least
  1287. // once, so I don't know how to recover those old tickets. The ticket numbers
  1288. // for the following tests are from our SVN/Trac repo.
  1289. //"narrowing conversion error with -std=c++0x in operator< with int_type != int"
  1290. BOOST_AUTO_TEST_CASE( ticket_5855_test )
  1291. {
  1292. // The internals of operator< currently store a structure of two int_type
  1293. // (where int_type is the component type of a boost::rational template
  1294. // class) and two computed types. These computed types, results of
  1295. // arithmetic operations among int_type values, are either int_type
  1296. // themselves or a larger type that can implicitly convert to int_type.
  1297. // Those conversions aren't usually a problem. But when an arithmetic
  1298. // operation involving two values of a built-in scalar type smaller than int
  1299. // are involved, the result is an int. But the resulting int-to-shorter
  1300. // conversion is considered narrowing, resulting in a warning or error on
  1301. // some compilers. Notably, C++11 compilers are supposed to consider it an
  1302. // error.
  1303. //
  1304. // The solution is to force an explicit conversion, although it's otherwise
  1305. // not needed. (The compiler can rescind the narrowing warning if the
  1306. // results of the larger type still fit in the smaller one, and that proof
  1307. // can be generated at constexpr time.)
  1308. typedef short shorter_than_int_type;
  1309. typedef boost::rational<shorter_than_int_type> rational_type;
  1310. bool const dummy = rational_type() < rational_type();
  1311. BOOST_REQUIRE( !dummy );
  1312. }
  1313. // "rational::assign" doesn't even have the basic guarantee
  1314. BOOST_AUTO_TEST_CASE( ticket_9067_test )
  1315. {
  1316. using boost::rational;
  1317. using boost::integer::gcd;
  1318. rational<int> a( 6, -8 );
  1319. // Normalize to maintain invariants
  1320. BOOST_CHECK_EQUAL( a.numerator(), -3 );
  1321. BOOST_CHECK_EQUAL( a.denominator(), 4 );
  1322. BOOST_CHECK( a.denominator() > 0 );
  1323. BOOST_CHECK_EQUAL( gcd(a.numerator(), a.denominator()), 1 );
  1324. // Do we maintain the basic guarantee after a failed component-assign?
  1325. BOOST_CHECK_THROW( a.assign(1, 0), boost::bad_rational );
  1326. BOOST_CHECK_NE( a.denominator(), 0 );
  1327. BOOST_CHECK( a.denominator() > 0 );
  1328. BOOST_CHECK_EQUAL( gcd(a.numerator(), a.denominator()), 1 );
  1329. // Do we get the strong guarantee?
  1330. BOOST_CHECK_EQUAL( a.numerator(), -3 );
  1331. BOOST_CHECK_EQUAL( a.denominator(), 4 );
  1332. #if INT_MIN + INT_MAX < 0
  1333. // Try an example without a zero-denominator
  1334. a = rational<int>( -9, 12 );
  1335. BOOST_CHECK_EQUAL( a.numerator(), -3 );
  1336. BOOST_CHECK_EQUAL( a.denominator(), 4 );
  1337. BOOST_CHECK( a.denominator() > 0 );
  1338. BOOST_CHECK_EQUAL( gcd(a.numerator(), a.denominator()), 1 );
  1339. BOOST_CHECK_THROW( a.assign(-(INT_MIN + 1), INT_MIN), boost::bad_rational );
  1340. BOOST_CHECK( a.denominator() > 0 );
  1341. BOOST_CHECK_EQUAL( gcd(a.numerator(), a.denominator()), 1 );
  1342. BOOST_CHECK_EQUAL( a.numerator(), -3 );
  1343. BOOST_CHECK_EQUAL( a.denominator(), 4 );
  1344. #endif
  1345. }
  1346. BOOST_AUTO_TEST_SUITE_END()