@@ -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); | |||
@@ -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) | |||
{ | |||