-
Notifications
You must be signed in to change notification settings - Fork 255
Polynomial fixes: for mixed-type arithmetic etc. #41
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: develop
Are you sure you want to change the base?
Changes from all commits
a1b34b8
bf46cd3
1271818
9c7d39e
78d7dc0
fb6b899
89331d0
a1f74c1
f4d73fe
35022a6
8646ae4
910a62a
2798e23
885e13f
1115101
9da5ff2
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -255,12 +255,11 @@ quotient_remainder(const polynomial<T>& dividend, const polynomial<T>& divisor) | |
|
|
||
|
|
||
| template <class T> | ||
| class polynomial : | ||
| equality_comparable< polynomial<T>, | ||
| dividable< polynomial<T>, | ||
| dividable2< polynomial<T>, T, | ||
| modable< polynomial<T>, | ||
| modable2< polynomial<T>, T > > > > > | ||
| class polynomial : ordered_euclidean_ring_operators< polynomial<T> > | ||
| /* Provides operators +, -, *, /, % for two polynomials (using member += etc.); | ||
| * operators >, <=, >= using operator < ; and operator != using operator ==. | ||
| * Note that polynomials are not actually a euclidean ring when T is not | ||
| * a field type, in particular, if T is integral. */ | ||
| { | ||
| public: | ||
| // typedefs: | ||
|
|
@@ -296,7 +295,7 @@ class polynomial : | |
| : m_data(p.m_data) { } | ||
|
|
||
| template <class U> | ||
| polynomial(const polynomial<U>& p) | ||
| explicit polynomial(const polynomial<U>& p) | ||
| { | ||
| for(unsigned i = 0; i < p.size(); ++i) | ||
| { | ||
|
|
@@ -388,30 +387,37 @@ class polynomial : | |
| } | ||
|
|
||
| template <class U> | ||
| polynomial& operator %=(const U& /*value*/) | ||
| { | ||
| // We can always divide by a scalar, so there is no remainder: | ||
| this->set_zero(); | ||
| polynomial& operator %=(const U& value) | ||
| { | ||
| // In the case that T is integral, this preserves the semantics | ||
| // p == r*(p/r) + (p % r), for polynomial<T> p and U r. | ||
| if (std::numeric_limits<T>::is_integer) | ||
| { | ||
| modulus(value); | ||
| normalize(); | ||
| } | ||
| else | ||
| { | ||
| set_zero(); | ||
| } | ||
| return *this; | ||
| } | ||
|
|
||
| template <class U> | ||
| polynomial& operator +=(const polynomial<U>& value) | ||
| polynomial& operator +=(const polynomial& value) | ||
| { | ||
| addition(value); | ||
| normalize(); | ||
| return *this; | ||
| } | ||
|
|
||
| template <class U> | ||
| polynomial& operator -=(const polynomial<U>& value) | ||
| polynomial& operator -=(const polynomial& value) | ||
| { | ||
| subtraction(value); | ||
| normalize(); | ||
| return *this; | ||
| } | ||
| template <class U> | ||
| polynomial& operator *=(const polynomial<U>& value) | ||
|
|
||
| polynomial& operator *=(const polynomial& value) | ||
| { | ||
| // TODO: FIXME: use O(N log(N)) algorithm!!! | ||
| if (!value) | ||
|
|
@@ -427,31 +433,28 @@ class polynomial : | |
| return *this; | ||
| } | ||
|
|
||
| template <typename U> | ||
| polynomial& operator /=(const polynomial<U>& value) | ||
| polynomial& operator /=(const polynomial& value) | ||
| { | ||
| *this = quotient_remainder(*this, value).first; | ||
| return *this; | ||
| } | ||
|
|
||
| template <typename U> | ||
| polynomial& operator %=(const polynomial<U>& value) | ||
| polynomial& operator %=(const polynomial& value) | ||
| { | ||
| *this = quotient_remainder(*this, value).second; | ||
| return *this; | ||
| } | ||
|
|
||
| template <typename U> | ||
| polynomial& operator >>=(U const &n) | ||
| polynomial& operator >>=(int n) | ||
| { | ||
| BOOST_ASSERT(n <= m_data.size()); | ||
| BOOST_ASSERT(n >= 0 && static_cast<unsigned>(n) <= m_data.size()); | ||
| m_data.erase(m_data.begin(), m_data.begin() + n); | ||
| return *this; | ||
| } | ||
|
|
||
| template <typename U> | ||
| polynomial& operator <<=(U const &n) | ||
| polynomial& operator <<=(int n) | ||
| { | ||
| BOOST_ASSERT(n >= 0); | ||
| m_data.insert(m_data.begin(), n, static_cast<T>(0)); | ||
| normalize(); | ||
| return *this; | ||
|
|
@@ -554,64 +557,59 @@ class polynomial : | |
| return *this; | ||
| } | ||
|
|
||
| template <class U> | ||
| polynomial& modulus(const U& value) | ||
| { | ||
| typedef typename std::vector<T>::iterator iter; | ||
| for (iter it = m_data.begin(); it != m_data.end(); ++it) | ||
| *it -= T(value * T(*it / value)); | ||
| return *this; | ||
| } | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Should
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes, |
||
|
|
||
| std::vector<T> m_data; | ||
| }; | ||
|
|
||
|
|
||
| template <class T> | ||
| inline polynomial<T> operator + (const polynomial<T>& a, const polynomial<T>& b) | ||
| { | ||
| polynomial<T> result(a); | ||
| result += b; | ||
| return result; | ||
| } | ||
|
|
||
| template <class T> | ||
| inline polynomial<T> operator - (const polynomial<T>& a, const polynomial<T>& b) | ||
| template <class T, class U> | ||
| inline polynomial<T> operator + (polynomial<T> a, const U& b) | ||
| { | ||
| polynomial<T> result(a); | ||
| result -= b; | ||
| return result; | ||
| a += b; | ||
| return a; | ||
| } | ||
|
|
||
| template <class T> | ||
| inline polynomial<T> operator * (const polynomial<T>& a, const polynomial<T>& b) | ||
| template <class T, class U> | ||
| inline polynomial<T> operator - (polynomial<T> a, const U& b) | ||
| { | ||
| polynomial<T> result(a); | ||
| result *= b; | ||
| return result; | ||
| a -= b; | ||
| return a; | ||
| } | ||
|
|
||
| template <class T, class U> | ||
| inline polynomial<T> operator + (const polynomial<T>& a, const U& b) | ||
| inline polynomial<T> operator * (polynomial<T> a, const U& b) | ||
| { | ||
| polynomial<T> result(a); | ||
| result += b; | ||
| return result; | ||
| a *= b; | ||
| return a; | ||
| } | ||
|
|
||
| template <class T, class U> | ||
| inline polynomial<T> operator - (const polynomial<T>& a, const U& b) | ||
| inline polynomial<T> operator / (polynomial<T> a, const U& b) | ||
| { | ||
| polynomial<T> result(a); | ||
| result -= b; | ||
| return result; | ||
| a /= b; | ||
| return a; | ||
| } | ||
|
|
||
| template <class T, class U> | ||
| inline polynomial<T> operator * (const polynomial<T>& a, const U& b) | ||
| inline polynomial<T> operator % (polynomial<T> a, const U& b) | ||
| { | ||
| polynomial<T> result(a); | ||
| result *= b; | ||
| return result; | ||
| a %= b; | ||
| return a; | ||
| } | ||
|
|
||
| template <class U, class T> | ||
| inline polynomial<T> operator + (const U& a, const polynomial<T>& b) | ||
| inline polynomial<T> operator + (const U& a, polynomial<T> b) | ||
| { | ||
| polynomial<T> result(b); | ||
| result += a; | ||
| return result; | ||
| b += a; | ||
| return b; | ||
| } | ||
|
|
||
| template <class U, class T> | ||
|
|
@@ -623,51 +621,57 @@ inline polynomial<T> operator - (const U& a, const polynomial<T>& b) | |
| } | ||
|
|
||
| template <class U, class T> | ||
| inline polynomial<T> operator * (const U& a, const polynomial<T>& b) | ||
| inline polynomial<T> operator * (const U& a, polynomial<T> b) | ||
| { | ||
| polynomial<T> result(b); | ||
| result *= a; | ||
| return result; | ||
| b *= a; | ||
| return b; | ||
| } | ||
|
|
||
| template <class T> | ||
| bool operator == (const polynomial<T> &a, const polynomial<T> &b) | ||
| inline bool operator == (const polynomial<T> &a, const polynomial<T> &b) | ||
| { | ||
| return a.data() == b.data(); | ||
| } | ||
|
|
||
| template <typename T, typename U> | ||
| polynomial<T> operator >> (const polynomial<T>& a, const U& b) | ||
| template <class T> | ||
| inline bool operator < (const polynomial<T> &a, const polynomial<T> &b) | ||
| { | ||
| polynomial<T> result(a); | ||
| result >>= b; | ||
| return result; | ||
| if (a.size() != b.size()) | ||
| return a.size() < b.size(); | ||
| return std::lexicographical_compare(a.data().rbegin(), a.data().rend(), | ||
| b.data().rbegin(), b.data().rend()); | ||
| } | ||
|
|
||
| template <typename T, typename U> | ||
| polynomial<T> operator << (const polynomial<T>& a, const U& b) | ||
| template <typename T> | ||
| inline polynomial<T> operator >> (polynomial<T> a, int b) | ||
| { | ||
| polynomial<T> result(a); | ||
| result <<= b; | ||
| return result; | ||
| a >>= b; | ||
| return a; | ||
| } | ||
|
|
||
| template <typename T> | ||
| inline polynomial<T> operator << (polynomial<T> a, int b) | ||
| { | ||
| a <<= b; | ||
| return a; | ||
| } | ||
|
|
||
| // Unary minus (negate). | ||
| template <class T> | ||
| polynomial<T> operator - (polynomial<T> a) | ||
| inline polynomial<T> operator - (polynomial<T> a) | ||
| { | ||
| std::transform(a.data().begin(), a.data().end(), a.data().begin(), std::negate<T>()); | ||
| return a; | ||
| } | ||
|
|
||
| template <class T> | ||
| bool odd(polynomial<T> const &a) | ||
| inline bool odd(polynomial<T> const &a) | ||
| { | ||
| return a.size() > 0 && a[0] != static_cast<T>(0); | ||
| } | ||
|
|
||
| template <class T> | ||
| bool even(polynomial<T> const &a) | ||
| inline bool even(polynomial<T> const &a) | ||
| { | ||
| return !odd(a); | ||
| } | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since this is a compile-time constant, can't we combine it with
enable_iffor static dispatch?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I seem to recall that using
enable_ifbased only onT, which is not one of the template parameters for the function, doesn't work. Let me check.Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, I was right: GCC 6.1, GCC 5.3, and Clang 703.0.31 all complain vociferously. To separate them, it's necessary to add a dummy condition to the enable_if that depends on
U, e.g. go back toBOOST_DEDUCED_TYPENAME enable_if_c<boost::is_convertible<U,T>::value && std::numeric_limits<T>::is_integer, polynomial >::type& operator %=(const U& value).I don't think this mess is worth it:
You can observe that the last thing is true at godbolt.