xo-unit: + Quantity division
This commit is contained in:
parent
6a3db2197e
commit
8548f26143
4 changed files with 353 additions and 25 deletions
|
|
@ -1,4 +1,4 @@
|
|||
/** @file Quantity2.hpp
|
||||
/** @file Quantity.hpp
|
||||
*
|
||||
* Author: Roland Conybeare
|
||||
**/
|
||||
|
|
@ -34,7 +34,7 @@ namespace xo {
|
|||
|
||||
public:
|
||||
constexpr Quantity(Repr scale,
|
||||
const natural_unit<Int> & unit)
|
||||
const natural_unit<Int> & unit)
|
||||
: scale_{scale}, unit_{unit} {}
|
||||
|
||||
constexpr const repr_type & scale() const { return scale_; }
|
||||
|
|
@ -63,6 +63,29 @@ namespace xo {
|
|||
rr.natural_unit_);
|
||||
}
|
||||
|
||||
template <typename Quantity2>
|
||||
static constexpr
|
||||
auto divide(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>;
|
||||
|
||||
auto rr = detail::nu_ratio(x.unit(), y.unit());
|
||||
|
||||
/* note: nu_ratio() reports multiplicative outer scaling factors,
|
||||
* so multiply is correct here
|
||||
*/
|
||||
r_repr_type r_scale = (::sqrt(rr.outer_scale_sq_)
|
||||
* rr.outer_scale_exact_.template 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>(r_scale,
|
||||
rr.natural_unit_);
|
||||
}
|
||||
|
||||
|
||||
private:
|
||||
/** @brief quantity represents this multiple of a unit amount **/
|
||||
Repr scale_ = Repr{};
|
||||
|
|
@ -89,8 +112,17 @@ namespace xo {
|
|||
{
|
||||
return Quantity::multiply(x, y);
|
||||
}
|
||||
|
||||
/** note: won't have constexpr result until c++26 (when ::sqrt(), ::pow() are constexpr)
|
||||
**/
|
||||
template <typename Quantity, typename OtherQuantity>
|
||||
constexpr auto
|
||||
operator/ (const Quantity & x, const OtherQuantity & y)
|
||||
{
|
||||
return Quantity::divide(x, y);
|
||||
}
|
||||
} /*namespace qty*/
|
||||
} /*namespace xo*/
|
||||
|
||||
|
||||
/** end Quantity2.hpp **/
|
||||
/** end Quantity.hpp **/
|
||||
|
|
|
|||
|
|
@ -16,10 +16,11 @@ namespace xo {
|
|||
/** @class natural_unit
|
||||
* @brief an array representing the cartesian product of distinct basis-power-units
|
||||
*
|
||||
* 1. Each bpu in the array represents a power of a basis dimension, e.g. "meter" or "second^2".
|
||||
* 2. Each bpu in an array has a different dimension id.
|
||||
* 1. Quantities are represented as a multiple of a natural unit
|
||||
* 2. Each bpu in the array represents a power of a basis dimension, e.g. "meter" or "second^2".
|
||||
* 3. Each bpu in an array has a different dimension id.
|
||||
* For example dim::time, if present, appears once.
|
||||
* 3. Basis dimensions can appear in any order.
|
||||
* 4. Basis dimensions can appear in any order.
|
||||
* Order used for constructing abbreviations: will get @c "kg.m" or @c "m.kg"
|
||||
* depending on the orderin of @c dim::distance and @c dim::mass in @c bpu_v_
|
||||
**/
|
||||
|
|
@ -46,6 +47,14 @@ namespace xo {
|
|||
return retval;
|
||||
}
|
||||
|
||||
/** @brief remove bpu at position @p p **/
|
||||
constexpr void remove_bpu(size_t p) {
|
||||
for (std::size_t i = p; i+1 < n_bpu_; ++i)
|
||||
bpu_v_[i] = bpu_v_[i+1];
|
||||
|
||||
--n_bpu_;
|
||||
}
|
||||
|
||||
constexpr void push_back(const bpu<Int> & bpu) {
|
||||
if (n_bpu_ < n_dim)
|
||||
bpu_v_[n_bpu_++] = bpu;
|
||||
|
|
@ -187,8 +196,8 @@ namespace xo {
|
|||
p_target_bpu->scalefactor());
|
||||
|
||||
*p_target_bpu = bpu<Int>(p_target_bpu->native_dim(),
|
||||
p_target_bpu->scalefactor(),
|
||||
p_target_bpu->power() + rhs_bpu_orig.power());
|
||||
p_target_bpu->scalefactor(),
|
||||
p_target_bpu->power() + rhs_bpu_orig.power());
|
||||
|
||||
return outer_scalefactor_result<Int>(rhs_bpu_rr.outer_scale_exact_,
|
||||
rhs_bpu_rr.outer_scale_sq_);
|
||||
|
|
@ -197,21 +206,49 @@ namespace xo {
|
|||
template <typename Int>
|
||||
constexpr
|
||||
outer_scalefactor_result<Int>
|
||||
bpu_array_product_inplace(natural_unit<Int> * p_target,
|
||||
const bpu<Int> & bpu)
|
||||
bpu_ratio_inplace(bpu<Int> * p_target_bpu,
|
||||
const bpu<Int> & rhs_bpu_orig)
|
||||
{
|
||||
assert(rhs_bpu_orig.native_dim() == p_target_bpu->native_dim());
|
||||
|
||||
bpu2_rescale_result<Int> rhs_bpu_rr = bpu2_rescale(rhs_bpu_orig,
|
||||
p_target_bpu->scalefactor());
|
||||
|
||||
*p_target_bpu = bpu<Int>(p_target_bpu->native_dim(),
|
||||
p_target_bpu->scalefactor(),
|
||||
p_target_bpu->power() - rhs_bpu_orig.power());
|
||||
|
||||
return outer_scalefactor_result<Int>(power_ratio_type(1,1) / rhs_bpu_rr.outer_scale_exact_,
|
||||
1.0 / rhs_bpu_rr.outer_scale_sq_);
|
||||
}
|
||||
|
||||
template <typename Int>
|
||||
constexpr
|
||||
outer_scalefactor_result<Int>
|
||||
nu_product_inplace(natural_unit<Int> * p_target,
|
||||
const bpu<Int> & bpu)
|
||||
{
|
||||
std::size_t i = 0;
|
||||
for (; i < p_target->n_bpu(); ++i) {
|
||||
if ((*p_target)[i].native_dim() == bpu.native_dim()) {
|
||||
outer_scalefactor_result<Int> retval = bpu_product_inplace(&((*p_target)[i]), bpu);
|
||||
auto * p_target_bpu = &((*p_target)[i]);
|
||||
|
||||
/* TODO: strip 0 power */
|
||||
if (p_target_bpu->native_dim() == bpu.native_dim()) {
|
||||
outer_scalefactor_result<Int> retval = bpu_product_inplace(p_target_bpu, bpu);
|
||||
|
||||
if (p_target_bpu->power().is_zero()) {
|
||||
/* dimension assoc'd with *p_target_bpu has been cancelled */
|
||||
p_target->remove_bpu(i);
|
||||
}
|
||||
|
||||
return retval;
|
||||
}
|
||||
}
|
||||
|
||||
/* control here: i=p_target->n_bpu() */
|
||||
/* control here: i=p_target->n_bpu()
|
||||
* Dimension represented by bpu does not already appear in *p_target.
|
||||
* Adopt bpu's scalefactor
|
||||
*/
|
||||
|
||||
p_target->push_back(bpu);
|
||||
|
||||
return outer_scalefactor_result<Int>
|
||||
|
|
@ -219,6 +256,40 @@ namespace xo {
|
|||
1.0 /*outer_scale_sq*/);
|
||||
}
|
||||
|
||||
template <typename Int>
|
||||
constexpr
|
||||
outer_scalefactor_result<Int>
|
||||
nu_ratio_inplace(natural_unit<Int> * p_target,
|
||||
const bpu<Int> & bpu)
|
||||
{
|
||||
std::size_t i = 0;
|
||||
for (; i < p_target->n_bpu(); ++i) {
|
||||
auto * p_target_bpu = &((*p_target)[i]);
|
||||
|
||||
if (p_target_bpu->native_dim() == bpu.native_dim()) {
|
||||
outer_scalefactor_result<Int> retval = bpu_ratio_inplace(p_target_bpu, bpu);
|
||||
|
||||
if (p_target_bpu->power().is_zero()) {
|
||||
/* dimension assoc'd with *p_target_bpu has been cancelled */
|
||||
p_target->remove_bpu(i);
|
||||
}
|
||||
|
||||
return retval;
|
||||
}
|
||||
}
|
||||
|
||||
/* here: i=p_target->n_bpu()
|
||||
* Dimension represented by bpu does not already appear in *p_target.
|
||||
* Adopt bpu's scalefactor
|
||||
*/
|
||||
|
||||
p_target->push_back(bpu.reciprocal());
|
||||
|
||||
return outer_scalefactor_result<Int>
|
||||
(ratio::ratio<Int>(1, 1) /*outer_scale_exact*/,
|
||||
1.0 /*outer_scale_sq*/);
|
||||
}
|
||||
|
||||
template <typename Int>
|
||||
constexpr natural_unit<Int>
|
||||
nu_reciprocal(const natural_unit<Int> & nu)
|
||||
|
|
|
|||
|
|
@ -67,15 +67,15 @@ namespace xo {
|
|||
template <typename Int>
|
||||
constexpr
|
||||
scaled_unit<Int>
|
||||
nu_product(const natural_unit<Int> & lhs_bpu_array,
|
||||
const bpu<Int> & rhs_bpu)
|
||||
nu_bpu_product(const natural_unit<Int> & lhs_bpu_array,
|
||||
const bpu<Int> & rhs_bpu)
|
||||
{
|
||||
natural_unit<Int> prod = lhs_bpu_array;
|
||||
auto rr = bpu_array_product_inplace(&prod, rhs_bpu);
|
||||
auto rr = nu_product_inplace(&prod, rhs_bpu);
|
||||
|
||||
return scaled_unit<Int>(prod,
|
||||
rr.outer_scale_exact_,
|
||||
rr.outer_scale_sq_);
|
||||
rr.outer_scale_exact_,
|
||||
rr.outer_scale_sq_);
|
||||
};
|
||||
|
||||
template <typename Int>
|
||||
|
|
@ -95,7 +95,7 @@ namespace xo {
|
|||
1.0 /*outer_scale_sq*/));
|
||||
|
||||
for (std::size_t i = 0; i < rhs_bpu_array.n_bpu(); ++i) {
|
||||
auto sfr2 = bpu_array_product_inplace(&prod, rhs_bpu_array[i]);
|
||||
auto sfr2 = nu_product_inplace(&prod, rhs_bpu_array[i]);
|
||||
|
||||
sfr.outer_scale_exact_ = sfr.outer_scale_exact_ * sfr2.outer_scale_exact_;
|
||||
sfr.outer_scale_sq_ *= sfr2.outer_scale_sq_;
|
||||
|
|
@ -106,6 +106,36 @@ namespace xo {
|
|||
sfr.outer_scale_sq_);
|
||||
}
|
||||
|
||||
template <typename Int>
|
||||
constexpr
|
||||
scaled_unit<Int>
|
||||
nu_ratio(const natural_unit<Int> & nu_lhs,
|
||||
const natural_unit<Int> & nu_rhs)
|
||||
{
|
||||
natural_unit<Int> ratio = nu_lhs;
|
||||
|
||||
/* accumulate product of scalefactors spun off by rescaling
|
||||
* any basis-units in rhs_bpu_array that conflict with the same dimension
|
||||
* in lh_bpu_array
|
||||
*/
|
||||
auto sfr = (detail::outer_scalefactor_result<Int>
|
||||
(scalefactor_ratio_type(1, 1) /*outer_scale_exact*/,
|
||||
1.0 /*outer_scale_sq*/));
|
||||
|
||||
for (std::size_t i = 0; i < nu_rhs.n_bpu(); ++i) {
|
||||
auto sfr2 = nu_ratio_inplace(&ratio, nu_rhs[i]);
|
||||
|
||||
/* note: nu_ratio_inplace() reports multiplicative outer scaling factors,
|
||||
* so multiply is correct here
|
||||
*/
|
||||
sfr.outer_scale_exact_ = sfr.outer_scale_exact_ * sfr2.outer_scale_exact_;
|
||||
sfr.outer_scale_sq_ *= sfr2.outer_scale_sq_;
|
||||
}
|
||||
|
||||
return scaled_unit<Int>(ratio,
|
||||
sfr.outer_scale_exact_,
|
||||
sfr.outer_scale_sq_);
|
||||
}
|
||||
}
|
||||
|
||||
template <typename Int>
|
||||
|
|
@ -114,7 +144,21 @@ namespace xo {
|
|||
const scaled_unit<Int> & y_unit)
|
||||
{
|
||||
auto rr = detail::nu_product(x_unit.natural_unit_,
|
||||
y_unit.natural_unit_);
|
||||
y_unit.natural_unit_);
|
||||
|
||||
return (scaled_unit<Int>
|
||||
(rr.natural_unit_,
|
||||
rr.outer_scale_exact_ * x_unit.outer_scale_exact_ * y_unit.outer_scale_exact_,
|
||||
rr.outer_scale_sq_ * x_unit.outer_scale_sq_ * y_unit.outer_scale_sq_));
|
||||
}
|
||||
|
||||
template <typename Int>
|
||||
inline constexpr scaled_unit<Int>
|
||||
operator/ (const scaled_unit<Int> & x_unit,
|
||||
const scaled_unit<Int> & y_unit)
|
||||
{
|
||||
auto rr = detail::nu_ratio(x_unit.natural_unit_,
|
||||
y_unit.natural_unit_);
|
||||
|
||||
return (scaled_unit<Int>
|
||||
(rr.natural_unit_,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue