Browse Source

polynomial: 3rd order solving v1.0

undefined
Guillaume Bittoun Sam Hocevar <sam@hocevar.net> 9 years ago
parent
commit
93dc8a70a7
2 changed files with 17 additions and 25 deletions
  1. +8
    -22
      src/lol/math/polynomial.h
  2. +9
    -3
      src/t/math/polynomial.cpp

+ 8
- 22
src/lol/math/polynomial.h View File

@@ -20,8 +20,6 @@

#include <functional>

// #define ENABLE_3SOLVE
// #include <iostream>

namespace lol
{
@@ -111,14 +109,9 @@ struct polynomial

array<T> roots() const
{
/* For now we can only solve polynomials of degrees 0, 1 or 2. */
#ifdef ENABLE_3SOLVE
/* For now we can only solve polynomials of degrees 0, 1, 2 or 3. */
ASSERT(degree() >= 0 && degree() <= 3,
"roots() called on polynomial of degree %d", degree());
#else
ASSERT(degree() >= 0 && degree() <= 2,
"roots() called on polynomial of degree %d", degree());
#endif

if (degree() == 0)
{
@@ -156,7 +149,6 @@ struct polynomial
return array<T> { -k };
}
}
#ifdef ENABLE_3SOLVE
else if (degree() == 3)
{
/* p(x) = ax³ + bx² + cx + d */
@@ -226,21 +218,15 @@ struct polynomial
pow(v3_norm, 1.f / 3.f) * cos(v_angle);
}

if (delta < 0)
if (delta < 0) // 3 real solutions
return array<T> {solutions[0] - k, solutions[1] - k, solutions[2] - k};
else
{
if (u3_norm > 0)
{
return array<T> {solutions[0] - k, solutions[1] - k};
}
else
{
return array<T> {solutions[0] - k};
}
}
else if (delta > 0) // 1 real solution
return array<T> {solutions[0] - k};
else if (u3_norm > 0) // 2 real solutions
return array<T> {solutions[0] - k, solutions[1] - k};
else // one triple solution
return array<T> {solutions[0] - k};
}
#endif

/* It is an error to reach this point. */
ASSERT(false);


+ 9
- 3
src/t/math/polynomial.cpp View File

@@ -272,13 +272,13 @@ lolunit_declare_fixture(PolynomialTest)
lolunit_assert_equal(roots2[1], 7.f);
}

#ifdef ENABLE_3SOLVE
lolunit_declare_test(RootsDegree3TripleSolution)
{
polynomial<float> p { 1.f, 3.f, 3.f, 1.f };
auto roots1 = p.roots();

lolunit_assert_equal(roots1.count(), 3);
lolunit_assert_equal(roots1.count(), 1);
lolunit_assert_doubles_equal(roots1[0], -1, 0);
}

lolunit_declare_test(RootsDegree3DoubleSolution)
@@ -286,7 +286,11 @@ lolunit_declare_fixture(PolynomialTest)
polynomial<float> p { 2.f, 5.f, 4.f, 1.f };
auto roots1 = p.roots();

// Should have 2 solutions only, but precision leads to 3 solutions
lolunit_assert_equal(roots1.count(), 3);
lolunit_assert_doubles_equal(roots1[0], -1, 1e-3);
lolunit_assert_doubles_equal(roots1[1], -2, 1e-6);
lolunit_assert_doubles_equal(roots1[2], -1, 1e-3);
}

lolunit_declare_test(RootsDegree3SingleSolutions)
@@ -295,8 +299,10 @@ lolunit_declare_fixture(PolynomialTest)
auto roots1 = p.roots();

lolunit_assert_equal(roots1.count(), 3);
lolunit_assert_doubles_equal(roots1[0], -1, 1e-8);
lolunit_assert_doubles_equal(roots1[1], -3, 1e-8);
lolunit_assert_doubles_equal(roots1[2], -2, 1e-8);
}
#endif

lolunit_declare_test(Chebyshev)
{


Loading…
Cancel
Save