refactor: 💥 ratio hidden as an implementation detail behind mag_ratio

This commit is contained in:
Mateusz Pusz
2024-04-19 15:29:00 +01:00
parent ae1003b279
commit f90a218705
24 changed files with 126 additions and 129 deletions

View File

@ -114,7 +114,7 @@ units of _length_:
```cpp
inline constexpr struct hubble_constant :
named_unit<{u8"H₀", "H_0"}, mag<ratio{701, 10}> * si::kilo<si::metre> / si::second / si::mega<parsec>> {} hubble_constant;
named_unit<{u8"H₀", "H_0"}, mag_ratio<701, 10> * si::kilo<si::metre> / si::second / si::mega<parsec>> {} hubble_constant;
```
@ -158,9 +158,9 @@ Besides the unit `one`, there are a few other scaled units predefined in the lib
with dimensionless quantities:
```cpp
inline constexpr struct percent : named_unit<"%", mag<ratio{1, 100}> * one> {} percent;
inline constexpr struct per_mille : named_unit<{u8"‰", "%o"}, mag<ratio(1, 1000)> * one> {} per_mille;
inline constexpr struct parts_per_million : named_unit<"ppm", mag<ratio(1, 1'000'000)> * one> {} parts_per_million;
inline constexpr struct percent : named_unit<"%", mag_ratio<1, 100> * one> {} percent;
inline constexpr struct per_mille : named_unit<{u8"‰", "%o"}, mag_ratio<1, 1000> * one> {} per_mille;
inline constexpr struct parts_per_million : named_unit<"ppm", mag_ratio<1, 1'000'000> * one> {} parts_per_million;
inline constexpr auto ppm = parts_per_million;
```

View File

@ -170,14 +170,14 @@ electronvolt:
```cpp
inline constexpr struct minute : named_unit<"min", mag<60> * si::second> {} minute;
inline constexpr struct hour : named_unit<"h", mag<60> * minute> {} hour;
inline constexpr struct electronvolt : named_unit<"eV", mag<ratio{1'602'176'634, 1'000'000'000}> * mag_power<10, -19> * si::joule> {} electronvolt;
inline constexpr struct electronvolt : named_unit<"eV", mag_ratio<1'602'176'634, 1'000'000'000> * mag_power<10, -19> * si::joule> {} electronvolt;
```
Also, units of other [systems of units](../../appendix/glossary.md#system-of-units) are often defined
in terms of scaled versions of the SI units. For example, the international yard is defined as:
```cpp
inline constexpr struct yard : named_unit<"yd", mag<ratio{9'144, 10'000}> * si::metre> {} yard;
inline constexpr struct yard : named_unit<"yd", mag_ratio<9'144, 10'000> * si::metre> {} yard;
```
For some units, a magnitude might also be irrational. The best example here is a `degree` which

View File

@ -77,10 +77,10 @@ and units of derived quantities.
```cpp
inline constexpr struct hyperfine_structure_transition_frequency_of_cs : named_unit<{u8"Δν_Cs", "dv_Cs"}, mag<9'192'631'770> * hertz> {} hyperfine_structure_transition_frequency_of_cs;
inline constexpr struct speed_of_light_in_vacuum : named_unit<"c", mag<299'792'458> * metre / second> {} speed_of_light_in_vacuum;
inline constexpr struct planck_constant : named_unit<"h", mag<ratio{662'607'015, 100'000'000}> * mag_power<10, -34> * joule * second> {} planck_constant;
inline constexpr struct elementary_charge : named_unit<"e", mag<ratio{1'602'176'634, 1'000'000'000}> * mag_power<10, -19> * coulomb> {} elementary_charge;
inline constexpr struct boltzmann_constant : named_unit<"k", mag<ratio{1'380'649, 1'000'000}> * mag_power<10, -23> * joule / kelvin> {} boltzmann_constant;
inline constexpr struct avogadro_constant : named_unit<"N_A", mag<ratio{602'214'076, 100'000'000}> * mag_power<10, 23> / mole> {} avogadro_constant;
inline constexpr struct planck_constant : named_unit<"h", mag_ratio<662'607'015, 100'000'000> * mag_power<10, -34> * joule * second> {} planck_constant;
inline constexpr struct elementary_charge : named_unit<"e", mag_ratio<1'602'176'634, 1'000'000'000> * mag_power<10, -19> * coulomb> {} elementary_charge;
inline constexpr struct boltzmann_constant : named_unit<"k", mag_ratio<1'380'649, 1'000'000> * mag_power<10, -23> * joule / kelvin> {} boltzmann_constant;
inline constexpr struct avogadro_constant : named_unit<"N_A", mag_ratio<602'214'076, 100'000'000> * mag_power<10, 23> / mole> {} avogadro_constant;
inline constexpr struct luminous_efficacy : named_unit<"K_cd", mag<683> * lumen / watt> {} luminous_efficacy;
```

View File

@ -403,7 +403,7 @@ inline constexpr struct zeroth_degree_Celsius : decltype(ice_point) {} zeroth_de
namespace usc {
inline constexpr struct zeroth_degree_Fahrenheit :
relative_point_origin<si::zeroth_degree_Celsius - 32 * (mag<ratio{5, 9}> * si::degree_Celsius)> {} zeroth_degree_Fahrenheit;
relative_point_origin<si::zeroth_degree_Celsius - 32 * (mag_ratio<5, 9> * si::degree_Celsius)> {} zeroth_degree_Fahrenheit;
}
```
@ -436,7 +436,7 @@ inline constexpr struct degree_Celsius :
namespace usc {
inline constexpr struct degree_Fahrenheit :
named_unit<{u8"°F", "`F"}, mag<ratio{5, 9}> * si::degree_Celsius,
named_unit<{u8"°F", "`F"}, mag_ratio<5, 9> * si::degree_Celsius,
zeroth_degree_Fahrenheit> {} degree_Fahrenheit;
}

View File

