-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
9529a69
commit 3f25bc3
Showing
5 changed files
with
97 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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)); | ||
} |