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 {