Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions doc/internals/polynomial.qbk
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,10 @@
const value_type& operator[](size_type i)const;
std::vector<T> const& data() const;
std::vector<T>& data();
operator bool() const;

// modify:
void set_zero();

// operators:
template <class U>
Expand Down
11 changes: 11 additions & 0 deletions example/polynomial_arithmetic.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -197,6 +197,17 @@ even otherwise. That is:


//] [/polynomial_arithmetic_5]
//[polynomial_arithmetic_6]
/* For performance and convenience, we can test whether a polynomial is zero
* by implicitly converting to bool with the same semantics as int. */
polynomial<double> zero; // Default construction is 0.
cout << "zero: " << (zero ? "not zero" : "zero") << "\n";
cout << "r: " << (r ? "not zero" : "zero") << "\n";
/* We can also set a polynomial to zero without needing a another zero
* polynomial to assign to it. */
r.set_zero();
cout << "r: " << (r ? "not zero" : "zero") << "\n";
//] [/polynomial_arithmetic_6]
}
catch (exception const &e)
{
Expand Down
43 changes: 35 additions & 8 deletions include/boost/math/tools/polynomial.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@

#include <boost/assert.hpp>
#include <boost/config.hpp>
#include <boost/config/suffix.hpp>
#include <boost/function.hpp>
#include <boost/lambda/lambda.hpp>
#include <boost/math/tools/rational.hpp>
Expand Down Expand Up @@ -192,8 +193,8 @@ std::pair< polynomial<T>, polynomial<T> >
division(polynomial<T> u, const polynomial<T>& v)
{
BOOST_ASSERT(v.size() <= u.size());
BOOST_ASSERT(v != zero_element(std::multiplies< polynomial<T> >()));
BOOST_ASSERT(u != zero_element(std::multiplies< polynomial<T> >()));
BOOST_ASSERT(v);
BOOST_ASSERT(u);

typedef typename polynomial<T>::size_type N;

Expand Down Expand Up @@ -246,9 +247,9 @@ template <typename T>
std::pair< polynomial<T>, polynomial<T> >
quotient_remainder(const polynomial<T>& dividend, const polynomial<T>& divisor)
{
BOOST_ASSERT(divisor != zero_element(std::multiplies< polynomial<T> >()));
BOOST_ASSERT(divisor);
if (dividend.size() < divisor.size())
return std::make_pair(zero_element(std::multiplies< polynomial<T> >()), dividend);
return std::make_pair(polynomial<T>(), dividend);
return detail::division(dividend, divisor);
}

Expand Down Expand Up @@ -390,7 +391,7 @@ class polynomial :
polynomial& operator %=(const U& /*value*/)
{
// We can always divide by a scalar, so there is no remainder:
*this = zero_element(std::multiplies<polynomial>());
this->set_zero();
return *this;
}

Expand All @@ -413,10 +414,9 @@ class polynomial :
polynomial& operator *=(const polynomial<U>& value)
{
// TODO: FIXME: use O(N log(N)) algorithm!!!
polynomial const zero = zero_element(std::multiplies<polynomial>());
if (value == zero)
if (!value)
{
*this = zero;
this->set_zero();
return *this;
}
std::vector<T> prod(size() + value.size() - 1, T(0));
Expand Down Expand Up @@ -456,6 +456,33 @@ class polynomial :
normalize();
return *this;
}

// Convenient and efficient query for zero.
bool is_zero() const
{
return m_data.empty();
}

// Conversion to bool.
#ifdef BOOST_NO_CXX11_EXPLICIT_CONVERSION_OPERATORS
typedef bool (polynomial::*unmentionable_type)() const;

BOOST_FORCEINLINE operator unmentionable_type() const
{
return is_zero() ? false : &polynomial::is_zero;
}
#else
BOOST_FORCEINLINE explicit operator bool() const
{
return !m_data.empty();
}
#endif

// Fast way to set a polynomial to zero.
void set_zero()
{
m_data.clear();
}

/** Remove zero coefficients 'from the top', that is for which there are no
* non-zero coefficients of higher degree. */
Expand Down
21 changes: 21 additions & 0 deletions test/test_polynomial.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -299,6 +299,7 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(test_odd_even, T, all_test_types)
BOOST_CHECK_EQUAL(even(b), true);
}


BOOST_AUTO_TEST_CASE_TEMPLATE( test_pow, T, all_test_types )
{
polynomial<T> a(d3a.begin(), d3a.end());
Expand All @@ -321,3 +322,23 @@ BOOST_AUTO_TEST_CASE_TEMPLATE( test_pow, T, all_test_types )
BOOST_CHECK_THROW(pow(a, -1), std::domain_error);
BOOST_CHECK_EQUAL(pow(one, 137), one);
}


BOOST_AUTO_TEST_CASE_TEMPLATE(test_bool, T, all_test_types)
{
polynomial<T> const zero;
polynomial<T> const a(d0a.begin(), d0a.end());
BOOST_CHECK_EQUAL(bool(zero), false);
BOOST_CHECK_EQUAL(bool(a), true);
}


BOOST_AUTO_TEST_CASE_TEMPLATE(test_set_zero, T, all_test_types)
{
polynomial<T> const zero;
polynomial<T> a(d0a.begin(), d0a.end());
a.set_zero();
BOOST_CHECK_EQUAL(a, zero);
a.set_zero(); // Ensure that setting zero to zero is a no-op.
BOOST_CHECK_EQUAL(a, zero);
}