Browse Source

math: allow to divide polynomials by scalars.

undefined
Sam Hocevar 11 years ago
parent
commit
ce9daf6899
1 changed files with 51 additions and 24 deletions
  1. +51
    -24
      src/lol/math/polynomial.h

+ 51
- 24
src/lol/math/polynomial.h View File

@@ -14,6 +14,9 @@
// The polynomial class // 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> #include <functional>


@@ -105,50 +108,56 @@ struct polynomial


array<T> roots() const 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) if (degree() == 0)
{ {
/* p(x) = a > 0 */
return array<T> {};
/* p(x) = a > 0 */
return array<T> {};
} }
else if (degree() == 1) 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) 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> {}; return array<T> {};
}
else if (delta > T(0))
{
}
else if (delta > T(0))
{
T const sqrt_delta = sqrt(delta); T const sqrt_delta = sqrt(delta);
return array<T> { -k - sqrt_delta, -k + sqrt_delta }; return array<T> { -k - sqrt_delta, -k + sqrt_delta };
}
else
{
}
else
{
return array<T> { -k }; 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> {}; 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 inline T operator[](ptrdiff_t n) const
{ {
if (n < 0 || n > degree()) if (n < 0 || n > degree())
@@ -157,11 +166,13 @@ struct polynomial
return m_coefficients[n]; return m_coefficients[n];
} }


/* Unary plus */
polynomial<T> operator +() const polynomial<T> operator +() const
{ {
return *this; return *this;
} }


/* Unary minus */
polynomial<T> operator -() const polynomial<T> operator -() const
{ {
polynomial<T> ret; polynomial<T> ret;
@@ -170,6 +181,7 @@ struct polynomial
return ret; return ret;
} }


/* Add two polynomials */
polynomial<T> &operator +=(polynomial<T> const &p) polynomial<T> &operator +=(polynomial<T> const &p)
{ {
int min_degree = lol::min(p.degree(), degree()); int min_degree = lol::min(p.degree(), degree());
@@ -189,6 +201,7 @@ struct polynomial
return polynomial<T>(*this) += p; return polynomial<T>(*this) += p;
} }


/* Subtract two polynomials */
polynomial<T> &operator -=(polynomial<T> const &p) polynomial<T> &operator -=(polynomial<T> const &p)
{ {
return *this += -p; return *this += -p;
@@ -199,6 +212,7 @@ struct polynomial
return polynomial<T>(*this) += -p; return polynomial<T>(*this) += -p;
} }


/* Multiply polynomial by a scalar */
polynomial<T> &operator *=(T const &k) polynomial<T> &operator *=(T const &k)
{ {
for (auto &a : m_coefficients) for (auto &a : m_coefficients)
@@ -212,6 +226,18 @@ struct polynomial
return polynomial<T>(*this) *= k; 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) polynomial<T> &operator *=(polynomial<T> const &p)
{ {
return *this = *this * p; return *this = *this * p;
@@ -239,6 +265,7 @@ struct polynomial
} }


private: private:
/* Enforce the non-zero leading coefficient rule. */
void reduce_degree() void reduce_degree()
{ {
while (m_coefficients.Count() && m_coefficients.Last() == T(0)) while (m_coefficients.Count() && m_coefficients.Last() == T(0))


Loading…
Cancel
Save