xo-unit: restore constexpr quantity*quantity

This commit is contained in:
Roland Conybeare 2024-05-03 01:37:27 -04:00
commit be67f55c79
5 changed files with 66 additions and 35 deletions

View file

@ -78,28 +78,6 @@ namespace xo {
// divide_by
// divide_into
/* parallel implementation to Quantity<Repr, Int>,
* but return type will have dimension computed at compile-time
*/
template <typename Quantity2>
static constexpr auto multiply(const quantity & x, const Quantity2 & y) {
using r_repr_type = std::common_type_t<typename quantity::repr_type,
typename Quantity2::repr_type>;
using r_int_type = std::common_type_t<typename quantity::ratio_int_type,
typename Quantity2::ratio_int_type>;
using r_int2x_type = std::common_type_t<typename quantity::ratio_int2x_type,
typename Quantity2::ratio_int2x_type>;
constexpr auto rr = detail::su_product<r_int_type, r_int2x_type>(x.unit(), y.unit());
r_repr_type r_scale = (::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);
}
// divide
// add
// subtract
@ -127,6 +105,53 @@ namespace xo {
Repr scale_ = Repr{};
};
struct quantity_util {
/* parallel implementation to Quantity<Repr, Int>,
* but return type will have dimension computed at compile-time
*/
template <typename Q1, typename Q2>
requires (quantity_concept<Q1>
&& quantity_concept<Q2>
&& Q1::always_constexpr_unit
&& Q2::always_constexpr_unit)
static constexpr auto multiply(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_product<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)
**/
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::multiply(x, y);
}
namespace qty {
// ----- mass -----
@ -179,6 +204,8 @@ namespace xo {
inline constexpr auto volatility_250d(double x) { return quantity<double, std::int64_t, nu::volatility_250d>(x); }
inline constexpr auto volatility_360d(double x) { return quantity<double, std::int64_t, nu::volatility_360d>(x); }
}
/* reminder: see [quantity_ops.hpp] for operator* etc */
} /*namespace qty*/
} /*namespace xo*/