xo-unit: + quantity / quantity

This commit is contained in:
Roland Conybeare 2024-05-03 01:43:23 -04:00
commit b028588877
2 changed files with 97 additions and 2 deletions

View file

@ -106,7 +106,7 @@ namespace xo {
};
struct quantity_util {
/* parallel implementation to Quantity<Repr, Int>,
/* parallel implementation to Quantity<Repr, Int> multiply,
* but return type will have dimension computed at compile-time
*/
template <typename Q1, typename Q2>
@ -137,9 +137,38 @@ namespace xo {
r_int2x_type
>(r_scale);
}
template <typename Q1, typename Q2>
requires (quantity_concept<Q1>
&& quantity_concept<Q2>
&& Q1::always_constexpr_unit
&& Q2::always_constexpr_unit)
static constexpr auto divide(Q1 x, Q2 y) {
using r_repr_type = std::common_type_t<typename Q1::repr_type,
typename Q2::repr_type>;
using r_int_type = std::common_type_t<typename Q1::ratio_int_type,
typename Q2::ratio_int_type>;
using r_int2x_type = std::common_type_t<typename Q1::ratio_int2x_type,
typename Q2::ratio_int2x_type>;
constexpr auto rr = detail::su_ratio<r_int_type, r_int2x_type>(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<r_repr_type>()
* static_cast<r_repr_type>(x.scale())
/ static_cast<r_repr_type>(y.scale()));
return quantity<r_repr_type,
r_int_type,
rr.natural_unit_,
r_int2x_type
>(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 <typename Q1, typename Q2>
requires (quantity_concept<Q1>
@ -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 <typename Q1, typename Q2>
requires (quantity_concept<Q1>
&& quantity_concept<Q2>
&& 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 -----

View file

@ -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<decltype(ms)::ratio_int_type,
decltype(ms)::ratio_int2x_type>(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<decltype(ms)::repr_type>() == 1.0);
static_assert(rr.natural_unit_.n_bpu() == 0);
constexpr auto q1 = quantity<decltype(ms)::repr_type,
decltype(ms)::ratio_int_type,
rr.natural_unit_,
decltype(ms)::ratio_int2x_type>(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<decltype(ms)::ratio_int_type,
decltype(ms)::ratio_int_type>;
using r_int2x_type = std::common_type_t<decltype(ms)::ratio_int2x_type,
decltype(ms)::ratio_int2x_type>;
constexpr auto rr = detail::su_ratio<r_int_type, r_int2x_type>(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*/