From 42503feb62b83e964494d4654f433924b171de84 Mon Sep 17 00:00:00 2001 From: Roland Conybeare Date: Fri, 3 May 2024 18:46:36 -0400 Subject: [PATCH] xo-unit: + qty::meter, qty::second --- include/xo/unit/quantity.hpp | 74 +++++++++++++++++++++++++++++++++++- 1 file changed, 72 insertions(+), 2 deletions(-) diff --git a/include/xo/unit/quantity.hpp b/include/xo/unit/quantity.hpp index 7f619edc..dded38d5 100644 --- a/include/xo/unit/quantity.hpp +++ b/include/xo/unit/quantity.hpp @@ -21,8 +21,7 @@ namespace xo { typename Repr = double, typename Int = std::int64_t, natural_unit NaturalUnit = natural_unit(), - typename Int2x = detail::width2x_t - > + typename Int2x = detail::width2x_t > class quantity { public: using repr_type = Repr; @@ -69,6 +68,30 @@ namespace xo { } } + template ScaledUnit2> + constexpr + auto rescale() const { + /* conversion factor from .unit -> unit2*/ + auto rr = detail::su_ratio(NaturalUnit, ScaledUnit2.natural_unit_); + + if (rr.natural_unit_.is_dimensionless()) { + /* NOTE: test for unit .outer_scale_sq values to get constexpr result with c++23 + * and integer dimension powers. + */ + repr_type r_scale = ((((rr.outer_scale_sq_ == 1.0) + && (ScaledUnit2.outer_scale_sq_ == 1.0)) + ? 1.0 + : ::sqrt(rr.outer_scale_sq_ / ScaledUnit2.outer_scale_sq_)) + * rr.outer_scale_factor_.template convert_to() + * this->scale_ + / ScaledUnit2.outer_scale_factor_.template convert_to()); + return quantity(r_scale); + } else { + return quantity(std::numeric_limits::quiet_NaN()); + } + } + template requires std::is_arithmetic_v constexpr auto scale_by(Dimensionless x) const { @@ -99,12 +122,44 @@ namespace xo { constexpr nu_abbrev_type abbrev() const { return s_unit.abbrev(); } + quantity & operator=(const quantity & x) { + this->scale_ = x.scale_; + return *this; + } + + template + requires(quantity_concept + && Q2::always_constexpr_unit) + quantity & operator=(const Q2 & x) { + auto x2 = x.template rescale(); + + this->scale_ = x2.scale(); + + return *this; + } + + template + requires(quantity_concept + && Q2::always_constexpr_unit) + constexpr operator Q2() const { + return this->template rescale(); + } + public: /* need public members so that a quantity instance can be a non-type template parameter (is a structural type) */ static constexpr natural_unit s_unit = NaturalUnit; Repr scale_ = Repr{}; }; + template NaturalUnit = natural_unit<::std::int64_t>()> + using stdquantity = xo::qty::quantity; + + template + constexpr auto + rescale(const Quantity & x, const scaled_unit & su) { + return x.template rescale(); + } + struct quantity_util { /* parallel implementation to Quantity multiply, * but return type will have dimension computed at compile-time @@ -168,6 +223,17 @@ namespace xo { } }; + template Unit = Q2::s_unit> + requires (quantity_concept + && quantity_concept + && Q1::always_constexpr_unit + && Q2::always_constexpr_unit) + constexpr auto + with_units(const Q1 & x, const Q2 & y) + { + return x.template rescale(); + } + /** note: won't have constexpr result w/ fractional dimension until c++26 (when ::sqrt(), ::pow() are constexpr) **/ template @@ -222,6 +288,8 @@ namespace xo { inline constexpr auto lightseconds(double x) { return quantity(x); } inline constexpr auto astronomicalunits(double x) { return quantity(x); } + static constexpr auto meter = meters(1); + // ----- time ----- inline constexpr auto picoseconds(double x) { return quantity(x); } @@ -240,6 +308,8 @@ namespace xo { inline constexpr auto year365s(double x) { return quantity(x); } //inline constexpr auto year366s(double x) { return quantity(x); } + static constexpr auto second = seconds(1); + // ----- volatility ----- /* volatility in units of 1/yr */