Merge pull request #496 from mpusz/unit_compose_ext

feat: quantities can now be multiplied and divided by units
This commit is contained in:
Mateusz Pusz
2023-10-06 23:52:58 +02:00
committed by GitHub
50 changed files with 351 additions and 351 deletions

View File

@@ -63,10 +63,9 @@ static_assert(1 * h == 3600 * s);
static_assert(1 * km + 1 * m == 1001 * m);
// derived quantities
inline constexpr auto kmph = km / h;
static_assert(1 * km / (1 * s) == 1000 * (m / s));
static_assert(2 * kmph * (2 * h) == 4 * km);
static_assert(2 * km / (2 * kmph) == 1 * h);
static_assert(1 * km / (1 * s) == 1000 * m / s);
static_assert(2 * km / h * (2 * h) == 4 * km);
static_assert(2 * km / (2 * km / h) == 1 * h);
static_assert(2 * m * (3 * m) == 6 * m2);
@@ -103,7 +102,7 @@ int main()
using namespace mp_units::si::unit_symbols;
using namespace mp_units::international::unit_symbols;
constexpr quantity v1 = 110 * (km / h);
constexpr quantity v1 = 110 * km / h;
constexpr quantity v2 = 70 * mph;
constexpr quantity v3 = avg_speed(220. * isq::distance[km], 2 * h);
constexpr quantity v4 = avg_speed(isq::distance(140. * mi), 2 * h);

View File

@@ -16,10 +16,9 @@ static_assert(1 * h == 3600 * s);
static_assert(1 * km + 1 * m == 1001 * m);
// derived quantities
inline constexpr auto kmph = km / h;
static_assert(1 * km / (1 * s) == 1000 * (m / s));
static_assert(2 * kmph * (2 * h) == 4 * km);
static_assert(2 * km / (2 * kmph) == 1 * h);
static_assert(1 * km / (1 * s) == 1000 * m / s);
static_assert(2 * km / h * (2 * h) == 4 * km);
static_assert(2 * km / (2 * km / h) == 1 * h);
static_assert(2 * m * (3 * m) == 6 * m2);
@@ -59,7 +58,7 @@ int main()
using namespace mp_units::si::unit_symbols;
using namespace mp_units::international::unit_symbols;
constexpr quantity v1 = 110 * (km / h);
constexpr quantity v1 = 110 * km / h;
constexpr quantity v2 = 70 * mph;
constexpr quantity v3 = avg_speed(220. * isq::distance[km], 2 * h);
constexpr quantity v4 = avg_speed(isq::distance(140. * mi), 2 * h);

View File

@@ -92,47 +92,6 @@ In the **mp-units** library, both a number and a unit have to always be explicit
form a quantity.
## Why `60 * km / h` does not compile?
The library design does not allow multiplying or dividing a quantity (the result of `60 * km`)
by another unit. This significantly limits the number of possible errors and surprises in the
quantity equations.
Consider the following expression:
```cpp
auto q = 60 * km / 2 * h;
```
Looks like `30 km/h`, right? But it is not. If the above code was allowed, it would result
in `30 km⋅h`. In case you want to divide `60 * km` by `2 * h` a parenthesis is needed:
```cpp
auto q = 60 * km / (2 * h);
```
Another surprising issue could result from the following code:
```cpp
template<typename T>
auto make_length(T v) { return v * si::metre; }
auto v = 42;
auto q = make_length(v);
```
The above might look like a good idea, but consider what would happen in the user provided
an already existing quantity:
```cpp
auto v = 42 * m;
auto q = make_length(v);
```
Fortunately, with the current design, such issues are detected at compile-time as
multiplying or dividing a quantity by a unit is not be supported.
## Why a dimensionless quantity is not just a fundamental arithmetic type?
In the initial design of this library, the resulting type of division of two quantities was their

View File

@@ -67,14 +67,9 @@ quantity q = make_quantity<si::metre>(42);
Sometimes it might be awkward to type some derived units:
```cpp
quantity speed = 60 * (km / h);
quantity speed = 60 * km / h;
```
!!! note
Please note that `60 * km / h` will not compile. To read more about the rationale for such
a design please check our [FAQ](faq.md#why-dont-we-use-udls-to-create-a-quantity).
In case such a unit is used a lot in the project, a user can easily provide a nicely named
wrapper for it with:

View File

@@ -212,9 +212,9 @@ either:
The following does not work:
```cpp
Quantity auto q1 = la_vector{1, 2, 3} * (m / s);
Quantity auto q2 = isq::velocity(la_vector{1, 2, 3} * (m / s));
quantity<isq::velocity[m/s]> q3{la_vector{1, 2, 3} * (m / s)};
Quantity auto q1 = la_vector{1, 2, 3} * m / s;
Quantity auto q2 = isq::velocity(la_vector{1, 2, 3} * m / s);
quantity<isq::velocity[m/s]> q3{la_vector{1, 2, 3} * m / s};
```
In all the cases above, the SI unit `m / s` has an associated scalar quantity of `isq::length / isq::time`.

View File

@@ -152,19 +152,21 @@ identities used in the library:
| `QuantitySpec` | `dimensionless` |
| `Unit` | `one` |
In the equations, a user can refer to an identity object either explicitly:
In the equations, a user can explicitly refer to an identity object:
```cpp
constexpr auto my_unit = one / second;
```
or implicitly:
!!! note
Another way to achieve the same result is to call an `inverse()` function:
```cpp
constexpr auto my_unit = 1 / second;
constexpr auto my_unit = inverse(second);
```
Both cases with result in the same expression template being generated and put into the wrapper
Both cases will result in the same expression template being generated and put into the wrapper
class template.

View File

@@ -136,7 +136,7 @@ However, suppose we multiply or divide quantities of the same or different types
number by a quantity. In that case, we most probably will end up in a quantity of yet another type:
```cpp
static_assert(120 * km / (2 * h) == 60 * (km / h));
static_assert(120 * km / (2 * h) == 60 * km / h);
static_assert(isq::width(2 * m) * isq::length(2 * m) == isq::area(4 * m2));
static_assert(50 / isq::time(1 * s) == isq::frequency(50 * Hz));
```
@@ -283,7 +283,7 @@ every time when we want to ensure that we deal with a non-zero or positive value
We could implement such checks in the following way:
```cpp
if (q1 / q2 != 0 * (m / s))
if (q1 / q2 != 0 * m / s)
// ...
```

View File

@@ -107,8 +107,8 @@ However, it also explicitly states:
The library allows constraining such units in the following way:
```cpp
inline constexpr struct hertz : named_unit<"Hz", 1 / second, kind_of<isq::frequency>> {} hertz;
inline constexpr struct becquerel : named_unit<"Bq", 1 / second, kind_of<isq::activity>> {} becquerel;
inline constexpr struct hertz : named_unit<"Hz", one / second, kind_of<isq::frequency>> {} hertz;
inline constexpr struct becquerel : named_unit<"Bq", one / second, kind_of<isq::activity>> {} becquerel;
```
With the above, `hertz` can only be used for frequencies while becquerel should only be used for

View File

@@ -291,12 +291,12 @@ in the denominator), or never in which case a parenthesis will be added to enclo
units.
```cpp
std::println("{:%Q %q}", 1 * (m / s)); // 1 m/s
std::println("{:%Q %q}", 1 * (kg / m / s2)); // 1 kg m⁻¹ s⁻²
std::println("{:%Q %aq}", 1 * (m / s)); // 1 m/s
std::println("{:%Q %aq}", 1 * (kg / m / s2)); // 1 kg/(m s²)
std::println("{:%Q %nq}", 1 * (m / s)); // 1 m s⁻¹
std::println("{:%Q %nq}", 1 * (kg / m / s2)); // 1 kg m⁻¹ s⁻²
std::println("{:%Q %q}", 1 * m / s); // 1 m/s
std::println("{:%Q %q}", 1 * kg / m / s2); // 1 kg m⁻¹ s⁻²
std::println("{:%Q %aq}", 1 * m / s); // 1 m/s
std::println("{:%Q %aq}", 1 * kg / m / s2); // 1 kg/(m s²)
std::println("{:%Q %nq}", 1 * m / s); // 1 m s⁻¹
std::println("{:%Q %nq}", 1 * kg / m / s2); // 1 kg m⁻¹ s⁻²
```
Also, there are a few options to separate the units being multiplied:
@@ -319,6 +319,6 @@ to just use the `·` symbol as a separator.
The `units-unit-symbol-separator` token allows us to obtain the following outputs:
```cpp
std::println("{:%Q %q}", 1 * (kg * m2 / s2)); // 1 kg m²/s²
std::println("{:%Q %dq}", 1 * (kg * m2 / s2)); // 1 kg⋅m²/s²
std::println("{:%Q %q}", 1 * kg * m2 / s2); // 1 kg m²/s²
std::println("{:%Q %dq}", 1 * kg * m2 / s2); // 1 kg⋅m²/s²
```

View File

