diff --git a/src/core/include/mp-units/framework/quantity_cast.h b/src/core/include/mp-units/framework/quantity_cast.h index 64d0154b..53b14815 100644 --- a/src/core/include/mp-units/framework/quantity_cast.h +++ b/src/core/include/mp-units/framework/quantity_cast.h @@ -53,10 +53,11 @@ namespace mp_units { * @tparam ToQS a quantity specification to use for a target quantity */ template - requires Quantity> && (castable(Q::quantity_spec, ToQS)) + requires Quantity> && (castable(std::remove_reference_t::quantity_spec, ToQS)) [[nodiscard]] constexpr Quantity auto quantity_cast(Q&& q) { - return quantity{std::forward(q).numerical_value_is_an_implementation_detail_, make_reference(ToQS, Q::unit)}; + return quantity{std::forward(q).numerical_value_is_an_implementation_detail_, + make_reference(ToQS, std::remove_reference_t::unit)}; } /** @@ -77,11 +78,11 @@ template * @tparam ToQS a quantity specification to use for a target quantity point */ template - requires QuantityPoint> && (castable(QP::quantity_spec, ToQS)) + requires QuantityPoint> && (castable(std::remove_reference_t::quantity_spec, ToQS)) [[nodiscard]] constexpr QuantityPoint auto quantity_cast(QP&& qp) { return QP{quantity_cast(std::forward(qp).quantity_from_origin_is_an_implementation_detail_), - qp.point_origin}; + std::remove_reference_t::point_origin}; } } // namespace mp_units diff --git a/src/core/include/mp-units/framework/value_cast.h b/src/core/include/mp-units/framework/value_cast.h index eaedbd17..1f92bcea 100644 --- a/src/core/include/mp-units/framework/value_cast.h +++ b/src/core/include/mp-units/framework/value_cast.h @@ -107,7 +107,7 @@ template [[nodiscard]] constexpr QuantityPoint auto value_cast(QP&& qp) { return quantity_point{value_cast(std::forward(qp).quantity_from_origin_is_an_implementation_detail_), - qp.point_origin}; + std::remove_reference_t::point_origin}; } /** @@ -124,10 +124,12 @@ template requires QuantityPoint> && RepresentationOf::quantity_spec.character> && std::constructible_from::rep> -[[nodiscard]] constexpr quantity_point::reference, QP::point_origin, ToRep> value_cast( - QP&& qp) +[[nodiscard]] constexpr quantity_point::reference, + std::remove_reference_t::point_origin, ToRep> +value_cast(QP&& qp) { - return {value_cast(std::forward(qp).quantity_from_origin_is_an_implementation_detail_), qp.point_origin}; + return {value_cast(std::forward(qp).quantity_from_origin_is_an_implementation_detail_), + std::remove_reference_t::point_origin}; } /** @@ -147,7 +149,7 @@ template [[nodiscard]] constexpr QuantityPoint auto value_cast(QP&& qp) { return quantity_point{value_cast(std::forward(qp).quantity_from_origin_is_an_implementation_detail_), - qp.point_origin}; + std::remove_reference_t::point_origin}; } } // namespace mp_units diff --git a/src/core/include/mp-units/math.h b/src/core/include/mp-units/math.h index 90a6539a..e6957201 100644 --- a/src/core/include/mp-units/math.h +++ b/src/core/include/mp-units/math.h @@ -25,6 +25,7 @@ #include #include #include +#include #include #include @@ -130,10 +131,10 @@ template } /** - * @brief Determines if a number is finite. + * @brief Determines if a quantity is finite. * - * @param a: Number to analyze. - * @return bool: Whether the number is finite or not. + * @param a: Quantity to analyze. + * @return bool: Whether the quantity is finite or not. */ template requires requires(Rep v) { isfinite(v); } || requires(Rep v) { std::isfinite(v); } @@ -144,10 +145,23 @@ template } /** - * @brief Determines if a number is infinite. + * @brief Determines if a quantity point is finite. * - * @param a: Number to analyze. - * @return bool: Whether the number is infinite or not. + * @param a: Quantity point to analyze. + * @return bool: Whether the quantity point is finite or not. + */ +template + requires requires(quantity q) { isfinite(q); } +[[nodiscard]] constexpr bool isfinite(const quantity_point& a) noexcept +{ + return isfinite(a.quantity_ref_from(a.point_origin)); +} + +/** + * @brief Determines if a quantity is infinite. + * + * @param a: Quantity to analyze. + * @return bool: Whether the quantity is infinite or not. */ template requires requires(Rep v) { isinf(v); } || requires(Rep v) { std::isinf(v); } @@ -157,12 +171,25 @@ template return isinf(a.numerical_value_ref_in(a.unit)); } +/** + * @brief Determines if a quantity point is infinite. + * + * @param a: Quantity point to analyze. + * @return bool: Whether the quantity point is infinite or not. + */ +template + requires requires(quantity q) { isinf(q); } +[[nodiscard]] constexpr bool isinf(const quantity_point& a) noexcept +{ + return isinf(a.quantity_ref_from(a.point_origin)); +} + /** - * @brief Determines if a number is a nan. + * @brief Determines if a quantity is a nan. * - * @param a: Number to analyze. - * @return bool: Whether the number is a NaN or not. + * @param a: Quantity to analyze. + * @return bool: Whether the quantity is a NaN or not. */ template requires requires(Rep v) { isnan(v); } || requires(Rep v) { std::isnan(v); } @@ -172,6 +199,20 @@ template return isnan(a.numerical_value_ref_in(a.unit)); } + +/** + * @brief Determines if a quantity point is a nan. + * + * @param a: Quantity point to analyze. + * @return bool: Whether the quantity point is a NaN or not. + */ +template + requires requires(quantity q) { isnan(q); } +[[nodiscard]] constexpr bool isnan(const quantity_point& a) noexcept +{ + return isnan(a.quantity_ref_from(a.point_origin)); +} + /** * @brief Computes the fma of 3 quantities * diff --git a/src/systems/include/mp-units/systems/si/unit_symbols.h b/src/systems/include/mp-units/systems/si/unit_symbols.h index 8477bbb2..060bfb93 100644 --- a/src/systems/include/mp-units/systems/si/unit_symbols.h +++ b/src/systems/include/mp-units/systems/si/unit_symbols.h @@ -474,6 +474,32 @@ inline constexpr auto YF = yotta; inline constexpr auto RF = ronna; inline constexpr auto QF = quetta; +inline constexpr auto qohm = quecto; +inline constexpr auto rohm = ronto; +inline constexpr auto yohm = yocto; +inline constexpr auto zohm = zepto; +inline constexpr auto aohm = atto; +inline constexpr auto fohm = femto; +inline constexpr auto pohm = pico; +inline constexpr auto nohm = nano; +inline constexpr auto uohm = micro; +inline constexpr auto mohm = milli; +inline constexpr auto cohm = centi; +inline constexpr auto dohm = deci; +using si::ohm; +inline constexpr auto daohm = deca; +inline constexpr auto hohm = hecto; +inline constexpr auto kohm = kilo; +inline constexpr auto Mohm = mega; +inline constexpr auto Gohm = giga; +inline constexpr auto Tohm = tera; +inline constexpr auto Pohm = peta; +inline constexpr auto Eohm = exa; +inline constexpr auto Zohm = zetta; +inline constexpr auto Yohm = yotta; +inline constexpr auto Rohm = ronna; +inline constexpr auto Qohm = quetta; + inline constexpr auto qS = quecto; inline constexpr auto rS = ronto; inline constexpr auto yS = yocto; diff --git a/test/static/quantity_point_test.cpp b/test/static/quantity_point_test.cpp index 27016618..acc53416 100644 --- a/test/static/quantity_point_test.cpp +++ b/test/static/quantity_point_test.cpp @@ -1677,4 +1677,19 @@ static_assert(invalid_addition(5 * isq::activity[Bq], 10 / (2 * isq::time[s]), q static_assert(invalid_subtraction(quantity_point{5 * isq::activity[Bq]}, 10 / (2 * isq::time[s]), 5 * isq::frequency[Hz])); +// value_cast + +static_assert(value_cast(quantity_point{2 * km}).quantity_from_zero().numerical_value_in(m) == 2000); +static_assert(value_cast(quantity_point{2000 * m}).quantity_from_zero().numerical_value_in(km) == 2); +static_assert(value_cast(quantity_point{1.23 * m}).quantity_from_zero().numerical_value_in(m) == 1); +static_assert( + value_cast(quantity_point{2000.0 * m / (3600.0 * s)}).quantity_from_zero().numerical_value_in(km / h) == 2); +// lvalue references in value_cast +namespace lvalue_tests { +constexpr quantity_point lvalue_qp{2 * km}; +static_assert(value_cast(lvalue_qp).quantity_from_zero().numerical_value_in(m) == 2000); +static_assert(value_cast(lvalue_qp).quantity_from_zero().numerical_value_in(km) == 2.f); +static_assert(value_cast(lvalue_qp).quantity_from_zero().numerical_value_in(m) == 2000.f); +} // namespace lvalue_tests + } // namespace diff --git a/test/static/quantity_test.cpp b/test/static/quantity_test.cpp index 4931ce74..69b653f7 100644 --- a/test/static/quantity_test.cpp +++ b/test/static/quantity_test.cpp @@ -937,7 +937,11 @@ static_assert(is_of_type(1 * m), quantity(isq::length(1 * m)), quantity>); static_assert(is_of_type>(isq::length(1 * m)), quantity>); static_assert(is_of_type>(isq::distance(1 * m)), quantity>); - +// lvalue references in quantity_cast +namespace lvalue_tests { +constexpr quantity lvalue_q = 1 * m; +static_assert(is_of_type(lvalue_q), quantity>); +} // namespace lvalue_tests // QuantityOf static_assert(QuantityOf, isq::length>);