mirror of
https://github.com/mpusz/mp-units.git
synced 2025-08-04 12:54:25 +02:00
Merge branch 'master' of github.com:mpusz/units
This commit is contained in:
@@ -33,7 +33,7 @@ using namespace units;
|
||||
namespace fps {
|
||||
|
||||
struct foot : named_unit<foot, "ft"> {};
|
||||
struct yard : named_scaled_unit<yard, "yd", as_magnitude<3>(), foot> {};
|
||||
struct yard : named_scaled_unit<yard, "yd", mag<3>(), foot> {};
|
||||
|
||||
struct dim_length : base_dimension<"L", foot> {};
|
||||
|
||||
@@ -54,8 +54,8 @@ using length = quantity<dim_length, U, Rep>;
|
||||
|
||||
namespace fps {
|
||||
|
||||
struct foot : named_scaled_unit<foot, "ft", as_magnitude<ratio(3'048, 1'000, -1)>(), metre> {};
|
||||
struct yard : named_scaled_unit<yard, "yd", as_magnitude<3>(), foot> {};
|
||||
struct foot : named_scaled_unit<foot, "ft", mag<ratio{3'048, 10'000}>(), metre> {};
|
||||
struct yard : named_scaled_unit<yard, "yd", mag<3>(), foot> {};
|
||||
|
||||
struct dim_length : base_dimension<"L", foot> {};
|
||||
|
||||
@@ -94,10 +94,7 @@ void unknown_dimensions()
|
||||
std::cout << si_fps_area << "\n";
|
||||
}
|
||||
|
||||
std::ostream& operator<<(std::ostream& os, const ratio& r)
|
||||
{
|
||||
return os << "ratio{" << r.num << ", " << r.den << ", " << r.exp << "}";
|
||||
}
|
||||
std::ostream& operator<<(std::ostream& os, const ratio& r) { return os << "ratio{" << r.num << ", " << r.den << "}"; }
|
||||
|
||||
template<Unit U>
|
||||
std::ostream& operator<<(std::ostream& os, const U& u)
|
||||
|
@@ -39,8 +39,7 @@ inline constexpr bool compatible_units<exponent_list<Es...>, Us...> = (UnitOf<Us
|
||||
template<Unit... Us, typename... Es>
|
||||
constexpr Magnitude auto derived_mag(exponent_list<Es...>)
|
||||
{
|
||||
return (as_magnitude<1>() * ... *
|
||||
pow<ratio{Es::num, Es::den}>(Us::mag / dimension_unit<typename Es::dimension>::mag));
|
||||
return (mag<1>() * ... * pow<ratio{Es::num, Es::den}>(Us::mag / dimension_unit<typename Es::dimension>::mag));
|
||||
}
|
||||
|
||||
template<DerivedDimension D, Unit... Us>
|
||||
|
@@ -39,108 +39,20 @@ template<typename T>
|
||||
return v < 0 ? -v : v;
|
||||
}
|
||||
|
||||
// the following functions enable gcd and related computations on ratios
|
||||
// with exponents. They avoid overflow. Further information here:
|
||||
// https://github.com/mpusz/units/issues/62#issuecomment-588152833
|
||||
|
||||
// Computes (a * b) mod m relies on unsigned integer arithmetic, should not
|
||||
// overflow
|
||||
[[nodiscard]] constexpr std::uint64_t mulmod(std::uint64_t a, std::uint64_t b, std::uint64_t m)
|
||||
{
|
||||
std::uint64_t res = 0;
|
||||
|
||||
if (b >= m) {
|
||||
if (m > UINT64_MAX / 2u) {
|
||||
b -= m;
|
||||
} else {
|
||||
b %= m;
|
||||
}
|
||||
}
|
||||
|
||||
while (a != 0) {
|
||||
if (a & 1) {
|
||||
if (b >= m - res) {
|
||||
res -= m;
|
||||
}
|
||||
res += b;
|
||||
}
|
||||
a >>= 1;
|
||||
|
||||
std::uint64_t temp_b = b;
|
||||
if (b >= m - b) {
|
||||
temp_b -= m;
|
||||
}
|
||||
b += temp_b;
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
// Calculates (a ^ e) mod m , should not overflow.
|
||||
[[nodiscard]] constexpr std::uint64_t modpow(std::uint64_t a, std::uint64_t e, std::uint64_t m)
|
||||
{
|
||||
a %= m;
|
||||
std::uint64_t result = 1;
|
||||
|
||||
while (e > 0) {
|
||||
if (e & 1) {
|
||||
result = mulmod(result, a, m);
|
||||
}
|
||||
a = mulmod(a, a, m);
|
||||
e >>= 1;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
// gcd(a * 10 ^ e, b), should not overflow
|
||||
[[nodiscard]] constexpr std::intmax_t gcdpow(std::intmax_t a, std::intmax_t e, std::intmax_t b) noexcept
|
||||
{
|
||||
assert(a > 0);
|
||||
assert(e >= 0);
|
||||
assert(b > 0);
|
||||
|
||||
// gcd(i, j) = gcd(j, i mod j) for j != 0 Euclid;
|
||||
//
|
||||
// gcd(a 10^e, b) = gcd(b, a 10^e mod b)
|
||||
//
|
||||
// (a 10^e) mod b -> [ (a mod b) (10^e mod b) ] mod b
|
||||
|
||||
return std::gcd(
|
||||
b, static_cast<std::intmax_t>(mulmod(static_cast<std::uint64_t>(a % b),
|
||||
modpow(10, static_cast<std::uint64_t>(e), static_cast<std::uint64_t>(b)),
|
||||
static_cast<std::uint64_t>(b))));
|
||||
}
|
||||
|
||||
constexpr void cwap(std::intmax_t& lhs, std::intmax_t& rhs)
|
||||
{
|
||||
std::intmax_t tmp = lhs;
|
||||
lhs = rhs;
|
||||
rhs = tmp;
|
||||
}
|
||||
|
||||
// Computes the rational gcd of n1/d1 x 10^e1 and n2/d2 x 10^e2
|
||||
[[nodiscard]] constexpr auto gcd_frac(std::intmax_t n1, std::intmax_t d1, std::intmax_t e1, std::intmax_t n2,
|
||||
std::intmax_t d2, std::intmax_t e2) noexcept
|
||||
// Computes the rational gcd of n1/d1 and n2/d2
|
||||
[[nodiscard]] constexpr auto gcd_frac(std::intmax_t n1, std::intmax_t d1, std::intmax_t n2, std::intmax_t d2) noexcept
|
||||
{
|
||||
// Short cut for equal ratios
|
||||
if (n1 == n2 && d1 == d2 && e1 == e2) {
|
||||
return std::array{n1, d1, e1};
|
||||
if (n1 == n2 && d1 == d2) {
|
||||
return std::array{n1, d1};
|
||||
}
|
||||
|
||||
if (e2 > e1) {
|
||||
detail::cwap(n1, n2);
|
||||
detail::cwap(d1, d2);
|
||||
detail::cwap(e1, e2);
|
||||
}
|
||||
|
||||
std::intmax_t exp = e2; // minimum
|
||||
|
||||
// gcd(a/b,c/d) = gcd(a⋅d, c⋅b) / b⋅d
|
||||
|
||||
assert(std::numeric_limits<std::intmax_t>::max() / n1 > d2);
|
||||
assert(std::numeric_limits<std::intmax_t>::max() / n2 > d1);
|
||||
|
||||
std::intmax_t num = detail::gcdpow(n1 * d2, e1 - e2, n2 * d1);
|
||||
std::intmax_t num = std::gcd(n1 * d2, n2 * d1);
|
||||
|
||||
assert(std::numeric_limits<std::intmax_t>::max() / d1 > d2);
|
||||
|
||||
@@ -148,29 +60,19 @@ constexpr void cwap(std::intmax_t& lhs, std::intmax_t& rhs)
|
||||
|
||||
std::intmax_t gcd = std::gcd(num, den);
|
||||
|
||||
return std::array{num / gcd, den / gcd, exp};
|
||||
return std::array{num / gcd, den / gcd};
|
||||
}
|
||||
|
||||
constexpr void normalize(std::intmax_t& num, std::intmax_t& den, std::intmax_t& exp)
|
||||
constexpr void normalize(std::intmax_t& num, std::intmax_t& den)
|
||||
{
|
||||
if (num == 0) {
|
||||
den = 1;
|
||||
exp = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
std::intmax_t gcd = std::gcd(num, den);
|
||||
num = num * (den < 0 ? -1 : 1) / gcd;
|
||||
den = detail::abs(den) / gcd;
|
||||
|
||||
while (num % 10 == 0) {
|
||||
num /= 10;
|
||||
++exp;
|
||||
}
|
||||
while (den % 10 == 0) {
|
||||
den /= 10;
|
||||
--exp;
|
||||
}
|
||||
}
|
||||
|
||||
[[nodiscard]] constexpr std::intmax_t safe_multiply(std::intmax_t lhs, std::intmax_t rhs)
|
||||
|
@@ -37,7 +37,7 @@ constexpr auto magnitude_text()
|
||||
{
|
||||
constexpr auto exp10 = extract_power_of_10(M);
|
||||
|
||||
constexpr Magnitude auto base = M / pow<exp10>(as_magnitude<10>());
|
||||
constexpr Magnitude auto base = M / pow<exp10>(mag<10>());
|
||||
constexpr Magnitude auto num = numerator(base);
|
||||
constexpr Magnitude auto den = denominator(base);
|
||||
static_assert(base == num / den, "Printing rational powers, or irrational bases, not yet supported");
|
||||
@@ -72,7 +72,7 @@ constexpr auto magnitude_text()
|
||||
template<Unit U, Magnitude auto M, std::size_t SymbolLen>
|
||||
constexpr auto prefix_or_magnitude_text()
|
||||
{
|
||||
if constexpr (M == as_magnitude<1>()) {
|
||||
if constexpr (M == mag<1>()) {
|
||||
// no ratio/prefix
|
||||
return basic_fixed_string("");
|
||||
} else {
|
||||
|
@@ -34,7 +34,7 @@ namespace units {
|
||||
template<typename Rep, typename Period>
|
||||
struct quantity_like_traits<std::chrono::duration<Rep, Period>> {
|
||||
private:
|
||||
static constexpr auto mag = as_magnitude<ratio(Period::num, Period::den)>();
|
||||
static constexpr auto mag = ::units::mag<ratio(Period::num, Period::den)>();
|
||||
public:
|
||||
using dimension = isq::si::dim_time;
|
||||
using unit = downcast_unit<dimension, mag>;
|
||||
@@ -48,7 +48,7 @@ struct clock_origin : point_origin<isq::si::dim_time> {};
|
||||
template<typename C, typename Rep, typename Period>
|
||||
struct quantity_point_like_traits<std::chrono::time_point<C, std::chrono::duration<Rep, Period>>> {
|
||||
private:
|
||||
static constexpr auto mag = as_magnitude<ratio(Period::num, Period::den)>();
|
||||
static constexpr auto mag = ::units::mag<ratio(Period::num, Period::den)>();
|
||||
public:
|
||||
using origin = clock_origin<C>;
|
||||
using unit = downcast_unit<typename origin::dimension, mag>;
|
||||
@@ -75,12 +75,7 @@ constexpr std::intmax_t pow_10(std::intmax_t v)
|
||||
template<ratio R>
|
||||
constexpr auto to_std_ratio_impl()
|
||||
{
|
||||
if constexpr (R.exp == 0)
|
||||
return std::ratio<R.num, R.den>{};
|
||||
else if constexpr (R.exp > 0)
|
||||
return std::ratio<R.num * pow_10(R.exp), R.den>{};
|
||||
else
|
||||
return std::ratio<R.num, R.den * pow_10(-R.exp)>{};
|
||||
return std::ratio<R.num, R.den>{};
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
|
@@ -31,7 +31,7 @@
|
||||
namespace units {
|
||||
|
||||
struct one : derived_unit<one> {};
|
||||
struct percent : named_scaled_unit<percent, "%", as_magnitude<ratio(1, 100)>(), one> {};
|
||||
struct percent : named_scaled_unit<percent, "%", mag<ratio(1, 100)>(), one> {};
|
||||
|
||||
/**
|
||||
* @brief Dimension one
|
||||
|
@@ -189,9 +189,6 @@ constexpr widen_t<T> compute_base_power(BasePower auto bp)
|
||||
if (bp.power.den != 1) {
|
||||
throw std::invalid_argument{"Rational powers not yet supported"};
|
||||
}
|
||||
if (bp.power.exp < 0) {
|
||||
throw std::invalid_argument{"Unsupported exp value"};
|
||||
}
|
||||
|
||||
if (bp.power.num < 0) {
|
||||
if constexpr (std::is_integral_v<T>) {
|
||||
@@ -201,7 +198,7 @@ constexpr widen_t<T> compute_base_power(BasePower auto bp)
|
||||
}
|
||||
}
|
||||
|
||||
auto power = numerator(bp.power);
|
||||
auto power = bp.power.num;
|
||||
return int_power(static_cast<widen_t<T>>(bp.get_base()), power);
|
||||
}
|
||||
|
||||
@@ -344,7 +341,7 @@ inline constexpr bool is_base_power_pack_valid = all_base_powers_valid<BPs...> &
|
||||
|
||||
constexpr bool is_rational(BasePower auto bp)
|
||||
{
|
||||
return std::is_integral_v<decltype(bp.get_base())> && (bp.power.den == 1) && (bp.power.exp >= 0);
|
||||
return std::is_integral_v<decltype(bp.get_base())> && (bp.power.den == 1);
|
||||
}
|
||||
|
||||
constexpr bool is_integral(BasePower auto bp) { return is_rational(bp) && bp.power.num > 0; }
|
||||
@@ -498,8 +495,8 @@ namespace detail {
|
||||
template<auto BP>
|
||||
constexpr auto integer_part(magnitude<BP>)
|
||||
{
|
||||
constexpr auto power_num = numerator(BP.power);
|
||||
constexpr auto power_den = denominator(BP.power);
|
||||
constexpr auto power_num = BP.power.num;
|
||||
constexpr auto power_den = BP.power.den;
|
||||
|
||||
if constexpr (std::is_integral_v<decltype(BP.get_base())> && (power_num >= power_den)) {
|
||||
constexpr auto largest_integer_power = [=](BasePower auto bp) {
|
||||
@@ -556,7 +553,7 @@ namespace detail {
|
||||
template<auto BP>
|
||||
constexpr auto remove_positive_power(magnitude<BP> m)
|
||||
{
|
||||
if constexpr (numerator(BP.power) < 0) {
|
||||
if constexpr (BP.power.num < 0) {
|
||||
return m;
|
||||
} else {
|
||||
return magnitude<>{};
|
||||
@@ -599,7 +596,7 @@ constexpr auto common_magnitude(magnitude<H1, T1...>, magnitude<H2, T2...>)
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// `as_magnitude()` implementation.
|
||||
// `mag()` implementation.
|
||||
|
||||
// Sometimes we need to give the compiler a "shortcut" when factorizing large numbers (specifically, numbers whose
|
||||
// _first factor_ is very large). If we don't, we can run into limits on the number of constexpr steps or iterations.
|
||||
@@ -650,10 +647,19 @@ inline constexpr auto prime_factorization_v = prime_factorization<N>::value;
|
||||
*/
|
||||
template<ratio R>
|
||||
requires(R.num > 0)
|
||||
constexpr Magnitude auto as_magnitude()
|
||||
constexpr Magnitude auto mag()
|
||||
{
|
||||
return pow<ratio{R.exp}>(detail::prime_factorization_v<10>) * detail::prime_factorization_v<R.num> /
|
||||
detail::prime_factorization_v<R.den>;
|
||||
return detail::prime_factorization_v<R.num> / detail::prime_factorization_v<R.den>;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Create a Magnitude which is some rational number raised to a rational power.
|
||||
*/
|
||||
template<ratio Base, ratio Pow>
|
||||
requires(Base.num > 0)
|
||||
constexpr Magnitude auto mag_power()
|
||||
{
|
||||
return pow<Pow>(mag<Base>());
|
||||
}
|
||||
|
||||
namespace detail {
|
||||
@@ -663,7 +669,7 @@ constexpr ratio get_power(T base, magnitude<BPs...>)
|
||||
return ((BPs.get_base() == base ? BPs.power : ratio{0}) + ... + ratio{0});
|
||||
}
|
||||
|
||||
constexpr std::intmax_t integer_part(ratio r) { return numerator(r) / denominator(r); }
|
||||
constexpr std::intmax_t integer_part(ratio r) { return r.num / r.den; }
|
||||
|
||||
constexpr std::intmax_t extract_power_of_10(Magnitude auto m)
|
||||
{
|
||||
|
@@ -444,7 +444,7 @@ public:
|
||||
};
|
||||
|
||||
// CTAD
|
||||
#if !UNITS_COMP_CLANG || UNITS_COMP_CLANG > 15
|
||||
#if !UNITS_COMP_CLANG || UNITS_COMP_CLANG > 16
|
||||
template<typename D, typename U, typename Rep>
|
||||
explicit(false) quantity(Rep&&)->quantity<D, U, Rep>;
|
||||
#endif
|
||||
|
@@ -43,42 +43,28 @@ constexpr ratio inverse(const ratio& r);
|
||||
/**
|
||||
* @brief Provides compile-time rational arithmetic support.
|
||||
*
|
||||
* This class is really similar to @c std::ratio but gets an additional `Exp`
|
||||
* template parameter that defines the exponent of the ratio. Another important
|
||||
* difference is the fact that the objects of that class are used as class NTTPs
|
||||
* rather then a type template parameter kind.
|
||||
* 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.
|
||||
*/
|
||||
struct ratio {
|
||||
std::intmax_t num;
|
||||
std::intmax_t den;
|
||||
std::intmax_t exp;
|
||||
|
||||
constexpr explicit(false) ratio(std::intmax_t n, std::intmax_t d = 1, std::intmax_t e = 0) : num(n), den(d), exp(e)
|
||||
constexpr explicit(false) ratio(std::intmax_t n, std::intmax_t d = 1) : num(n), den(d)
|
||||
{
|
||||
gsl_Expects(den != 0);
|
||||
detail::normalize(num, den, exp);
|
||||
detail::normalize(num, den);
|
||||
}
|
||||
|
||||
[[nodiscard]] friend constexpr bool operator==(const ratio&, const ratio&) = default;
|
||||
|
||||
[[nodiscard]] friend constexpr auto operator<=>(const ratio& lhs, const ratio& rhs) { return (lhs - rhs).num <=> 0; }
|
||||
|
||||
[[nodiscard]] friend constexpr ratio operator-(const ratio& r) { return ratio(-r.num, r.den, r.exp); }
|
||||
[[nodiscard]] friend constexpr ratio operator-(const ratio& r) { return ratio(-r.num, r.den); }
|
||||
|
||||
[[nodiscard]] friend constexpr ratio operator+(ratio lhs, ratio rhs)
|
||||
{
|
||||
// First, get the inputs into a common exponent.
|
||||
const auto common_exp = std::min(lhs.exp, rhs.exp);
|
||||
auto commonify = [common_exp](ratio& r) {
|
||||
while (r.exp > common_exp) {
|
||||
r.num *= 10;
|
||||
--r.exp;
|
||||
}
|
||||
};
|
||||
commonify(lhs);
|
||||
commonify(rhs);
|
||||
|
||||
return ratio{lhs.num * rhs.den + lhs.den * rhs.num, lhs.den * rhs.den, common_exp};
|
||||
return ratio{lhs.num * rhs.den + lhs.den * rhs.num, lhs.den * rhs.den};
|
||||
}
|
||||
|
||||
[[nodiscard]] friend constexpr ratio operator-(const ratio& lhs, const ratio& rhs) { return lhs + (-rhs); }
|
||||
@@ -88,96 +74,27 @@ struct ratio {
|
||||
const std::intmax_t gcd1 = std::gcd(lhs.num, rhs.den);
|
||||
const std::intmax_t gcd2 = std::gcd(rhs.num, lhs.den);
|
||||
return ratio(detail::safe_multiply(lhs.num / gcd1, rhs.num / gcd2),
|
||||
detail::safe_multiply(lhs.den / gcd2, rhs.den / gcd1), lhs.exp + rhs.exp);
|
||||
detail::safe_multiply(lhs.den / gcd2, rhs.den / gcd1));
|
||||
}
|
||||
|
||||
[[nodiscard]] friend constexpr ratio operator/(const ratio& lhs, const ratio& rhs) { return lhs * inverse(rhs); }
|
||||
|
||||
[[nodiscard]] friend constexpr std::intmax_t numerator(const ratio& r)
|
||||
{
|
||||
std::intmax_t true_num = r.num;
|
||||
for (auto i = r.exp; i > 0; --i) {
|
||||
true_num *= 10;
|
||||
}
|
||||
return true_num;
|
||||
}
|
||||
|
||||
[[nodiscard]] friend constexpr std::intmax_t denominator(const ratio& r)
|
||||
{
|
||||
std::intmax_t true_den = r.den;
|
||||
for (auto i = r.exp; i < 0; ++i) {
|
||||
true_den *= 10;
|
||||
}
|
||||
return true_den;
|
||||
}
|
||||
};
|
||||
|
||||
[[nodiscard]] constexpr ratio inverse(const ratio& r) { return ratio(r.den, r.num, -r.exp); }
|
||||
[[nodiscard]] constexpr ratio inverse(const ratio& r) { return ratio(r.den, r.num); }
|
||||
|
||||
[[nodiscard]] constexpr bool is_integral(const ratio& r)
|
||||
{
|
||||
if (r.exp < 0) {
|
||||
return false;
|
||||
} else {
|
||||
return detail::gcdpow(r.num, r.exp, r.den) == r.den;
|
||||
}
|
||||
}
|
||||
[[nodiscard]] constexpr bool is_integral(const ratio& r) { return r.num % r.den == 0; }
|
||||
|
||||
namespace detail {
|
||||
|
||||
[[nodiscard]] constexpr auto make_exp_align(const ratio& r, std::intmax_t alignment)
|
||||
{
|
||||
gsl_Expects(alignment > 0);
|
||||
const std::intmax_t rem = r.exp % alignment;
|
||||
|
||||
if (rem == 0) { // already aligned
|
||||
return std::array{r.num, r.den, r.exp};
|
||||
}
|
||||
|
||||
if (r.exp > 0) { // remainder is positive
|
||||
return std::array{r.num * ipow10(rem), r.den, r.exp - rem};
|
||||
}
|
||||
|
||||
// remainder is negative
|
||||
return std::array{r.num, r.den * ipow10(-rem), r.exp - rem};
|
||||
}
|
||||
|
||||
template<std::intmax_t N>
|
||||
requires gt_zero<N>
|
||||
[[nodiscard]] constexpr ratio root(const ratio& r)
|
||||
{
|
||||
if constexpr (N == 1) {
|
||||
return r;
|
||||
} else {
|
||||
if (r.num == 0) {
|
||||
return ratio(0);
|
||||
}
|
||||
|
||||
const auto aligned = make_exp_align(r, N);
|
||||
return ratio(iroot<N>(aligned[0]), iroot<N>(aligned[1]), aligned[2] / N);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
|
||||
template<std::intmax_t Num, std::intmax_t Den = 1>
|
||||
requires detail::non_zero<Den>
|
||||
template<std::intmax_t Num>
|
||||
[[nodiscard]] constexpr ratio pow(const ratio& r)
|
||||
{
|
||||
if constexpr (Num == 0) {
|
||||
return ratio(1);
|
||||
} else if constexpr (Num == Den) {
|
||||
} else if constexpr (Num == 1) {
|
||||
return r;
|
||||
} else {
|
||||
// simplify factors first and compute power for positive exponent
|
||||
constexpr std::intmax_t gcd = std::gcd(Num, Den);
|
||||
constexpr std::intmax_t num = detail::abs(Num / gcd);
|
||||
constexpr std::intmax_t den = detail::abs(Den / gcd);
|
||||
const ratio result = detail::pow_impl<Num>(r);
|
||||
|
||||
// integer root loses precision so do pow first
|
||||
const ratio result = detail::root<den>(detail::pow_impl<num>(r));
|
||||
|
||||
if constexpr (Num * Den < 0) { // account for negative exponent
|
||||
if constexpr (Num < 0) { // account for negative exponent
|
||||
return inverse(result);
|
||||
} else {
|
||||
return result;
|
||||
@@ -185,15 +102,11 @@ template<std::intmax_t Num, std::intmax_t Den = 1>
|
||||
}
|
||||
}
|
||||
|
||||
[[nodiscard]] constexpr ratio sqrt(const ratio& r) { return pow<1, 2>(r); }
|
||||
|
||||
[[nodiscard]] constexpr ratio cbrt(const ratio& r) { return pow<1, 3>(r); }
|
||||
|
||||
// common_ratio
|
||||
[[nodiscard]] constexpr ratio common_ratio(const ratio& r1, const ratio& r2)
|
||||
{
|
||||
const auto res = detail::gcd_frac(r1.num, r1.den, r1.exp, r2.num, r2.den, r2.exp);
|
||||
return ratio(res[0], res[1], res[2]);
|
||||
const auto res = detail::gcd_frac(r1.num, r1.den, r2.num, r2.den);
|
||||
return ratio(res[0], res[1]);
|
||||
}
|
||||
|
||||
} // namespace units
|
||||
|
@@ -80,7 +80,7 @@ struct same_unit_reference : is_same<typename U1::reference, typename U2::refere
|
||||
* @tparam Symbol a short text representation of the unit
|
||||
*/
|
||||
template<typename Child, basic_symbol_text Symbol>
|
||||
struct named_unit : downcast_dispatch<Child, scaled_unit<as_magnitude<1>(), Child>> {
|
||||
struct named_unit : downcast_dispatch<Child, scaled_unit<mag<1>(), Child>> {
|
||||
static constexpr auto symbol = Symbol;
|
||||
};
|
||||
|
||||
@@ -126,7 +126,7 @@ struct prefixed_unit : downcast_dispatch<Child, scaled_unit<P::mag * U::mag, typ
|
||||
* @tparam Child inherited class type used by the downcasting facility (CRTP Idiom)
|
||||
*/
|
||||
template<typename Child>
|
||||
struct derived_unit : downcast_dispatch<Child, scaled_unit<as_magnitude<1>(), Child>> {};
|
||||
struct derived_unit : downcast_dispatch<Child, scaled_unit<mag<1>(), Child>> {};
|
||||
|
||||
/**
|
||||
* @brief A unit with a deduced ratio and symbol
|
||||
|
@@ -26,13 +26,13 @@
|
||||
|
||||
namespace units::isq::iec80000 {
|
||||
|
||||
struct kibi : prefix<kibi, "Ki", pow<10>(as_magnitude<2>())> {};
|
||||
struct mebi : prefix<mebi, "Mi", pow<20>(as_magnitude<2>())> {};
|
||||
struct gibi : prefix<gibi, "Gi", pow<30>(as_magnitude<2>())> {};
|
||||
struct tebi : prefix<tebi, "Ti", pow<40>(as_magnitude<2>())> {};
|
||||
struct pebi : prefix<pebi, "Pi", pow<50>(as_magnitude<2>())> {};
|
||||
struct exbi : prefix<exbi, "Ei", pow<60>(as_magnitude<2>())> {};
|
||||
struct zebi : prefix<zebi, "Zi", pow<70>(as_magnitude<2>())> {};
|
||||
struct yobi : prefix<yobi, "Yi", pow<80>(as_magnitude<2>())> {};
|
||||
struct kibi : prefix<kibi, "Ki", pow<10>(mag<2>())> {};
|
||||
struct mebi : prefix<mebi, "Mi", pow<20>(mag<2>())> {};
|
||||
struct gibi : prefix<gibi, "Gi", pow<30>(mag<2>())> {};
|
||||
struct tebi : prefix<tebi, "Ti", pow<40>(mag<2>())> {};
|
||||
struct pebi : prefix<pebi, "Pi", pow<50>(mag<2>())> {};
|
||||
struct exbi : prefix<exbi, "Ei", pow<60>(mag<2>())> {};
|
||||
struct zebi : prefix<zebi, "Zi", pow<70>(mag<2>())> {};
|
||||
struct yobi : prefix<yobi, "Yi", pow<80>(mag<2>())> {};
|
||||
|
||||
} // namespace units::isq::iec80000
|
||||
|
@@ -53,7 +53,7 @@ struct tebibit : prefixed_unit<tebibit, tebi, bit> {};
|
||||
struct pebibit : prefixed_unit<pebibit, pebi, bit> {};
|
||||
struct exbibit : prefixed_unit<exbibit, exbi, bit> {};
|
||||
|
||||
struct byte : named_scaled_unit<byte, "B", as_magnitude<8>(), bit> {};
|
||||
struct byte : named_scaled_unit<byte, "B", mag<8>(), bit> {};
|
||||
|
||||
struct kilobyte : prefixed_unit<kilobyte, si::kilo, byte> {};
|
||||
struct megabyte : prefixed_unit<megabyte, si::mega, byte> {};
|
||||
|
@@ -40,7 +40,7 @@ namespace units::isq::si::fps {
|
||||
struct poundal : named_unit<poundal, "pdl"> {};
|
||||
|
||||
// https://en.wikipedia.org/wiki/Pound_(force)
|
||||
struct pound_force : named_scaled_unit<pound_force, "lbf", as_magnitude<ratio(32'174'049, 1'000'000)>(), poundal> {};
|
||||
struct pound_force : named_scaled_unit<pound_force, "lbf", mag<ratio(32'174'049, 1'000'000)>(), poundal> {};
|
||||
|
||||
struct kilopound_force : prefixed_unit<kilopound_force, si::kilo, pound_force> {};
|
||||
|
||||
|
@@ -48,7 +48,7 @@ struct thousandth : alias_unit<thou, "thou"> {};
|
||||
|
||||
struct kiloyard : prefixed_unit<kiloyard, si::kilo, yard> {};
|
||||
|
||||
struct nautical_mile : named_scaled_unit<nautical_mile, "nmi", as_magnitude<2'000>(), yard> {};
|
||||
struct nautical_mile : named_scaled_unit<nautical_mile, "nmi", mag<2'000>(), yard> {};
|
||||
|
||||
struct dim_length : isq::dim_length<foot> {};
|
||||
|
||||
|
@@ -35,28 +35,28 @@
|
||||
namespace units::isq::si::fps {
|
||||
|
||||
// https://en.wikipedia.org/wiki/Pound_(mass)
|
||||
struct pound : named_scaled_unit<pound, "lb", as_magnitude<ratio(45'359'237, 100'000'000)>(), si::kilogram> {};
|
||||
struct pound : named_scaled_unit<pound, "lb", mag<ratio(45'359'237, 100'000'000)>(), si::kilogram> {};
|
||||
|
||||
struct dim_mass : isq::dim_mass<pound> {};
|
||||
|
||||
template<UnitOf<dim_mass> U, Representation Rep = double>
|
||||
using mass = quantity<dim_mass, U, Rep>;
|
||||
|
||||
struct grain : named_scaled_unit<grain, "gr", as_magnitude<ratio(1, 7000)>(), pound> {};
|
||||
struct grain : named_scaled_unit<grain, "gr", mag<ratio(1, 7000)>(), pound> {};
|
||||
|
||||
struct dram : named_scaled_unit<dram, "dr", as_magnitude<ratio(1, 256)>(), pound> {};
|
||||
struct dram : named_scaled_unit<dram, "dr", mag<ratio(1, 256)>(), pound> {};
|
||||
|
||||
struct ounce : named_scaled_unit<ounce, "oz", as_magnitude<ratio(1, 16)>(), pound> {};
|
||||
struct ounce : named_scaled_unit<ounce, "oz", mag<ratio(1, 16)>(), pound> {};
|
||||
|
||||
struct stone : named_scaled_unit<stone, "st", as_magnitude<14>(), pound> {};
|
||||
struct stone : named_scaled_unit<stone, "st", mag<14>(), pound> {};
|
||||
|
||||
struct quarter : named_scaled_unit<quarter, "qr", as_magnitude<28>(), pound> {};
|
||||
struct quarter : named_scaled_unit<quarter, "qr", mag<28>(), pound> {};
|
||||
|
||||
struct hundredweight : named_scaled_unit<hundredweight, "cwt", as_magnitude<112>(), pound> {};
|
||||
struct hundredweight : named_scaled_unit<hundredweight, "cwt", mag<112>(), pound> {};
|
||||
|
||||
struct short_ton : named_scaled_unit<short_ton, "ton (short)", as_magnitude<2'000>(), pound> {};
|
||||
struct short_ton : named_scaled_unit<short_ton, "ton (short)", mag<2'000>(), pound> {};
|
||||
|
||||
struct long_ton : named_scaled_unit<long_ton, "ton (long)", as_magnitude<2'240>(), pound> {};
|
||||
struct long_ton : named_scaled_unit<long_ton, "ton (long)", mag<2'240>(), pound> {};
|
||||
|
||||
#ifndef UNITS_NO_LITERALS
|
||||
|
||||
|
@@ -42,7 +42,7 @@ struct dim_power : isq::dim_power<dim_power, foot_poundal_per_second, dim_length
|
||||
struct foot_pound_force_per_second :
|
||||
derived_scaled_unit<foot_pound_force_per_second, dim_power, foot, pound_force, second> {};
|
||||
|
||||
struct horse_power : named_scaled_unit<horse_power, "hp", as_magnitude<550>(), foot_pound_force_per_second> {};
|
||||
struct horse_power : named_scaled_unit<horse_power, "hp", mag<550>(), foot_pound_force_per_second> {};
|
||||
|
||||
template<UnitOf<dim_power> U, Representation Rep = double>
|
||||
using power = quantity<dim_power, U, Rep>;
|
||||
|
@@ -44,11 +44,10 @@ template<UnitOf<dim_pressure> U, Representation Rep = double>
|
||||
using pressure = quantity<dim_pressure, U, Rep>;
|
||||
|
||||
struct pound_force_per_foot_sq :
|
||||
named_scaled_unit<pound_force_per_foot_sq, "lbf ft2", as_magnitude<ratio(32'174'049, 1'000'000)>(),
|
||||
poundal_per_foot_sq> {};
|
||||
named_scaled_unit<pound_force_per_foot_sq, "lbf ft2", mag<ratio(32'174'049, 1'000'000)>(), poundal_per_foot_sq> {};
|
||||
|
||||
struct pound_force_per_inch_sq :
|
||||
named_scaled_unit<pound_force_per_inch_sq, "psi", as_magnitude<ratio(1, 144)>(), pound_force_per_foot_sq> {};
|
||||
named_scaled_unit<pound_force_per_inch_sq, "psi", mag<ratio(1, 144)>(), pound_force_per_foot_sq> {};
|
||||
|
||||
struct kilopound_force_per_inch_sq : prefixed_unit<kilopound_force_per_inch_sq, si::kilo, pound_force_per_inch_sq> {};
|
||||
|
||||
|
@@ -37,7 +37,7 @@ namespace units::isq::si::hep {
|
||||
// effective cross-sectional area according to EU council directive 80/181/EEC
|
||||
// https://eur-lex.europa.eu/legal-content/EN/TXT/PDF/?uri=CELEX:01980L0181-20090527#page=10
|
||||
// https://www.fedlex.admin.ch/eli/cc/1994/3109_3109_3109/de
|
||||
struct barn : named_scaled_unit<barn, "b", as_magnitude<ratio(1, 1, -28)>(), square_metre> {};
|
||||
struct barn : named_scaled_unit<barn, "b", mag_power<10, -28>(), square_metre> {};
|
||||
struct yocto_barn : prefixed_unit<yocto_barn, yocto, barn> {};
|
||||
struct zepto_barn : prefixed_unit<zepto_barn, zepto, barn> {};
|
||||
struct atto_barn : prefixed_unit<atto_barn, atto, barn> {};
|
||||
|
@@ -44,7 +44,7 @@ namespace units::isq::si::hep {
|
||||
|
||||
struct eV_per_c2 :
|
||||
named_scaled_unit<eV_per_c2, basic_symbol_text{"eV/c²", "eV/c^2"},
|
||||
as_magnitude<ratio(17'826'619'216'279, 1'000'000'000'000, -35)>(), kilogram> {};
|
||||
mag<ratio(17'826'619'216'279, 1'000'000'000'000)>() * mag_power<10, -35>(), kilogram> {};
|
||||
struct feV_per_c2 : prefixed_unit<feV_per_c2, femto, eV_per_c2> {};
|
||||
struct peV_per_c2 : prefixed_unit<peV_per_c2, pico, eV_per_c2> {};
|
||||
struct neV_per_c2 : prefixed_unit<neV_per_c2, nano, eV_per_c2> {};
|
||||
@@ -60,11 +60,14 @@ struct PeV_per_c2 : prefixed_unit<PeV_per_c2, peta, eV_per_c2> {};
|
||||
struct EeV_per_c2 : prefixed_unit<EeV_per_c2, exa, eV_per_c2> {};
|
||||
struct YeV_per_c2 : prefixed_unit<YeV_per_c2, yotta, eV_per_c2> {};
|
||||
struct electron_mass :
|
||||
named_scaled_unit<eV_per_c2, "m_e", as_magnitude<ratio(9'109'383'701'528, 1'000'000'000'000, -31)>(), kilogram> {};
|
||||
named_scaled_unit<eV_per_c2, "m_e", mag<ratio(9'109'383'701'528, 1'000'000'000'000)>() * mag_power<10, -31>(),
|
||||
kilogram> {};
|
||||
struct proton_mass :
|
||||
named_scaled_unit<eV_per_c2, "m_p", as_magnitude<ratio(1'672'621'923'695, 1'000'000'000'000, -27)>(), kilogram> {};
|
||||
named_scaled_unit<eV_per_c2, "m_p", mag<ratio(1'672'621'923'695, 1'000'000'000'000)>() * mag_power<10, -27>(),
|
||||
kilogram> {};
|
||||
struct neutron_mass :
|
||||
named_scaled_unit<eV_per_c2, "m_n", as_magnitude<ratio(1'674'927'498'049, 1'000'000'000'000, -27)>(), kilogram> {};
|
||||
named_scaled_unit<eV_per_c2, "m_n", mag<ratio(1'674'927'498'049, 1'000'000'000'000)>() * mag_power<10, -27>(),
|
||||
kilogram> {};
|
||||
|
||||
struct dim_mass : isq::dim_mass<eV_per_c2> {};
|
||||
|
||||
|
@@ -41,7 +41,7 @@ namespace units::isq::si::hep {
|
||||
struct kilogram_metre_per_second : derived_unit<kilogram_metre_per_second> {};
|
||||
|
||||
struct eV_per_c :
|
||||
named_scaled_unit<eV_per_c, "eV/c", as_magnitude<ratio(5'344'285'992'678, 1'000'000'000'000, -35)>(),
|
||||
named_scaled_unit<eV_per_c, "eV/c", mag<ratio(5'344'285'992'678, 1'000'000'000'000)>() * mag_power<10, -35>(),
|
||||
kilogram_metre_per_second> {};
|
||||
struct feV_per_c : prefixed_unit<feV_per_c, femto, eV_per_c> {};
|
||||
struct peV_per_c : prefixed_unit<peV_per_c, pico, eV_per_c> {};
|
||||
|
@@ -36,13 +36,13 @@
|
||||
namespace units::isq::si::iau {
|
||||
|
||||
// https://en.wikipedia.org/wiki/Light-year
|
||||
struct light_year : named_scaled_unit<light_year, "ly", as_magnitude<9460730472580800>(), si::metre> {};
|
||||
struct light_year : named_scaled_unit<light_year, "ly", mag<9460730472580800>(), si::metre> {};
|
||||
|
||||
// https://en.wikipedia.org/wiki/Parsec
|
||||
struct parsec : named_scaled_unit<parsec, "pc", as_magnitude<30'856'775'814'913'673>(), si::metre> {};
|
||||
struct parsec : named_scaled_unit<parsec, "pc", mag<30'856'775'814'913'673>(), si::metre> {};
|
||||
|
||||
// https://en.wikipedia.org/wiki/Angstrom
|
||||
struct angstrom : named_scaled_unit<angstrom, "angstrom", as_magnitude<ratio(1, 1, -10)>(), si::metre> {};
|
||||
struct angstrom : named_scaled_unit<angstrom, "angstrom", mag_power<10, -10>(), si::metre> {};
|
||||
|
||||
#ifndef UNITS_NO_LITERALS
|
||||
|
||||
|
@@ -35,10 +35,10 @@
|
||||
namespace units::isq::si::imperial {
|
||||
|
||||
// https://en.wikipedia.org/wiki/Chain_(unit)
|
||||
struct chain : named_scaled_unit<chain, "ch", as_magnitude<22>(), si::international::yard> {};
|
||||
struct chain : named_scaled_unit<chain, "ch", mag<22>(), si::international::yard> {};
|
||||
|
||||
// https://en.wikipedia.org/wiki/Rod_(unit)
|
||||
struct rod : named_scaled_unit<rod, "rd", as_magnitude<ratio(1, 4)>(), chain> {};
|
||||
struct rod : named_scaled_unit<rod, "rd", mag<ratio(1, 4)>(), chain> {};
|
||||
|
||||
#ifndef UNITS_NO_LITERALS
|
||||
|
||||
|
@@ -37,30 +37,30 @@ namespace units::isq::si::international {
|
||||
|
||||
// si::international yard
|
||||
// https://en.wikipedia.org/wiki/International_yard_and_pound
|
||||
struct yard : named_scaled_unit<yard, "yd", as_magnitude<ratio(9'144, 1'000, -1)>(), si::metre> {};
|
||||
struct yard : named_scaled_unit<yard, "yd", mag<ratio{9'144, 10'000}>(), si::metre> {};
|
||||
|
||||
// si::international foot
|
||||
// https://en.wikipedia.org/wiki/Foot_(unit)#International_foot
|
||||
struct foot : named_scaled_unit<foot, "ft", as_magnitude<ratio(1, 3)>(), yard> {};
|
||||
struct foot : named_scaled_unit<foot, "ft", mag<ratio(1, 3)>(), yard> {};
|
||||
|
||||
// https://en.wikipedia.org/wiki/Fathom#International_fathom
|
||||
struct fathom : named_scaled_unit<fathom, "fathom", as_magnitude<2>(), yard> {};
|
||||
struct fathom : named_scaled_unit<fathom, "fathom", mag<2>(), yard> {};
|
||||
|
||||
// si::international inch
|
||||
// https://en.wikipedia.org/wiki/Inch#Equivalences
|
||||
struct inch : named_scaled_unit<inch, "in", as_magnitude<ratio(1, 36)>(), yard> {};
|
||||
struct inch : named_scaled_unit<inch, "in", mag<ratio(1, 36)>(), yard> {};
|
||||
|
||||
// intrnational mile
|
||||
// https://en.wikipedia.org/wiki/Mile#International_mile
|
||||
struct mile : named_scaled_unit<mile, "mi", as_magnitude<ratio(25'146, 15'625)>(), si::kilometre> {};
|
||||
struct mile : named_scaled_unit<mile, "mi", mag<ratio(25'146, 15'625)>(), si::kilometre> {};
|
||||
|
||||
// si::international nautical mile
|
||||
// https://en.wikipedia.org/wiki/Nautical_mile
|
||||
struct nautical_mile : named_scaled_unit<nautical_mile, "mi(naut)", as_magnitude<1852>(), si::metre> {};
|
||||
struct nautical_mile : named_scaled_unit<nautical_mile, "mi(naut)", mag<1852>(), si::metre> {};
|
||||
|
||||
// thou
|
||||
// https://en.wikipedia.org/wiki/Thousandth_of_an_inch
|
||||
struct thou : named_scaled_unit<thou, "thou", as_magnitude<ratio(1, 1000)>(), inch> {};
|
||||
struct thou : named_scaled_unit<thou, "thou", mag<ratio(1, 1000)>(), inch> {};
|
||||
|
||||
// mil - different name for thou
|
||||
// https://en.wikipedia.org/wiki/Thousandth_of_an_inch
|
||||
|
@@ -37,12 +37,13 @@ namespace units::isq::si::typographic {
|
||||
|
||||
// TODO Conflicts with (https://en.wikipedia.org/wiki/Pica_(typography)), verify correctness of below conversion factors
|
||||
// and provide hyperlinks to definitions
|
||||
struct pica_comp :
|
||||
named_scaled_unit<pica_comp, "pica(comp)", as_magnitude<ratio(4233333, 1000000, -3)>(), si::metre> {};
|
||||
struct pica_prn : named_scaled_unit<pica_prn, "pica(prn)", as_magnitude<ratio(2108759, 500000, -3)>(), si::metre> {};
|
||||
struct pica_comp : named_scaled_unit<pica_comp, "pica(comp)", mag<4'233'333>() * mag_power<10, -9>(), si::metre> {};
|
||||
struct pica_prn :
|
||||
named_scaled_unit<pica_prn, "pica(prn)", mag<ratio(2108759, 500000)>() * mag_power<10, -3>(), si::metre> {};
|
||||
struct point_comp :
|
||||
named_scaled_unit<point_comp, "point(comp)", as_magnitude<ratio(1763889, 500000, -4)>(), si::metre> {};
|
||||
struct point_prn : named_scaled_unit<point_prn, "point(prn)", as_magnitude<ratio(1757299, 500000, -4)>(), si::metre> {};
|
||||
named_scaled_unit<point_comp, "point(comp)", mag<ratio(1763889, 500000)>() * mag_power<10, -4>(), si::metre> {};
|
||||
struct point_prn :
|
||||
named_scaled_unit<point_prn, "point(prn)", mag<ratio(1757299, 500000)>() * mag_power<10, -4>(), si::metre> {};
|
||||
|
||||
#ifndef UNITS_NO_LITERALS
|
||||
|
||||
|
@@ -36,14 +36,14 @@ namespace units::isq::si::uscs {
|
||||
|
||||
// https://en.wikipedia.org/wiki/Foot_(unit)#US_survey_foot
|
||||
// https://www.nist.gov/pml/special-publication-811/nist-guide-si-appendix-b-conversion-factors#B6
|
||||
struct foot : named_scaled_unit<foot, "ft(us)", as_magnitude<ratio(1'200, 3'937)>(), si::metre> {};
|
||||
struct foot : named_scaled_unit<foot, "ft(us)", mag<ratio(1'200, 3'937)>(), si::metre> {};
|
||||
|
||||
// https://www.nist.gov/pml/special-publication-811/nist-guide-si-appendix-b-conversion-factors#B6
|
||||
struct fathom : named_scaled_unit<fathom, "fathom(us)", as_magnitude<6>(), foot> {};
|
||||
struct fathom : named_scaled_unit<fathom, "fathom(us)", mag<6>(), foot> {};
|
||||
|
||||
// https://en.wikipedia.org/wiki/Mile#U.S._survey_mile
|
||||
// https://www.nist.gov/pml/special-publication-811/nist-guide-si-appendix-b-conversion-factors#B6
|
||||
struct mile : named_scaled_unit<mile, "mi(us)", as_magnitude<5280>(), foot> {};
|
||||
struct mile : named_scaled_unit<mile, "mi(us)", mag<5280>(), foot> {};
|
||||
|
||||
#ifndef UNITS_NO_LITERALS
|
||||
|
||||
|
@@ -58,7 +58,7 @@ struct exakatal : prefixed_unit<exakatal, exa, katal> {};
|
||||
struct zettakatal : prefixed_unit<zettakatal, zetta, katal> {};
|
||||
struct yottakatal : prefixed_unit<yottakatal, yotta, katal> {};
|
||||
|
||||
struct enzyme_unit : named_scaled_unit<enzyme_unit, "U", as_magnitude<ratio(1, 60, -6)>(), katal> {};
|
||||
struct enzyme_unit : named_scaled_unit<enzyme_unit, "U", mag<ratio(1, 60)>() * mag_power<10, -6>(), katal> {};
|
||||
|
||||
struct dim_catalytic_activity :
|
||||
isq::dim_catalytic_activity<dim_catalytic_activity, katal, dim_time, dim_amount_of_substance> {};
|
||||
|
@@ -56,7 +56,7 @@ struct yottajoule : prefixed_unit<yottajoule, yotta, joule> {};
|
||||
// N.B. electron charge (and eV) is an exact constant:
|
||||
// https://www.bipm.org/documents/20126/41483022/SI-Brochure-9.pdf#page=147
|
||||
struct electronvolt :
|
||||
named_scaled_unit<electronvolt, "eV", as_magnitude<ratio(1'602'176'634, 1'000'000'000, -19)>(), joule> {};
|
||||
named_scaled_unit<electronvolt, "eV", mag<ratio(1'602'176'634, 1'000'000'000)>() * mag_power<10, -19>(), joule> {};
|
||||
struct gigaelectronvolt : prefixed_unit<gigaelectronvolt, giga, electronvolt> {};
|
||||
|
||||
struct dim_energy : isq::dim_energy<dim_energy, joule, dim_force, dim_length> {};
|
||||
|
@@ -56,7 +56,7 @@ struct exametre : prefixed_unit<exametre, exa, metre> {};
|
||||
struct zettametre : prefixed_unit<zettametre, zetta, metre> {};
|
||||
struct yottametre : prefixed_unit<yottametre, yotta, metre> {};
|
||||
|
||||
struct astronomical_unit : named_scaled_unit<astronomical_unit, "au", as_magnitude<149'597'870'700>(), metre> {};
|
||||
struct astronomical_unit : named_scaled_unit<astronomical_unit, "au", mag<149'597'870'700>(), metre> {};
|
||||
|
||||
struct dim_length : isq::dim_length<metre> {};
|
||||
|
||||
|
@@ -36,7 +36,7 @@ namespace units::isq::si {
|
||||
|
||||
// TODO Is this correct? Should we account for steradian here? How?
|
||||
|
||||
struct lumen : named_scaled_unit<lumen, "lm", as_magnitude<ratio(1, 683)>(), watt> {};
|
||||
struct lumen : named_scaled_unit<lumen, "lm", mag<ratio(1, 683)>(), watt> {};
|
||||
|
||||
using dim_luminous_flux = dim_power;
|
||||
|
||||
|
@@ -56,7 +56,7 @@ struct exatesla : prefixed_unit<exatesla, exa, tesla> {};
|
||||
struct zettatesla : prefixed_unit<zettatesla, zetta, tesla> {};
|
||||
struct yottatesla : prefixed_unit<yottatesla, yotta, tesla> {};
|
||||
|
||||
struct gauss : named_scaled_unit<gauss, "G", as_magnitude<ratio(1, 10'000)>(), tesla> {};
|
||||
struct gauss : named_scaled_unit<gauss, "G", mag<ratio(1, 10'000)>(), tesla> {};
|
||||
|
||||
struct dim_magnetic_induction :
|
||||
isq::dim_magnetic_induction<dim_magnetic_induction, tesla, dim_voltage, dim_time, dim_length> {};
|
||||
|
@@ -79,7 +79,8 @@ struct zettatonne : prefixed_unit<zettatonne, zetta, tonne> {};
|
||||
struct yottatonne : prefixed_unit<yottatonne, yotta, tonne> {};
|
||||
|
||||
struct dalton :
|
||||
named_scaled_unit<dalton, "Da", as_magnitude<ratio(16'605'390'666'050, 10'000'000'000'000, -27)>(), kilogram> {};
|
||||
named_scaled_unit<dalton, "Da", mag<ratio(16'605'390'666'050, 10'000'000'000'000)>() * mag_power<10, -27>(),
|
||||
kilogram> {};
|
||||
|
||||
struct dim_mass : isq::dim_mass<kilogram> {};
|
||||
|
||||
|
@@ -27,26 +27,26 @@
|
||||
namespace units::isq::si {
|
||||
|
||||
// clang-format off
|
||||
struct yocto : prefix<yocto, "y", pow<-24>(as_magnitude<10>())> {};
|
||||
struct zepto : prefix<zepto, "z", pow<-21>(as_magnitude<10>())> {};
|
||||
struct atto : prefix<atto, "a", pow<-18>(as_magnitude<10>())> {};
|
||||
struct femto : prefix<femto, "f", pow<-15>(as_magnitude<10>())> {};
|
||||
struct pico : prefix<pico, "p", pow<-12>(as_magnitude<10>())> {};
|
||||
struct nano : prefix<nano, "n", pow<-9>(as_magnitude<10>())> {};
|
||||
struct micro : prefix<micro, basic_symbol_text{"\u00b5", "u"}, pow<-6>(as_magnitude<10>())> {};
|
||||
struct milli : prefix<milli, "m", pow<-3>(as_magnitude<10>())> {};
|
||||
struct centi : prefix<centi, "c", pow<-2>(as_magnitude<10>())> {};
|
||||
struct deci : prefix<deci, "d", pow<-1>(as_magnitude<10>())> {};
|
||||
struct deca : prefix<deca, "da", pow<1>(as_magnitude<10>())> {};
|
||||
struct hecto : prefix<hecto, "h", pow<2>(as_magnitude<10>())> {};
|
||||
struct kilo : prefix<kilo, "k", pow<3>(as_magnitude<10>())> {};
|
||||
struct mega : prefix<mega, "M", pow<6>(as_magnitude<10>())> {};
|
||||
struct giga : prefix<giga, "G", pow<9>(as_magnitude<10>())> {};
|
||||
struct tera : prefix<tera, "T", pow<12>(as_magnitude<10>())> {};
|
||||
struct peta : prefix<peta, "P", pow<15>(as_magnitude<10>())> {};
|
||||
struct exa : prefix<exa, "E", pow<18>(as_magnitude<10>())> {};
|
||||
struct zetta : prefix<zetta, "Z", pow<21>(as_magnitude<10>())> {};
|
||||
struct yotta : prefix<yotta, "Y", pow<24>(as_magnitude<10>())> {};
|
||||
struct yocto : prefix<yocto, "y", pow<-24>(mag<10>())> {};
|
||||
struct zepto : prefix<zepto, "z", pow<-21>(mag<10>())> {};
|
||||
struct atto : prefix<atto, "a", pow<-18>(mag<10>())> {};
|
||||
struct femto : prefix<femto, "f", pow<-15>(mag<10>())> {};
|
||||
struct pico : prefix<pico, "p", pow<-12>(mag<10>())> {};
|
||||
struct nano : prefix<nano, "n", pow<-9>(mag<10>())> {};
|
||||
struct micro : prefix<micro, basic_symbol_text{"\u00b5", "u"}, pow<-6>(mag<10>())> {};
|
||||
struct milli : prefix<milli, "m", pow<-3>(mag<10>())> {};
|
||||
struct centi : prefix<centi, "c", pow<-2>(mag<10>())> {};
|
||||
struct deci : prefix<deci, "d", pow<-1>(mag<10>())> {};
|
||||
struct deca : prefix<deca, "da", pow<1>(mag<10>())> {};
|
||||
struct hecto : prefix<hecto, "h", pow<2>(mag<10>())> {};
|
||||
struct kilo : prefix<kilo, "k", pow<3>(mag<10>())> {};
|
||||
struct mega : prefix<mega, "M", pow<6>(mag<10>())> {};
|
||||
struct giga : prefix<giga, "G", pow<9>(mag<10>())> {};
|
||||
struct tera : prefix<tera, "T", pow<12>(mag<10>())> {};
|
||||
struct peta : prefix<peta, "P", pow<15>(mag<10>())> {};
|
||||
struct exa : prefix<exa, "E", pow<18>(mag<10>())> {};
|
||||
struct zetta : prefix<zetta, "Z", pow<21>(mag<10>())> {};
|
||||
struct yotta : prefix<yotta, "Y", pow<24>(mag<10>())> {};
|
||||
// clang-format on
|
||||
|
||||
} // namespace units::isq::si
|
||||
|
@@ -43,9 +43,9 @@ struct picosecond : prefixed_unit<picosecond, pico, second> {};
|
||||
struct nanosecond : prefixed_unit<nanosecond, nano, second> {};
|
||||
struct microsecond : prefixed_unit<microsecond, micro, second> {};
|
||||
struct millisecond : prefixed_unit<millisecond, milli, second> {};
|
||||
struct minute : named_scaled_unit<minute, "min", as_magnitude<60>(), second> {};
|
||||
struct hour : named_scaled_unit<hour, "h", as_magnitude<60>(), minute> {};
|
||||
struct day : named_scaled_unit<day, "d", as_magnitude<24>(), hour> {};
|
||||
struct minute : named_scaled_unit<minute, "min", mag<60>(), second> {};
|
||||
struct hour : named_scaled_unit<hour, "h", mag<60>(), minute> {};
|
||||
struct day : named_scaled_unit<day, "d", mag<24>(), hour> {};
|
||||
|
||||
struct dim_time : isq::dim_time<second> {};
|
||||
|
||||
|
@@ -84,7 +84,7 @@ TEST_CASE("operator<< on a quantity", "[text][ostream][fmt]")
|
||||
{
|
||||
SECTION("in terms of base units")
|
||||
{
|
||||
const length<scaled_unit<pow<6>(as_magnitude<10>()), metre>> q(123);
|
||||
const length<scaled_unit<pow<6>(mag<10>()), metre>> q(123);
|
||||
os << q;
|
||||
|
||||
SECTION("iostream") { CHECK(os.str() == "123 Mm"); }
|
||||
@@ -96,7 +96,7 @@ TEST_CASE("operator<< on a quantity", "[text][ostream][fmt]")
|
||||
|
||||
SECTION("in terms of derived units")
|
||||
{
|
||||
const energy<scaled_unit<pow<-2>(as_magnitude<10>()), joule>> q(60);
|
||||
const energy<scaled_unit<pow<-2>(mag<10>()), joule>> q(60);
|
||||
os << q;
|
||||
|
||||
SECTION("iostream") { CHECK(os.str() == "60 cJ"); }
|
||||
|
@@ -327,7 +327,7 @@ TEST_CASE("std::format on synthesized unit symbols", "[text][fmt]")
|
||||
SECTION("unknown scaled unit with reference different than the dimension's coherent unit")
|
||||
{
|
||||
// TODO(chogg): Reinstate after format/Magnitude redesign.
|
||||
// constexpr auto mag = units::as_magnitude<units::ratio{2, 3}>();
|
||||
// constexpr auto mag = units::mag<units::ratio{2, 3}>();
|
||||
// CHECK(STD_FMT::format("{}", mass<units::scaled_unit<mag, gram>>(1)) == "1 [2/3 × 10⁻³] kg");
|
||||
// CHECK(STD_FMT::format("{:%Q %Aq}", mass<units::scaled_unit<mag, gram>>(1)) == "1 [2/3 x 10^-3] kg");
|
||||
}
|
||||
|
@@ -66,7 +66,7 @@ void check_same_type_and_value(T actual, U expected)
|
||||
template<ratio R>
|
||||
void check_ratio_round_trip_is_identity()
|
||||
{
|
||||
constexpr Magnitude auto m = as_magnitude<R>();
|
||||
constexpr Magnitude auto m = mag<R>();
|
||||
constexpr ratio round_trip = ratio{
|
||||
get_value<std::intmax_t>(numerator(m)),
|
||||
get_value<std::intmax_t>(denominator(m)),
|
||||
@@ -125,10 +125,10 @@ TEST_CASE("base_power")
|
||||
|
||||
SECTION("product with inverse equals identity")
|
||||
{
|
||||
auto check_product_with_inverse_is_identity = [](auto x) { CHECK(x * pow<-1>(x) == as_magnitude<1>()); };
|
||||
auto check_product_with_inverse_is_identity = [](auto x) { CHECK(x * pow<-1>(x) == mag<1>()); };
|
||||
|
||||
check_product_with_inverse_is_identity(as_magnitude<3>());
|
||||
check_product_with_inverse_is_identity(as_magnitude<ratio{4, 17}>());
|
||||
check_product_with_inverse_is_identity(mag<3>());
|
||||
check_product_with_inverse_is_identity(mag<ratio{4, 17}>());
|
||||
check_product_with_inverse_is_identity(pi_to_the<ratio{-22, 7}>());
|
||||
}
|
||||
|
||||
@@ -144,28 +144,21 @@ TEST_CASE("make_ratio performs prime factorization correctly")
|
||||
{
|
||||
SECTION("Performs prime factorization when denominator is 1")
|
||||
{
|
||||
CHECK(as_magnitude<1>() == magnitude<>{});
|
||||
CHECK(as_magnitude<2>() == magnitude<base_power{2}>{});
|
||||
CHECK(as_magnitude<3>() == magnitude<base_power{3}>{});
|
||||
CHECK(as_magnitude<4>() == magnitude<base_power{2, 2}>{});
|
||||
CHECK(mag<1>() == magnitude<>{});
|
||||
CHECK(mag<2>() == magnitude<base_power{2}>{});
|
||||
CHECK(mag<3>() == magnitude<base_power{3}>{});
|
||||
CHECK(mag<4>() == magnitude<base_power{2, 2}>{});
|
||||
|
||||
CHECK(as_magnitude<792>() == magnitude<base_power{2, 3}, base_power{3, 2}, base_power{11}>{});
|
||||
CHECK(mag<792>() == magnitude<base_power{2, 3}, base_power{3, 2}, base_power{11}>{});
|
||||
}
|
||||
|
||||
SECTION("Supports fractions") { CHECK(as_magnitude<ratio{5, 8}>() == magnitude<base_power{2, -3}, base_power{5}>{}); }
|
||||
|
||||
SECTION("Supports nonzero exp")
|
||||
{
|
||||
constexpr ratio r{3, 1, 2};
|
||||
REQUIRE(r.exp == 2);
|
||||
CHECK(as_magnitude<r>() == as_magnitude<300>());
|
||||
}
|
||||
SECTION("Supports fractions") { CHECK(mag<ratio{5, 8}>() == magnitude<base_power{2, -3}, base_power{5}>{}); }
|
||||
|
||||
SECTION("Can handle prime factor which would be large enough to overflow int")
|
||||
{
|
||||
// This was taken from a case which failed when we used `int` for our base to store prime numbers.
|
||||
// The failure was due to a prime factor which is larger than 2^31.
|
||||
as_magnitude<ratio(16'605'390'666'050, 10'000'000'000'000)>();
|
||||
mag<ratio(16'605'390'666'050, 10'000'000'000'000)>();
|
||||
}
|
||||
|
||||
SECTION("Can bypass computing primes by providing known_first_factor<N>")
|
||||
@@ -176,7 +169,7 @@ TEST_CASE("make_ratio performs prime factorization correctly")
|
||||
// In this case, we test that we can represent the largest prime that fits in a signed 64-bit int. The reason this
|
||||
// test can pass is that we have provided the answer, by specializing the `known_first_factor` variable template
|
||||
// above in this file.
|
||||
as_magnitude<9'223'372'036'854'775'783>();
|
||||
mag<9'223'372'036'854'775'783>();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -184,7 +177,7 @@ TEST_CASE("magnitude converts to numerical value")
|
||||
{
|
||||
SECTION("Positive integer powers of integer bases give integer values")
|
||||
{
|
||||
constexpr auto mag_412 = as_magnitude<412>();
|
||||
constexpr auto mag_412 = mag<412>();
|
||||
check_same_type_and_value(get_value<int>(mag_412), 412);
|
||||
check_same_type_and_value(get_value<std::size_t>(mag_412), std::size_t{412});
|
||||
check_same_type_and_value(get_value<float>(mag_412), 412.0f);
|
||||
@@ -193,7 +186,7 @@ TEST_CASE("magnitude converts to numerical value")
|
||||
|
||||
SECTION("Negative integer powers of integer bases compute correct values")
|
||||
{
|
||||
constexpr auto mag_0p125 = as_magnitude<ratio{1, 8}>();
|
||||
constexpr auto mag_0p125 = mag<ratio{1, 8}>();
|
||||
check_same_type_and_value(get_value<float>(mag_0p125), 0.125f);
|
||||
check_same_type_and_value(get_value<double>(mag_0p125), 0.125);
|
||||
}
|
||||
@@ -226,20 +219,20 @@ TEST_CASE("magnitude converts to numerical value")
|
||||
// Naturally, we cannot actually write a test to verify a compiler error. But any of these can
|
||||
// be uncommented if desired to verify that it breaks the build.
|
||||
|
||||
// get_value<int8_t>(as_magnitude<412>());
|
||||
// get_value<int8_t>(mag<412>());
|
||||
|
||||
// Would work for pow<62>:
|
||||
// get_value<int64_t>(pow<63>(as_magnitude<2>()));
|
||||
// get_value<int64_t>(pow<63>(mag<2>()));
|
||||
|
||||
// Would work for pow<63>:
|
||||
// get_value<uint64_t>(pow<64>(as_magnitude<2>()));
|
||||
// get_value<uint64_t>(pow<64>(mag<2>()));
|
||||
|
||||
get_value<double>(pow<308>(as_magnitude<10>())); // Compiles, correctly.
|
||||
// get_value<double>(pow<309>(as_magnitude<10>()));
|
||||
// get_value<double>(pow<3099>(as_magnitude<10>()));
|
||||
// get_value<double>(pow<3099999>(as_magnitude<10>()));
|
||||
get_value<double>(pow<308>(mag<10>())); // Compiles, correctly.
|
||||
// get_value<double>(pow<309>(mag<10>()));
|
||||
// get_value<double>(pow<3099>(mag<10>()));
|
||||
// get_value<double>(pow<3099999>(mag<10>()));
|
||||
|
||||
auto sqrt_2 = pow<ratio{1, 2}>(as_magnitude<2>());
|
||||
auto sqrt_2 = pow<ratio{1, 2}>(mag<2>());
|
||||
CHECK(!is_integral(sqrt_2));
|
||||
// get_value<int>(sqrt_2);
|
||||
}
|
||||
@@ -249,46 +242,40 @@ TEST_CASE("Equality works for magnitudes")
|
||||
{
|
||||
SECTION("Equivalent ratios are equal")
|
||||
{
|
||||
CHECK(as_magnitude<1>() == as_magnitude<1>());
|
||||
CHECK(as_magnitude<3>() == as_magnitude<3>());
|
||||
CHECK(as_magnitude<ratio{3, 4}>() == as_magnitude<ratio{9, 12}>());
|
||||
CHECK(mag<1>() == mag<1>());
|
||||
CHECK(mag<3>() == mag<3>());
|
||||
CHECK(mag<ratio{3, 4}>() == mag<ratio{9, 12}>());
|
||||
}
|
||||
|
||||
SECTION("Different ratios are unequal")
|
||||
{
|
||||
CHECK(as_magnitude<3>() != as_magnitude<5>());
|
||||
CHECK(as_magnitude<3>() != as_magnitude<ratio{3, 2}>());
|
||||
CHECK(mag<3>() != mag<5>());
|
||||
CHECK(mag<3>() != mag<ratio{3, 2}>());
|
||||
}
|
||||
|
||||
SECTION("Supports constexpr")
|
||||
{
|
||||
constexpr auto eq = (as_magnitude<ratio{4, 5}>() == as_magnitude<ratio{4, 3}>());
|
||||
constexpr auto eq = (mag<ratio{4, 5}>() == mag<ratio{4, 3}>());
|
||||
CHECK(!eq);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("Multiplication works for magnitudes")
|
||||
{
|
||||
SECTION("Reciprocals reduce to null magnitude")
|
||||
{
|
||||
CHECK(as_magnitude<ratio{3, 4}>() * as_magnitude<ratio{4, 3}>() == as_magnitude<1>());
|
||||
}
|
||||
SECTION("Reciprocals reduce to null magnitude") { CHECK(mag<ratio{3, 4}>() * mag<ratio{4, 3}>() == mag<1>()); }
|
||||
|
||||
SECTION("Products work as expected")
|
||||
{
|
||||
CHECK(as_magnitude<ratio{4, 5}>() * as_magnitude<ratio{4, 3}>() == as_magnitude<ratio{16, 15}>());
|
||||
}
|
||||
SECTION("Products work as expected") { CHECK(mag<ratio{4, 5}>() * mag<ratio{4, 3}>() == mag<ratio{16, 15}>()); }
|
||||
|
||||
SECTION("Products handle pi correctly")
|
||||
{
|
||||
CHECK(pi_to_the<1>() * as_magnitude<ratio{2, 3}>() * pi_to_the<ratio{-1, 2}>() ==
|
||||
CHECK(pi_to_the<1>() * mag<ratio{2, 3}>() * pi_to_the<ratio{-1, 2}>() ==
|
||||
magnitude<base_power{2}, base_power{3, -1}, base_power<pi_base>{ratio{1, 2}}>{});
|
||||
}
|
||||
|
||||
SECTION("Supports constexpr")
|
||||
{
|
||||
constexpr auto p = as_magnitude<ratio{4, 5}>() * as_magnitude<ratio{4, 3}>();
|
||||
CHECK(p == as_magnitude<ratio{16, 15}>());
|
||||
constexpr auto p = mag<ratio{4, 5}>() * mag<ratio{4, 3}>();
|
||||
CHECK(p == mag<ratio{16, 15}>());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -296,20 +283,20 @@ TEST_CASE("Common Magnitude")
|
||||
{
|
||||
SECTION("Identity for identical magnitudes")
|
||||
{
|
||||
CHECK(common_magnitude(as_magnitude<1>(), as_magnitude<1>()) == as_magnitude<1>());
|
||||
CHECK(common_magnitude(as_magnitude<15>(), as_magnitude<15>()) == as_magnitude<15>());
|
||||
CHECK(common_magnitude(mag<1>(), mag<1>()) == mag<1>());
|
||||
CHECK(common_magnitude(mag<15>(), mag<15>()) == mag<15>());
|
||||
CHECK(common_magnitude(pi_to_the<ratio{3, 4}>(), pi_to_the<ratio{3, 4}>()) == pi_to_the<ratio{3, 4}>());
|
||||
}
|
||||
|
||||
SECTION("Greatest Common Factor for integers")
|
||||
{
|
||||
CHECK(common_magnitude(as_magnitude<24>(), as_magnitude<36>()) == as_magnitude<12>());
|
||||
CHECK(common_magnitude(as_magnitude<24>(), as_magnitude<37>()) == as_magnitude<1>());
|
||||
CHECK(common_magnitude(mag<24>(), mag<36>()) == mag<12>());
|
||||
CHECK(common_magnitude(mag<24>(), mag<37>()) == mag<1>());
|
||||
}
|
||||
|
||||
SECTION("Handles fractions")
|
||||
{
|
||||
CHECK(common_magnitude(as_magnitude<ratio{3, 8}>(), as_magnitude<ratio{5, 6}>()) == as_magnitude<ratio{1, 24}>());
|
||||
CHECK(common_magnitude(mag<ratio{3, 8}>(), mag<ratio{5, 6}>()) == mag<ratio{1, 24}>());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -317,19 +304,16 @@ TEST_CASE("Division works for magnitudes")
|
||||
{
|
||||
SECTION("Dividing anything by itself reduces to null magnitude")
|
||||
{
|
||||
CHECK(as_magnitude<ratio{3, 4}>() / as_magnitude<ratio{3, 4}>() == as_magnitude<1>());
|
||||
CHECK(as_magnitude<15>() / as_magnitude<15>() == as_magnitude<1>());
|
||||
CHECK(mag<ratio{3, 4}>() / mag<ratio{3, 4}>() == mag<1>());
|
||||
CHECK(mag<15>() / mag<15>() == mag<1>());
|
||||
}
|
||||
|
||||
SECTION("Quotients work as expected")
|
||||
{
|
||||
CHECK(as_magnitude<ratio{4, 5}>() / as_magnitude<ratio{4, 3}>() == as_magnitude<ratio{3, 5}>());
|
||||
}
|
||||
SECTION("Quotients work as expected") { CHECK(mag<ratio{4, 5}>() / mag<ratio{4, 3}>() == mag<ratio{3, 5}>()); }
|
||||
|
||||
SECTION("Supports constexpr")
|
||||
{
|
||||
constexpr auto q = as_magnitude<ratio{4, 5}>() / as_magnitude<ratio{4, 3}>();
|
||||
CHECK(q == as_magnitude<ratio{3, 5}>());
|
||||
constexpr auto q = mag<ratio{4, 5}>() / mag<ratio{4, 3}>();
|
||||
CHECK(q == mag<ratio{3, 5}>());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -337,17 +321,17 @@ TEST_CASE("Can raise Magnitudes to rational powers")
|
||||
{
|
||||
SECTION("Anything to the 0 is 1")
|
||||
{
|
||||
CHECK(pow<0>(as_magnitude<1>()) == as_magnitude<1>());
|
||||
CHECK(pow<0>(as_magnitude<123>()) == as_magnitude<1>());
|
||||
CHECK(pow<0>(as_magnitude<ratio{3, 4}>()) == as_magnitude<1>());
|
||||
CHECK(pow<0>(pi_to_the<ratio{-1, 2}>()) == as_magnitude<1>());
|
||||
CHECK(pow<0>(mag<1>()) == mag<1>());
|
||||
CHECK(pow<0>(mag<123>()) == mag<1>());
|
||||
CHECK(pow<0>(mag<ratio{3, 4}>()) == mag<1>());
|
||||
CHECK(pow<0>(pi_to_the<ratio{-1, 2}>()) == mag<1>());
|
||||
}
|
||||
|
||||
SECTION("Anything to the 1 is itself")
|
||||
{
|
||||
CHECK(pow<1>(as_magnitude<1>()) == as_magnitude<1>());
|
||||
CHECK(pow<1>(as_magnitude<123>()) == as_magnitude<123>());
|
||||
CHECK(pow<1>(as_magnitude<ratio{3, 4}>()) == as_magnitude<ratio{3, 4}>());
|
||||
CHECK(pow<1>(mag<1>()) == mag<1>());
|
||||
CHECK(pow<1>(mag<123>()) == mag<123>());
|
||||
CHECK(pow<1>(mag<ratio{3, 4}>()) == mag<ratio{3, 4}>());
|
||||
CHECK(pow<1>(pi_to_the<ratio{-1, 2}>()) == pi_to_the<ratio{-1, 2}>());
|
||||
}
|
||||
|
||||
@@ -366,11 +350,11 @@ TEST_CASE("can distinguish integral, rational, and irrational magnitudes")
|
||||
CHECK(is_rational(m));
|
||||
};
|
||||
check_rational_and_integral(magnitude<>{});
|
||||
check_rational_and_integral(as_magnitude<1>());
|
||||
check_rational_and_integral(as_magnitude<3>());
|
||||
check_rational_and_integral(as_magnitude<8>());
|
||||
check_rational_and_integral(as_magnitude<412>());
|
||||
check_rational_and_integral(as_magnitude<ratio{1, 1}>());
|
||||
check_rational_and_integral(mag<1>());
|
||||
check_rational_and_integral(mag<3>());
|
||||
check_rational_and_integral(mag<8>());
|
||||
check_rational_and_integral(mag<412>());
|
||||
check_rational_and_integral(mag<ratio{1, 1}>());
|
||||
}
|
||||
|
||||
SECTION("Fractional magnitudes are rational, but not integral")
|
||||
@@ -379,8 +363,8 @@ TEST_CASE("can distinguish integral, rational, and irrational magnitudes")
|
||||
CHECK(!is_integral(m));
|
||||
CHECK(is_rational(m));
|
||||
};
|
||||
check_rational_but_not_integral(as_magnitude<ratio{1, 2}>());
|
||||
check_rational_but_not_integral(as_magnitude<ratio{5, 8}>());
|
||||
check_rational_but_not_integral(mag<ratio{1, 2}>());
|
||||
check_rational_but_not_integral(mag<ratio{5, 8}>());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -397,17 +381,17 @@ TEST_CASE("Constructing ratio from rational magnitude")
|
||||
|
||||
SECTION("Rational magnitude converts to ratio")
|
||||
{
|
||||
constexpr ratio r = as_ratio(as_magnitude<ratio{22, 7}>());
|
||||
constexpr ratio r = as_ratio(mag<ratio{22, 7}>());
|
||||
CHECK(r == ratio{22, 7});
|
||||
}
|
||||
|
||||
SECTION("Irrational magnitude does not convert to ratio")
|
||||
{
|
||||
// The following code should not compile.
|
||||
// as_ratio(pow<ratio{1, 2}>(as_magnitude<2>()));
|
||||
// as_ratio(pow<ratio{1, 2}>(mag<2>()));
|
||||
|
||||
// The following code should not compile.
|
||||
// as_ratio(as_magnitude<180>() / pi_to_the<1>());
|
||||
// as_ratio(mag<180>() / pi_to_the<1>());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -614,26 +598,26 @@ TEST_CASE("extract_power_of_10")
|
||||
{
|
||||
SECTION("Picks out positive powers")
|
||||
{
|
||||
CHECK(extract_power_of_10(as_magnitude<10>()) == 1);
|
||||
CHECK(extract_power_of_10(as_magnitude<20>()) == 1);
|
||||
CHECK(extract_power_of_10(as_magnitude<40>()) == 1);
|
||||
CHECK(extract_power_of_10(as_magnitude<50>()) == 1);
|
||||
CHECK(extract_power_of_10(as_magnitude<100>()) == 2);
|
||||
CHECK(extract_power_of_10(mag<10>()) == 1);
|
||||
CHECK(extract_power_of_10(mag<20>()) == 1);
|
||||
CHECK(extract_power_of_10(mag<40>()) == 1);
|
||||
CHECK(extract_power_of_10(mag<50>()) == 1);
|
||||
CHECK(extract_power_of_10(mag<100>()) == 2);
|
||||
}
|
||||
|
||||
SECTION("Picks out negative powers")
|
||||
{
|
||||
constexpr auto ONE = as_magnitude<1>();
|
||||
CHECK(extract_power_of_10(ONE / as_magnitude<10>()) == -1);
|
||||
CHECK(extract_power_of_10(ONE / as_magnitude<20>()) == -1);
|
||||
CHECK(extract_power_of_10(ONE / as_magnitude<40>()) == -1);
|
||||
CHECK(extract_power_of_10(ONE / as_magnitude<50>()) == -1);
|
||||
CHECK(extract_power_of_10(ONE / as_magnitude<100>()) == -2);
|
||||
constexpr auto ONE = mag<1>();
|
||||
CHECK(extract_power_of_10(ONE / mag<10>()) == -1);
|
||||
CHECK(extract_power_of_10(ONE / mag<20>()) == -1);
|
||||
CHECK(extract_power_of_10(ONE / mag<40>()) == -1);
|
||||
CHECK(extract_power_of_10(ONE / mag<50>()) == -1);
|
||||
CHECK(extract_power_of_10(ONE / mag<100>()) == -2);
|
||||
}
|
||||
|
||||
SECTION("Zero if signs disagree") { CHECK(extract_power_of_10(as_magnitude<2>() / as_magnitude<5>()) == 0); }
|
||||
SECTION("Zero if signs disagree") { CHECK(extract_power_of_10(mag<2>() / mag<5>()) == 0); }
|
||||
|
||||
SECTION("Handles rational powers") { CHECK(extract_power_of_10(sqrt(as_magnitude<1000>())) == 1); }
|
||||
SECTION("Handles rational powers") { CHECK(extract_power_of_10(sqrt(mag<1000>())) == 1); }
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
@@ -456,9 +456,9 @@ concept invalid_compound_assignments =
|
||||
requires !requires { w *= m; };
|
||||
requires !requires { w /= m; };
|
||||
requires !requires { w %= m; };
|
||||
requires !requires { w *= quantity_kind<downcast_kind<Width, dim_one>, scaled_unit<as_magnitude<1000>(), one>, int>{1}; };
|
||||
requires !requires { w /= quantity_kind<downcast_kind<Width, dim_one>, scaled_unit<as_magnitude<1000>(), one>, int>{1}; };
|
||||
requires !requires { w %= quantity_kind<downcast_kind<Width, dim_one>, scaled_unit<as_magnitude<1000>(), one>, int>{1}; };
|
||||
requires !requires { w *= quantity_kind<downcast_kind<Width, dim_one>, scaled_unit<mag<1000>(), one>, int>{1}; };
|
||||
requires !requires { w /= quantity_kind<downcast_kind<Width, dim_one>, scaled_unit<mag<1000>(), one>, int>{1}; };
|
||||
requires !requires { w %= quantity_kind<downcast_kind<Width, dim_one>, scaled_unit<mag<1000>(), one>, int>{1}; };
|
||||
requires !requires { w %= 1.0; };
|
||||
requires !requires { w %= quantity(1.0); };
|
||||
requires !requires { w %= 1.0 * (w / w); };
|
||||
|
@@ -287,7 +287,7 @@ static_assert(get_length_derived_quantity() == 1_q_m);
|
||||
// CTAD
|
||||
/////////
|
||||
|
||||
#if UNITS_COMP_GCC >= 11 || UNITS_COMP_CLANG > 15
|
||||
#if UNITS_COMP_GCC >= 11 || UNITS_COMP_CLANG > 16
|
||||
static_assert(std::is_same_v<decltype(aliases::isq::si::m(123))::rep, int>);
|
||||
static_assert(std::is_same_v<decltype(aliases::isq::si::m(123.))::rep, double>);
|
||||
static_assert(
|
||||
@@ -498,7 +498,7 @@ static_assert(compare<decltype(1_q_m / 1_q_m), dimensionless<one, std::int64_t>>
|
||||
static_assert(compare<decltype(1 / 1_q_s), frequency<hertz, std::int64_t>>);
|
||||
static_assert(compare<decltype(quantity{1} / 1_q_s), frequency<hertz, std::int64_t>>);
|
||||
static_assert(compare<decltype(dimensionless<percent, std::int64_t>(1) / 1_q_s),
|
||||
frequency<scaled_unit<as_magnitude<ratio(1, 100)>(), hertz>, std::int64_t>>);
|
||||
frequency<scaled_unit<mag<ratio(1, 100)>(), hertz>, std::int64_t>>);
|
||||
|
||||
static_assert(is_same_v<decltype((std::uint8_t(0) * m + std::uint8_t(0) * m).number()), int&&>);
|
||||
static_assert(is_same_v<decltype((std::uint8_t(0) * m - std::uint8_t(0) * m).number()), int&&>);
|
||||
@@ -529,7 +529,7 @@ static_assert(compare<decltype(1_q_m / 1._q_m), dimensionless<one, long double>>
|
||||
static_assert(compare<decltype(1 / 1._q_s), frequency<hertz, long double>>);
|
||||
static_assert(compare<decltype(quantity{1} / 1._q_s), frequency<hertz, long double>>);
|
||||
static_assert(compare<decltype(dimensionless<percent, std::int64_t>(1) / 1._q_s),
|
||||
frequency<scaled_unit<as_magnitude<ratio(1, 100)>(), hertz>, long double>>);
|
||||
frequency<scaled_unit<mag<ratio(1, 100)>(), hertz>, long double>>);
|
||||
static_assert(compare<decltype(1_q_m % short(1)), length<metre, std::int64_t>>);
|
||||
static_assert(compare<decltype(1_q_m % quantity{short(1)}), length<metre, std::int64_t>>);
|
||||
static_assert(compare<decltype(1_q_m % dimensionless<percent, short>(1)), length<metre, std::int64_t>>);
|
||||
@@ -551,7 +551,7 @@ static_assert(compare<decltype(1._q_m / 1_q_m), dimensionless<one, long double>>
|
||||
static_assert(compare<decltype(1.L / 1_q_s), frequency<hertz, long double>>);
|
||||
static_assert(compare<decltype(quantity{1.L} / 1_q_s), frequency<hertz, long double>>);
|
||||
static_assert(compare<decltype(dimensionless<percent, long double>(1) / 1_q_s),
|
||||
frequency<scaled_unit<as_magnitude<ratio(1, 100)>(), hertz>, long double>>);
|
||||
frequency<scaled_unit<mag<ratio(1, 100)>(), hertz>, long double>>);
|
||||
|
||||
// different units
|
||||
static_assert(compare<decltype(1_q_m + 1_q_km), length<metre, std::int64_t>>);
|
||||
@@ -579,25 +579,23 @@ static_assert(is_same_v<decltype(1_q_km % 1_q_m), length<kilometre, std::int64_t
|
||||
|
||||
// different dimensions
|
||||
static_assert(compare<decltype(1_q_m_per_s * 1_q_s), length<metre, std::int64_t>>);
|
||||
static_assert(
|
||||
compare<decltype(1_q_m_per_s * 1_q_h), length<scaled_unit<as_magnitude<ratio(36, 1, 2)>(), metre>, std::int64_t>>);
|
||||
static_assert(compare<decltype(1_q_m_per_s * 1_q_h), length<scaled_unit<mag<3600>(), metre>, std::int64_t>>);
|
||||
static_assert(
|
||||
compare<decltype(1_q_m * 1_q_min), quantity<unknown_dimension<exponent<dim_length, 1>, exponent<dim_time, 1>>,
|
||||
scaled_unit<as_magnitude<60>(), unknown_coherent_unit>, std::int64_t>>);
|
||||
scaled_unit<mag<60>(), unknown_coherent_unit>, std::int64_t>>);
|
||||
static_assert(compare<decltype(1_q_s * 1_q_Hz), dimensionless<one, std::int64_t>>);
|
||||
static_assert(
|
||||
compare<decltype(1 / 1_q_min), frequency<scaled_unit<as_magnitude<ratio(1, 60)>(), hertz>, std::int64_t>>);
|
||||
static_assert(compare<decltype(1 / 1_q_min), frequency<scaled_unit<mag<ratio(1, 60)>(), hertz>, std::int64_t>>);
|
||||
static_assert(compare<decltype(1 / 1_q_Hz), isq::si::time<second, std::int64_t>>);
|
||||
static_assert(compare<decltype(1 / 1_q_km),
|
||||
quantity<unknown_dimension<exponent<dim_length, -1>>,
|
||||
scaled_unit<as_magnitude<ratio(1, 1, -3)>(), unknown_coherent_unit>, std::int64_t>>);
|
||||
static_assert(compare<decltype(1_q_km / 1_q_m), dimensionless<scaled_unit<as_magnitude<1000>(), one>, std::int64_t>>);
|
||||
static_assert(
|
||||
compare<decltype(1 / 1_q_km), quantity<unknown_dimension<exponent<dim_length, -1>>,
|
||||
scaled_unit<mag<ratio(1, 1000)>(), unknown_coherent_unit>, std::int64_t>>);
|
||||
static_assert(compare<decltype(1_q_km / 1_q_m), dimensionless<scaled_unit<mag<1000>(), one>, std::int64_t>>);
|
||||
static_assert(compare<decltype(1_q_m / 1_q_s), speed<metre_per_second, std::int64_t>>);
|
||||
static_assert(
|
||||
compare<decltype(1_q_m / 1_q_min), speed<scaled_unit<as_magnitude<ratio(1, 60)>(), metre_per_second>, std::int64_t>>);
|
||||
compare<decltype(1_q_m / 1_q_min), speed<scaled_unit<mag<ratio(1, 60)>(), metre_per_second>, std::int64_t>>);
|
||||
static_assert(
|
||||
compare<decltype(1_q_min / 1_q_m), quantity<unknown_dimension<exponent<dim_length, -1>, exponent<dim_time, 1>>,
|
||||
scaled_unit<as_magnitude<60>(), unknown_coherent_unit>, std::int64_t>>);
|
||||
scaled_unit<mag<60>(), unknown_coherent_unit>, std::int64_t>>);
|
||||
|
||||
static_assert((1_q_m + 1_q_m).number() == 2);
|
||||
static_assert((1_q_m + 1_q_km).number() == 1001);
|
||||
@@ -887,9 +885,8 @@ static_assert(!is_same_v<decltype(quantity_cast<litre>(2_q_dm3)), volume<cubic_d
|
||||
|
||||
static_assert(is_same_v<decltype(10_q_m / 5_q_s),
|
||||
quantity<unknown_dimension<units::exponent<dim_length, 1>, units::exponent<dim_time, -1>>,
|
||||
scaled_unit<as_magnitude<1>(), unknown_coherent_unit>, std::int64_t>>);
|
||||
static_assert(
|
||||
is_same_v<decltype(1_q_mm + 1_q_km), length<scaled_unit<as_magnitude<ratio(1, 1, -3)>(), metre>, std::int64_t>>);
|
||||
scaled_unit<mag<1>(), unknown_coherent_unit>, std::int64_t>>);
|
||||
static_assert(is_same_v<decltype(1_q_mm + 1_q_km), length<scaled_unit<mag<ratio(1, 1000)>(), metre>, std::int64_t>>);
|
||||
|
||||
#else
|
||||
|
||||
@@ -919,8 +916,7 @@ static_assert(same(quotient_remainder_theorem(3'000 * m, 400), 3'000 * m));
|
||||
static_assert(comp(quotient_remainder_theorem(3'000 * m, quantity(400)), 3'000 * m));
|
||||
static_assert(comp(quotient_remainder_theorem(3 * km, quantity(400)), 3 * km));
|
||||
static_assert(comp(quotient_remainder_theorem(3 * km, quantity(2)), 3 * km));
|
||||
static_assert(
|
||||
comp(quotient_remainder_theorem(3 * km, dimensionless<scaled_unit<as_magnitude<ratio(1, 1000)>(), one>, int>(400)),
|
||||
3 * km));
|
||||
static_assert(comp(quotient_remainder_theorem(3 * km, dimensionless<scaled_unit<mag<ratio(1, 1000)>(), one>, int>(400)),
|
||||
3 * km));
|
||||
|
||||
} // namespace
|
||||
|
@@ -28,11 +28,6 @@ using namespace units;
|
||||
|
||||
static_assert(ratio(2, 4) == ratio(1, 2));
|
||||
|
||||
// basic exponents tests
|
||||
static_assert(ratio(2, 40, 1) == ratio(1, 20, 1));
|
||||
static_assert(ratio(20, 4, -1) == ratio(10, 2, -1));
|
||||
static_assert(ratio(200, 5) == ratio(20'000, 50, -1));
|
||||
|
||||
static_assert(ratio(1) * ratio(3, 8) == ratio(3, 8));
|
||||
static_assert(ratio(3, 8) * ratio(1) == ratio(3, 8));
|
||||
static_assert(ratio(4) * ratio(1, 8) == ratio(1, 2));
|
||||
@@ -45,21 +40,12 @@ static_assert(-ratio(3, 8) == ratio(-3, 8));
|
||||
|
||||
// ratio addition
|
||||
static_assert(ratio(1, 2) + ratio(1, 3) == ratio(5, 6));
|
||||
static_assert(ratio(1, 3, 2) + ratio(11, 6) == ratio(211, 6)); // 100/3 + 11/6
|
||||
|
||||
// multiply with exponents
|
||||
static_assert(ratio(1, 8, 2) * ratio(2, 1, 4) == ratio(1, 4, 6));
|
||||
static_assert(ratio(1, 2, -4) * ratio(8, 1, 3) == ratio(4, 1, -1));
|
||||
|
||||
static_assert(ratio(4) / ratio(2) == ratio(2));
|
||||
static_assert(ratio(2) / ratio(8) == ratio(1, 4));
|
||||
static_assert(ratio(1, 8) / ratio(2) == ratio(1, 16));
|
||||
static_assert(ratio(6) / ratio(3) == ratio(2));
|
||||
|
||||
// divide with exponents
|
||||
static_assert(ratio(1, 8, -6) / ratio(2, 1, -8) == ratio(1, 16, 2));
|
||||
static_assert(ratio(6, 1, 4) / ratio(3) == ratio(2, 1, 4));
|
||||
|
||||
static_assert(pow<0>(ratio(2)) == ratio(1));
|
||||
static_assert(pow<1>(ratio(2)) == ratio(2));
|
||||
static_assert(pow<2>(ratio(2)) == ratio(4));
|
||||
@@ -69,27 +55,6 @@ static_assert(pow<1>(ratio(1, 2)) == ratio(1, 2));
|
||||
static_assert(pow<2>(ratio(1, 2)) == ratio(1, 4));
|
||||
static_assert(pow<3>(ratio(1, 2)) == ratio(1, 8));
|
||||
|
||||
// pow with exponents
|
||||
static_assert(pow<2>(ratio(1, 2, 3)) == ratio(1, 4, 6));
|
||||
static_assert(pow<4, 2>(ratio(1, 2, 3)) == ratio(1, 4, 6));
|
||||
static_assert(pow<3>(ratio(1, 2, -6)) == ratio(1, 8, -18));
|
||||
|
||||
static_assert(sqrt(ratio(9)) == ratio(3));
|
||||
static_assert(cbrt(ratio(27)) == ratio(3));
|
||||
static_assert(sqrt(ratio(4)) == ratio(2));
|
||||
static_assert(cbrt(ratio(8)) == ratio(2));
|
||||
static_assert(sqrt(ratio(1)) == ratio(1));
|
||||
static_assert(cbrt(ratio(1)) == ratio(1));
|
||||
static_assert(sqrt(ratio(0)) == ratio(0));
|
||||
static_assert(cbrt(ratio(0)) == ratio(0));
|
||||
static_assert(sqrt(ratio(1, 4)) == ratio(1, 2));
|
||||
static_assert(cbrt(ratio(1, 8)) == ratio(1, 2));
|
||||
|
||||
// sqrt with exponents
|
||||
static_assert(sqrt(ratio(9, 1, 2)) == ratio(3, 1, 1));
|
||||
static_assert(cbrt(ratio(27, 1, 3)) == ratio(3, 1, 1));
|
||||
static_assert(cbrt(ratio(27, 1, 2)) == ratio(13, 1, 0));
|
||||
|
||||
// common_ratio
|
||||
static_assert(common_ratio(ratio(1), ratio(1000)) == ratio(1));
|
||||
static_assert(common_ratio(ratio(1000), ratio(1)) == ratio(1));
|
||||
@@ -98,20 +63,9 @@ static_assert(common_ratio(ratio(1, 1000), ratio(1)) == ratio(1, 1000));
|
||||
static_assert(common_ratio(ratio(100, 1), ratio(10, 1)) == ratio(10, 1));
|
||||
static_assert(common_ratio(ratio(100, 1), ratio(1, 10)) == ratio(1, 10));
|
||||
|
||||
// common ratio with exponents
|
||||
static_assert(common_ratio(ratio(1), ratio(1, 1, 3)) == ratio(1));
|
||||
static_assert(common_ratio(ratio(10, 1, -1), ratio(1, 1, -3)) == ratio(1, 1, -3));
|
||||
|
||||
// numerator and denominator
|
||||
static_assert(numerator(ratio(3, 4)) == 3);
|
||||
static_assert(numerator(ratio(3, 7, 2)) == 300);
|
||||
static_assert(denominator(ratio(3, 4)) == 4);
|
||||
static_assert(denominator(ratio(3, 7, -2)) == 700);
|
||||
|
||||
// comparison
|
||||
static_assert((ratio(3, 4) <=> ratio(6, 8)) == (0 <=> 0));
|
||||
static_assert((ratio(3, 4) <=> ratio(-3, 4)) == (0 <=> -1));
|
||||
static_assert((ratio(-3, 4) <=> ratio(3, -4)) == (0 <=> 0));
|
||||
static_assert((ratio(1, 1, 1) <=> ratio(10)) == (0 <=> 0));
|
||||
|
||||
} // namespace
|
||||
|
@@ -43,7 +43,7 @@ static_assert(1_q_au == 149'597'870'700_q_m);
|
||||
static_assert(1_q_km + 1_q_m == 1001_q_m);
|
||||
static_assert(10_q_km / 5_q_km == 2);
|
||||
static_assert(10_q_km / 5_q_km < 3);
|
||||
static_assert(100_q_mm / 5_q_cm == dimensionless<scaled_unit<as_magnitude<ratio(1, 10)>(), one>>(20));
|
||||
static_assert(100_q_mm / 5_q_cm == dimensionless<scaled_unit<mag<ratio(1, 10)>(), one>>(20));
|
||||
static_assert(100_q_mm / 5_q_cm == dimensionless<one>(2));
|
||||
static_assert(10_q_km / 2 == 5_q_km);
|
||||
|
||||
@@ -107,7 +107,7 @@ static_assert(1000 / 1_q_s == 1_q_kHz);
|
||||
static_assert(1 / 1_q_ms == 1_q_kHz);
|
||||
static_assert(3.2_q_GHz == 3'200'000'000_q_Hz);
|
||||
static_assert((10_q_Hz * 1_q_min).number() == 10);
|
||||
static_assert(10_q_Hz * 1_q_min == dimensionless<scaled_unit<as_magnitude<60>(), one>>(10));
|
||||
static_assert(10_q_Hz * 1_q_min == dimensionless<scaled_unit<mag<60>(), one>>(10));
|
||||
static_assert(10_q_Hz * 1_q_min == dimensionless<one>(600));
|
||||
static_assert(2 / 1_q_Hz == 2_q_s);
|
||||
|
||||
|
@@ -36,12 +36,12 @@ using namespace units::isq;
|
||||
struct metre : named_unit<metre, "m"> {};
|
||||
struct centimetre : prefixed_unit<centimetre, si::centi, metre> {};
|
||||
struct kilometre : prefixed_unit<kilometre, si::kilo, metre> {};
|
||||
struct yard : named_scaled_unit<yard, "yd", as_magnitude<ratio(9'144, 1, -4)>(), metre> {};
|
||||
struct foot : named_scaled_unit<foot, "ft", as_magnitude<ratio(1, 3)>(), yard> {};
|
||||
struct yard : named_scaled_unit<yard, "yd", mag<ratio{9'144, 10'000}>(), metre> {};
|
||||
struct foot : named_scaled_unit<foot, "ft", mag<ratio(1, 3)>(), yard> {};
|
||||
struct dim_length : base_dimension<"length", metre> {};
|
||||
|
||||
struct second : named_unit<second, "s"> {};
|
||||
struct hour : named_scaled_unit<hour, "h", as_magnitude<ratio(36, 1, 2)>(), second> {};
|
||||
struct hour : named_scaled_unit<hour, "h", mag<3600>(), second> {};
|
||||
struct dim_time : base_dimension<"time", second> {};
|
||||
|
||||
struct kelvin : named_unit<kelvin, "K"> {};
|
||||
@@ -59,10 +59,10 @@ struct kilometre_per_hour : derived_scaled_unit<kilometre_per_hour, dim_speed, k
|
||||
|
||||
static_assert(equivalent<metre::named_unit, metre>);
|
||||
static_assert(equivalent<metre::scaled_unit, metre>);
|
||||
static_assert(compare<downcast<scaled_unit<as_magnitude<1>(), metre>>, metre>);
|
||||
static_assert(compare<downcast<scaled_unit<as_magnitude<ratio(1, 1, -2)>(), metre>>, centimetre>);
|
||||
static_assert(compare<downcast<scaled_unit<mag<1>(), metre>>, metre>);
|
||||
static_assert(compare<downcast<scaled_unit<mag<ratio(1, 100)>(), metre>>, centimetre>);
|
||||
static_assert(compare<downcast<scaled_unit<yard::mag, metre>>, yard>);
|
||||
static_assert(compare<downcast<scaled_unit<yard::mag / as_magnitude<3>(), metre>>, foot>);
|
||||
static_assert(compare<downcast<scaled_unit<yard::mag / mag<3>(), metre>>, foot>);
|
||||
static_assert(compare<downcast<scaled_unit<kilometre::mag / hour::mag, metre_per_second>>, kilometre_per_hour>);
|
||||
|
||||
static_assert(centimetre::symbol == "cm");
|
||||
|
Reference in New Issue
Block a user