Skip to content

Commit

Permalink
Add power function
Browse files Browse the repository at this point in the history
  • Loading branch information
tobiashienzsch committed Feb 14, 2024
1 parent 9529a69 commit 3f25bc3
Show file tree
Hide file tree
Showing 5 changed files with 97 additions and 0 deletions.
1 change: 1 addition & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ if(NOT CMAKE_CROSSCOMPILING)
"lib/grit/fft/fft_test.cpp"
"lib/grit/math/ilog2_test.cpp"
"lib/grit/math/ipow_test.cpp"
"lib/grit/math/power_test.cpp"
"lib/grit/math/normalizable_range_test.cpp"
"lib/grit/math/static_lookup_table_test.cpp"
"lib/grit/unit/decibel_test.cpp"
Expand Down
2 changes: 2 additions & 0 deletions lib/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,9 @@ target_sources(gritwave-grit INTERFACE
"grit/math/ilog2.hpp"
"grit/math/ipow.hpp"
"grit/math/linear_interpolation.hpp"
"grit/math/normalizable_range.hpp"
"grit/math/remap.hpp"
"grit/math/power.hpp"
"grit/math/sign.hpp"
"grit/math/static_lookup_table.hpp"
"grit/math/static_lookup_table_transform.hpp"
Expand Down
1 change: 1 addition & 0 deletions lib/grit/math.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
#include <grit/math/ipow.hpp>
#include <grit/math/linear_interpolation.hpp>
#include <grit/math/normalizable_range.hpp>
#include <grit/math/power.hpp>
#include <grit/math/remap.hpp>
#include <grit/math/sign.hpp>
#include <grit/math/static_lookup_table.hpp>
Expand Down
44 changes: 44 additions & 0 deletions lib/grit/math/power.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
#pragma once

#include <etl/concepts.hpp>

namespace grit {

/// \ingroup grit-math
template<int Exponent, typename Numeric>
requires(Exponent >= 0)
[[nodiscard]] constexpr auto power(Numeric base) -> Numeric
{
// Unrolling is necessary when not compiling with `-ffast-math`.
// https://godbolt.org/z/bEnvWKdsq

if constexpr (Exponent == 0) {
return Numeric(1);
} else if constexpr (Exponent == 1) {
return base;
} else if constexpr (Exponent == 2) {
return base * base;
} else if constexpr (Exponent == 3) {
return base * power<2>(base);
} else if constexpr (Exponent == 4) {
auto const x2 = power<2>(base);
return x2 * x2;
} else if constexpr (Exponent == 5) {
return base * power<4>(base);
} else if constexpr (Exponent == 6) {
return power<2>(base) * power<4>(base);
} else if constexpr (Exponent == 7) {
auto const x2 = power<2>(base);
auto const x4 = x2 * x2;
return base * x2 * x4;
} else if constexpr (Exponent == 8) {
auto const x2 = power<2>(base);
auto const x3 = x2 * base;
auto const x6 = x3 * x3;
return x6 * x2;
} else {
return base * power<Exponent - 1>(base);
}
}

} // namespace grit
49 changes: 49 additions & 0 deletions lib/grit/math/power_test.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
#include "power.hpp"

#include <catch2/catch_template_test_macros.hpp>
#include <catch2/matchers/catch_matchers_floating_point.hpp>

TEMPLATE_TEST_CASE(
"grit/math: power",
"",
short,
int,
long,
long long,
unsigned short,
unsigned int,
unsigned long,
unsigned long long
)
{
using Int = TestType;

REQUIRE(grit::power<1>(Int(1)) == 1);
REQUIRE(grit::power<1>(Int(2)) == 2);
REQUIRE(grit::power<1>(Int(3)) == 3);

REQUIRE(grit::power<2>(Int(1)) == 1);
REQUIRE(grit::power<2>(Int(2)) == 4);
REQUIRE(grit::power<2>(Int(3)) == 9);

REQUIRE(grit::power<3>(Int(1)) == 1);
REQUIRE(grit::power<3>(Int(2)) == 8);
REQUIRE(grit::power<3>(Int(3)) == 27);
}

TEMPLATE_TEST_CASE("grit/math: power", "", float, double)
{
using Float = TestType;

REQUIRE_THAT(grit::power<1>(Float(1)), Catch::Matchers::WithinAbs(1, 1e-8));
REQUIRE_THAT(grit::power<1>(Float(2)), Catch::Matchers::WithinAbs(2, 1e-8));
REQUIRE_THAT(grit::power<1>(Float(3)), Catch::Matchers::WithinAbs(3, 1e-8));

REQUIRE_THAT(grit::power<2>(Float(1)), Catch::Matchers::WithinAbs(1, 1e-8));
REQUIRE_THAT(grit::power<2>(Float(2)), Catch::Matchers::WithinAbs(4, 1e-8));
REQUIRE_THAT(grit::power<2>(Float(3)), Catch::Matchers::WithinAbs(9, 1e-8));

REQUIRE_THAT(grit::power<3>(Float(1)), Catch::Matchers::WithinAbs(1, 1e-8));
REQUIRE_THAT(grit::power<3>(Float(2)), Catch::Matchers::WithinAbs(8, 1e-8));
REQUIRE_THAT(grit::power<3>(Float(3)), Catch::Matchers::WithinAbs(27, 1e-8));
}

0 comments on commit 3f25bc3

Please sign in to comment.