From b028588877207bad4e7248216d708017009d9741 Mon Sep 17 00:00:00 2001 From: Roland Conybeare Date: Fri, 3 May 2024 01:43:23 -0400 Subject: [PATCH] xo-unit: + quantity / quantity --- include/xo/unit/quantity.hpp | 46 +++++++++++++++++++++++++++++-- utest/quantity.test.cpp | 53 ++++++++++++++++++++++++++++++++++++ 2 files changed, 97 insertions(+), 2 deletions(-) diff --git a/include/xo/unit/quantity.hpp b/include/xo/unit/quantity.hpp index c19c2fe3..7f619edc 100644 --- a/include/xo/unit/quantity.hpp +++ b/include/xo/unit/quantity.hpp @@ -106,7 +106,7 @@ namespace xo { }; struct quantity_util { - /* parallel implementation to Quantity, + /* parallel implementation to Quantity multiply, * but return type will have dimension computed at compile-time */ template @@ -137,9 +137,38 @@ namespace xo { r_int2x_type >(r_scale); } + + template + requires (quantity_concept + && quantity_concept + && Q1::always_constexpr_unit + && Q2::always_constexpr_unit) + static constexpr auto divide(Q1 x, Q2 y) { + using r_repr_type = std::common_type_t; + using r_int_type = std::common_type_t; + using r_int2x_type = std::common_type_t; + + constexpr auto rr = detail::su_ratio(x.unit(), y.unit()); + + r_repr_type r_scale = (((rr.outer_scale_sq_ == 1.0) + ? 1.0 + : ::sqrt(rr.outer_scale_sq_)) + * rr.outer_scale_factor_.template convert_to() + * static_cast(x.scale()) + / static_cast(y.scale())); + + return quantity(r_scale); + } }; - /** note: won't have constexpr result until c++26 (when ::sqrt(), ::pow() are constexpr) + /** note: won't have constexpr result w/ fractional dimension until c++26 (when ::sqrt(), ::pow() are constexpr) **/ template requires (quantity_concept @@ -152,6 +181,19 @@ namespace xo { return quantity_util::multiply(x, y); } + /** note: won't have constexpr result w/ fractional dimension until c++26 (when ::sqrt(), ::pow() are constexpr) + **/ + template + requires (quantity_concept + && quantity_concept + && Q1::always_constexpr_unit + && Q2::always_constexpr_unit) + constexpr auto + operator/ (const Q1 & x, const Q2 & y) + { + return quantity_util::divide(x, y); + } + namespace qty { // ----- mass ----- diff --git a/utest/quantity.test.cpp b/utest/quantity.test.cpp index 4611ed8c..3496841d 100644 --- a/utest/quantity.test.cpp +++ b/utest/quantity.test.cpp @@ -422,6 +422,59 @@ namespace xo { static_assert(q3.unit()[0].power() == power_ratio_type(2,1)); } /*TEST_CASE(quantity.mult2)*/ + + TEST_CASE("quantity.div2", "[quantity.div]") { + constexpr auto ms = qty::milliseconds(1.0); + + /* proof that ms.s_unit is constexpr */ + static_assert(ms.s_unit.n_bpu() == 1); + + /* proof that ms.unit() is constexpr */ + static_assert(ms.unit().n_bpu() == 1); + + constexpr auto rr = detail::su_ratio(ms.unit(), ms.unit()); + + /* proof that detail::su_product<..>(..) return value is constexpr */ + static_assert(rr.outer_scale_sq_ == 1.0); + static_assert(rr.outer_scale_factor_.template convert_to() == 1.0); + static_assert(rr.natural_unit_.n_bpu() == 0); + + constexpr auto q1 = quantity(ms.scale() * ms.scale()); + + /* proof that q is constexpr */ + static_assert(q1.scale() == 1.0); + static_assert(q1.unit().n_bpu() == 0); + + { + using r_int_type = std::common_type_t; + using r_int2x_type = std::common_type_t; + + constexpr auto rr = detail::su_ratio(ms.unit(), ms.unit()); + + static_assert(rr.outer_scale_sq_ == 1.0); + } + + constexpr auto q2 = quantity_util::divide(ms, ms); + + /* proof that q2 is constexpr */ + static_assert(q2.scale() == 1.0); + static_assert(q2.unit().n_bpu() == 0); + static_assert(q2.unit()[0].power() == power_ratio_type(0,1)); + + constexpr auto q3 = ms / ms; + + /* proof that q3 is constexpr */ + static_assert(q3.scale() == 1.0); + static_assert(q3.unit().n_bpu() == 0); + static_assert(q3.unit()[0].power() == power_ratio_type(0,1)); + + } /*TEST_CASE(quantity.mult2)*/ } /*namespace qty*/ } /*namespace xo*/