@@ -82,11 +82,11 @@ int main()
auto bismark = Ship{.length{251. * m},
.draft{9.3 * m},
.beam{36 * m},
.speed{56 * (km / h)},
.speed{56 * km / h},
.mass{50'300 * t},
.mainGuns{380 * mm},
.shellMass{800 * kg},
.shellSpeed{820. * (m / s)},
.shellSpeed{820. * m / s},
.power{110.45 * kW}};
// USS Iowa, using units from the foot-pound-second system
@@ -97,7 +97,7 @@ int main()
.mass{57'540 * imperial::long_ton},
.mainGuns{16 * in},
.shellMass{2700 * lb},
.shellSpeed{2690. * (ft / s)},
.shellSpeed{2690. * ft / s},
.power{212'000 * hp}};
// HMS King George V, using units from the foot-pound-second system
@@ -108,7 +108,7 @@ int main()
.mass{42'245 * imperial::long_ton},
.mainGuns{14 * in},
.shellMass{1590 * lb},
.shellSpeed{2483. * (ft / s)},
.shellSpeed{2483. * ft / s},
.power{110'000 * hp}};
print_details("KMS Bismark, defined in appropriate units from the SI system", bismark);

View File

@@ -45,10 +45,10 @@ auto get_gliders()
using namespace mp_units::si::unit_symbols;
MP_UNITS_DIAGNOSTIC_PUSH
MP_UNITS_DIAGNOSTIC_IGNORE_MISSING_BRACES
static const std::array gliders = {glider{"SZD-30 Pirat", {83 * (km / h), -0.7389 * (m / s)}},
glider{"SZD-51 Junior", {80 * (km / h), -0.6349 * (m / s)}},
glider{"SZD-48 Jantar Std 3", {110 * (km / h), -0.77355 * (m / s)}},
glider{"SZD-56 Diana", {110 * (km / h), -0.63657 * (m / s)}}};
static const std::array gliders = {glider{"SZD-30 Pirat", {83 * km / h, -0.7389 * m / s}},
glider{"SZD-51 Junior", {80 * km / h, -0.6349 * m / s}},
glider{"SZD-48 Jantar Std 3", {110 * km / h, -0.77355 * m / s}},
glider{"SZD-56 Diana", {110 * km / h, -0.63657 * m / s}}};
MP_UNITS_DIAGNOSTIC_POP
return gliders;
}
@@ -56,9 +56,9 @@ auto get_gliders()
auto get_weather_conditions()
{
using namespace mp_units::si::unit_symbols;
static const std::array weather_conditions = {std::pair{"Good", weather{1900 * m, 4.3 * (m / s)}},
std::pair{"Medium", weather{1550 * m, 2.8 * (m / s)}},
std::pair{"Bad", weather{850 * m, 1.8 * (m / s)}}};
static const std::array weather_conditions = {std::pair{"Good", weather{1900 * m, 4.3 * m / s}},
std::pair{"Medium", weather{1550 * m, 2.8 * m / s}},
std::pair{"Bad", weather{850 * m, 1.8 * m / s}}};
return weather_conditions;
}
@@ -164,7 +164,7 @@ void example()
const auto waypoints = get_waypoints();
const auto weather_conditions = get_weather_conditions();
const task t = {waypoints[0], waypoints[1], waypoints[0]};
const aircraft_tow tow = {400 * m, 1.6 * (m / s)};
const aircraft_tow tow = {400 * m, 1.6 * m / s};
// TODO use C++20 date library when available
// set `start_time` to 11:00 am today
const timestamp start_time(std::chrono::system_clock::now());

View File

@@ -44,7 +44,7 @@ int main()
using namespace mp_units::si::unit_symbols;
using namespace mp_units::international::unit_symbols;
constexpr quantity v1 = 110 * (km / h);
constexpr quantity v1 = 110 * km / h;
constexpr quantity v2 = 70 * mph;
constexpr quantity v3 = avg_speed(220. * km, 2 * h);
constexpr quantity v4 = avg_speed(isq::distance(140. * mi), 2 * isq::duration[h]);

View File

@@ -53,7 +53,7 @@ int main()
using state = kalman::state<quantity<isq::position_vector[m]>, quantity<isq::velocity[m / s]>>;
const auto interval = isq::duration(5 * s);
const state initial = {30 * km, 40 * (m / s)};
const state initial = {30 * km, 40 * m / s};
const quantity<isq::position_vector[m], int> measurements[] = {30'110 * m, 30'265 * m, 30'740 * m, 30'750 * m,
31'135 * m, 31'015 * m, 31'180 * m, 31'610 * m,
31'960 * m, 31'865 * m};

View File

@@ -53,7 +53,7 @@ int main()
using state = kalman::state<quantity<isq::position_vector[m]>, quantity<isq::velocity[m / s]>>;
const auto interval = isq::duration(5 * s);
const state initial = {30 * km, 50 * (m / s)};
const state initial = {30 * km, 50 * m / s};
const quantity<isq::position_vector[m], int> measurements[] = {30'160 * m, 30'365 * m, 30'890 * m, 31'050 * m,
31'785 * m, 32'215 * m, 33'130 * m, 34'510 * m,
36'010 * m, 37'265 * m};

View File

@@ -53,7 +53,7 @@ int main()
using state = kalman::state<quantity<isq::position_vector[m]>, quantity<isq::velocity[m / s]>,
quantity<isq::acceleration[m / s2]>>;
const auto interval = isq::duration(5. * s);
const state initial = {30 * km, 50 * (m / s), 0 * (m / s2)};
const state initial = {30 * km, 50 * m / s, 0 * m / s2};
const quantity<isq::position_vector[m], int> measurements[] = {30'160 * m, 30'365 * m, 30'890 * m, 31'050 * m,
31'785 * m, 32'215 * m, 33'130 * m, 34'510 * m,

View File

@@ -134,7 +134,7 @@ void example()
using namespace mp_units;
using namespace mp_units::si::unit_symbols;
const auto acceleration = isq::acceleration(measurement{9.8, 0.1} * (m / s2));
const auto acceleration = isq::acceleration(measurement{9.8, 0.1} * m / s2);
const auto time = measurement{1.2, 0.1} * s;
const QuantityOf<isq::velocity> auto velocity = acceleration * time;

View File

@@ -35,6 +35,7 @@ inline constexpr bool mp_units::is_vector<T> = true;
int main()
{
using namespace mp_units;
using namespace mp_units::si;
using namespace mp_units::si::unit_symbols;
@@ -52,7 +53,7 @@ int main()
std::cout << MP_UNITS_STD_FMT::format("- Boltzmann constant: {} = {:%.6eQ %q}\n",
1. * si2019::boltzmann_constant, (1. * si2019::boltzmann_constant).in(J / K));
std::cout << MP_UNITS_STD_FMT::format("- Avogadro constant: {} = {:%.8eQ %q}\n",
1. * si2019::avogadro_constant, (1. * si2019::avogadro_constant).in(1 / mol));
1. * si2019::avogadro_constant, (1. * si2019::avogadro_constant).in(one / mol));
std::cout << MP_UNITS_STD_FMT::format("- luminous efficacy: {} = {}\n",
1. * si2019::luminous_efficacy, (1. * si2019::luminous_efficacy).in(lm / W));
}

View File

@@ -61,7 +61,7 @@ template<QuantityOf<isq::energy> T1, QuantityOf<isq::wavenumber> T2, QuantityOf<
void print_line_si(const std::tuple<T1, T2, T3, T4, T5>& t)
{
MP_UNITS_STD_FMT::println("| {:<15} | {:<15} | {:<15} | {:<15} | {:<15} |", std::get<0>(t).in(eV),
std::get<1>(t).in(1 / cm), std::get<2>(t).in(THz), std::get<3>(t).in(K),
std::get<1>(t).in(one / cm), std::get<2>(t).in(THz), std::get<3>(t).in(K),
std::get<4>(t).in(um));
}
@@ -71,7 +71,7 @@ int main()
const auto t1 = std::make_tuple(q1, isq::wavenumber(q1 / (h * c)), isq::frequency(q1 / h),
isq::thermodynamic_temperature(q1 / kb), isq::wavelength(h * c / q1));
const auto q2 = 1. * isq::wavenumber[1 / cm];
const auto q2 = 1. * isq::wavenumber[one / cm];
const auto t2 = std::make_tuple(isq::energy(q2 * h * c), q2, isq::frequency(q2 * c),
isq::thermodynamic_temperature(q2 * h * c / kb), isq::wavelength(1 / q2));

View File

@@ -53,7 +53,7 @@ QUANTITY_SPEC(horizontal_length, isq::length);
QUANTITY_SPEC(horizontal_area, isq::area, horizontal_length* isq::width);
inline constexpr auto g = 1 * si::standard_gravity;
inline constexpr auto air_density = isq::mass_density(1.225 * (kg / m3));
inline constexpr auto air_density = isq::mass_density(1.225 * kg / m3);
class StorageTank {
quantity<horizontal_area[m2]> base_;
@@ -114,7 +114,7 @@ int main()
{
const quantity height = isq::height(200 * mm);
auto tank = RectangularStorageTank(horizontal_length(1'000 * mm), isq::width(500 * mm), height);
tank.set_contents_density(1'000 * isq::mass_density[kg / m3]);
tank.set_contents_density(1'000 * kg / m3);
const auto duration = std::chrono::seconds{200};
const quantity fill_time = value_cast<int>(quantity{duration}); // time since starting fill

View File

@@ -88,7 +88,7 @@ using type_list_of_base_dimension_less = expr_less<T1, T2, base_dimension_less>;
* For example:
*
* @code{.cpp}
* using frequency = decltype(1 / dim_time);
* using frequency = decltype(inverse(dim_time));
* using speed = decltype(dim_length / dim_time);
* using acceleration = decltype(dim_speed / dim_time);
* using force = decltype(dim_mass * dim_acceleration);
@@ -150,22 +150,14 @@ template<Dimension Lhs, Dimension Rhs>
Rhs{});
}
template<Dimension D>
[[nodiscard]] consteval Dimension auto operator/(int value, D)
{
gsl_Expects(value == 1);
return detail::expr_invert<derived_dimension, struct dimension_one>(D{});
}
template<Dimension D>
[[nodiscard]] consteval Dimension auto operator/(D, int) = delete;
template<Dimension Lhs, Dimension Rhs>
[[nodiscard]] consteval bool operator==(Lhs, Rhs)
{
return is_same_v<Lhs, Rhs>;
}
[[nodiscard]] consteval Dimension auto inverse(Dimension auto d) { return dimension_one / d; }
/**
* @brief Computes the value of a dimension raised to the `Num/Den` power
*

View File

@@ -432,7 +432,7 @@ template<auto R1, typename Rep1, auto R2, typename Rep2>
}
template<auto R, typename Rep, typename Value>
requires(!Quantity<Value>) &&
requires(!Quantity<Value>) && (!Reference<Value>) &&
detail::InvokeResultOf<get_quantity_spec(R).character, std::multiplies<>, Rep, const Value&>
[[nodiscard]] constexpr Quantity auto operator*(const quantity<R, Rep>& q, const Value& v)
{
@@ -440,7 +440,7 @@ template<auto R, typename Rep, typename Value>
}
template<typename Value, auto R, typename Rep>
requires(!Quantity<Value>) &&
requires(!Quantity<Value>) && (!Reference<Value>) &&
detail::InvokeResultOf<get_quantity_spec(R).character, std::multiplies<>, const Value&, Rep>
[[nodiscard]] constexpr Quantity auto operator*(const Value& v, const quantity<R, Rep>& q)
{
@@ -456,7 +456,7 @@ template<auto R1, typename Rep1, auto R2, typename Rep2>
}
template<auto R, typename Rep, typename Value>
requires(!Quantity<Value>) &&
requires(!Quantity<Value>) && (!Reference<Value>) &&
detail::InvokeResultOf<get_quantity_spec(R).character, std::divides<>, Rep, const Value&>
[[nodiscard]] constexpr Quantity auto operator/(const quantity<R, Rep>& q, const Value& v)
{
@@ -465,7 +465,7 @@ template<auto R, typename Rep, typename Value>
}
template<typename Value, auto R, typename Rep>
requires(!Quantity<Value>) &&
requires(!Quantity<Value>) && (!Reference<Value>) &&
detail::InvokeResultOf<get_quantity_spec(R).character, std::divides<>, const Value&, Rep>
[[nodiscard]] constexpr Quantity auto operator/(const Value& v, const quantity<R, Rep>& q)
{

View File

@@ -395,7 +395,7 @@ struct quantity_spec<Self, QS, Eq, Args...> : quantity_spec<Self, QS, Args...> {
* For example:
*
* @code{.cpp}
* auto frequency = 1 / period_duration;
* auto frequency = inverse(period_duration);
* auto area = pow<2>(length);
* auto speed = distance / duration;
* auto velocity = position_vector / duration;
@@ -497,7 +497,7 @@ template<QuantitySpec auto... From, QuantitySpec Q>
template<QuantitySpec Lhs, QuantitySpec Rhs>
[[nodiscard]] consteval QuantitySpec auto operator*(Lhs lhs, Rhs rhs)
{
return clone_kind_of<Lhs{}, Rhs{}>(
return detail::clone_kind_of<Lhs{}, Rhs{}>(
detail::expr_multiply<derived_quantity_spec, struct dimensionless, detail::type_list_of_quantity_spec_less>(
remove_kind(lhs), remove_kind(rhs)));
}
@@ -505,20 +505,11 @@ template<QuantitySpec Lhs, QuantitySpec Rhs>
template<QuantitySpec Lhs, QuantitySpec Rhs>
[[nodiscard]] consteval QuantitySpec auto operator/(Lhs lhs, Rhs rhs)
{
return clone_kind_of<Lhs{}, Rhs{}>(
return detail::clone_kind_of<Lhs{}, Rhs{}>(
detail::expr_divide<derived_quantity_spec, struct dimensionless, detail::type_list_of_quantity_spec_less>(
remove_kind(lhs), remove_kind(rhs)));
}
template<QuantitySpec QS>
[[nodiscard]] consteval QuantitySpec auto operator/(int value, QS qs)
{
gsl_Expects(value == 1);
return clone_kind_of<QS{}>(detail::expr_invert<derived_quantity_spec, struct dimensionless>(qs));
}
[[nodiscard]] consteval QuantitySpec auto operator/(QuantitySpec auto, int) = delete;
template<QuantitySpec Lhs, QuantitySpec Rhs>
[[nodiscard]] consteval bool operator==(Lhs, Rhs)
{
@@ -537,6 +528,8 @@ template<QuantitySpec Lhs, detail::QuantityKindSpec Rhs>
return is_same_v<Lhs, std::remove_const_t<decltype(remove_kind(rhs))>>;
}
[[nodiscard]] consteval QuantitySpec auto inverse(QuantitySpec auto q) { return dimensionless / q; }
/**
* @brief Computes the value of a quantity specification raised to the `Num/Den` power

View File

@@ -119,6 +119,8 @@ struct reference {
return {};
}
[[nodiscard]] friend consteval reference<inverse(Q), inverse(U)> inverse(reference) { return {}; }
/**
* @brief Computes the value of a reference raised to the `Num/Den` power
*
@@ -176,12 +178,48 @@ template<Reference auto R, RepresentationOf<get_quantity_spec(R).character> Rep>
class quantity;
template<typename Rep, Reference R>
requires RepresentationOf<std::remove_cvref_t<Rep>, get_quantity_spec(R{}).character>
[[nodiscard]] constexpr quantity<R{}, std::remove_cvref_t<Rep>> operator*(Rep&& lhs, R)
{
return make_quantity<R{}>(std::forward<Rep>(lhs));
}
void /*Use `q * (1 * r)` rather than `q * r`.*/ operator*(Quantity auto, Reference auto) = delete;
template<typename Rep, Reference R>
requires RepresentationOf<std::remove_cvref_t<Rep>, get_quantity_spec(R{}).character>
[[nodiscard]] constexpr quantity<inverse(R{}), std::remove_cvref_t<Rep>> operator/(Rep&& lhs, R)
{
return make_quantity<inverse(R{})>(std::forward<Rep>(lhs));
}
template<Reference R, typename Rep>
requires RepresentationOf<std::remove_cvref_t<Rep>, get_quantity_spec(R{}).character>
constexpr auto operator*(R, Rep&&) = delete;
template<Reference R, typename Rep>
requires RepresentationOf<std::remove_cvref_t<Rep>, get_quantity_spec(R{}).character>
constexpr auto operator/(R, Rep&&) = delete;
template<typename Q, Reference R>
requires Quantity<std::remove_cvref_t<Q>>
[[nodiscard]] constexpr Quantity auto operator*(Q&& q, R)
{
return make_quantity<std::remove_cvref_t<Q>::reference * R{}>(std::forward<Q>(q).numerical_value_);
}
template<typename Q, Reference R>
requires Quantity<std::remove_cvref_t<Q>>
[[nodiscard]] constexpr Quantity auto operator/(Q&& q, R)
{
return make_quantity<std::remove_cvref_t<Q>::reference / R{}>(std::forward<Q>(q).numerical_value_);
}
template<Reference R, typename Q>
requires Quantity<std::remove_cvref_t<Q>>
constexpr auto operator*(R, Q&& q) = delete;
template<Reference R, typename Q>
requires Quantity<std::remove_cvref_t<Q>>
constexpr auto operator/(R, Q&& q) = delete;
[[nodiscard]] consteval AssociatedUnit auto common_reference(AssociatedUnit auto u1, AssociatedUnit auto u2,
AssociatedUnit auto... rest)

View File

@@ -77,7 +77,7 @@ inline constexpr bool is_specialization_of_scaled_unit<scaled_unit<M, U>> = true
* @code{.cpp}
* inline constexpr struct second : named_unit<"s", time> {} second;
* inline constexpr struct metre : named_unit<"m", length> {} metre;
* inline constexpr struct hertz : named_unit<"Hz", 1 / second> {} hertz;
* inline constexpr struct hertz : named_unit<"Hz", inverse(second)> {} hertz;
* inline constexpr struct newton : named_unit<"N", kilogram * metre / square(second)> {} newton;
* inline constexpr struct degree_Celsius : named_unit<basic_symbol_text{"°C", "`C"}, kelvin> {} degree_Celsius;
* inline constexpr struct minute : named_unit<"min", mag<60> * second> {} minute;
@@ -212,8 +212,8 @@ struct is_one : std::false_type {};
* For example:
*
* @code{.cpp}
* static_assert(is_of_type<1 / second, derived_unit<one, per<second>>>);
* static_assert(is_of_type<1 / (1 / second), second>);
* static_assert(is_of_type<inverse(second), derived_unit<one, per<second>>>);
* static_assert(is_of_type<one / inverse(second), second>);
* static_assert(is_of_type<one * second, second>);
* static_assert(is_of_type<metre * metre, derived_unit<power<metre, 2>>>);
* static_assert(is_of_type<metre * second, derived_unit<metre, second>>);
@@ -430,6 +430,15 @@ template<Unit Lhs, Unit Rhs>
return detail::expr_multiply<derived_unit, struct one, detail::type_list_of_unit_less>(lhs, rhs);
}
/**
* Returns the result of multiplication with an inverse unit.
*/
template<Magnitude M, Unit U>
[[nodiscard]] MP_UNITS_CONSTEVAL Unit auto operator/(M mag, const U u)
{
return mag * inverse(u);
}
/**
* `scaled_unit` specializations have priority in this operation. This means that the library framework
* prevents passing it as an element to the `derived_unit`. In such case only the reference unit is passed
@@ -448,13 +457,8 @@ template<Unit Lhs, Unit Rhs>
return detail::expr_divide<derived_unit, struct one, detail::type_list_of_unit_less>(lhs, rhs);
}
[[nodiscard]] MP_UNITS_CONSTEVAL Unit auto operator/(int value, Unit auto u)
{
gsl_Expects(value == 1);
return detail::expr_invert<derived_unit, struct one>(u);
}
[[nodiscard]] MP_UNITS_CONSTEVAL Unit auto inverse(Unit auto u) { return one / u; }
[[nodiscard]] consteval Unit auto operator/(Unit auto, int) = delete;
namespace detail {

View File

@@ -37,7 +37,7 @@ inline constexpr struct erg : named_unit<"erg", dyne * centimetre> {} erg;
inline constexpr struct barye : named_unit<"Ba", gram / (centimetre * square(second))> {} barye;
inline constexpr struct poise : named_unit<"P", gram / (centimetre * second)> {} poise;
inline constexpr struct stokes : named_unit<"St", square(centimetre) / second> {} stokes;
inline constexpr struct kayser : named_unit<"K", 1 / centimetre> {} kayser;
inline constexpr struct kayser : named_unit<"K", one / centimetre> {} kayser;
// clang-format on
namespace unit_symbols {

View File

@@ -42,21 +42,21 @@ inline constexpr auto traffic_load = traffic_carried_intensity;
QUANTITY_SPEC(mean_queue_length, dimensionless);
QUANTITY_SPEC(loss_probability, dimensionless);
QUANTITY_SPEC(waiting_probability, dimensionless);
QUANTITY_SPEC(call_intensity, 1 / isq::duration);
QUANTITY_SPEC(call_intensity, inverse(isq::duration));
inline constexpr auto calling_rate = call_intensity;
QUANTITY_SPEC(completed_call_intensity, call_intensity);
QUANTITY_SPEC(storage_capacity, dimensionless, is_kind);
inline constexpr auto storage_size = storage_capacity;
QUANTITY_SPEC(equivalent_binary_storage_capacity, storage_capacity);
QUANTITY_SPEC(transfer_rate, storage_capacity / isq::duration);
QUANTITY_SPEC(period_of_data_elements, isq::period, 1 / transfer_rate);
QUANTITY_SPEC(period_of_data_elements, isq::period, inverse(transfer_rate));
QUANTITY_SPEC(binary_digit_rate, transfer_rate);
inline constexpr auto bit_rate = binary_digit_rate;
QUANTITY_SPEC(period_of_binary_digits, isq::period, 1 / binary_digit_rate);
QUANTITY_SPEC(period_of_binary_digits, isq::period, inverse(binary_digit_rate));
inline constexpr auto bit_period = period_of_binary_digits;
QUANTITY_SPEC(equivalent_binary_digit_rate, binary_digit_rate);
inline constexpr auto equivalent_bit_rate = bit_rate;
QUANTITY_SPEC(modulation_rate, 1 / isq::duration);
QUANTITY_SPEC(modulation_rate, inverse(isq::duration));
inline constexpr auto line_digit_rate = modulation_rate;
QUANTITY_SPEC(quantizing_distortion_power, isq::power);
QUANTITY_SPEC(carrier_power, isq::power);

View File

@@ -33,7 +33,7 @@ inline constexpr struct erlang : named_unit<"E", kind_of<traffic_intensity>> {}
inline constexpr struct bit : named_unit<"bit", one, kind_of<storage_capacity>> {} bit;
inline constexpr struct octet : named_unit<"o", mag<8> * bit> {} octet;
inline constexpr struct byte : named_unit<"B", mag<8> * bit> {} byte;
inline constexpr struct baud : named_unit<"Bd", 1 / si::second, kind_of<modulation_rate>> {} baud;
inline constexpr struct baud : named_unit<"Bd", one / si::second, kind_of<modulation_rate>> {} baud;
// clang-format on
} // namespace mp_units::iec80000

View File

@@ -30,7 +30,7 @@
namespace mp_units::isq {
// TODO Add all the remaining ISQ definitions
QUANTITY_SPEC(activity, 1 / duration);
QUANTITY_SPEC(activity, inverse(duration));
QUANTITY_SPEC(absorbed_dose, energy / mass);
QUANTITY_SPEC(ionizing_radiation_quality_factor, dimensionless);
QUANTITY_SPEC(dose_equivalent, absorbed_dose* ionizing_radiation_quality_factor);

View File

@@ -63,7 +63,7 @@ QUANTITY_SPEC(phase_speed_of_electromagnetic_waves, angular_frequency / angular_
QUANTITY_SPEC(speed_of_light_in_vacuum, speed);
inline constexpr auto light_speed_in_vacuum = speed_of_light_in_vacuum;
inline constexpr auto luminal_speed = speed_of_light_in_vacuum;
QUANTITY_SPEC(electric_constant, 1 / (magnetic_constant * pow<2>(speed_of_light_in_vacuum)));
QUANTITY_SPEC(electric_constant, inverse(magnetic_constant* pow<2>(speed_of_light_in_vacuum)));
inline constexpr auto permittivity_of_vacuum = electric_constant;
QUANTITY_SPEC(permittivity, electric_flux_density / electric_field_strength, quantity_character::scalar);
QUANTITY_SPEC(relative_permittivity, dimensionless, permittivity / electric_constant);
@@ -101,18 +101,18 @@ QUANTITY_SPEC(magnetomotive_force, electric_current, magnetic_field_strength* po
QUANTITY_SPEC(current_linkage, electric_current);
QUANTITY_SPEC(number_of_turns_in_a_winding, dimensionless);
QUANTITY_SPEC(reluctance, magnetic_tension / magnetic_flux);
QUANTITY_SPEC(permeance, 1 / reluctance);
QUANTITY_SPEC(permeance, inverse(reluctance));
QUANTITY_SPEC(inductance, linked_flux / electric_current);
inline constexpr auto self_inductance = inductance;
QUANTITY_SPEC(mutual_inductance, linked_flux / electric_current);
QUANTITY_SPEC(coupling_factor, dimensionless, mutual_inductance / pow<1, 2>(pow<2>(self_inductance)));
QUANTITY_SPEC(leakage_factor, dimensionless, pow<2>(coupling_factor));
QUANTITY_SPEC(conductivity, electric_current_density / electric_field_strength, quantity_character::scalar);
QUANTITY_SPEC(resistivity, 1 / conductivity);
QUANTITY_SPEC(resistivity, inverse(conductivity));
QUANTITY_SPEC(electromagnetism_power, power, voltage* electric_current);
inline constexpr auto instantaneous_power = electromagnetism_power;
QUANTITY_SPEC(resistance, voltage / electric_current);
QUANTITY_SPEC(conductance, 1 / resistance);
QUANTITY_SPEC(conductance, inverse(resistance));
QUANTITY_SPEC(phase_difference, phase_angle);
QUANTITY_SPEC(electric_current_phasor, electric_current);
QUANTITY_SPEC(voltage_phasor, voltage);
@@ -121,15 +121,15 @@ inline constexpr auto complex_impedance = impedance;
QUANTITY_SPEC(resistance_to_alternating_current, impedance);
QUANTITY_SPEC(reactance, impedance);
QUANTITY_SPEC(modulus_of_impedance, impedance);
QUANTITY_SPEC(admittance, 1 / impedance);
QUANTITY_SPEC(admittance, inverse(impedance));
inline constexpr auto complex_admittance = admittance;
QUANTITY_SPEC(conductance_for_alternating_current, admittance);
QUANTITY_SPEC(susceptance, admittance);
QUANTITY_SPEC(modulus_of_admittance, admittance);
QUANTITY_SPEC(quality_factor, dimensionless, reactance / resistance);
QUANTITY_SPEC(loss_factor, dimensionless, 1 / quality_factor);
QUANTITY_SPEC(loss_factor, dimensionless, inverse(quality_factor));
QUANTITY_SPEC(loss_angle, angular_measure);
QUANTITY_SPEC(active_power, 1 / period * (instantaneous_power * time));
QUANTITY_SPEC(active_power, inverse(period) * (instantaneous_power * time));
QUANTITY_SPEC(apparent_power, voltage* electric_current);
QUANTITY_SPEC(power_factor, dimensionless, active_power / apparent_power);
QUANTITY_SPEC(complex_power, voltage_phasor* electric_current_phasor);

View File

@@ -30,7 +30,7 @@ namespace mp_units::isq {
QUANTITY_SPEC(mass_density, mass / volume);
inline constexpr auto density = mass_density;
QUANTITY_SPEC(specific_volume, 1 / mass_density);
QUANTITY_SPEC(specific_volume, inverse(mass_density));
QUANTITY_SPEC(relative_mass_density, mass_density / mass_density);
inline constexpr auto relative_density = relative_mass_density;
QUANTITY_SPEC(surface_mass_density, mass / area);
@@ -70,7 +70,7 @@ QUANTITY_SPEC(modulus_of_rigidity, shear_stress / shear_strain);
inline constexpr auto shear_modulus = modulus_of_rigidity;
QUANTITY_SPEC(modulus_of_compression, pressure / relative_volume_strain);
inline constexpr auto bulk_modulus = modulus_of_compression;
QUANTITY_SPEC(compressibility, 1 / volume * (volume / pressure));
QUANTITY_SPEC(compressibility, inverse(volume) * (volume / pressure));
QUANTITY_SPEC(second_axial_moment_of_area, pow<2>(radial_distance) * area);
QUANTITY_SPEC(second_polar_moment_of_area, pow<2>(radial_distance) * area);
QUANTITY_SPEC(section_modulus, second_axial_moment_of_area / radial_distance);

View File

@@ -42,7 +42,7 @@ QUANTITY_SPEC(radial_distance, distance);
QUANTITY_SPEC(position_vector, length, quantity_character::vector);
QUANTITY_SPEC(displacement, length, quantity_character::vector);
QUANTITY_SPEC(radius_of_curvature, radius);
QUANTITY_SPEC(curvature, 1 / radius_of_curvature);
QUANTITY_SPEC(curvature, inverse(radius_of_curvature));
QUANTITY_SPEC(area, pow<2>(length));
QUANTITY_SPEC(volume, pow<3>(length));
QUANTITY_SPEC(angular_measure, dimensionless, arc_length / radius, is_kind);
@@ -61,25 +61,25 @@ QUANTITY_SPEC(period_duration, duration);
inline constexpr auto period = period_duration;
QUANTITY_SPEC(time_constant, duration);
QUANTITY_SPEC(rotation, dimensionless);
QUANTITY_SPEC(frequency, 1 / period_duration);
QUANTITY_SPEC(frequency, inverse(period_duration));
QUANTITY_SPEC(rotational_frequency, rotation / duration);
QUANTITY_SPEC(angular_frequency, phase_angle / duration);
QUANTITY_SPEC(wavelength, length);
QUANTITY_SPEC(repetency, 1 / wavelength);
QUANTITY_SPEC(repetency, inverse(wavelength));
inline constexpr auto wavenumber = repetency;
QUANTITY_SPEC(wave_vector, repetency, quantity_character::vector);
QUANTITY_SPEC(angular_repetency, 1 / wavelength);
QUANTITY_SPEC(angular_repetency, inverse(wavelength));
inline constexpr auto angular_wavenumber = angular_repetency;
QUANTITY_SPEC(phase_velocity, angular_frequency / angular_repetency);
inline constexpr auto phase_speed = phase_velocity;
QUANTITY_SPEC(group_velocity, angular_frequency / angular_repetency);
inline constexpr auto group_speed = group_velocity;
QUANTITY_SPEC(damping_coefficient, 1 / time_constant);
QUANTITY_SPEC(damping_coefficient, inverse(time_constant));
QUANTITY_SPEC(logarithmic_decrement, dimensionless, damping_coefficient* period_duration);
QUANTITY_SPEC(attenuation, 1 / distance);
QUANTITY_SPEC(attenuation, inverse(distance));
inline constexpr auto extinction = attenuation;
QUANTITY_SPEC(phase_coefficient, phase_angle / path_length);
QUANTITY_SPEC(propagation_coefficient, 1 / length); // γ = α + iβ where α denotes attenuation
QUANTITY_SPEC(propagation_coefficient, inverse(length)); // γ = α + iβ where α denotes attenuation
// and β the phase coefficient of a plane wave
} // namespace mp_units::isq

View File

@@ -30,12 +30,12 @@
namespace mp_units::isq {
QUANTITY_SPEC(Celsius_temperature, thermodynamic_temperature); // TODO should we account for T0 here?
QUANTITY_SPEC(linear_expansion_coefficient, 1 / length * (length / thermodynamic_temperature));
QUANTITY_SPEC(cubic_expansion_coefficient, 1 / volume * (volume / thermodynamic_temperature));
QUANTITY_SPEC(relative_pressure_coefficient, 1 / pressure * (pressure / thermodynamic_temperature));
QUANTITY_SPEC(linear_expansion_coefficient, inverse(length) * (length / thermodynamic_temperature));
QUANTITY_SPEC(cubic_expansion_coefficient, inverse(volume) * (volume / thermodynamic_temperature));
QUANTITY_SPEC(relative_pressure_coefficient, inverse(pressure) * (pressure / thermodynamic_temperature));
QUANTITY_SPEC(pressure_coefficient, pressure / thermodynamic_temperature);
QUANTITY_SPEC(isothermal_compressibility, 1 / volume * (volume / pressure)); // TODO how to handle "negative" part
QUANTITY_SPEC(isentropic_compressibility, 1 / volume * (volume / pressure)); // TODO how to handle "negative" part
QUANTITY_SPEC(isothermal_compressibility, inverse(volume) * (volume / pressure)); // TODO how to handle "negative" part
QUANTITY_SPEC(isentropic_compressibility, inverse(volume) * (volume / pressure)); // TODO how to handle "negative" part
// energy definition moved to mechanics
QUANTITY_SPEC(heat, energy);
inline constexpr auto amount_of_heat = heat;
@@ -45,10 +45,10 @@ QUANTITY_SPEC(density_of_heat_flow_rate, heat_flow_rate / area);
QUANTITY_SPEC(thermal_conductivity, density_of_heat_flow_rate*(length / thermodynamic_temperature));
QUANTITY_SPEC(coefficient_of_heat_transfer, density_of_heat_flow_rate / thermodynamic_temperature);
QUANTITY_SPEC(surface_coefficient_of_heat_transfer, density_of_heat_flow_rate / thermodynamic_temperature);
QUANTITY_SPEC(thermal_insulance, 1 / coefficient_of_heat_transfer);
QUANTITY_SPEC(thermal_insulance, inverse(coefficient_of_heat_transfer));
inline constexpr auto coefficient_of_thermal_insulance = thermal_insulance;
QUANTITY_SPEC(thermal_resistance, thermodynamic_temperature / heat_flow_rate);
QUANTITY_SPEC(thermal_conductance, 1 / thermal_resistance);
QUANTITY_SPEC(thermal_conductance, inverse(thermal_resistance));
QUANTITY_SPEC(heat_capacity, heat / thermodynamic_temperature);
QUANTITY_SPEC(specific_heat_capacity, heat_capacity / mass);
QUANTITY_SPEC(specific_heat_capacity_at_constant_pressure, specific_heat_capacity);

View File

@@ -36,8 +36,8 @@ inline constexpr struct electronvolt : named_unit<"eV"> {} electronvolt;
inline constexpr struct gigaelectronvolt : decltype(si::giga<electronvolt>) {} gigaelectronvolt;
// system references
inline constexpr struct time : system_reference<isq::time, 1 / gigaelectronvolt> {} time;
inline constexpr struct length : system_reference<isq::length, 1 / gigaelectronvolt> {} length;
inline constexpr struct time : system_reference<isq::time, inverse(gigaelectronvolt)> {} time;
inline constexpr struct length : system_reference<isq::length, inverse(gigaelectronvolt)> {} length;
inline constexpr struct mass : system_reference<isq::mass, gigaelectronvolt> {} mass;
inline constexpr struct velocity : system_reference<isq::velocity, one> {} velocity;
inline constexpr struct speed : system_reference<isq::speed, one> {} speed;

View File

@@ -41,7 +41,7 @@ inline constexpr struct 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> * (1 / 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

View File

@@ -46,7 +46,7 @@ inline constexpr struct candela : named_unit<"cd", kind_of<isq::luminous_intensi
// derived named units
inline constexpr struct radian : named_unit<"rad", metre / metre, kind_of<isq::angular_measure>> {} radian;
inline constexpr struct steradian : named_unit<"sr", square(metre) / square(metre), kind_of<isq::solid_angular_measure>> {} steradian;
inline constexpr struct hertz : named_unit<"Hz", 1 / second, kind_of<isq::frequency>> {} hertz;
inline constexpr struct hertz : named_unit<"Hz", one / second, kind_of<isq::frequency>> {} hertz;
inline constexpr struct newton : named_unit<"N", kilogram * metre / square(second)> {} newton;
#ifdef pascal
#pragma push_macro("pascal")
@@ -64,14 +64,14 @@ inline constexpr struct coulomb : named_unit<"C", ampere * second> {} coulomb;
inline constexpr struct volt : named_unit<"V", watt / ampere> {} volt;
inline constexpr struct farad : named_unit<"F", coulomb / volt> {} farad;
inline constexpr struct ohm : named_unit<basic_symbol_text{"Ω", "ohm"}, volt / ampere> {} ohm;
inline constexpr struct siemens : named_unit<"S", 1 / ohm> {} siemens;
inline constexpr struct siemens : named_unit<"S", one / ohm> {} siemens;
inline constexpr struct weber : named_unit<"Wb", volt * second> {} weber;
inline constexpr struct tesla : named_unit<"T", weber / square(metre)> {} tesla;
inline constexpr struct henry : named_unit<"H", weber / ampere> {} henry;
inline constexpr struct degree_Celsius : named_unit<basic_symbol_text{"°C", "`C"}, kelvin> {} degree_Celsius;
inline constexpr struct lumen : named_unit<"lm", candela * steradian> {} lumen;
inline constexpr struct lux : named_unit<"lx", lumen / square(metre)> {} lux;
inline constexpr struct becquerel : named_unit<"Bq", 1 / second, kind_of<isq::activity>> {} becquerel;
inline constexpr struct becquerel : named_unit<"Bq", one / second, kind_of<isq::activity>> {} becquerel;
inline constexpr struct gray : named_unit<"Gy", joule / kilogram, kind_of<isq::absorbed_dose>> {} gray;
inline constexpr struct sievert : named_unit<"Sv", joule / kilogram, kind_of<isq::dose_equivalent>> {} sievert;
inline constexpr struct katal : named_unit<"kat", mole / second> {} katal;

View File

@@ -167,7 +167,7 @@ TEST_CASE("operator<< on a quantity", "[text][ostream][fmt]")
SECTION("compressibility")
{
const auto q = 123 * isq::compressibility[1 / Pa];
const auto q = 123 * isq::compressibility[one / Pa];
os << q;
SECTION("iostream") { CHECK(os.str() == "123 1/Pa"); }

View File

@@ -311,7 +311,7 @@ TEST_CASE("vector of quantities", "[la]")
SECTION("to scalar magnitude")
{
const vector<quantity<isq::velocity[km / h], int>> v = {2 * (km / h), 3 * (km / h), 6 * (km / h)};
const vector<quantity<isq::velocity[km / h], int>> v = {2 * km / h, 3 * km / h, 6 * km / h};
const auto speed = get_magnitude<isq::speed>(v);
CHECK(speed.numerical_value_ref_in(km / h) == 7);
}
@@ -384,12 +384,12 @@ TEST_CASE("vector of quantities", "[la]")
SECTION("multiply by scalar quantity")
{
const vector<quantity<isq::velocity[m / s], int>> v = {1 * (m / s), 2 * (m / s), 3 * (m / s)};
const vector<quantity<isq::velocity[m / s], int>> v = {1 * m / s, 2 * m / s, 3 * m / s};
SECTION("integral")
{
const auto mass = 2 * isq::mass[kg];
const auto result = vector<quantity<isq::momentum[N * s], int>>{2 * (N * s), 4 * (N * s), 6 * (N * s)};
const auto result = vector<quantity<isq::momentum[N * s], int>>{2 * N * s, 4 * N * s, 6 * N * s};
SECTION("derived_quantity_spec")
{
@@ -417,7 +417,7 @@ TEST_CASE("vector of quantities", "[la]")
SECTION("floating-point")
{
const auto mass = 0.5 * isq::mass[kg];
const auto result = vector<quantity<isq::momentum[N * s], double>>{0.5 * (N * s), 1. * (N * s), 1.5 * (N * s)};
const auto result = vector<quantity<isq::momentum[N * s], double>>{0.5 * N * s, 1. * N * s, 1.5 * N * s};
SECTION("derived_quantity_spec")
{
@@ -453,7 +453,7 @@ TEST_CASE("vector of quantities", "[la]")
SECTION("derived_quantity_spec")
{
CHECK(pos / dur == vector<quantity<isq::velocity[km / h], int>>{15 * (km / h), 10 * (km / h), 5 * (km / h)});
CHECK(pos / dur == vector<quantity<isq::velocity[km / h], int>>{15 * km / h, 10 * km / h, 5 * km / h});
}
// no way to apply quantity_cast to sub-components
@@ -461,7 +461,7 @@ TEST_CASE("vector of quantities", "[la]")
SECTION("quantity of velocity")
{
const vector<quantity<isq::velocity[km / h], int>> v = pos / dur;
CHECK(v == vector<quantity<isq::velocity[km / h], int>>{15 * (km / h), 10 * (km / h), 5 * (km / h)});
CHECK(v == vector<quantity<isq::velocity[km / h], int>>{15 * km / h, 10 * km / h, 5 * km / h});
}
}
@@ -471,8 +471,7 @@ TEST_CASE("vector of quantities", "[la]")
SECTION("derived_quantity_spec")
{
CHECK(pos / dur ==
vector<quantity<isq::velocity[km / h], double>>{60. * (km / h), 40. * (km / h), 20. * (km / h)});
CHECK(pos / dur == vector<quantity<isq::velocity[km / h], double>>{60. * km / h, 40. * km / h, 20. * km / h});
}
// no way to apply quantity_cast to sub-components
@@ -480,7 +479,7 @@ TEST_CASE("vector of quantities", "[la]")
SECTION("quantity of velocity")
{
const vector<quantity<isq::velocity[km / h], double>> v = pos / dur;
CHECK(v == vector<quantity<isq::velocity[km / h], double>>{60. * (km / h), 40. * (km / h), 20. * (km / h)});
CHECK(v == vector<quantity<isq::velocity[km / h], double>>{60. * km / h, 40. * km / h, 20. * km / h});
}
}
}
@@ -490,7 +489,6 @@ TEST_CASE("vector of quantities", "[la]")
const vector<quantity<isq::position_vector[m], int>> r = {3 * m, 0 * m, 0 * m};
const vector<quantity<isq::force[N], int>> f = {0 * N, 10 * N, 0 * N};
CHECK(cross_product(r, f) ==
vector<quantity<isq::moment_of_force[N * m], int>>{0 * (N * m), 0 * (N * m), 30 * (N * m)});
CHECK(cross_product(r, f) == vector<quantity<isq::moment_of_force[N * m], int>>{0 * N * m, 0 * N * m, 30 * N * m});
}
}

View File

@@ -40,24 +40,24 @@ using namespace mp_units::cgs::unit_symbols;
static_assert(isq::length(100 * cm) == isq::length(1 * si::metre));
static_assert(isq::mass(1000 * g) == isq::mass(1 * si::kilogram));
static_assert(isq::time(1 * s) == isq::time(1 * si::second));
static_assert(isq::speed(100 * (cm / s)) == isq::speed(1 * (si::metre / si::second)));
static_assert(isq::acceleration(100 * Gal) == isq::acceleration(1 * (si::metre / square(si::second))));
static_assert(isq::speed(100 * cm / s) == isq::speed(1 * si::metre / si::second));
static_assert(isq::acceleration(100 * Gal) == isq::acceleration(1 * si::metre / square(si::second)));
static_assert(isq::force(100'000 * dyn) == isq::force(1 * si::newton));
static_assert(isq::energy(10'000'000 * erg) == isq::energy(1 * si::joule));
static_assert(isq::power(10'000'000 * (erg / s)) == isq::power(1 * si::watt));
static_assert(isq::power(10'000'000 * erg / s) == isq::power(1 * si::watt));
static_assert(isq::pressure(10 * Ba) == isq::pressure(1 * si::pascal));
static_assert(isq::dynamic_viscosity(10 * P) == isq::dynamic_viscosity(1 * (si::pascal * si::second)));
static_assert(isq::kinematic_viscosity(10'000 * St) == isq::kinematic_viscosity(1 * (square(si::metre) / si::second)));
static_assert(isq::wavenumber(1 * K) == isq::wavenumber(100 * (1 / si::metre)));
static_assert(isq::dynamic_viscosity(10 * P) == isq::dynamic_viscosity(1 * si::pascal * si::second));
static_assert(isq::kinematic_viscosity(10'000 * St) == isq::kinematic_viscosity(1 * square(si::metre) / si::second));
static_assert(isq::wavenumber(1 * K) == isq::wavenumber(100 / si::metre));
static_assert(10'000'000 * erg + 1 * si::joule == 2 * si::joule);
static_assert(1 * si::joule + 10'000'000 * erg == 2 * si::joule);
static_assert(is_of_type<10'000'000 * erg + 1 * si::joule, quantity<erg, int>>);
static_assert(is_of_type<1 * si::joule + 10'000'000 * erg, quantity<erg, int>>);
static_assert(1 * K + 100 * (1 / si::metre) == 2 * K);
static_assert(100 * (1 / si::metre) + 1 * K == 2 * K);
static_assert(is_of_type<1 * K + 100 * (1 / si::metre), quantity<1 / si::metre, int>>);
static_assert(is_of_type<100 * (1 / si::metre) + 1 * K, quantity<1 / si::metre, int>>);
static_assert(1 * K + 100 / si::metre == 2 * K);
static_assert(100 / si::metre + 1 * K == 2 * K);
static_assert(is_of_type<1 * K + 100 / si::metre, quantity<inverse(si::metre), int>>);
static_assert(is_of_type<100 / si::metre + 1 * K, quantity<inverse(si::metre), int>>);
} // namespace

View File

@@ -114,7 +114,7 @@ static_assert(quantity{std::chrono::years{1}} == 31556952 * s);
// operators
static_assert(quantity{1s} + 1 * s == 2 * s);
static_assert(quantity{1s} + 1 * min == 61 * s);
static_assert(10 * m / quantity{2s} == 5 * (m / s));
static_assert(10 * m / quantity{2s} == 5 * m / s);
static_assert(quantity_point{sys_seconds{1s}} + 1 * s == chrono_point_origin<std::chrono::system_clock> + 2 * s);
static_assert(quantity_point{sys_seconds{1s}} + 1 * min == chrono_point_origin<std::chrono::system_clock> + 61 * s);

View File

@@ -48,7 +48,7 @@ struct dim_speed : decltype(isq::dim_length / isq::dim_time) {};
// BaseDimension
static_assert(detail::BaseDimension<struct isq::dim_length>);
static_assert(!detail::BaseDimension<std::remove_const_t<decltype(isq::dim_length / isq::dim_time)>>);
static_assert(!detail::BaseDimension<std::remove_const_t<decltype(1 / isq::dim_time)>>);
static_assert(!detail::BaseDimension<std::remove_const_t<decltype(inverse(isq::dim_time))>>);
static_assert(!detail::BaseDimension<std::remove_const_t<decltype(pow<2>(isq::dim_length))>>);
static_assert(!detail::BaseDimension<derived_dimension<struct isq::dim_length, per<struct isq::dim_time>>>);
static_assert(!detail::BaseDimension<dim_speed>);
@@ -58,7 +58,7 @@ static_assert(!detail::BaseDimension<int>);
// DerivedDimension
static_assert(detail::DerivedDimension<std::remove_const_t<decltype(isq::dim_length / isq::dim_time)>>);
static_assert(detail::DerivedDimension<std::remove_const_t<decltype(1 / isq::dim_time)>>);
static_assert(detail::DerivedDimension<std::remove_const_t<decltype(inverse(isq::dim_time))>>);
static_assert(detail::DerivedDimension<std::remove_const_t<decltype(pow<2>(isq::dim_length))>>);
static_assert(detail::DerivedDimension<derived_dimension<struct isq::dim_length, per<struct isq::dim_time>>>);
static_assert(detail::DerivedDimension<dim_speed>);
@@ -70,7 +70,7 @@ static_assert(!detail::DerivedDimension<int>);
// Dimension
static_assert(Dimension<struct isq::dim_length>);
static_assert(Dimension<std::remove_const_t<decltype(isq::dim_length / isq::dim_time)>>);
static_assert(Dimension<std::remove_const_t<decltype(1 / isq::dim_time)>>);
static_assert(Dimension<std::remove_const_t<decltype(inverse(isq::dim_time))>>);
static_assert(Dimension<std::remove_const_t<decltype(pow<2>(isq::dim_length))>>);
static_assert(Dimension<derived_dimension<struct isq::dim_length, per<struct isq::dim_time>>>);
static_assert(Dimension<dim_speed>);
@@ -137,7 +137,7 @@ static_assert(Unit<struct si::kilogram>);
static_assert(Unit<std::remove_const_t<decltype(si::kilo<si::gram>)>>);
static_assert(Unit<struct natural::electronvolt>);
static_assert(Unit<std::remove_const_t<decltype(si::metre / si::second)>>);
static_assert(Unit<std::remove_const_t<decltype(1 / si::second)>>);
static_assert(Unit<std::remove_const_t<decltype(inverse(si::second))>>);
static_assert(Unit<std::remove_const_t<decltype(mag<10> * si::second)>>);
static_assert(Unit<std::remove_const_t<decltype(square(si::metre))>>);
static_assert(Unit<std::remove_const_t<decltype(pow<2>(si::metre))>>);
@@ -161,7 +161,7 @@ static_assert(detail::NamedUnit<struct natural::electronvolt>);
static_assert(!detail::NamedUnit<struct si::kilogram>);
static_assert(!detail::NamedUnit<std::remove_const_t<decltype(si::kilo<si::gram>)>>);
static_assert(!detail::NamedUnit<std::remove_const_t<decltype(si::metre / si::second)>>);
static_assert(!detail::NamedUnit<std::remove_const_t<decltype(1 / si::second)>>);
static_assert(!detail::NamedUnit<std::remove_const_t<decltype(inverse(si::second))>>);
static_assert(!detail::NamedUnit<std::remove_const_t<decltype(mag<10> * si::second)>>);
static_assert(!detail::NamedUnit<std::remove_const_t<decltype(square(si::metre))>>);
static_assert(!detail::NamedUnit<std::remove_const_t<decltype(pow<2>(si::metre))>>);
@@ -185,7 +185,7 @@ static_assert(PrefixableUnit<struct natural::electronvolt>);
static_assert(!PrefixableUnit<struct si::kilogram>);
static_assert(!PrefixableUnit<std::remove_const_t<decltype(si::kilo<si::gram>)>>);
static_assert(!PrefixableUnit<std::remove_const_t<decltype(si::metre / si::second)>>);
static_assert(!PrefixableUnit<std::remove_const_t<decltype(1 / si::second)>>);
static_assert(!PrefixableUnit<std::remove_const_t<decltype(inverse(si::second))>>);
static_assert(!PrefixableUnit<std::remove_const_t<decltype(mag<10> * si::second)>>);
static_assert(!PrefixableUnit<std::remove_const_t<decltype(square(si::metre))>>);
static_assert(!PrefixableUnit<std::remove_const_t<decltype(pow<2>(si::metre))>>);
@@ -209,7 +209,7 @@ static_assert(!AssociatedUnit<struct natural::electronvolt>);
static_assert(AssociatedUnit<struct si::kilogram>);
static_assert(AssociatedUnit<std::remove_const_t<decltype(si::kilo<si::gram>)>>);
static_assert(AssociatedUnit<std::remove_const_t<decltype(si::metre / si::second)>>);
static_assert(AssociatedUnit<std::remove_const_t<decltype(1 / si::second)>>);
static_assert(AssociatedUnit<std::remove_const_t<decltype(inverse(si::second))>>);
static_assert(AssociatedUnit<std::remove_const_t<decltype(mag<10> * si::second)>>);
static_assert(AssociatedUnit<std::remove_const_t<decltype(square(si::metre))>>);
static_assert(AssociatedUnit<std::remove_const_t<decltype(pow<2>(si::metre))>>);
@@ -232,7 +232,7 @@ static_assert(UnitOf<struct si::metre, isq::length>);
static_assert(UnitOf<struct si::metre, isq::radius>);
static_assert(UnitOf<struct si::kilogram, isq::mass>);
static_assert(UnitOf<struct si::hertz, isq::frequency>);
static_assert(UnitOf<struct si::hertz, 1 / isq::time>);
static_assert(UnitOf<struct si::hertz, inverse(isq::time)>);
static_assert(UnitOf<struct one, dimensionless>);
static_assert(UnitOf<struct percent, dimensionless>);
static_assert(UnitOf<struct si::radian, isq::angular_measure>);

View File

@@ -41,8 +41,8 @@ inline constexpr struct time_ : base_dimension<"T"> {} time;
QUANTITY_SPEC_(q_time, time);
inline constexpr struct second_ : named_unit<"s", kind_of<q_time>> {} second;
inline constexpr auto frequency = 1 / time;
inline constexpr auto action = 1 / time;
inline constexpr auto frequency = inverse(time);
inline constexpr auto action = inverse(time);
inline constexpr auto area = length * length;
inline constexpr auto volume = area * length;
inline constexpr auto speed = length / time;
@@ -71,13 +71,13 @@ static_assert(detail::DerivedDimension<decltype(length / length)>); // dimensio
static_assert(detail::BaseDimension<decltype(speed * time)>); // length
// derived dimension expression template syntax verification
static_assert(is_of_type<1 / time, derived_dimension<dimension_one_, per<time_>>>);
static_assert(is_of_type<1 / (1 / time), time_>);
static_assert(is_of_type<inverse(time), derived_dimension<dimension_one_, per<time_>>>);
static_assert(is_of_type<dimension_one / inverse(time), time_>);
static_assert(is_of_type<dimension_one * time, time_>);
static_assert(is_of_type<time * dimension_one, time_>);
static_assert(is_of_type<dimension_one * (1 / time), derived_dimension<dimension_one_, per<time_>>>);
static_assert(is_of_type<1 / time * dimension_one, derived_dimension<dimension_one_, per<time_>>>);
static_assert(is_of_type<dimension_one * inverse(time), derived_dimension<dimension_one_, per<time_>>>);
static_assert(is_of_type<inverse(time) * dimension_one, derived_dimension<dimension_one_, per<time_>>>);
static_assert(is_of_type<length * time, derived_dimension<length_, time_>>);
static_assert(is_of_type<length * length, derived_dimension<mp_units::power<length_, 2>>>);
@@ -88,18 +88,19 @@ static_assert(is_of_type<length * time * length, derived_dimension<mp_units::pow
static_assert(is_of_type<length*(time* length), derived_dimension<mp_units::power<length_, 2>, time_>>);
static_assert(is_of_type<time*(length* length), derived_dimension<mp_units::power<length_, 2>, time_>>);
static_assert(is_of_type<1 / time * length, derived_dimension<length_, per<time_>>>);
static_assert(is_of_type<1 / time * time, dimension_one_>);
static_assert(is_of_type<inverse(time) * length, derived_dimension<length_, per<time_>>>);
static_assert(is_of_type<inverse(time) * time, dimension_one_>);
static_assert(is_of_type<time / dimension_one, time_>);
static_assert(is_of_type<1 / time / dimension_one, derived_dimension<dimension_one_, per<time_>>>);
static_assert(is_of_type<inverse(time) / dimension_one, derived_dimension<dimension_one_, per<time_>>>);
static_assert(is_of_type<length / time * time, length_>);
static_assert(is_of_type<1 / time * (1 / time), derived_dimension<dimension_one_, per<mp_units::power<time_, 2>>>>);
static_assert(is_of_type<1 / (time * time), derived_dimension<dimension_one_, per<mp_units::power<time_, 2>>>>);
static_assert(is_of_type<1 / (1 / (time * time)), derived_dimension<mp_units::power<time_, 2>>>);
static_assert(
is_of_type<inverse(time) * inverse(time), derived_dimension<dimension_one_, per<mp_units::power<time_, 2>>>>);
static_assert(is_of_type<inverse(time* time), derived_dimension<dimension_one_, per<mp_units::power<time_, 2>>>>);
static_assert(is_of_type<dimension_one / inverse(time* time), derived_dimension<mp_units::power<time_, 2>>>);
static_assert(is_of_type<length / time * (1 / time), derived_dimension<length_, per<mp_units::power<time_, 2>>>>);
static_assert(is_of_type<length / time * inverse(time), derived_dimension<length_, per<mp_units::power<time_, 2>>>>);
static_assert(is_of_type<length / time*(length / time),
derived_dimension<mp_units::power<length_, 2>, per<mp_units::power<time_, 2>>>>);
static_assert(is_of_type<length / time*(time / length), dimension_one_>);
@@ -107,7 +108,7 @@ static_assert(is_of_type<length / time*(time / length), dimension_one_>);
static_assert(is_of_type<speed / acceleration, time_>);
static_assert(is_of_type<acceleration / speed, derived_dimension<dimension_one_, per<time_>>>);
static_assert(is_of_type<speed * speed / length, derived_dimension<length_, per<mp_units::power<time_, 2>>>>);
static_assert(is_of_type<1 / (speed * speed) * length, derived_dimension<mp_units::power<time_, 2>, per<length_>>>);
static_assert(is_of_type<inverse(speed* speed) * length, derived_dimension<mp_units::power<time_, 2>, per<length_>>>);
static_assert(is_of_type<(length * length) * (time * time),
derived_dimension<mp_units::power<length_, 2>, mp_units::power<time_, 2>>>);
@@ -172,8 +173,8 @@ static_assert(speed == speed);
// comparisons of equivalent dimensions (named vs unnamed/derived)
static_assert(length / length == dimension_one);
static_assert(1 / time == frequency);
static_assert(1 / frequency == time);
static_assert(inverse(time) == frequency);
static_assert(inverse(frequency) == time);
static_assert(frequency * time == dimension_one);
static_assert(length * length == area);

View File

@@ -36,10 +36,10 @@ using namespace mp_units::hep::unit_symbols;
using namespace mp_units::si::unit_symbols;
// mass
static_assert(isq::mass(1'000 * (eV / c2)) == isq::mass(1 * (keV / c2)));
static_assert(isq::mass(1'000 * eV / c2) == isq::mass(1 * keV / c2));
// momentum
static_assert(isq::momentum(1'000'000 * (eV / c)) == isq::momentum(1 * (MeV / c)));
static_assert(isq::momentum(1'000'000 * eV / c) == isq::momentum(1 * MeV / c));
// area
static_assert(isq::area(1e28 * b) == isq::area(1. * m2));

View File

@@ -47,6 +47,6 @@ static_assert(isq::length(10'000'000'000 * A) == 1 * si::metre);
static_assert(round<si::metre>(isq::length(1.L * pc)) == 30'856'775'814'913'673 * si::metre);
#endif
static_assert(isq::speed(1 * c_0) == 299'792'458 * (si::metre / si::second));
static_assert(isq::speed(1 * c_0) == 299'792'458 * si::metre / si::second);
} // namespace

View File

@@ -48,22 +48,22 @@ static_assert(verify(traffic_load, scalar, E));
static_assert(verify(mean_queue_length, scalar, one));
static_assert(verify(loss_probability, scalar, one));
static_assert(verify(waiting_probability, scalar, one));
static_assert(verify(call_intensity, scalar, 1 / s));
static_assert(verify(calling_rate, scalar, 1 / s));
static_assert(verify(completed_call_intensity, scalar, 1 / s));
static_assert(verify(call_intensity, scalar, one / s));
static_assert(verify(calling_rate, scalar, one / s));
static_assert(verify(completed_call_intensity, scalar, one / s));
static_assert(verify(storage_capacity, scalar, one, bit, o, B));
static_assert(verify(storage_size, scalar, one, bit, o, B));
static_assert(verify(equivalent_binary_storage_capacity, scalar, one, bit));
static_assert(verify(transfer_rate, scalar, 1 / s, o / s, B / s));
static_assert(verify(transfer_rate, scalar, one / s, o / s, B / s));
static_assert(verify(period_of_data_elements, scalar, s));
static_assert(verify(binary_digit_rate, scalar, 1 / s, bit / s));
static_assert(verify(bit_rate, scalar, 1 / s, bit / s));
static_assert(verify(binary_digit_rate, scalar, one / s, bit / s));
static_assert(verify(bit_rate, scalar, one / s, bit / s));
static_assert(verify(period_of_binary_digits, scalar, s));
static_assert(verify(bit_period, scalar, s));
static_assert(verify(equivalent_binary_digit_rate, scalar, 1 / s, bit / s));
static_assert(verify(equivalent_bit_rate, scalar, 1 / s, bit / s));
static_assert(verify(modulation_rate, scalar, 1 / s, Bd));
static_assert(verify(line_digit_rate, scalar, 1 / s, Bd));
static_assert(verify(equivalent_binary_digit_rate, scalar, one / s, bit / s));
static_assert(verify(equivalent_bit_rate, scalar, one / s, bit / s));
static_assert(verify(modulation_rate, scalar, one / s, Bd));
static_assert(verify(line_digit_rate, scalar, one / s, Bd));
static_assert(verify(quantizing_distortion_power, scalar, W));
static_assert(verify(carrier_power, scalar, W));
static_assert(verify(signal_energy_per_binary_digit, scalar, J));
@@ -92,8 +92,8 @@ static_assert(storage_capacity(1 * Pibit) == storage_capacity(1024 * Tibit));
static_assert(storage_capacity(1 * Eibit) == storage_capacity(1024 * Pibit));
// transfer rate
static_assert(storage_capacity(16 * B) / isq::duration(2 * s) == transfer_rate(8 * (B / s)));
static_assert(storage_capacity(120 * kB) / isq::duration(2 * min) == transfer_rate(1000 * (B / s)));
static_assert(storage_capacity(16 * B) / isq::duration(2 * s) == transfer_rate(8 * B / s));
static_assert(storage_capacity(120 * kB) / isq::duration(2 * min) == transfer_rate(1000 * B / s));
// modulation rate
static_assert(12 / isq::duration(2 * s) == modulation_rate(6 * Bd));

View File

@@ -52,7 +52,7 @@ static_assert(verify(isq::radial_distance, scalar, m));
static_assert(verify(isq::position_vector, vector, m));
static_assert(verify(isq::displacement, vector, m));
static_assert(verify(isq::radius_of_curvature, scalar, m));
static_assert(verify(isq::curvature, scalar, 1 / m));
static_assert(verify(isq::curvature, scalar, one / m));
static_assert(verify(isq::area, scalar, m2));
static_assert(verify(isq::volume, scalar, m3));
static_assert(verify(isq::angular_measure, scalar, rad, one));
@@ -64,31 +64,31 @@ static_assert(verify(isq::duration, scalar, s));
static_assert(verify(isq::velocity, vector, m / s));
static_assert(verify(isq::speed, scalar, m / s));
static_assert(verify(isq::acceleration, vector, m / s2));
static_assert(verify(isq::angular_velocity, vector, rad / s, 1 / s));
static_assert(verify(isq::angular_acceleration, vector, rad / s2, 1 / s2));
static_assert(verify(isq::angular_velocity, vector, rad / s, one / s));
static_assert(verify(isq::angular_acceleration, vector, rad / s2, one / s2));
static_assert(verify(isq::period_duration, scalar, s));
static_assert(verify(isq::duration, scalar, s));
static_assert(verify(isq::time_constant, scalar, s));
static_assert(verify(isq::rotation, scalar, one));
static_assert(verify(isq::frequency, scalar, Hz, 1 / s));
static_assert(verify(isq::rotational_frequency, scalar, 1 / s));
static_assert(verify(isq::angular_frequency, scalar, rad / s, 1 / s));
static_assert(verify(isq::frequency, scalar, Hz, one / s));
static_assert(verify(isq::rotational_frequency, scalar, one / s));
static_assert(verify(isq::angular_frequency, scalar, rad / s, one / s));
static_assert(verify(isq::wavelength, scalar, m));
static_assert(verify(isq::repetency, scalar, 1 / m));
static_assert(verify(isq::wavenumber, scalar, 1 / m));
static_assert(verify(isq::wave_vector, vector, 1 / m));
static_assert(verify(isq::angular_repetency, scalar, 1 / m));
static_assert(verify(isq::angular_wavenumber, scalar, 1 / m));
static_assert(verify(isq::repetency, scalar, one / m));
static_assert(verify(isq::wavenumber, scalar, one / m));
static_assert(verify(isq::wave_vector, vector, one / m));
static_assert(verify(isq::angular_repetency, scalar, one / m));
static_assert(verify(isq::angular_wavenumber, scalar, one / m));
static_assert(verify(isq::phase_velocity, scalar, m / s));
static_assert(verify(isq::phase_speed, scalar, m / s));
static_assert(verify(isq::group_velocity, scalar, m / s));
static_assert(verify(isq::group_speed, scalar, m / s));
static_assert(verify(isq::damping_coefficient, scalar, 1 / s));
static_assert(verify(isq::damping_coefficient, scalar, one / s));
static_assert(verify(isq::logarithmic_decrement, scalar, one));
static_assert(verify(isq::attenuation, scalar, 1 / m));
static_assert(verify(isq::extinction, scalar, 1 / m));
static_assert(verify(isq::phase_coefficient, scalar, rad / m, 1 / m));
static_assert(verify(isq::propagation_coefficient, scalar, 1 / m));
static_assert(verify(isq::attenuation, scalar, one / m));
static_assert(verify(isq::extinction, scalar, one / m));
static_assert(verify(isq::phase_coefficient, scalar, rad / m, one / m));
static_assert(verify(isq::propagation_coefficient, scalar, one / m));
// mechanics
static_assert(verify(isq::mass, scalar, kg));
@@ -134,7 +134,7 @@ static_assert(verify(isq::modulus_of_rigidity, scalar, Pa, N / m2, kg / m / s2))
static_assert(verify(isq::shear_modulus, scalar, Pa, N / m2, kg / m / s2));
static_assert(verify(isq::modulus_of_compression, scalar, Pa, N / m2, kg / m / s2));
static_assert(verify(isq::bulk_modulus, scalar, Pa, N / m2, kg / m / s2));
static_assert(verify(isq::compressibility, scalar, 1 / Pa, m* s2 / kg));
static_assert(verify(isq::compressibility, scalar, one / Pa, m* s2 / kg));
static_assert(verify(isq::second_axial_moment_of_area, scalar, m4));
static_assert(verify(isq::second_polar_moment_of_area, scalar, m4));
static_assert(verify(isq::section_modulus, scalar, m3));
@@ -165,12 +165,12 @@ static_assert(verify(isq::action, scalar, J* s, kg* m2 / s));
// thermodynamics
static_assert(verify(isq::thermodynamic_temperature, scalar, K));
static_assert(verify(isq::Celsius_temperature, scalar, deg_C));
static_assert(verify(isq::linear_expansion_coefficient, scalar, 1 / K));
static_assert(verify(isq::cubic_expansion_coefficient, scalar, 1 / K));
static_assert(verify(isq::relative_pressure_coefficient, scalar, 1 / K));
static_assert(verify(isq::linear_expansion_coefficient, scalar, one / K));
static_assert(verify(isq::cubic_expansion_coefficient, scalar, one / K));
static_assert(verify(isq::relative_pressure_coefficient, scalar, one / K));
static_assert(verify(isq::pressure_coefficient, scalar, Pa / K, kg / m / s2 / K));
static_assert(verify(isq::isothermal_compressibility, scalar, 1 / Pa, m* s2 / kg));
static_assert(verify(isq::isentropic_compressibility, scalar, 1 / Pa, m* s2 / kg));
static_assert(verify(isq::isothermal_compressibility, scalar, one / Pa, m* s2 / kg));
static_assert(verify(isq::isentropic_compressibility, scalar, one / Pa, m* s2 / kg));
static_assert(verify(isq::heat, scalar, J, kg* m2 / s2));
static_assert(verify(isq::amount_of_heat, scalar, J, kg* m2 / s2));
static_assert(verify(isq::latent_heat, scalar, J, kg* m2 / s2));
@@ -289,7 +289,7 @@ static_assert(verify(isq::magnetic_tension, scalar, A));
static_assert(verify(isq::magnetomotive_force, scalar, A));
static_assert(verify(isq::current_linkage, scalar, A));
static_assert(verify(isq::number_of_turns_in_a_winding, scalar, one));
static_assert(verify(isq::reluctance, scalar, 1 / H));
static_assert(verify(isq::reluctance, scalar, one / H));
static_assert(verify(isq::permeance, scalar, H));
static_assert(verify(isq::inductance, scalar, H));
static_assert(verify(isq::self_inductance, scalar, H));
@@ -327,7 +327,7 @@ static_assert(verify(isq::non_active_power, scalar, V* A));
static_assert(verify(isq::active_energy, scalar, J, W* h));
// atomic and nuclear physics
static_assert(verify(isq::activity, scalar, Bq, 1 / s));
static_assert(verify(isq::activity, scalar, Bq, one / s));
static_assert(verify(isq::absorbed_dose, scalar, Gy, J / kg, m2 / s2));
static_assert(verify(isq::quality_factor, scalar, one));
static_assert(verify(isq::dose_equivalent, scalar, Sv, J / kg, m2 / s2));

View File

@@ -32,12 +32,12 @@ namespace {
using namespace mp_units;
using namespace mp_units::natural::unit_symbols;
static_assert(1 * natural::length[1 / GeV] / (1 * natural::time[1 / GeV]) == 1 * natural::speed[one]);
static_assert(1 * natural::length[1 / GeV] / (1 * natural::time[1 / GeV] * (1 * natural::time[1 / GeV])) ==
static_assert(1 * natural::length[one / GeV] / (1 * natural::time[one / GeV]) == 1 * natural::speed[one]);
static_assert(1 * natural::length[one / GeV] / (1 * natural::time[one / GeV] * (1 * natural::time[one / GeV])) ==
1 * natural::acceleration[GeV]);
static_assert(1 * natural::mass[GeV] * (1 * natural::velocity[one]) == 1 * natural::momentum[GeV]);
static_assert(1 * natural::mass[GeV] * (1 * natural::acceleration[GeV]) == 1 * natural::force[GeV2]);
static_assert(1 * natural::mass[GeV] * (1 * natural::acceleration[GeV]) * (1 * natural::length[1 / GeV]) ==
static_assert(1 * natural::mass[GeV] * (1 * natural::acceleration[GeV]) * (1 * natural::length[one / GeV]) ==
1 * natural::energy[GeV]);
} // namespace

View File

@@ -54,8 +54,8 @@ QUANTITY_SPEC_(distance, path_length);
QUANTITY_SPEC_(position_vector, length, quantity_character::vector);
QUANTITY_SPEC_(period_duration, time);
QUANTITY_SPEC_(rotation, dimensionless);
QUANTITY_SPEC_(frequency, 1 / period_duration);
QUANTITY_SPEC_(activity, 1 / time);
QUANTITY_SPEC_(frequency, inverse(period_duration));
QUANTITY_SPEC_(activity, inverse(time));
QUANTITY_SPEC_(area, pow<2>(length));
QUANTITY_SPEC_(volume, pow<3>(length));
QUANTITY_SPEC_(angular_measure, dimensionless, arc_length / radius, is_kind);
@@ -97,10 +97,10 @@ static_assert(detail::NamedQuantitySpec<frequency_>);
static_assert(!detail::IntermediateDerivedQuantitySpec<frequency_>);
static_assert(!detail::QuantityKindSpec<frequency_>);
static_assert(QuantitySpec<decltype(1 / time)>);
static_assert(!detail::NamedQuantitySpec<decltype(1 / time)>);
static_assert(detail::IntermediateDerivedQuantitySpec<decltype(1 / time)>);
static_assert(!detail::QuantityKindSpec<decltype(1 / time)>);
static_assert(QuantitySpec<decltype(inverse(time))>);
static_assert(!detail::NamedQuantitySpec<decltype(inverse(time))>);
static_assert(detail::IntermediateDerivedQuantitySpec<decltype(inverse(time))>);
static_assert(!detail::QuantityKindSpec<decltype(inverse(time))>);
static_assert(QuantitySpec<dimensionless_>);
static_assert(detail::NamedQuantitySpec<dimensionless_>);
@@ -117,10 +117,10 @@ static_assert(detail::NamedQuantitySpec<frequency_>);
static_assert(!detail::IntermediateDerivedQuantitySpec<frequency_>);
static_assert(!detail::QuantityKindSpec<frequency_>);
static_assert(QuantitySpec<decltype(1 / time)>);
static_assert(!detail::NamedQuantitySpec<decltype(1 / time)>);
static_assert(detail::IntermediateDerivedQuantitySpec<decltype(1 / time)>);
static_assert(!detail::QuantityKindSpec<decltype(1 / time)>);
static_assert(QuantitySpec<decltype(inverse(time))>);
static_assert(!detail::NamedQuantitySpec<decltype(inverse(time))>);
static_assert(detail::IntermediateDerivedQuantitySpec<decltype(inverse(time))>);
static_assert(!detail::QuantityKindSpec<decltype(inverse(time))>);
static_assert(QuantitySpec<kind_of_<length / time>>);
static_assert(!detail::NamedQuantitySpec<kind_of_<length / time>>);
@@ -184,8 +184,8 @@ static_assert(detail::IntermediateDerivedQuantitySpec<decltype(speed * time)>);
static_assert(is_of_type<dimensionless * time, time_>);
static_assert(is_of_type<time * dimensionless, time_>);
static_assert(is_of_type<dimensionless * (1 / time), derived_quantity_spec<dimensionless_, per<time_>>>);
static_assert(is_of_type<1 / time * dimensionless, derived_quantity_spec<dimensionless_, per<time_>>>);
static_assert(is_of_type<dimensionless*(inverse(time)), derived_quantity_spec<dimensionless_, per<time_>>>);
static_assert(is_of_type<inverse(time) * dimensionless, derived_quantity_spec<dimensionless_, per<time_>>>);
static_assert(is_of_type<length / length, dimensionless_>);
static_assert(is_of_type<pow<2>(length / length), dimensionless_>);
@@ -203,22 +203,24 @@ static_assert(is_of_type<length * time * length, derived_quantity_spec<mp_units:
static_assert(is_of_type<length*(time* length), derived_quantity_spec<mp_units::power<length_, 2>, time_>>);
static_assert(is_of_type<time*(length* length), derived_quantity_spec<mp_units::power<length_, 2>, time_>>);
static_assert(is_of_type<1 / time * length, derived_quantity_spec<length_, per<time_>>>);
static_assert(is_of_type<length * (1 / time), derived_quantity_spec<length_, per<time_>>>);
static_assert(is_of_type<1 / time * time, dimensionless_>);
static_assert(is_of_type<inverse(time) * length, derived_quantity_spec<length_, per<time_>>>);
static_assert(is_of_type<length * inverse(time), derived_quantity_spec<length_, per<time_>>>);
static_assert(is_of_type<inverse(time) * time, dimensionless_>);
static_assert(is_of_type<1 / length / (1 / width), derived_quantity_spec<width_, per<length_>>>);
static_assert(is_of_type<inverse(length) / inverse(width), derived_quantity_spec<width_, per<length_>>>);
static_assert(is_of_type<dimensionless / (time / length), derived_quantity_spec<length_, per<time_>>>);
static_assert(is_of_type<time / dimensionless, time_>);
static_assert(is_of_type<1 / time / dimensionless, derived_quantity_spec<dimensionless_, per<time_>>>);
static_assert(is_of_type<inverse(time) / dimensionless, derived_quantity_spec<dimensionless_, per<time_>>>);
static_assert(is_of_type<length / time * time, length_>);
static_assert(is_of_type<1 / time * (1 / time), derived_quantity_spec<dimensionless_, per<mp_units::power<time_, 2>>>>);
static_assert(is_of_type<1 / (time * time), derived_quantity_spec<dimensionless_, per<mp_units::power<time_, 2>>>>);
static_assert(is_of_type<1 / (1 / (time * time)), derived_quantity_spec<mp_units::power<time_, 2>>>);
static_assert(
is_of_type<inverse(time) * inverse(time), derived_quantity_spec<dimensionless_, per<mp_units::power<time_, 2>>>>);
static_assert(is_of_type<inverse(time* time), derived_quantity_spec<dimensionless_, per<mp_units::power<time_, 2>>>>);
static_assert(is_of_type<inverse(inverse(time* time)), derived_quantity_spec<mp_units::power<time_, 2>>>);
static_assert(is_of_type<length / time * (1 / time), derived_quantity_spec<length_, per<mp_units::power<time_, 2>>>>);
static_assert(
is_of_type<length / time * inverse(time), derived_quantity_spec<length_, per<mp_units::power<time_, 2>>>>);
static_assert(is_of_type<length / time*(length / time),
derived_quantity_spec<mp_units::power<length_, 2>, per<mp_units::power<time_, 2>>>>);
static_assert(is_of_type<length / time*(time / length), dimensionless_>);
@@ -231,8 +233,8 @@ static_assert(is_of_type<speed * speed / length, derived_quantity_spec<mp_units:
static_assert(
is_of_type<(speed * speed / length).dimension, derived_dimension<dim_length_, per<mp_units::power<dim_time_, 2>>>>);
static_assert(
is_of_type<1 / (speed * speed) * length, derived_quantity_spec<length_, per<mp_units::power<speed_, 2>>>>);
static_assert(is_of_type<(1 / (speed * speed) * length).dimension,
is_of_type<inverse(speed* speed) * length, derived_quantity_spec<length_, per<mp_units::power<speed_, 2>>>>);
static_assert(is_of_type<(inverse(speed * speed) * length).dimension,
derived_dimension<mp_units::power<dim_time_, 2>, per<dim_length_>>>);
static_assert(is_of_type<(length * length) * (time * time),
@@ -350,8 +352,8 @@ static_assert(rate_of_climb != length / time);
static_assert(velocity != speed);
static_assert(energy != torque);
static_assert(1 / time != frequency);
static_assert(1 / frequency != time);
static_assert(inverse(time) != frequency);
static_assert(inverse(frequency) != time);
static_assert(frequency * time != dimensionless);
static_assert(length * length != area);
static_assert(length * length != volume);
@@ -397,8 +399,8 @@ static_assert(get_kind(period_duration) == time);
static_assert(get_kind(length / time) == length / time);
static_assert(get_kind(speed) == speed);
static_assert(get_kind(height / time) == length / time);
static_assert(get_kind(1 / time) == 1 / time);
static_assert(get_kind(1 / period_duration) == 1 / time);
static_assert(get_kind(inverse(time)) == inverse(time));
static_assert(get_kind(inverse(period_duration)) == inverse(time));
static_assert(get_kind(frequency) == frequency);
static_assert(get_kind(mass * frequency) == mass * frequency);
static_assert(get_kind(moment_of_force) == moment_of_force);
@@ -450,7 +452,7 @@ static_assert(get_complexity(pow<4>(length)) == 1);
static_assert(get_complexity(pow<2>(area)) == 2);
// explode
static_assert(explode<get_complexity(1 / time)>(frequency).quantity == 1 / period_duration);
static_assert(explode<get_complexity(inverse(time))>(frequency).quantity == inverse(period_duration));
static_assert(explode<get_complexity(kind_of<length / time>)>(speed).quantity == length / time);
static_assert(explode<get_complexity(kind_of<length / time>)>(velocity).quantity == position_vector / time);
static_assert(explode<get_complexity(dimensionless)>(angular_measure).quantity == arc_length / radius);
@@ -530,7 +532,7 @@ static_assert(convertible_impl(kinetic_energy, energy) == yes);
static_assert(convertible_impl(angular_measure, dimensionless) == yes);
// upcasting beyond the hierarchy/kind
static_assert(convertible_impl(frequency, 1 / time) == yes);
static_assert(convertible_impl(frequency, inverse(time)) == yes);
static_assert(convertible_impl(speed, length / time) == yes);
static_assert(convertible_impl(speed, length / time) == yes);
static_assert(convertible_impl(velocity, length / time) == yes);
@@ -559,8 +561,8 @@ static_assert(convertible_impl(kind_of<dimensionless>, angular_measure) == yes);
static_assert(convertible_impl(kind_of<dimensionless>, kind_of<angular_measure>) == yes);
// derived quantities to type
static_assert(convertible_impl(1 / frequency, time) == yes);
static_assert(convertible_impl(1 / period_duration, frequency) == yes);
static_assert(convertible_impl(inverse(frequency), time) == yes);
static_assert(convertible_impl(inverse(period_duration), frequency) == yes);
static_assert(convertible_impl(length * length, area) == yes);
static_assert(convertible_impl(length / time, speed) == yes);
static_assert(convertible_impl(position_vector / time, speed) == yes);
@@ -597,7 +599,7 @@ static_assert(convertible_impl(mass * pow<2>(length) / pow<2>(time), kinetic_ene
static_assert(convertible_impl(length / speed, time) == yes);
// derived quantities to more constrained type
static_assert(convertible_impl(1 / time, frequency) == explicit_conversion);
static_assert(convertible_impl(inverse(time), frequency) == explicit_conversion);
static_assert(convertible_impl(length / time / time, acceleration) == explicit_conversion);
static_assert(convertible_impl(length / time, velocity) == explicit_conversion);
static_assert(convertible_impl(length / time, rate_of_climb) == explicit_conversion);
@@ -645,16 +647,16 @@ static_assert(convertible_impl(velocity * time / period_duration, velocity) == y
static_assert(convertible_impl(mass * acceleration_of_free_fall * height / weight, height) == yes);
// derived quantities to more generic derived compatible type
static_assert(convertible_impl(1 / (width * height), 1 / area) == yes);
static_assert(convertible_impl(inverse(width * height), inverse(area)) == yes);
static_assert(convertible_impl(path_length * distance, pow<2>(path_length)) == yes);
// derived to compatible derived
static_assert(convertible_impl(1 / (length * length), 1 / area) == yes);
static_assert(convertible_impl(inverse(length * length), inverse(area)) == yes);
static_assert(convertible_impl(velocity * time, acceleration* pow<2>(time)) == yes);
static_assert(convertible_impl(height / period_duration, length / time) == yes);
static_assert(convertible_impl(height / width, length / length) == yes);
static_assert(convertible_impl(height * width, length* length) == yes);
static_assert(convertible_impl(1 / (path_length * distance), 1 / pow<2>(path_length)) == yes);
static_assert(convertible_impl(inverse(path_length * distance), inverse(pow<2>(path_length))) == yes);
static_assert(convertible_impl(volume * length, pow<2>(area)) == yes);
static_assert(convertible_impl(pow<4>(length), pow<2>(area)) == yes);
@@ -670,7 +672,7 @@ static_assert(convertible_impl(height / time, distance / time) == cast);
// when more than one possible combination is present
// TODO revise that
static_assert(convertible_impl(width * height, pow<2>(height)) == cast);
static_assert(convertible_impl(1 / (width * height), 1 / pow<2>(height)) == cast);
static_assert(convertible_impl(inverse(width * height), inverse(pow<2>(height))) == cast);
static_assert(convertible_impl(width * distance, path_length* width) == yes);
static_assert(convertible_impl(height * distance, path_length* height) == cast);
static_assert(convertible_impl(width * length, length* height) == explicit_conversion);
@@ -706,8 +708,8 @@ static_assert(convertible_impl(kind_of<frequency>, activity) == no);
static_assert(convertible_impl(kind_of<length / time>, speed) == yes);
static_assert(convertible_impl(kind_of<length / time>, velocity) == yes);
static_assert(convertible_impl(kind_of<length / pow<2>(time)>, acceleration) == yes);
static_assert(convertible_impl(kind_of<1 / time>, frequency) == yes);
static_assert(convertible_impl(kind_of<1 / time>, activity) == yes);
static_assert(convertible_impl(kind_of<inverse(time)>, frequency) == yes);
static_assert(convertible_impl(kind_of<inverse(time)>, activity) == yes);
static_assert(convertible_impl(kind_of<mass * pow<2>(length) / pow<2>(time)>, energy) == yes);
static_assert(convertible_impl(kind_of<mass * pow<2>(length) / pow<2>(time)>, moment_of_force) == yes);
@@ -724,7 +726,7 @@ static_assert(convertible_impl(activity, kind_of<frequency>) == no);
static_assert(convertible_impl(length, kind_of<length>) == yes);
static_assert(convertible_impl(width, kind_of<length>) == yes);
static_assert(convertible_impl(frequency, kind_of<frequency>) == yes);
static_assert(convertible_impl(frequency, kind_of<1 / time>) == yes);
static_assert(convertible_impl(frequency, kind_of<inverse(time)>) == yes);
static_assert(convertible_impl(frequency, kind_of<activity>) == no);
static_assert(convertible_impl(energy, kind_of<energy>) == yes);
static_assert(convertible_impl(potential_energy, kind_of<energy>) == yes);
@@ -734,7 +736,7 @@ static_assert(convertible_impl(angular_measure, kind_of<dimensionless>) == yes);
static_assert(convertible_impl(rotational_displacement, kind_of<dimensionless>) == yes);
// converting derived type to a kind
static_assert(convertible_impl(1 / time, kind_of<frequency>) == yes);
static_assert(convertible_impl(inverse(time), kind_of<frequency>) == yes);
static_assert(convertible_impl(length / time, kind_of<speed>) == yes);
static_assert(convertible_impl(length / pow<2>(time), kind_of<acceleration>) == yes);
@@ -743,7 +745,7 @@ static_assert(convertible_impl(kind_of<dimensionless>, kind_of<angular_measure>)
static_assert(convertible_impl(kind_of<angular_measure>, kind_of<dimensionless>) == yes);
// converting derived kind to a kind
static_assert(convertible_impl(kind_of<1 / time>, kind_of<frequency>) == yes);
static_assert(convertible_impl(kind_of<inverse(time)>, kind_of<frequency>) == yes);
static_assert(convertible_impl(kind_of<length / time>, kind_of<speed>) == yes);
static_assert(convertible_impl(kind_of<length / pow<2>(time)>, kind_of<acceleration>) == yes);
@@ -785,7 +787,7 @@ static_assert(common_quantity_spec(distance, path_length) == path_length);
static_assert(common_quantity_spec(potential_energy, kinetic_energy) == mechanical_energy);
static_assert(common_quantity_spec(length / time, length / time) == length / time);
static_assert(common_quantity_spec(length / time, 1 / (time / length)) == length / time);
static_assert(common_quantity_spec(length / time, inverse(time / length)) == length / time);
static_assert(common_quantity_spec(speed, length / time) == speed);
static_assert(common_quantity_spec(length / time, speed) == speed);

View File

@@ -518,6 +518,7 @@ static_assert(is_of_type<1 * m / (1 * one), quantity<si::metre, int>>);
static_assert(is_of_type<1 * m / (1 * percent), quantity<derived_unit<struct si::metre, per<struct percent>>{}, int>>);
static_assert(is_of_type<1 / (1 * s), quantity<derived_unit<struct one, per<struct si::second>>{}, int>>);
static_assert(is_of_type<1 / s, quantity<derived_unit<struct one, per<struct si::second>>{}, int>>);
static_assert(is_of_type<1 * one / (1 * s), quantity<derived_unit<struct one, per<struct si::second>>{}, int>>);
static_assert(is_of_type<1 * percent / (1 * s), quantity<derived_unit<struct percent, per<struct si::second>>{}, int>>);
@@ -566,6 +567,7 @@ static_assert(
is_of_type<1 * m / (1. * percent), quantity<derived_unit<struct si::metre, per<struct percent>>{}, double>>);
static_assert(is_of_type<1 / (1. * s), quantity<derived_unit<struct one, per<struct si::second>>{}, double>>);
static_assert(is_of_type<1. / s, quantity<derived_unit<struct one, per<struct si::second>>{}, double>>);
static_assert(is_of_type<1. * one / (1 * s), quantity<derived_unit<struct one, per<struct si::second>>{}, double>>);
static_assert(
is_of_type<1 * percent / (1. * s), quantity<derived_unit<struct percent, per<struct si::second>>{}, double>>);
@@ -594,14 +596,17 @@ static_assert(is_of_type<1. * km - 1. * m, quantity<si::metre, double>>);
static_assert(is_of_type<1 * m % (1 * km), quantity<si::metre, int>>);
// different dimensions
static_assert(is_of_type<1 * (m / s) * (1 * s), quantity<si::metre, int>>);
static_assert(is_of_type<1 * (m / s) * (1 * h),
static_assert(is_of_type<1 * m / s * (1 * s), quantity<si::metre, int>>);
static_assert(is_of_type<1 * m / s * (1 * h),
quantity<derived_unit<struct si::hour, struct si::metre, per<struct si::second>>{}, int>>);
static_assert(is_of_type<1 * m * (1 * min), quantity<derived_unit<struct si::metre, struct si::minute>{}, int>>);
static_assert(is_of_type<1 * s * (1 * Hz), quantity<derived_unit<struct si::hertz, struct si::second>{}, int>>);
static_assert(is_of_type<1 / (1 * min), quantity<derived_unit<struct one, per<struct si::minute>>{}, int>>);
static_assert(is_of_type<1 / (1 * Hz), quantity<derived_unit<struct one, per<struct si::hertz>>{}, int>>);
static_assert(is_of_type<1 / (1 * km), quantity<derived_unit<struct one, per<si::kilo_<si::metre>>>{}, int>>);
static_assert(is_of_type<1 / min, quantity<derived_unit<struct one, per<struct si::minute>>{}, int>>);
static_assert(is_of_type<1 / Hz, quantity<derived_unit<struct one, per<struct si::hertz>>{}, int>>);
static_assert(is_of_type<1 / km, quantity<derived_unit<struct one, per<si::kilo_<si::metre>>>{}, int>>);
static_assert(is_of_type<1 * km / (1 * m), quantity<derived_unit<si::kilo_<si::metre>, per<struct si::metre>>{}, int>>);
static_assert(is_of_type<1 * m / (1 * s), quantity<derived_unit<struct si::metre, per<struct si::second>>{}, int>>);
static_assert(is_of_type<1 * m / (1 * min), quantity<derived_unit<struct si::metre, per<struct si::minute>>{}, int>>);
@@ -811,8 +816,8 @@ static_assert(10 * isq::length[m] / (2 * isq::time[s]) == 5 * isq::speed[m / s])
static_assert(5 * isq::speed[m / s] == 10 * isq::length[m] / (2 * isq::time[s]));
// Same named dimension & different but equivalent unit
static_assert(10 * isq::frequency[1 / s] == 10 * isq::frequency[Hz]);
static_assert(10 * isq::frequency[Hz] == 10 * isq::frequency[1 / s]);
static_assert(10 * isq::frequency[one / s] == 10 * isq::frequency[Hz]);
static_assert(10 * isq::frequency[Hz] == 10 * isq::frequency[one / s]);
// Named and derived dimensions (different but equivalent units)
static_assert(10 / (2 * isq::time[s]) == 5 * isq::frequency[Hz]);

View File

@@ -51,8 +51,8 @@ QUANTITY_SPEC_(width, length);
QUANTITY_SPEC_(radius, width);
QUANTITY_SPEC_(arc_length, length);
QUANTITY_SPEC_(frequency, 1 / time);
QUANTITY_SPEC_(activity, 1 / time);
QUANTITY_SPEC_(frequency, inverse(time));
QUANTITY_SPEC_(activity, inverse(time));
QUANTITY_SPEC_(area, length* length);
QUANTITY_SPEC_(angular_measure, dimensionless, arc_length / radius, is_kind);
QUANTITY_SPEC_(solid_angular_measure, dimensionless, area / pow<2>(radius), is_kind);
@@ -83,8 +83,8 @@ inline constexpr struct speed : system_reference<speed_{}, second / second> {} s
// derived named units
inline constexpr struct radian_ : named_unit<"rad", metre / metre, kind_of<angular_measure>> {} radian;
inline constexpr struct steradian_ : named_unit<"sr", square(metre) / square(metre), kind_of<solid_angular_measure>> {} steradian;
inline constexpr struct hertz_ : named_unit<"Hz", 1 / second, kind_of<frequency>> {} hertz;
inline constexpr struct becquerel_ : named_unit<"Bq", 1 / second, kind_of<activity>> {} becquerel;
inline constexpr struct hertz_ : named_unit<"Hz", inverse(second), kind_of<frequency>> {} hertz;
inline constexpr struct becquerel_ : named_unit<"Bq", inverse(second), kind_of<activity>> {} becquerel;
inline constexpr struct newton_ : named_unit<"N", kilogram * metre / square(second)> {} newton;
inline constexpr struct joule_ : named_unit<"J", newton * metre> {} joule;
inline constexpr struct watt_ : named_unit<"W", joule / second> {} watt;
@@ -108,7 +108,7 @@ static_assert(is_of_type<42 * metre, quantity<metre, int>>);
static_assert(quantity<metre, int>::quantity_spec == length);
static_assert(is_of_type<42 * square(metre), quantity<square(metre), int>>);
static_assert(quantity<square(metre), int>::quantity_spec == pow<2>(length));
static_assert(is_of_type<42 * (metre / second), quantity<metre / second, int>>);
static_assert(is_of_type<42 * metre / second, quantity<metre / second, int>>);
static_assert(quantity<metre / second, int>::quantity_spec == length / time);
static_assert(is_of_type<42 * newton, quantity<newton, int>>);
static_assert(quantity<newton, int>::quantity_spec == mass * length / pow<2>(time));
@@ -138,7 +138,6 @@ static_assert(is_of_type<20 * speed[metre / second] / (10 * length[metre]) * (5
template<auto s>
concept invalid_operations = requires {
requires !requires { 2 / s; };
requires !requires { s / 2; };
requires !requires { s * 2; };
requires !requires { s + 2; };
@@ -156,13 +155,26 @@ concept invalid_operations = requires {
requires !requires { s < 1 * time[second]; };
requires !requires { 1 * time[second] + s; };
requires !requires { 1 * time[second] - s; };
requires !requires { 1 * time[second] * s; };
requires !requires { 1 * time[second] / s; };
requires !requires { 1 * time[second] == s; };
requires !requires { 1 * time[second] < s; };
};
static_assert(invalid_operations<time[second]>);
static_assert(is_of_type<2 / second, quantity<derived_unit<one_, per<second_>>{}, int>>);
static_assert(is_of_type<2 / time[second], quantity<reference<derived_quantity_spec<dimensionless_, per<time_>>{},
derived_unit<one_, per<second_>>{}>{},
int>>);
static_assert(is_of_type<1 * time[second] * second, quantity<reference<pow<2>(time), pow<2>(second)>{}, int>>);
static_assert(is_of_type<1 * time[second] * time[second], quantity<reference<pow<2>(time), pow<2>(second)>{}, int>>);
static_assert(is_of_type<1 * time[second] / second, quantity<reference<dimensionless, one>{}, int>>);
static_assert(is_of_type<1 * time[second] / time[second], quantity<reference<dimensionless, one>{}, int>>);
static_assert(
is_of_type<
1 * inverse(time[second]),
quantity<reference<derived_quantity_spec<dimensionless_, per<time_>>{}, derived_unit<one_, per<second_>>{}>{},
int>>);
static_assert(
is_of_type<
2 * length[metre] / (1 * time[second]),

View File

@@ -61,8 +61,8 @@ inline constexpr struct nu_second_ : named_unit<"s"> {} nu_second;
// derived named units
inline constexpr struct radian_ : named_unit<"rad", metre / metre> {} radian;
inline constexpr struct steradian_ : named_unit<"sr", square(metre) / square(metre)> {} steradian;
inline constexpr struct hertz_ : named_unit<"Hz", 1 / second> {} hertz;
inline constexpr struct becquerel_ : named_unit<"Bq", 1 / second> {} becquerel;
inline constexpr struct hertz_ : named_unit<"Hz", inverse(second)> {} hertz;
inline constexpr struct becquerel_ : named_unit<"Bq", inverse(second)> {} becquerel;
inline constexpr struct newton_ : named_unit<"N", kilogram * metre / square(second)> {} newton;
inline constexpr struct pascal_ : named_unit<"Pa", newton / square(metre)> {} pascal;
inline constexpr struct joule_ : named_unit<"J", newton * metre> {} joule;
@@ -267,13 +267,13 @@ static_assert(get_canonical_unit(kJ_42).mag == mag<42'000'000>);
// derived unit expression template syntax verification
static_assert(is_of_type<1 / second, derived_unit<one_, per<second_>>>);
static_assert(is_of_type<1 / (1 / second), second_>);
static_assert(is_of_type<inverse(second), derived_unit<one_, per<second_>>>);
static_assert(is_of_type<one / (inverse(second)), second_>);
static_assert(is_of_type<one * second, second_>);
static_assert(is_of_type<second * one, second_>);
static_assert(is_of_type<one * (1 / second), derived_unit<one_, per<second_>>>);
static_assert(is_of_type<1 / second * one, derived_unit<one_, per<second_>>>);
static_assert(is_of_type<one * inverse(second), derived_unit<one_, per<second_>>>);
static_assert(is_of_type<one / second * one, derived_unit<one_, per<second_>>>);
static_assert(is_of_type<metre * second, derived_unit<metre_, second_>>);
static_assert(is_of_type<metre * metre, derived_unit<power<metre_, 2>>>);
@@ -295,18 +295,18 @@ static_assert(is_of_type<metre * second * metre, derived_unit<power<metre_, 2>,
static_assert(is_of_type<metre*(second* metre), derived_unit<power<metre_, 2>, second_>>);
static_assert(is_of_type<second*(metre* metre), derived_unit<power<metre_, 2>, second_>>);
static_assert(is_of_type<1 / second * metre, derived_unit<metre_, per<second_>>>);
static_assert(is_of_type<1 / second * second, one_>);
static_assert(is_of_type<one / second * metre, derived_unit<metre_, per<second_>>>);
static_assert(is_of_type<one / second * second, one_>);
static_assert(is_of_type<second / one, second_>);
static_assert(is_of_type<1 / second / one, derived_unit<one_, per<second_>>>);
static_assert(is_of_type<one / second / one, derived_unit<one_, per<second_>>>);
static_assert(is_of_type<metre / second * second, metre_>);
static_assert(is_of_type<1 / second * (1 / second), derived_unit<one_, per<power<second_, 2>>>>);
static_assert(is_of_type<1 / (second * second), derived_unit<one_, per<power<second_, 2>>>>);
static_assert(is_of_type<1 / (1 / (second * second)), derived_unit<power<second_, 2>>>);
static_assert(is_of_type<one / second * inverse(second), derived_unit<one_, per<power<second_, 2>>>>);
static_assert(is_of_type<one / (second * second), derived_unit<one_, per<power<second_, 2>>>>);
static_assert(is_of_type<one / inverse(second* second), derived_unit<power<second_, 2>>>);
static_assert(is_of_type<metre / second * (1 / second), derived_unit<metre_, per<power<second_, 2>>>>);
static_assert(is_of_type<metre / second * inverse(second), derived_unit<metre_, per<power<second_, 2>>>>);
static_assert(is_of_type<metre / second*(metre / second), derived_unit<power<metre_, 2>, per<power<second_, 2>>>>);
static_assert(is_of_type<metre / second*(second / metre), one_>);
@@ -314,12 +314,13 @@ static_assert(is_of_type<watt / joule, derived_unit<watt_, per<joule_>>>);
static_assert(is_of_type<joule / watt, derived_unit<joule_, per<watt_>>>);
static_assert(is_of_type<one / second, derived_unit<one_, per<second_>>>);
static_assert(is_of_type<1 / (1 / second), second_>);
static_assert(is_of_type<one / (1 / second), second_>);
static_assert(is_of_type<one / inverse(second), second_>);
static_assert(is_of_type<one / inverse(second), second_>);
static_assert(is_of_type<1 / pascal, derived_unit<one_, per<pascal_>>>);
static_assert(is_of_type<1 / gram * metre * square(second), derived_unit<metre_, power<second_, 2>, per<gram_>>>);
static_assert(is_of_type<1 / (gram / (metre * square(second))), derived_unit<metre_, power<second_, 2>, per<gram_>>>);
static_assert(is_of_type<inverse(pascal), derived_unit<one_, per<pascal_>>>);
static_assert(is_of_type<inverse(gram) * metre * square(second), derived_unit<metre_, power<second_, 2>, per<gram_>>>);
static_assert(
is_of_type<inverse(gram / (metre * square(second))), derived_unit<metre_, power<second_, 2>, per<gram_>>>);
static_assert(is_of_type<one*(metre* square(second) / gram), derived_unit<metre_, power<second_, 2>, per<gram_>>>);
static_assert(is_of_type<one * metre * square(second) / gram, derived_unit<metre_, power<second_, 2>, per<gram_>>>);
static_assert(is_of_type<(metre * square(second) / gram) * one, derived_unit<metre_, power<second_, 2>, per<gram_>>>);
@@ -335,11 +336,11 @@ static_assert(is_of_type<speed_of_light_in_vacuum * gram * standard_gravity,
static_assert(is_of_type<gram * standard_gravity * speed_of_light_in_vacuum,
derived_unit<speed_of_light_in_vacuum_, gram_, standard_gravity_>>);
static_assert(std::is_same_v<decltype(1 / second * metre), decltype(metre / second)>);
static_assert(std::is_same_v<decltype(metre * (1 / second)), decltype(metre / second)>);
static_assert(std::is_same_v<decltype((metre / second) * (1 / second)), decltype(metre / second / second)>);
static_assert(std::is_same_v<decltype((metre / second) * (1 / second)), decltype(metre / (second * second))>);
static_assert(std::is_same_v<decltype((metre / second) * (1 / second)), decltype(metre / square(second))>);
static_assert(std::is_same_v<decltype(inverse(second) * metre), decltype(metre / second)>);
static_assert(std::is_same_v<decltype(metre * inverse(second)), decltype(metre / second)>);
static_assert(std::is_same_v<decltype((metre / second) * inverse(second)), decltype(metre / second / second)>);
static_assert(std::is_same_v<decltype((metre / second) * inverse(second)), decltype(metre / (second * second))>);
static_assert(std::is_same_v<decltype((metre / second) * inverse(second)), decltype(metre / square(second))>);
// derived unit normalization
@@ -357,13 +358,13 @@ 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(is_of_type<get_canonical_unit(1 / metre).reference_unit, derived_unit<one_, per<metre_>>>);
static_assert(is_of_type<get_canonical_unit(1 / hertz).reference_unit, second_>);
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_>);
static_assert(
is_of_type<get_canonical_unit(pascal).reference_unit, derived_unit<gram_, per<metre_, power<second_, 2>>>>);
static_assert(
is_of_type<get_canonical_unit(1 / pascal).reference_unit, derived_unit<metre_, power<second_, 2>, per<gram_>>>);
is_of_type<get_canonical_unit(one / pascal).reference_unit, derived_unit<metre_, power<second_, 2>, per<gram_>>>);
static_assert(
is_of_type<get_canonical_unit(standard_gravity).reference_unit, derived_unit<metre_, per<power<second_, 2>>>>);
@@ -384,7 +385,7 @@ static_assert(is_of_type<u2, scaled_unit<mag<1000>, derived_unit<kilometre_, per
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}>);
constexpr auto u3 = 1 / hour * (mag<1000> * kilometre);
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}>);
@@ -417,7 +418,6 @@ concept invalid_operations = requires {
requires !requires { s == 1 * time[second]; };
requires !requires { 1 * time[second] + s; };
requires !requires { 1 * time[second] - s; };
requires !requires { 1 * time[second] * s; };
requires !requires { 1 * time[second] == s; };
requires !requires { 1 * time[second] < s; };
};
@@ -433,8 +433,8 @@ static_assert(si::milli<metre> * si::kilo<metre> == si::deci<metre> * si::deca<m
static_assert(si::kilo<metre> * si::milli<metre> == si::deca<metre> * si::deci<metre>);
// comparisons of equivalent units (named vs unnamed/derived)
static_assert(1 / second == hertz);
static_assert(convertible(1 / second, hertz));
static_assert(one / second == hertz);
static_assert(convertible(one / second, hertz));
// comparisons of equivalent units of different quantities
static_assert(hertz == becquerel);
@@ -473,7 +473,7 @@ static_assert(percent * one == percent);
static_assert(is_of_type<one * percent, percent_>);
static_assert(is_of_type<percent * one, percent_>);
static_assert(hertz == 1 / second);
static_assert(hertz == one / second);
static_assert(newton == kilogram * metre / square(second));
static_assert(joule == kilogram * square(metre) / square(second));
static_assert(joule == newton * metre);
@@ -517,8 +517,8 @@ static_assert(is_of_type<common_unit(si::kilo<gram>, kilogram), kilogram_>);
static_assert(is_of_type<common_unit(kilogram, si::kilo<gram>), kilogram_>);
static_assert(is_of_type<common_unit(mag<1000>* gram, kilogram), kilogram_>);
static_assert(is_of_type<common_unit(kilogram, mag<1000>* gram), kilogram_>);
static_assert(is_of_type<common_unit(1 / second, hertz), hertz_>);
static_assert(is_of_type<common_unit(hertz, 1 / second), hertz_>);
static_assert(is_of_type<common_unit(one / second, hertz), hertz_>);
static_assert(is_of_type<common_unit(hertz, one / second), hertz_>);
static_assert(is_of_type<common_unit(gram, kilogram), gram_>);
static_assert(is_of_type<common_unit(kilogram, gram), gram_>);
static_assert(is_of_type<common_unit(second, hour), second_>);