diff --git a/src/utility/include/mp-units/math.h b/src/utility/include/mp-units/math.h index 67d7abb8..04b4b494 100644 --- a/src/utility/include/mp-units/math.h +++ b/src/utility/include/mp-units/math.h @@ -136,6 +136,53 @@ template return {static_cast(abs(q.numerical_value_ref_in(q.unit))), R}; } +/** + * @brief Determines if a number is finite. + * + * @param a: Number to analyze. + * @return bool: Whether the number is finite or not. + */ +template +[[nodiscard]] constexpr bool isfinite(const quantity& a) noexcept + requires( + requires { isfinite(a.numerical_value_ref_in(a.unit)); } || + requires { std::isfinite(a.numerical_value_ref_in(a.unit)); }) +{ + using std::isfinite; + return isfinite(a.numerical_value_ref_in(a.unit)); +} + +/** + * @brief Determines if a number is infinite. + * + * @param a: Number to analyze. + * @return bool: Whether the number is infinite or not. + */ +template +[[nodiscard]] constexpr bool isinf(const quantity& a) noexcept + requires( + requires { isinf(a.numerical_value_ref_in(a.unit)); } || requires { std::isinf(a.numerical_value_ref_in(a.unit)); }) +{ + using std::isinf; + return isinf(a.numerical_value_ref_in(a.unit)); +} + + +/** + * @brief Determines if a number is a nan. + * + * @param a: Number to analyze. + * @return bool: Whether the number is a NaN or not. + */ +template +[[nodiscard]] constexpr bool isnan(const quantity& a) noexcept + requires( + requires { isnan(a.numerical_value_ref_in(a.unit)); } || requires { std::isnan(a.numerical_value_ref_in(a.unit)); }) +{ + using std::isnan; + return isnan(a.numerical_value_ref_in(a.unit)); +} + /** * @brief Computes the fma of 3 quantities * diff --git a/test/unit_test/runtime/math_test.cpp b/test/unit_test/runtime/math_test.cpp index 714f71e3..5c803c73 100644 --- a/test/unit_test/runtime/math_test.cpp +++ b/test/unit_test/runtime/math_test.cpp @@ -72,6 +72,12 @@ TEST_CASE("'fma()' returns a common reference.", "[math][fma]") REQUIRE(fma(isq::speed(10.0 * m / s), isq::time(2.0 * s), isq::height(42.0 * m)) == isq::length(62.0 * m)); } +TEST_CASE("'isfinite()' accepts dimensioned arguments", "[math][isfinite]") { REQUIRE(isfinite(4.0 * isq::length[m])); } + +TEST_CASE("'isinf()' accepts dimensioned arguments", "[math][isinf]") { REQUIRE(!isinf(4.0 * isq::length[m])); } + +TEST_CASE("'isnan()' accepts dimensioned arguments", "[math][isnan]") { REQUIRE(!isnan(4.0 * isq::length[m])); } + TEST_CASE("'pow()' on quantity changes the value and the dimension accordingly", "[math][pow]") { diff --git a/test/unit_test/static/math_test.cpp b/test/unit_test/static/math_test.cpp index 4874aabb..84848c02 100644 --- a/test/unit_test/static/math_test.cpp +++ b/test/unit_test/static/math_test.cpp @@ -49,6 +49,16 @@ static_assert(compare(pow<1>(2 * m), 2 * m)); static_assert(compare(pow<2>(2 * m), 4 * pow<2>(m), 4 * m2)); static_assert(compare(pow<2>(2 * km), 4 * pow<2>(km), 4 * square(km))); static_assert(compare(pow<2>(2 * ft), 4 * pow<2>(ft), 4 * square(ft))); +static_assert(isfinite(2 * m)); +static_assert(isfinite(2.0 * one)); +static_assert(!isfinite(std::numeric_limits::quiet_NaN() * one)); +static_assert(!isfinite(std::numeric_limits::infinity() * km)); +static_assert(!isinf(2 * m)); +static_assert(!isinf(2.0 * one)); +static_assert(isinf(std::numeric_limits::infinity() * one)); +static_assert(!isnan(2 * m)); +static_assert(!isnan(std::numeric_limits::infinity() * one)); +static_assert(isnan(std::numeric_limits::quiet_NaN() * m)); static_assert(compare(sqrt(4 * m2), 2 * m)); static_assert(compare(sqrt(4 * square(km)), 2 * km)); static_assert(compare(sqrt(4 * square(ft)), 2 * ft));