|
|
@@ -14,6 +14,9 @@ |
|
|
|
// The polynomial class |
|
|
|
// -------------------- |
|
|
|
// |
|
|
|
// The data structure is a simple dynamic array of scalars, with the |
|
|
|
// added guarantee that the leading coefficient is always non-zero. |
|
|
|
// |
|
|
|
|
|
|
|
#include <functional> |
|
|
|
|
|
|
@@ -105,50 +108,56 @@ struct polynomial |
|
|
|
|
|
|
|
array<T> roots() const |
|
|
|
{ |
|
|
|
ASSERT(degree() >= 0, "roots() called on the null polynomial"); |
|
|
|
/* For now we can only solve polynomials of degrees 0, 1 or 2. */ |
|
|
|
ASSERT(degree() >= 0 && degree() <= 2, |
|
|
|
"roots() called on polynomial of degree %d", degree()); |
|
|
|
|
|
|
|
if (degree() == 0) |
|
|
|
{ |
|
|
|
/* p(x) = a > 0 */ |
|
|
|
return array<T> {}; |
|
|
|
/* p(x) = a > 0 */ |
|
|
|
return array<T> {}; |
|
|
|
} |
|
|
|
else if (degree() == 1) |
|
|
|
{ |
|
|
|
/* p(x) = ax + b */ |
|
|
|
T const &a = m_coefficients[1]; |
|
|
|
T const &b = m_coefficients[0]; |
|
|
|
return array<T> { -b / a }; |
|
|
|
/* p(x) = ax + b */ |
|
|
|
T const &a = m_coefficients[1]; |
|
|
|
T const &b = m_coefficients[0]; |
|
|
|
return array<T> { -b / a }; |
|
|
|
} |
|
|
|
else if (degree() == 2) |
|
|
|
{ |
|
|
|
/* p(x) = ax² + bx + c */ |
|
|
|
T const &a = m_coefficients[2]; |
|
|
|
T const &b = m_coefficients[1]; |
|
|
|
T const &c = m_coefficients[0]; |
|
|
|
/* p(x) = ax² + bx + c */ |
|
|
|
T const &a = m_coefficients[2]; |
|
|
|
T const &b = m_coefficients[1]; |
|
|
|
T const &c = m_coefficients[0]; |
|
|
|
|
|
|
|
T const k = b / (a + a); |
|
|
|
T const delta = k * k - c / a; |
|
|
|
T const k = b / (a + a); |
|
|
|
T const delta = k * k - c / a; |
|
|
|
|
|
|
|
if (delta < T(0)) |
|
|
|
{ |
|
|
|
if (delta < T(0)) |
|
|
|
{ |
|
|
|
return array<T> {}; |
|
|
|
} |
|
|
|
else if (delta > T(0)) |
|
|
|
{ |
|
|
|
} |
|
|
|
else if (delta > T(0)) |
|
|
|
{ |
|
|
|
T const sqrt_delta = sqrt(delta); |
|
|
|
return array<T> { -k - sqrt_delta, -k + sqrt_delta }; |
|
|
|
} |
|
|
|
else |
|
|
|
{ |
|
|
|
} |
|
|
|
else |
|
|
|
{ |
|
|
|
return array<T> { -k }; |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
ASSERT(false, "roots() called on polynomial of degree %d > 2", |
|
|
|
degree()); |
|
|
|
/* It is an error to reach this point. */ |
|
|
|
ASSERT(false); |
|
|
|
return array<T> {}; |
|
|
|
} |
|
|
|
|
|
|
|
/* Access individual coefficients. This is read-only and returns a |
|
|
|
* copy because we cannot let the user mess with the integrity of |
|
|
|
* the structure (i.e. the guarantee that the leading coefficient |
|
|
|
* remains non-zero). */ |
|
|
|
inline T operator[](ptrdiff_t n) const |
|
|
|
{ |
|
|
|
if (n < 0 || n > degree()) |
|
|
@@ -157,11 +166,13 @@ struct polynomial |
|
|
|
return m_coefficients[n]; |
|
|
|
} |
|
|
|
|
|
|
|
/* Unary plus */ |
|
|
|
polynomial<T> operator +() const |
|
|
|
{ |
|
|
|
return *this; |
|
|
|
} |
|
|
|
|
|
|
|
/* Unary minus */ |
|
|
|
polynomial<T> operator -() const |
|
|
|
{ |
|
|
|
polynomial<T> ret; |
|
|
@@ -170,6 +181,7 @@ struct polynomial |
|
|
|
return ret; |
|
|
|
} |
|
|
|
|
|
|
|
/* Add two polynomials */ |
|
|
|
polynomial<T> &operator +=(polynomial<T> const &p) |
|
|
|
{ |
|
|
|
int min_degree = lol::min(p.degree(), degree()); |
|
|
@@ -189,6 +201,7 @@ struct polynomial |
|
|
|
return polynomial<T>(*this) += p; |
|
|
|
} |
|
|
|
|
|
|
|
/* Subtract two polynomials */ |
|
|
|
polynomial<T> &operator -=(polynomial<T> const &p) |
|
|
|
{ |
|
|
|
return *this += -p; |
|
|
@@ -199,6 +212,7 @@ struct polynomial |
|
|
|
return polynomial<T>(*this) += -p; |
|
|
|
} |
|
|
|
|
|
|
|
/* Multiply polynomial by a scalar */ |
|
|
|
polynomial<T> &operator *=(T const &k) |
|
|
|
{ |
|
|
|
for (auto &a : m_coefficients) |
|
|
@@ -212,6 +226,18 @@ struct polynomial |
|
|
|
return polynomial<T>(*this) *= k; |
|
|
|
} |
|
|
|
|
|
|
|
/* Divide polynomial by a scalar */ |
|
|
|
polynomial<T> &operator /=(T const &k) |
|
|
|
{ |
|
|
|
return *this *= (T(1) / k); |
|
|
|
} |
|
|
|
|
|
|
|
polynomial<T> operator /(T const &k) const |
|
|
|
{ |
|
|
|
return *this * (T(1) / k); |
|
|
|
} |
|
|
|
|
|
|
|
/* Multiply polynomial by another polynomial */ |
|
|
|
polynomial<T> &operator *=(polynomial<T> const &p) |
|
|
|
{ |
|
|
|
return *this = *this * p; |
|
|
@@ -239,6 +265,7 @@ struct polynomial |
|
|
|
} |
|
|
|
|
|
|
|
private: |
|
|
|
/* Enforce the non-zero leading coefficient rule. */ |
|
|
|
void reduce_degree() |
|
|
|
{ |
|
|
|
while (m_coefficients.Count() && m_coefficients.Last() == T(0)) |
|
|
|