Skip to content

Commit

Permalink
Floating point classification functions
Browse files Browse the repository at this point in the history
Add the ability for `isnan`, `isfinite`, and `isinf` to work on dimensioned quantities.
  • Loading branch information
NAThompson committed Dec 16, 2023
1 parent 462b418 commit 25b7c4d
Show file tree
Hide file tree
Showing 3 changed files with 63 additions and 0 deletions.
47 changes: 47 additions & 0 deletions src/utility/include/mp-units/math.h
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,53 @@ template<auto R, typename Rep>
return {static_cast<Rep>(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<auto R, typename Rep>
[[nodiscard]] constexpr bool isfinite(const quantity<R, Rep>& 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<auto R, typename Rep>
[[nodiscard]] constexpr bool isinf(const quantity<R, Rep>& 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<auto R, typename Rep>
[[nodiscard]] constexpr bool isnan(const quantity<R, Rep>& 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
*
Expand Down
6 changes: 6 additions & 0 deletions test/unit_test/runtime/math_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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<Num, Den>()' on quantity changes the value and the dimension accordingly", "[math][pow]")
{
Expand Down
10 changes: 10 additions & 0 deletions test/unit_test/static/math_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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<double>::quiet_NaN() * one));
static_assert(!isfinite(std::numeric_limits<double>::infinity() * km));
static_assert(!isinf(2 * m));
static_assert(!isinf(2.0 * one));
static_assert(isinf(std::numeric_limits<double>::infinity() * one));
static_assert(!isnan(2 * m));
static_assert(!isnan(std::numeric_limits<double>::infinity() * one));
static_assert(isnan(std::numeric_limits<double>::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));
Expand Down

0 comments on commit 25b7c4d

Please sign in to comment.