Scaled Unit
A dimensionless multiple of a natural_unit
Context
Introduction
#include <xo/unit/scaled_unit.hpp>
Extension of natural_unit to enable representing the intermediate result of multiplication (or division) of natural units.
represents a (dimensionless) multiple of a cartesian product of basis units.
constexpr implementation
limited support for fractional dimensions such as time^-1/2
scaled unit after (u::meter * u::foot / u::minute)
Scaled units with non-unity outer scalefactors arise as intermediate results of quantity arithmetic
Motivation
Consider multiplying two units:
using namespace xo::qty;
constexpr auto u_prod = u::meter * u::kilometer;
How should we represent the product?
We don’t want to mix units. Instead we consolidate on a common unit; to do this we accumulate a product of conversion factors from such consolidation.
For example:
static_assert(u_prod.n_bpu() == 1);
static_assert(u_prod[0].bu() == detail::bu::meter);
static_assert(u_prod[0].power() == power_ratio_type(2));
static_assert(u_prod.outer_scale_factor_ == xo::ratio::ratio<int64_t>(1000));
static_assert(u_prod.outer_scale_sq_ == 1.0); // used if fractional dimension
Here we accumulate 1000, from converting kilometers to meters.
Division works similarly. In this example dimension cancel, but we still have a non-unity conversion factor.
namespace u = xo::qty::u;
constexpr auto u_div = u::meter / u::kilometer;
// dimensionlesss result
static_assert(u_prod.n_bpu() == 0);
static_assert(u_prod.outer_scale_factor_ == xo::ratio::ratio<int64_t>(1,1000));
static_assert(u_prod.outer_scale_sq_ == 1.0);
When multiple dimensions needing conversion are involved, scalefactors accumulate:
namespace u = xo::qty::u;
constexpr auto u2_prod = u::meter * u::hour * u::kilometer * u::minute;
static_assert(u2_prod.n_bpu() == 2);
static_assert(u2_prod[0].bu() == detail::bu::meter);
static_assert(u2_prod[1].bu() == detail::bu::hour);
static_assert(u2_prod.outer_scale_factor_ == xo::ratio::ratio<int64_t>(50,3));
static_assert(u2_prod.outer_scale_sq_ == 1.0); // used if fractional dimension
Here the 50/3 result comes from multiplying 1000/1 (converting kilometers -> meters)
by 1/60 (converting minutes -> hours)
Class
Member Variables
- group Scaled-unit-instance-vars
Variables
-
OuterScale outer_scale_factor_
scale factor multiplying natural_unit_
-
double outer_scale_sq_
squared scale factor multiplying natural_unit_
-
natural_unit<Int> natural_unit_
natural unit term in this scaled unit
-
OuterScale outer_scale_factor_
Type Traits
- group scaled-unit type traits
Typedefs
-
using ratio_int_type = typename natural_unit<Int>::ratio_int_type
type for representing individual basis-unit scalefactors
-
using ratio_int_type = typename natural_unit<Int>::ratio_int_type
Access Methods
- group scaled-unit access methods
Functions
-
inline bool is_scaled_unit_type() const
always true for scaled_unit
-
inline bool is_natural() const
true iff scaled unit can be faithfully represented by a natural_unit
-
inline bool is_dimensionless() const
true if this scaled unit has no dimension
-
inline std::size_t n_bpu() const
get number of distinct native dimensions present. e.g. for unit Newton = 1 kg.m.s^-2, n_bpu would be 3, with {mass, distance, time} present. Note that this value does not count exponents
Variables
-
static bool is_scaled_unit_type_v = true
always true for scaled_unit
-
inline bool is_scaled_unit_type() const
General Methods
- group scaled-unit access methods
Functions
-
inline scaled_unit reciprocal() const
return reciprocal of this unit.
-
inline bpu<Int> lookup_dim(dimension d) const
get bpu for dimension
d. if d isn’t present, construct bpu with 0 power
-
inline bpu<Int> &operator[](std::size_t i)
return
i'thbpu associated with this unit
-
inline const bpu<Int> &operator[](std::size_t i) const
return
i'thbpu associated with this unit (const version)
-
inline scaled_unit reciprocal() const
Operators
- group Scaled-unit-operators
Functions
-
template<typename Int, typename Int2x = detail::width2x_t<Int>>
inline scaled_unit<Int> operator*(const scaled_unit<Int> &x_unit, const scaled_unit<Int> &y_unit) Multiply scaled_unit instances
x_unitandy_unit. Result is a scaled_unit for the product dimension. For each basis dimension, result will prioritize scale fromx_unitahead ofy_unit.
-
template<typename Int, typename Int2x = detail::width2x_t<Int>>
inline scaled_unit<Int> operator/(const scaled_unit<Int> &x_unit, const scaled_unit<Int> &y_unit) Divide scaled_unit instances
x_unitbyy_unit. Result is a scaled_unit for the quotient dimension. For each basis dimension, result will prioritize scale fromx_unitahead ofy_unit.
-
template<typename Int, typename Int2x = detail::width2x_t<Int>>