@@ -44,7 +44,7 @@ liblolcore_headers = \ | |||
lol/math/functions.h lol/math/vector.h lol/math/half.h lol/math/real.h \ | |||
lol/math/geometry.h lol/math/interp.h lol/math/rand.h lol/math/array2d.h \ | |||
lol/math/array3d.h lol/math/constants.h lol/math/matrix.h lol/math/ops.h \ | |||
lol/math/transform.h \ | |||
lol/math/transform.h lol/math/polynomial.h lol/math/simplex_interpolator.h \ | |||
\ | |||
lol/algorithm/all.h \ | |||
lol/algorithm/sort.h lol/algorithm/portal.h lol/algorithm/aabb_tree.h \ | |||
@@ -22,3 +22,5 @@ | |||
#include <lol/math/geometry.h> | |||
#include <lol/math/interp.h> | |||
#include <lol/math/rand.h> | |||
#include <lol/math/polynomial.h> | |||
#include <lol/math/simplex_interpolator.h> |
@@ -0,0 +1,151 @@ | |||
// | |||
// Lol Engine | |||
// | |||
// Copyright: (c) 2010-2014 Sam Hocevar <sam@hocevar.net> | |||
// This program is free software; you can redistribute it and/or | |||
// modify it under the terms of the Do What The Fuck You Want To | |||
// Public License, Version 2, as published by Sam Hocevar. See | |||
// http://www.wtfpl.net/ for more details. | |||
// | |||
#pragma once | |||
// | |||
// The polynomial class | |||
// -------------------- | |||
// | |||
namespace lol | |||
{ | |||
template<typename T> | |||
struct polynomial | |||
{ | |||
inline polynomial() | |||
{ | |||
} | |||
explicit polynomial(std::initializer_list<T> const &init) | |||
{ | |||
for (auto a : init) | |||
factors.Push(a); | |||
reduce_degree(); | |||
} | |||
/* We define the zero polynomial (with no coefficients) as having | |||
* degree -1 on purpose. */ | |||
inline int degree() const | |||
{ | |||
return (int)factors.Count() - 1; | |||
} | |||
T eval(T x) const | |||
{ | |||
T ret = this->operator[](degree()); | |||
for (int i = degree() - 1; i >= 0; --i) | |||
ret = ret * x + factors[i]; | |||
return ret; | |||
} | |||
inline T operator[](ptrdiff_t n) const | |||
{ | |||
if (n < 0 || n > degree()) | |||
return T(0); | |||
return factors[n]; | |||
} | |||
polynomial<T> operator +() const | |||
{ | |||
return *this; | |||
} | |||
polynomial<T> operator -() const | |||
{ | |||
polynomial<T> ret; | |||
for (auto a : factors) | |||
ret.factors.Push(-a); | |||
return ret; | |||
} | |||
polynomial<T> &operator +=(polynomial<T> const &p) | |||
{ | |||
int min_degree = lol::min(p.degree(), degree()); | |||
for (int i = 0; i <= min_degree; ++i) | |||
factors[i] += p[i]; | |||
for (int i = min_degree + 1; i <= p.degree(); ++i) | |||
factors.Push(p[i]); | |||
reduce_degree(); | |||
return *this; | |||
} | |||
polynomial<T> operator +(polynomial<T> const &p) const | |||
{ | |||
return polynomial<T>(*this) += p; | |||
} | |||
polynomial<T> &operator -=(polynomial<T> const &p) | |||
{ | |||
return *this += -p; | |||
} | |||
polynomial<T> operator -(polynomial<T> const &p) const | |||
{ | |||
return polynomial<T>(*this) += -p; | |||
} | |||
polynomial<T> &operator *=(T const &k) | |||
{ | |||
for (auto &a : factors) | |||
a *= k; | |||
reduce_degree(); | |||
return *this; | |||
} | |||
polynomial<T> operator *(T const &k) const | |||
{ | |||
return polynomial<T>(*this) *= k; | |||
} | |||
polynomial<T> &operator *=(polynomial<T> const &p) | |||
{ | |||
return *this = *this * p; | |||
} | |||
polynomial<T> operator *(polynomial<T> const &p) const | |||
{ | |||
polynomial<T> ret; | |||
polynomial<T> const &q = *this; | |||
if (p.degree() >= 0 && q.degree() >= 0) | |||
{ | |||
int n = p.degree() + q.degree(); | |||
for (int i = 0; i <= n; ++i) | |||
ret.factors.Push(T(0)); | |||
for (int i = 0; i <= p.degree(); ++i) | |||
for (int j = 0; j <= q.degree(); ++j) | |||
ret.factors[i + j] += p[i] * q[j]; | |||
ret.reduce_degree(); | |||
} | |||
return ret; | |||
} | |||
private: | |||
void reduce_degree() | |||
{ | |||
while (factors.Count() && factors.Last() == T(0)) | |||
factors.Pop(); | |||
} | |||
array<T> factors; | |||
}; | |||
} /* namespace lol */ | |||
@@ -333,9 +333,11 @@ | |||
<ClInclude Include="lol\math\interp.h" /> | |||
<ClInclude Include="lol\math\matrix.h" /> | |||
<ClInclude Include="lol\math\ops.h" /> | |||
<ClInclude Include="lol\math\polynomial.h" /> | |||
<ClInclude Include="lol\math\rand.h" /> | |||
<ClInclude Include="lol\math\real.h" /> | |||
<ClInclude Include="lol\math\remez.h" /> | |||
<ClInclude Include="lol\math\simplex_interpolator.h" /> | |||
<ClInclude Include="lol\math\transform.h" /> | |||
<ClInclude Include="lol\math\vector.h" /> | |||
<ClInclude Include="lol\public.h" /> | |||
@@ -453,6 +453,9 @@ | |||
<ClInclude Include="lol\math\ops.h"> | |||
<Filter>lol\math</Filter> | |||
</ClInclude> | |||
<ClInclude Include="lol\math\polynomial.h"> | |||
<Filter>lol\math</Filter> | |||
</ClInclude> | |||
<ClInclude Include="lol\math\rand.h"> | |||
<Filter>lol\math</Filter> | |||
</ClInclude> | |||
@@ -462,6 +465,9 @@ | |||
<ClInclude Include="lol\math\remez.h"> | |||
<Filter>lol\math</Filter> | |||
</ClInclude> | |||
<ClInclude Include="lol\math\simplex_interpolator.h"> | |||
<Filter>lol\math</Filter> | |||
</ClInclude> | |||
<ClInclude Include="lol\math\transform.h"> | |||
<Filter>lol\math</Filter> | |||
</ClInclude> | |||
@@ -20,7 +20,8 @@ test_math_SOURCES = test-common.cpp \ | |||
math/array2d.cpp math/array3d.cpp math/arraynd.cpp math/box.cpp \ | |||
math/cmplx.cpp math/half.cpp math/interp.cpp math/matrix.cpp \ | |||
math/quat.cpp math/rand.cpp math/real.cpp math/rotation.cpp \ | |||
math/trig.cpp math/vector.cpp math/simplex_interpolator.cpp | |||
math/trig.cpp math/vector.cpp math/simplex_interpolator.cpp \ | |||
math/polynomial.cpp | |||
test_math_CPPFLAGS = $(AM_CPPFLAGS) -I$(top_srcdir)/tools/lolunit | |||
test_math_DEPENDENCIES = @LOL_DEPS@ | |||
@@ -0,0 +1,165 @@ | |||
// | |||
// Lol Engine | |||
// | |||
// Copyright: (c) 2010-2014 Sam Hocevar <sam@hocevar.net> | |||
// This program is free software; you can redistribute it and/or | |||
// modify it under the terms of the Do What The Fuck You Want To | |||
// Public License, Version 2, as published by Sam Hocevar. See | |||
// http://www.wtfpl.net/ for more details. | |||
// | |||
#include <lol/engine-internal.h> | |||
#include <lolunit.h> | |||
namespace lol | |||
{ | |||
lolunit_declare_fixture(PolynomialTest) | |||
{ | |||
lolunit_declare_test(Declaration) | |||
{ | |||
polynomial<float> p; | |||
polynomial<real> q; | |||
} | |||
lolunit_declare_test(Init) | |||
{ | |||
polynomial<float> p { }; | |||
lolunit_assert_equal(p[0], 0.f); | |||
lolunit_assert_equal(p[1], 0.f); | |||
lolunit_assert_equal(p[2], 0.f); | |||
lolunit_assert_equal(p.degree(), -1); | |||
polynomial<float> q { 1.f }; | |||
lolunit_assert_equal(q[0], 1.f); | |||
lolunit_assert_equal(q[1], 0.f); | |||
lolunit_assert_equal(q[2], 0.f); | |||
lolunit_assert_equal(q.degree(), 0); | |||
polynomial<float> r { 1.f, 2.f }; | |||
lolunit_assert_equal(r[0], 1.f); | |||
lolunit_assert_equal(r[1], 2.f); | |||
lolunit_assert_equal(r[2], 0.f); | |||
lolunit_assert_equal(r.degree(), 1); | |||
polynomial<float> s { 0.f }; | |||
lolunit_assert_equal(s[0], 0.f); | |||
lolunit_assert_equal(s[1], 0.f); | |||
lolunit_assert_equal(s[2], 0.f); | |||
lolunit_assert_equal(s.degree(), -1); | |||
} | |||
lolunit_declare_test(Eval) | |||
{ | |||
/* Special null polynomial */ | |||
polynomial<float> p; | |||
float a = p.eval(42.f); | |||
lolunit_assert_equal(a, 0.f); | |||
} | |||
lolunit_declare_test(Eval0) | |||
{ | |||
/* Constant polynomial p(x) = 1 */ | |||
polynomial<float> p { 1.f }; | |||
float a = p.eval(42.f); | |||
lolunit_assert_equal(a, 1.f); | |||
} | |||
lolunit_declare_test(Eval1) | |||
{ | |||
/* p(x) = 1 + 2x */ | |||
polynomial<float> p { 1.f, 2.f }; | |||
float a = p.eval(0.f); | |||
lolunit_assert_equal(a, 1.f); | |||
float b = p.eval(1.f); | |||
lolunit_assert_equal(b, 3.f); | |||
float c = p.eval(2.f); | |||
lolunit_assert_equal(c, 5.f); | |||
} | |||
lolunit_declare_test(Eval2) | |||
{ | |||
/* p(x) = 1 + 2x + 3x² */ | |||
polynomial<float> p { 1.f, 2.f, 3.f }; | |||
float a = p.eval(0.f); | |||
lolunit_assert_equal(a, 1.f); | |||
float b = p.eval(1.f); | |||
lolunit_assert_equal(b, 6.f); | |||
float c = p.eval(2.f); | |||
lolunit_assert_equal(c, 17.f); | |||
} | |||
lolunit_declare_test(UnaryPlusMinus) | |||
{ | |||
/* p(x) = 1 + 2x + 3x² */ | |||
polynomial<float> p { 1.f, 2.f, 3.f }; | |||
polynomial<float> q = +p; | |||
polynomial<float> r = -p; | |||
lolunit_assert_equal(q[0], 1.f); | |||
lolunit_assert_equal(q[1], 2.f); | |||
lolunit_assert_equal(q[2], 3.f); | |||
lolunit_assert_equal(r[0], -1.f); | |||
lolunit_assert_equal(r[1], -2.f); | |||
lolunit_assert_equal(r[2], -3.f); | |||
} | |||
lolunit_declare_test(Addition) | |||
{ | |||
/* p(x) = 1 + 2x + 3x² */ | |||
/* q(x) = 4 + 5x */ | |||
polynomial<float> p { 1.f, 2.f, 3.f }; | |||
polynomial<float> q { 4.f, 5.f }; | |||
/* r(x) = 5 + 7x + 3x² */ | |||
polynomial<float> r = p + q; | |||
lolunit_assert_equal(r.degree(), 2); | |||
lolunit_assert_equal(r[0], 5.f); | |||
lolunit_assert_equal(r[1], 7.f); | |||
lolunit_assert_equal(r[2], 3.f); | |||
} | |||
lolunit_declare_test(Subtraction) | |||
{ | |||
/* p(x) = 1 + 2x + 3x² */ | |||
/* q(x) = 4 + 5x */ | |||
polynomial<float> p { 1.f, 2.f, 3.f }; | |||
polynomial<float> q { 4.f, 5.f }; | |||
/* r(x) = -3 + -3x + 3x² */ | |||
polynomial<float> r = p - q; | |||
lolunit_assert_equal(r.degree(), 2); | |||
lolunit_assert_equal(r[0], -3.f); | |||
lolunit_assert_equal(r[1], -3.f); | |||
lolunit_assert_equal(r[2], 3.f); | |||
} | |||
lolunit_declare_test(Multiplication) | |||
{ | |||
/* p(x) = 1 + 2x + 3x² */ | |||
/* q(x) = 4 + 5x */ | |||
polynomial<float> p { 1.f, 2.f, 3.f }; | |||
polynomial<float> q { 4.f, 5.f }; | |||
/* r(x) = 4 + 13x + 22x² + 15x³ */ | |||
polynomial<float> r = p * q; | |||
lolunit_assert_equal(r.degree(), 3); | |||
lolunit_assert_equal(r[0], 4.f); | |||
lolunit_assert_equal(r[1], 13.f); | |||
lolunit_assert_equal(r[2], 22.f); | |||
lolunit_assert_equal(r[3], 15.f); | |||
} | |||
}; | |||
} /* namespace lol */ | |||
@@ -52,10 +52,12 @@ | |||
<ClCompile Include="math\half.cpp" /> | |||
<ClCompile Include="math\interp.cpp" /> | |||
<ClCompile Include="math\matrix.cpp" /> | |||
<ClCompile Include="math\polynomial.cpp" /> | |||
<ClCompile Include="math\quat.cpp" /> | |||
<ClCompile Include="math\rand.cpp" /> | |||
<ClCompile Include="math\real.cpp" /> | |||
<ClCompile Include="math\rotation.cpp" /> | |||
<ClCompile Include="math\simplex_interpolation.cpp" /> | |||
<ClCompile Include="math\trig.cpp" /> | |||
<ClCompile Include="math\vector.cpp" /> | |||
</ItemGroup> | |||