Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add methods for computing Chebyshev polynomials #528

Merged
merged 5 commits into from
Apr 23, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
60 changes: 60 additions & 0 deletions modules/dsp/chowdsp_math/Math/chowdsp_ChebyshevPolynomials.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
#pragma once

namespace chowdsp
{
#ifndef DOXYGEN
namespace cheby_detail
{
template <typename T, size_t max_order = 32>
constexpr auto cheby0()
{
Polynomial<T, max_order, poly_order_ascending> poly {};
poly.coeffs[0] = static_cast<T> (1);
return poly;
}

template <typename T, size_t max_order = 32>
constexpr auto cheby1()
{
Polynomial<T, max_order, poly_order_ascending> poly {};
poly.coeffs[1] = static_cast<T> (1);
return poly;
}
} // namespace cheby_detail
#endif

/** Recursively computes a Chebyshev polynomial given two previous Chebyshev polynomials */
template <typename T, size_t max_order = 32>
constexpr auto chebyshev_polynomial_recurse (const Polynomial<T, max_order, poly_order_ascending>& cheby_n1,
const Polynomial<T, max_order, poly_order_ascending>& cheby_n2)
{
Polynomial<T, max_order, poly_order_ascending> cheby_n {};
cheby_n.coeffs[0] = -cheby_n2.coeffs[0];
for (size_t i = 1; i < max_order; ++i)
cheby_n.coeffs[i] = (T) 2 * cheby_n1.coeffs[i - 1] - cheby_n2.coeffs[i];
return cheby_n;
}

/** Computes a Chebyshev polynomial of a given order. */
template <typename T, size_t order, size_t max_order = 32>
constexpr auto chebyshev_polynomial()
{
if constexpr (order == 0)
return cheby_detail::cheby0<T, 32>();

if constexpr (order == 1)
return cheby_detail::cheby1<T, 32>();

auto cheby_n2 = cheby_detail::cheby0<T, 32>();
auto cheby_n1 = cheby_detail::cheby1<T, 32>();
auto cheby_n = Polynomial<T, max_order, poly_order_ascending> {};
for (size_t i = 2; i <= order; ++i)
{
cheby_n = chebyshev_polynomial_recurse<T, max_order> (cheby_n1, cheby_n2);
cheby_n2 = cheby_n1;
cheby_n1 = cheby_n;
}

return cheby_n;
}
} // namespace chowdsp
1 change: 1 addition & 0 deletions modules/dsp/chowdsp_math/chowdsp_math.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ JUCE_END_IGNORE_WARNINGS_GCC_LIKE
#include "Math/chowdsp_OtherMathOps.h"
#include "Math/chowdsp_MatrixOps.h"
#include "Math/chowdsp_Polynomials.h"
#include "Math/chowdsp_ChebyshevPolynomials.h"
#include "Math/chowdsp_Power.h"
#include "Math/chowdsp_RandomFloat.h"
#include "Math/chowdsp_JacobiElliptic.h"
Expand Down
1 change: 1 addition & 0 deletions tests/dsp_tests/chowdsp_math_test/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ target_sources(chowdsp_math_test
FloatVectorOperationsTest.cpp
MatrixOpsTest.cpp
PolynomialsTest.cpp
ChebyshevPolynomialTest.cpp
PowerTest.cpp
OtherMathOpsTest.cpp
JacobiEllipticTest.cpp
Expand Down
23 changes: 23 additions & 0 deletions tests/dsp_tests/chowdsp_math_test/ChebyshevPolynomialTest.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
#include <CatchUtils.h>
#include <chowdsp_math/chowdsp_math.h>

static void check_poly (const chowdsp::Polynomial<float, 32, chowdsp::poly_order_ascending>& cheby_poly,
std::vector<float>&& actual)
{
size_t i = 0;
for (; i < actual.size(); ++i)
REQUIRE (cheby_poly.coeffs[i] == Catch::Approx { actual[i] }.margin (1.0e-6));
for (; i < cheby_poly.coeffs.size(); ++i)
REQUIRE (cheby_poly.coeffs[i] == Catch::Approx { 0.0f }.margin (1.0e-6));
}

TEST_CASE ("Chebyshev Polynomials Test", "[dsp][math]")
{
check_poly (chowdsp::chebyshev_polynomial<float, 2>(), { -1.0f, 0.0f, 2.0f });
check_poly (chowdsp::chebyshev_polynomial<float, 3>(), { 0.0f, -3.0f, 0.0f, 4.0f });
check_poly (chowdsp::chebyshev_polynomial<float, 4>(), { 1.0f, 0.0f, -8.0f, 0.0f, 8.0f });
check_poly (chowdsp::chebyshev_polynomial<float, 5>(), { 0.0f, 5.0f, 0.0f, -20.0f, 0.0f, 16.0f });
check_poly (chowdsp::chebyshev_polynomial<float, 6>(), { -1.0f, 0.0f, 18.0f, 0.0f, -48.0f, 0.0f, 32.0f });
check_poly (chowdsp::chebyshev_polynomial<float, 7>(), { 0.0f, -7.0f, 0.0f, 56.0f, 0.0f, -112.0f, 0.0f, 64.0f });
check_poly (chowdsp::chebyshev_polynomial<float, 8>(), { 1.0f, 0.0f, -32.0f, 0.0f, 160.0f, 0.0f, -256.0f, 0.0f, 128.0f });
}
Loading