From 409aaf463665f8f3945fef456e9dac2db2861732 Mon Sep 17 00:00:00 2001 From: Chip Hogg Date: Sat, 8 Jan 2022 19:34:21 -0500 Subject: [PATCH] Generalize inverse() to pow<...>() --- src/core/include/units/magnitude.h | 23 +++++++++++++---------- test/unit_test/runtime/magnitude_test.cpp | 17 +++++++++++++++++ 2 files changed, 30 insertions(+), 10 deletions(-) diff --git a/src/core/include/units/magnitude.h b/src/core/include/units/magnitude.h index f50ca775..c4964337 100644 --- a/src/core/include/units/magnitude.h +++ b/src/core/include/units/magnitude.h @@ -126,11 +126,11 @@ constexpr bool operator==(T t, U u) { } /** - * @brief The (multiplicative) inverse of a BasePower. + * @brief A BasePower, raised to a rational power E. */ -template -constexpr auto inverse(BP bp) { - bp.power = -bp.power; +template +constexpr auto pow(BasePower auto bp) { + bp.power = bp.power * E; return bp; } @@ -220,8 +220,8 @@ constexpr bool strictly_increasing(Ts&&... ts) { /** * @brief A representation for positive real numbers which optimizes taking products and rational powers. * - * Magnitudes can be treated as values. Each type encodes exactly one value. Users can multiply, divide, and compare - * for equality. + * Magnitudes can be treated as values. Each type encodes exactly one value. Users can multiply, divide, raise to + * rational powers, and compare for equality. */ template requires ((detail::is_valid_base_power(BPs) && ... && detail::strictly_increasing(BPs.get_base()...))) @@ -274,10 +274,13 @@ constexpr bool operator==(magnitude, magnitude) { } //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// Magnitude inverse implementation. +// Magnitude rational powers implementation. -template -constexpr auto inverse(magnitude) { return magnitude{}; } +template +constexpr auto pow(magnitude) { + if constexpr (E == 0) { return magnitude<>{}; } + else { return magnitude(BPs)...>{}; } +} //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Magnitude product implementation. @@ -322,7 +325,7 @@ constexpr auto operator*(magnitude, magnitude) { //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Magnitude quotient implementation. -constexpr auto operator/(Magnitude auto l, Magnitude auto r) { return l * inverse(r); } +constexpr auto operator/(Magnitude auto l, Magnitude auto r) { return l * pow<-1>(r); } //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // `as_magnitude()` implementation. diff --git a/test/unit_test/runtime/magnitude_test.cpp b/test/unit_test/runtime/magnitude_test.cpp index 0750a4b5..b32d2928 100644 --- a/test/unit_test/runtime/magnitude_test.cpp +++ b/test/unit_test/runtime/magnitude_test.cpp @@ -181,6 +181,23 @@ TEST_CASE("Division works for magnitudes") } } +TEST_CASE("Can raise Magnitudes to rational powers") +{ + SECTION("Anything to the 0 is 1") { + CHECK(pow<0>(as_magnitude<1>()) == as_magnitude<1>()); + CHECK(pow<0>(as_magnitude<123>()) == as_magnitude<1>()); + CHECK(pow<0>(as_magnitude()) == as_magnitude<1>()); + CHECK(pow<0>(pi_to_the()) == as_magnitude<1>()); + } + + SECTION("Anything to the 1 is itself") { + CHECK(pow<1>(as_magnitude<1>()) == as_magnitude<1>()); + CHECK(pow<1>(as_magnitude<123>()) == as_magnitude<123>()); + CHECK(pow<1>(as_magnitude()) == as_magnitude()); + CHECK(pow<1>(pi_to_the()) == pi_to_the()); + } +} + namespace detail {