@ -99,7 +99,7 @@ template<typename F, int Num, int... Den>
requires(detail::valid_ratio<Num, Den...> && detail::positive_ratio<Num, Den...> && !detail::ratio_one<Num, Den...>)
struct power {
using factor = F;
static constexpr ratio exponent{Num, Den...};
static constexpr detail::ratio exponent{Num, Den...};
};
namespace detail {

View File

@ -166,7 +166,7 @@ template<PowerVBase auto V, int Num, int... Den>
requires(detail::valid_ratio<Num, Den...> && !detail::ratio_one<Num, Den...>)
struct power_v {
static constexpr auto base = V;
static constexpr ratio exponent{Num, Den...};
static constexpr detail::ratio exponent{Num, Den...};
};
namespace detail {
@ -565,7 +565,8 @@ template<std::intmax_t Num, std::intmax_t Den = 1, auto... Ms>
if constexpr (Num == 0) {
return magnitude<>{};
} else {
return magnitude<detail::power_v_or_T<detail::get_base(Ms), detail::get_exponent(Ms) * ratio{Num, Den}>()...>{};
return magnitude<
detail::power_v_or_T<detail::get_base(Ms), detail::get_exponent(Ms) * detail::ratio{Num, Den}>()...>{};
}
}
@ -675,8 +676,6 @@ template<auto M>
}
}
} // namespace detail
template<auto... Ms>
[[nodiscard]] consteval auto numerator(magnitude<Ms...>)
{
@ -685,8 +684,8 @@ template<auto... Ms>
[[nodiscard]] consteval auto denominator(Magnitude auto m) { return numerator(pow<-1>(m)); }
// Implementation of conversion to ratio goes here, because it needs `numerator()` and `denominator()`.
constexpr ratio as_ratio(Magnitude auto m)
// TODO This probably should not be exported but is used in chrono.h
MP_UNITS_EXPORT constexpr ratio as_ratio(Magnitude auto m)
requires(is_rational(decltype(m){}))
{
return ratio{
@ -695,7 +694,6 @@ constexpr ratio as_ratio(Magnitude auto m)
};
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Common Magnitude.
//
@ -714,8 +712,6 @@ constexpr ratio as_ratio(Magnitude auto m)
// Thus, we make the _simplest_ choice which reproduces the correct convention in the rational case: namely, taking the
// minimum power for each base (where absent bases implicitly have a power of 0).
namespace detail {
template<auto M>
[[nodiscard]] consteval auto remove_positive_power(magnitude<M> m)
{
@ -830,16 +826,20 @@ inline constexpr auto prime_factorization_v = prime_factorization<N>::value;
* This will be the main way end users create Magnitudes. They should rarely (if ever) create a magnitude<...> by
* manually adding base powers.
*/
MP_UNITS_EXPORT template<ratio R>
requires detail::gt_zero<R.num>
inline constexpr Magnitude auto mag = detail::prime_factorization_v<R.num> / detail::prime_factorization_v<R.den>;
MP_UNITS_EXPORT template<std::intmax_t V>
requires detail::gt_zero<V>
inline constexpr Magnitude auto mag = detail::prime_factorization_v<V>;
MP_UNITS_EXPORT template<std::intmax_t N, std::intmax_t D>
requires detail::gt_zero<N>
inline constexpr Magnitude auto mag_ratio = detail::prime_factorization_v<N> / detail::prime_factorization_v<D>;
/**
* @brief Create a Magnitude which is some rational number raised to a rational power.
*/
MP_UNITS_EXPORT template<ratio Base, ratio Pow>
requires detail::gt_zero<Base.num>
inline constexpr Magnitude auto mag_power = pow<Pow.num, Pow.den>(mag<Base>);
MP_UNITS_EXPORT template<std::intmax_t Base, std::intmax_t Pow>
requires detail::gt_zero<Base>
inline constexpr Magnitude auto mag_power = pow<Pow>(mag<Base>);
namespace detail {

View File

@ -32,9 +32,7 @@
#include <numeric>
#endif
namespace mp_units {
namespace detail {
namespace mp_units::detail {
template<typename T>
[[nodiscard]] MP_UNITS_CONSTEVAL T abs(T v) noexcept
@ -59,14 +57,13 @@ template<typename T>
return lhs * rhs;
}
} // namespace detail
/**
* @brief Provides compile-time rational arithmetic support.
*
* This class is really similar to @c std::ratio. An important difference is the fact that the objects of that class
* are used as class NTTPs rather then a type template parameter kind.
*/
// TODO This probably should not be exported but is used in chrono.h
MP_UNITS_EXPORT struct ratio {
std::intmax_t num;
std::intmax_t den;
@ -123,4 +120,4 @@ MP_UNITS_EXPORT struct ratio {
return ratio{num / gcd, den / gcd};
}
} // namespace mp_units
} // namespace mp_units::detail

View File

@ -56,7 +56,7 @@ template<std::intmax_t Num, std::intmax_t Den = 1, auto R, typename Rep>
{
if constexpr (Num == 0) {
return quantity<pow<Num, Den>(R), Rep>::one();
} else if constexpr (ratio{Num, Den} == 1) {
} else if constexpr (Num == Den) {
return q;
} else {
using std::pow;

View File

@ -555,7 +555,7 @@ template<std::intmax_t Num, std::intmax_t Den = 1, QuantitySpec Q>
// all are dimensionless quantities :-(
if constexpr (Num == 0 || Q{} == dimensionless)
return dimensionless;
else if constexpr (ratio{Num, Den} == 1)
else if constexpr (detail::ratio{Num, Den} == 1)
return q;
else if constexpr (detail::IntermediateDerivedQuantitySpec<Q>)
return detail::clone_kind_of<Q{}>(

View File

@ -566,7 +566,7 @@ template<std::intmax_t Num, std::intmax_t Den = 1, Unit U>
{
if constexpr (Num == 0 || is_same_v<U, struct one>)
return one;
else if constexpr (ratio{Num, Den} == 1)
else if constexpr (detail::ratio{Num, Den} == 1)
return u;
else if constexpr (detail::is_specialization_of_scaled_unit<U>)
return scaled_unit<pow<Num, Den>(U::mag), std::remove_const_t<decltype(pow<Num, Den>(U::reference_unit))>>{};
@ -617,9 +617,9 @@ template<std::intmax_t Num, std::intmax_t Den = 1, Unit U>
// common dimensionless units
// clang-format off
inline constexpr struct percent : named_unit<"%", mag<ratio{1, 100}> * one> {} percent;
inline constexpr struct per_mille : named_unit<symbol_text{u8"", "%o"}, mag<ratio(1, 1000)> * one> {} per_mille;
inline constexpr struct parts_per_million : named_unit<"ppm", mag<ratio(1, 1'000'000)> * one> {} parts_per_million;
inline constexpr struct percent : named_unit<"%", mag_ratio<1, 100> * one> {} percent;
inline constexpr struct per_mille : named_unit<symbol_text{u8"", "%o"}, mag_ratio<1, 1000> * one> {} per_mille;
inline constexpr struct parts_per_million : named_unit<"ppm", mag_ratio<1, 1'000'000> * one> {} parts_per_million;
inline constexpr auto ppm = parts_per_million;
// clang-format on

View File

@ -40,8 +40,8 @@ QUANTITY_SPEC(solid_angle, pow<2>(angle));
inline constexpr struct radian : named_unit<"rad", kind_of<angle>> {} radian;
inline constexpr struct revolution : named_unit<"rev", mag<2> * mag_pi * radian> {} revolution;
inline constexpr struct degree : named_unit<symbol_text{u8"°", "deg"}, mag<ratio{1, 360}> * revolution> {} degree;
inline constexpr struct gradian : named_unit<symbol_text{u8"", "grad"}, mag<ratio{1, 400}> * revolution> {} gradian;
inline constexpr struct degree : named_unit<symbol_text{u8"°", "deg"}, mag_ratio<1, 360> * revolution> {} degree;
inline constexpr struct gradian : named_unit<symbol_text{u8"", "grad"}, mag_ratio<1, 400> * revolution> {} gradian;
inline constexpr struct steradian : named_unit<"sr", square(radian)> {} steradian;
// clang-format on

View File

@ -49,9 +49,9 @@ using si::electronvolt;
inline constexpr struct barn : named_unit<"b", mag_power<10, -28> * square(si::metre)> {} barn;
// mass
inline constexpr struct electron_mass : named_unit<"m_e", mag<ratio{9'109'383'701'528, 1'000'000'000'000}> * mag_power<10, -31> * si::kilogram> {} electron_mass;
inline constexpr struct proton_mass : named_unit<"m_p", mag<ratio{1'672'621'923'695, 1'000'000'000'000}> * mag_power<10, -27> * si::kilogram> {} proton_mass;
inline constexpr struct neutron_mass : named_unit<"m_n", mag<ratio{1'674'927'498'049, 1'000'000'000'000}> * mag_power<10, -27> * si::kilogram> {} neutron_mass;
inline constexpr struct electron_mass : named_unit<"m_e", mag_ratio<9'109'383'701'528, 1'000'000'000'000> * mag_power<10, -31> * si::kilogram> {} electron_mass;
inline constexpr struct proton_mass : named_unit<"m_p", mag_ratio<1'672'621'923'695, 1'000'000'000'000> * mag_power<10, -27> * si::kilogram> {} proton_mass;
inline constexpr struct neutron_mass : named_unit<"m_n", mag_ratio<1'674'927'498'049, 1'000'000'000'000> * mag_power<10, -27> * si::kilogram> {} neutron_mass;
// speed
inline constexpr struct speed_of_light : decltype(si::si2019::speed_of_light_in_vacuum) {} speed_of_light;

View File

@ -38,14 +38,14 @@ namespace mp_units::iau {
// clang-format off
// time
inline constexpr struct day : named_unit<"D", si::day> {} day;
inline constexpr struct Julian_year : named_unit<"a", mag<ratio{365'25, 100}> * day> {} Julian_year;
inline constexpr struct Julian_year : named_unit<"a", mag_ratio<365'25, 100> * day> {} Julian_year;
// mass
// https://en.wikipedia.org/wiki/Solar_mass
// TODO What is the official mass of sun (every source in the Internet provides a different value)
inline constexpr struct solar_mass : named_unit<symbol_text{u8"M_☉", "M_SUN"}, mag<ratio{198'847, 100'000}> * mag_power<10, 30> * si::kilogram> {} solar_mass;
inline constexpr struct Jupiter_mass : named_unit<"M_JUP", mag<ratio{1'898, 1'000}> * mag_power<10, 27> * si::kilogram> {} Jupiter_mass;
inline constexpr struct Earth_mass : named_unit<"M_EARTH", mag<ratio{59'742, 10'000}> * mag_power<10, 24> * si::kilogram> {} Earth_mass;
inline constexpr struct solar_mass : named_unit<symbol_text{u8"M_☉", "M_SUN"}, mag_ratio<198'847, 100'000> * mag_power<10, 30> * si::kilogram> {} solar_mass;
inline constexpr struct Jupiter_mass : named_unit<"M_JUP", mag_ratio<1'898, 1'000> * mag_power<10, 27> * si::kilogram> {} Jupiter_mass;
inline constexpr struct Earth_mass : named_unit<"M_EARTH", mag_ratio<59'742, 10'000> * mag_power<10, 24> * si::kilogram> {} Earth_mass;
// length
inline constexpr struct astronomical_unit : decltype(si::astronomical_unit) {} astronomical_unit;
@ -57,7 +57,7 @@ inline constexpr struct lunar_distance : named_unit<"LD", mag<384'399> * si::kil
inline constexpr struct light_year : named_unit<"ly", mag<9'460'730'472'580'800> * si::metre> {} light_year;
// https://en.wikipedia.org/wiki/Parsec
inline constexpr struct parsec : named_unit<"pc", astronomical_unit / (mag<ratio{1, 60 * 60}> * si::degree)> {} parsec;
inline constexpr struct parsec : named_unit<"pc", astronomical_unit / (mag_ratio<1, 60 * 60> * si::degree)> {} parsec;
// https://en.wikipedia.org/wiki/Angstrom
inline constexpr struct angstrom : named_unit<symbol_text{u8"Å", "A"}, mag_power<10, -10> * si::metre> {} angstrom;
@ -65,16 +65,16 @@ inline constexpr struct angstrom : named_unit<symbol_text{u8"Å", "A"}, mag_powe
// selected constants
// https://en.wikipedia.org/wiki/Astronomical_constant
inline constexpr struct gaussian_gravitational_constant :
named_unit<"k", mag<ratio{1'720'209'895, 100'000'000'000}> * pow<3, 2>(astronomical_unit) / pow<1,2>(solar_mass) / day> {} gaussian_gravitational_constant;
named_unit<"k", mag_ratio<1'720'209'895, 100'000'000'000> * pow<3, 2>(astronomical_unit) / pow<1,2>(solar_mass) / day> {} gaussian_gravitational_constant;
inline constexpr struct speed_of_light :
named_unit<symbol_text{u8"c₀", "c_0"}, si::si2019::speed_of_light_in_vacuum> {} speed_of_light;
inline constexpr struct constant_of_gravitation :
named_unit<"G", mag<ratio{667'430, 100'000}> * mag_power<10, -11> * cubic(si::metre) / si::kilogram / square(si::second)> {} constant_of_gravitation;
named_unit<"G", mag_ratio<667'430, 100'000> * mag_power<10, -11> * cubic(si::metre) / si::kilogram / square(si::second)> {} constant_of_gravitation;
inline constexpr struct hubble_constant :
named_unit<symbol_text{u8"H₀", "H_0"}, mag<ratio{701, 10}> * si::kilo<si::metre> / si::second / si::mega<parsec>> {} hubble_constant;
named_unit<symbol_text{u8"H₀", "H_0"}, mag_ratio<701, 10> * si::kilo<si::metre> / si::second / si::mega<parsec>> {} hubble_constant;
// clang-format on
namespace unit_symbols {

View File

@ -36,18 +36,18 @@ using namespace international;
// clang-format off
// https://en.wikipedia.org/wiki/Imperial_units#Length
inline constexpr struct hand : named_unit<"hh", mag<ratio{1, 3}> * foot> {} hand;
inline constexpr struct barleycorn : named_unit<"Bc", mag<ratio(1, 3)> * inch> {} barleycorn;
inline constexpr struct thou : named_unit<"th", mag<ratio{1, 12'000}> * foot> {} thou;
inline constexpr struct hand : named_unit<"hh", mag_ratio<1, 3> * foot> {} hand;
inline constexpr struct barleycorn : named_unit<"Bc", mag_ratio<1, 3> * inch> {} barleycorn;
inline constexpr struct thou : named_unit<"th", mag_ratio<1, 12'000> * foot> {} thou;
inline constexpr struct chain : named_unit<"ch", mag<22> * yard> {} chain;
inline constexpr struct furlong : named_unit<"fur", mag<10> * chain> {} furlong;
// maritime units
inline constexpr struct cable : named_unit<"cb", mag<ratio{1, 10}> * nautical_mile> {} cable;
inline constexpr struct fathom : named_unit<"ftm", mag<ratio{1, 1000}> * nautical_mile> {} fathom;
inline constexpr struct cable : named_unit<"cb", mag_ratio<1, 10> * nautical_mile> {} cable;
inline constexpr struct fathom : named_unit<"ftm", mag_ratio<1, 1000> * nautical_mile> {} fathom;
// survey
inline constexpr struct link : named_unit<"li", mag<ratio{1, 100}> * chain> {} link;
inline constexpr struct link : named_unit<"li", mag_ratio<1, 100> * chain> {} link;
inline constexpr struct rod : named_unit<"rd", mag<25> * link> {} rod;
// https://en.wikipedia.org/wiki/Imperial_units#Area
@ -56,11 +56,11 @@ inline constexpr struct rood : decltype(mag<40> * perch) {} rood;
inline constexpr struct acre : decltype(mag<4> * rood) {} acre;
// https://en.wikipedia.org/wiki/Imperial_units#Volume
inline constexpr struct gallon : named_unit<"gal", mag<ratio{454'609, 100'000}> * si::litre> {} gallon;
inline constexpr struct quart : named_unit<"qt", mag<ratio{1, 4}> * gallon> {} quart;
inline constexpr struct pint : named_unit<"pt", mag<ratio{1, 2}> * quart> {} pint;
inline constexpr struct gill : named_unit<"gi", mag<ratio{1, 4}> * pint> {} gill;
inline constexpr struct fluid_ounce : named_unit<"fl oz", mag<ratio{1, 5}> * gill> {} fluid_ounce;
inline constexpr struct gallon : named_unit<"gal", mag_ratio<454'609, 100'000> * si::litre> {} gallon;
inline constexpr struct quart : named_unit<"qt", mag_ratio<1, 4> * gallon> {} quart;
inline constexpr struct pint : named_unit<"pt", mag_ratio<1, 2> * quart> {} pint;
inline constexpr struct gill : named_unit<"gi", mag_ratio<1, 4> * pint> {} gill;
inline constexpr struct fluid_ounce : named_unit<"fl oz", mag_ratio<1, 5> * gill> {} fluid_ounce;
// https://en.wikipedia.org/wiki/Avoirdupois_system#Post-Elizabethan_units
inline constexpr auto drachm = dram;

View File

@ -35,20 +35,20 @@ namespace mp_units::international {
// clang-format off
// mass
inline constexpr struct pound : named_unit<"lb", mag<ratio{45'359'237, 100'000'000}> * si::kilogram> {} pound;
inline constexpr struct ounce : named_unit<"oz", mag<ratio(1, 16)> * pound> {} ounce;
inline constexpr struct dram : named_unit<"dr", mag<ratio(1, 16)> * ounce> {} dram;
inline constexpr struct grain : named_unit<"gr", mag<ratio(1, 7'000)> * pound> {} grain;
inline constexpr struct pound : named_unit<"lb", mag_ratio<45'359'237, 100'000'000> * si::kilogram> {} pound;
inline constexpr struct ounce : named_unit<"oz", mag_ratio<1, 16> * pound> {} ounce;
inline constexpr struct dram : named_unit<"dr", mag_ratio<1, 16> * ounce> {} dram;
inline constexpr struct grain : named_unit<"gr", mag_ratio<1, 7'000> * pound> {} grain;
// length
// https://en.wikipedia.org/wiki/United_States_customary_units#Length
inline constexpr struct yard : named_unit<"yd", mag<ratio{9'144, 10'000}> * si::metre> {} yard;
inline constexpr struct foot : named_unit<"ft", mag<ratio{1, 3}> * yard> {} foot;
inline constexpr struct inch : named_unit<"in", mag<ratio{1, 12}> * foot> {} inch;
inline constexpr struct pica : named_unit<"P", mag<ratio{1, 6}> * inch> {} pica;
inline constexpr struct point : named_unit<"p", mag<ratio{1, 12}> * pica> {} point;
inline constexpr struct mil : named_unit<"mil", mag<ratio{1, 1'000}> * inch> {} mil;
inline constexpr struct twip : named_unit<"twip", mag<ratio{1, 20}> * point> {} twip;
inline constexpr struct yard : named_unit<"yd", mag_ratio<9'144, 10'000> * si::metre> {} yard;
inline constexpr struct foot : named_unit<"ft", mag_ratio<1, 3> * yard> {} foot;
inline constexpr struct inch : named_unit<"in", mag_ratio<1, 12> * foot> {} inch;
inline constexpr struct pica : named_unit<"P", mag_ratio<1, 6> * inch> {} pica;
inline constexpr struct point : named_unit<"p", mag_ratio<1, 12> * pica> {} point;
inline constexpr struct mil : named_unit<"mil", mag_ratio<1, 1'000> * inch> {} mil;
inline constexpr struct twip : named_unit<"twip", mag_ratio<1, 20> * point> {} twip;
inline constexpr struct mile : named_unit<"mi", mag<1760> * yard> {} mile;
inline constexpr struct league : named_unit<"le", mag<3> * mile> {} league;

View File

@ -59,7 +59,7 @@ template<typename Period>
else if constexpr (is_same_v<Period, std::chrono::weeks::period>)
return mag<7> * day;
else
return mag<ratio{Period::num, Period::den}> * second;
return mag_ratio<Period::num, Period::den> * second;
}
} // namespace detail
@ -115,7 +115,7 @@ template<QuantityOf<isq::time> Q>
[[nodiscard]] constexpr auto to_chrono_duration(const Q& q)
{
constexpr auto canonical = get_canonical_unit(Q::unit);
constexpr ratio r = as_ratio(canonical.mag);
constexpr detail::ratio r = detail::as_ratio(canonical.mag);
return std::chrono::duration<typename Q::rep, std::ratio<r.num, r.den>>{q};
}
@ -126,7 +126,7 @@ template<QuantityPointOf<isq::time> QP>
using clock = MP_UNITS_TYPENAME decltype(QP::absolute_point_origin)::clock;
using rep = MP_UNITS_TYPENAME QP::rep;
constexpr auto canonical = get_canonical_unit(QP::unit);
constexpr ratio r = as_ratio(canonical.mag);
constexpr detail::ratio r = detail::as_ratio(canonical.mag);
using ret_type = std::chrono::time_point<clock, std::chrono::duration<rep, std::ratio<r.num, r.den>>>;
return ret_type(to_chrono_duration(qp - qp.absolute_point_origin));
}

View File

@ -40,13 +40,13 @@ inline constexpr struct hyperfine_structure_transition_frequency_of_cs :
inline constexpr struct speed_of_light_in_vacuum :
named_unit<"c", mag<299'792'458> * metre / second> {} speed_of_light_in_vacuum;
inline constexpr struct planck_constant :
named_unit<"h", mag<ratio{662'607'015, 100'000'000}> * mag_power<10, -34> * joule * second> {} planck_constant;
named_unit<"h", mag_ratio<662'607'015, 100'000'000> * mag_power<10, -34> * joule * second> {} planck_constant;
inline constexpr struct elementary_charge :
named_unit<"e", mag<ratio{1'602'176'634, 1'000'000'000}> * mag_power<10, -19> * coulomb> {} elementary_charge;
named_unit<"e", mag_ratio<1'602'176'634, 1'000'000'000> * mag_power<10, -19> * coulomb> {} elementary_charge;
inline constexpr struct boltzmann_constant :
named_unit<"k", mag<ratio{1'380'649, 1'000'000}> * mag_power<10, -23> * joule / kelvin> {} boltzmann_constant;
named_unit<"k", mag_ratio<1'380'649, 1'000'000> * mag_power<10, -23> * joule / kelvin> {} boltzmann_constant;
inline constexpr struct avogadro_constant :
named_unit<"N_A", mag<ratio{602'214'076, 100'000'000}> * mag_power<10, 23> / mole> {} avogadro_constant;
named_unit<"N_A", mag_ratio<602'214'076, 100'000'000> * mag_power<10, 23> / mole> {} avogadro_constant;
inline constexpr struct luminous_efficacy :
named_unit<"K_cd", mag<683> * lumen / watt> {} luminous_efficacy;
// clang-format on
@ -55,7 +55,7 @@ inline constexpr struct luminous_efficacy :
// clang-format off
inline constexpr struct standard_gravity :
named_unit<symbol_text{u8"g₀", "g_0"}, mag<ratio{980'665, 100'000}> * metre / square(second)> {} standard_gravity;
named_unit<symbol_text{u8"g₀", "g_0"}, mag_ratio<980'665, 100'000> * metre / square(second)> {} standard_gravity;
inline constexpr struct magnetic_constant :
named_unit<symbol_text{u8"μ₀", "u_0"}, mag<4> * mag_pi * mag_power<10, -7> * henry / metre> {} magnetic_constant;
// clang-format on

View File

@ -104,8 +104,8 @@ inline constexpr struct hour : named_unit<"h", mag<60> * minute> {} hour;
inline constexpr struct day : named_unit<"d", mag<24> * hour> {} day;
inline constexpr struct astronomical_unit : named_unit<"au", mag<149'597'870'700> * si::metre> {} astronomical_unit;
inline constexpr struct degree : named_unit<symbol_text{u8"°", "deg"}, mag_pi / mag<180> * si::radian> {} degree;
inline constexpr struct arcminute : named_unit<symbol_text{u8"", "'"}, mag<ratio{1, 60}> * degree> {} arcminute;
inline constexpr struct arcsecond : named_unit<symbol_text{u8"", "''"}, mag<ratio{1, 60}> * arcminute> {} arcsecond;
inline constexpr struct arcminute : named_unit<symbol_text{u8"", "'"}, mag_ratio<1, 60> * degree> {} arcminute;
inline constexpr struct arcsecond : named_unit<symbol_text{u8"", "''"}, mag_ratio<1, 60> * arcminute> {} arcsecond;
inline constexpr struct are : named_unit<"a", square(si::deca<si::metre>)> {} are;
#if MP_UNITS_COMP_MSVC
inline constexpr struct hectare : si::hecto_<are> {} hectare;
@ -114,9 +114,9 @@ inline constexpr struct hectare : decltype(si::hecto<are>) {} hectare;
#endif
inline constexpr struct litre : named_unit<"l", cubic(si::deci<si::metre>)> {} litre;
inline constexpr struct tonne : named_unit<"t", mag<1000> * si::kilogram> {} tonne;
inline constexpr struct dalton : named_unit<"Da", mag<ratio{16'605'390'666'050, 10'000'000'000'000}> * mag_power<10, -27> * si::kilogram> {} dalton;
inline constexpr struct dalton : named_unit<"Da", mag_ratio<16'605'390'666'050, 10'000'000'000'000> * mag_power<10, -27> * si::kilogram> {} dalton;
// TODO A different value is provided in the SI Brochure and different in the ISO 80000
inline constexpr struct electronvolt : named_unit<"eV", mag<ratio{1'602'176'634, 1'000'000'000}> * mag_power<10, -19> * si::joule> {} electronvolt;
inline constexpr struct electronvolt : named_unit<"eV", mag_ratio<1'602'176'634, 1'000'000'000> * mag_power<10, -19> * si::joule> {} electronvolt;
// TODO the below are logarithmic units - how to support those?
// neper
// bel

View File

@ -34,10 +34,10 @@ namespace mp_units::typographic {
// clang-format off
// https://en.wikipedia.org/wiki/Point_(typography)
inline constexpr struct pica_us : named_unit<"pica(us)", mag<ratio{166'044, 1'000'000}> * international::inch> {} pica_us;
inline constexpr struct point_us : named_unit<"point(us)", mag<ratio{1, 12}> * pica_us> {} point_us;
inline constexpr struct pica_us : named_unit<"pica(us)", mag_ratio<166'044, 1'000'000> * international::inch> {} pica_us;
inline constexpr struct point_us : named_unit<"point(us)", mag_ratio<1, 12> * pica_us> {} point_us;
inline constexpr struct point_dtp : named_unit<"point(dtp)", mag<ratio{1, 72}> * international::inch> {} point_dtp;
inline constexpr struct point_dtp : named_unit<"point(dtp)", mag_ratio<1, 72> * international::inch> {} point_dtp;
inline constexpr struct pica_dtp : named_unit<"pica(dtp)", mag<12> * point_dtp> {} pica_dtp;
// clang-format on

View File

@ -42,7 +42,7 @@ inline constexpr struct fathom : named_unit<"ftm(us)", mag<2> * yard> {} fathom;
inline constexpr struct cable : named_unit<"cb(us)", mag<120> * fathom> {} cable;
// survey
struct us_survey_foot : named_unit<"ft(us)", mag<ratio{1'200, 3'937}> * si::metre> {};
struct us_survey_foot : named_unit<"ft(us)", mag_ratio<1'200, 3'937> * si::metre> {};
struct us_survey_mile : named_unit<"mi(us)", mag<5280> * us_survey_foot{}> {};
[[deprecated("In accordance with NIST SP 811, as of January 1, 2023, the use of the U.S. survey foot and U.S. survey mile is deprecated.")]]
@ -51,7 +51,7 @@ inline constexpr us_survey_foot us_survey_foot;
[[deprecated("In accordance with NIST SP 811, as of January 1, 2023, the use of the U.S. survey foot and U.S. survey mile is deprecated.")]]
inline constexpr us_survey_mile us_survey_mile;
inline constexpr struct link : named_unit<"li", mag<ratio{33, 50}> * foot> {} link;
inline constexpr struct link : named_unit<"li", mag_ratio<33, 50> * foot> {} link;
inline constexpr struct rod : named_unit<"rd", mag<25> * link> {} rod;
inline constexpr struct chain : named_unit<"ch", mag<4> * rod> {} chain;
inline constexpr struct furlong : named_unit<"fur", mag<10> * chain> {} furlong;
@ -60,8 +60,8 @@ inline constexpr struct furlong : named_unit<"fur", mag<10> * chain> {} furlong;
namespace survey1893 {
// clang-format off
inline constexpr struct us_survey_foot : named_unit<"ft(us)", mag<ratio{1'200, 3'937}> * si::metre> {} us_survey_foot;
inline constexpr struct link : named_unit<"li", mag<ratio{33, 50}> * us_survey_foot> {} link;
inline constexpr struct us_survey_foot : named_unit<"ft(us)", mag_ratio<1'200, 3'937> * si::metre> {} us_survey_foot;
inline constexpr struct link : named_unit<"li", mag_ratio<33, 50> * us_survey_foot> {} link;
inline constexpr struct rod : named_unit<"rd", mag<25> * link> {} rod;
inline constexpr struct chain : named_unit<"ch", mag<4> * rod> {} chain;
inline constexpr struct furlong : named_unit<"fur", mag<10> * chain> {} furlong;
@ -78,28 +78,28 @@ inline constexpr struct section : named_unit<"section", mag<640> * acre> {} sect
// https://en.wikipedia.org/wiki/United_States_customary_units#Fluid_volume
inline constexpr struct gallon : named_unit<"gal", mag<231> * cubic(inch)> {} gallon;
inline constexpr struct pottle : named_unit<"pot", mag<ratio{1, 2}> * gallon> {} pottle;
inline constexpr struct quart : named_unit<"qt", mag<ratio{1, 2}> * pottle> {} quart;
inline constexpr struct pint : named_unit<"pt", mag<ratio{1, 2}> * quart> {} pint;
inline constexpr struct cup : named_unit<"c", mag<ratio{1, 2}> * pint> {} cup;
inline constexpr struct gill : named_unit<"gi", mag<ratio{1, 2}> * cup> {} gill;
inline constexpr struct fluid_ounce : named_unit<"fl oz", mag<ratio{1, 4}> * gill> {} fluid_ounce;
inline constexpr struct tablespoon : named_unit<"tbsp", mag<ratio{1, 2}> * fluid_ounce> {} tablespoon;
inline constexpr struct pottle : named_unit<"pot", mag_ratio<1, 2> * gallon> {} pottle;
inline constexpr struct quart : named_unit<"qt", mag_ratio<1, 2> * pottle> {} quart;
inline constexpr struct pint : named_unit<"pt", mag_ratio<1, 2> * quart> {} pint;
inline constexpr struct cup : named_unit<"c", mag_ratio<1, 2> * pint> {} cup;
inline constexpr struct gill : named_unit<"gi", mag_ratio<1, 2> * cup> {} gill;
inline constexpr struct fluid_ounce : named_unit<"fl oz", mag_ratio<1, 4> * gill> {} fluid_ounce;
inline constexpr struct tablespoon : named_unit<"tbsp", mag_ratio<1, 2> * fluid_ounce> {} tablespoon;
inline constexpr struct shot : named_unit<"jig", mag<3> * tablespoon> {} shot;
inline constexpr struct teaspoon : named_unit<"tsp", mag<ratio{1, 3}> * tablespoon> {} teaspoon;
inline constexpr struct minim : named_unit<"min", mag<ratio{1, 80}> * teaspoon> {} minim;
inline constexpr struct teaspoon : named_unit<"tsp", mag_ratio<1, 3> * tablespoon> {} teaspoon;
inline constexpr struct minim : named_unit<"min", mag_ratio<1, 80> * teaspoon> {} minim;
inline constexpr struct fluid_dram : named_unit<"fl dr", mag<60> * minim> {} fluid_dram;
inline constexpr struct barrel : named_unit<"bbl", mag<ratio{315, 10}> * gallon> {} barrel;
inline constexpr struct oil_barrel : named_unit<"bbl", mag<ratio{4, 3}> * barrel> {} oil_barrel;
inline constexpr struct barrel : named_unit<"bbl", mag_ratio<315, 10> * gallon> {} barrel;
inline constexpr struct oil_barrel : named_unit<"bbl", mag_ratio<4, 3> * barrel> {} oil_barrel;
inline constexpr struct hogshead : decltype(mag<63> * gallon) {} hogshead;
// https://en.wikipedia.org/wiki/United_States_customary_units#Dry_volume
inline constexpr struct dry_barrel : named_unit<"bbl", mag<7056> * cubic(inch)> {} dry_barrel;
inline constexpr struct bushel : named_unit<"bu", mag<ratio{3'523'907'016'688, 100'000'000'000}> * si::litre> {} bushel;
inline constexpr struct peck : named_unit<"pk", mag<ratio{1, 4}> * bushel> {} peck;
inline constexpr struct dry_gallon : named_unit<"gal", mag<ratio{1, 2}> * peck> {} dry_gallon;
inline constexpr struct dry_quart : named_unit<"qt", mag<ratio{1, 4}> * dry_gallon> {} dry_quart;
inline constexpr struct dry_pint : named_unit<"pt", mag<ratio{1, 2}> * dry_quart> {} dry_pint;
inline constexpr struct bushel : named_unit<"bu", mag_ratio<3'523'907'016'688, 100'000'000'000> * si::litre> {} bushel;
inline constexpr struct peck : named_unit<"pk", mag_ratio<1, 4> * bushel> {} peck;
inline constexpr struct dry_gallon : named_unit<"gal", mag_ratio<1, 2> * peck> {} dry_gallon;
inline constexpr struct dry_quart : named_unit<"qt", mag_ratio<1, 4> * dry_gallon> {} dry_quart;
inline constexpr struct dry_pint : named_unit<"pt", mag_ratio<1, 2> * dry_quart> {} dry_pint;
// https://en.wikipedia.org/wiki/United_States_customary_units#Mass_and_Weight
// https://en.wikipedia.org/wiki/Avoirdupois_system#American_customary_system
@ -112,11 +112,11 @@ inline constexpr struct troy_once : named_unit<"oz t", mag<20> * pennyweight> {}
inline constexpr struct troy_pound : named_unit<"lb t", mag<12> * troy_once> {} troy_pound;
// https://en.wikipedia.org/wiki/Inch_of_mercury
inline constexpr struct inch_of_mercury : named_unit<"inHg", mag<ratio(3'386'389, 1'000)> * si::pascal> {} inch_of_mercury;
inline constexpr struct inch_of_mercury : named_unit<"inHg", mag_ratio<3'386'389, 1'000> * si::pascal> {} inch_of_mercury;
// https://en.wikipedia.org/wiki/United_States_customary_units#Temperature
inline constexpr struct zeroth_degree_Fahrenheit : relative_point_origin<si::zeroth_degree_Celsius - 32 * (mag<ratio{5, 9}> * si::degree_Celsius)> {} zeroth_degree_Fahrenheit;
inline constexpr struct degree_Fahrenheit : named_unit<symbol_text{u8"°F", "`F"}, mag<ratio{5, 9}> * si::degree_Celsius, zeroth_degree_Fahrenheit> {} degree_Fahrenheit;
inline constexpr struct zeroth_degree_Fahrenheit : relative_point_origin<si::zeroth_degree_Celsius - 32 * (mag_ratio<5, 9> * si::degree_Celsius)> {} zeroth_degree_Fahrenheit;
inline constexpr struct degree_Fahrenheit : named_unit<symbol_text{u8"°F", "`F"}, mag_ratio<5, 9> * si::degree_Celsius, zeroth_degree_Fahrenheit> {} degree_Fahrenheit;
// clang-format on

View File

@ -24,7 +24,7 @@
namespace {
using namespace mp_units;
using namespace mp_units::detail;
static_assert(ratio(2, 4) == ratio(1, 2));

View File

@ -69,7 +69,7 @@ static_assert(can_not_be_prefixed<si::milli_, si::kilogram>);
static_assert(can_not_be_prefixed<si::milli_, si::hectare>);
static_assert(can_not_be_prefixed<si::milli_, si::kilo<si::metre>>);
static_assert(can_not_be_prefixed<si::milli_, si::metre / si::second>);
static_assert(can_not_be_prefixed<si::milli_, mag<ratio{1, 60}> * si::degree>);
static_assert(can_not_be_prefixed<si::milli_, mag_ratio<1, 60> * si::degree>);
// coherent SI units are checked in isq_test.cpp

View File

@ -107,7 +107,7 @@ static_assert(unit_symbol(mag<100> * metre) == "× 10² m");
static_assert(unit_symbol<unit_symbol_formatting{.encoding = ascii}>(mag<100> * metre) == "x 10^2 m");
static_assert(unit_symbol(mag<60> * second) == "[6 × 10¹] s");
static_assert(unit_symbol<unit_symbol_formatting{.encoding = ascii}>(mag<60> * second) == "[6 x 10^1] s");
static_assert(unit_symbol(mag<ratio{1, 18}> * metre / second) == "[1/18] m/s");
static_assert(unit_symbol(mag_ratio<1, 18> * metre / second) == "[1/18] m/s");
// derived units
static_assert(unit_symbol(one) == "");

View File

@ -73,14 +73,14 @@ inline constexpr struct minute_ : named_unit<"min", mag<60> * second> {} minute;
inline constexpr struct hour_ : named_unit<"h", mag<60> * minute> {} hour;
inline constexpr struct degree_ : named_unit<symbol_text{u8"°", "deg"}, mag_pi / mag<180> * radian> {} degree;
inline constexpr struct yard_ : named_unit<"yd", mag<ratio{9'144, 10'000}> * metre> {} yard;
inline constexpr struct yard_ : named_unit<"yd", mag_ratio<9'144, 10'000> * metre> {} yard;
inline constexpr struct mile_ : named_unit<"mi", mag<1760> * yard> {} mile;
inline constexpr struct kilometre_ : decltype(si::kilo<metre>) {} kilometre;
inline constexpr struct kilojoule_ : decltype(si::kilo<joule>) {} kilojoule;
// physical constant units
inline constexpr struct standard_gravity_ : named_unit<symbol_text{u8"g₀", "g_0"}, mag<ratio{980'665, 100'000}> * metre / square(second)> {} standard_gravity;
inline constexpr struct standard_gravity_ : named_unit<symbol_text{u8"g₀", "g_0"}, mag_ratio<980'665, 100'000> * metre / square(second)> {} standard_gravity;
inline constexpr struct speed_of_light_in_vacuum_ : named_unit<"c", mag<299'792'458> * metre / second> {} speed_of_light_in_vacuum;
// clang-format on
@ -185,7 +185,7 @@ static_assert(is_of_type<nu_second / nu_second, one_>);
static_assert(is_of_type<standard_gravity, standard_gravity_>);
static_assert(
is_of_type<get_canonical_unit(standard_gravity).reference_unit, derived_unit<metre_, per<power<second_, 2>>>>);
static_assert(get_canonical_unit(standard_gravity).mag == mag<ratio{980'665, 100'000}>);
static_assert(get_canonical_unit(standard_gravity).mag == mag_ratio<980'665, 100'000>);
static_assert(convertible(standard_gravity, standard_gravity));
static_assert(convertible(standard_gravity, metre / square(second)));
static_assert(standard_gravity == standard_gravity);
@ -356,7 +356,7 @@ static_assert(get_canonical_unit(km_per_s).mag == mag<1000>);
constexpr auto km_per_h = kilometre / hour;
static_assert(is_of_type<km_per_h, derived_unit<kilometre_, per<hour_>>>);
static_assert(is_of_type<get_canonical_unit(km_per_h).reference_unit, derived_unit<metre_, per<second_>>>);
static_assert(get_canonical_unit(km_per_h).mag == mag<ratio{1000, 3600}>);
static_assert(get_canonical_unit(km_per_h).mag == mag_ratio<1000, 3600>);
static_assert(is_of_type<get_canonical_unit(inverse(metre)).reference_unit, derived_unit<one_, per<metre_>>>);
static_assert(is_of_type<get_canonical_unit(inverse(hertz)).reference_unit, second_>);
@ -368,7 +368,7 @@ static_assert(
static_assert(
is_of_type<get_canonical_unit(standard_gravity).reference_unit, derived_unit<metre_, per<power<second_, 2>>>>);
static_assert(get_canonical_unit(standard_gravity).mag == mag<ratio{980'665, 100'000}>);
static_assert(get_canonical_unit(standard_gravity).mag == mag_ratio<980'665, 100'000>);
static_assert(is_of_type<get_canonical_unit(standard_gravity* gram).reference_unit,
derived_unit<gram_, metre_, per<power<second_, 2>>>>);
static_assert(is_of_type<get_canonical_unit(standard_gravity / speed_of_light_in_vacuum).reference_unit,
@ -378,17 +378,17 @@ static_assert(is_of_type<get_canonical_unit(standard_gravity / speed_of_light_in
constexpr auto u1 = mag<1000> * kilometre / hour;
static_assert(is_of_type<u1, scaled_unit<mag<1000>, derived_unit<kilometre_, per<hour_>>>>);
static_assert(is_of_type<get_canonical_unit(u1).reference_unit, derived_unit<metre_, per<second_>>>);
static_assert(get_canonical_unit(u1).mag == mag<ratio{1'000'000, 3'600}>);
static_assert(get_canonical_unit(u1).mag == mag_ratio<1'000'000, 3'600>);
constexpr auto u2 = mag<1000> * (kilometre / hour);
static_assert(is_of_type<u2, scaled_unit<mag<1000>, derived_unit<kilometre_, per<hour_>>>>);
static_assert(is_of_type<get_canonical_unit(u2).reference_unit, derived_unit<metre_, per<second_>>>);
static_assert(get_canonical_unit(u2).mag == mag<ratio{1'000'000, 3'600}>);
static_assert(get_canonical_unit(u2).mag == mag_ratio<1'000'000, 3'600>);
constexpr auto u3 = one / hour * (mag<1000> * kilometre);
static_assert(is_of_type<u3, scaled_unit<mag<1000>, derived_unit<kilometre_, per<hour_>>>>);
static_assert(is_of_type<get_canonical_unit(u3).reference_unit, derived_unit<metre_, per<second_>>>);
static_assert(get_canonical_unit(u3).mag == mag<ratio{1'000'000, 3'600}>);
static_assert(get_canonical_unit(u3).mag == mag_ratio<1'000'000, 3'600>);
template<auto& s>
concept invalid_operations = requires {
@ -448,7 +448,7 @@ static_assert(convertible(si::kilo<metre>, kilometre));
static_assert(convertible(mag<1000> * metre, si::kilo<metre>));
static_assert(convertible(mag<1000> * metre, kilometre));
static_assert(mag<60> * metre / second == metre / (mag<ratio{1, 60}> * second));
static_assert(mag<60> * metre / second == metre / (mag_ratio<1, 60> * second));
static_assert(metre != kilometre);
static_assert(convertible(metre, kilometre));
@ -533,11 +533,11 @@ static_assert(is_of_type<common_unit(yard, mile), yard_>);
static_assert(is_of_type<common_unit(mile, yard), yard_>);
// TODO The below have long/unreadable magnitude types
static_assert(is_of_type<common_unit(kilometre / hour, metre / second),
scaled_unit<mag<ratio{1, 18}>, derived_unit<metre_, per<second_>>>>);
scaled_unit<mag_ratio<1, 18>, derived_unit<metre_, per<second_>>>>);
static_assert(is_of_type<common_unit(metre / second, kilometre / hour),
scaled_unit<mag<ratio{1, 18}>, derived_unit<metre_, per<second_>>>>);
static_assert(is_of_type<common_unit(kilometre, mile), scaled_unit<mag<ratio{8, 125}>, metre_>>);
static_assert(is_of_type<common_unit(mile, kilometre), scaled_unit<mag<ratio{8, 125}>, metre_>>);
scaled_unit<mag_ratio<1, 18>, derived_unit<metre_, per<second_>>>>);
static_assert(is_of_type<common_unit(kilometre, mile), scaled_unit<mag_ratio<8, 125>, metre_>>);
static_assert(is_of_type<common_unit(mile, kilometre), scaled_unit<mag_ratio<8, 125>, metre_>>);
static_assert(is_of_type<common_unit(speed_of_light_in_vacuum, metre / second), derived_unit<metre_, per<second_>>>);
} // namespace