Skip to content

Commit

Permalink
Add pow method
Browse files Browse the repository at this point in the history
  • Loading branch information
James E. King III authored and jeking3 committed Jun 18, 2018
1 parent 70fe050 commit 25ad8e5
Show file tree
Hide file tree
Showing 2 changed files with 56 additions and 3 deletions.
23 changes: 20 additions & 3 deletions include/boost/rational.hpp
Expand Up @@ -21,6 +21,7 @@
// Nickolay Mladenov, for the implementation of operator+=

// Revision History
// 14 Jun 18 Add pow
// 02 Sep 13 Remove unneeded forward declarations; tweak private helper
// function (Daryle Walker)
// 30 Aug 13 Improve exception safety of "assign"; start modernizing I/O code
Expand Down Expand Up @@ -840,7 +841,7 @@ template <typename IntType>
void rational<IntType>::normalize()
{
// Avoid repeated construction
IntType zero(0);
IntType const zero(0);

if (den == zero)
BOOST_THROW_EXCEPTION(bad_rational());
Expand All @@ -856,9 +857,8 @@ void rational<IntType>::normalize()
num /= g;
den /= g;

if (den < -(std::numeric_limits<IntType>::max)()) {
if (den < -(std::numeric_limits<IntType>::max)())
BOOST_THROW_EXCEPTION(bad_rational("bad rational: non-zero singular denominator"));
}

// Ensure that the denominator is positive
if (den < zero) {
Expand All @@ -869,6 +869,23 @@ void rational<IntType>::normalize()
BOOST_ASSERT( this->test_invariant() );
}

template <typename IntType>
inline rational<IntType> pow(rational<IntType> base, IntType exponent)
{
if (!base)
return base;
bool const positive = exponent >= 0;
rational<IntType> result((exponent % 2 != 0) ? base : rational<IntType>(1));

while ((exponent /= 2) != 0) {
base *= base;
if ((exponent % 2) != 0)
result *= base;
}

return positive ? result : (static_cast<IntType>(1) / result);
}

#ifndef BOOST_NO_IOSTREAM
namespace detail {

Expand Down
36 changes: 36 additions & 0 deletions test/rational_test.cpp
Expand Up @@ -19,6 +19,7 @@
// since he hasn't been in contact for years.)

// Revision History
// 14 Jun 18 Added pow tests
// 30 Aug 13 Add bug-test of assignments holding the basic and/or strong
// guarantees (Daryle Walker)
// 27 Aug 13 Add test for cross-version constructor template (Daryle Walker)
Expand Down Expand Up @@ -1605,4 +1606,39 @@ BOOST_AUTO_TEST_CASE( ticket_9067_test )
#endif
}

// Power tests
BOOST_AUTO_TEST_CASE_TEMPLATE( rational_pow_test, T, all_signed_test_types )
{
typedef boost::rational<T> rational_type;

BOOST_CHECK_EQUAL( pow(rational_type(0), T( 0)), rational_type(0) );

BOOST_CHECK_EQUAL( pow(rational_type(2), T(-4)), rational_type(1, 16) );
BOOST_CHECK_EQUAL( pow(rational_type(2), T(-3)), rational_type(1, 8) );
BOOST_CHECK_EQUAL( pow(rational_type(2), T(-2)), rational_type(1, 4) );
BOOST_CHECK_EQUAL( pow(rational_type(2), T(-1)), rational_type(1, 2) );
BOOST_CHECK_EQUAL( pow(rational_type(2), T( 0)), rational_type(1) );
BOOST_CHECK_EQUAL( pow(rational_type(2), T( 1)), rational_type(2) );
BOOST_CHECK_EQUAL( pow(rational_type(2), T( 2)), rational_type(4) );
BOOST_CHECK_EQUAL( pow(rational_type(2), T( 3)), rational_type(8) );
BOOST_CHECK_EQUAL( pow(rational_type(2), T( 4)), rational_type(16) );

BOOST_CHECK_EQUAL( pow(rational_type(-1, 2), T(-4)), rational_type(16) );
BOOST_CHECK_EQUAL( pow(rational_type(-1, 2), T(-3)), rational_type(-8) );
BOOST_CHECK_EQUAL( pow(rational_type(-1, 2), T(-2)), rational_type(4) );
BOOST_CHECK_EQUAL( pow(rational_type(-1, 2), T(-1)), rational_type(-2) );
BOOST_CHECK_EQUAL( pow(rational_type(-1, 2), T( 0)), rational_type(1) );
BOOST_CHECK_EQUAL( pow(rational_type(-1, 2), T( 1)), rational_type(-1, 2) );
BOOST_CHECK_EQUAL( pow(rational_type(-1, 2), T( 2)), rational_type(1, 4) );
BOOST_CHECK_EQUAL( pow(rational_type(-1, 2), T( 3)), rational_type(-1, 8) );
BOOST_CHECK_EQUAL( pow(rational_type(-1, 2), T( 4)), rational_type(1, 16) );

BOOST_CHECK_EQUAL( pow(rational_type(1, 3), T(3)), rational_type(1, 27) );
BOOST_CHECK_EQUAL( pow(rational_type(2, 3), T(3)), rational_type(8, 27) );
BOOST_CHECK_EQUAL( pow(rational_type(1, 5), T(5)), rational_type(1, 3125) );
BOOST_CHECK_EQUAL( pow(rational_type(2, 5), T(5)), rational_type(32, 3125) );
BOOST_CHECK_EQUAL( pow(rational_type(3, 5), T(5)), rational_type(243, 3125) );
BOOST_CHECK_EQUAL( pow(rational_type(4, 5), T(5)), rational_type(1024, 3125) );
}

BOOST_AUTO_TEST_SUITE_END()

0 comments on commit 25ad8e5

Please sign in to comment.