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,20 +152,22 @@ 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
```cpp
constexpr auto my_unit = 1 / second;
```
Another way to achieve the same result is to call an `inverse()` function:
Both cases with result in the same expression template being generated and put into the wrapper
class template.
```cpp
constexpr auto my_unit = inverse(second);
```
Both cases will result in the same expression template being generated and put into the wrapper
class template.
### Supported operations and their results

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
// and β the phase coefficient of a plane wave
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_>);