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.)
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.
12 * Incorporated into the boost rational number library, and modified and
13 * extended, by Paul Moore, with permission.
16 // boostinspect:nolicense (don't complain about the lack of a Boost license)
17 // (Stephen Silver hasn't been contacted yet for permission to change the
18 // license. If Paul Moore's permission is also needed, then that's a problem
19 // since he hasn't been in contact for years.)
22 // 30 Aug 13 Add bug-test of assignments holding the basic and/or strong
23 // guarantees (Daryle Walker)
24 // 27 Aug 13 Add test for cross-version constructor template (Daryle Walker)
25 // 23 Aug 13 Add bug-test of narrowing conversions during order comparison;
26 // spell logical-negation in it as "!" because MSVC won't accept
27 // "not" (Daryle Walker)
28 // 05 Nov 06 Add testing of zero-valued denominators & divisors; casting with
29 // types that are not implicitly convertible (Daryle Walker)
30 // 04 Nov 06 Resolve GCD issue with depreciation (Daryle Walker)
31 // 02 Nov 06 Add testing for operator<(int_type) w/ unsigneds (Daryle Walker)
32 // 31 Oct 06 Add testing for operator<(rational) overflow (Daryle Walker)
33 // 18 Oct 06 Various fixes for old compilers (Joaquín M López Muñoz)
34 // 27 Dec 05 Add testing for Boolean conversion operator (Daryle Walker)
35 // 24 Dec 05 Change code to use Boost.Test (Daryle Walker)
36 // 04 Mar 01 Patches for Intel C++ and GCC (David Abrahams)
38 #define BOOST_TEST_MAIN "Boost::Rational unit tests"
40 #include <boost/config.hpp>
41 #include <boost/limits.hpp>
42 #include <boost/mpl/list.hpp>
43 #include <boost/operators.hpp>
44 #include <boost/preprocessor/stringize.hpp>
45 #include <boost/integer/common_factor_rt.hpp>
46 #include <boost/cstdint.hpp>
48 #include <boost/rational.hpp>
50 #include <boost/test/unit_test.hpp>
63 #pragma warning(disable:4146)
67 // We can override this on the compile, as -DINT_TYPE=short or whatever.
68 // The default test is against rational<long>.
75 class MyOverflowingUnsigned
;
77 // This is a trivial user-defined wrapper around the built in int type.
78 // It can be used as a test type for rational<>
79 class MyInt
: boost::operators
<MyInt
>
81 friend class MyOverflowingUnsigned
;
84 MyInt(int n
= 0) : val(n
) {}
85 friend MyInt
operator+ (const MyInt
&);
86 friend MyInt
operator- (const MyInt
&);
87 MyInt
& operator+= (const MyInt
& rhs
) { val
+= rhs
.val
; return *this; }
88 MyInt
& operator-= (const MyInt
& rhs
) { val
-= rhs
.val
; return *this; }
89 MyInt
& operator*= (const MyInt
& rhs
) { val
*= rhs
.val
; return *this; }
90 MyInt
& operator/= (const MyInt
& rhs
) { val
/= rhs
.val
; return *this; }
91 MyInt
& operator%= (const MyInt
& rhs
) { val
%= rhs
.val
; return *this; }
92 MyInt
& operator|= (const MyInt
& rhs
) { val
|= rhs
.val
; return *this; }
93 MyInt
& operator&= (const MyInt
& rhs
) { val
&= rhs
.val
; return *this; }
94 MyInt
& operator^= (const MyInt
& rhs
) { val
^= rhs
.val
; return *this; }
95 const MyInt
& operator++() { ++val
; return *this; }
96 const MyInt
& operator--() { --val
; return *this; }
97 bool operator< (const MyInt
& rhs
) const { return val
< rhs
.val
; }
98 bool operator== (const MyInt
& rhs
) const { return val
== rhs
.val
; }
99 bool operator! () const { return !val
; }
100 friend std::istream
& operator>>(std::istream
&, MyInt
&);
101 friend std::ostream
& operator<<(std::ostream
&, const MyInt
&);
104 inline MyInt
operator+(const MyInt
& rhs
) { return rhs
; }
105 inline MyInt
operator-(const MyInt
& rhs
) { return MyInt(-rhs
.val
); }
106 inline std::istream
& operator>>(std::istream
& is
, MyInt
& i
) { is
>> i
.val
; return is
; }
107 inline std::ostream
& operator<<(std::ostream
& os
, const MyInt
& i
) { os
<< i
.val
; return os
; }
108 inline MyInt
abs(MyInt rhs
) { if (rhs
< MyInt()) rhs
= -rhs
; return rhs
; }
110 // This is an "unsigned" wrapper, that throws on overflow. It can be used to
111 // test rational<> when an operation goes out of bounds.
112 class MyOverflowingUnsigned
113 : private boost::unit_steppable
<MyOverflowingUnsigned
>
114 , private boost::ordered_euclidian_ring_operators1
<MyOverflowingUnsigned
>
116 // Helper type-aliases
117 typedef MyOverflowingUnsigned self_type
;
118 typedef unsigned self_type::* bool_type
;
124 // Exception base class
125 class exception_base
{ protected: virtual ~exception_base() throw() {} };
127 // Divide-by-zero exception class
128 class divide_by_0_error
129 : public virtual exception_base
130 , public std::domain_error
133 explicit divide_by_0_error( std::string
const &w
)
134 : std::domain_error( w
) {}
136 virtual ~divide_by_0_error() throw() {}
139 // Overflow exception class
140 class overflowing_error
141 : public virtual exception_base
142 , public std::overflow_error
145 explicit overflowing_error( std::string
const &w
)
146 : std::overflow_error( w
) {}
148 virtual ~overflowing_error() throw() {}
151 // Lifetime management (use automatic dtr & copy-ctr)
152 MyOverflowingUnsigned( unsigned v
= 0 ) : v_( v
) {}
153 explicit MyOverflowingUnsigned( MyInt
const &m
) : v_( m
.val
) {}
155 // Operators (use automatic copy-assignment); arithmetic & comparison only
156 self_type
& operator ++()
158 if ( this->v_
== UINT_MAX
) throw overflowing_error( "increment" );
162 self_type
& operator --()
164 if ( !this->v_
) throw overflowing_error( "decrement" );
169 operator bool_type() const { return this->v_
? &self_type::v_
: 0; }
171 bool operator !() const { return !this->v_
; }
172 self_type
operator +() const { return self_type( +this->v_
); }
173 self_type
operator -() const { return self_type( -this->v_
); }
175 bool operator <(self_type
const &r
) const { return this->v_
< r
.v_
; }
176 bool operator ==(self_type
const &r
) const { return this->v_
== r
.v_
; }
178 self_type
& operator *=( self_type
const &r
)
180 if ( r
.v_
&& this->v_
> UINT_MAX
/ r
.v_
)
182 throw overflowing_error( "oversized factors" );
187 self_type
& operator /=( self_type
const &r
)
189 if ( !r
.v_
) throw divide_by_0_error( "division" );
193 self_type
& operator %=( self_type
const &r
)
195 if ( !r
.v_
) throw divide_by_0_error( "modulus" );
199 self_type
& operator +=( self_type
const &r
)
201 if ( this->v_
> UINT_MAX
- r
.v_
)
203 throw overflowing_error( "oversized addends" );
208 self_type
& operator -=( self_type
const &r
)
210 if ( this->v_
< r
.v_
)
212 throw overflowing_error( "oversized subtrahend" );
219 template < typename Ch
, class Tr
>
220 friend std::basic_istream
<Ch
, Tr
> &
221 operator >>( std::basic_istream
<Ch
, Tr
> &i
, self_type
&x
)
222 { return i
>> x
.v_
; }
224 template < typename Ch
, class Tr
>
225 friend std::basic_ostream
<Ch
, Tr
> &
226 operator <<( std::basic_ostream
<Ch
, Tr
> &o
, self_type
const &x
)
227 { return o
<< x
.v_
; }
229 }; // MyOverflowingUnsigned
231 inline MyOverflowingUnsigned
abs( MyOverflowingUnsigned
const &x
) { return x
; }
236 // Specialize numeric_limits for the custom types
241 class numeric_limits
< MyInt
>
243 typedef numeric_limits
<int> limits_type
;
246 static const bool is_specialized
= limits_type::is_specialized
;
248 static MyInt min
BOOST_PREVENT_MACRO_SUBSTITUTION () throw() { return
249 limits_type::min
BOOST_PREVENT_MACRO_SUBSTITUTION (); }
250 static MyInt max
BOOST_PREVENT_MACRO_SUBSTITUTION () throw() { return
251 limits_type::max
BOOST_PREVENT_MACRO_SUBSTITUTION (); }
252 static MyInt
lowest() throw() { return min BOOST_PREVENT_MACRO_SUBSTITUTION
255 static const int digits
= limits_type::digits
;
256 static const int digits10
= limits_type::digits10
;
257 static const int max_digits10
= 0; // C++11
258 static const bool is_signed
= limits_type::is_signed
;
259 static const bool is_integer
= limits_type::is_integer
;
260 static const bool is_exact
= limits_type::is_exact
;
261 static const int radix
= limits_type::radix
;
262 static MyInt
epsilon() throw() { return limits_type::epsilon(); }
263 static MyInt
round_error() throw() { return limits_type::round_error(); }
265 static const int min_exponent
= limits_type::min_exponent
;
266 static const int min_exponent10
= limits_type::min_exponent10
;
267 static const int max_exponent
= limits_type::max_exponent
;
268 static const int max_exponent10
= limits_type::max_exponent10
;
270 static const bool has_infinity
= limits_type::has_infinity
;
271 static const bool has_quiet_NaN
= limits_type::has_quiet_NaN
;
272 static const bool has_signaling_NaN
= limits_type::has_signaling_NaN
;
273 static const float_denorm_style has_denorm
= limits_type::has_denorm
;
274 static const bool has_denorm_loss
= limits_type::has_denorm_loss
;
276 static MyInt
infinity() throw() { return limits_type::infinity(); }
277 static MyInt
quiet_NaN() throw() { return limits_type::quiet_NaN(); }
278 static MyInt
signaling_NaN() throw() {return limits_type::signaling_NaN();}
279 static MyInt
denorm_min() throw() { return limits_type::denorm_min(); }
281 static const bool is_iec559
= limits_type::is_iec559
;
282 static const bool is_bounded
= limits_type::is_bounded
;
283 static const bool is_modulo
= limits_type::is_modulo
;
285 static const bool traps
= limits_type::traps
;
286 static const bool tinyness_before
= limits_type::tinyness_before
;
287 static const float_round_style round_style
= limits_type::round_style
;
289 }; // std::numeric_limits<MyInt>
292 class numeric_limits
< MyOverflowingUnsigned
>
294 typedef numeric_limits
<unsigned> limits_type
;
297 static const bool is_specialized
= limits_type::is_specialized
;
299 static MyOverflowingUnsigned min
BOOST_PREVENT_MACRO_SUBSTITUTION () throw()
300 { return limits_type::min
BOOST_PREVENT_MACRO_SUBSTITUTION (); }
301 static MyOverflowingUnsigned max
BOOST_PREVENT_MACRO_SUBSTITUTION () throw()
302 { return limits_type::max
BOOST_PREVENT_MACRO_SUBSTITUTION (); }
303 static MyOverflowingUnsigned
lowest() throw()
304 { return min
BOOST_PREVENT_MACRO_SUBSTITUTION (); } // C++11
306 static const int digits
= limits_type::digits
;
307 static const int digits10
= limits_type::digits10
;
308 static const int max_digits10
= 0; // C++11
309 static const bool is_signed
= limits_type::is_signed
;
310 static const bool is_integer
= limits_type::is_integer
;
311 static const bool is_exact
= limits_type::is_exact
;
312 static const int radix
= limits_type::radix
;
313 static MyOverflowingUnsigned
epsilon() throw()
314 { return limits_type::epsilon(); }
315 static MyOverflowingUnsigned
round_error() throw()
316 {return limits_type::round_error();}
318 static const int min_exponent
= limits_type::min_exponent
;
319 static const int min_exponent10
= limits_type::min_exponent10
;
320 static const int max_exponent
= limits_type::max_exponent
;
321 static const int max_exponent10
= limits_type::max_exponent10
;
323 static const bool has_infinity
= limits_type::has_infinity
;
324 static const bool has_quiet_NaN
= limits_type::has_quiet_NaN
;
325 static const bool has_signaling_NaN
= limits_type::has_signaling_NaN
;
326 static const float_denorm_style has_denorm
= limits_type::has_denorm
;
327 static const bool has_denorm_loss
= limits_type::has_denorm_loss
;
329 static MyOverflowingUnsigned
infinity() throw()
330 { return limits_type::infinity(); }
331 static MyOverflowingUnsigned
quiet_NaN() throw()
332 { return limits_type::quiet_NaN(); }
333 static MyOverflowingUnsigned
signaling_NaN() throw()
334 { return limits_type::signaling_NaN(); }
335 static MyOverflowingUnsigned
denorm_min() throw()
336 { return limits_type::denorm_min(); }
338 static const bool is_iec559
= limits_type::is_iec559
;
339 static const bool is_bounded
= limits_type::is_bounded
;
340 static const bool is_modulo
= limits_type::is_modulo
;
342 static const bool traps
= limits_type::traps
;
343 static const bool tinyness_before
= limits_type::tinyness_before
;
344 static const float_round_style round_style
= limits_type::round_style
;
346 }; // std::numeric_limits<MyOverflowingUnsigned>
353 // This fixture replaces the check of rational's packing at the start of main.
354 class rational_size_check
356 typedef INT_TYPE int_type
;
357 typedef ::boost::rational
<int_type
> rational_type
;
360 rational_size_check()
364 char const * const int_name
= BOOST_PP_STRINGIZE( INT_TYPE
);
366 cout
<< "Running tests for boost::rational<" << int_name
<< ">\n\n";
368 cout
<< "Implementation issue: the minimal size for a rational\n"
369 << "is twice the size of the underlying integer type.\n\n";
371 cout
<< "Checking to see if space is being wasted.\n"
372 << "\tsizeof(" << int_name
<< ") == " << sizeof( int_type
)
374 cout
<< "\tsizeof(boost::rational<" << int_name
<< ">) == "
375 << sizeof( rational_type
) << "\n\n";
377 cout
<< "Implementation has "
379 (sizeof( rational_type
) > 2u * sizeof( int_type
))
380 ? "included padding bytes"
387 // This fixture groups all the common settings.
388 class my_configuration
391 template < typename T
>
395 typedef ::boost::rational
<T
> rational_type
;
398 struct parts
{ rational_type parts_
[ 9 ]; };
400 static parts
generate_rationals()
402 rational_type r1
, r2( 0 ), r3( 1 ), r4( -3 ), r5( 7, 2 ),
403 r6( 5, 15 ), r7( 14, -21 ), r8( -4, 6 ),
406 result
.parts_
[0] = r1
;
407 result
.parts_
[1] = r2
;
408 result
.parts_
[2] = r3
;
409 result
.parts_
[3] = r4
;
410 result
.parts_
[4] = r5
;
411 result
.parts_
[5] = r6
;
412 result
.parts_
[6] = r7
;
413 result
.parts_
[7] = r8
;
414 result
.parts_
[8] = r9
;
419 parts p_
; // Order Dependency
422 rational_type ( &r_
)[ 9 ]; // Order Dependency
424 hook() : p_( generate_rationals() ), r_( p_
.parts_
) {}
428 // Instead of controlling the integer type needed with a #define, use a list of
429 // all available types. Since the headers #included don't change because of the
430 // integer #define, only the built-in types and MyInt are available. (Any other
431 // arbitrary integer type introduced by the #define would get compiler errors
432 // because its header can't be #included.)
433 typedef ::boost::mpl::list
<short, int, long> builtin_signed_test_types
;
434 typedef ::boost::mpl::list
<short, int, long, MyInt
> all_signed_test_types
;
436 // Without these explicit instantiations, MSVC++ 6.5/7.0 does not find
437 // some friend operators in certain contexts.
438 ::boost::rational
<short> dummy1
;
439 ::boost::rational
<int> dummy2
;
440 ::boost::rational
<long> dummy3
;
441 ::boost::rational
<MyInt
> dummy4
;
442 ::boost::rational
<MyOverflowingUnsigned
> dummy5
;
443 ::boost::rational
<unsigned> dummy6
;
445 // Should there be regular tests with unsigned integer types?
450 // Check if rational is the smallest size possible
451 BOOST_GLOBAL_FIXTURE( rational_size_check
);
454 #if BOOST_CONTROL_RATIONAL_HAS_GCD
455 // The factoring function template suite
456 BOOST_AUTO_TEST_SUITE( factoring_suite
)
459 BOOST_AUTO_TEST_CASE_TEMPLATE( gcd_test
, T
, all_signed_test_types
)
461 BOOST_CHECK_EQUAL( boost::gcd
<T
>( 1, -1), static_cast<T
>( 1) );
462 BOOST_CHECK_EQUAL( boost::gcd
<T
>( -1, 1), static_cast<T
>( 1) );
463 BOOST_CHECK_EQUAL( boost::gcd
<T
>( 1, 1), static_cast<T
>( 1) );
464 BOOST_CHECK_EQUAL( boost::gcd
<T
>( -1, -1), static_cast<T
>( 1) );
465 BOOST_CHECK_EQUAL( boost::gcd
<T
>( 0, 0), static_cast<T
>( 0) );
466 BOOST_CHECK_EQUAL( boost::gcd
<T
>( 7, 0), static_cast<T
>( 7) );
467 BOOST_CHECK_EQUAL( boost::gcd
<T
>( 0, 9), static_cast<T
>( 9) );
468 BOOST_CHECK_EQUAL( boost::gcd
<T
>( -7, 0), static_cast<T
>( 7) );
469 BOOST_CHECK_EQUAL( boost::gcd
<T
>( 0, -9), static_cast<T
>( 9) );
470 BOOST_CHECK_EQUAL( boost::gcd
<T
>( 42, 30), static_cast<T
>( 6) );
471 BOOST_CHECK_EQUAL( boost::gcd
<T
>( 6, -9), static_cast<T
>( 3) );
472 BOOST_CHECK_EQUAL( boost::gcd
<T
>(-10, -10), static_cast<T
>(10) );
473 BOOST_CHECK_EQUAL( boost::gcd
<T
>(-25, -10), static_cast<T
>( 5) );
477 BOOST_AUTO_TEST_CASE_TEMPLATE( lcm_test
, T
, all_signed_test_types
)
479 BOOST_CHECK_EQUAL( boost::lcm
<T
>( 1, -1), static_cast<T
>( 1) );
480 BOOST_CHECK_EQUAL( boost::lcm
<T
>( -1, 1), static_cast<T
>( 1) );
481 BOOST_CHECK_EQUAL( boost::lcm
<T
>( 1, 1), static_cast<T
>( 1) );
482 BOOST_CHECK_EQUAL( boost::lcm
<T
>( -1, -1), static_cast<T
>( 1) );
483 BOOST_CHECK_EQUAL( boost::lcm
<T
>( 0, 0), static_cast<T
>( 0) );
484 BOOST_CHECK_EQUAL( boost::lcm
<T
>( 6, 0), static_cast<T
>( 0) );
485 BOOST_CHECK_EQUAL( boost::lcm
<T
>( 0, 7), static_cast<T
>( 0) );
486 BOOST_CHECK_EQUAL( boost::lcm
<T
>( -5, 0), static_cast<T
>( 0) );
487 BOOST_CHECK_EQUAL( boost::lcm
<T
>( 0, -4), static_cast<T
>( 0) );
488 BOOST_CHECK_EQUAL( boost::lcm
<T
>( 18, 30), static_cast<T
>(90) );
489 BOOST_CHECK_EQUAL( boost::lcm
<T
>( -6, 9), static_cast<T
>(18) );
490 BOOST_CHECK_EQUAL( boost::lcm
<T
>(-10, -10), static_cast<T
>(10) );
491 BOOST_CHECK_EQUAL( boost::lcm
<T
>( 25, -10), static_cast<T
>(50) );
494 BOOST_AUTO_TEST_SUITE_END()
495 #endif // BOOST_CONTROL_RATIONAL_HAS_GCD
498 // The basic test suite
499 BOOST_FIXTURE_TEST_SUITE( basic_rational_suite
, my_configuration
)
501 // Initialization tests
502 BOOST_AUTO_TEST_CASE_TEMPLATE( rational_initialization_test
, T
,
503 all_signed_test_types
)
505 my_configuration::hook
<T
> h
;
506 boost::rational
<T
> &r1
= h
.r_
[ 0 ], &r2
= h
.r_
[ 1 ], &r3
= h
.r_
[ 2 ],
507 &r4
= h
.r_
[ 3 ], &r5
= h
.r_
[ 4 ], &r6
= h
.r_
[ 5 ],
508 &r7
= h
.r_
[ 6 ], &r8
= h
.r_
[ 7 ], &r9
= h
.r_
[ 8 ];
510 BOOST_CHECK_EQUAL( r1
.numerator(), static_cast<T
>( 0) );
511 BOOST_CHECK_EQUAL( r2
.numerator(), static_cast<T
>( 0) );
512 BOOST_CHECK_EQUAL( r3
.numerator(), static_cast<T
>( 1) );
513 BOOST_CHECK_EQUAL( r4
.numerator(), static_cast<T
>(-3) );
514 BOOST_CHECK_EQUAL( r5
.numerator(), static_cast<T
>( 7) );
515 BOOST_CHECK_EQUAL( r6
.numerator(), static_cast<T
>( 1) );
516 BOOST_CHECK_EQUAL( r7
.numerator(), static_cast<T
>(-2) );
517 BOOST_CHECK_EQUAL( r8
.numerator(), static_cast<T
>(-2) );
518 BOOST_CHECK_EQUAL( r9
.numerator(), static_cast<T
>( 1) );
520 BOOST_CHECK_EQUAL( r1
.denominator(), static_cast<T
>(1) );
521 BOOST_CHECK_EQUAL( r2
.denominator(), static_cast<T
>(1) );
522 BOOST_CHECK_EQUAL( r3
.denominator(), static_cast<T
>(1) );
523 BOOST_CHECK_EQUAL( r4
.denominator(), static_cast<T
>(1) );
524 BOOST_CHECK_EQUAL( r5
.denominator(), static_cast<T
>(2) );
525 BOOST_CHECK_EQUAL( r6
.denominator(), static_cast<T
>(3) );
526 BOOST_CHECK_EQUAL( r7
.denominator(), static_cast<T
>(3) );
527 BOOST_CHECK_EQUAL( r8
.denominator(), static_cast<T
>(3) );
528 BOOST_CHECK_EQUAL( r9
.denominator(), static_cast<T
>(5) );
530 BOOST_CHECK_THROW( boost::rational
<T
>( 3, 0), boost::bad_rational
);
531 BOOST_CHECK_THROW( boost::rational
<T
>(-2, 0), boost::bad_rational
);
532 BOOST_CHECK_THROW( boost::rational
<T
>( 0, 0), boost::bad_rational
);
535 // Assignment (non-operator) tests
536 BOOST_AUTO_TEST_CASE_TEMPLATE( rational_assign_test
, T
, all_signed_test_types
)
538 my_configuration::hook
<T
> h
;
539 boost::rational
<T
> & r
= h
.r_
[ 0 ];
542 BOOST_CHECK_EQUAL( r
.numerator(), static_cast<T
>(3) );
543 BOOST_CHECK_EQUAL( r
.denominator(), static_cast<T
>(4) );
546 BOOST_CHECK_EQUAL( r
.numerator(), static_cast<T
>(0) );
547 BOOST_CHECK_EQUAL( r
.denominator(), static_cast<T
>(1) );
549 BOOST_CHECK_THROW( r
.assign( 4, 0), boost::bad_rational
);
550 BOOST_CHECK_THROW( r
.assign( 0, 0), boost::bad_rational
);
551 BOOST_CHECK_THROW( r
.assign(-7, 0), boost::bad_rational
);
555 BOOST_AUTO_TEST_CASE_TEMPLATE( rational_comparison_test
, T
,
556 all_signed_test_types
)
558 my_configuration::hook
<T
> h
;
559 const boost::rational
<T
> &r1
= h
.r_
[ 0 ], &r2
= h
.r_
[ 1 ], &r3
= h
.r_
[ 2 ],
560 &r4
= h
.r_
[ 3 ], &r5
= h
.r_
[ 4 ], &r6
= h
.r_
[ 5 ],
561 &r7
= h
.r_
[ 6 ], &r8
= h
.r_
[ 7 ], &r9
= h
.r_
[ 8 ];
563 BOOST_CHECK( r1
== r2
);
564 BOOST_CHECK( r2
!= r3
);
565 BOOST_CHECK( r4
< r3
);
566 BOOST_CHECK( r4
<= r5
);
567 BOOST_CHECK( r1
<= r2
);
568 BOOST_CHECK( r5
> r6
);
569 BOOST_CHECK( r5
>= r6
);
570 BOOST_CHECK( r7
>= r8
);
572 BOOST_CHECK( !(r3
== r2
) );
573 BOOST_CHECK( !(r1
!= r2
) );
574 BOOST_CHECK( !(r1
< r2
) );
575 BOOST_CHECK( !(r5
< r6
) );
576 BOOST_CHECK( !(r9
<= r2
) );
577 BOOST_CHECK( !(r8
> r7
) );
578 BOOST_CHECK( !(r8
> r2
) );
579 BOOST_CHECK( !(r4
>= r6
) );
581 BOOST_CHECK( r1
== static_cast<T
>( 0) );
582 BOOST_CHECK( r2
!= static_cast<T
>(-1) );
583 BOOST_CHECK( r3
< static_cast<T
>( 2) );
584 BOOST_CHECK( r4
<= static_cast<T
>(-3) );
585 BOOST_CHECK( r5
> static_cast<T
>( 3) );
586 BOOST_CHECK( r6
>= static_cast<T
>( 0) );
588 BOOST_CHECK( static_cast<T
>( 0) == r2
);
589 BOOST_CHECK( static_cast<T
>( 0) != r7
);
590 BOOST_CHECK( static_cast<T
>(-1) < r8
);
591 BOOST_CHECK( static_cast<T
>(-2) <= r9
);
592 BOOST_CHECK( static_cast<T
>( 1) > r1
);
593 BOOST_CHECK( static_cast<T
>( 1) >= r3
);
595 // Extra tests with values close in continued-fraction notation
596 boost::rational
<T
> const x1( static_cast<T
>(9), static_cast<T
>(4) );
597 boost::rational
<T
> const x2( static_cast<T
>(61), static_cast<T
>(27) );
598 boost::rational
<T
> const x3( static_cast<T
>(52), static_cast<T
>(23) );
599 boost::rational
<T
> const x4( static_cast<T
>(70), static_cast<T
>(31) );
601 BOOST_CHECK( x1
< x2
);
602 BOOST_CHECK( !(x1
< x1
) );
603 BOOST_CHECK( !(x2
< x2
) );
604 BOOST_CHECK( !(x2
< x1
) );
605 BOOST_CHECK( x2
< x3
);
606 BOOST_CHECK( x4
< x2
);
607 BOOST_CHECK( !(x3
< x4
) );
608 BOOST_CHECK( r7
< x1
); // not actually close; wanted -ve v. +ve instead
609 BOOST_CHECK( !(x2
< r7
) );
612 // Increment & decrement tests
613 BOOST_AUTO_TEST_CASE_TEMPLATE( rational_1step_test
, T
, all_signed_test_types
)
615 my_configuration::hook
<T
> h
;
616 boost::rational
<T
> &r1
= h
.r_
[ 0 ], &r2
= h
.r_
[ 1 ], &r3
= h
.r_
[ 2 ],
617 &r7
= h
.r_
[ 6 ], &r8
= h
.r_
[ 7 ];
619 BOOST_CHECK( r1
++ == r2
);
620 BOOST_CHECK( r1
!= r2
);
621 BOOST_CHECK( r1
== r3
);
622 BOOST_CHECK( --r1
== r2
);
623 BOOST_CHECK( r8
-- == r7
);
624 BOOST_CHECK( r8
!= r7
);
625 BOOST_CHECK( ++r8
== r7
);
628 // Absolute value tests
629 BOOST_AUTO_TEST_CASE_TEMPLATE( rational_abs_test
, T
, all_signed_test_types
)
631 typedef my_configuration::hook
<T
> hook_type
;
632 typedef typename
hook_type::rational_type rational_type
;
635 rational_type
&r2
= h
.r_
[ 1 ], &r5
= h
.r_
[ 4 ], &r8
= h
.r_
[ 7 ];
637 #ifdef BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP
638 // This is a nasty hack, required because some compilers do not implement
639 // "Koenig Lookup." Basically, if I call abs(r), the C++ standard says that
640 // the compiler should look for a definition of abs in the namespace which
641 // contains r's class (in this case boost)--among other places.
646 BOOST_CHECK_EQUAL( abs(r2
), r2
);
647 BOOST_CHECK_EQUAL( abs(r5
), r5
);
648 BOOST_CHECK_EQUAL( abs(r8
), rational_type(2, 3) );
651 // Unary operator tests
652 BOOST_AUTO_TEST_CASE_TEMPLATE( rational_unary_test
, T
, all_signed_test_types
)
654 my_configuration::hook
<T
> h
;
655 boost::rational
<T
> &r2
= h
.r_
[ 1 ], &r3
= h
.r_
[ 2 ],
656 &r4
= h
.r_
[ 3 ], &r5
= h
.r_
[ 4 ];
658 BOOST_CHECK_EQUAL( +r5
, r5
);
660 BOOST_CHECK( -r3
!= r3
);
661 BOOST_CHECK_EQUAL( -(-r3
), r3
);
662 BOOST_CHECK_EQUAL( -r4
, static_cast<T
>(3) );
667 BOOST_CHECK( ! static_cast<bool>(r2
) );
671 BOOST_AUTO_TEST_SUITE_END()
674 // The rational arithmetic operations suite
675 BOOST_AUTO_TEST_SUITE( rational_arithmetic_suite
)
677 // Addition & subtraction tests
678 BOOST_AUTO_TEST_CASE_TEMPLATE( rational_additive_test
, T
,
679 all_signed_test_types
)
681 typedef boost::rational
<T
> rational_type
;
683 BOOST_CHECK_EQUAL( rational_type( 1, 2) + rational_type(1, 2),
685 BOOST_CHECK_EQUAL( rational_type(11, 3) + rational_type(1, 2),
686 rational_type( 25, 6) );
687 BOOST_CHECK_EQUAL( rational_type(-8, 3) + rational_type(1, 5),
688 rational_type(-37, 15) );
689 BOOST_CHECK_EQUAL( rational_type(-7, 6) + rational_type(1, 7),
690 rational_type( 1, 7) - rational_type(7, 6) );
691 BOOST_CHECK_EQUAL( rational_type(13, 5) - rational_type(1, 2),
692 rational_type( 21, 10) );
693 BOOST_CHECK_EQUAL( rational_type(22, 3) + static_cast<T
>(1),
694 rational_type( 25, 3) );
695 BOOST_CHECK_EQUAL( rational_type(12, 7) - static_cast<T
>(2),
696 rational_type( -2, 7) );
697 BOOST_CHECK_EQUAL( static_cast<T
>(3) + rational_type(4, 5),
698 rational_type( 19, 5) );
699 BOOST_CHECK_EQUAL( static_cast<T
>(4) - rational_type(9, 2),
700 rational_type( -1, 2) );
702 rational_type
r( 11 );
704 r
-= rational_type( 20, 3 );
705 BOOST_CHECK_EQUAL( r
, rational_type(13, 3) );
707 r
+= rational_type( 1, 2 );
708 BOOST_CHECK_EQUAL( r
, rational_type(29, 6) );
710 r
-= static_cast<T
>( 5 );
711 BOOST_CHECK_EQUAL( r
, rational_type( 1, -6) );
713 r
+= rational_type( 1, 5 );
714 BOOST_CHECK_EQUAL( r
, rational_type( 1, 30) );
716 r
+= static_cast<T
>( 2 );
717 BOOST_CHECK_EQUAL( r
, rational_type(61, 30) );
721 BOOST_AUTO_TEST_CASE_TEMPLATE( rational_assignment_test
, T
,
722 all_signed_test_types
)
724 typedef boost::rational
<T
> rational_type
;
728 r
= rational_type( 1, 10 );
729 BOOST_CHECK_EQUAL( r
, rational_type( 1, 10) );
731 r
= static_cast<T
>( -9 );
732 BOOST_CHECK_EQUAL( r
, rational_type(-9, 1) );
735 // Multiplication tests
736 BOOST_AUTO_TEST_CASE_TEMPLATE( rational_multiplication_test
, T
,
737 all_signed_test_types
)
739 typedef boost::rational
<T
> rational_type
;
741 BOOST_CHECK_EQUAL( rational_type(1, 3) * rational_type(-3, 4),
742 rational_type(-1, 4) );
743 BOOST_CHECK_EQUAL( rational_type(2, 5) * static_cast<T
>(7),
744 rational_type(14, 5) );
745 BOOST_CHECK_EQUAL( static_cast<T
>(-2) * rational_type(1, 6),
746 rational_type(-1, 3) );
748 rational_type r
= rational_type( 3, 7 );
750 r
*= static_cast<T
>( 14 );
751 BOOST_CHECK_EQUAL( r
, static_cast<T
>(6) );
753 r
*= rational_type( 3, 8 );
754 BOOST_CHECK_EQUAL( r
, rational_type(9, 4) );
758 BOOST_AUTO_TEST_CASE_TEMPLATE( rational_division_test
, T
,
759 all_signed_test_types
)
761 typedef boost::rational
<T
> rational_type
;
763 BOOST_CHECK_EQUAL( rational_type(-1, 20) / rational_type(4, 5),
764 rational_type(-1, 16) );
765 BOOST_CHECK_EQUAL( rational_type( 5, 6) / static_cast<T
>(7),
766 rational_type( 5, 42) );
767 BOOST_CHECK_EQUAL( static_cast<T
>(8) / rational_type(2, 7),
768 static_cast<T
>(28) );
770 BOOST_CHECK_THROW( rational_type(23, 17) / rational_type(),
771 boost::bad_rational
);
772 BOOST_CHECK_THROW( rational_type( 4, 15) / static_cast<T
>(0),
773 boost::bad_rational
);
775 rational_type r
= rational_type( 4, 3 );
777 r
/= rational_type( 5, 4 );
778 BOOST_CHECK_EQUAL( r
, rational_type(16, 15) );
780 r
/= static_cast<T
>( 4 );
781 BOOST_CHECK_EQUAL( r
, rational_type( 4, 15) );
783 BOOST_CHECK_THROW( r
/= rational_type(), boost::bad_rational
);
784 BOOST_CHECK_THROW( r
/= static_cast<T
>(0), boost::bad_rational
);
786 BOOST_CHECK_EQUAL( rational_type(-1) / rational_type(-3),
787 rational_type(1, 3) );
790 // Tests for operations on self
791 BOOST_AUTO_TEST_CASE_TEMPLATE( rational_self_operations_test
, T
,
792 all_signed_test_types
)
794 typedef boost::rational
<T
> rational_type
;
796 rational_type r
= rational_type( 4, 3 );
799 BOOST_CHECK_EQUAL( r
, rational_type( 8, 3) );
802 BOOST_CHECK_EQUAL( r
, rational_type(64, 9) );
805 BOOST_CHECK_EQUAL( r
, rational_type( 1, 1) );
808 BOOST_CHECK_EQUAL( r
, rational_type( 0, 1) );
810 BOOST_CHECK_THROW( r
/= r
, boost::bad_rational
);
813 BOOST_AUTO_TEST_CASE_TEMPLATE( gcd_and_lcm_on_rationals
, T
, all_signed_test_types
)
815 typedef boost::rational
<T
> rational
;
816 BOOST_CHECK_EQUAL(boost::integer::gcd(rational(1, 4), rational(1, 3)),
818 BOOST_CHECK_EQUAL(boost::integer::lcm(rational(1, 4), rational(1, 3)),
823 BOOST_AUTO_TEST_CASE_TEMPLATE(rational_mixed_test
, T
,
824 /*all_signed_test_types*/ builtin_signed_test_types
)
827 typedef boost::rational
<boost::intmax_t> rational_type
;
829 boost::intmax_t val2
= 30;
831 rational_type
r(val1
, val2
);
832 BOOST_CHECK_EQUAL(r
, rational_type(20, 30));
834 r
.assign(val1
, val2
);
835 BOOST_CHECK_EQUAL(r
, rational_type(20, 30));
838 typedef boost::rational
<boost::uintmax_t> rational_type2
;
841 boost::uintmax_t val3
= 30;
843 rational_type2
r2(val1
, val3
);
844 BOOST_CHECK_EQUAL(r2
, rational_type2(20, 30));
846 r2
.assign(val1
, val3
);
847 BOOST_CHECK_EQUAL(r2
, rational_type2(20, 30));
850 typedef boost::rational
<short> rational_type
;
854 rational_type
r(val1
, val2
);
855 BOOST_CHECK_EQUAL(r
, rational_type(20, 30));
857 r
.assign(val1
, val2
);
858 BOOST_CHECK_EQUAL(r
, rational_type(20, 30));
861 typedef boost::rational
<unsigned short> rational_type
;
863 unsigned short val2
= 30;
865 rational_type
r(val1
, val2
);
866 BOOST_CHECK_EQUAL(r
, rational_type(20, 30));
868 r
.assign(val1
, val2
);
869 BOOST_CHECK_EQUAL(r
, rational_type(20, 30));
872 typedef boost::rational
<long> rational_type
;
876 rational_type
r(val1
, val2
);
877 BOOST_CHECK_EQUAL(r
, rational_type(20, 30));
879 r
.assign(val1
, val2
);
880 BOOST_CHECK_EQUAL(r
, rational_type(20, 30));
883 typedef boost::rational
<unsigned long> rational_type
;
885 unsigned long val2
= 30;
887 rational_type
r(val1
, val2
);
888 BOOST_CHECK_EQUAL(r
, rational_type(20, 30));
890 r
.assign(val1
, val2
);
891 BOOST_CHECK_EQUAL(r
, rational_type(20, 30));
894 typedef boost::rational
<boost::intmax_t> rational_type
;
896 boost::intmax_t val2
= -30;
898 rational_type
r(val1
, val2
);
899 BOOST_CHECK_EQUAL(r
, rational_type(20, -30));
901 r
.assign(val1
, val2
);
902 BOOST_CHECK_EQUAL(r
, rational_type(20, -30));
905 typedef boost::rational
<short> rational_type
;
909 rational_type
r(val1
, val2
);
910 BOOST_CHECK_EQUAL(r
, rational_type(-20, -30));
912 r
.assign(val1
, val2
);
913 BOOST_CHECK_EQUAL(r
, rational_type(-20, -30));
916 typedef boost::rational
<long> rational_type
;
920 rational_type
r(val1
, val2
);
921 BOOST_CHECK_EQUAL(r
, rational_type(-20, 30));
923 r
.assign(val1
, val2
);
924 BOOST_CHECK_EQUAL(r
, rational_type(-20, 30));
928 BOOST_AUTO_TEST_CASE(conversions
)
930 typedef boost::rational
<boost::int32_t> signed_rat
;
932 boost::int32_t signed_max
= (std::numeric_limits
<boost::int32_t>::max
)();
933 boost::int32_t signed_min
= (std::numeric_limits
<boost::int32_t>::min
)();
934 boost::int32_t signed_min_num
= signed_min
+ 1;
936 BOOST_CHECK_EQUAL(signed_rat(signed_max
).numerator(), signed_max
);
937 BOOST_CHECK_EQUAL(signed_rat(signed_min
).numerator(), signed_min
);
938 BOOST_CHECK_EQUAL(signed_rat(signed_max
, 1).numerator(), signed_max
);
939 BOOST_CHECK_EQUAL(signed_rat(signed_min
, 1).numerator(), signed_min
);
940 BOOST_CHECK_EQUAL(signed_rat(1, signed_max
).denominator(), signed_max
);
941 BOOST_CHECK_EQUAL(signed_rat(1, signed_min_num
).denominator(), -signed_min_num
);
942 // This throws because we can't negate signed_min:
943 BOOST_CHECK_THROW(signed_rat(1, signed_min
).denominator(), std::domain_error
);
946 BOOST_CHECK_EQUAL(sr
.assign(signed_max
, 1).numerator(), signed_max
);
947 BOOST_CHECK_EQUAL(sr
.assign(1, signed_max
).denominator(), signed_max
);
948 BOOST_CHECK_EQUAL(sr
.assign(signed_min
, 1).numerator(), signed_min
);
949 BOOST_CHECK_EQUAL(sr
.assign(1, signed_min_num
).denominator(), -signed_min_num
);
950 BOOST_CHECK_THROW(sr
.assign(1, signed_min
), std::domain_error
);
952 BOOST_CHECK_EQUAL((sr
= signed_max
).numerator(), signed_max
);
953 BOOST_CHECK_EQUAL((sr
= signed_min
).numerator(), signed_min
);
955 boost::int64_t big_signed_max
= (std::numeric_limits
<boost::int32_t>::max
)();
956 boost::int64_t big_signed_min
= (std::numeric_limits
<boost::int32_t>::min
)();
957 boost::int64_t big_signed_min_num
= signed_min
+ 1;
959 BOOST_CHECK_EQUAL(signed_rat(big_signed_max
).numerator(), big_signed_max
);
960 BOOST_CHECK_EQUAL(signed_rat(big_signed_min
).numerator(), big_signed_min
);
961 BOOST_CHECK_EQUAL(signed_rat(big_signed_max
, 1).numerator(), big_signed_max
);
962 BOOST_CHECK_EQUAL(signed_rat(big_signed_min
, 1).numerator(), big_signed_min
);
963 BOOST_CHECK_EQUAL(signed_rat(1, big_signed_max
).denominator(), big_signed_max
);
964 BOOST_CHECK_EQUAL(signed_rat(1, big_signed_min_num
).denominator(), -big_signed_min_num
);
965 // This throws because we can't negate big_signed_min:
966 BOOST_CHECK_THROW(signed_rat(1, big_signed_min
).denominator(), std::domain_error
);
968 BOOST_CHECK_EQUAL(sr
.assign(big_signed_max
, 1).numerator(), big_signed_max
);
969 BOOST_CHECK_EQUAL(sr
.assign(1, big_signed_max
).denominator(), big_signed_max
);
970 BOOST_CHECK_EQUAL(sr
.assign(big_signed_min
, 1).numerator(), big_signed_min
);
971 BOOST_CHECK_EQUAL(sr
.assign(1, big_signed_min_num
).denominator(), -big_signed_min_num
);
972 BOOST_CHECK_THROW(sr
.assign(1, big_signed_min
), std::domain_error
);
974 BOOST_CHECK_EQUAL((sr
= big_signed_max
).numerator(), big_signed_max
);
975 BOOST_CHECK_EQUAL((sr
= big_signed_min
).numerator(), big_signed_min
);
979 BOOST_CHECK_THROW(signed_rat(big_signed_max
).numerator(), std::domain_error
);
980 BOOST_CHECK_THROW(signed_rat(big_signed_min
).numerator(), std::domain_error
);
981 BOOST_CHECK_THROW(signed_rat(big_signed_max
, 1).numerator(), std::domain_error
);
982 BOOST_CHECK_THROW(signed_rat(big_signed_min
, 1).numerator(), std::domain_error
);
983 BOOST_CHECK_THROW(signed_rat(1, big_signed_max
).denominator(), std::domain_error
);
985 BOOST_CHECK_THROW(sr
.assign(big_signed_max
, 1).numerator(), std::domain_error
);
986 BOOST_CHECK_THROW(sr
.assign(1, big_signed_max
).denominator(), std::domain_error
);
987 BOOST_CHECK_THROW(sr
.assign(big_signed_min
, 1).numerator(), std::domain_error
);
989 BOOST_CHECK_THROW((sr
= big_signed_max
).numerator(), std::domain_error
);
990 BOOST_CHECK_THROW((sr
= big_signed_min
).numerator(), std::domain_error
);
992 boost::int16_t small_signed_max
= (std::numeric_limits
<boost::int16_t>::max
)();
993 boost::int16_t small_signed_min
= (std::numeric_limits
<boost::int16_t>::min
)();
995 BOOST_CHECK_EQUAL(signed_rat(small_signed_max
).numerator(), small_signed_max
);
996 BOOST_CHECK_EQUAL(signed_rat(small_signed_min
).numerator(), small_signed_min
);
997 BOOST_CHECK_EQUAL(signed_rat(small_signed_max
, 1).numerator(), small_signed_max
);
998 BOOST_CHECK_EQUAL(signed_rat(small_signed_min
, 1).numerator(), small_signed_min
);
999 BOOST_CHECK_EQUAL(signed_rat(1, small_signed_max
).denominator(), small_signed_max
);
1000 BOOST_CHECK_EQUAL(signed_rat(1, small_signed_min
).denominator(), -static_cast<boost::int32_t>(small_signed_min
));
1002 BOOST_CHECK_EQUAL(sr
.assign(small_signed_max
, 1).numerator(), small_signed_max
);
1003 BOOST_CHECK_EQUAL(sr
.assign(1, small_signed_max
).denominator(), small_signed_max
);
1004 BOOST_CHECK_EQUAL(sr
.assign(small_signed_min
, 1).numerator(), small_signed_min
);
1005 BOOST_CHECK_EQUAL(sr
.assign(1, small_signed_min
).denominator(), -static_cast<boost::int32_t>(small_signed_min
));
1007 BOOST_CHECK_EQUAL((sr
= small_signed_max
).numerator(), small_signed_max
);
1008 BOOST_CHECK_EQUAL((sr
= small_signed_min
).numerator(), small_signed_min
);
1010 boost::uint32_t unsigned_max
= signed_max
;
1011 BOOST_CHECK_EQUAL(signed_rat(unsigned_max
).numerator(), signed_max
);
1012 BOOST_CHECK_EQUAL(signed_rat(unsigned_max
, 1).numerator(), signed_max
);
1013 BOOST_CHECK_EQUAL(signed_rat(1, unsigned_max
).denominator(), signed_max
);
1015 BOOST_CHECK_EQUAL(sr
.assign(unsigned_max
, 1).numerator(), signed_max
);
1016 BOOST_CHECK_EQUAL(sr
.assign(1, unsigned_max
).denominator(), signed_max
);
1017 BOOST_CHECK_EQUAL((sr
= unsigned_max
).numerator(), signed_max
);
1019 BOOST_CHECK_THROW(signed_rat(unsigned_max
).numerator(), std::domain_error
);
1020 BOOST_CHECK_THROW(signed_rat(unsigned_max
, 1).numerator(), std::domain_error
);
1021 BOOST_CHECK_THROW(signed_rat(1, unsigned_max
).denominator(), std::domain_error
);
1023 BOOST_CHECK_THROW(sr
.assign(unsigned_max
, 1).numerator(), std::domain_error
);
1024 BOOST_CHECK_THROW(sr
.assign(1, unsigned_max
).denominator(), std::domain_error
);
1025 BOOST_CHECK_THROW((sr
= unsigned_max
).numerator(), std::domain_error
);
1027 boost::uint64_t big_unsigned_max
= signed_max
;
1028 BOOST_CHECK_EQUAL(signed_rat(big_unsigned_max
).numerator(), signed_max
);
1029 BOOST_CHECK_EQUAL(signed_rat(big_unsigned_max
, 1).numerator(), signed_max
);
1030 BOOST_CHECK_EQUAL(signed_rat(1, big_unsigned_max
).denominator(), signed_max
);
1032 BOOST_CHECK_EQUAL(sr
.assign(big_unsigned_max
, 1).numerator(), signed_max
);
1033 BOOST_CHECK_EQUAL(sr
.assign(1, big_unsigned_max
).denominator(), signed_max
);
1034 BOOST_CHECK_EQUAL((sr
= big_unsigned_max
).numerator(), signed_max
);
1036 BOOST_CHECK_THROW(signed_rat(big_unsigned_max
).numerator(), std::domain_error
);
1037 BOOST_CHECK_THROW(signed_rat(big_unsigned_max
, 1).numerator(), std::domain_error
);
1038 BOOST_CHECK_THROW(signed_rat(1, big_unsigned_max
).denominator(), std::domain_error
);
1040 BOOST_CHECK_THROW(sr
.assign(big_unsigned_max
, 1).numerator(), std::domain_error
);
1041 BOOST_CHECK_THROW(sr
.assign(1, big_unsigned_max
).denominator(), std::domain_error
);
1042 BOOST_CHECK_THROW((sr
= big_unsigned_max
).numerator(), std::domain_error
);
1044 boost::uint16_t small_unsigned_max
= signed_max
;
1045 BOOST_CHECK_EQUAL(signed_rat(small_unsigned_max
).numerator(), small_unsigned_max
);
1046 BOOST_CHECK_EQUAL(signed_rat(small_unsigned_max
, 1).numerator(), small_unsigned_max
);
1047 BOOST_CHECK_EQUAL(signed_rat(1, small_unsigned_max
).denominator(), small_unsigned_max
);
1049 BOOST_CHECK_EQUAL(sr
.assign(small_unsigned_max
, 1).numerator(), small_unsigned_max
);
1050 BOOST_CHECK_EQUAL(sr
.assign(1, small_unsigned_max
).denominator(), small_unsigned_max
);
1051 BOOST_CHECK_EQUAL((sr
= small_unsigned_max
).numerator(), small_unsigned_max
);
1053 // Over again with unsigned rational type:
1054 typedef boost::rational
<boost::uint32_t> unsigned_rat
;
1056 unsigned_max
= (std::numeric_limits
<boost::uint32_t>::max
)();
1058 BOOST_CHECK_EQUAL(unsigned_rat(unsigned_max
).numerator(), unsigned_max
);
1059 BOOST_CHECK_EQUAL(unsigned_rat(unsigned_max
, 1).numerator(), unsigned_max
);
1060 BOOST_CHECK_EQUAL(unsigned_rat(1, unsigned_max
).denominator(), unsigned_max
);
1063 BOOST_CHECK_EQUAL((ur
= unsigned_max
).numerator(), unsigned_max
);
1064 BOOST_CHECK_EQUAL(ur
.assign(unsigned_max
, 1).numerator(), unsigned_max
);
1065 BOOST_CHECK_EQUAL(ur
.assign(1, unsigned_max
).denominator(), unsigned_max
);
1067 big_unsigned_max
= unsigned_max
;
1068 BOOST_CHECK_EQUAL(unsigned_rat(big_unsigned_max
).numerator(), big_unsigned_max
);
1069 BOOST_CHECK_EQUAL(unsigned_rat(big_unsigned_max
, 1).numerator(), big_unsigned_max
);
1070 BOOST_CHECK_EQUAL(unsigned_rat(1, big_unsigned_max
).denominator(), big_unsigned_max
);
1071 BOOST_CHECK_EQUAL((ur
= big_unsigned_max
).numerator(), big_unsigned_max
);
1072 BOOST_CHECK_EQUAL(ur
.assign(big_unsigned_max
, 1).numerator(), big_unsigned_max
);
1073 BOOST_CHECK_EQUAL(ur
.assign(1, big_unsigned_max
).denominator(), big_unsigned_max
);
1075 BOOST_CHECK_THROW(unsigned_rat(big_unsigned_max
).numerator(), std::domain_error
);
1076 BOOST_CHECK_THROW(unsigned_rat(big_unsigned_max
, 1).numerator(), std::domain_error
);
1077 BOOST_CHECK_THROW(unsigned_rat(1, big_unsigned_max
).denominator(), std::domain_error
);
1078 BOOST_CHECK_THROW((ur
= big_unsigned_max
).numerator(), std::domain_error
);
1079 BOOST_CHECK_THROW(ur
.assign(big_unsigned_max
, 1).numerator(), std::domain_error
);
1080 BOOST_CHECK_THROW(ur
.assign(1, big_unsigned_max
).denominator(), std::domain_error
);
1082 BOOST_CHECK_EQUAL(unsigned_rat(small_unsigned_max
).numerator(), small_unsigned_max
);
1083 BOOST_CHECK_EQUAL(unsigned_rat(small_unsigned_max
, 1).numerator(), small_unsigned_max
);
1084 BOOST_CHECK_EQUAL(unsigned_rat(1, small_unsigned_max
).denominator(), small_unsigned_max
);
1085 BOOST_CHECK_EQUAL((ur
= small_unsigned_max
).numerator(), small_unsigned_max
);
1086 BOOST_CHECK_EQUAL(ur
.assign(small_unsigned_max
, 1).numerator(), small_unsigned_max
);
1087 BOOST_CHECK_EQUAL(ur
.assign(1, small_unsigned_max
).denominator(), small_unsigned_max
);
1089 BOOST_CHECK_EQUAL(unsigned_rat(signed_max
).numerator(), signed_max
);
1090 BOOST_CHECK_EQUAL(unsigned_rat(signed_max
, 1).numerator(), signed_max
);
1091 BOOST_CHECK_EQUAL(unsigned_rat(1, signed_max
).denominator(), signed_max
);
1092 BOOST_CHECK_EQUAL((ur
= signed_max
).numerator(), signed_max
);
1093 BOOST_CHECK_EQUAL(ur
.assign(signed_max
, 1).numerator(), signed_max
);
1094 BOOST_CHECK_EQUAL(ur
.assign(1, signed_max
).denominator(), signed_max
);
1095 BOOST_CHECK_THROW(unsigned_rat(signed_min
).numerator(), std::domain_error
);
1096 BOOST_CHECK_THROW(unsigned_rat(signed_min
, 1).numerator(), std::domain_error
);
1097 BOOST_CHECK_THROW(unsigned_rat(1, signed_min
).denominator(), std::domain_error
);
1098 BOOST_CHECK_THROW((ur
= signed_min
).numerator(), std::domain_error
);
1099 BOOST_CHECK_THROW(ur
.assign(signed_min
, 1).numerator(), std::domain_error
);
1100 BOOST_CHECK_THROW(ur
.assign(1, signed_min
).denominator(), std::domain_error
);
1102 big_signed_max
= unsigned_max
;
1103 BOOST_CHECK_EQUAL(unsigned_rat(big_signed_max
).numerator(), unsigned_max
);
1104 BOOST_CHECK_EQUAL(unsigned_rat(big_signed_max
, 1).numerator(), unsigned_max
);
1105 BOOST_CHECK_EQUAL(unsigned_rat(1, big_signed_max
).denominator(), unsigned_max
);
1106 BOOST_CHECK_EQUAL((ur
= big_signed_max
).numerator(), unsigned_max
);
1107 BOOST_CHECK_EQUAL(ur
.assign(big_signed_max
, 1).numerator(), unsigned_max
);
1108 BOOST_CHECK_EQUAL(ur
.assign(1, big_signed_max
).denominator(), unsigned_max
);
1110 BOOST_CHECK_THROW(unsigned_rat(big_signed_max
).numerator(), std::domain_error
);
1111 BOOST_CHECK_THROW(unsigned_rat(big_signed_max
, 1).numerator(), std::domain_error
);
1112 BOOST_CHECK_THROW(unsigned_rat(1, big_signed_max
).denominator(), std::domain_error
);
1113 BOOST_CHECK_THROW((ur
= big_signed_max
).numerator(), std::domain_error
);
1114 BOOST_CHECK_THROW(ur
.assign(big_signed_max
, 1).numerator(), std::domain_error
);
1115 BOOST_CHECK_THROW(ur
.assign(1, big_signed_max
).denominator(), std::domain_error
);
1116 big_signed_max
= -1;
1117 BOOST_CHECK_THROW(unsigned_rat(big_signed_max
).numerator(), std::domain_error
);
1118 BOOST_CHECK_THROW(unsigned_rat(big_signed_max
, 1).numerator(), std::domain_error
);
1119 BOOST_CHECK_THROW(unsigned_rat(1, big_signed_max
).denominator(), std::domain_error
);
1120 BOOST_CHECK_THROW((ur
= big_signed_max
).numerator(), std::domain_error
);
1121 BOOST_CHECK_THROW(ur
.assign(big_signed_max
, 1).numerator(), std::domain_error
);
1122 BOOST_CHECK_THROW(ur
.assign(1, big_signed_max
).denominator(), std::domain_error
);
1124 BOOST_CHECK_EQUAL(unsigned_rat(small_signed_max
).numerator(), small_signed_max
);
1125 BOOST_CHECK_EQUAL(unsigned_rat(small_signed_max
, 1).numerator(), small_signed_max
);
1126 BOOST_CHECK_EQUAL(unsigned_rat(1, small_signed_max
).denominator(), small_signed_max
);
1127 BOOST_CHECK_EQUAL((ur
= small_signed_max
).numerator(), small_signed_max
);
1128 BOOST_CHECK_EQUAL(ur
.assign(small_signed_max
, 1).numerator(), small_signed_max
);
1129 BOOST_CHECK_EQUAL(ur
.assign(1, small_signed_max
).denominator(), small_signed_max
);
1130 small_signed_max
= -1;
1131 BOOST_CHECK_THROW(unsigned_rat(small_signed_max
).numerator(), std::domain_error
);
1132 BOOST_CHECK_THROW(unsigned_rat(small_signed_max
, 1).numerator(), std::domain_error
);
1133 BOOST_CHECK_THROW(unsigned_rat(1, small_signed_max
).denominator(), std::domain_error
);
1134 BOOST_CHECK_THROW((ur
= small_signed_max
).numerator(), std::domain_error
);
1135 BOOST_CHECK_THROW(ur
.assign(small_signed_max
, 1).numerator(), std::domain_error
);
1136 BOOST_CHECK_THROW(ur
.assign(1, small_signed_max
).denominator(), std::domain_error
);
1139 BOOST_AUTO_TEST_SUITE_END()
1142 // The non-basic rational operations suite
1143 BOOST_AUTO_TEST_SUITE( rational_extras_suite
)
1145 #ifndef BOOST_NO_IOSTREAM
1147 BOOST_AUTO_TEST_CASE_TEMPLATE( rational_output_test
, T
, all_signed_test_types
)
1149 using namespace std
;
1150 typedef boost::rational
<T
> rational_type
;
1155 oss
<< rational_type( 44, 14 );
1156 BOOST_CHECK_EQUAL( oss
.str(), "22/7" );
1159 oss
.clear(); oss
.str( "" );
1160 oss
<< setw( 5 ) << setfill('*') << rational_type( 1, 2 ) << 'r';
1161 BOOST_CHECK_EQUAL( oss
.str(), "**1/2r" ); // not "****1/2r"
1164 oss
.clear(); oss
.str( "" );
1165 oss
<< showpos
<< rational_type( 2, 3 ) << noshowpos
;
1166 BOOST_CHECK_EQUAL( oss
.str(), "+2/3" ); // not "+2/+3"
1169 oss
.clear(); oss
.str( "" );
1170 oss
<< setw( 8 ) << internal
<< rational_type( 36, -15 ) << right
<< 'r';
1171 BOOST_CHECK_EQUAL( oss
.str(), "-***12/5r" ); // not "-*****12/5r"
1174 oss
.clear(); oss
.str( "" );
1175 oss
<< showbase
<< hex
<< rational_type( 34, 987 ) << noshowbase
<< dec
;
1176 BOOST_CHECK_EQUAL( oss
.str(), "0x22/3db" ); // not "0x22/0x3db"
1179 // Input test, failing
1180 BOOST_AUTO_TEST_CASE_TEMPLATE( rational_input_failing_test
, T
,
1181 all_signed_test_types
)
1183 std::istringstream
iss( "" );
1184 boost::rational
<T
> r
;
1187 BOOST_CHECK( !iss
);
1188 BOOST_CHECK( !iss
.bad() );
1193 BOOST_CHECK( !iss
);
1198 BOOST_CHECK( !iss
);
1203 BOOST_CHECK( !iss
);
1208 BOOST_CHECK( !iss
);
1213 BOOST_CHECK( !iss
);
1218 BOOST_CHECK( !iss
);
1220 // Illegal value check(s)
1221 typedef std::numeric_limits
<T
> limits_type
;
1226 BOOST_CHECK( !iss
);
1228 if ( limits_type::is_signed
&& limits_type::is_bounded
&&
1229 limits_type::min
BOOST_PREVENT_MACRO_SUBSTITUTION () +
1230 limits_type::max
BOOST_PREVENT_MACRO_SUBSTITUTION () < T(0) )
1232 std::ostringstream oss
;
1234 oss
<< 1 << '/' << limits_type::min
BOOST_PREVENT_MACRO_SUBSTITUTION ();
1236 iss
.str( oss
.str() );
1237 iss
.exceptions( std::ios::failbit
);
1238 BOOST_CHECK( iss
.good() );
1239 BOOST_CHECK_THROW( iss
>> r
, boost::bad_rational
);
1240 BOOST_CHECK( iss
.fail() && !iss
.bad() );
1241 iss
.exceptions( std::ios::goodbit
);
1245 // Input test, passing
1246 BOOST_AUTO_TEST_CASE_TEMPLATE( rational_input_passing_test
, T
,
1247 all_signed_test_types
)
1249 typedef boost::rational
<T
> rational_type
;
1251 std::istringstream
iss( "1/2 12" );
1255 BOOST_CHECK( iss
>> r
>> n
);
1256 BOOST_CHECK_EQUAL( r
, rational_type(1, 2) );
1257 BOOST_CHECK_EQUAL( n
, 12 );
1261 BOOST_CHECK( iss
>> r
);
1262 BOOST_CHECK_EQUAL( r
, rational_type(34, 67) );
1266 BOOST_CHECK( iss
>> r
);
1267 BOOST_CHECK_EQUAL( r
, rational_type(1, 2) );
1269 #endif // BOOST_NO_IOSTREAM
1272 BOOST_AUTO_TEST_CASE( rational_cast_test
)
1274 // Note that these are not generic. The problem is that rational_cast<T>
1275 // requires a conversion from IntType to T. However, for a user-defined
1276 // IntType, it is not possible to define such a conversion except as an
1277 // "operator T()". This causes problems with overloading resolution.
1278 boost::rational
<int> const half( 1, 2 );
1280 BOOST_CHECK_CLOSE( boost::rational_cast
<double>(half
), 0.5, 0.01 );
1281 BOOST_CHECK_EQUAL( boost::rational_cast
<int>(half
), 0 );
1282 BOOST_CHECK_EQUAL( boost::rational_cast
<MyInt
>(half
), MyInt() );
1283 BOOST_CHECK_EQUAL( boost::rational_cast
<boost::rational
<MyInt
> >(half
),
1284 boost::rational
<MyInt
>(1, 2) );
1286 // Conversions via explicit-marked constructors
1287 // (Note that the "explicit" mark prevents conversion to
1288 // boost::rational<MyOverflowingUnsigned>.)
1289 boost::rational
<MyInt
> const threehalves( 3, 2 );
1291 BOOST_CHECK_EQUAL( boost::rational_cast
<MyOverflowingUnsigned
>(threehalves
),
1292 MyOverflowingUnsigned(1u) );
1294 // Converting constructor should throw if a bad rational number results:
1296 BOOST_CHECK_THROW(boost::rational
<short>(boost::rational
<long>(1, 1 << sizeof(short) * CHAR_BIT
)), boost::bad_rational
);
1298 // New tests from checked narrowing conversions:
1300 BOOST_CHECK_THROW(boost::rational
<unsigned>(-1), boost::bad_rational
);
1301 BOOST_CHECK_THROW(boost::rational
<unsigned>(-1, 1), boost::bad_rational
);
1302 BOOST_CHECK_THROW(boost::rational
<unsigned>(1, -1), boost::bad_rational
);
1303 unsigned ui_max
= (std::numeric_limits
<unsigned>::max
)();
1304 BOOST_CHECK_THROW(boost::rational
<int>(static_cast<unsigned>(ui_max
)), boost::bad_rational
);
1305 BOOST_CHECK_THROW(boost::rational
<int>(ui_max
, 1u), boost::bad_rational
);
1306 BOOST_CHECK_THROW(boost::rational
<int>(1u, ui_max
), boost::bad_rational
);
1308 // Check assignments that should succeed from both wider and narrower types:
1310 boost::rational
<boost::int32_t> rat
;
1311 #ifndef BOOST_NO_INT64_T
1312 boost::int64_t ll
, ll1(1);
1313 boost::uint64_t ull
, ull1(1);
1314 boost::int32_t imax
= (std::numeric_limits
<boost::int32_t>::max
)();
1315 boost::int32_t imin
= (std::numeric_limits
<boost::int32_t>::min
)();
1317 rat
.assign(ll
, ll1
);
1318 BOOST_CHECK_EQUAL(rat
.numerator(), imax
);
1319 BOOST_CHECK_EQUAL(rat
.denominator(), 1);
1321 BOOST_CHECK_THROW(rat
.assign(ll
, ll1
), boost::bad_rational
);
1323 rat
.assign(ll
, ll1
);
1324 BOOST_CHECK_EQUAL(rat
.numerator(), imin
);
1325 BOOST_CHECK_EQUAL(rat
.denominator(), 1);
1327 BOOST_CHECK_THROW(rat
.assign(ll
, ll1
), boost::bad_rational
);
1329 rat
.assign(ull
, ull1
);
1330 BOOST_CHECK_EQUAL(rat
.numerator(), imax
);
1331 BOOST_CHECK_EQUAL(rat
.denominator(), 1);
1333 BOOST_CHECK_THROW(rat
.assign(ull
, ull1
), boost::bad_rational
);
1335 rat
.assign(ull
, ull1
);
1336 BOOST_CHECK_EQUAL(rat
.numerator(), 0);
1337 BOOST_CHECK_EQUAL(rat
.denominator(), 1);
1339 boost::int16_t smax
= (std::numeric_limits
<boost::int16_t>::max
)();
1340 boost::int16_t smin
= (std::numeric_limits
<boost::int16_t>::min
)();
1341 boost::int16_t s1
= 1;
1342 rat
.assign(smax
, s1
);
1343 BOOST_CHECK_EQUAL(rat
.numerator(), smax
);
1344 BOOST_CHECK_EQUAL(rat
.denominator(), 1);
1345 rat
.assign(smin
, s1
);
1346 BOOST_CHECK_EQUAL(rat
.numerator(), smin
);
1347 BOOST_CHECK_EQUAL(rat
.denominator(), 1);
1348 boost::uint16_t usmax
= (std::numeric_limits
<boost::uint16_t>::max
)();
1349 boost::uint16_t usmin
= (std::numeric_limits
<boost::uint16_t>::min
)();
1350 boost::uint16_t us1
= 1;
1351 rat
.assign(usmax
, us1
);
1352 BOOST_CHECK_EQUAL(rat
.numerator(), usmax
);
1353 BOOST_CHECK_EQUAL(rat
.denominator(), 1);
1354 rat
.assign(usmin
, us1
);
1355 BOOST_CHECK_EQUAL(rat
.numerator(), usmin
);
1356 BOOST_CHECK_EQUAL(rat
.denominator(), 1);
1358 // Over again with unsigned rational:
1360 boost::rational
<boost::uint32_t> urat
;
1361 unsigned uimax
= (std::numeric_limits
<boost::uint32_t>::max
)();
1362 unsigned uimin
= (std::numeric_limits
<boost::uint32_t>::min
)();
1363 #ifndef BOOST_NO_INT64_T
1365 urat
.assign(ll
, ll1
);
1366 BOOST_CHECK_EQUAL(urat
.numerator(), uimax
);
1367 BOOST_CHECK_EQUAL(urat
.denominator(), 1);
1369 BOOST_CHECK_THROW(urat
.assign(ll
, ll1
), boost::bad_rational
);
1371 urat
.assign(ll
, ll1
);
1372 BOOST_CHECK_EQUAL(urat
.numerator(), uimin
);
1373 BOOST_CHECK_EQUAL(urat
.denominator(), 1);
1375 BOOST_CHECK_THROW(urat
.assign(ll
, ll1
), boost::bad_rational
);
1377 urat
.assign(ull
, ull1
);
1378 BOOST_CHECK_EQUAL(urat
.numerator(), uimax
);
1379 BOOST_CHECK_EQUAL(urat
.denominator(), 1);
1381 BOOST_CHECK_THROW(urat
.assign(ull
, ull1
), boost::bad_rational
);
1383 urat
.assign(ull
, ull1
);
1384 BOOST_CHECK_EQUAL(urat
.numerator(), 0);
1385 BOOST_CHECK_EQUAL(urat
.denominator(), 1);
1389 urat
.assign(smax
, s1
);
1390 BOOST_CHECK_EQUAL(urat
.numerator(), smax
);
1391 BOOST_CHECK_EQUAL(urat
.denominator(), 1);
1392 urat
.assign(smin
, s1
);
1393 BOOST_CHECK_EQUAL(urat
.numerator(), smin
);
1394 BOOST_CHECK_EQUAL(urat
.denominator(), 1);
1395 urat
.assign(usmax
, us1
);
1396 BOOST_CHECK_EQUAL(urat
.numerator(), usmax
);
1397 BOOST_CHECK_EQUAL(urat
.denominator(), 1);
1398 urat
.assign(usmin
, us1
);
1399 BOOST_CHECK_EQUAL(urat
.numerator(), usmin
);
1400 BOOST_CHECK_EQUAL(urat
.denominator(), 1);
1402 // Conversions that must not be allowed:
1404 BOOST_STATIC_ASSERT(!boost::is_convertible
<float, boost::rational
<int> >::value
);
1405 BOOST_STATIC_ASSERT(!boost::is_convertible
<double, boost::rational
<int> >::value
);
1406 BOOST_STATIC_ASSERT(!boost::is_convertible
<long double, boost::rational
<int> >::value
);
1407 // And ones that should:
1408 BOOST_STATIC_ASSERT(boost::is_convertible
<char, boost::rational
<int> >::value
);
1409 BOOST_STATIC_ASSERT(boost::is_convertible
<signed char, boost::rational
<int> >::value
);
1410 BOOST_STATIC_ASSERT(boost::is_convertible
<unsigned char, boost::rational
<int> >::value
);
1411 BOOST_STATIC_ASSERT(boost::is_convertible
<short, boost::rational
<int> >::value
);
1412 BOOST_STATIC_ASSERT(boost::is_convertible
<unsigned short, boost::rational
<int> >::value
);
1413 BOOST_STATIC_ASSERT(boost::is_convertible
<int, boost::rational
<int> >::value
);
1414 BOOST_STATIC_ASSERT(boost::is_convertible
<unsigned int, boost::rational
<int> >::value
);
1415 BOOST_STATIC_ASSERT(boost::is_convertible
<long, boost::rational
<int> >::value
);
1416 BOOST_STATIC_ASSERT(boost::is_convertible
<unsigned long, boost::rational
<int> >::value
);
1419 #ifndef BOOST_NO_MEMBER_TEMPLATES
1420 // Cross-conversion constructor test
1421 BOOST_AUTO_TEST_CASE( rational_cross_constructor_test
)
1423 // This template will be repeated a lot.
1424 using boost::rational
;
1426 // Create a bunch of explicit conversions.
1427 rational
<int> const half_i( 2, 4 );
1428 rational
<unsigned> const half_u( half_i
);
1429 rational
<MyInt
> const half_mi( half_i
);
1430 rational
<MyOverflowingUnsigned
> const half_mu1(half_u
), half_mu2(half_mi
);
1432 BOOST_CHECK_EQUAL( half_u
.numerator(), 1u );
1433 BOOST_CHECK_EQUAL( half_u
.denominator(), 2u );
1434 BOOST_CHECK_EQUAL( half_mi
.numerator(), MyInt(1) );
1435 BOOST_CHECK_EQUAL( half_mi
.denominator(), MyInt(2) );
1436 BOOST_CHECK_EQUAL( half_mu1
.numerator(), MyOverflowingUnsigned(1u) );
1437 BOOST_CHECK_EQUAL( half_mu1
.denominator(), MyOverflowingUnsigned(2u) );
1438 BOOST_CHECK_EQUAL( half_mu2
.numerator(), MyOverflowingUnsigned(1u) );
1439 BOOST_CHECK_EQUAL( half_mu2
.denominator(), MyOverflowingUnsigned(2u) );
1442 // This will fail since it needs an implicit conversion.
1443 // (Try it if your compiler supports C++11 lambdas.)
1444 BOOST_CHECK( [](rational
<unsigned> x
){return !!x
;}(half_i
) );
1447 // Translation from a built-in unsigned type to a signed one is
1448 // implementation-defined, so hopefully we won't get a trap value.
1449 // (We're counting on static_cast<int>(UINT_MAX) being negative.)
1450 rational
<unsigned> const too_small( 1u, UINT_MAX
);
1451 rational
<int> receiver
;
1453 BOOST_CHECK_THROW( receiver
=rational
<int>(too_small
), boost::bad_rational
);
1455 #endif // BOOST_NO_MEMBER_TEMPLATES
1457 // Dice tests (a non-main test)
1458 BOOST_AUTO_TEST_CASE_TEMPLATE( dice_roll_test
, T
, all_signed_test_types
)
1460 typedef boost::rational
<T
> rational_type
;
1462 // Determine the mean number of times a fair six-sided die
1463 // must be thrown until each side has appeared at least once.
1464 rational_type r
= T( 0 );
1466 for ( int i
= 1 ; i
<= 6 ; ++i
)
1468 r
+= rational_type( 1, i
);
1470 r
*= static_cast<T
>( 6 );
1472 BOOST_CHECK_EQUAL( r
, rational_type(147, 10) );
1475 BOOST_AUTO_TEST_SUITE_END()
1478 // The bugs, patches, and requests checking suite
1479 BOOST_AUTO_TEST_SUITE( bug_patch_request_suite
)
1481 // "rational operator< can overflow"
1482 BOOST_AUTO_TEST_CASE( bug_798357_test
)
1484 // Choose values such that rational-number comparisons will overflow if
1485 // the multiplication method (n1/d1 ? n2/d2 == n1*d2 ? n2*d1) is used.
1486 // (And make sure that the large components are relatively prime, so they
1487 // won't partially cancel to make smaller, more reasonable, values.)
1488 unsigned const n1
= UINT_MAX
- 2u, d1
= UINT_MAX
- 1u;
1489 unsigned const n2
= d1
, d2
= UINT_MAX
;
1490 boost::rational
<MyOverflowingUnsigned
> const r1( n1
, d1
), r2( n2
, d2
);
1492 BOOST_REQUIRE_EQUAL( boost::integer::gcd(n1
, d1
), 1u );
1493 BOOST_REQUIRE_EQUAL( boost::integer::gcd(n2
, d2
), 1u );
1494 BOOST_REQUIRE( n1
> UINT_MAX
/ d2
);
1495 BOOST_REQUIRE( n2
> UINT_MAX
/ d1
);
1496 BOOST_CHECK( r1
< r2
);
1497 BOOST_CHECK( !(r1
< r1
) );
1498 BOOST_CHECK( !(r2
< r1
) );
1501 // "rational::operator< fails for unsigned value types"
1502 BOOST_AUTO_TEST_CASE( patch_1434821_test
)
1504 // If a zero-rational v. positive-integer comparison involves negation, then
1505 // it may fail with unsigned types, which wrap around (for built-ins) or
1506 // throw/be-undefined (for user-defined types).
1507 boost::rational
<unsigned> const r( 0u );
1509 BOOST_CHECK( r
< 1u );
1512 // "rational.hpp::gcd returns a negative value sometimes"
1513 BOOST_AUTO_TEST_CASE( patch_1438626_test
)
1515 // The issue only manifests with 2's-complement integers that use their
1516 // entire range of bits. [This means that ln(-INT_MIN)/ln(2) is an integer
1517 // and INT_MAX + INT_MIN == -1.] The common computer platforms match this.
1518 #if (INT_MAX + INT_MIN == -1) && ((INT_MAX ^ INT_MIN) == -1)
1519 // If a GCD routine takes the absolute value of an argument only before
1520 // processing, it won't realize that -INT_MIN -> INT_MIN (i.e. no change
1521 // from negation) and will propagate a negative sign to its result.
1522 BOOST_REQUIRE_EQUAL( boost::integer::gcd(INT_MIN
, 6), 2 );
1524 // That is bad if the rational number type does not check for that
1525 // possibility during normalization.
1526 boost::rational
<int> const r1( INT_MIN
/ 2 + 3, 6 ),
1527 r2( INT_MIN
/ 2 - 3, 6 ), r3
= r1
+ r2
;
1529 // If the error happens, the signs of the components will be switched.
1530 // (The numerators' sum is INT_MIN, and its GCD with 6 would be negated.)
1531 BOOST_CHECK_EQUAL( r3
.numerator(), INT_MIN
/ 2 );
1532 BOOST_CHECK_EQUAL( r3
.denominator(), 3 );
1536 // The bug/patch numbers for the above 3 tests are from our SourceForge repo
1537 // before we moved to our own SVN & Trac server. At the time this note is
1538 // written, it seems that SourceForge has reset their tracking numbers at least
1539 // once, so I don't know how to recover those old tickets. The ticket numbers
1540 // for the following tests are from our SVN/Trac repo.
1542 //"narrowing conversion error with -std=c++0x in operator< with int_type != int"
1543 BOOST_AUTO_TEST_CASE( ticket_5855_test
)
1545 // The internals of operator< currently store a structure of two int_type
1546 // (where int_type is the component type of a boost::rational template
1547 // class) and two computed types. These computed types, results of
1548 // arithmetic operations among int_type values, are either int_type
1549 // themselves or a larger type that can implicitly convert to int_type.
1550 // Those conversions aren't usually a problem. But when an arithmetic
1551 // operation involving two values of a built-in scalar type smaller than int
1552 // are involved, the result is an int. But the resulting int-to-shorter
1553 // conversion is considered narrowing, resulting in a warning or error on
1554 // some compilers. Notably, C++11 compilers are supposed to consider it an
1557 // The solution is to force an explicit conversion, although it's otherwise
1558 // not needed. (The compiler can rescind the narrowing warning if the
1559 // results of the larger type still fit in the smaller one, and that proof
1560 // can be generated at constexpr time.)
1561 typedef short shorter_than_int_type
;
1562 typedef boost::rational
<shorter_than_int_type
> rational_type
;
1564 bool const dummy
= rational_type() < rational_type();
1566 BOOST_REQUIRE( !dummy
);
1569 // "rational::assign" doesn't even have the basic guarantee
1570 BOOST_AUTO_TEST_CASE( ticket_9067_test
)
1572 using boost::rational
;
1573 using boost::integer::gcd
;
1575 rational
<int> a( 6, -8 );
1577 // Normalize to maintain invariants
1578 BOOST_CHECK_EQUAL( a
.numerator(), -3 );
1579 BOOST_CHECK_EQUAL( a
.denominator(), 4 );
1580 BOOST_CHECK( a
.denominator() > 0 );
1581 BOOST_CHECK_EQUAL( gcd(a
.numerator(), a
.denominator()), 1 );
1583 // Do we maintain the basic guarantee after a failed component-assign?
1584 BOOST_CHECK_THROW( a
.assign(1, 0), boost::bad_rational
);
1585 BOOST_CHECK_NE( a
.denominator(), 0 );
1586 BOOST_CHECK( a
.denominator() > 0 );
1587 BOOST_CHECK_EQUAL( gcd(a
.numerator(), a
.denominator()), 1 );
1589 // Do we get the strong guarantee?
1590 BOOST_CHECK_EQUAL( a
.numerator(), -3 );
1591 BOOST_CHECK_EQUAL( a
.denominator(), 4 );
1593 #if INT_MIN + INT_MAX < 0
1594 // Try an example without a zero-denominator
1595 a
= rational
<int>( -9, 12 );
1596 BOOST_CHECK_EQUAL( a
.numerator(), -3 );
1597 BOOST_CHECK_EQUAL( a
.denominator(), 4 );
1598 BOOST_CHECK( a
.denominator() > 0 );
1599 BOOST_CHECK_EQUAL( gcd(a
.numerator(), a
.denominator()), 1 );
1600 BOOST_CHECK_THROW( a
.assign(-(INT_MIN
+ 1), INT_MIN
), boost::bad_rational
);
1601 BOOST_CHECK( a
.denominator() > 0 );
1602 BOOST_CHECK_EQUAL( gcd(a
.numerator(), a
.denominator()), 1 );
1603 BOOST_CHECK_EQUAL( a
.numerator(), -3 );
1604 BOOST_CHECK_EQUAL( a
.denominator(), 4 );
1608 BOOST_AUTO_TEST_SUITE_END()