mirror of
https://github.com/mpusz/mp-units.git
synced 2025-08-04 04:44:27 +02:00
Merge pull request #484 from mpusz/mpusz/issue477
Renaming of accessor functions
This commit is contained in:
@@ -65,11 +65,11 @@ some issues start to be clearly visible:
|
|||||||
Trying to use an integral type in this scenario will work only for `s1`, while `s2` and `s3`
|
Trying to use an integral type in this scenario will work only for `s1`, while `s2` and `s3`
|
||||||
will fail to compile. Failing to compile is a good thing here as the library tries to prevent
|
will fail to compile. Failing to compile is a good thing here as the library tries to prevent
|
||||||
the user from doing a clearly wrong thing. To make the code compile, the user needs to use
|
the user from doing a clearly wrong thing. To make the code compile, the user needs to use
|
||||||
a dedicated [`value_cast`](value_conversions.md#value-truncating-conversions) like this:
|
dedicated [`value_cast` or `force_in`](value_conversions.md#value-truncating-conversions) like this:
|
||||||
|
|
||||||
```cpp
|
```cpp
|
||||||
quantity<isq::speed[mi / h]> s2 = avg_speed(value_cast<km>(140 * mi), 2 * h);
|
quantity<isq::speed[mi / h]> s2 = avg_speed(value_cast<km>(140 * mi), 2 * h);
|
||||||
quantity<isq::speed[m / s]> s3 = avg_speed(value_cast<km>(20 * m), value_cast<h>(2 * s));
|
quantity<isq::speed[m / s]> s3 = avg_speed((20 * m).force_in(km), (2 * s).force_in(h));
|
||||||
```
|
```
|
||||||
|
|
||||||
but the above will obviously provide an incorrect behavior (i.e. division by `0` in the evaluation
|
but the above will obviously provide an incorrect behavior (i.e. division by `0` in the evaluation
|
||||||
|
@@ -74,7 +74,7 @@ associated with this quantity.
|
|||||||
|
|
||||||
```cpp
|
```cpp
|
||||||
std::cout << v1.in(km / h) << '\n'; // 110 km/h
|
std::cout << v1.in(km / h) << '\n'; // 110 km/h
|
||||||
std::cout << value_cast<m / s>(v1) << '\n'; // 30.5556 m/s
|
std::cout << v1.force_in(m / s) << '\n'; // 30.5556 m/s
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
|
@@ -59,12 +59,18 @@ The second solution is to force a truncating conversion:
|
|||||||
```cpp
|
```cpp
|
||||||
auto q1 = 5 * m;
|
auto q1 = 5 * m;
|
||||||
std::cout << value_cast<km>(q1) << '\n';
|
std::cout << value_cast<km>(q1) << '\n';
|
||||||
quantity<si::kilo<si::metre>, int> q2 = value_cast<km>(q1);
|
quantity<si::kilo<si::metre>, int> q2 = q1.force_in(km);
|
||||||
```
|
```
|
||||||
|
|
||||||
This explicit cast makes it clear that something unsafe is going on. It is easy to spot in code
|
This explicit cast makes it clear that something unsafe is going on. It is easy to spot in code
|
||||||
reviews or while chasing a bug in the source code.
|
reviews or while chasing a bug in the source code.
|
||||||
|
|
||||||
|
!!! note
|
||||||
|
|
||||||
|
`q.force_in(U)` is just a shortcut to run `value_cast<U>(q)`. There is no difference in behavior
|
||||||
|
between those two interfaces. `q.force_in(U)` was added for consistency with `q.in(U)` and
|
||||||
|
`q.force_numerical_value_in(U)`.
|
||||||
|
|
||||||
Another place where this cast is useful is when a user wants to convert a quantity with
|
Another place where this cast is useful is when a user wants to convert a quantity with
|
||||||
a floating-point representation to the one using an integral one. Again this is a truncating
|
a floating-point representation to the one using an integral one. Again this is a truncating
|
||||||
conversion, so an explicit cast is needed:
|
conversion, so an explicit cast is needed:
|
||||||
|
@@ -56,7 +56,7 @@ constexpr QuantityOf<isq::speed> auto avg_speed(QuantityOf<isq::length> auto d,
|
|||||||
template<QuantityOf<isq::length> D, QuantityOf<isq::time> T, QuantityOf<isq::speed> V>
|
template<QuantityOf<isq::length> D, QuantityOf<isq::time> T, QuantityOf<isq::speed> V>
|
||||||
void print_result(D distance, T duration, V speed)
|
void print_result(D distance, T duration, V speed)
|
||||||
{
|
{
|
||||||
const auto result_in_kmph = value_cast<si::kilo<si::metre> / non_si::hour>(speed);
|
const auto result_in_kmph = speed.force_in(si::kilo<si::metre> / non_si::hour);
|
||||||
std::cout << "Average speed of a car that makes " << distance << " in " << duration << " is " << result_in_kmph
|
std::cout << "Average speed of a car that makes " << distance << " in " << duration << " is " << result_in_kmph
|
||||||
<< ".\n";
|
<< ".\n";
|
||||||
}
|
}
|
||||||
@@ -101,7 +101,7 @@ void example()
|
|||||||
|
|
||||||
// it is not possible to make a lossless conversion of miles to meters on an integral type
|
// it is not possible to make a lossless conversion of miles to meters on an integral type
|
||||||
// (explicit cast needed)
|
// (explicit cast needed)
|
||||||
print_result(distance, duration, fixed_int_si_avg_speed(value_cast<si::metre>(distance), duration));
|
print_result(distance, duration, fixed_int_si_avg_speed(distance.force_in(m), duration));
|
||||||
print_result(distance, duration, fixed_double_si_avg_speed(distance, duration));
|
print_result(distance, duration, fixed_double_si_avg_speed(distance, duration));
|
||||||
print_result(distance, duration, avg_speed(distance, duration));
|
print_result(distance, duration, avg_speed(distance, duration));
|
||||||
}
|
}
|
||||||
@@ -119,7 +119,7 @@ void example()
|
|||||||
// also it is not possible to make a lossless conversion of miles to meters on an integral type
|
// also it is not possible to make a lossless conversion of miles to meters on an integral type
|
||||||
// (explicit cast needed)
|
// (explicit cast needed)
|
||||||
print_result(distance, duration,
|
print_result(distance, duration,
|
||||||
fixed_int_si_avg_speed(value_cast<int>(value_cast<si::metre>(distance)), value_cast<int>(duration)));
|
fixed_int_si_avg_speed(value_cast<int>(distance.force_in(m)), value_cast<int>(duration)));
|
||||||
print_result(distance, duration, fixed_double_si_avg_speed(distance, duration));
|
print_result(distance, duration, fixed_double_si_avg_speed(distance, duration));
|
||||||
print_result(distance, duration, avg_speed(distance, duration));
|
print_result(distance, duration, avg_speed(distance, duration));
|
||||||
}
|
}
|
||||||
@@ -133,7 +133,7 @@ void example()
|
|||||||
|
|
||||||
// it is not possible to make a lossless conversion of centimeters to meters on an integral type
|
// it is not possible to make a lossless conversion of centimeters to meters on an integral type
|
||||||
// (explicit cast needed)
|
// (explicit cast needed)
|
||||||
print_result(distance, duration, fixed_int_si_avg_speed(value_cast<si::metre>(distance), duration));
|
print_result(distance, duration, fixed_int_si_avg_speed(distance.force_in(m), duration));
|
||||||
print_result(distance, duration, fixed_double_si_avg_speed(distance, duration));
|
print_result(distance, duration, fixed_double_si_avg_speed(distance, duration));
|
||||||
print_result(distance, duration, avg_speed(distance, duration));
|
print_result(distance, duration, avg_speed(distance, duration));
|
||||||
}
|
}
|
||||||
@@ -149,7 +149,7 @@ void example()
|
|||||||
// it is not possible to make a lossless conversion of centimeters to meters on an integral type
|
// it is not possible to make a lossless conversion of centimeters to meters on an integral type
|
||||||
// (explicit cast needed)
|
// (explicit cast needed)
|
||||||
print_result(distance, duration,
|
print_result(distance, duration,
|
||||||
fixed_int_si_avg_speed(value_cast<int>(value_cast<m>(distance)), value_cast<int>(duration)));
|
fixed_int_si_avg_speed(value_cast<int>(distance.force_in(m)), value_cast<int>(duration)));
|
||||||
|
|
||||||
print_result(distance, duration, fixed_double_si_avg_speed(distance, duration));
|
print_result(distance, duration, fixed_double_si_avg_speed(distance, duration));
|
||||||
print_result(distance, duration, avg_speed(distance, duration));
|
print_result(distance, duration, avg_speed(distance, duration));
|
||||||
|
@@ -33,7 +33,7 @@ template<mp_units::Quantity Target, mp_units::Quantity Source>
|
|||||||
requires std::constructible_from<Target, Source>
|
requires std::constructible_from<Target, Source>
|
||||||
inline constexpr double conversion_factor(Target, Source)
|
inline constexpr double conversion_factor(Target, Source)
|
||||||
{
|
{
|
||||||
return mp_units::value_cast<Target::unit>(1. * Source::reference).numerical_value();
|
return (1. * Source::reference).force_numerical_value_in(Target::unit);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
@@ -56,6 +56,7 @@ int main()
|
|||||||
std::cout << MP_UNITS_STD_FMT::format("conversion factor from lengthA::unit of {:%q} to lengthB::unit of {:%q}:\n\n",
|
std::cout << MP_UNITS_STD_FMT::format("conversion factor from lengthA::unit of {:%q} to lengthB::unit of {:%q}:\n\n",
|
||||||
lengthA, lengthB)
|
lengthA, lengthB)
|
||||||
<< MP_UNITS_STD_FMT::format("lengthB.value( {} ) == lengthA.value( {} ) * conversion_factor( {} )\n",
|
<< MP_UNITS_STD_FMT::format("lengthB.value( {} ) == lengthA.value( {} ) * conversion_factor( {} )\n",
|
||||||
lengthB.numerical_value(), lengthA.numerical_value(),
|
lengthB.numerical_value_ref_in(lengthB.unit),
|
||||||
|
lengthA.numerical_value_ref_in(lengthA.unit),
|
||||||
conversion_factor(lengthB, lengthA));
|
conversion_factor(lengthB, lengthA));
|
||||||
}
|
}
|
||||||
|
@@ -81,9 +81,9 @@ quantity<To, Rep> exchange_to(quantity<From, Rep> q)
|
|||||||
template<ReferenceOf<currency> auto To, ReferenceOf<currency> auto From, auto PO, typename Rep>
|
template<ReferenceOf<currency> auto To, ReferenceOf<currency> auto From, auto PO, typename Rep>
|
||||||
quantity_point<To, PO, Rep> exchange_to(quantity_point<From, PO, Rep> q)
|
quantity_point<To, PO, Rep> exchange_to(quantity_point<From, PO, Rep> q)
|
||||||
{
|
{
|
||||||
return quantity_point{
|
return quantity_point{zero + static_cast<Rep>(exchange_rate<q.unit, get_unit(To)>() *
|
||||||
zero +
|
(q - q.absolute_point_origin).numerical_value_in(q.unit)) *
|
||||||
static_cast<Rep>(exchange_rate<q.unit, get_unit(To)>() * (q - q.absolute_point_origin).numerical_value()) * To};
|
To};
|
||||||
}
|
}
|
||||||
|
|
||||||
int main()
|
int main()
|
||||||
@@ -91,6 +91,6 @@ int main()
|
|||||||
quantity_point price_usd = zero + 100 * us_dollar;
|
quantity_point price_usd = zero + 100 * us_dollar;
|
||||||
quantity_point price_euro = exchange_to<euro>(price_usd);
|
quantity_point price_euro = exchange_to<euro>(price_usd);
|
||||||
|
|
||||||
std::cout << price_usd.quantity_from_origin() << " -> " << price_euro.quantity_from_origin() << "\n";
|
std::cout << price_usd.quantity_from(zero) << " -> " << price_euro.quantity_from(zero) << "\n";
|
||||||
// std::cout << price_usd.quantity_from_origin() + price_euro.quantity_from_origin() << "\n"; // does not compile
|
// std::cout << price_usd.quantity_from(zero) + price_euro.quantity_from(zero) << "\n"; // does not compile
|
||||||
}
|
}
|
||||||
|
@@ -83,12 +83,12 @@ void print(const R& gliders)
|
|||||||
std::cout << "- Name: " << g.name << "\n";
|
std::cout << "- Name: " << g.name << "\n";
|
||||||
std::cout << "- Polar:\n";
|
std::cout << "- Polar:\n";
|
||||||
for (const auto& p : g.polar) {
|
for (const auto& p : g.polar) {
|
||||||
const auto ratio = value_cast<one>(glide_ratio(g.polar[0]));
|
const auto ratio = glide_ratio(g.polar[0]).force_in(one);
|
||||||
std::cout << MP_UNITS_STD_FMT::format(" * {:%.4Q %q} @ {:%.1Q %q} -> {:%.1Q %q} ({:%.1Q %q})\n", p.climb, p.v,
|
std::cout << MP_UNITS_STD_FMT::format(" * {:%.4Q %q} @ {:%.1Q %q} -> {:%.1Q %q} ({:%.1Q %q})\n", p.climb, p.v,
|
||||||
ratio,
|
ratio,
|
||||||
// TODO is it possible to make ADL work below (we need another set of trig
|
// TODO is it possible to make ADL work below (we need another set of trig
|
||||||
// functions for strong angle in a different namespace)
|
// functions for strong angle in a different namespace)
|
||||||
value_cast<si::degree>(isq::asin(1 / ratio)));
|
isq::asin(1 / ratio).force_in(si::degree));
|
||||||
}
|
}
|
||||||
std::cout << "\n";
|
std::cout << "\n";
|
||||||
}
|
}
|
||||||
|
@@ -138,7 +138,7 @@ struct MP_UNITS_STD_FMT::formatter<geographic::latitude<T>> :
|
|||||||
auto format(geographic::latitude<T> lat, FormatContext& ctx)
|
auto format(geographic::latitude<T> lat, FormatContext& ctx)
|
||||||
{
|
{
|
||||||
formatter<typename geographic::latitude<T>::quantity_type>::format(
|
formatter<typename geographic::latitude<T>::quantity_type>::format(
|
||||||
is_gt_zero(lat) ? lat.quantity_from_origin() : -lat.quantity_from_origin(), ctx);
|
is_gt_zero(lat) ? lat.quantity_from(geographic::equator) : -lat.quantity_from(geographic::equator), ctx);
|
||||||
MP_UNITS_STD_FMT::format_to(ctx.out(), "{}", is_gt_zero(lat) ? " N" : "S");
|
MP_UNITS_STD_FMT::format_to(ctx.out(), "{}", is_gt_zero(lat) ? " N" : "S");
|
||||||
return ctx.out();
|
return ctx.out();
|
||||||
}
|
}
|
||||||
@@ -151,7 +151,8 @@ struct MP_UNITS_STD_FMT::formatter<geographic::longitude<T>> :
|
|||||||
auto format(geographic::longitude<T> lon, FormatContext& ctx)
|
auto format(geographic::longitude<T> lon, FormatContext& ctx)
|
||||||
{
|
{
|
||||||
formatter<typename geographic::longitude<T>::quantity_type>::format(
|
formatter<typename geographic::longitude<T>::quantity_type>::format(
|
||||||
is_gt_zero(lon) ? lon.quantity_from_origin() : -lon.quantity_from_origin(), ctx);
|
is_gt_zero(lon) ? lon.quantity_from(geographic::prime_meridian) : -lon.quantity_from(geographic::prime_meridian),
|
||||||
|
ctx);
|
||||||
MP_UNITS_STD_FMT::format_to(ctx.out(), "{}", is_gt_zero(lon) ? " E" : " W");
|
MP_UNITS_STD_FMT::format_to(ctx.out(), "{}", is_gt_zero(lon) ? " E" : " W");
|
||||||
return ctx.out();
|
return ctx.out();
|
||||||
}
|
}
|
||||||
@@ -171,28 +172,29 @@ template<typename T>
|
|||||||
distance spherical_distance(position<T> from, position<T> to)
|
distance spherical_distance(position<T> from, position<T> to)
|
||||||
{
|
{
|
||||||
using namespace mp_units;
|
using namespace mp_units;
|
||||||
constexpr auto earth_radius = 6'371 * isq::radius[si::kilo<si::metre>];
|
constexpr quantity earth_radius = 6'371 * isq::radius[si::kilo<si::metre>];
|
||||||
|
|
||||||
using isq::sin, isq::cos, isq::asin, isq::acos;
|
using isq::sin, isq::cos, isq::asin, isq::acos;
|
||||||
|
|
||||||
const auto& from_lat = from.lat.quantity_from_origin();
|
const quantity from_lat = from.lat.quantity_from(equator);
|
||||||
const auto& from_lon = from.lon.quantity_from_origin();
|
const quantity from_lon = from.lon.quantity_from(prime_meridian);
|
||||||
const auto& to_lat = to.lat.quantity_from_origin();
|
const quantity to_lat = to.lat.quantity_from(equator);
|
||||||
const auto& to_lon = to.lon.quantity_from_origin();
|
const quantity to_lon = to.lon.quantity_from(prime_meridian);
|
||||||
|
|
||||||
// https://en.wikipedia.org/wiki/Great-circle_distance#Formulae
|
// https://en.wikipedia.org/wiki/Great-circle_distance#Formulae
|
||||||
if constexpr (sizeof(T) >= 8) {
|
if constexpr (sizeof(T) >= 8) {
|
||||||
// spherical law of cosines
|
// spherical law of cosines
|
||||||
const auto central_angle = acos(sin(from_lat) * sin(to_lat) + cos(from_lat) * cos(to_lat) * cos(to_lon - from_lon));
|
const quantity central_angle =
|
||||||
|
acos(sin(from_lat) * sin(to_lat) + cos(from_lat) * cos(to_lat) * cos(to_lon - from_lon));
|
||||||
// const auto central_angle = 2 * asin(sqrt(0.5 - cos(to_lat - from_lat) / 2 + cos(from_lat) * cos(to_lat) * (1
|
// const auto central_angle = 2 * asin(sqrt(0.5 - cos(to_lat - from_lat) / 2 + cos(from_lat) * cos(to_lat) * (1
|
||||||
// - cos(lon2_rad - from_lon)) / 2));
|
// - cos(lon2_rad - from_lon)) / 2));
|
||||||
|
|
||||||
return quantity_cast<isq::distance>(earth_radius * central_angle);
|
return quantity_cast<isq::distance>(earth_radius * central_angle);
|
||||||
} else {
|
} else {
|
||||||
// the haversine formula
|
// the haversine formula
|
||||||
const auto sin_lat = sin((to_lat - from_lat) / 2);
|
const quantity sin_lat = sin((to_lat - from_lat) / 2);
|
||||||
const auto sin_lon = sin((to_lon - from_lon) / 2);
|
const quantity sin_lon = sin((to_lon - from_lon) / 2);
|
||||||
const auto central_angle = 2 * asin(sqrt(sin_lat * sin_lat + cos(from_lat) * cos(to_lat) * sin_lon * sin_lon));
|
const quantity central_angle = 2 * asin(sqrt(sin_lat * sin_lat + cos(from_lat) * cos(to_lat) * sin_lon * sin_lon));
|
||||||
|
|
||||||
return quantity_cast<isq::distance>(earth_radius * central_angle);
|
return quantity_cast<isq::distance>(earth_radius * central_angle);
|
||||||
}
|
}
|
||||||
|
@@ -212,7 +212,7 @@ struct MP_UNITS_STD_FMT::formatter<kalman::estimation<Q>> {
|
|||||||
if constexpr (mp_units::Quantity<Q>)
|
if constexpr (mp_units::Quantity<Q>)
|
||||||
return t;
|
return t;
|
||||||
else
|
else
|
||||||
return t.quantity_from_origin();
|
return t.quantity_ref_from(t.point_origin);
|
||||||
}(kalman::get<0>(e.state));
|
}(kalman::get<0>(e.state));
|
||||||
|
|
||||||
std::string value_buffer;
|
std::string value_buffer;
|
||||||
|
@@ -45,7 +45,7 @@ template<QuantityPoint QP, QuantityOf<dimensionless> K>
|
|||||||
void print(auto iteration, K gain, QP measured, kalman::estimation<QP> current, kalman::estimation<QP> next)
|
void print(auto iteration, K gain, QP measured, kalman::estimation<QP> current, kalman::estimation<QP> next)
|
||||||
{
|
{
|
||||||
std::cout << MP_UNITS_STD_FMT::format("{:2} | {:7%.4Q} | {:10%.3Q %q} | {:>18.3} | {:>18.3}\n", iteration, gain,
|
std::cout << MP_UNITS_STD_FMT::format("{:2} | {:7%.4Q} | {:10%.3Q %q} | {:>18.3} | {:>18.3}\n", iteration, gain,
|
||||||
measured.quantity_from_origin(), current, next);
|
measured.quantity_ref_from(QP::point_origin), current, next);
|
||||||
}
|
}
|
||||||
|
|
||||||
int main()
|
int main()
|
||||||
|
@@ -45,7 +45,7 @@ template<QuantityPoint QP, QuantityOf<dimensionless> K>
|
|||||||
void print(auto iteration, K gain, QP measured, kalman::estimation<QP> current, kalman::estimation<QP> next)
|
void print(auto iteration, K gain, QP measured, kalman::estimation<QP> current, kalman::estimation<QP> next)
|
||||||
{
|
{
|
||||||
std::cout << MP_UNITS_STD_FMT::format("{:2} | {:7%.4Q} | {:10%.3Q %q} | {:>18.3} | {:>18.3}\n", iteration, gain,
|
std::cout << MP_UNITS_STD_FMT::format("{:2} | {:7%.4Q} | {:10%.3Q %q} | {:>18.3} | {:>18.3}\n", iteration, gain,
|
||||||
measured.quantity_from_origin(), current, next);
|
measured.quantity_ref_from(QP::point_origin), current, next);
|
||||||
}
|
}
|
||||||
|
|
||||||
int main()
|
int main()
|
||||||
|
@@ -45,7 +45,7 @@ template<QuantityPoint QP, QuantityOf<dimensionless> K>
|
|||||||
void print(auto iteration, K gain, QP measured, kalman::estimation<QP> current, kalman::estimation<QP> next)
|
void print(auto iteration, K gain, QP measured, kalman::estimation<QP> current, kalman::estimation<QP> next)
|
||||||
{
|
{
|
||||||
std::cout << MP_UNITS_STD_FMT::format("{:2} | {:7%.3Q} | {:10%.3Q %q} | {:>16.2} | {:>16.2}\n", iteration, gain,
|
std::cout << MP_UNITS_STD_FMT::format("{:2} | {:7%.3Q} | {:10%.3Q %q} | {:>16.2} | {:>16.2}\n", iteration, gain,
|
||||||
measured.quantity_from_origin(), current, next);
|
measured.quantity_ref_from(QP::point_origin), current, next);
|
||||||
}
|
}
|
||||||
|
|
||||||
int main()
|
int main()
|
||||||
|
@@ -80,7 +80,7 @@ void si_example()
|
|||||||
<< "E = " << E3 << "\n";
|
<< "E = " << E3 << "\n";
|
||||||
|
|
||||||
std::cout << "\n[converted from SI units back to GeV]\n"
|
std::cout << "\n[converted from SI units back to GeV]\n"
|
||||||
<< "E = " << value_cast<GeV>(E3) << "\n";
|
<< "E = " << E3.force_in(GeV) << "\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
void natural_example()
|
void natural_example()
|
||||||
|
@@ -97,8 +97,8 @@ template<earth_gravity_model M>
|
|||||||
hae_altitude<M> to_hae(msl_altitude msl, position<long double> pos)
|
hae_altitude<M> to_hae(msl_altitude msl, position<long double> pos)
|
||||||
{
|
{
|
||||||
const auto geoid_undulation =
|
const auto geoid_undulation =
|
||||||
isq::height(GeographicLibWhatsMyOffset(pos.lat.quantity_from_origin().numerical_value_in(si::degree),
|
isq::height(GeographicLibWhatsMyOffset(pos.lat.quantity_from(equator).numerical_value_in(si::degree),
|
||||||
pos.lon.quantity_from_origin().numerical_value_in(si::degree)) *
|
pos.lon.quantity_from(prime_meridian).numerical_value_in(si::degree)) *
|
||||||
si::metre);
|
si::metre);
|
||||||
return height_above_ellipsoid<M> + (msl - mean_sea_level - geoid_undulation);
|
return height_above_ellipsoid<M> + (msl - mean_sea_level - geoid_undulation);
|
||||||
}
|
}
|
||||||
@@ -115,7 +115,7 @@ using hal_altitude = quantity_point<isq::altitude[si::metre], height_above_launc
|
|||||||
template<class CharT, class Traits>
|
template<class CharT, class Traits>
|
||||||
std::basic_ostream<CharT, Traits>& operator<<(std::basic_ostream<CharT, Traits>& os, const hal_altitude& a)
|
std::basic_ostream<CharT, Traits>& operator<<(std::basic_ostream<CharT, Traits>& os, const hal_altitude& a)
|
||||||
{
|
{
|
||||||
return os << a.quantity_from_origin() << " HAL";
|
return os << a.quantity_from(height_above_launch) << " HAL";
|
||||||
}
|
}
|
||||||
|
|
||||||
template<>
|
template<>
|
||||||
@@ -123,7 +123,7 @@ struct MP_UNITS_STD_FMT::formatter<hal_altitude> : formatter<hal_altitude::quant
|
|||||||
template<typename FormatContext>
|
template<typename FormatContext>
|
||||||
auto format(const hal_altitude& a, FormatContext& ctx)
|
auto format(const hal_altitude& a, FormatContext& ctx)
|
||||||
{
|
{
|
||||||
formatter<hal_altitude::quantity_type>::format(a.quantity_from_origin(), ctx);
|
formatter<hal_altitude::quantity_type>::format(a.quantity_from(height_above_launch), ctx);
|
||||||
return MP_UNITS_STD_FMT::format_to(ctx.out(), " HAL");
|
return MP_UNITS_STD_FMT::format_to(ctx.out(), " HAL");
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@@ -224,9 +224,9 @@ struct quantity_formatter {
|
|||||||
const quantity_format_specs<CharT>& specs;
|
const quantity_format_specs<CharT>& specs;
|
||||||
Locale loc;
|
Locale loc;
|
||||||
|
|
||||||
explicit quantity_formatter(OutputIt o, quantity<Reference, Rep> q, const quantity_format_specs<CharT>& fspecs,
|
explicit quantity_formatter(OutputIt o, const quantity<Reference, Rep>& q, const quantity_format_specs<CharT>& fspecs,
|
||||||
Locale lc) :
|
Locale lc) :
|
||||||
out(o), val(std::move(q).numerical_value()), specs(fspecs), loc(std::move(lc))
|
out(o), val(q.numerical_value_ref_in(q.unit)), specs(fspecs), loc(std::move(lc))
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -396,7 +396,8 @@ private:
|
|||||||
|
|
||||||
if (begin == end || *begin == '}') {
|
if (begin == end || *begin == '}') {
|
||||||
// default format should print value followed by the unit separated with 1 space
|
// default format should print value followed by the unit separated with 1 space
|
||||||
out = mp_units::detail::format_units_quantity_value<CharT>(out, q.numerical_value(), specs.rep, ctx.locale());
|
out = mp_units::detail::format_units_quantity_value<CharT>(out, q.numerical_value_ref_in(q.unit), specs.rep,
|
||||||
|
ctx.locale());
|
||||||
if constexpr (mp_units::detail::has_unit_symbol(get_unit(Reference))) {
|
if constexpr (mp_units::detail::has_unit_symbol(get_unit(Reference))) {
|
||||||
if constexpr (mp_units::space_before_unit_symbol<get_unit(Reference)>) *out++ = CharT(' ');
|
if constexpr (mp_units::space_before_unit_symbol<get_unit(Reference)>) *out++ = CharT(' ');
|
||||||
out = unit_symbol_to<CharT>(out, get_unit(Reference));
|
out = unit_symbol_to<CharT>(out, get_unit(Reference));
|
||||||
|
@@ -36,9 +36,9 @@ void to_stream(std::basic_ostream<CharT, Traits>& os, const quantity<R, Rep>& q)
|
|||||||
{
|
{
|
||||||
if constexpr (is_same_v<Rep, std::uint8_t> || is_same_v<Rep, std::int8_t>)
|
if constexpr (is_same_v<Rep, std::uint8_t> || is_same_v<Rep, std::int8_t>)
|
||||||
// promote the value to int
|
// promote the value to int
|
||||||
os << +q.numerical_value();
|
os << +q.numerical_value_ref_in(q.unit);
|
||||||
else
|
else
|
||||||
os << q.numerical_value();
|
os << q.numerical_value_ref_in(q.unit);
|
||||||
if constexpr (has_unit_symbol(get_unit(R))) {
|
if constexpr (has_unit_symbol(get_unit(R))) {
|
||||||
if constexpr (space_before_unit_symbol<get_unit(R)>) os << " ";
|
if constexpr (space_before_unit_symbol<get_unit(R)>) os << " ";
|
||||||
unit_symbol_to<CharT>(std::ostream_iterator<CharT>(os), get_unit(R));
|
unit_symbol_to<CharT>(std::ostream_iterator<CharT>(os), get_unit(R));
|
||||||
@@ -49,7 +49,7 @@ void to_stream(std::basic_ostream<CharT, Traits>& os, const quantity<R, Rep>& q)
|
|||||||
|
|
||||||
template<typename CharT, typename Traits, auto R, typename Rep>
|
template<typename CharT, typename Traits, auto R, typename Rep>
|
||||||
std::basic_ostream<CharT, Traits>& operator<<(std::basic_ostream<CharT, Traits>& os, const quantity<R, Rep>& q)
|
std::basic_ostream<CharT, Traits>& operator<<(std::basic_ostream<CharT, Traits>& os, const quantity<R, Rep>& q)
|
||||||
requires requires { os << q.numerical_value(); }
|
requires requires { os << q.numerical_value_ref_in(q.unit); }
|
||||||
{
|
{
|
||||||
if (os.width()) {
|
if (os.width()) {
|
||||||
// std::setw() applies to the whole quantity output so it has to be first put into std::string
|
// std::setw() applies to the whole quantity output so it has to be first put into std::string
|
||||||
|
@@ -51,9 +51,9 @@ template<QuantitySpec auto ToQS, typename Q>
|
|||||||
{
|
{
|
||||||
if constexpr (detail::QuantityKindSpec<std::remove_const_t<decltype(ToQS)>> &&
|
if constexpr (detail::QuantityKindSpec<std::remove_const_t<decltype(ToQS)>> &&
|
||||||
AssociatedUnit<std::remove_const_t<decltype(Q::unit)>>)
|
AssociatedUnit<std::remove_const_t<decltype(Q::unit)>>)
|
||||||
return make_quantity<Q::unit>(std::forward<Q>(q).numerical_value());
|
return make_quantity<Q::unit>(std::forward<Q>(q).numerical_value_);
|
||||||
else
|
else
|
||||||
return make_quantity<reference<ToQS, Q::unit>{}>(std::forward<Q>(q).numerical_value());
|
return make_quantity<reference<ToQS, Q::unit>{}>(std::forward<Q>(q).numerical_value_);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace mp_units
|
} // namespace mp_units
|
||||||
|
@@ -63,7 +63,7 @@ template<Quantity To, typename From>
|
|||||||
if constexpr (q_unit == To::unit) {
|
if constexpr (q_unit == To::unit) {
|
||||||
// no scaling of the number needed
|
// no scaling of the number needed
|
||||||
return make_quantity<To::reference>(static_cast<MP_UNITS_TYPENAME To::rep>(
|
return make_quantity<To::reference>(static_cast<MP_UNITS_TYPENAME To::rep>(
|
||||||
std::forward<From>(q).numerical_value())); // this is the only (and recommended) way to do
|
std::forward<From>(q).numerical_value_)); // this is the only (and recommended) way to do
|
||||||
// a truncating conversion on a number, so we are
|
// a truncating conversion on a number, so we are
|
||||||
// using static_cast to suppress all the compiler
|
// using static_cast to suppress all the compiler
|
||||||
// warnings on conversions
|
// warnings on conversions
|
||||||
@@ -78,7 +78,7 @@ template<Quantity To, typename From>
|
|||||||
using multiplier_type =
|
using multiplier_type =
|
||||||
conditional<treat_as_floating_point<c_rep_type>, std::common_type_t<c_mag_type, long double>, c_mag_type>;
|
conditional<treat_as_floating_point<c_rep_type>, std::common_type_t<c_mag_type, long double>, c_mag_type>;
|
||||||
constexpr auto val = [](Magnitude auto m) { return get_value<multiplier_type>(m); };
|
constexpr auto val = [](Magnitude auto m) { return get_value<multiplier_type>(m); };
|
||||||
return static_cast<MP_UNITS_TYPENAME To::rep>(static_cast<c_rep_type>(std::forward<From>(q).numerical_value()) *
|
return static_cast<MP_UNITS_TYPENAME To::rep>(static_cast<c_rep_type>(std::forward<From>(q).numerical_value_) *
|
||||||
val(num) / val(den) * val(irr)) *
|
val(num) / val(den) * val(irr)) *
|
||||||
To::reference;
|
To::reference;
|
||||||
}
|
}
|
||||||
|
@@ -85,7 +85,7 @@ using common_quantity_for = quantity<common_reference(Q1::reference, Q2::referen
|
|||||||
template<Reference auto R, RepresentationOf<get_quantity_spec(R).character> Rep = double>
|
template<Reference auto R, RepresentationOf<get_quantity_spec(R).character> Rep = double>
|
||||||
class quantity {
|
class quantity {
|
||||||
public:
|
public:
|
||||||
Rep value_; // needs to be public for a structural type
|
Rep numerical_value_; // needs to be public for a structural type
|
||||||
|
|
||||||
// member types and values
|
// member types and values
|
||||||
static constexpr Reference auto reference = R;
|
static constexpr Reference auto reference = R;
|
||||||
@@ -126,7 +126,7 @@ public:
|
|||||||
|
|
||||||
template<detail::QuantityConvertibleTo<quantity> Q>
|
template<detail::QuantityConvertibleTo<quantity> Q>
|
||||||
constexpr explicit(!std::convertible_to<typename Q::rep, Rep>) quantity(const Q& q) :
|
constexpr explicit(!std::convertible_to<typename Q::rep, Rep>) quantity(const Q& q) :
|
||||||
value_(detail::sudo_cast<quantity>(q).numerical_value())
|
numerical_value_(detail::sudo_cast<quantity>(q).numerical_value_)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -141,27 +141,7 @@ public:
|
|||||||
quantity& operator=(const quantity&) = default;
|
quantity& operator=(const quantity&) = default;
|
||||||
quantity& operator=(quantity&&) = default;
|
quantity& operator=(quantity&&) = default;
|
||||||
|
|
||||||
// data access
|
// conversions
|
||||||
#ifdef __cpp_explicit_this_parameter
|
|
||||||
template<typename Self>
|
|
||||||
[[nodiscard]] constexpr auto&& value(this Self&& self) noexcept
|
|
||||||
{
|
|
||||||
return std::forward<Self>(self).value_;
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
[[nodiscard]] constexpr rep& numerical_value() & noexcept { return value_; }
|
|
||||||
[[nodiscard]] constexpr const rep& numerical_value() const& noexcept { return value_; }
|
|
||||||
[[nodiscard]] constexpr rep&& numerical_value() && noexcept { return std::move(value_); }
|
|
||||||
[[nodiscard]] constexpr const rep&& numerical_value() const&& noexcept { return std::move(value_); }
|
|
||||||
#endif
|
|
||||||
|
|
||||||
template<Unit U>
|
|
||||||
requires requires(quantity q) { q.in(U{}); }
|
|
||||||
[[nodiscard]] constexpr rep numerical_value_in(U) const noexcept
|
|
||||||
{
|
|
||||||
return (*this).in(U{}).numerical_value();
|
|
||||||
}
|
|
||||||
|
|
||||||
template<Unit U>
|
template<Unit U>
|
||||||
requires detail::QuantityConvertibleTo<quantity, quantity<quantity_spec[U{}], Rep>>
|
requires detail::QuantityConvertibleTo<quantity, quantity<quantity_spec[U{}], Rep>>
|
||||||
[[nodiscard]] constexpr quantity<quantity_spec[U{}], Rep> in(U) const
|
[[nodiscard]] constexpr quantity<quantity_spec[U{}], Rep> in(U) const
|
||||||
@@ -169,6 +149,46 @@ public:
|
|||||||
return quantity<quantity_spec[U{}], Rep>{*this};
|
return quantity<quantity_spec[U{}], Rep>{*this};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<Unit U>
|
||||||
|
requires requires(quantity q) { value_cast<U{}>(q); }
|
||||||
|
[[nodiscard]] constexpr quantity<quantity_spec[U{}], Rep> force_in(U) const
|
||||||
|
{
|
||||||
|
return value_cast<U{}>(*this);
|
||||||
|
}
|
||||||
|
|
||||||
|
// data access
|
||||||
|
template<Unit U>
|
||||||
|
requires(U{} == unit)
|
||||||
|
[[nodiscard]] constexpr rep& numerical_value_ref_in(U) & noexcept
|
||||||
|
{
|
||||||
|
return numerical_value_;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<Unit U>
|
||||||
|
requires(U{} == unit)
|
||||||
|
[[nodiscard]] constexpr const rep& numerical_value_ref_in(U) const& noexcept
|
||||||
|
{
|
||||||
|
return numerical_value_;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<Unit U>
|
||||||
|
requires(U{} == unit)
|
||||||
|
constexpr const rep&& numerical_value_ref_in(U) const&& noexcept = delete;
|
||||||
|
|
||||||
|
template<Unit U>
|
||||||
|
requires requires(quantity q) { q.in(U{}); }
|
||||||
|
[[nodiscard]] constexpr rep numerical_value_in(U) const noexcept
|
||||||
|
{
|
||||||
|
return (*this).in(U{}).numerical_value_;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<Unit U>
|
||||||
|
requires requires(quantity q) { q.force_in(U{}); }
|
||||||
|
[[nodiscard]] constexpr rep force_numerical_value_in(U) const noexcept
|
||||||
|
{
|
||||||
|
return (*this).force_in(U{}).numerical_value_;
|
||||||
|
}
|
||||||
|
|
||||||
// member unary operators
|
// member unary operators
|
||||||
[[nodiscard]] constexpr Quantity auto operator+() const
|
[[nodiscard]] constexpr Quantity auto operator+() const
|
||||||
requires requires(rep v) {
|
requires requires(rep v) {
|
||||||
@@ -177,7 +197,7 @@ public:
|
|||||||
} -> std::common_with<rep>;
|
} -> std::common_with<rep>;
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
return make_quantity<reference>(+numerical_value());
|
return make_quantity<reference>(+numerical_value_);
|
||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]] constexpr Quantity auto operator-() const
|
[[nodiscard]] constexpr Quantity auto operator-() const
|
||||||
@@ -187,18 +207,19 @@ public:
|
|||||||
} -> std::common_with<rep>;
|
} -> std::common_with<rep>;
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
return make_quantity<reference>(-numerical_value());
|
return make_quantity<reference>(-numerical_value_);
|
||||||
}
|
}
|
||||||
|
|
||||||
constexpr quantity& operator++()
|
template<typename Q>
|
||||||
requires requires(rep v) {
|
friend constexpr decltype(auto) operator++(Q&& q)
|
||||||
|
requires std::derived_from<std::remove_cvref_t<Q>, quantity> && requires(rep v) {
|
||||||
{
|
{
|
||||||
++v
|
++v
|
||||||
} -> std::same_as<rep&>;
|
} -> std::same_as<rep&>;
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
++value_;
|
++q.numerical_value_;
|
||||||
return *this;
|
return std::forward<Q>(q);
|
||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]] constexpr Quantity auto operator++(int)
|
[[nodiscard]] constexpr Quantity auto operator++(int)
|
||||||
@@ -208,18 +229,19 @@ public:
|
|||||||
} -> std::common_with<rep>;
|
} -> std::common_with<rep>;
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
return make_quantity<reference>(value_++);
|
return make_quantity<reference>(numerical_value_++);
|
||||||
}
|
}
|
||||||
|
|
||||||
constexpr quantity& operator--()
|
template<typename Q>
|
||||||
requires requires(rep v) {
|
friend constexpr decltype(auto) operator--(Q&& q)
|
||||||
|
requires std::derived_from<std::remove_cvref_t<Q>, quantity> && requires(rep v) {
|
||||||
{
|
{
|
||||||
--v
|
--v
|
||||||
} -> std::same_as<rep&>;
|
} -> std::same_as<rep&>;
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
--value_;
|
--q.numerical_value_;
|
||||||
return *this;
|
return std::forward<Q>(q);
|
||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]] constexpr Quantity auto operator--(int)
|
[[nodiscard]] constexpr Quantity auto operator--(int)
|
||||||
@@ -229,92 +251,101 @@ public:
|
|||||||
} -> std::common_with<rep>;
|
} -> std::common_with<rep>;
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
return make_quantity<reference>(value_--);
|
return make_quantity<reference>(numerical_value_--);
|
||||||
}
|
}
|
||||||
|
|
||||||
// compound assignment operators
|
// compound assignment operators
|
||||||
constexpr quantity& operator+=(const quantity& q)
|
template<typename Q>
|
||||||
requires requires(rep a, rep b) {
|
requires std::derived_from<std::remove_cvref_t<Q>, quantity> && requires(rep a, rep b) {
|
||||||
{
|
{
|
||||||
a += b
|
a += b
|
||||||
} -> std::same_as<rep&>;
|
} -> std::same_as<rep&>;
|
||||||
}
|
}
|
||||||
|
friend constexpr decltype(auto) operator+=(Q&& lhs, const quantity& rhs)
|
||||||
{
|
{
|
||||||
value_ += q.numerical_value();
|
lhs.numerical_value_ += rhs.numerical_value_;
|
||||||
return *this;
|
return std::forward<Q>(lhs);
|
||||||
}
|
}
|
||||||
|
|
||||||
constexpr quantity& operator-=(const quantity& q)
|
template<typename Q>
|
||||||
requires requires(rep a, rep b) {
|
requires std::derived_from<std::remove_cvref_t<Q>, quantity> && requires(rep a, rep b) {
|
||||||
{
|
{
|
||||||
a -= b
|
a -= b
|
||||||
} -> std::same_as<rep&>;
|
} -> std::same_as<rep&>;
|
||||||
}
|
}
|
||||||
|
friend constexpr decltype(auto) operator-=(Q&& lhs, const quantity& rhs)
|
||||||
{
|
{
|
||||||
value_ -= q.numerical_value();
|
lhs.numerical_value_ -= rhs.numerical_value_;
|
||||||
return *this;
|
return std::forward<Q>(lhs);
|
||||||
}
|
}
|
||||||
|
|
||||||
constexpr quantity& operator%=(const quantity& q)
|
template<typename Q>
|
||||||
requires(!treat_as_floating_point<rep>) && requires(rep a, rep b) {
|
requires std::derived_from<std::remove_cvref_t<Q>, quantity> && (!treat_as_floating_point<rep>) &&
|
||||||
|
requires(rep a, rep b) {
|
||||||
{
|
{
|
||||||
a %= b
|
a %= b
|
||||||
} -> std::same_as<rep&>;
|
} -> std::same_as<rep&>;
|
||||||
}
|
}
|
||||||
|
friend constexpr decltype(auto) operator%=(Q&& lhs, const quantity& rhs)
|
||||||
|
|
||||||
{
|
{
|
||||||
gsl_ExpectsAudit(q != zero());
|
gsl_ExpectsAudit(rhs != zero());
|
||||||
value_ %= q.numerical_value();
|
lhs.numerical_value_ %= rhs.numerical_value_;
|
||||||
return *this;
|
return std::forward<Q>(lhs);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename Value>
|
template<typename Q, typename Value>
|
||||||
requires(!Quantity<Value>) && requires(rep a, const Value b) {
|
requires std::derived_from<std::remove_cvref_t<Q>, quantity> && (!Quantity<Value>) &&
|
||||||
|
requires(rep a, const Value b) {
|
||||||
{
|
{
|
||||||
a *= b
|
a *= b
|
||||||
} -> std::same_as<rep&>;
|
} -> std::same_as<rep&>;
|
||||||
}
|
}
|
||||||
constexpr quantity& operator*=(const Value& v)
|
friend constexpr decltype(auto) operator*=(Q&& lhs, const Value& v)
|
||||||
{
|
{
|
||||||
value_ *= v;
|
lhs.numerical_value_ *= v;
|
||||||
return *this;
|
return std::forward<Q>(lhs);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<QuantityOf<dimension_one> Q>
|
template<typename Q1, QuantityOf<dimension_one> Q2>
|
||||||
requires(Q::unit == ::mp_units::one) && requires(rep a, const typename Q::rep b) {
|
requires std::derived_from<std::remove_cvref_t<Q1>, quantity> && (Q2::unit == ::mp_units::one) &&
|
||||||
|
requires(rep a, const typename Q2::rep b) {
|
||||||
{
|
{
|
||||||
a *= b
|
a *= b
|
||||||
} -> std::same_as<rep&>;
|
} -> std::same_as<rep&>;
|
||||||
}
|
}
|
||||||
constexpr quantity& operator*=(const Q& rhs)
|
friend constexpr decltype(auto) operator*=(Q1&& lhs, const Q2& rhs)
|
||||||
{
|
{
|
||||||
value_ *= rhs.numerical_value();
|
lhs.numerical_value_ *= rhs.numerical_value_;
|
||||||
return *this;
|
return std::forward<Q1>(lhs);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename Value>
|
template<typename Q, typename Value>
|
||||||
requires(!Quantity<Value>) && requires(rep a, const Value b) {
|
requires std::derived_from<std::remove_cvref_t<Q>, quantity> && (!Quantity<Value>) &&
|
||||||
|
requires(rep a, const Value b) {
|
||||||
{
|
{
|
||||||
a /= b
|
a /= b
|
||||||
} -> std::same_as<rep&>;
|
} -> std::same_as<rep&>;
|
||||||
}
|
}
|
||||||
constexpr quantity& operator/=(const Value& v)
|
friend constexpr decltype(auto) operator/=(Q&& lhs, const Value& v)
|
||||||
{
|
{
|
||||||
gsl_ExpectsAudit(v != quantity_values<Value>::zero());
|
gsl_ExpectsAudit(v != quantity_values<Value>::zero());
|
||||||
value_ /= v;
|
lhs.numerical_value_ /= v;
|
||||||
return *this;
|
return std::forward<Q>(lhs);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<QuantityOf<dimension_one> Q>
|
template<typename Q1, QuantityOf<dimension_one> Q2>
|
||||||
requires(Q::unit == ::mp_units::one) && requires(rep a, const typename Q::rep b) {
|
requires std::derived_from<std::remove_cvref_t<Q1>, quantity> && (Q2::unit == ::mp_units::one) &&
|
||||||
|
requires(rep a, const typename Q2::rep b) {
|
||||||
{
|
{
|
||||||
a /= b
|
a /= b
|
||||||
} -> std::same_as<rep&>;
|
} -> std::same_as<rep&>;
|
||||||
}
|
}
|
||||||
constexpr quantity& operator/=(const Q& rhs)
|
friend constexpr decltype(auto) operator/=(Q1&& lhs, const Q2& rhs)
|
||||||
{
|
{
|
||||||
gsl_ExpectsAudit(rhs != rhs.zero());
|
gsl_ExpectsAudit(rhs != rhs.zero());
|
||||||
value_ /= rhs.numerical_value();
|
lhs.numerical_value_ /= rhs.numerical_value_;
|
||||||
return *this;
|
return std::forward<Q1>(lhs);
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@@ -327,7 +358,7 @@ private:
|
|||||||
|
|
||||||
template<typename Value>
|
template<typename Value>
|
||||||
requires std::constructible_from<rep, Value&&>
|
requires std::constructible_from<rep, Value&&>
|
||||||
constexpr explicit quantity(Value&& v) : value_(std::forward<Value>(v))
|
constexpr explicit quantity(Value&& v) : numerical_value_(std::forward<Value>(v))
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -342,7 +373,7 @@ template<auto R1, typename Rep1, auto R2, typename Rep2>
|
|||||||
[[nodiscard]] constexpr Quantity auto operator+(const quantity<R1, Rep1>& lhs, const quantity<R2, Rep2>& rhs)
|
[[nodiscard]] constexpr Quantity auto operator+(const quantity<R1, Rep1>& lhs, const quantity<R2, Rep2>& rhs)
|
||||||
{
|
{
|
||||||
using ret = detail::common_quantity_for<std::plus<>, quantity<R1, Rep1>, quantity<R2, Rep2>>;
|
using ret = detail::common_quantity_for<std::plus<>, quantity<R1, Rep1>, quantity<R2, Rep2>>;
|
||||||
return make_quantity<ret::reference>(ret(lhs).numerical_value() + ret(rhs).numerical_value());
|
return make_quantity<ret::reference>(ret(lhs).numerical_value_ + ret(rhs).numerical_value_);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<auto R1, typename Rep1, auto R2, typename Rep2>
|
template<auto R1, typename Rep1, auto R2, typename Rep2>
|
||||||
@@ -350,7 +381,7 @@ template<auto R1, typename Rep1, auto R2, typename Rep2>
|
|||||||
[[nodiscard]] constexpr Quantity auto operator-(const quantity<R1, Rep1>& lhs, const quantity<R2, Rep2>& rhs)
|
[[nodiscard]] constexpr Quantity auto operator-(const quantity<R1, Rep1>& lhs, const quantity<R2, Rep2>& rhs)
|
||||||
{
|
{
|
||||||
using ret = detail::common_quantity_for<std::minus<>, quantity<R1, Rep1>, quantity<R2, Rep2>>;
|
using ret = detail::common_quantity_for<std::minus<>, quantity<R1, Rep1>, quantity<R2, Rep2>>;
|
||||||
return make_quantity<ret::reference>(ret(lhs).numerical_value() - ret(rhs).numerical_value());
|
return make_quantity<ret::reference>(ret(lhs).numerical_value_ - ret(rhs).numerical_value_);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<auto R1, typename Rep1, auto R2, typename Rep2>
|
template<auto R1, typename Rep1, auto R2, typename Rep2>
|
||||||
@@ -360,7 +391,7 @@ template<auto R1, typename Rep1, auto R2, typename Rep2>
|
|||||||
{
|
{
|
||||||
gsl_ExpectsAudit(rhs != rhs.zero());
|
gsl_ExpectsAudit(rhs != rhs.zero());
|
||||||
using ret = detail::common_quantity_for<std::modulus<>, quantity<R1, Rep1>, quantity<R2, Rep2>>;
|
using ret = detail::common_quantity_for<std::modulus<>, quantity<R1, Rep1>, quantity<R2, Rep2>>;
|
||||||
return make_quantity<ret::reference>(ret(lhs).numerical_value() % ret(rhs).numerical_value());
|
return make_quantity<ret::reference>(ret(lhs).numerical_value_ % ret(rhs).numerical_value_);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<auto R1, typename Rep1, auto R2, typename Rep2>
|
template<auto R1, typename Rep1, auto R2, typename Rep2>
|
||||||
@@ -368,7 +399,7 @@ template<auto R1, typename Rep1, auto R2, typename Rep2>
|
|||||||
Rep2>
|
Rep2>
|
||||||
[[nodiscard]] constexpr Quantity auto operator*(const quantity<R1, Rep1>& lhs, const quantity<R2, Rep2>& rhs)
|
[[nodiscard]] constexpr Quantity auto operator*(const quantity<R1, Rep1>& lhs, const quantity<R2, Rep2>& rhs)
|
||||||
{
|
{
|
||||||
return make_quantity<R1 * R2>(lhs.numerical_value() * rhs.numerical_value());
|
return make_quantity<R1 * R2>(lhs.numerical_value_ * rhs.numerical_value_);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<auto R, typename Rep, typename Value>
|
template<auto R, typename Rep, typename Value>
|
||||||
@@ -376,7 +407,7 @@ template<auto R, typename Rep, typename Value>
|
|||||||
detail::InvokeResultOf<get_quantity_spec(R).character, std::multiplies<>, Rep, const 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)
|
[[nodiscard]] constexpr Quantity auto operator*(const quantity<R, Rep>& q, const Value& v)
|
||||||
{
|
{
|
||||||
return make_quantity<R>(q.numerical_value() * v);
|
return make_quantity<R>(q.numerical_value_ * v);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename Value, auto R, typename Rep>
|
template<typename Value, auto R, typename Rep>
|
||||||
@@ -384,7 +415,7 @@ template<typename Value, auto R, typename Rep>
|
|||||||
detail::InvokeResultOf<get_quantity_spec(R).character, std::multiplies<>, const Value&, Rep>
|
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)
|
[[nodiscard]] constexpr Quantity auto operator*(const Value& v, const quantity<R, Rep>& q)
|
||||||
{
|
{
|
||||||
return make_quantity<R>(v * q.numerical_value());
|
return make_quantity<R>(v * q.numerical_value_);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<auto R1, typename Rep1, auto R2, typename Rep2>
|
template<auto R1, typename Rep1, auto R2, typename Rep2>
|
||||||
@@ -392,7 +423,7 @@ template<auto R1, typename Rep1, auto R2, typename Rep2>
|
|||||||
[[nodiscard]] constexpr Quantity auto operator/(const quantity<R1, Rep1>& lhs, const quantity<R2, Rep2>& rhs)
|
[[nodiscard]] constexpr Quantity auto operator/(const quantity<R1, Rep1>& lhs, const quantity<R2, Rep2>& rhs)
|
||||||
{
|
{
|
||||||
gsl_ExpectsAudit(rhs != rhs.zero());
|
gsl_ExpectsAudit(rhs != rhs.zero());
|
||||||
return make_quantity<R1 / R2>(lhs.numerical_value() / rhs.numerical_value());
|
return make_quantity<R1 / R2>(lhs.numerical_value_ / rhs.numerical_value_);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<auto R, typename Rep, typename Value>
|
template<auto R, typename Rep, typename Value>
|
||||||
@@ -401,7 +432,7 @@ template<auto R, typename Rep, typename Value>
|
|||||||
[[nodiscard]] constexpr Quantity auto operator/(const quantity<R, Rep>& q, const Value& v)
|
[[nodiscard]] constexpr Quantity auto operator/(const quantity<R, Rep>& q, const Value& v)
|
||||||
{
|
{
|
||||||
gsl_ExpectsAudit(v != quantity_values<Value>::zero());
|
gsl_ExpectsAudit(v != quantity_values<Value>::zero());
|
||||||
return make_quantity<R>(q.numerical_value() / v);
|
return make_quantity<R>(q.numerical_value_ / v);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename Value, auto R, typename Rep>
|
template<typename Value, auto R, typename Rep>
|
||||||
@@ -409,7 +440,7 @@ template<typename Value, auto R, typename Rep>
|
|||||||
detail::InvokeResultOf<get_quantity_spec(R).character, std::divides<>, const Value&, Rep>
|
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)
|
[[nodiscard]] constexpr Quantity auto operator/(const Value& v, const quantity<R, Rep>& q)
|
||||||
{
|
{
|
||||||
return make_quantity<::mp_units::one / R>(v / q.numerical_value());
|
return make_quantity<::mp_units::one / R>(v / q.numerical_value_);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<auto R1, typename Rep1, auto R2, typename Rep2>
|
template<auto R1, typename Rep1, auto R2, typename Rep2>
|
||||||
@@ -418,7 +449,7 @@ template<auto R1, typename Rep1, auto R2, typename Rep2>
|
|||||||
[[nodiscard]] constexpr bool operator==(const quantity<R1, Rep1>& lhs, const quantity<R2, Rep2>& rhs)
|
[[nodiscard]] constexpr bool operator==(const quantity<R1, Rep1>& lhs, const quantity<R2, Rep2>& rhs)
|
||||||
{
|
{
|
||||||
using ct = std::common_type_t<quantity<R1, Rep1>, quantity<R2, Rep2>>;
|
using ct = std::common_type_t<quantity<R1, Rep1>, quantity<R2, Rep2>>;
|
||||||
return ct(lhs).numerical_value() == ct(rhs).numerical_value();
|
return ct(lhs).numerical_value_ == ct(rhs).numerical_value_;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<auto R1, typename Rep1, auto R2, typename Rep2>
|
template<auto R1, typename Rep1, auto R2, typename Rep2>
|
||||||
@@ -427,7 +458,7 @@ template<auto R1, typename Rep1, auto R2, typename Rep2>
|
|||||||
[[nodiscard]] constexpr auto operator<=>(const quantity<R1, Rep1>& lhs, const quantity<R2, Rep2>& rhs)
|
[[nodiscard]] constexpr auto operator<=>(const quantity<R1, Rep1>& lhs, const quantity<R2, Rep2>& rhs)
|
||||||
{
|
{
|
||||||
using ct = std::common_type_t<quantity<R1, Rep1>, quantity<R2, Rep2>>;
|
using ct = std::common_type_t<quantity<R1, Rep1>, quantity<R2, Rep2>>;
|
||||||
return ct(lhs).numerical_value() <=> ct(rhs).numerical_value();
|
return ct(lhs).numerical_value_ <=> ct(rhs).numerical_value_;
|
||||||
}
|
}
|
||||||
|
|
||||||
// make_quantity
|
// make_quantity
|
||||||
|
@@ -82,7 +82,7 @@ public:
|
|||||||
using rep = Rep;
|
using rep = Rep;
|
||||||
using quantity_type = quantity<reference, Rep>;
|
using quantity_type = quantity<reference, Rep>;
|
||||||
|
|
||||||
quantity_type q_; // needs to be public for a structural type
|
quantity_type quantity_from_origin_; // needs to be public for a structural type
|
||||||
|
|
||||||
// static member functions
|
// static member functions
|
||||||
[[nodiscard]] static constexpr quantity_point zero() noexcept
|
[[nodiscard]] static constexpr quantity_point zero() noexcept
|
||||||
@@ -112,10 +112,10 @@ public:
|
|||||||
requires std::constructible_from<quantity_type, typename QP::quantity_type>
|
requires std::constructible_from<quantity_type, typename QP::quantity_type>
|
||||||
// TODO add perfect forwarding
|
// TODO add perfect forwarding
|
||||||
constexpr explicit(!std::convertible_to<typename QP::quantity_type, quantity_type>) quantity_point(const QP& qp) :
|
constexpr explicit(!std::convertible_to<typename QP::quantity_type, quantity_type>) quantity_point(const QP& qp) :
|
||||||
q_([&] {
|
quantity_from_origin_([&] {
|
||||||
if constexpr (is_same_v<std::remove_const_t<decltype(point_origin)>,
|
if constexpr (is_same_v<std::remove_const_t<decltype(point_origin)>,
|
||||||
std::remove_const_t<decltype(QP::point_origin)>>)
|
std::remove_const_t<decltype(QP::point_origin)>>)
|
||||||
return qp.quantity_from_origin();
|
return qp.quantity_ref_from(point_origin);
|
||||||
else
|
else
|
||||||
return qp - point_origin;
|
return qp - point_origin;
|
||||||
}())
|
}())
|
||||||
@@ -128,7 +128,8 @@ public:
|
|||||||
std::convertible_to<
|
std::convertible_to<
|
||||||
quantity<quantity_point_like_traits<QP>::reference, typename quantity_point_like_traits<QP>::rep>,
|
quantity<quantity_point_like_traits<QP>::reference, typename quantity_point_like_traits<QP>::rep>,
|
||||||
quantity_type>
|
quantity_type>
|
||||||
constexpr explicit quantity_point(const QP& qp) : q_(quantity_point_like_traits<QP>::quantity_from_origin(qp))
|
constexpr explicit quantity_point(const QP& qp) :
|
||||||
|
quantity_from_origin_(quantity_point_like_traits<QP>::quantity_from_origin(qp))
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -145,66 +146,88 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
// data access
|
// data access
|
||||||
#ifdef __cpp_explicit_this_parameter
|
template<std::same_as<std::remove_const_t<decltype(PO)>> PO2>
|
||||||
template<typename Self>
|
[[nodiscard]] constexpr quantity_type& quantity_ref_from(PO2) & noexcept
|
||||||
[[nodiscard]] constexpr auto&& quantity_from_origin(this Self&& self) noexcept
|
|
||||||
{
|
{
|
||||||
return std::forward<Self>(self).q_;
|
return quantity_from_origin_;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<std::same_as<std::remove_const_t<decltype(PO)>> PO2>
|
||||||
|
[[nodiscard]] constexpr const quantity_type& quantity_ref_from(PO2) const& noexcept
|
||||||
|
{
|
||||||
|
return quantity_from_origin_;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<std::same_as<std::remove_const_t<decltype(PO)>> PO2>
|
||||||
|
constexpr const quantity_type&& quantity_ref_from(PO2) const&& noexcept = delete;
|
||||||
|
|
||||||
|
template<PointOrigin PO2>
|
||||||
|
requires requires { quantity_point{} - PO2{}; }
|
||||||
|
[[nodiscard]] constexpr Quantity auto quantity_from(PO2) const
|
||||||
|
{
|
||||||
|
return *this - PO2{};
|
||||||
}
|
}
|
||||||
#else
|
|
||||||
[[nodiscard]] constexpr quantity_type& quantity_from_origin() & noexcept { return q_; }
|
|
||||||
[[nodiscard]] constexpr const quantity_type& quantity_from_origin() const& noexcept { return q_; }
|
|
||||||
[[nodiscard]] constexpr quantity_type&& quantity_from_origin() && noexcept { return std::move(q_); }
|
|
||||||
[[nodiscard]] constexpr const quantity_type&& quantity_from_origin() const&& noexcept { return std::move(q_); }
|
|
||||||
#endif
|
|
||||||
|
|
||||||
template<Unit U>
|
template<Unit U>
|
||||||
requires detail::QuantityConvertibleTo<quantity_type, quantity<::mp_units::reference<quantity_spec, U{}>{}, Rep>>
|
requires detail::QuantityConvertibleTo<quantity_type, quantity<quantity_spec[U{}], Rep>>
|
||||||
[[nodiscard]] constexpr quantity_point<::mp_units::reference<quantity_spec, U{}>{}, PO, Rep> in(U) const
|
[[nodiscard]] constexpr quantity_point<quantity_spec[U{}], PO, Rep> in(U) const
|
||||||
{
|
{
|
||||||
return make_quantity_point<PO>(quantity_from_origin().in(U{}));
|
return make_quantity_point<PO>(quantity_ref_from(PO).in(U{}));
|
||||||
|
}
|
||||||
|
|
||||||
|
template<Unit U>
|
||||||
|
requires requires(quantity_type q) { value_cast<U{}>(q); }
|
||||||
|
[[nodiscard]] constexpr quantity_point<quantity_spec[U{}], PO, Rep> force_in(U) const
|
||||||
|
{
|
||||||
|
return make_quantity_point<PO>(quantity_ref_from(PO).force_in(U{}));
|
||||||
}
|
}
|
||||||
|
|
||||||
// member unary operators
|
// member unary operators
|
||||||
constexpr quantity_point& operator++()
|
template<typename QP>
|
||||||
requires requires { ++q_; }
|
friend constexpr decltype(auto) operator++(QP&& qp)
|
||||||
|
requires std::derived_from<std::remove_cvref_t<QP>, quantity_point> && requires { ++qp.quantity_from_origin_; }
|
||||||
{
|
{
|
||||||
++q_;
|
++qp.quantity_from_origin_;
|
||||||
return *this;
|
return std::forward<QP>(qp);
|
||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]] constexpr quantity_point operator++(int)
|
[[nodiscard]] constexpr quantity_point operator++(int)
|
||||||
requires requires { q_++; }
|
requires requires { quantity_from_origin_++; }
|
||||||
{
|
{
|
||||||
return quantity_point(q_++);
|
return quantity_point(quantity_from_origin_++);
|
||||||
}
|
}
|
||||||
|
|
||||||
constexpr quantity_point& operator--()
|
template<typename QP>
|
||||||
requires requires { --q_; }
|
friend constexpr decltype(auto) operator--(QP&& qp)
|
||||||
|
requires std::derived_from<std::remove_cvref_t<QP>, quantity_point> && requires { --qp.quantity_from_origin_; }
|
||||||
{
|
{
|
||||||
--q_;
|
--qp.quantity_from_origin_;
|
||||||
return *this;
|
return std::forward<QP>(qp);
|
||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]] constexpr quantity_point operator--(int)
|
[[nodiscard]] constexpr quantity_point operator--(int)
|
||||||
requires requires { q_--; }
|
requires requires { quantity_from_origin_--; }
|
||||||
{
|
{
|
||||||
return quantity_point(q_--);
|
return quantity_point(quantity_from_origin_--);
|
||||||
}
|
}
|
||||||
|
|
||||||
// compound assignment operators
|
// compound assignment operators
|
||||||
constexpr quantity_point& operator+=(const quantity_type& q)
|
template<typename QP>
|
||||||
requires requires { q_ += q; }
|
requires std::derived_from<std::remove_cvref_t<QP>, quantity_point> &&
|
||||||
|
requires(quantity_type q) { quantity_from_origin_ += q; }
|
||||||
|
friend constexpr decltype(auto) operator+=(QP&& qp, const quantity_type& q)
|
||||||
{
|
{
|
||||||
q_ += q;
|
qp.quantity_from_origin_ += q;
|
||||||
return *this;
|
return std::forward<QP>(qp);
|
||||||
}
|
}
|
||||||
|
|
||||||
constexpr quantity_point& operator-=(const quantity_type& q)
|
template<typename QP>
|
||||||
requires requires { q_ -= q; }
|
requires std::derived_from<std::remove_cvref_t<QP>, quantity_point> &&
|
||||||
|
requires(quantity_type q) { quantity_from_origin_ -= q; }
|
||||||
|
friend constexpr decltype(auto) operator-=(QP&& qp, const quantity_type& q)
|
||||||
{
|
{
|
||||||
q_ -= q;
|
qp.quantity_from_origin_ -= q;
|
||||||
return *this;
|
return std::forward<QP>(qp);
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@@ -219,7 +242,7 @@ private:
|
|||||||
template<Quantity Q>
|
template<Quantity Q>
|
||||||
requires std::constructible_from<quantity_type, Q> &&
|
requires std::constructible_from<quantity_type, Q> &&
|
||||||
ReferenceOf<std::remove_const_t<decltype(Q::reference)>, PO.quantity_spec>
|
ReferenceOf<std::remove_const_t<decltype(Q::reference)>, PO.quantity_spec>
|
||||||
constexpr explicit quantity_point(Q&& q) : q_(std::forward<Q>(q))
|
constexpr explicit quantity_point(Q&& q) : quantity_from_origin_(std::forward<Q>(q))
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -235,9 +258,9 @@ template<auto R1, auto PO1, typename Rep1, auto R2, typename Rep2>
|
|||||||
requires ReferenceOf<std::remove_const_t<decltype(R2)>, PO1.quantity_spec>
|
requires ReferenceOf<std::remove_const_t<decltype(R2)>, PO1.quantity_spec>
|
||||||
[[nodiscard]] constexpr QuantityPoint auto operator+(const quantity_point<R1, PO1, Rep1>& qp,
|
[[nodiscard]] constexpr QuantityPoint auto operator+(const quantity_point<R1, PO1, Rep1>& qp,
|
||||||
const quantity<R2, Rep2>& q)
|
const quantity<R2, Rep2>& q)
|
||||||
requires requires { qp.quantity_from_origin() + q; }
|
requires requires { qp.quantity_ref_from(PO1) + q; }
|
||||||
{
|
{
|
||||||
return make_quantity_point<PO1>(qp.quantity_from_origin() + q);
|
return make_quantity_point<PO1>(qp.quantity_ref_from(PO1) + q);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<auto R1, typename Rep1, auto R2, auto PO2, typename Rep2>
|
template<auto R1, typename Rep1, auto R2, auto PO2, typename Rep2>
|
||||||
@@ -245,7 +268,7 @@ template<auto R1, typename Rep1, auto R2, auto PO2, typename Rep2>
|
|||||||
requires ReferenceOf<std::remove_const_t<decltype(R1)>, PO2.quantity_spec>
|
requires ReferenceOf<std::remove_const_t<decltype(R1)>, PO2.quantity_spec>
|
||||||
[[nodiscard]] constexpr QuantityPoint auto operator+(const quantity<R1, Rep1>& q,
|
[[nodiscard]] constexpr QuantityPoint auto operator+(const quantity<R1, Rep1>& q,
|
||||||
const quantity_point<R2, PO2, Rep2>& qp)
|
const quantity_point<R2, PO2, Rep2>& qp)
|
||||||
requires requires { q + qp.quantity_from_origin(); }
|
requires requires { q + qp.quantity_ref_from(PO2); }
|
||||||
{
|
{
|
||||||
return qp + q;
|
return qp + q;
|
||||||
}
|
}
|
||||||
@@ -269,9 +292,9 @@ template<auto R1, auto PO1, typename Rep1, auto R2, typename Rep2>
|
|||||||
requires ReferenceOf<std::remove_const_t<decltype(R2)>, PO1.quantity_spec>
|
requires ReferenceOf<std::remove_const_t<decltype(R2)>, PO1.quantity_spec>
|
||||||
[[nodiscard]] constexpr QuantityPoint auto operator-(const quantity_point<R1, PO1, Rep1>& qp,
|
[[nodiscard]] constexpr QuantityPoint auto operator-(const quantity_point<R1, PO1, Rep1>& qp,
|
||||||
const quantity<R2, Rep2>& q)
|
const quantity<R2, Rep2>& q)
|
||||||
requires requires { qp.quantity_from_origin() - q; }
|
requires requires { qp.quantity_ref_from(PO1) - q; }
|
||||||
{
|
{
|
||||||
return make_quantity_point<PO1>(qp.quantity_from_origin() - q);
|
return make_quantity_point<PO1>(qp.quantity_ref_from(PO1) - q);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<PointOrigin PO, Quantity Q>
|
template<PointOrigin PO, Quantity Q>
|
||||||
@@ -285,13 +308,14 @@ template<PointOrigin PO, Quantity Q>
|
|||||||
template<QuantityPoint QP1, QuantityPointOf<QP1::absolute_point_origin> QP2>
|
template<QuantityPoint QP1, QuantityPointOf<QP1::absolute_point_origin> QP2>
|
||||||
[[nodiscard]] constexpr Quantity auto operator-(const QP1& lhs, const QP2& rhs)
|
[[nodiscard]] constexpr Quantity auto operator-(const QP1& lhs, const QP2& rhs)
|
||||||
// TODO consider constraining it for both branches
|
// TODO consider constraining it for both branches
|
||||||
requires requires { lhs.quantity_from_origin() - rhs.quantity_from_origin(); }
|
requires requires { lhs.quantity_ref_from(QP1::point_origin) - rhs.quantity_ref_from(QP2::point_origin); }
|
||||||
{
|
{
|
||||||
if constexpr (is_same_v<std::remove_const_t<decltype(QP1::point_origin)>,
|
if constexpr (is_same_v<std::remove_const_t<decltype(QP1::point_origin)>,
|
||||||
std::remove_const_t<decltype(QP2::point_origin)>>)
|
std::remove_const_t<decltype(QP2::point_origin)>>)
|
||||||
return lhs.quantity_from_origin() - rhs.quantity_from_origin();
|
return lhs.quantity_ref_from(QP1::point_origin) - rhs.quantity_ref_from(QP2::point_origin);
|
||||||
else
|
else
|
||||||
return lhs.quantity_from_origin() - rhs.quantity_from_origin() + (lhs.point_origin - rhs.point_origin);
|
return lhs.quantity_ref_from(QP1::point_origin) - rhs.quantity_ref_from(QP2::point_origin) +
|
||||||
|
(lhs.point_origin - rhs.point_origin);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<PointOrigin PO, QuantityPointOf<PO{}> QP>
|
template<PointOrigin PO, QuantityPointOf<PO{}> QP>
|
||||||
@@ -299,19 +323,21 @@ template<PointOrigin PO, QuantityPointOf<PO{}> QP>
|
|||||||
[[nodiscard]] constexpr Quantity auto operator-(const QP& qp, PO po)
|
[[nodiscard]] constexpr Quantity auto operator-(const QP& qp, PO po)
|
||||||
{
|
{
|
||||||
if constexpr (is_same_v<std::remove_const_t<decltype(QP::point_origin)>, std::remove_const_t<PO>>)
|
if constexpr (is_same_v<std::remove_const_t<decltype(QP::point_origin)>, std::remove_const_t<PO>>)
|
||||||
return qp.quantity_from_origin();
|
return qp.quantity_ref_from(QP::point_origin);
|
||||||
else if constexpr (detail::is_derived_from_specialization_of_absolute_point_origin<PO>) {
|
else if constexpr (detail::is_derived_from_specialization_of_absolute_point_origin<PO>) {
|
||||||
if constexpr (is_same_v<std::remove_const_t<decltype(QP::point_origin)>,
|
if constexpr (is_same_v<std::remove_const_t<decltype(QP::point_origin)>,
|
||||||
std::remove_const_t<decltype(QP::absolute_point_origin)>>)
|
std::remove_const_t<decltype(QP::absolute_point_origin)>>)
|
||||||
return qp.quantity_from_origin();
|
return qp.quantity_ref_from(QP::point_origin);
|
||||||
else
|
else
|
||||||
return qp.quantity_from_origin() + (qp.point_origin - qp.absolute_point_origin);
|
return qp.quantity_ref_from(QP::point_origin) + (qp.point_origin - qp.absolute_point_origin);
|
||||||
} else {
|
} else {
|
||||||
if constexpr (is_same_v<std::remove_const_t<decltype(QP::point_origin)>,
|
if constexpr (is_same_v<std::remove_const_t<decltype(QP::point_origin)>,
|
||||||
std::remove_const_t<decltype(po.quantity_point.point_origin)>>)
|
std::remove_const_t<decltype(po.quantity_point.point_origin)>>)
|
||||||
return qp.quantity_from_origin() - po.quantity_point.quantity_from_origin();
|
return qp.quantity_ref_from(QP::point_origin) -
|
||||||
|
po.quantity_point.quantity_ref_from(po.quantity_point.point_origin);
|
||||||
else
|
else
|
||||||
return qp.quantity_from_origin() - po.quantity_point.quantity_from_origin() +
|
return qp.quantity_ref_from(QP::point_origin) -
|
||||||
|
po.quantity_point.quantity_ref_from(po.quantity_point.point_origin) +
|
||||||
(qp.point_origin - po.quantity_point.point_origin);
|
(qp.point_origin - po.quantity_point.point_origin);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -344,7 +370,7 @@ template<QuantityPoint QP1, QuantityPointOf<QP1::absolute_point_origin> QP2>
|
|||||||
{
|
{
|
||||||
if constexpr (is_same_v<std::remove_const_t<decltype(QP1::point_origin)>,
|
if constexpr (is_same_v<std::remove_const_t<decltype(QP1::point_origin)>,
|
||||||
std::remove_const_t<decltype(QP2::point_origin)>>)
|
std::remove_const_t<decltype(QP2::point_origin)>>)
|
||||||
return lhs.quantity_from_origin() <=> rhs.quantity_from_origin();
|
return lhs.quantity_ref_from(QP1::point_origin) <=> rhs.quantity_ref_from(QP2::point_origin);
|
||||||
else
|
else
|
||||||
return lhs - lhs.absolute_point_origin <=> rhs - rhs.absolute_point_origin;
|
return lhs - lhs.absolute_point_origin <=> rhs - rhs.absolute_point_origin;
|
||||||
}
|
}
|
||||||
@@ -355,7 +381,7 @@ template<QuantityPoint QP1, QuantityPointOf<QP1::absolute_point_origin> QP2>
|
|||||||
{
|
{
|
||||||
if constexpr (is_same_v<std::remove_const_t<decltype(QP1::point_origin)>,
|
if constexpr (is_same_v<std::remove_const_t<decltype(QP1::point_origin)>,
|
||||||
std::remove_const_t<decltype(QP2::point_origin)>>)
|
std::remove_const_t<decltype(QP2::point_origin)>>)
|
||||||
return lhs.quantity_from_origin() == rhs.quantity_from_origin();
|
return lhs.quantity_ref_from(QP1::point_origin) == rhs.quantity_ref_from(QP2::point_origin);
|
||||||
else
|
else
|
||||||
return lhs - lhs.absolute_point_origin == rhs - rhs.absolute_point_origin;
|
return lhs - lhs.absolute_point_origin == rhs - rhs.absolute_point_origin;
|
||||||
}
|
}
|
||||||
|
@@ -111,7 +111,7 @@ struct quantity_spec_interface {
|
|||||||
requires Quantity<std::remove_cvref_t<Q>> &&
|
requires Quantity<std::remove_cvref_t<Q>> &&
|
||||||
(explicitly_convertible(std::remove_reference_t<Q>::quantity_spec, self))
|
(explicitly_convertible(std::remove_reference_t<Q>::quantity_spec, self))
|
||||||
{
|
{
|
||||||
return make_quantity<reference<self, std::remove_cvref_t<Q>::unit>{}>(std::forward<Q>(q).numerical_value());
|
return make_quantity<reference<self, std::remove_cvref_t<Q>::unit>{}>(std::forward<Q>(q).numerical_value_);
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
template<typename Self_ = Self, UnitOf<Self_{}> U>
|
template<typename Self_ = Self, UnitOf<Self_{}> U>
|
||||||
@@ -128,7 +128,7 @@ struct quantity_spec_interface {
|
|||||||
(explicitly_convertible(std::remove_reference_t<Q>::quantity_spec, Self_{}))
|
(explicitly_convertible(std::remove_reference_t<Q>::quantity_spec, Self_{}))
|
||||||
[[nodiscard]] constexpr Quantity auto operator()(Q&& q) const
|
[[nodiscard]] constexpr Quantity auto operator()(Q&& q) const
|
||||||
{
|
{
|
||||||
return make_quantity<reference<Self{}, std::remove_cvref_t<Q>::unit>{}>(std::forward<Q>(q).numerical_value());
|
return make_quantity<reference<Self{}, std::remove_cvref_t<Q>::unit>{}>(std::forward<Q>(q).numerical_value_);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
@@ -307,7 +307,7 @@ struct quantity_spec<Self, QS, Args...> : std::remove_const_t<decltype(QS)> {
|
|||||||
(explicitly_convertible(std::remove_reference_t<Q>::quantity_spec, Self_{}))
|
(explicitly_convertible(std::remove_reference_t<Q>::quantity_spec, Self_{}))
|
||||||
[[nodiscard]] constexpr Quantity auto operator()(Q&& q) const
|
[[nodiscard]] constexpr Quantity auto operator()(Q&& q) const
|
||||||
{
|
{
|
||||||
return make_quantity<reference<Self{}, std::remove_cvref_t<Q>::unit>{}>(std::forward<Q>(q).numerical_value());
|
return make_quantity<reference<Self{}, std::remove_cvref_t<Q>::unit>{}>(std::forward<Q>(q).numerical_value_);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
@@ -402,7 +402,7 @@ using type_list_of_unit_less = expr_less<T1, T2, unit_less>;
|
|||||||
* Multiplication by `1` returns the same unit, otherwise `scaled_unit` is being returned.
|
* Multiplication by `1` returns the same unit, otherwise `scaled_unit` is being returned.
|
||||||
*/
|
*/
|
||||||
template<Magnitude M, Unit U>
|
template<Magnitude M, Unit U>
|
||||||
[[nodiscard]] consteval Unit auto operator*(M mag, const U u)
|
[[nodiscard]] MP_UNITS_CONSTEVAL Unit auto operator*(M mag, const U u)
|
||||||
{
|
{
|
||||||
if constexpr (mag == mp_units::mag<1>)
|
if constexpr (mag == mp_units::mag<1>)
|
||||||
return u;
|
return u;
|
||||||
@@ -418,7 +418,7 @@ template<Magnitude M, Unit U>
|
|||||||
* to the derived unit and the magnitude remains outside forming another scaled unit as a result of the operation.
|
* to the derived unit and the magnitude remains outside forming another scaled unit as a result of the operation.
|
||||||
*/
|
*/
|
||||||
template<Unit Lhs, Unit Rhs>
|
template<Unit Lhs, Unit Rhs>
|
||||||
[[nodiscard]] consteval Unit auto operator*(Lhs lhs, Rhs rhs)
|
[[nodiscard]] MP_UNITS_CONSTEVAL Unit auto operator*(Lhs lhs, Rhs rhs)
|
||||||
{
|
{
|
||||||
if constexpr (detail::is_specialization_of_scaled_unit<Lhs> && detail::is_specialization_of_scaled_unit<Rhs>)
|
if constexpr (detail::is_specialization_of_scaled_unit<Lhs> && detail::is_specialization_of_scaled_unit<Rhs>)
|
||||||
return (Lhs::mag * Rhs::mag) * (Lhs::reference_unit * Rhs::reference_unit);
|
return (Lhs::mag * Rhs::mag) * (Lhs::reference_unit * Rhs::reference_unit);
|
||||||
@@ -436,7 +436,7 @@ template<Unit Lhs, Unit Rhs>
|
|||||||
* to the derived unit and the magnitude remains outside forming another scaled unit as a result of the operation.
|
* to the derived unit and the magnitude remains outside forming another scaled unit as a result of the operation.
|
||||||
*/
|
*/
|
||||||
template<Unit Lhs, Unit Rhs>
|
template<Unit Lhs, Unit Rhs>
|
||||||
[[nodiscard]] consteval Unit auto operator/(Lhs lhs, Rhs rhs)
|
[[nodiscard]] MP_UNITS_CONSTEVAL Unit auto operator/(Lhs lhs, Rhs rhs)
|
||||||
{
|
{
|
||||||
if constexpr (detail::is_specialization_of_scaled_unit<Lhs> && detail::is_specialization_of_scaled_unit<Rhs>)
|
if constexpr (detail::is_specialization_of_scaled_unit<Lhs> && detail::is_specialization_of_scaled_unit<Rhs>)
|
||||||
return (Lhs::mag / Rhs::mag) * (Lhs::reference_unit / Rhs::reference_unit);
|
return (Lhs::mag / Rhs::mag) * (Lhs::reference_unit / Rhs::reference_unit);
|
||||||
|
@@ -92,7 +92,7 @@ template<QuantityOf<isq::time> Q>
|
|||||||
{
|
{
|
||||||
constexpr auto canonical = detail::get_canonical_unit(Q::unit);
|
constexpr auto canonical = detail::get_canonical_unit(Q::unit);
|
||||||
constexpr ratio r = as_ratio(canonical.mag);
|
constexpr ratio r = as_ratio(canonical.mag);
|
||||||
return std::chrono::duration<typename Q::rep, std::ratio<r.num, r.den>>{q.numerical_value()};
|
return std::chrono::duration<typename Q::rep, std::ratio<r.num, r.den>>{q.numerical_value_ref_in(Q::unit)};
|
||||||
}
|
}
|
||||||
|
|
||||||
template<QuantityPointOf<isq::time> QP>
|
template<QuantityPointOf<isq::time> QP>
|
||||||
|
@@ -54,7 +54,8 @@ template<std::intmax_t Num, std::intmax_t Den = 1, auto R, typename Rep>
|
|||||||
requires detail::non_zero<Den> &&
|
requires detail::non_zero<Den> &&
|
||||||
requires { quantity_values<Rep>::one(); }
|
requires { quantity_values<Rep>::one(); }
|
||||||
[[nodiscard]] constexpr quantity<pow<Num, Den>(R), Rep> pow(const quantity<R, Rep>& q) noexcept
|
[[nodiscard]] constexpr quantity<pow<Num, Den>(R), Rep> pow(const quantity<R, Rep>& q) noexcept
|
||||||
requires requires { pow(q.numerical_value(), 1.0); } || requires { std::pow(q.numerical_value(), 1.0); }
|
requires requires { pow(q.numerical_value_ref_in(q.unit), 1.0); } ||
|
||||||
|
requires { std::pow(q.numerical_value_ref_in(q.unit), 1.0); }
|
||||||
{
|
{
|
||||||
if constexpr (Num == 0) {
|
if constexpr (Num == 0) {
|
||||||
return quantity<pow<Num, Den>(R), Rep>::one();
|
return quantity<pow<Num, Den>(R), Rep>::one();
|
||||||
@@ -63,7 +64,7 @@ template<std::intmax_t Num, std::intmax_t Den = 1, auto R, typename Rep>
|
|||||||
} else {
|
} else {
|
||||||
using std::pow;
|
using std::pow;
|
||||||
return make_quantity<pow<Num, Den>(R)>(
|
return make_quantity<pow<Num, Den>(R)>(
|
||||||
static_cast<Rep>(pow(q.numerical_value(), static_cast<double>(Num) / static_cast<double>(Den))));
|
static_cast<Rep>(pow(q.numerical_value_ref_in(q.unit), static_cast<double>(Num) / static_cast<double>(Den))));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -77,10 +78,11 @@ template<std::intmax_t Num, std::intmax_t Den = 1, auto R, typename Rep>
|
|||||||
*/
|
*/
|
||||||
template<auto R, typename Rep>
|
template<auto R, typename Rep>
|
||||||
[[nodiscard]] constexpr quantity<sqrt(R), Rep> sqrt(const quantity<R, Rep>& q) noexcept
|
[[nodiscard]] constexpr quantity<sqrt(R), Rep> sqrt(const quantity<R, Rep>& q) noexcept
|
||||||
requires requires { sqrt(q.numerical_value()); } || requires { std::sqrt(q.numerical_value()); }
|
requires requires { sqrt(q.numerical_value_ref_in(q.unit)); } ||
|
||||||
|
requires { std::sqrt(q.numerical_value_ref_in(q.unit)); }
|
||||||
{
|
{
|
||||||
using std::sqrt;
|
using std::sqrt;
|
||||||
return make_quantity<sqrt(R)>(static_cast<Rep>(sqrt(q.numerical_value())));
|
return make_quantity<sqrt(R)>(static_cast<Rep>(sqrt(q.numerical_value_ref_in(q.unit))));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -93,10 +95,11 @@ template<auto R, typename Rep>
|
|||||||
*/
|
*/
|
||||||
template<auto R, typename Rep>
|
template<auto R, typename Rep>
|
||||||
[[nodiscard]] constexpr quantity<cbrt(R), Rep> cbrt(const quantity<R, Rep>& q) noexcept
|
[[nodiscard]] constexpr quantity<cbrt(R), Rep> cbrt(const quantity<R, Rep>& q) noexcept
|
||||||
requires requires { cbrt(q.numerical_value()); } || requires { std::cbrt(q.numerical_value()); }
|
requires requires { cbrt(q.numerical_value_ref_in(q.unit)); } ||
|
||||||
|
requires { std::cbrt(q.numerical_value_ref_in(q.unit)); }
|
||||||
{
|
{
|
||||||
using std::cbrt;
|
using std::cbrt;
|
||||||
return make_quantity<cbrt(R)>(static_cast<Rep>(cbrt(q.numerical_value())));
|
return make_quantity<cbrt(R)>(static_cast<Rep>(cbrt(q.numerical_value_ref_in(q.unit))));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -109,11 +112,12 @@ template<auto R, typename Rep>
|
|||||||
*/
|
*/
|
||||||
template<ReferenceOf<dimensionless> auto R, typename Rep>
|
template<ReferenceOf<dimensionless> auto R, typename Rep>
|
||||||
[[nodiscard]] constexpr quantity<R, Rep> exp(const quantity<R, Rep>& q)
|
[[nodiscard]] constexpr quantity<R, Rep> exp(const quantity<R, Rep>& q)
|
||||||
requires requires { exp(q.numerical_value()); } || requires { std::exp(q.numerical_value()); }
|
requires requires { exp(q.numerical_value_ref_in(q.unit)); } ||
|
||||||
|
requires { std::exp(q.numerical_value_ref_in(q.unit)); }
|
||||||
{
|
{
|
||||||
using std::exp;
|
using std::exp;
|
||||||
return value_cast<get_unit(R)>(
|
return value_cast<get_unit(R)>(
|
||||||
make_quantity<detail::clone_reference_with<one>(R)>(static_cast<Rep>(exp(value_cast<one>(q).numerical_value()))));
|
make_quantity<detail::clone_reference_with<one>(R)>(static_cast<Rep>(exp(q.force_numerical_value_in(q.unit)))));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -124,10 +128,11 @@ template<ReferenceOf<dimensionless> auto R, typename Rep>
|
|||||||
*/
|
*/
|
||||||
template<auto R, typename Rep>
|
template<auto R, typename Rep>
|
||||||
[[nodiscard]] constexpr quantity<R, Rep> abs(const quantity<R, Rep>& q) noexcept
|
[[nodiscard]] constexpr quantity<R, Rep> abs(const quantity<R, Rep>& q) noexcept
|
||||||
requires requires { abs(q.numerical_value()); } || requires { std::abs(q.numerical_value()); }
|
requires requires { abs(q.numerical_value_ref_in(q.unit)); } ||
|
||||||
|
requires { std::abs(q.numerical_value_ref_in(q.unit)); }
|
||||||
{
|
{
|
||||||
using std::abs;
|
using std::abs;
|
||||||
return make_quantity<R>(static_cast<Rep>(abs(q.numerical_value())));
|
return make_quantity<R>(static_cast<Rep>(abs(q.numerical_value_ref_in(q.unit))));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -153,10 +158,10 @@ template<Representation Rep, Reference R>
|
|||||||
*/
|
*/
|
||||||
template<Unit auto To, auto R, typename Rep>
|
template<Unit auto To, auto R, typename Rep>
|
||||||
[[nodiscard]] constexpr quantity<detail::clone_reference_with<To>(R), Rep> floor(const quantity<R, Rep>& q) noexcept
|
[[nodiscard]] constexpr quantity<detail::clone_reference_with<To>(R), Rep> floor(const quantity<R, Rep>& q) noexcept
|
||||||
requires((!treat_as_floating_point<Rep>) || requires { floor(q.numerical_value()); } ||
|
requires((!treat_as_floating_point<Rep>) || requires { floor(q.numerical_value_ref_in(q.unit)); } ||
|
||||||
requires { std::floor(q.numerical_value()); }) &&
|
requires { std::floor(q.numerical_value_ref_in(q.unit)); }) &&
|
||||||
(To == get_unit(R) || requires {
|
(To == get_unit(R) || requires {
|
||||||
::mp_units::value_cast<To>(q);
|
q.force_in(To);
|
||||||
quantity_values<Rep>::one();
|
quantity_values<Rep>::one();
|
||||||
})
|
})
|
||||||
{
|
{
|
||||||
@@ -169,16 +174,17 @@ template<Unit auto To, auto R, typename Rep>
|
|||||||
if constexpr (treat_as_floating_point<Rep>) {
|
if constexpr (treat_as_floating_point<Rep>) {
|
||||||
using std::floor;
|
using std::floor;
|
||||||
if constexpr (To == get_unit(R)) {
|
if constexpr (To == get_unit(R)) {
|
||||||
return make_quantity<detail::clone_reference_with<To>(R)>(static_cast<Rep>(floor(q.numerical_value())));
|
return make_quantity<detail::clone_reference_with<To>(R)>(
|
||||||
|
static_cast<Rep>(floor(q.numerical_value_ref_in(q.unit))));
|
||||||
} else {
|
} else {
|
||||||
return handle_signed_results(make_quantity<detail::clone_reference_with<To>(R)>(
|
return handle_signed_results(
|
||||||
static_cast<Rep>(floor(value_cast<To>(q).numerical_value()))));
|
make_quantity<detail::clone_reference_with<To>(R)>(static_cast<Rep>(floor(q.force_numerical_value_in(To)))));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if constexpr (To == get_unit(R)) {
|
if constexpr (To == get_unit(R)) {
|
||||||
return value_cast<To>(q);
|
return q.force_in(To);
|
||||||
} else {
|
} else {
|
||||||
return handle_signed_results(value_cast<To>(q));
|
return handle_signed_results(q.force_in(To));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -191,10 +197,10 @@ template<Unit auto To, auto R, typename Rep>
|
|||||||
*/
|
*/
|
||||||
template<Unit auto To, auto R, typename Rep>
|
template<Unit auto To, auto R, typename Rep>
|
||||||
[[nodiscard]] constexpr quantity<detail::clone_reference_with<To>(R), Rep> ceil(const quantity<R, Rep>& q) noexcept
|
[[nodiscard]] constexpr quantity<detail::clone_reference_with<To>(R), Rep> ceil(const quantity<R, Rep>& q) noexcept
|
||||||
requires((!treat_as_floating_point<Rep>) || requires { ceil(q.numerical_value()); } ||
|
requires((!treat_as_floating_point<Rep>) || requires { ceil(q.numerical_value_ref_in(q.unit)); } ||
|
||||||
requires { std::ceil(q.numerical_value()); }) &&
|
requires { std::ceil(q.numerical_value_ref_in(q.unit)); }) &&
|
||||||
(To == get_unit(R) || requires {
|
(To == get_unit(R) || requires {
|
||||||
::mp_units::value_cast<To>(q);
|
q.force_in(To);
|
||||||
quantity_values<Rep>::one();
|
quantity_values<Rep>::one();
|
||||||
})
|
})
|
||||||
{
|
{
|
||||||
@@ -207,16 +213,17 @@ template<Unit auto To, auto R, typename Rep>
|
|||||||
if constexpr (treat_as_floating_point<Rep>) {
|
if constexpr (treat_as_floating_point<Rep>) {
|
||||||
using std::ceil;
|
using std::ceil;
|
||||||
if constexpr (To == get_unit(R)) {
|
if constexpr (To == get_unit(R)) {
|
||||||
return make_quantity<detail::clone_reference_with<To>(R)>(static_cast<Rep>(ceil(q.numerical_value())));
|
return make_quantity<detail::clone_reference_with<To>(R)>(
|
||||||
|
static_cast<Rep>(ceil(q.numerical_value_ref_in(q.unit))));
|
||||||
} else {
|
} else {
|
||||||
return handle_signed_results(make_quantity<detail::clone_reference_with<To>(R)>(
|
return handle_signed_results(
|
||||||
static_cast<Rep>(ceil(value_cast<To>(q).numerical_value()))));
|
make_quantity<detail::clone_reference_with<To>(R)>(static_cast<Rep>(ceil(q.force_numerical_value_in(To)))));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if constexpr (To == get_unit(R)) {
|
if constexpr (To == get_unit(R)) {
|
||||||
return value_cast<To>(q);
|
return q.force_in(To);
|
||||||
} else {
|
} else {
|
||||||
return handle_signed_results(value_cast<To>(q));
|
return handle_signed_results(q.force_in(To));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -231,8 +238,8 @@ template<Unit auto To, auto R, typename Rep>
|
|||||||
*/
|
*/
|
||||||
template<Unit auto To, auto R, typename Rep>
|
template<Unit auto To, auto R, typename Rep>
|
||||||
[[nodiscard]] constexpr quantity<detail::clone_reference_with<To>(R), Rep> round(const quantity<R, Rep>& q) noexcept
|
[[nodiscard]] constexpr quantity<detail::clone_reference_with<To>(R), Rep> round(const quantity<R, Rep>& q) noexcept
|
||||||
requires((!treat_as_floating_point<Rep>) || requires { round(q.numerical_value()); } ||
|
requires((!treat_as_floating_point<Rep>) || requires { round(q.numerical_value_ref_in(q.unit)); } ||
|
||||||
requires { std::round(q.numerical_value()); }) &&
|
requires { std::round(q.numerical_value_ref_in(q.unit)); }) &&
|
||||||
(To == get_unit(R) || requires {
|
(To == get_unit(R) || requires {
|
||||||
::mp_units::floor<To>(q);
|
::mp_units::floor<To>(q);
|
||||||
quantity_values<Rep>::one();
|
quantity_values<Rep>::one();
|
||||||
@@ -241,9 +248,10 @@ template<Unit auto To, auto R, typename Rep>
|
|||||||
if constexpr (To == get_unit(R)) {
|
if constexpr (To == get_unit(R)) {
|
||||||
if constexpr (treat_as_floating_point<Rep>) {
|
if constexpr (treat_as_floating_point<Rep>) {
|
||||||
using std::round;
|
using std::round;
|
||||||
return make_quantity<detail::clone_reference_with<To>(R)>(static_cast<Rep>(round(q.numerical_value())));
|
return make_quantity<detail::clone_reference_with<To>(R)>(
|
||||||
|
static_cast<Rep>(round(q.numerical_value_ref_in(q.unit))));
|
||||||
} else {
|
} else {
|
||||||
return value_cast<To>(q);
|
return q.force_in(To);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
const auto res_low = mp_units::floor<To>(q);
|
const auto res_low = mp_units::floor<To>(q);
|
||||||
@@ -251,7 +259,7 @@ template<Unit auto To, auto R, typename Rep>
|
|||||||
const auto diff0 = q - res_low;
|
const auto diff0 = q - res_low;
|
||||||
const auto diff1 = res_high - q;
|
const auto diff1 = res_high - q;
|
||||||
if (diff0 == diff1) {
|
if (diff0 == diff1) {
|
||||||
if (static_cast<int>(res_low.numerical_value()) & 1) {
|
if (static_cast<int>(res_low.numerical_value_ref_in(To)) & 1) {
|
||||||
return res_high;
|
return res_high;
|
||||||
}
|
}
|
||||||
return res_low;
|
return res_low;
|
||||||
@@ -272,8 +280,8 @@ template<auto R1, typename Rep1, auto R2, typename Rep2>
|
|||||||
const quantity<R1, Rep1>& x, const quantity<R2, Rep2>& y) noexcept
|
const quantity<R1, Rep1>& x, const quantity<R2, Rep2>& y) noexcept
|
||||||
requires requires { common_reference(R1, R2); } &&
|
requires requires { common_reference(R1, R2); } &&
|
||||||
(
|
(
|
||||||
requires { hypot(x.numerical_value(), y.numerical_value()); } ||
|
requires { hypot(x.numerical_value_ref_in(x.unit), y.numerical_value_ref_in(y.unit)); } ||
|
||||||
requires { std::hypot(x.numerical_value(), y.numerical_value()); })
|
requires { std::hypot(x.numerical_value_ref_in(x.unit), y.numerical_value_ref_in(y.unit)); })
|
||||||
{
|
{
|
||||||
constexpr auto ref = common_reference(R1, R2);
|
constexpr auto ref = common_reference(R1, R2);
|
||||||
constexpr auto unit = get_unit(ref);
|
constexpr auto unit = get_unit(ref);
|
||||||
@@ -290,8 +298,14 @@ template<auto R1, typename Rep1, auto R2, typename Rep2, auto R3, typename Rep3>
|
|||||||
const quantity<R1, Rep1>& x, const quantity<R2, Rep2>& y, const quantity<R3, Rep3>& z) noexcept
|
const quantity<R1, Rep1>& x, const quantity<R2, Rep2>& y, const quantity<R3, Rep3>& z) noexcept
|
||||||
requires requires { common_reference(R1, R2, R3); } &&
|
requires requires { common_reference(R1, R2, R3); } &&
|
||||||
(
|
(
|
||||||
requires { hypot(x.numerical_value(), y.numerical_value(), z.numerical_value()); } ||
|
requires {
|
||||||
requires { std::hypot(x.numerical_value(), y.numerical_value(), z.numerical_value()); })
|
hypot(x.numerical_value_ref_in(x.unit), y.numerical_value_ref_in(y.unit),
|
||||||
|
z.numerical_value_ref_in(z.unit));
|
||||||
|
} ||
|
||||||
|
requires {
|
||||||
|
std::hypot(x.numerical_value_ref_in(x.unit), y.numerical_value_ref_in(y.unit),
|
||||||
|
z.numerical_value_ref_in(z.unit));
|
||||||
|
})
|
||||||
{
|
{
|
||||||
constexpr auto ref = common_reference(R1, R2);
|
constexpr auto ref = common_reference(R1, R2);
|
||||||
constexpr auto unit = get_unit(ref);
|
constexpr auto unit = get_unit(ref);
|
||||||
@@ -303,12 +317,13 @@ namespace isq {
|
|||||||
|
|
||||||
template<ReferenceOf<angular_measure> auto R, typename Rep>
|
template<ReferenceOf<angular_measure> auto R, typename Rep>
|
||||||
[[nodiscard]] inline QuantityOf<dimensionless> auto sin(const quantity<R, Rep>& q) noexcept
|
[[nodiscard]] inline QuantityOf<dimensionless> auto sin(const quantity<R, Rep>& q) noexcept
|
||||||
requires requires { sin(q.numerical_value()); } || requires { std::sin(q.numerical_value()); }
|
requires requires { sin(q.numerical_value_ref_in(q.unit)); } ||
|
||||||
|
requires { std::sin(q.numerical_value_ref_in(q.unit)); }
|
||||||
{
|
{
|
||||||
using std::sin;
|
using std::sin;
|
||||||
if constexpr (!treat_as_floating_point<Rep>) {
|
if constexpr (!treat_as_floating_point<Rep>) {
|
||||||
// check what is the return type when called with the integral value
|
// check what is the return type when called with the integral value
|
||||||
using rep = decltype(sin(value_cast<si::radian>(q).numerical_value()));
|
using rep = decltype(sin(q.force_numerical_value_in(si::radian)));
|
||||||
// use this type ahead of calling the function to prevent narrowing if a unit conversion is needed
|
// use this type ahead of calling the function to prevent narrowing if a unit conversion is needed
|
||||||
return make_quantity<one>(sin(value_cast<rep>(q).numerical_value_in(si::radian)));
|
return make_quantity<one>(sin(value_cast<rep>(q).numerical_value_in(si::radian)));
|
||||||
} else
|
} else
|
||||||
@@ -317,12 +332,13 @@ template<ReferenceOf<angular_measure> auto R, typename Rep>
|
|||||||
|
|
||||||
template<ReferenceOf<angular_measure> auto R, typename Rep>
|
template<ReferenceOf<angular_measure> auto R, typename Rep>
|
||||||
[[nodiscard]] inline QuantityOf<dimensionless> auto cos(const quantity<R, Rep>& q) noexcept
|
[[nodiscard]] inline QuantityOf<dimensionless> auto cos(const quantity<R, Rep>& q) noexcept
|
||||||
requires requires { cos(q.numerical_value()); } || requires { std::cos(q.numerical_value()); }
|
requires requires { cos(q.numerical_value_ref_in(q.unit)); } ||
|
||||||
|
requires { std::cos(q.numerical_value_ref_in(q.unit)); }
|
||||||
{
|
{
|
||||||
using std::cos;
|
using std::cos;
|
||||||
if constexpr (!treat_as_floating_point<Rep>) {
|
if constexpr (!treat_as_floating_point<Rep>) {
|
||||||
// check what is the return type when called with the integral value
|
// check what is the return type when called with the integral value
|
||||||
using rep = decltype(cos(value_cast<si::radian>(q).numerical_value()));
|
using rep = decltype(cos(q.force_numerical_value_in(si::radian)));
|
||||||
// use this type ahead of calling the function to prevent narrowing if a unit conversion is needed
|
// use this type ahead of calling the function to prevent narrowing if a unit conversion is needed
|
||||||
return make_quantity<one>(cos(value_cast<rep>(q).numerical_value_in(si::radian)));
|
return make_quantity<one>(cos(value_cast<rep>(q).numerical_value_in(si::radian)));
|
||||||
} else
|
} else
|
||||||
@@ -331,12 +347,13 @@ template<ReferenceOf<angular_measure> auto R, typename Rep>
|
|||||||
|
|
||||||
template<ReferenceOf<angular_measure> auto R, typename Rep>
|
template<ReferenceOf<angular_measure> auto R, typename Rep>
|
||||||
[[nodiscard]] inline QuantityOf<dimensionless> auto tan(const quantity<R, Rep>& q) noexcept
|
[[nodiscard]] inline QuantityOf<dimensionless> auto tan(const quantity<R, Rep>& q) noexcept
|
||||||
requires requires { tan(q.numerical_value()); } || requires { std::tan(q.numerical_value()); }
|
requires requires { tan(q.numerical_value_ref_in(q.unit)); } ||
|
||||||
|
requires { std::tan(q.numerical_value_ref_in(q.unit)); }
|
||||||
{
|
{
|
||||||
using std::tan;
|
using std::tan;
|
||||||
if constexpr (!treat_as_floating_point<Rep>) {
|
if constexpr (!treat_as_floating_point<Rep>) {
|
||||||
// check what is the return type when called with the integral value
|
// check what is the return type when called with the integral value
|
||||||
using rep = decltype(tan(value_cast<si::radian>(q).numerical_value()));
|
using rep = decltype(tan(q.force_numerical_value_in(si::radian)));
|
||||||
// use this type ahead of calling the function to prevent narrowing if a unit conversion is needed
|
// use this type ahead of calling the function to prevent narrowing if a unit conversion is needed
|
||||||
return make_quantity<one>(tan(value_cast<rep>(q).numerical_value_in(si::radian)));
|
return make_quantity<one>(tan(value_cast<rep>(q).numerical_value_in(si::radian)));
|
||||||
} else
|
} else
|
||||||
@@ -345,12 +362,13 @@ template<ReferenceOf<angular_measure> auto R, typename Rep>
|
|||||||
|
|
||||||
template<ReferenceOf<dimensionless> auto R, typename Rep>
|
template<ReferenceOf<dimensionless> auto R, typename Rep>
|
||||||
[[nodiscard]] inline QuantityOf<isq::angular_measure> auto asin(const quantity<R, Rep>& q) noexcept
|
[[nodiscard]] inline QuantityOf<isq::angular_measure> auto asin(const quantity<R, Rep>& q) noexcept
|
||||||
requires requires { asin(q.numerical_value()); } || requires { std::asin(q.numerical_value()); }
|
requires requires { asin(q.numerical_value_ref_in(q.unit)); } ||
|
||||||
|
requires { std::asin(q.numerical_value_ref_in(q.unit)); }
|
||||||
{
|
{
|
||||||
using std::asin;
|
using std::asin;
|
||||||
if constexpr (!treat_as_floating_point<Rep>) {
|
if constexpr (!treat_as_floating_point<Rep>) {
|
||||||
// check what is the return type when called with the integral value
|
// check what is the return type when called with the integral value
|
||||||
using rep = decltype(asin(value_cast<one>(q).numerical_value()));
|
using rep = decltype(asin(q.force_numerical_value_in(one)));
|
||||||
// use this type ahead of calling the function to prevent narrowing if a unit conversion is needed
|
// use this type ahead of calling the function to prevent narrowing if a unit conversion is needed
|
||||||
return make_quantity<si::radian>(asin(value_cast<rep>(q).numerical_value_in(one)));
|
return make_quantity<si::radian>(asin(value_cast<rep>(q).numerical_value_in(one)));
|
||||||
} else
|
} else
|
||||||
@@ -359,12 +377,13 @@ template<ReferenceOf<dimensionless> auto R, typename Rep>
|
|||||||
|
|
||||||
template<ReferenceOf<dimensionless> auto R, typename Rep>
|
template<ReferenceOf<dimensionless> auto R, typename Rep>
|
||||||
[[nodiscard]] inline QuantityOf<isq::angular_measure> auto acos(const quantity<R, Rep>& q) noexcept
|
[[nodiscard]] inline QuantityOf<isq::angular_measure> auto acos(const quantity<R, Rep>& q) noexcept
|
||||||
requires requires { acos(q.numerical_value()); } || requires { std::acos(q.numerical_value()); }
|
requires requires { acos(q.numerical_value_ref_in(q.unit)); } ||
|
||||||
|
requires { std::acos(q.numerical_value_ref_in(q.unit)); }
|
||||||
{
|
{
|
||||||
using std::acos;
|
using std::acos;
|
||||||
if constexpr (!treat_as_floating_point<Rep>) {
|
if constexpr (!treat_as_floating_point<Rep>) {
|
||||||
// check what is the return type when called with the integral value
|
// check what is the return type when called with the integral value
|
||||||
using rep = decltype(acos(value_cast<one>(q).numerical_value()));
|
using rep = decltype(acos(q.force_numerical_value_in(one)));
|
||||||
// use this type ahead of calling the function to prevent narrowing if a unit conversion is needed
|
// use this type ahead of calling the function to prevent narrowing if a unit conversion is needed
|
||||||
return make_quantity<si::radian>(acos(value_cast<rep>(q).numerical_value_in(one)));
|
return make_quantity<si::radian>(acos(value_cast<rep>(q).numerical_value_in(one)));
|
||||||
} else
|
} else
|
||||||
@@ -373,12 +392,13 @@ template<ReferenceOf<dimensionless> auto R, typename Rep>
|
|||||||
|
|
||||||
template<ReferenceOf<dimensionless> auto R, typename Rep>
|
template<ReferenceOf<dimensionless> auto R, typename Rep>
|
||||||
[[nodiscard]] inline QuantityOf<isq::angular_measure> auto atan(const quantity<R, Rep>& q) noexcept
|
[[nodiscard]] inline QuantityOf<isq::angular_measure> auto atan(const quantity<R, Rep>& q) noexcept
|
||||||
requires requires { atan(q.numerical_value()); } || requires { std::atan(q.numerical_value()); }
|
requires requires { atan(q.numerical_value_ref_in(q.unit)); } ||
|
||||||
|
requires { std::atan(q.numerical_value_ref_in(q.unit)); }
|
||||||
{
|
{
|
||||||
using std::atan;
|
using std::atan;
|
||||||
if constexpr (!treat_as_floating_point<Rep>) {
|
if constexpr (!treat_as_floating_point<Rep>) {
|
||||||
// check what is the return type when called with the integral value
|
// check what is the return type when called with the integral value
|
||||||
using rep = decltype(atan(value_cast<one>(q).numerical_value()));
|
using rep = decltype(atan(q.force_numerical_value_in(one)));
|
||||||
// use this type ahead of calling the function to prevent narrowing if a unit conversion is needed
|
// use this type ahead of calling the function to prevent narrowing if a unit conversion is needed
|
||||||
return make_quantity<si::radian>(atan(value_cast<rep>(q).numerical_value_in(one)));
|
return make_quantity<si::radian>(atan(value_cast<rep>(q).numerical_value_in(one)));
|
||||||
} else
|
} else
|
||||||
@@ -391,12 +411,13 @@ namespace angular {
|
|||||||
|
|
||||||
template<ReferenceOf<angle> auto R, typename Rep>
|
template<ReferenceOf<angle> auto R, typename Rep>
|
||||||
[[nodiscard]] inline QuantityOf<dimensionless> auto sin(const quantity<R, Rep>& q) noexcept
|
[[nodiscard]] inline QuantityOf<dimensionless> auto sin(const quantity<R, Rep>& q) noexcept
|
||||||
requires requires { sin(q.numerical_value()); } || requires { std::sin(q.numerical_value()); }
|
requires requires { sin(q.numerical_value_ref_in(q.unit)); } ||
|
||||||
|
requires { std::sin(q.numerical_value_ref_in(q.unit)); }
|
||||||
{
|
{
|
||||||
using std::sin;
|
using std::sin;
|
||||||
if constexpr (!treat_as_floating_point<Rep>) {
|
if constexpr (!treat_as_floating_point<Rep>) {
|
||||||
// check what is the return type when called with the integral value
|
// check what is the return type when called with the integral value
|
||||||
using rep = decltype(sin(value_cast<radian>(q).numerical_value()));
|
using rep = decltype(sin(q.force_numerical_value_in(radian)));
|
||||||
// use this type ahead of calling the function to prevent narrowing if a unit conversion is needed
|
// use this type ahead of calling the function to prevent narrowing if a unit conversion is needed
|
||||||
return make_quantity<one>(sin(value_cast<rep>(q).numerical_value_in(radian)));
|
return make_quantity<one>(sin(value_cast<rep>(q).numerical_value_in(radian)));
|
||||||
} else
|
} else
|
||||||
@@ -405,12 +426,13 @@ template<ReferenceOf<angle> auto R, typename Rep>
|
|||||||
|
|
||||||
template<ReferenceOf<angle> auto R, typename Rep>
|
template<ReferenceOf<angle> auto R, typename Rep>
|
||||||
[[nodiscard]] inline QuantityOf<dimensionless> auto cos(const quantity<R, Rep>& q) noexcept
|
[[nodiscard]] inline QuantityOf<dimensionless> auto cos(const quantity<R, Rep>& q) noexcept
|
||||||
requires requires { cos(q.numerical_value()); } || requires { std::cos(q.numerical_value()); }
|
requires requires { cos(q.numerical_value_ref_in(q.unit)); } ||
|
||||||
|
requires { std::cos(q.numerical_value_ref_in(q.unit)); }
|
||||||
{
|
{
|
||||||
using std::cos;
|
using std::cos;
|
||||||
if constexpr (!treat_as_floating_point<Rep>) {
|
if constexpr (!treat_as_floating_point<Rep>) {
|
||||||
// check what is the return type when called with the integral value
|
// check what is the return type when called with the integral value
|
||||||
using rep = decltype(cos(value_cast<radian>(q).numerical_value()));
|
using rep = decltype(cos(q.force_numerical_value_in(radian)));
|
||||||
// use this type ahead of calling the function to prevent narrowing if a unit conversion is needed
|
// use this type ahead of calling the function to prevent narrowing if a unit conversion is needed
|
||||||
return make_quantity<one>(cos(value_cast<rep>(q).numerical_value_in(radian)));
|
return make_quantity<one>(cos(value_cast<rep>(q).numerical_value_in(radian)));
|
||||||
} else
|
} else
|
||||||
@@ -419,12 +441,13 @@ template<ReferenceOf<angle> auto R, typename Rep>
|
|||||||
|
|
||||||
template<ReferenceOf<angle> auto R, typename Rep>
|
template<ReferenceOf<angle> auto R, typename Rep>
|
||||||
[[nodiscard]] inline QuantityOf<dimensionless> auto tan(const quantity<R, Rep>& q) noexcept
|
[[nodiscard]] inline QuantityOf<dimensionless> auto tan(const quantity<R, Rep>& q) noexcept
|
||||||
requires requires { tan(q.numerical_value()); } || requires { std::tan(q.numerical_value()); }
|
requires requires { tan(q.numerical_value_ref_in(q.unit)); } ||
|
||||||
|
requires { std::tan(q.numerical_value_ref_in(q.unit)); }
|
||||||
{
|
{
|
||||||
using std::tan;
|
using std::tan;
|
||||||
if constexpr (!treat_as_floating_point<Rep>) {
|
if constexpr (!treat_as_floating_point<Rep>) {
|
||||||
// check what is the return type when called with the integral value
|
// check what is the return type when called with the integral value
|
||||||
using rep = decltype(tan(value_cast<radian>(q).numerical_value()));
|
using rep = decltype(tan(q.force_numerical_value_in(radian)));
|
||||||
// use this type ahead of calling the function to prevent narrowing if a unit conversion is needed
|
// use this type ahead of calling the function to prevent narrowing if a unit conversion is needed
|
||||||
return make_quantity<one>(tan(value_cast<rep>(q).numerical_value_in(radian)));
|
return make_quantity<one>(tan(value_cast<rep>(q).numerical_value_in(radian)));
|
||||||
} else
|
} else
|
||||||
@@ -433,12 +456,13 @@ template<ReferenceOf<angle> auto R, typename Rep>
|
|||||||
|
|
||||||
template<ReferenceOf<dimensionless> auto R, typename Rep>
|
template<ReferenceOf<dimensionless> auto R, typename Rep>
|
||||||
[[nodiscard]] inline QuantityOf<angle> auto asin(const quantity<R, Rep>& q) noexcept
|
[[nodiscard]] inline QuantityOf<angle> auto asin(const quantity<R, Rep>& q) noexcept
|
||||||
requires requires { asin(q.numerical_value()); } || requires { std::asin(q.numerical_value()); }
|
requires requires { asin(q.numerical_value_ref_in(q.unit)); } ||
|
||||||
|
requires { std::asin(q.numerical_value_ref_in(q.unit)); }
|
||||||
{
|
{
|
||||||
using std::asin;
|
using std::asin;
|
||||||
if constexpr (!treat_as_floating_point<Rep>) {
|
if constexpr (!treat_as_floating_point<Rep>) {
|
||||||
// check what is the return type when called with the integral value
|
// check what is the return type when called with the integral value
|
||||||
using rep = decltype(asin(value_cast<one>(q).numerical_value()));
|
using rep = decltype(asin(q.force_numerical_value_in(one)));
|
||||||
// use this type ahead of calling the function to prevent narrowing if a unit conversion is needed
|
// use this type ahead of calling the function to prevent narrowing if a unit conversion is needed
|
||||||
return make_quantity<radian>(asin(value_cast<rep>(q).numerical_value_in(one)));
|
return make_quantity<radian>(asin(value_cast<rep>(q).numerical_value_in(one)));
|
||||||
} else
|
} else
|
||||||
@@ -447,12 +471,13 @@ template<ReferenceOf<dimensionless> auto R, typename Rep>
|
|||||||
|
|
||||||
template<ReferenceOf<dimensionless> auto R, typename Rep>
|
template<ReferenceOf<dimensionless> auto R, typename Rep>
|
||||||
[[nodiscard]] inline QuantityOf<angle> auto acos(const quantity<R, Rep>& q) noexcept
|
[[nodiscard]] inline QuantityOf<angle> auto acos(const quantity<R, Rep>& q) noexcept
|
||||||
requires requires { acos(q.numerical_value()); } || requires { std::acos(q.numerical_value()); }
|
requires requires { acos(q.numerical_value_ref_in(q.unit)); } ||
|
||||||
|
requires { std::acos(q.numerical_value_ref_in(q.unit)); }
|
||||||
{
|
{
|
||||||
using std::acos;
|
using std::acos;
|
||||||
if constexpr (!treat_as_floating_point<Rep>) {
|
if constexpr (!treat_as_floating_point<Rep>) {
|
||||||
// check what is the return type when called with the integral value
|
// check what is the return type when called with the integral value
|
||||||
using rep = decltype(acos(value_cast<one>(q).numerical_value()));
|
using rep = decltype(acos(q.force_numerical_value_in(one)));
|
||||||
// use this type ahead of calling the function to prevent narrowing if a unit conversion is needed
|
// use this type ahead of calling the function to prevent narrowing if a unit conversion is needed
|
||||||
return make_quantity<radian>(acos(value_cast<rep>(q).numerical_value_in(one)));
|
return make_quantity<radian>(acos(value_cast<rep>(q).numerical_value_in(one)));
|
||||||
} else
|
} else
|
||||||
@@ -461,12 +486,13 @@ template<ReferenceOf<dimensionless> auto R, typename Rep>
|
|||||||
|
|
||||||
template<ReferenceOf<dimensionless> auto R, typename Rep>
|
template<ReferenceOf<dimensionless> auto R, typename Rep>
|
||||||
[[nodiscard]] inline QuantityOf<angle> auto atan(const quantity<R, Rep>& q) noexcept
|
[[nodiscard]] inline QuantityOf<angle> auto atan(const quantity<R, Rep>& q) noexcept
|
||||||
requires requires { atan(q.numerical_value()); } || requires { std::atan(q.numerical_value()); }
|
requires requires { atan(q.numerical_value_ref_in(q.unit)); } ||
|
||||||
|
requires { std::atan(q.numerical_value_ref_in(q.unit)); }
|
||||||
{
|
{
|
||||||
using std::atan;
|
using std::atan;
|
||||||
if constexpr (!treat_as_floating_point<Rep>) {
|
if constexpr (!treat_as_floating_point<Rep>) {
|
||||||
// check what is the return type when called with the integral value
|
// check what is the return type when called with the integral value
|
||||||
using rep = decltype(atan(value_cast<one>(q).numerical_value()));
|
using rep = decltype(atan(q.force_numerical_value_in(one)));
|
||||||
// use this type ahead of calling the function to prevent narrowing if a unit conversion is needed
|
// use this type ahead of calling the function to prevent narrowing if a unit conversion is needed
|
||||||
return make_quantity<radian>(atan(value_cast<rep>(q).numerical_value_in(one)));
|
return make_quantity<radian>(atan(value_cast<rep>(q).numerical_value_in(one)));
|
||||||
} else
|
} else
|
||||||
|
@@ -35,7 +35,7 @@ static std::vector<typename Q::rep> i_qty_to_rep(InputIt first, InputIt last)
|
|||||||
std::vector<typename Q::rep> intervals_rep;
|
std::vector<typename Q::rep> intervals_rep;
|
||||||
intervals_rep.reserve(static_cast<size_t>(std::distance(first, last)));
|
intervals_rep.reserve(static_cast<size_t>(std::distance(first, last)));
|
||||||
for (auto itr = first; itr != last; ++itr) {
|
for (auto itr = first; itr != last; ++itr) {
|
||||||
intervals_rep.push_back(itr->numerical_value());
|
intervals_rep.push_back(itr->numerical_value_ref_in(Q::unit));
|
||||||
}
|
}
|
||||||
return intervals_rep;
|
return intervals_rep;
|
||||||
}
|
}
|
||||||
@@ -46,7 +46,7 @@ static std::vector<typename Q::rep> bl_qty_to_rep(std::initializer_list<Q>& bl)
|
|||||||
std::vector<typename Q::rep> bl_rep;
|
std::vector<typename Q::rep> bl_rep;
|
||||||
bl_rep.reserve(bl.size());
|
bl_rep.reserve(bl.size());
|
||||||
for (const Q& qty : bl) {
|
for (const Q& qty : bl) {
|
||||||
bl_rep.push_back(qty.numerical_value());
|
bl_rep.push_back(qty.numerical_value_ref_in(Q::unit));
|
||||||
}
|
}
|
||||||
return bl_rep;
|
return bl_rep;
|
||||||
}
|
}
|
||||||
@@ -88,7 +88,10 @@ struct uniform_int_distribution : public std::uniform_int_distribution<typename
|
|||||||
using base = MP_UNITS_TYPENAME std::uniform_int_distribution<rep>;
|
using base = MP_UNITS_TYPENAME std::uniform_int_distribution<rep>;
|
||||||
|
|
||||||
uniform_int_distribution() : base() {}
|
uniform_int_distribution() : base() {}
|
||||||
uniform_int_distribution(const Q& a, const Q& b) : base(a.numerical_value(), b.numerical_value()) {}
|
uniform_int_distribution(const Q& a, const Q& b) :
|
||||||
|
base(a.numerical_value_ref_in(Q::unit), b.numerical_value_ref_in(Q::unit))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
template<typename Generator>
|
template<typename Generator>
|
||||||
Q operator()(Generator& g)
|
Q operator()(Generator& g)
|
||||||
@@ -110,7 +113,10 @@ struct uniform_real_distribution : public std::uniform_real_distribution<typenam
|
|||||||
using base = MP_UNITS_TYPENAME std::uniform_real_distribution<rep>;
|
using base = MP_UNITS_TYPENAME std::uniform_real_distribution<rep>;
|
||||||
|
|
||||||
uniform_real_distribution() : base() {}
|
uniform_real_distribution() : base() {}
|
||||||
uniform_real_distribution(const Q& a, const Q& b) : base(a.numerical_value(), b.numerical_value()) {}
|
uniform_real_distribution(const Q& a, const Q& b) :
|
||||||
|
base(a.numerical_value_ref_in(Q::unit), b.numerical_value_ref_in(Q::unit))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
template<typename Generator>
|
template<typename Generator>
|
||||||
Q operator()(Generator& g)
|
Q operator()(Generator& g)
|
||||||
@@ -132,7 +138,7 @@ struct binomial_distribution : public std::binomial_distribution<typename Q::rep
|
|||||||
using base = MP_UNITS_TYPENAME std::binomial_distribution<rep>;
|
using base = MP_UNITS_TYPENAME std::binomial_distribution<rep>;
|
||||||
|
|
||||||
binomial_distribution() : base() {}
|
binomial_distribution() : base() {}
|
||||||
binomial_distribution(const Q& t, double p) : base(t.numerical_value(), p) {}
|
binomial_distribution(const Q& t, double p) : base(t.numerical_value_ref_in(Q::unit), p) {}
|
||||||
|
|
||||||
template<typename Generator>
|
template<typename Generator>
|
||||||
Q operator()(Generator& g)
|
Q operator()(Generator& g)
|
||||||
@@ -153,7 +159,7 @@ struct negative_binomial_distribution : public std::negative_binomial_distributi
|
|||||||
using base = MP_UNITS_TYPENAME std::negative_binomial_distribution<rep>;
|
using base = MP_UNITS_TYPENAME std::negative_binomial_distribution<rep>;
|
||||||
|
|
||||||
negative_binomial_distribution() : base() {}
|
negative_binomial_distribution() : base() {}
|
||||||
negative_binomial_distribution(const Q& k, double p) : base(k.numerical_value(), p) {}
|
negative_binomial_distribution(const Q& k, double p) : base(k.numerical_value_ref_in(Q::unit), p) {}
|
||||||
|
|
||||||
template<typename Generator>
|
template<typename Generator>
|
||||||
Q operator()(Generator& g)
|
Q operator()(Generator& g)
|
||||||
@@ -269,7 +275,7 @@ struct extreme_value_distribution : public std::extreme_value_distribution<typen
|
|||||||
using base = MP_UNITS_TYPENAME std::extreme_value_distribution<rep>;
|
using base = MP_UNITS_TYPENAME std::extreme_value_distribution<rep>;
|
||||||
|
|
||||||
extreme_value_distribution() : base() {}
|
extreme_value_distribution() : base() {}
|
||||||
extreme_value_distribution(const Q& a, const rep& b) : base(a.numerical_value(), b) {}
|
extreme_value_distribution(const Q& a, const rep& b) : base(a.numerical_value_ref_in(Q::unit), b) {}
|
||||||
|
|
||||||
template<typename Generator>
|
template<typename Generator>
|
||||||
Q operator()(Generator& g)
|
Q operator()(Generator& g)
|
||||||
@@ -290,7 +296,10 @@ struct normal_distribution : public std::normal_distribution<typename Q::rep> {
|
|||||||
using base = MP_UNITS_TYPENAME std::normal_distribution<rep>;
|
using base = MP_UNITS_TYPENAME std::normal_distribution<rep>;
|
||||||
|
|
||||||
normal_distribution() : base() {}
|
normal_distribution() : base() {}
|
||||||
normal_distribution(const Q& mean, const Q& stddev) : base(mean.numerical_value(), stddev.numerical_value()) {}
|
normal_distribution(const Q& mean, const Q& stddev) :
|
||||||
|
base(mean.numerical_value_ref_in(Q::unit), stddev.numerical_value_ref_in(Q::unit))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
template<typename Generator>
|
template<typename Generator>
|
||||||
Q operator()(Generator& g)
|
Q operator()(Generator& g)
|
||||||
@@ -312,7 +321,10 @@ struct lognormal_distribution : public std::lognormal_distribution<typename Q::r
|
|||||||
using base = MP_UNITS_TYPENAME std::lognormal_distribution<rep>;
|
using base = MP_UNITS_TYPENAME std::lognormal_distribution<rep>;
|
||||||
|
|
||||||
lognormal_distribution() : base() {}
|
lognormal_distribution() : base() {}
|
||||||
lognormal_distribution(const Q& m, const Q& s) : base(m.numerical_value(), s.numerical_value()) {}
|
lognormal_distribution(const Q& m, const Q& s) :
|
||||||
|
base(m.numerical_value_ref_in(Q::unit), s.numerical_value_ref_in(Q::unit))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
template<typename Generator>
|
template<typename Generator>
|
||||||
Q operator()(Generator& g)
|
Q operator()(Generator& g)
|
||||||
@@ -353,7 +365,10 @@ struct cauchy_distribution : public std::cauchy_distribution<typename Q::rep> {
|
|||||||
using base = MP_UNITS_TYPENAME std::cauchy_distribution<rep>;
|
using base = MP_UNITS_TYPENAME std::cauchy_distribution<rep>;
|
||||||
|
|
||||||
cauchy_distribution() : base() {}
|
cauchy_distribution() : base() {}
|
||||||
cauchy_distribution(const Q& a, const Q& b) : base(a.numerical_value(), b.numerical_value()) {}
|
cauchy_distribution(const Q& a, const Q& b) :
|
||||||
|
base(a.numerical_value_ref_in(Q::unit), b.numerical_value_ref_in(Q::unit))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
template<typename Generator>
|
template<typename Generator>
|
||||||
Q operator()(Generator& g)
|
Q operator()(Generator& g)
|
||||||
@@ -470,7 +485,8 @@ public:
|
|||||||
|
|
||||||
template<typename UnaryOperation>
|
template<typename UnaryOperation>
|
||||||
piecewise_constant_distribution(std::size_t nw, const Q& xmin, const Q& xmax, UnaryOperation fw) :
|
piecewise_constant_distribution(std::size_t nw, const Q& xmin, const Q& xmax, UnaryOperation fw) :
|
||||||
base(nw, xmin.numerical_value(), xmax.numerical_value(), [fw](rep val) { return fw(val * Q::reference); })
|
base(nw, xmin.numerical_value_ref_in(Q::unit), xmax.numerical_value_ref_in(Q::unit),
|
||||||
|
[fw](rep val) { return fw(val * Q::reference); })
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -528,7 +544,8 @@ public:
|
|||||||
|
|
||||||
template<typename UnaryOperation>
|
template<typename UnaryOperation>
|
||||||
piecewise_linear_distribution(std::size_t nw, const Q& xmin, const Q& xmax, UnaryOperation fw) :
|
piecewise_linear_distribution(std::size_t nw, const Q& xmin, const Q& xmax, UnaryOperation fw) :
|
||||||
base(nw, xmin.numerical_value(), xmax.numerical_value(), [fw](rep val) { return fw(val * Q::reference); })
|
base(nw, xmin.numerical_value_ref_in(Q::unit), xmax.numerical_value_ref_in(Q::unit),
|
||||||
|
[fw](rep val) { return fw(val * Q::reference); })
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -36,8 +36,8 @@ struct AlmostEqualsMatcher : Catch::Matchers::MatcherGenericBase {
|
|||||||
{
|
{
|
||||||
using std::abs;
|
using std::abs;
|
||||||
using common = std::common_type_t<T, U>;
|
using common = std::common_type_t<T, U>;
|
||||||
const auto x = common(target_).numerical_value();
|
const auto x = common(target_).numerical_value_in(common::unit);
|
||||||
const auto y = common(other).numerical_value();
|
const auto y = common(other).numerical_value_in(common::unit);
|
||||||
const auto maxXYOne = std::max({typename T::rep{1}, abs(x), abs(y)});
|
const auto maxXYOne = std::max({typename T::rep{1}, abs(x), abs(y)});
|
||||||
return abs(x - y) <= std::numeric_limits<typename T::rep>::epsilon() * maxXYOne;
|
return abs(x - y) <= std::numeric_limits<typename T::rep>::epsilon() * maxXYOne;
|
||||||
}
|
}
|
||||||
|
@@ -559,8 +559,8 @@ TEST_CASE("piecewise_constant_distribution")
|
|||||||
3.0 * isq::length[si::metre]};
|
3.0 * isq::length[si::metre]};
|
||||||
|
|
||||||
auto stl_dist = std::piecewise_constant_distribution<rep>(intervals_rep, [](rep val) { return val; });
|
auto stl_dist = std::piecewise_constant_distribution<rep>(intervals_rep, [](rep val) { return val; });
|
||||||
auto units_dist =
|
auto units_dist = mp_units::piecewise_constant_distribution<q>(
|
||||||
mp_units::piecewise_constant_distribution<q>(intervals_qty, [](q qty) { return qty.numerical_value(); });
|
intervals_qty, [](q qty) { return qty.numerical_value_ref_in(qty.unit); });
|
||||||
|
|
||||||
CHECK(units_dist.intervals() == intervals_qty_vec);
|
CHECK(units_dist.intervals() == intervals_qty_vec);
|
||||||
CHECK(units_dist.densities() == stl_dist.densities());
|
CHECK(units_dist.densities() == stl_dist.densities());
|
||||||
@@ -573,8 +573,8 @@ TEST_CASE("piecewise_constant_distribution")
|
|||||||
constexpr q xmin_qty = 1.0 * isq::length[si::metre], xmax_qty = 3.0 * isq::length[si::metre];
|
constexpr q xmin_qty = 1.0 * isq::length[si::metre], xmax_qty = 3.0 * isq::length[si::metre];
|
||||||
|
|
||||||
auto stl_dist = std::piecewise_constant_distribution<rep>(nw, xmin_rep, xmax_rep, [](rep val) { return val; });
|
auto stl_dist = std::piecewise_constant_distribution<rep>(nw, xmin_rep, xmax_rep, [](rep val) { return val; });
|
||||||
auto units_dist =
|
auto units_dist = mp_units::piecewise_constant_distribution<q>(
|
||||||
mp_units::piecewise_constant_distribution<q>(nw, xmin_qty, xmax_qty, [](q qty) { return qty.numerical_value(); });
|
nw, xmin_qty, xmax_qty, [](q qty) { return qty.numerical_value_ref_in(qty.unit); });
|
||||||
|
|
||||||
CHECK(units_dist.intervals() == intervals_qty_vec);
|
CHECK(units_dist.intervals() == intervals_qty_vec);
|
||||||
CHECK(units_dist.densities() == stl_dist.densities());
|
CHECK(units_dist.densities() == stl_dist.densities());
|
||||||
@@ -627,8 +627,8 @@ TEST_CASE("piecewise_linear_distribution")
|
|||||||
3.0 * isq::length[si::metre]};
|
3.0 * isq::length[si::metre]};
|
||||||
|
|
||||||
auto stl_dist = std::piecewise_linear_distribution<rep>(intervals_rep, [](rep val) { return val; });
|
auto stl_dist = std::piecewise_linear_distribution<rep>(intervals_rep, [](rep val) { return val; });
|
||||||
auto units_dist =
|
auto units_dist = mp_units::piecewise_linear_distribution<q>(
|
||||||
mp_units::piecewise_linear_distribution<q>(intervals_qty, [](q qty) { return qty.numerical_value(); });
|
intervals_qty, [](q qty) { return qty.numerical_value_ref_in(qty.unit); });
|
||||||
|
|
||||||
CHECK(units_dist.intervals() == intervals_qty_vec);
|
CHECK(units_dist.intervals() == intervals_qty_vec);
|
||||||
CHECK(units_dist.densities() == stl_dist.densities());
|
CHECK(units_dist.densities() == stl_dist.densities());
|
||||||
@@ -641,8 +641,8 @@ TEST_CASE("piecewise_linear_distribution")
|
|||||||
constexpr q xmin_qty = 1.0 * isq::length[si::metre], xmax_qty = 3.0 * isq::length[si::metre];
|
constexpr q xmin_qty = 1.0 * isq::length[si::metre], xmax_qty = 3.0 * isq::length[si::metre];
|
||||||
|
|
||||||
auto stl_dist = std::piecewise_linear_distribution<rep>(nw, xmin_rep, xmax_rep, [](rep val) { return val; });
|
auto stl_dist = std::piecewise_linear_distribution<rep>(nw, xmin_rep, xmax_rep, [](rep val) { return val; });
|
||||||
auto units_dist =
|
auto units_dist = mp_units::piecewise_linear_distribution<q>(
|
||||||
mp_units::piecewise_linear_distribution<q>(nw, xmin_qty, xmax_qty, [](q qty) { return qty.numerical_value(); });
|
nw, xmin_qty, xmax_qty, [](q qty) { return qty.numerical_value_ref_in(qty.unit); });
|
||||||
|
|
||||||
CHECK(units_dist.intervals() == intervals_qty_vec);
|
CHECK(units_dist.intervals() == intervals_qty_vec);
|
||||||
CHECK(units_dist.densities() == stl_dist.densities());
|
CHECK(units_dist.densities() == stl_dist.densities());
|
||||||
|
@@ -56,11 +56,19 @@ namespace {
|
|||||||
using namespace mp_units;
|
using namespace mp_units;
|
||||||
using namespace mp_units::si::unit_symbols;
|
using namespace mp_units::si::unit_symbols;
|
||||||
|
|
||||||
template<typename T>
|
template<QuantitySpec auto QS, QuantityOf<QS> Q>
|
||||||
[[nodiscard]] auto get_magnitude(const vector<T>& v)
|
requires(Q::quantity_spec.character == quantity_character::vector) && (QS.character == quantity_character::scalar)
|
||||||
|
[[nodiscard]] QuantityOf<QS> auto get_magnitude(const Q& q)
|
||||||
{
|
{
|
||||||
using namespace std;
|
const auto& v = q.numerical_value_ref_in(q.unit);
|
||||||
return hypot(v(0), v(1), v(2));
|
return hypot(v(0) * QS[q.unit], v(1) * QS[q.unit], v(2) * QS[q.unit]);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<QuantitySpec auto QS, QuantityOf<QS> T>
|
||||||
|
requires(T::quantity_spec.character == quantity_character::vector) && (QS.character == quantity_character::scalar)
|
||||||
|
[[nodiscard]] QuantityOf<QS> auto get_magnitude(const vector<T>& v)
|
||||||
|
{
|
||||||
|
return hypot(QS(v(0)), QS(v(1)), QS(v(2)));
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T, typename U>
|
template<typename T, typename U>
|
||||||
@@ -74,7 +82,8 @@ template<Quantity Q1, Quantity Q2>
|
|||||||
requires(typename Q1::rep v1, typename Q2::rep v2) { cross_product(v1, v2); }
|
requires(typename Q1::rep v1, typename Q2::rep v2) { cross_product(v1, v2); }
|
||||||
[[nodiscard]] QuantityOf<Q1::quantity_spec * Q2::quantity_spec> auto cross_product(const Q1& q1, const Q2& q2)
|
[[nodiscard]] QuantityOf<Q1::quantity_spec * Q2::quantity_spec> auto cross_product(const Q1& q1, const Q2& q2)
|
||||||
{
|
{
|
||||||
return cross_product(q1.numerical_value(), q2.numerical_value()) * (Q1::reference * Q2::reference);
|
return cross_product(q1.numerical_value_ref_in(q1.unit), q2.numerical_value_ref_in(q2.unit)) *
|
||||||
|
(Q1::reference * Q2::reference);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
@@ -86,21 +95,21 @@ TEST_CASE("vector quantity", "[la]")
|
|||||||
SECTION("non-truncating")
|
SECTION("non-truncating")
|
||||||
{
|
{
|
||||||
const auto v = vector<int>{3, 2, 1} * isq::position_vector[km];
|
const auto v = vector<int>{3, 2, 1} * isq::position_vector[km];
|
||||||
CHECK(v.in(m).numerical_value() == vector<int>{3000, 2000, 1000});
|
CHECK(v.numerical_value_in(m) == vector<int>{3000, 2000, 1000});
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("truncating")
|
SECTION("truncating")
|
||||||
{
|
{
|
||||||
const auto v = vector<int>{1001, 1002, 1003} * isq::position_vector[m];
|
const auto v = vector<int>{1001, 1002, 1003} * isq::position_vector[m];
|
||||||
CHECK(value_cast<km>(v).numerical_value() == vector<int>{1, 1, 1});
|
CHECK(v.force_numerical_value_in(km) == vector<int>{1, 1, 1});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("to scalar magnitude")
|
SECTION("to scalar magnitude")
|
||||||
{
|
{
|
||||||
const auto v = vector<int>{2, 3, 6} * isq::velocity[km / h];
|
const auto v = vector<int>{2, 3, 6} * isq::velocity[km / h];
|
||||||
const auto speed = get_magnitude(v.numerical_value()) * isq::speed[v.unit]; // TODO can we do better here?
|
const auto speed = get_magnitude<isq::speed>(v);
|
||||||
CHECK(speed.numerical_value() == 7);
|
CHECK(speed.numerical_value_ref_in(km / h) == 7);
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("multiply by scalar value")
|
SECTION("multiply by scalar value")
|
||||||
@@ -109,14 +118,14 @@ TEST_CASE("vector quantity", "[la]")
|
|||||||
|
|
||||||
SECTION("integral")
|
SECTION("integral")
|
||||||
{
|
{
|
||||||
SECTION("scalar on LHS") { CHECK((2 * v).numerical_value() == vector<int>{2, 4, 6}); }
|
SECTION("scalar on LHS") { CHECK((2 * v).numerical_value_ == vector<int>{2, 4, 6}); }
|
||||||
SECTION("scalar on RHS") { CHECK((v * 2).numerical_value() == vector<int>{2, 4, 6}); }
|
SECTION("scalar on RHS") { CHECK((v * 2).numerical_value_ == vector<int>{2, 4, 6}); }
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("floating-point")
|
SECTION("floating-point")
|
||||||
{
|
{
|
||||||
SECTION("scalar on LHS") { CHECK((0.5 * v).numerical_value() == vector<double>{0.5, 1., 1.5}); }
|
SECTION("scalar on LHS") { CHECK((0.5 * v).numerical_value_ == vector<double>{0.5, 1., 1.5}); }
|
||||||
SECTION("scalar on RHS") { CHECK((v * 0.5).numerical_value() == vector<double>{0.5, 1., 1.5}); }
|
SECTION("scalar on RHS") { CHECK((v * 0.5).numerical_value_ == vector<double>{0.5, 1., 1.5}); }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -124,8 +133,8 @@ TEST_CASE("vector quantity", "[la]")
|
|||||||
{
|
{
|
||||||
const auto v = vector<int>{2, 4, 6} * isq::position_vector[m];
|
const auto v = vector<int>{2, 4, 6} * isq::position_vector[m];
|
||||||
|
|
||||||
SECTION("integral") { CHECK((v / 2).numerical_value() == vector<int>{1, 2, 3}); }
|
SECTION("integral") { CHECK((v / 2).numerical_value_ == vector<int>{1, 2, 3}); }
|
||||||
SECTION("floating-point") { CHECK((v / 0.5).numerical_value() == vector<double>{4., 8., 12.}); }
|
SECTION("floating-point") { CHECK((v / 0.5).numerical_value_ == vector<double>{4., 8., 12.}); }
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("add")
|
SECTION("add")
|
||||||
@@ -135,12 +144,12 @@ TEST_CASE("vector quantity", "[la]")
|
|||||||
SECTION("same unit")
|
SECTION("same unit")
|
||||||
{
|
{
|
||||||
const auto u = vector<int>{3, 2, 1} * isq::position_vector[m];
|
const auto u = vector<int>{3, 2, 1} * isq::position_vector[m];
|
||||||
CHECK((v + u).numerical_value() == vector<int>{4, 4, 4});
|
CHECK((v + u).numerical_value_ == vector<int>{4, 4, 4});
|
||||||
}
|
}
|
||||||
SECTION("different units")
|
SECTION("different units")
|
||||||
{
|
{
|
||||||
const auto u = vector<int>{3, 2, 1} * isq::position_vector[km];
|
const auto u = vector<int>{3, 2, 1} * isq::position_vector[km];
|
||||||
CHECK((v + u).numerical_value() == vector<int>{3001, 2002, 1003});
|
CHECK((v + u).numerical_value_ == vector<int>{3001, 2002, 1003});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -151,12 +160,12 @@ TEST_CASE("vector quantity", "[la]")
|
|||||||
SECTION("same unit")
|
SECTION("same unit")
|
||||||
{
|
{
|
||||||
const auto u = vector<int>{3, 2, 1} * isq::position_vector[m];
|
const auto u = vector<int>{3, 2, 1} * isq::position_vector[m];
|
||||||
CHECK((v - u).numerical_value() == vector<int>{-2, 0, 2});
|
CHECK((v - u).numerical_value_ == vector<int>{-2, 0, 2});
|
||||||
}
|
}
|
||||||
SECTION("different units")
|
SECTION("different units")
|
||||||
{
|
{
|
||||||
const auto u = vector<int>{3, 2, 1} * isq::position_vector[km];
|
const auto u = vector<int>{3, 2, 1} * isq::position_vector[km];
|
||||||
CHECK((v - u).numerical_value() == vector<int>{-2999, -1998, -997});
|
CHECK((v - u).numerical_value_ == vector<int>{-2999, -1998, -997});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -170,18 +179,18 @@ TEST_CASE("vector quantity", "[la]")
|
|||||||
|
|
||||||
SECTION("derived_quantity_spec")
|
SECTION("derived_quantity_spec")
|
||||||
{
|
{
|
||||||
SECTION("scalar on LHS") { CHECK((mass * v).numerical_value() == vector<int>{2, 4, 6}); }
|
SECTION("scalar on LHS") { CHECK((mass * v).numerical_value_ == vector<int>{2, 4, 6}); }
|
||||||
SECTION("scalar on RHS") { CHECK((v * mass).numerical_value() == vector<int>{2, 4, 6}); }
|
SECTION("scalar on RHS") { CHECK((v * mass).numerical_value_ == vector<int>{2, 4, 6}); }
|
||||||
}
|
}
|
||||||
SECTION("quantity_cast to momentum")
|
SECTION("quantity_cast to momentum")
|
||||||
{
|
{
|
||||||
SECTION("scalar on LHS")
|
SECTION("scalar on LHS")
|
||||||
{
|
{
|
||||||
CHECK(quantity_cast<isq::momentum>(mass * v).numerical_value() == vector<int>{2, 4, 6});
|
CHECK(quantity_cast<isq::momentum>(mass * v).numerical_value_ == vector<int>{2, 4, 6});
|
||||||
}
|
}
|
||||||
SECTION("scalar on RHS")
|
SECTION("scalar on RHS")
|
||||||
{
|
{
|
||||||
CHECK(quantity_cast<isq::momentum>(v * mass).numerical_value() == vector<int>{2, 4, 6});
|
CHECK(quantity_cast<isq::momentum>(v * mass).numerical_value_ == vector<int>{2, 4, 6});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
SECTION("quantity of momentum")
|
SECTION("quantity of momentum")
|
||||||
@@ -189,12 +198,12 @@ TEST_CASE("vector quantity", "[la]")
|
|||||||
SECTION("scalar on LHS")
|
SECTION("scalar on LHS")
|
||||||
{
|
{
|
||||||
const quantity<isq::momentum[N * s], vector<int>> momentum = mass * v;
|
const quantity<isq::momentum[N * s], vector<int>> momentum = mass * v;
|
||||||
CHECK(momentum.numerical_value() == vector<int>{2, 4, 6});
|
CHECK(momentum.numerical_value_ == vector<int>{2, 4, 6});
|
||||||
}
|
}
|
||||||
SECTION("scalar on RHS")
|
SECTION("scalar on RHS")
|
||||||
{
|
{
|
||||||
const quantity<isq::momentum[N * s], vector<int>> momentum = v * mass;
|
const quantity<isq::momentum[N * s], vector<int>> momentum = v * mass;
|
||||||
CHECK(momentum.numerical_value() == vector<int>{2, 4, 6});
|
CHECK(momentum.numerical_value_ == vector<int>{2, 4, 6});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -205,18 +214,18 @@ TEST_CASE("vector quantity", "[la]")
|
|||||||
|
|
||||||
SECTION("derived_quantity_spec")
|
SECTION("derived_quantity_spec")
|
||||||
{
|
{
|
||||||
SECTION("scalar on LHS") { CHECK((mass * v).numerical_value() == vector<double>{0.5, 1., 1.5}); }
|
SECTION("scalar on LHS") { CHECK((mass * v).numerical_value_ == vector<double>{0.5, 1., 1.5}); }
|
||||||
SECTION("scalar on RHS") { CHECK((v * mass).numerical_value() == vector<double>{0.5, 1., 1.5}); }
|
SECTION("scalar on RHS") { CHECK((v * mass).numerical_value_ == vector<double>{0.5, 1., 1.5}); }
|
||||||
}
|
}
|
||||||
SECTION("quantity_cast to momentum")
|
SECTION("quantity_cast to momentum")
|
||||||
{
|
{
|
||||||
SECTION("scalar on LHS")
|
SECTION("scalar on LHS")
|
||||||
{
|
{
|
||||||
CHECK(quantity_cast<isq::momentum>(mass * v).numerical_value() == vector<double>{0.5, 1., 1.5});
|
CHECK(quantity_cast<isq::momentum>(mass * v).numerical_value_ == vector<double>{0.5, 1., 1.5});
|
||||||
}
|
}
|
||||||
SECTION("scalar on RHS")
|
SECTION("scalar on RHS")
|
||||||
{
|
{
|
||||||
CHECK(quantity_cast<isq::momentum>(v * mass).numerical_value() == vector<double>{0.5, 1., 1.5});
|
CHECK(quantity_cast<isq::momentum>(v * mass).numerical_value_ == vector<double>{0.5, 1., 1.5});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
SECTION("quantity of momentum")
|
SECTION("quantity of momentum")
|
||||||
@@ -224,12 +233,12 @@ TEST_CASE("vector quantity", "[la]")
|
|||||||
SECTION("scalar on LHS")
|
SECTION("scalar on LHS")
|
||||||
{
|
{
|
||||||
const quantity<isq::momentum[N * s], vector<double>> momentum = mass * v;
|
const quantity<isq::momentum[N * s], vector<double>> momentum = mass * v;
|
||||||
CHECK(momentum.numerical_value() == vector<double>{0.5, 1., 1.5});
|
CHECK(momentum.numerical_value_ == vector<double>{0.5, 1., 1.5});
|
||||||
}
|
}
|
||||||
SECTION("scalar on RHS")
|
SECTION("scalar on RHS")
|
||||||
{
|
{
|
||||||
const quantity<isq::momentum[N * s], vector<double>> momentum = v * mass;
|
const quantity<isq::momentum[N * s], vector<double>> momentum = v * mass;
|
||||||
CHECK(momentum.numerical_value() == vector<double>{0.5, 1., 1.5});
|
CHECK(momentum.numerical_value_ == vector<double>{0.5, 1., 1.5});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -243,15 +252,15 @@ TEST_CASE("vector quantity", "[la]")
|
|||||||
{
|
{
|
||||||
const auto dur = 2 * isq::duration[h];
|
const auto dur = 2 * isq::duration[h];
|
||||||
|
|
||||||
SECTION("derived_quantity_spec") { CHECK((pos / dur).numerical_value() == vector<int>{15, 10, 5}); }
|
SECTION("derived_quantity_spec") { CHECK((pos / dur).numerical_value_ == vector<int>{15, 10, 5}); }
|
||||||
SECTION("quantity_cast to velocity")
|
SECTION("quantity_cast to velocity")
|
||||||
{
|
{
|
||||||
CHECK(quantity_cast<isq::velocity>(pos / dur).numerical_value() == vector<int>{15, 10, 5});
|
CHECK(quantity_cast<isq::velocity>(pos / dur).numerical_value_ == vector<int>{15, 10, 5});
|
||||||
}
|
}
|
||||||
SECTION("quantity of velocity")
|
SECTION("quantity of velocity")
|
||||||
{
|
{
|
||||||
const quantity<isq::velocity[km / h], vector<int>> v = pos / dur;
|
const quantity<isq::velocity[km / h], vector<int>> v = pos / dur;
|
||||||
CHECK(v.numerical_value() == vector<int>{15, 10, 5});
|
CHECK(v.numerical_value_ == vector<int>{15, 10, 5});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -259,15 +268,15 @@ TEST_CASE("vector quantity", "[la]")
|
|||||||
{
|
{
|
||||||
const auto dur = 0.5 * isq::duration[h];
|
const auto dur = 0.5 * isq::duration[h];
|
||||||
|
|
||||||
SECTION("derived_quantity_spec") { CHECK((pos / dur).numerical_value() == vector<double>{60, 40, 20}); }
|
SECTION("derived_quantity_spec") { CHECK((pos / dur).numerical_value_ == vector<double>{60, 40, 20}); }
|
||||||
SECTION("quantity_cast to velocity")
|
SECTION("quantity_cast to velocity")
|
||||||
{
|
{
|
||||||
CHECK(quantity_cast<isq::velocity>(pos / dur).numerical_value() == vector<double>{60, 40, 20});
|
CHECK(quantity_cast<isq::velocity>(pos / dur).numerical_value_ == vector<double>{60, 40, 20});
|
||||||
}
|
}
|
||||||
SECTION("quantity of velocity")
|
SECTION("quantity of velocity")
|
||||||
{
|
{
|
||||||
const quantity<isq::velocity[km / h], vector<double>> v = pos / dur;
|
const quantity<isq::velocity[km / h], vector<double>> v = pos / dur;
|
||||||
CHECK(v.numerical_value() == vector<double>{60, 40, 20});
|
CHECK(v.numerical_value_ == vector<double>{60, 40, 20});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -303,8 +312,8 @@ TEST_CASE("vector of quantities", "[la]")
|
|||||||
SECTION("to scalar magnitude")
|
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(v).numerical_value() * isq::speed[v(0).unit]; // TODO can we do better here?
|
const auto speed = get_magnitude<isq::speed>(v);
|
||||||
CHECK(speed.numerical_value() == 7);
|
CHECK(speed.numerical_value_ref_in(km / h) == 7);
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("multiply by scalar value")
|
SECTION("multiply by scalar value")
|
||||||
|
@@ -90,12 +90,12 @@ TEST_CASE("numeric_limits functions", "[limits]")
|
|||||||
{
|
{
|
||||||
SECTION("'epsilon' works as expected using default floating type")
|
SECTION("'epsilon' works as expected using default floating type")
|
||||||
{
|
{
|
||||||
REQUIRE(epsilon<double>(isq::length[m]).numerical_value() ==
|
REQUIRE(epsilon<double>(isq::length[m]).numerical_value_ ==
|
||||||
std::numeric_limits<decltype(1. * isq::length[m])::rep>::epsilon());
|
std::numeric_limits<decltype(1. * isq::length[m])::rep>::epsilon());
|
||||||
}
|
}
|
||||||
SECTION("'epsilon' works as expected using integers")
|
SECTION("'epsilon' works as expected using integers")
|
||||||
{
|
{
|
||||||
REQUIRE(epsilon<int>(isq::length[m]).numerical_value() ==
|
REQUIRE(epsilon<int>(isq::length[m]).numerical_value_ ==
|
||||||
std::numeric_limits<decltype(1 * isq::length[m])::rep>::epsilon());
|
std::numeric_limits<decltype(1 * isq::length[m])::rep>::epsilon());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -241,16 +241,18 @@ static_assert(
|
|||||||
// static member functions
|
// static member functions
|
||||||
////////////////////////////
|
////////////////////////////
|
||||||
|
|
||||||
static_assert(quantity_point<isq::height[m], mean_sea_level>::zero().quantity_from_origin().numerical_value() == 0);
|
static_assert(quantity_point<isq::height[m], mean_sea_level>::zero().quantity_from_origin_.numerical_value_ == 0);
|
||||||
static_assert(quantity_point<isq::height[m], mean_sea_level>::min().quantity_from_origin().numerical_value() ==
|
static_assert(quantity_point<isq::height[m], mean_sea_level>::min().quantity_from_origin_.numerical_value_ ==
|
||||||
std::numeric_limits<double>::lowest());
|
std::numeric_limits<double>::lowest());
|
||||||
static_assert(quantity_point<isq::height[m], mean_sea_level>::max().quantity_from_origin().numerical_value() ==
|
static_assert(quantity_point<isq::height[m], mean_sea_level>::max().quantity_from_origin_.numerical_value_ ==
|
||||||
std::numeric_limits<double>::max());
|
std::numeric_limits<double>::max());
|
||||||
|
|
||||||
static_assert(quantity_point<isq::height[m], ground_level, int>::zero().quantity_from_origin().numerical_value() == 0);
|
static_assert(
|
||||||
static_assert(quantity_point<isq::height[m], ground_level, int>::min().quantity_from_origin().numerical_value() ==
|
|
||||||
|
quantity_point<isq::height[m], ground_level, int>::zero().quantity_from_origin_.numerical_value_ == 0);
|
||||||
|
static_assert(quantity_point<isq::height[m], ground_level, int>::min().quantity_from_origin_.numerical_value_ ==
|
||||||
std::numeric_limits<int>::lowest());
|
std::numeric_limits<int>::lowest());
|
||||||
static_assert(quantity_point<isq::height[m], ground_level, int>::max().quantity_from_origin().numerical_value() ==
|
static_assert(quantity_point<isq::height[m], ground_level, int>::max().quantity_from_origin_.numerical_value_ ==
|
||||||
std::numeric_limits<int>::max());
|
std::numeric_limits<int>::max());
|
||||||
|
|
||||||
|
|
||||||
@@ -537,36 +539,36 @@ static_assert(
|
|||||||
// obtaining a relative quantity
|
// obtaining a relative quantity
|
||||||
//////////////////////////////////
|
//////////////////////////////////
|
||||||
|
|
||||||
static_assert((mean_sea_level + 42 * m).quantity_from_origin() == 42 * m);
|
static_assert((mean_sea_level + 42 * m).quantity_from_origin_ == 42 * m);
|
||||||
static_assert((mean_sea_level + isq::height(42 * m)).quantity_from_origin() == 42 * m);
|
static_assert((mean_sea_level + isq::height(42 * m)).quantity_from_origin_ == 42 * m);
|
||||||
|
|
||||||
static_assert((zero + 1 * one).quantity_from_origin() == 1 * one);
|
static_assert((zero + 1 * one).quantity_from_origin_ == 1 * one);
|
||||||
static_assert((zero + dimensionless(1 * one)).quantity_from_origin() == 1 * one);
|
static_assert((zero + dimensionless(1 * one)).quantity_from_origin_ == 1 * one);
|
||||||
|
|
||||||
static_assert((mean_sea_level + 42 * m).quantity_from_origin() == 42 * m);
|
static_assert((mean_sea_level + 42 * m).quantity_from_origin_ == 42 * m);
|
||||||
static_assert((ground_level + 42 * m).quantity_from_origin() == 42 * m);
|
static_assert((ground_level + 42 * m).quantity_from_origin_ == 42 * m);
|
||||||
static_assert((tower_peak + 42 * m).quantity_from_origin() == 42 * m);
|
static_assert((tower_peak + 42 * m).quantity_from_origin_ == 42 * m);
|
||||||
|
|
||||||
static_assert(quantity_point<isq::height[m], mean_sea_level>(ground_level + 42 * m).quantity_from_origin() == 84 * m);
|
static_assert(quantity_point<isq::height[m], mean_sea_level>(ground_level + 42 * m).quantity_from_origin_ == 84 * m);
|
||||||
static_assert(quantity_point<isq::height[m], mean_sea_level>(tower_peak + 42 * m).quantity_from_origin() == 126 * m);
|
static_assert(quantity_point<isq::height[m], mean_sea_level>(tower_peak + 42 * m).quantity_from_origin_ == 126 * m);
|
||||||
|
|
||||||
static_assert(quantity_point<isq::height[m], ground_level>(mean_sea_level + 84 * m).quantity_from_origin() == 42 * m);
|
static_assert(quantity_point<isq::height[m], ground_level>(mean_sea_level + 84 * m).quantity_from_origin_ == 42 * m);
|
||||||
static_assert(quantity_point<isq::height[m], ground_level>(tower_peak + 42 * m).quantity_from_origin() == 84 * m);
|
static_assert(quantity_point<isq::height[m], ground_level>(tower_peak + 42 * m).quantity_from_origin_ == 84 * m);
|
||||||
|
|
||||||
static_assert(quantity_point<isq::height[m], tower_peak>(mean_sea_level + 42 * m).quantity_from_origin() == -42 * m);
|
static_assert(quantity_point<isq::height[m], tower_peak>(mean_sea_level + 42 * m).quantity_from_origin_ == -42 * m);
|
||||||
static_assert(quantity_point<isq::height[m], tower_peak>(ground_level + 84 * m).quantity_from_origin() == 42 * m);
|
static_assert(quantity_point<isq::height[m], tower_peak>(ground_level + 84 * m).quantity_from_origin_ == 42 * m);
|
||||||
|
|
||||||
static_assert((mean_sea_level + 42 * m).point_for(mean_sea_level).quantity_from_origin() == 42 * m);
|
static_assert((mean_sea_level + 42 * m).point_for(mean_sea_level).quantity_from_origin_ == 42 * m);
|
||||||
static_assert((ground_level + 42 * m).point_for(mean_sea_level).quantity_from_origin() == 84 * m);
|
static_assert((ground_level + 42 * m).point_for(mean_sea_level).quantity_from_origin_ == 84 * m);
|
||||||
static_assert((tower_peak + 42 * m).point_for(mean_sea_level).quantity_from_origin() == 126 * m);
|
static_assert((tower_peak + 42 * m).point_for(mean_sea_level).quantity_from_origin_ == 126 * m);
|
||||||
|
|
||||||
static_assert((ground_level + 84 * m).point_for(ground_level).quantity_from_origin() == 84 * m);
|
static_assert((ground_level + 84 * m).point_for(ground_level).quantity_from_origin_ == 84 * m);
|
||||||
static_assert((mean_sea_level + 84 * m).point_for(ground_level).quantity_from_origin() == 42 * m);
|
static_assert((mean_sea_level + 84 * m).point_for(ground_level).quantity_from_origin_ == 42 * m);
|
||||||
static_assert((tower_peak + 42 * m).point_for(ground_level).quantity_from_origin() == 84 * m);
|
static_assert((tower_peak + 42 * m).point_for(ground_level).quantity_from_origin_ == 84 * m);
|
||||||
|
|
||||||
static_assert((tower_peak + 42 * m).point_for(tower_peak).quantity_from_origin() == 42 * m);
|
static_assert((tower_peak + 42 * m).point_for(tower_peak).quantity_from_origin_ == 42 * m);
|
||||||
static_assert((mean_sea_level + 42 * m).point_for(tower_peak).quantity_from_origin() == -42 * m);
|
static_assert((mean_sea_level + 42 * m).point_for(tower_peak).quantity_from_origin_ == -42 * m);
|
||||||
static_assert((ground_level + 84 * m).point_for(tower_peak).quantity_from_origin() == 42 * m);
|
static_assert((ground_level + 84 * m).point_for(tower_peak).quantity_from_origin_ == 42 * m);
|
||||||
|
|
||||||
static_assert(is_of_type<(ground_level + isq::height(short(42) * m)).point_for(mean_sea_level),
|
static_assert(is_of_type<(ground_level + isq::height(short(42) * m)).point_for(mean_sea_level),
|
||||||
quantity_point<isq::height[m], mean_sea_level, int>>);
|
quantity_point<isq::height[m], mean_sea_level, int>>);
|
||||||
@@ -576,15 +578,15 @@ static_assert(is_of_type<(ground_level + isq::height(short(42) * m)).point_for(m
|
|||||||
// converting to a different unit
|
// converting to a different unit
|
||||||
///////////////////////////////////
|
///////////////////////////////////
|
||||||
|
|
||||||
static_assert((mean_sea_level + 2. * km).in(km).quantity_from_origin().numerical_value() == 2.);
|
static_assert((mean_sea_level + 2. * km).in(km).quantity_from_origin_.numerical_value_ == 2.);
|
||||||
static_assert((mean_sea_level + 2. * km).in(m).quantity_from_origin().numerical_value() == 2000.);
|
static_assert((mean_sea_level + 2. * km).in(m).quantity_from_origin_.numerical_value_ == 2000.);
|
||||||
static_assert((mean_sea_level + 2000. * m).in(km).quantity_from_origin().numerical_value() == 2.);
|
static_assert((mean_sea_level + 2000. * m).in(km).quantity_from_origin_.numerical_value_ == 2.);
|
||||||
static_assert((ground_level + 2. * km).in(km).quantity_from_origin().numerical_value() == 2.);
|
static_assert((ground_level + 2. * km).in(km).quantity_from_origin_.numerical_value_ == 2.);
|
||||||
static_assert((ground_level + 2. * km).in(m).quantity_from_origin().numerical_value() == 2000.);
|
static_assert((ground_level + 2. * km).in(m).quantity_from_origin_.numerical_value_ == 2000.);
|
||||||
static_assert((ground_level + 2000. * m).in(km).quantity_from_origin().numerical_value() == 2.);
|
static_assert((ground_level + 2000. * m).in(km).quantity_from_origin_.numerical_value_ == 2.);
|
||||||
static_assert((tower_peak + 2. * km).in(km).quantity_from_origin().numerical_value() == 2.);
|
static_assert((tower_peak + 2. * km).in(km).quantity_from_origin_.numerical_value_ == 2.);
|
||||||
static_assert((tower_peak + 2. * km).in(m).quantity_from_origin().numerical_value() == 2000.);
|
static_assert((tower_peak + 2. * km).in(m).quantity_from_origin_.numerical_value_ == 2000.);
|
||||||
static_assert((tower_peak + 2000. * m).in(km).quantity_from_origin().numerical_value() == 2.);
|
static_assert((tower_peak + 2000. * m).in(km).quantity_from_origin_.numerical_value_ == 2.);
|
||||||
|
|
||||||
#if MP_UNITS_COMP_GCC != 10 || MP_UNITS_COMP_GCC_MINOR > 2
|
#if MP_UNITS_COMP_GCC != 10 || MP_UNITS_COMP_GCC_MINOR > 2
|
||||||
template<template<auto, auto, typename> typename QP>
|
template<template<auto, auto, typename> typename QP>
|
||||||
@@ -616,18 +618,18 @@ static_assert(([]() {
|
|||||||
quantity_point l1{mean_sea_level + 1 * m}, l2{mean_sea_level + 2 * m};
|
quantity_point l1{mean_sea_level + 1 * m}, l2{mean_sea_level + 2 * m};
|
||||||
return l2 = l1;
|
return l2 = l1;
|
||||||
}())
|
}())
|
||||||
.quantity_from_origin() == 1 * m);
|
.quantity_from_origin_ == 1 * m);
|
||||||
static_assert(([]() {
|
static_assert(([]() {
|
||||||
const quantity_point l1{mean_sea_level + 1 * m};
|
const quantity_point l1{mean_sea_level + 1 * m};
|
||||||
quantity_point l2{mean_sea_level + 2 * m};
|
quantity_point l2{mean_sea_level + 2 * m};
|
||||||
return l2 = l1;
|
return l2 = l1;
|
||||||
}())
|
}())
|
||||||
.quantity_from_origin() == 1 * m);
|
.quantity_from_origin_ == 1 * m);
|
||||||
static_assert(([]() {
|
static_assert(([]() {
|
||||||
quantity_point l1{mean_sea_level + 1 * m}, l2{mean_sea_level + 2 * m};
|
quantity_point l1{mean_sea_level + 1 * m}, l2{mean_sea_level + 2 * m};
|
||||||
return l2 = std::move(l1);
|
return l2 = std::move(l1);
|
||||||
}())
|
}())
|
||||||
.quantity_from_origin() == 1 * m);
|
.quantity_from_origin_ == 1 * m);
|
||||||
|
|
||||||
|
|
||||||
////////////////////
|
////////////////////
|
||||||
@@ -657,14 +659,14 @@ static_assert([](auto v) {
|
|||||||
////////////////////////
|
////////////////////////
|
||||||
|
|
||||||
// same type
|
// same type
|
||||||
static_assert((mean_sea_level + 1 * m += 1 * m).quantity_from_origin().numerical_value() == 2);
|
static_assert((mean_sea_level + 1 * m += 1 * m).quantity_from_origin_.numerical_value_ == 2);
|
||||||
static_assert((mean_sea_level + 2 * m -= 1 * m).quantity_from_origin().numerical_value() == 1);
|
static_assert((mean_sea_level + 2 * m -= 1 * m).quantity_from_origin_.numerical_value_ == 1);
|
||||||
|
|
||||||
// different types
|
// different types
|
||||||
static_assert((mean_sea_level + 2.5 * m += 3 * m).quantity_from_origin().numerical_value() == 5.5);
|
static_assert((mean_sea_level + 2.5 * m += 3 * m).quantity_from_origin_.numerical_value_ == 5.5);
|
||||||
static_assert((mean_sea_level + 123 * m += 1 * km).quantity_from_origin().numerical_value() == 1123);
|
static_assert((mean_sea_level + 123 * m += 1 * km).quantity_from_origin_.numerical_value_ == 1123);
|
||||||
static_assert((mean_sea_level + 5.5 * m -= 3 * m).quantity_from_origin().numerical_value() == 2.5);
|
static_assert((mean_sea_level + 5.5 * m -= 3 * m).quantity_from_origin_.numerical_value_ == 2.5);
|
||||||
static_assert((mean_sea_level + 1123 * m -= 1 * km).quantity_from_origin().numerical_value() == 123);
|
static_assert((mean_sea_level + 1123 * m -= 1 * km).quantity_from_origin_.numerical_value_ == 123);
|
||||||
|
|
||||||
|
|
||||||
template<template<auto, auto, typename> typename QP>
|
template<template<auto, auto, typename> typename QP>
|
||||||
@@ -935,30 +937,25 @@ static_assert(is_of_type<(1 * m + tower_peak) - (1 * m + other_ground_level), qu
|
|||||||
|
|
||||||
|
|
||||||
// check for integral types promotion
|
// check for integral types promotion
|
||||||
|
static_assert(is_same_v<decltype(((mean_sea_level + std::uint8_t(0) * m) + std::uint8_t(0) * m)
|
||||||
|
.quantity_from_origin_.numerical_value_),
|
||||||
|
int>);
|
||||||
|
static_assert(is_same_v<decltype((std::uint8_t(0) * m + (mean_sea_level + std::uint8_t(0) * m))
|
||||||
|
.quantity_from_origin_.numerical_value_),
|
||||||
|
int>);
|
||||||
|
static_assert(is_same_v<decltype(((mean_sea_level + std::uint8_t(0) * m) - std::uint8_t(0) * m)
|
||||||
|
.quantity_from_origin_.numerical_value_),
|
||||||
|
int>);
|
||||||
static_assert(
|
static_assert(
|
||||||
is_same_v<
|
is_same_v<
|
||||||
decltype(((mean_sea_level + std::uint8_t(0) * m) + std::uint8_t(0) * m).quantity_from_origin().numerical_value()),
|
decltype(((mean_sea_level + std::uint8_t(0) * m) - (mean_sea_level + std::uint8_t(0) * m)).numerical_value_), int>);
|
||||||
int&&>);
|
static_assert(((mean_sea_level + std::uint8_t(128) * m) + std::uint8_t(128) * m)
|
||||||
static_assert(
|
.quantity_from_origin_.numerical_value_ == std::uint8_t(128) + std::uint8_t(128));
|
||||||
is_same_v<
|
static_assert((std::uint8_t(128) * m + (mean_sea_level + std::uint8_t(128) * m))
|
||||||
decltype((std::uint8_t(0) * m + (mean_sea_level + std::uint8_t(0) * m)).quantity_from_origin().numerical_value()),
|
.quantity_from_origin_.numerical_value_ == std::uint8_t(128) + std::uint8_t(128));
|
||||||
int&&>);
|
static_assert(((mean_sea_level + std::uint8_t(0) * m) - std::uint8_t(1) * m).quantity_from_origin_.numerical_value_ ==
|
||||||
static_assert(
|
|
||||||
is_same_v<
|
|
||||||
decltype(((mean_sea_level + std::uint8_t(0) * m) - std::uint8_t(0) * m).quantity_from_origin().numerical_value()),
|
|
||||||
int&&>);
|
|
||||||
static_assert(is_same_v<decltype(((mean_sea_level + std::uint8_t(0) * m) - (mean_sea_level + std::uint8_t(0) * m))
|
|
||||||
.numerical_value()),
|
|
||||||
int&&>);
|
|
||||||
static_assert(
|
|
||||||
((mean_sea_level + std::uint8_t(128) * m) + std::uint8_t(128) * m).quantity_from_origin().numerical_value() ==
|
|
||||||
std::uint8_t(128) + std::uint8_t(128));
|
|
||||||
static_assert(
|
|
||||||
(std::uint8_t(128) * m + (mean_sea_level + std::uint8_t(128) * m)).quantity_from_origin().numerical_value() ==
|
|
||||||
std::uint8_t(128) + std::uint8_t(128));
|
|
||||||
static_assert(((mean_sea_level + std::uint8_t(0) * m) - std::uint8_t(1) * m).quantity_from_origin().numerical_value() ==
|
|
||||||
std::uint8_t(0) - std::uint8_t(1));
|
std::uint8_t(0) - std::uint8_t(1));
|
||||||
static_assert(((mean_sea_level + std::uint8_t(0) * m) - (mean_sea_level + std::uint8_t(1) * m)).numerical_value() ==
|
static_assert(((mean_sea_level + std::uint8_t(0) * m) - (mean_sea_level + std::uint8_t(1) * m)).numerical_value_ ==
|
||||||
std::uint8_t(0) - std::uint8_t(1));
|
std::uint8_t(0) - std::uint8_t(1));
|
||||||
|
|
||||||
// different representation types
|
// different representation types
|
||||||
@@ -1013,39 +1010,39 @@ static_assert(is_of_type<(mean_sea_level + 1 * km) - (mean_sea_level + 1. * m),
|
|||||||
static_assert(is_of_type<(mean_sea_level + 1. * km) - (mean_sea_level + 1. * m), quantity<si::metre, double>>);
|
static_assert(is_of_type<(mean_sea_level + 1. * km) - (mean_sea_level + 1. * m), quantity<si::metre, double>>);
|
||||||
|
|
||||||
|
|
||||||
static_assert(((mean_sea_level + 1 * m) + 1 * m).quantity_from_origin().numerical_value() == 2);
|
static_assert(((mean_sea_level + 1 * m) + 1 * m).quantity_from_origin_.numerical_value_ == 2);
|
||||||
static_assert((1 * m + (mean_sea_level + 1 * m)).quantity_from_origin().numerical_value() == 2);
|
static_assert((1 * m + (mean_sea_level + 1 * m)).quantity_from_origin_.numerical_value_ == 2);
|
||||||
static_assert(((mean_sea_level + 1 * m) + 1 * km).quantity_from_origin().numerical_value() == 1001);
|
static_assert(((mean_sea_level + 1 * m) + 1 * km).quantity_from_origin_.numerical_value_ == 1001);
|
||||||
static_assert((1 * m + (mean_sea_level + 1 * km)).quantity_from_origin().numerical_value() == 1001);
|
static_assert((1 * m + (mean_sea_level + 1 * km)).quantity_from_origin_.numerical_value_ == 1001);
|
||||||
static_assert(((mean_sea_level + 1 * km) + 1 * m).quantity_from_origin().numerical_value() == 1001);
|
static_assert(((mean_sea_level + 1 * km) + 1 * m).quantity_from_origin_.numerical_value_ == 1001);
|
||||||
static_assert((1 * km + (mean_sea_level + 1 * m)).quantity_from_origin().numerical_value() == 1001);
|
static_assert((1 * km + (mean_sea_level + 1 * m)).quantity_from_origin_.numerical_value_ == 1001);
|
||||||
static_assert(((mean_sea_level + 2 * m) - 1 * m).quantity_from_origin().numerical_value() == 1);
|
static_assert(((mean_sea_level + 2 * m) - 1 * m).quantity_from_origin_.numerical_value_ == 1);
|
||||||
static_assert(((mean_sea_level + 1 * km) - 1 * m).quantity_from_origin().numerical_value() == 999);
|
static_assert(((mean_sea_level + 1 * km) - 1 * m).quantity_from_origin_.numerical_value_ == 999);
|
||||||
|
|
||||||
static_assert(((mean_sea_level + 1.5 * m) + 1 * m).quantity_from_origin().numerical_value() == 2.5);
|
static_assert(((mean_sea_level + 1.5 * m) + 1 * m).quantity_from_origin_.numerical_value_ == 2.5);
|
||||||
static_assert((1.5 * m + (mean_sea_level + 1 * m)).quantity_from_origin().numerical_value() == 2.5);
|
static_assert((1.5 * m + (mean_sea_level + 1 * m)).quantity_from_origin_.numerical_value_ == 2.5);
|
||||||
static_assert(((mean_sea_level + 1.5 * m) + 1 * km).quantity_from_origin().numerical_value() == 1001.5);
|
static_assert(((mean_sea_level + 1.5 * m) + 1 * km).quantity_from_origin_.numerical_value_ == 1001.5);
|
||||||
static_assert((1.5 * m + (mean_sea_level + 1 * km)).quantity_from_origin().numerical_value() == 1001.5);
|
static_assert((1.5 * m + (mean_sea_level + 1 * km)).quantity_from_origin_.numerical_value_ == 1001.5);
|
||||||
static_assert(((mean_sea_level + 1.5 * km) + 1 * m).quantity_from_origin().numerical_value() == 1501);
|
static_assert(((mean_sea_level + 1.5 * km) + 1 * m).quantity_from_origin_.numerical_value_ == 1501);
|
||||||
static_assert((1.5 * km + (mean_sea_level + 1 * m)).quantity_from_origin().numerical_value() == 1501);
|
static_assert((1.5 * km + (mean_sea_level + 1 * m)).quantity_from_origin_.numerical_value_ == 1501);
|
||||||
static_assert(((mean_sea_level + 2.5 * m) - 1 * m).quantity_from_origin().numerical_value() == 1.5);
|
static_assert(((mean_sea_level + 2.5 * m) - 1 * m).quantity_from_origin_.numerical_value_ == 1.5);
|
||||||
static_assert(((mean_sea_level + 1.5 * km) - 1 * m).quantity_from_origin().numerical_value() == 1499);
|
static_assert(((mean_sea_level + 1.5 * km) - 1 * m).quantity_from_origin_.numerical_value_ == 1499);
|
||||||
|
|
||||||
static_assert(((mean_sea_level + 1 * m) + 1.5 * m).quantity_from_origin().numerical_value() == 2.5);
|
static_assert(((mean_sea_level + 1 * m) + 1.5 * m).quantity_from_origin_.numerical_value_ == 2.5);
|
||||||
static_assert((1 * m + (mean_sea_level + 1.5 * m)).quantity_from_origin().numerical_value() == 2.5);
|
static_assert((1 * m + (mean_sea_level + 1.5 * m)).quantity_from_origin_.numerical_value_ == 2.5);
|
||||||
static_assert(((mean_sea_level + 1 * m) + 1.5 * km).quantity_from_origin().numerical_value() == 1501);
|
static_assert(((mean_sea_level + 1 * m) + 1.5 * km).quantity_from_origin_.numerical_value_ == 1501);
|
||||||
static_assert((1 * m + (mean_sea_level + 1.5 * km)).quantity_from_origin().numerical_value() == 1501);
|
static_assert((1 * m + (mean_sea_level + 1.5 * km)).quantity_from_origin_.numerical_value_ == 1501);
|
||||||
static_assert(((mean_sea_level + 1 * km) + 1.5 * m).quantity_from_origin().numerical_value() == 1001.5);
|
static_assert(((mean_sea_level + 1 * km) + 1.5 * m).quantity_from_origin_.numerical_value_ == 1001.5);
|
||||||
static_assert((1 * km + (mean_sea_level + 1.5 * m)).quantity_from_origin().numerical_value() == 1001.5);
|
static_assert((1 * km + (mean_sea_level + 1.5 * m)).quantity_from_origin_.numerical_value_ == 1001.5);
|
||||||
static_assert(((mean_sea_level + 2 * m) - 1.5 * m).quantity_from_origin().numerical_value() == 0.5);
|
static_assert(((mean_sea_level + 2 * m) - 1.5 * m).quantity_from_origin_.numerical_value_ == 0.5);
|
||||||
static_assert(((mean_sea_level + 1 * km) - 1.5 * m).quantity_from_origin().numerical_value() == 998.5);
|
static_assert(((mean_sea_level + 1 * km) - 1.5 * m).quantity_from_origin_.numerical_value_ == 998.5);
|
||||||
|
|
||||||
static_assert(((mean_sea_level + 2 * m) - (mean_sea_level + 1 * m)).numerical_value() == 1);
|
static_assert(((mean_sea_level + 2 * m) - (mean_sea_level + 1 * m)).numerical_value_ == 1);
|
||||||
static_assert(((mean_sea_level + 1 * km) - (mean_sea_level + 1 * m)).numerical_value() == 999);
|
static_assert(((mean_sea_level + 1 * km) - (mean_sea_level + 1 * m)).numerical_value_ == 999);
|
||||||
static_assert(((mean_sea_level + 2.5 * m) - (mean_sea_level + 1 * m)).numerical_value() == 1.5);
|
static_assert(((mean_sea_level + 2.5 * m) - (mean_sea_level + 1 * m)).numerical_value_ == 1.5);
|
||||||
static_assert(((mean_sea_level + 1.5 * km) - (mean_sea_level + 1 * m)).numerical_value() == 1499);
|
static_assert(((mean_sea_level + 1.5 * km) - (mean_sea_level + 1 * m)).numerical_value_ == 1499);
|
||||||
static_assert(((mean_sea_level + 2 * m) - (mean_sea_level + 1.5 * m)).numerical_value() == 0.5);
|
static_assert(((mean_sea_level + 2 * m) - (mean_sea_level + 1.5 * m)).numerical_value_ == 0.5);
|
||||||
static_assert(((mean_sea_level + 1 * km) - (mean_sea_level + 1.5 * m)).numerical_value() == 998.5);
|
static_assert(((mean_sea_level + 1 * km) - (mean_sea_level + 1.5 * m)).numerical_value_ == 998.5);
|
||||||
|
|
||||||
static_assert((mean_sea_level + 42 * m) - (ground_level + 42 * m) == -42 * m);
|
static_assert((mean_sea_level + 42 * m) - (ground_level + 42 * m) == -42 * m);
|
||||||
static_assert((ground_level + 42 * m) - (mean_sea_level + 42 * m) == 42 * m);
|
static_assert((ground_level + 42 * m) - (mean_sea_level + 42 * m) == 42 * m);
|
||||||
@@ -1058,15 +1055,15 @@ static_assert((ground_level + 42 * m) - (other_ground_level + 42 * m) == -81 * m
|
|||||||
static_assert((other_ground_level + 42 * m) - (tower_peak + 42 * m) == 39 * m);
|
static_assert((other_ground_level + 42 * m) - (tower_peak + 42 * m) == 39 * m);
|
||||||
static_assert((tower_peak + 42 * m) - (other_ground_level + 42 * m) == -39 * m);
|
static_assert((tower_peak + 42 * m) - (other_ground_level + 42 * m) == -39 * m);
|
||||||
|
|
||||||
static_assert((mean_sea_level + 42 * m).quantity_from_origin() == 42 * m);
|
static_assert((mean_sea_level + 42 * m).quantity_from_origin_ == 42 * m);
|
||||||
static_assert((42 * m + mean_sea_level).quantity_from_origin() == 42 * m);
|
static_assert((42 * m + mean_sea_level).quantity_from_origin_ == 42 * m);
|
||||||
static_assert((mean_sea_level - 42 * m).quantity_from_origin() == -42 * m);
|
static_assert((mean_sea_level - 42 * m).quantity_from_origin_ == -42 * m);
|
||||||
static_assert((ground_level + 42 * m).quantity_from_origin() == 42 * m);
|
static_assert((ground_level + 42 * m).quantity_from_origin_ == 42 * m);
|
||||||
static_assert((42 * m + ground_level).quantity_from_origin() == 42 * m);
|
static_assert((42 * m + ground_level).quantity_from_origin_ == 42 * m);
|
||||||
static_assert((ground_level - 42 * m).quantity_from_origin() == -42 * m);
|
static_assert((ground_level - 42 * m).quantity_from_origin_ == -42 * m);
|
||||||
static_assert((tower_peak + 42 * m).quantity_from_origin() == 42 * m);
|
static_assert((tower_peak + 42 * m).quantity_from_origin_ == 42 * m);
|
||||||
static_assert((42 * m + tower_peak).quantity_from_origin() == 42 * m);
|
static_assert((42 * m + tower_peak).quantity_from_origin_ == 42 * m);
|
||||||
static_assert((tower_peak - 42 * m).quantity_from_origin() == -42 * m);
|
static_assert((tower_peak - 42 * m).quantity_from_origin_ == -42 * m);
|
||||||
|
|
||||||
static_assert((mean_sea_level + 42 * m) - ground_level == 0 * m);
|
static_assert((mean_sea_level + 42 * m) - ground_level == 0 * m);
|
||||||
static_assert((ground_level + 42 * m) - mean_sea_level == 84 * m);
|
static_assert((ground_level + 42 * m) - mean_sea_level == 84 * m);
|
||||||
@@ -1079,6 +1076,17 @@ static_assert((ground_level + 42 * m) - other_ground_level == -39 * m);
|
|||||||
static_assert((other_ground_level + 42 * m) - tower_peak == 81 * m);
|
static_assert((other_ground_level + 42 * m) - tower_peak == 81 * m);
|
||||||
static_assert((tower_peak + 42 * m) - other_ground_level == 3 * m);
|
static_assert((tower_peak + 42 * m) - other_ground_level == 3 * m);
|
||||||
|
|
||||||
|
static_assert((mean_sea_level + 42 * m).quantity_from(ground_level) == 0 * m);
|
||||||
|
static_assert((ground_level + 42 * m).quantity_from(mean_sea_level) == 84 * m);
|
||||||
|
static_assert((tower_peak + 42 * m).quantity_from(ground_level) == 84 * m);
|
||||||
|
static_assert((ground_level + 42 * m).quantity_from(tower_peak) == 0 * m);
|
||||||
|
static_assert((tower_peak + 42 * m).quantity_from(mean_sea_level) == 126 * m);
|
||||||
|
static_assert((mean_sea_level + 42 * m).quantity_from(tower_peak) == -42 * m);
|
||||||
|
static_assert((other_ground_level + 42 * m).quantity_from(ground_level) == 123 * m);
|
||||||
|
static_assert((ground_level + 42 * m).quantity_from(other_ground_level) == -39 * m);
|
||||||
|
static_assert((other_ground_level + 42 * m).quantity_from(tower_peak) == 81 * m);
|
||||||
|
static_assert((tower_peak + 42 * m).quantity_from(other_ground_level) == 3 * m);
|
||||||
|
|
||||||
static_assert(mean_sea_level - (ground_level + 42 * m) == -84 * m);
|
static_assert(mean_sea_level - (ground_level + 42 * m) == -84 * m);
|
||||||
static_assert(ground_level - (mean_sea_level + 42 * m) == 0 * m);
|
static_assert(ground_level - (mean_sea_level + 42 * m) == 0 * m);
|
||||||
static_assert(tower_peak - (ground_level + 42 * m) == 0 * m);
|
static_assert(tower_peak - (ground_level + 42 * m) == 0 * m);
|
||||||
@@ -1106,17 +1114,17 @@ inline constexpr struct zero_m_per_s : absolute_point_origin<kind_of<isq::speed>
|
|||||||
|
|
||||||
// commutativity and associativity
|
// commutativity and associativity
|
||||||
static_assert(((zero_m_per_s + 10 * isq::height[m] / (2 * isq::time[s])) + 5 * isq::speed[m / s])
|
static_assert(((zero_m_per_s + 10 * isq::height[m] / (2 * isq::time[s])) + 5 * isq::speed[m / s])
|
||||||
.quantity_from_origin() == 10 * isq::speed[m / s]);
|
.quantity_from_origin_ == 10 * isq::speed[m / s]);
|
||||||
static_assert((10 * isq::height[m] / (2 * isq::time[s]) + (zero_m_per_s + 5 * isq::speed[m / s]))
|
static_assert((10 * isq::height[m] / (2 * isq::time[s]) + (zero_m_per_s + 5 * isq::speed[m / s]))
|
||||||
.quantity_from_origin() == 10 * isq::speed[m / s]);
|
.quantity_from_origin_ == 10 * isq::speed[m / s]);
|
||||||
static_assert(((zero_m_per_s + 5 * isq::speed[m / s]) + 10 * isq::height[m] / (2 * isq::time[s]))
|
static_assert(((zero_m_per_s + 5 * isq::speed[m / s]) + 10 * isq::height[m] / (2 * isq::time[s]))
|
||||||
.quantity_from_origin() == 10 * isq::speed[m / s]);
|
.quantity_from_origin_ == 10 * isq::speed[m / s]);
|
||||||
static_assert((5 * isq::speed[m / s] + (zero_m_per_s + 10 * isq::height[m] / (2 * isq::time[s])))
|
static_assert((5 * isq::speed[m / s] + (zero_m_per_s + 10 * isq::height[m] / (2 * isq::time[s])))
|
||||||
.quantity_from_origin() == 10 * isq::speed[m / s]);
|
.quantity_from_origin_ == 10 * isq::speed[m / s]);
|
||||||
static_assert(((zero_m_per_s + 10 * isq::height[m] / (2 * isq::time[s])) - 5 * isq::speed[m / s])
|
static_assert(((zero_m_per_s + 10 * isq::height[m] / (2 * isq::time[s])) - 5 * isq::speed[m / s])
|
||||||
.quantity_from_origin() == 0 * isq::speed[m / s]);
|
.quantity_from_origin_ == 0 * isq::speed[m / s]);
|
||||||
static_assert(((zero_m_per_s + 5 * isq::speed[m / s]) - 10 * isq::height[m] / (2 * isq::time[s]))
|
static_assert(((zero_m_per_s + 5 * isq::speed[m / s]) - 10 * isq::height[m] / (2 * isq::time[s]))
|
||||||
.quantity_from_origin() == 0 * isq::speed[m / s]);
|
.quantity_from_origin_ == 0 * isq::speed[m / s]);
|
||||||
static_assert((zero_m_per_s + 10 * isq::height[m] / (2 * isq::time[s])) - (zero_m_per_s + 5 * isq::speed[m / s]) ==
|
static_assert((zero_m_per_s + 10 * isq::height[m] / (2 * isq::time[s])) - (zero_m_per_s + 5 * isq::speed[m / s]) ==
|
||||||
0 * isq::speed[m / s]);
|
0 * isq::speed[m / s]);
|
||||||
static_assert((zero_m_per_s + 5 * isq::speed[m / s]) - (zero_m_per_s + 10 * isq::height[m] / (2 * isq::time[s])) ==
|
static_assert((zero_m_per_s + 5 * isq::speed[m / s]) - (zero_m_per_s + 10 * isq::height[m] / (2 * isq::time[s])) ==
|
||||||
@@ -1148,17 +1156,17 @@ static_assert(
|
|||||||
inline constexpr struct zero_Hz : absolute_point_origin<kind_of<isq::frequency>> {
|
inline constexpr struct zero_Hz : absolute_point_origin<kind_of<isq::frequency>> {
|
||||||
} zero_Hz;
|
} zero_Hz;
|
||||||
|
|
||||||
static_assert(((zero_Hz + 10 / (2 * isq::period_duration[s])) + 5 * isq::frequency[Hz]).quantity_from_origin() ==
|
static_assert(((zero_Hz + 10 / (2 * isq::period_duration[s])) + 5 * isq::frequency[Hz]).quantity_from_origin_ ==
|
||||||
10 * isq::frequency[Hz]);
|
10 * isq::frequency[Hz]);
|
||||||
static_assert((10 / (2 * isq::period_duration[s]) + (zero_Hz + 5 * isq::frequency[Hz])).quantity_from_origin() ==
|
static_assert((10 / (2 * isq::period_duration[s]) + (zero_Hz + 5 * isq::frequency[Hz])).quantity_from_origin_ ==
|
||||||
10 * isq::frequency[Hz]);
|
10 * isq::frequency[Hz]);
|
||||||
static_assert(((zero_Hz + 5 * isq::frequency[Hz]) + 10 / (2 * isq::period_duration[s])).quantity_from_origin() ==
|
static_assert(((zero_Hz + 5 * isq::frequency[Hz]) + 10 / (2 * isq::period_duration[s])).quantity_from_origin_ ==
|
||||||
10 * isq::frequency[Hz]);
|
10 * isq::frequency[Hz]);
|
||||||
static_assert((5 * isq::frequency[Hz] + (zero_Hz + 10 / (2 * isq::period_duration[s]))).quantity_from_origin() ==
|
static_assert((5 * isq::frequency[Hz] + (zero_Hz + 10 / (2 * isq::period_duration[s]))).quantity_from_origin_ ==
|
||||||
10 * isq::frequency[Hz]);
|
10 * isq::frequency[Hz]);
|
||||||
static_assert(((zero_Hz + 10 / (2 * isq::period_duration[s])) - 5 * isq::frequency[Hz]).quantity_from_origin() ==
|
static_assert(((zero_Hz + 10 / (2 * isq::period_duration[s])) - 5 * isq::frequency[Hz]).quantity_from_origin_ ==
|
||||||
0 * isq::frequency[Hz]);
|
0 * isq::frequency[Hz]);
|
||||||
static_assert(((zero_Hz + 5 * isq::frequency[Hz]) - 10 / (2 * isq::period_duration[s])).quantity_from_origin() ==
|
static_assert(((zero_Hz + 5 * isq::frequency[Hz]) - 10 / (2 * isq::period_duration[s])).quantity_from_origin_ ==
|
||||||
0 * isq::frequency[Hz]);
|
0 * isq::frequency[Hz]);
|
||||||
static_assert((zero_Hz + 10 / (2 * isq::period_duration[s])) - (zero_Hz + 5 * isq::frequency[Hz]) ==
|
static_assert((zero_Hz + 10 / (2 * isq::period_duration[s])) - (zero_Hz + 5 * isq::frequency[Hz]) ==
|
||||||
0 * isq::frequency[Hz]);
|
0 * isq::frequency[Hz]);
|
||||||
|
@@ -112,14 +112,14 @@ static_assert(is_same_v<quantity<isq::length[m], int>::rep, int>);
|
|||||||
// static member functions
|
// static member functions
|
||||||
////////////////////////////
|
////////////////////////////
|
||||||
|
|
||||||
static_assert(quantity<isq::length[m], int>::zero().numerical_value() == 0);
|
static_assert(quantity<isq::length[m], int>::zero().numerical_value_ == 0);
|
||||||
static_assert(quantity<isq::length[m], int>::one().numerical_value() == 1);
|
static_assert(quantity<isq::length[m], int>::one().numerical_value_ == 1);
|
||||||
static_assert(quantity<isq::length[m], int>::min().numerical_value() == std::numeric_limits<int>::lowest());
|
static_assert(quantity<isq::length[m], int>::min().numerical_value_ == std::numeric_limits<int>::lowest());
|
||||||
static_assert(quantity<isq::length[m], int>::max().numerical_value() == std::numeric_limits<int>::max());
|
static_assert(quantity<isq::length[m], int>::max().numerical_value_ == std::numeric_limits<int>::max());
|
||||||
static_assert(quantity<isq::length[m], double>::zero().numerical_value() == 0.0);
|
static_assert(quantity<isq::length[m], double>::zero().numerical_value_ == 0.0);
|
||||||
static_assert(quantity<isq::length[m], double>::one().numerical_value() == 1.0);
|
static_assert(quantity<isq::length[m], double>::one().numerical_value_ == 1.0);
|
||||||
static_assert(quantity<isq::length[m], double>::min().numerical_value() == std::numeric_limits<double>::lowest());
|
static_assert(quantity<isq::length[m], double>::min().numerical_value_ == std::numeric_limits<double>::lowest());
|
||||||
static_assert(quantity<isq::length[m], double>::max().numerical_value() == std::numeric_limits<double>::max());
|
static_assert(quantity<isq::length[m], double>::max().numerical_value_ == std::numeric_limits<double>::max());
|
||||||
|
|
||||||
|
|
||||||
//////////////////////////////
|
//////////////////////////////
|
||||||
@@ -190,10 +190,10 @@ static_assert(std::convertible_to<quantity<isq::length[m], int>, quantity<isq::l
|
|||||||
// obtaining a number
|
// obtaining a number
|
||||||
///////////////////////
|
///////////////////////
|
||||||
|
|
||||||
static_assert(quantity<isq::length[m], int>(123 * m).numerical_value() == 123);
|
static_assert(quantity<isq::length[m], int>(123 * m).numerical_value_ == 123);
|
||||||
static_assert(quantity<isq::length[m], int>(2 * km).numerical_value() == 2000);
|
static_assert(quantity<isq::length[m], int>(2 * km).numerical_value_ == 2000);
|
||||||
static_assert(quantity<isq::length[km], int>(2 * km).numerical_value() == 2);
|
static_assert(quantity<isq::length[km], int>(2 * km).numerical_value_ == 2);
|
||||||
static_assert(quantity<isq::length[km]>(1500 * m).numerical_value() == 1.5);
|
static_assert(quantity<isq::length[km]>(1500 * m).numerical_value_ == 1.5);
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////
|
///////////////////////////////////
|
||||||
@@ -204,11 +204,11 @@ static_assert(is_of_type<(2. * km).in(m), quantity<si::metre>>);
|
|||||||
static_assert(is_of_type<isq::length(2. * km).in(m), quantity<isq::length[m]>>);
|
static_assert(is_of_type<isq::length(2. * km).in(m), quantity<isq::length[m]>>);
|
||||||
static_assert(is_of_type<isq::height(2. * km).in(m), quantity<isq::height[m]>>);
|
static_assert(is_of_type<isq::height(2. * km).in(m), quantity<isq::height[m]>>);
|
||||||
|
|
||||||
static_assert(quantity<isq::length[km]>(2. * km).in(km).numerical_value() == 2.);
|
static_assert(quantity<isq::length[km]>(2. * km).in(km).numerical_value_ == 2.);
|
||||||
static_assert(quantity<isq::length[km]>(2. * km).in(m).numerical_value() == 2000.);
|
static_assert(quantity<isq::length[km]>(2. * km).in(m).numerical_value_ == 2000.);
|
||||||
static_assert(quantity<isq::length[m]>(2000. * m).in(km).numerical_value() == 2.);
|
static_assert(quantity<isq::length[m]>(2000. * m).in(km).numerical_value_ == 2.);
|
||||||
static_assert(quantity<isq::length[km], int>(2 * km).in(km).numerical_value() == 2);
|
static_assert(quantity<isq::length[km], int>(2 * km).in(km).numerical_value_ == 2);
|
||||||
static_assert(quantity<isq::length[km], int>(2 * km).in(m).numerical_value() == 2000);
|
static_assert(quantity<isq::length[km], int>(2 * km).in(m).numerical_value_ == 2000);
|
||||||
|
|
||||||
#if MP_UNITS_COMP_GCC != 10 || MP_UNITS_COMP_GCC_MINOR > 2
|
#if MP_UNITS_COMP_GCC != 10 || MP_UNITS_COMP_GCC_MINOR > 2
|
||||||
template<template<auto, typename> typename Q>
|
template<template<auto, typename> typename Q>
|
||||||
@@ -308,28 +308,28 @@ static_assert([] {
|
|||||||
auto l1(1 * m), l2(2 * m);
|
auto l1(1 * m), l2(2 * m);
|
||||||
return l2 = l1;
|
return l2 = l1;
|
||||||
}()
|
}()
|
||||||
.numerical_value() == 1);
|
.numerical_value_ == 1);
|
||||||
static_assert([] {
|
static_assert([] {
|
||||||
const auto l1(1 * m);
|
const auto l1(1 * m);
|
||||||
auto l2(2 * m);
|
auto l2(2 * m);
|
||||||
return l2 = l1;
|
return l2 = l1;
|
||||||
}()
|
}()
|
||||||
.numerical_value() == 1);
|
.numerical_value_ == 1);
|
||||||
static_assert([]() {
|
static_assert([]() {
|
||||||
auto l1(1 * m), l2(2 * m);
|
auto l1(1 * m), l2(2 * m);
|
||||||
return l2 = std::move(l1);
|
return l2 = std::move(l1);
|
||||||
}()
|
}()
|
||||||
.numerical_value() == 1);
|
.numerical_value_ == 1);
|
||||||
|
|
||||||
|
|
||||||
////////////////////
|
////////////////////
|
||||||
// unary operators
|
// unary operators
|
||||||
////////////////////
|
////////////////////
|
||||||
|
|
||||||
static_assert((+123 * m).numerical_value() == 123);
|
static_assert((+123 * m).numerical_value_ == 123);
|
||||||
static_assert((-123 * m).numerical_value() == -123);
|
static_assert((-123 * m).numerical_value_ == -123);
|
||||||
static_assert((+(-123 * m)).numerical_value() == -123);
|
static_assert((+(-123 * m)).numerical_value_ == -123);
|
||||||
static_assert((-(-123 * m)).numerical_value() == 123);
|
static_assert((-(-123 * m)).numerical_value_ == 123);
|
||||||
|
|
||||||
static_assert([](auto v) {
|
static_assert([](auto v) {
|
||||||
auto vv = v++;
|
auto vv = v++;
|
||||||
@@ -348,7 +348,7 @@ static_assert([](auto v) {
|
|||||||
return std::pair(v, vv);
|
return std::pair(v, vv);
|
||||||
}(123 * m) == std::pair(122 * m, 122 * m));
|
}(123 * m) == std::pair(122 * m, 122 * m));
|
||||||
|
|
||||||
static_assert(is_same_v<decltype((+(short{0} * m)).numerical_value()), int&&>);
|
static_assert(is_same_v<decltype((+(short{0} * m)).numerical_value_), int>);
|
||||||
|
|
||||||
|
|
||||||
////////////////////////
|
////////////////////////
|
||||||
@@ -356,29 +356,31 @@ static_assert(is_same_v<decltype((+(short{0} * m)).numerical_value()), int&&>);
|
|||||||
////////////////////////
|
////////////////////////
|
||||||
|
|
||||||
// same type
|
// same type
|
||||||
static_assert((1 * m += 1 * m).numerical_value() == 2);
|
static_assert((1 * m += 1 * m).numerical_value_ == 2);
|
||||||
static_assert((2 * m -= 1 * m).numerical_value() == 1);
|
static_assert((2 * m -= 1 * m).numerical_value_ == 1);
|
||||||
static_assert((1 * m *= 2).numerical_value() == 2);
|
static_assert((1 * m *= 2).numerical_value_ == 2);
|
||||||
static_assert((2 * m /= 2).numerical_value() == 1);
|
static_assert((2 * m /= 2).numerical_value_ == 1);
|
||||||
static_assert((1 * m *= 2 * one).numerical_value() == 2);
|
static_assert((1 * m *= 2 * one).numerical_value_ == 2);
|
||||||
static_assert((2 * m /= 2 * one).numerical_value() == 1);
|
static_assert((2 * m /= 2 * one).numerical_value_ == 1);
|
||||||
static_assert((7 * m %= 2 * m).numerical_value() == 1);
|
static_assert((7 * m %= 2 * m).numerical_value_ == 1);
|
||||||
|
|
||||||
// different types
|
// different types
|
||||||
static_assert((2.5 * m += 3 * m).numerical_value() == 5.5);
|
static_assert((2.5 * m += 3 * m).numerical_value_ == 5.5);
|
||||||
static_assert((123 * m += 1 * km).numerical_value() == 1123);
|
static_assert((123 * m += 1 * km).numerical_value_ == 1123);
|
||||||
static_assert((5.5 * m -= 3 * m).numerical_value() == 2.5);
|
static_assert((5.5 * m -= 3 * m).numerical_value_ == 2.5);
|
||||||
static_assert((1123 * m -= 1 * km).numerical_value() == 123);
|
static_assert((1123 * m -= 1 * km).numerical_value_ == 123);
|
||||||
static_assert((2.5 * m *= 3).numerical_value() == 7.5);
|
static_assert((2.5 * m *= 3).numerical_value_ == 7.5);
|
||||||
static_assert((7.5 * m /= 3).numerical_value() == 2.5);
|
static_assert((7.5 * m /= 3).numerical_value_ == 2.5);
|
||||||
static_assert((2.5 * m *= 3 * one).numerical_value() == 7.5);
|
static_assert((2.5 * m *= 3 * one).numerical_value_ == 7.5);
|
||||||
static_assert((7.5 * m /= 3 * one).numerical_value() == 2.5);
|
static_assert((7.5 * m /= 3 * one).numerical_value_ == 2.5);
|
||||||
static_assert((3500 * m %= 1 * km).numerical_value() == 500);
|
static_assert((3500 * m %= 1 * km).numerical_value_ == 500);
|
||||||
|
|
||||||
// static_assert((std::uint8_t(255) * m %= 256 * m).numerical_value() != [] { std::uint8_t ui(255); return ui %= 256;
|
// static_assert((std::uint8_t(255) * m %= 256 * m).numerical_value_ == [] {
|
||||||
|
// std::uint8_t ui(255);
|
||||||
|
// return ui %= 256;
|
||||||
// }()); // UB
|
// }()); // UB
|
||||||
// TODO: Fix
|
// TODO: Fix
|
||||||
static_assert((std::uint8_t(255) * m %= 257 * m).numerical_value() != [] {
|
static_assert((std::uint8_t(255) * m %= 257 * m).numerical_value_ != [] {
|
||||||
std::uint8_t ui(255);
|
std::uint8_t ui(255);
|
||||||
return ui %= 257;
|
return ui %= 257;
|
||||||
}());
|
}());
|
||||||
@@ -388,10 +390,10 @@ static_assert((std::uint8_t(255) * m %= 257 * m).numerical_value() != [] {
|
|||||||
#ifndef MP_UNITS_COMP_MSVC
|
#ifndef MP_UNITS_COMP_MSVC
|
||||||
// next two lines trigger conversions warnings
|
// next two lines trigger conversions warnings
|
||||||
// (warning disabled in CMake for this file)
|
// (warning disabled in CMake for this file)
|
||||||
static_assert((22 * m *= 33.33).numerical_value() == 733);
|
static_assert((22 * m *= 33.33).numerical_value_ == 733);
|
||||||
static_assert((22 * m /= 3.33).numerical_value() == 6);
|
static_assert((22 * m /= 3.33).numerical_value_ == 6);
|
||||||
static_assert((22 * m *= 33.33 * one).numerical_value() == 733);
|
static_assert((22 * m *= 33.33 * one).numerical_value_ == 733);
|
||||||
static_assert((22 * m /= 3.33 * one).numerical_value() == 6);
|
static_assert((22 * m /= 3.33 * one).numerical_value_ == 6);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
template<template<auto, typename> typename Q>
|
template<template<auto, typename> typename Q>
|
||||||
@@ -516,14 +518,14 @@ static_assert(is_of_type<1 * km % (300 * m), quantity<si::metre, int>>);
|
|||||||
static_assert(is_of_type<4 * one % (2 * one), quantity<one, int>>);
|
static_assert(is_of_type<4 * one % (2 * one), quantity<one, int>>);
|
||||||
|
|
||||||
// check for integral types promotion
|
// check for integral types promotion
|
||||||
static_assert(is_same_v<decltype((std::uint8_t(0) * m + std::uint8_t(0) * m).numerical_value()), int&&>);
|
static_assert(is_same_v<decltype(std::uint8_t(0) * m + std::uint8_t(0) * m)::rep, int>);
|
||||||
static_assert(is_same_v<decltype((std::uint8_t(0) * m - std::uint8_t(0) * m).numerical_value()), int&&>);
|
static_assert(is_same_v<decltype(std::uint8_t(0) * m - std::uint8_t(0) * m)::rep, int>);
|
||||||
static_assert((std::uint8_t(128) * m + std::uint8_t(128) * m).numerical_value() ==
|
static_assert((std::uint8_t(128) * m + std::uint8_t(128) * m).numerical_value_ ==
|
||||||
std::uint8_t(128) + std::uint8_t(128));
|
std::uint8_t(128) + std::uint8_t(128));
|
||||||
static_assert((std::uint8_t(0) * m - std::uint8_t(1) * m).numerical_value() == std::uint8_t(0) - std::uint8_t(1));
|
static_assert((std::uint8_t(0) * m - std::uint8_t(1) * m).numerical_value_ == std::uint8_t(0) - std::uint8_t(1));
|
||||||
|
|
||||||
static_assert(is_same_v<decltype(((std::uint8_t(0) * m) % (std::uint8_t(0) * m)).numerical_value()),
|
static_assert(
|
||||||
decltype(std::uint8_t(0) % std::uint8_t(0))&&>);
|
is_same_v<decltype((std::uint8_t(0) * m) % (std::uint8_t(0) * m))::rep, decltype(std::uint8_t(0) % std::uint8_t(0))>);
|
||||||
|
|
||||||
// different representation types
|
// different representation types
|
||||||
static_assert(is_of_type<1. * m + 1 * m, quantity<si::metre, double>>);
|
static_assert(is_of_type<1. * m + 1 * m, quantity<si::metre, double>>);
|
||||||
@@ -596,67 +598,67 @@ static_assert(is_of_type<1 * m / (1 * s), quantity<derived_unit<struct si::metre
|
|||||||
static_assert(is_of_type<1 * m / (1 * min), quantity<derived_unit<struct si::metre, per<struct si::minute>>{}, int>>);
|
static_assert(is_of_type<1 * m / (1 * min), quantity<derived_unit<struct si::metre, per<struct si::minute>>{}, int>>);
|
||||||
static_assert(is_of_type<1 * min / (1 * m), quantity<derived_unit<struct si::minute, per<struct si::metre>>{}, int>>);
|
static_assert(is_of_type<1 * min / (1 * m), quantity<derived_unit<struct si::minute, per<struct si::metre>>{}, int>>);
|
||||||
|
|
||||||
static_assert((1 * m + 1 * m).numerical_value() == 2);
|
static_assert((1 * m + 1 * m).numerical_value_ == 2);
|
||||||
static_assert((1 * m + 1 * km).numerical_value() == 1001);
|
static_assert((1 * m + 1 * km).numerical_value_ == 1001);
|
||||||
static_assert((1 * km + 1 * m).numerical_value() == 1001);
|
static_assert((1 * km + 1 * m).numerical_value_ == 1001);
|
||||||
static_assert((2 * m - 1 * m).numerical_value() == 1);
|
static_assert((2 * m - 1 * m).numerical_value_ == 1);
|
||||||
static_assert((1 * km - 1 * m).numerical_value() == 999);
|
static_assert((1 * km - 1 * m).numerical_value_ == 999);
|
||||||
static_assert((2 * m * 2).numerical_value() == 4);
|
static_assert((2 * m * 2).numerical_value_ == 4);
|
||||||
static_assert((2 * m * (2 * one)).numerical_value() == 4);
|
static_assert((2 * m * (2 * one)).numerical_value_ == 4);
|
||||||
static_assert((2 * m * (2 * percent)).numerical_value() == 4);
|
static_assert((2 * m * (2 * percent)).numerical_value_ == 4);
|
||||||
static_assert((3 * 3 * m).numerical_value() == 9);
|
static_assert((3 * 3 * m).numerical_value_ == 9);
|
||||||
static_assert(((3 * one) * (3 * m)).numerical_value() == 9);
|
static_assert(((3 * one) * (3 * m)).numerical_value_ == 9);
|
||||||
static_assert(((3 * percent) * (3 * m)).numerical_value() == 9);
|
static_assert(((3 * percent) * (3 * m)).numerical_value_ == 9);
|
||||||
static_assert((4 * m / 2).numerical_value() == 2);
|
static_assert((4 * m / 2).numerical_value_ == 2);
|
||||||
static_assert((4 * m / (2 * one)).numerical_value() == 2);
|
static_assert((4 * m / (2 * one)).numerical_value_ == 2);
|
||||||
static_assert((4 * m / (2 * percent)).numerical_value() == 2);
|
static_assert((4 * m / (2 * percent)).numerical_value_ == 2);
|
||||||
static_assert((4 * km / (2 * m)).numerical_value() == 2);
|
static_assert((4 * km / (2 * m)).numerical_value_ == 2);
|
||||||
static_assert((4000 * m / (2 * m)).numerical_value() == 2000);
|
static_assert((4000 * m / (2 * m)).numerical_value_ == 2000);
|
||||||
|
|
||||||
static_assert((1.5 * m + 1 * m).numerical_value() == 2.5);
|
static_assert((1.5 * m + 1 * m).numerical_value_ == 2.5);
|
||||||
static_assert((1.5 * m + 1 * km).numerical_value() == 1001.5);
|
static_assert((1.5 * m + 1 * km).numerical_value_ == 1001.5);
|
||||||
static_assert((1.5 * km + 1 * m).numerical_value() == 1501);
|
static_assert((1.5 * km + 1 * m).numerical_value_ == 1501);
|
||||||
static_assert((2.5 * m - 1 * m).numerical_value() == 1.5);
|
static_assert((2.5 * m - 1 * m).numerical_value_ == 1.5);
|
||||||
static_assert((1.5 * km - 1 * m).numerical_value() == 1499);
|
static_assert((1.5 * km - 1 * m).numerical_value_ == 1499);
|
||||||
static_assert((2.5 * m * 2).numerical_value() == 5);
|
static_assert((2.5 * m * 2).numerical_value_ == 5);
|
||||||
static_assert((2.5 * m * (2 * one)).numerical_value() == 5);
|
static_assert((2.5 * m * (2 * one)).numerical_value_ == 5);
|
||||||
static_assert((2.5 * m * (2 * percent)).numerical_value() == 5);
|
static_assert((2.5 * m * (2 * percent)).numerical_value_ == 5);
|
||||||
static_assert((2.5L * (2 * m)).numerical_value() == 5);
|
static_assert((2.5L * (2 * m)).numerical_value_ == 5);
|
||||||
static_assert((2.5L * one * (2 * m)).numerical_value() == 5);
|
static_assert((2.5L * one * (2 * m)).numerical_value_ == 5);
|
||||||
static_assert((2.5L * percent * (2 * m)).numerical_value() == 5);
|
static_assert((2.5L * percent * (2 * m)).numerical_value_ == 5);
|
||||||
static_assert((5. * m / 2).numerical_value() == 2.5);
|
static_assert((5. * m / 2).numerical_value_ == 2.5);
|
||||||
static_assert((5. * m / (2 * one)).numerical_value() == 2.5);
|
static_assert((5. * m / (2 * one)).numerical_value_ == 2.5);
|
||||||
static_assert((5. * m / (2 * percent)).numerical_value() == 2.5);
|
static_assert((5. * m / (2 * percent)).numerical_value_ == 2.5);
|
||||||
static_assert((5. * km / (2 * m)).numerical_value() == 2.5);
|
static_assert((5. * km / (2 * m)).numerical_value_ == 2.5);
|
||||||
static_assert((5000. * m / (2 * m)).numerical_value() == 2500);
|
static_assert((5000. * m / (2 * m)).numerical_value_ == 2500);
|
||||||
|
|
||||||
static_assert((1 * m + 1.5 * m).numerical_value() == 2.5);
|
static_assert((1 * m + 1.5 * m).numerical_value_ == 2.5);
|
||||||
static_assert((1 * m + 1.5 * km).numerical_value() == 1501);
|
static_assert((1 * m + 1.5 * km).numerical_value_ == 1501);
|
||||||
static_assert((1 * km + 1.5 * m).numerical_value() == 1001.5);
|
static_assert((1 * km + 1.5 * m).numerical_value_ == 1001.5);
|
||||||
static_assert((2 * m - 1.5 * m).numerical_value() == 0.5);
|
static_assert((2 * m - 1.5 * m).numerical_value_ == 0.5);
|
||||||
static_assert((1 * km - 1.5 * m).numerical_value() == 998.5);
|
static_assert((1 * km - 1.5 * m).numerical_value_ == 998.5);
|
||||||
static_assert((2 * m * 2.5L).numerical_value() == 5);
|
static_assert((2 * m * 2.5L).numerical_value_ == 5);
|
||||||
static_assert((2 * m * (2.5L * one)).numerical_value() == 5);
|
static_assert((2 * m * (2.5L * one)).numerical_value_ == 5);
|
||||||
static_assert((2 * m * (2.5L * percent)).numerical_value() == 5);
|
static_assert((2 * m * (2.5L * percent)).numerical_value_ == 5);
|
||||||
static_assert((2 * 2.5 * m).numerical_value() == 5);
|
static_assert((2 * 2.5 * m).numerical_value_ == 5);
|
||||||
static_assert((2 * one * (2.5 * m)).numerical_value() == 5);
|
static_assert((2 * one * (2.5 * m)).numerical_value_ == 5);
|
||||||
static_assert((2 * percent * (2.5 * m)).numerical_value() == 5);
|
static_assert((2 * percent * (2.5 * m)).numerical_value_ == 5);
|
||||||
static_assert((5 * m / 2.5L).numerical_value() == 2);
|
static_assert((5 * m / 2.5L).numerical_value_ == 2);
|
||||||
static_assert((5 * m / (2.5L * one)).numerical_value() == 2);
|
static_assert((5 * m / (2.5L * one)).numerical_value_ == 2);
|
||||||
static_assert((5 * m / (2.5L * percent)).numerical_value() == 2);
|
static_assert((5 * m / (2.5L * percent)).numerical_value_ == 2);
|
||||||
static_assert((5 * km / (2.5 * m)).numerical_value() == 2);
|
static_assert((5 * km / (2.5 * m)).numerical_value_ == 2);
|
||||||
static_assert((5000 * m / (2.5 * m)).numerical_value() == 2000);
|
static_assert((5000 * m / (2.5 * m)).numerical_value_ == 2000);
|
||||||
|
|
||||||
static_assert((7 * m % (2 * m)).numerical_value() == 1);
|
static_assert((7 * m % (2 * m)).numerical_value_ == 1);
|
||||||
static_assert((7 * km % (2000 * m)).numerical_value() == 1000);
|
static_assert((7 * km % (2000 * m)).numerical_value_ == 1000);
|
||||||
static_assert((1300 * m % (1 * km)).numerical_value() == 300);
|
static_assert((1300 * m % (1 * km)).numerical_value_ == 300);
|
||||||
static_assert((7 * one % (2 * one)).numerical_value() == 1);
|
static_assert((7 * one % (2 * one)).numerical_value_ == 1);
|
||||||
|
|
||||||
static_assert((10 * m2 * (10 * m2)) / (50 * m2) == 2 * m2);
|
static_assert((10 * m2 * (10 * m2)) / (50 * m2) == 2 * m2);
|
||||||
|
|
||||||
static_assert((10 * km / (5 * m)).numerical_value() == 2);
|
static_assert((10 * km / (5 * m)).numerical_value_ == 2);
|
||||||
static_assert((10 * km / (5 * m)).in(one).numerical_value() == 2000);
|
static_assert((10 * km / (5 * m)).numerical_value_in(one) == 2000);
|
||||||
static_assert((10 * s * (2 * kHz)).numerical_value() == 20);
|
static_assert((10 * s * (2 * kHz)).numerical_value_ == 20);
|
||||||
|
|
||||||
// commutativity and associativity
|
// commutativity and associativity
|
||||||
static_assert(10 * isq::length[si::metre] / (2 * isq::time[s]) + 5 * isq::speed[m / s] == 10 * isq::speed[m / s]);
|
static_assert(10 * isq::length[si::metre] / (2 * isq::time[s]) + 5 * isq::speed[m / s] == 10 * isq::speed[m / s]);
|
||||||
@@ -740,14 +742,13 @@ static_assert(is_same_v<decltype(0.0 * one - 0 * one), decltype(0.0 * one)>);
|
|||||||
static_assert(1 * one - 30 * percent == (100 - 30) * percent);
|
static_assert(1 * one - 30 * percent == (100 - 30) * percent);
|
||||||
static_assert(1 * one + 30 * percent == (100 + 30) * percent);
|
static_assert(1 * one + 30 * percent == (100 + 30) * percent);
|
||||||
|
|
||||||
static_assert(is_same_v<decltype((std::uint8_t(0) * one + std::uint8_t(0) * one).numerical_value()), int&&>);
|
static_assert(is_same_v<decltype(std::uint8_t(0) * one + std::uint8_t(0) * one)::rep, int>);
|
||||||
static_assert(is_same_v<decltype((std::uint8_t(0) * one - std::uint8_t(0) * one).numerical_value()), int&&>);
|
static_assert(is_same_v<decltype(std::uint8_t(0) * one - std::uint8_t(0) * one)::rep, int>);
|
||||||
static_assert((std::uint8_t(128) * one + std::uint8_t(128) * one).numerical_value() ==
|
static_assert((std::uint8_t(128) * one + std::uint8_t(128) * one).numerical_value_ ==
|
||||||
std::uint8_t(128) + std::uint8_t(128));
|
std::uint8_t(128) + std::uint8_t(128));
|
||||||
static_assert((std::uint8_t(0) * one - std::uint8_t(1) * one).numerical_value() == std::uint8_t(0) - std::uint8_t(1));
|
static_assert((std::uint8_t(0) * one - std::uint8_t(1) * one).numerical_value_ == std::uint8_t(0) - std::uint8_t(1));
|
||||||
|
static_assert(is_same_v<decltype(std::uint8_t(0) * one % (std::uint8_t(0) * one))::rep,
|
||||||
static_assert(is_same_v<decltype((std::uint8_t(0) * one % (std::uint8_t(0) * one)).numerical_value()),
|
decltype(std::uint8_t(0) % std::uint8_t(0))>);
|
||||||
decltype(std::uint8_t(0) % std::uint8_t(0))&&>);
|
|
||||||
|
|
||||||
static_assert(2 * one * (1 * m) == 2 * m);
|
static_assert(2 * one * (1 * m) == 2 * m);
|
||||||
static_assert(2 * one / (1 * m) == 2 / (1 * m));
|
static_assert(2 * one / (1 * m) == 2 / (1 * m));
|
||||||
@@ -880,20 +881,24 @@ static_assert(!(123 * km >= 321'000 * m));
|
|||||||
|
|
||||||
static_assert(is_of_type<10 * km / (5 * km), quantity<one, int>>);
|
static_assert(is_of_type<10 * km / (5 * km), quantity<one, int>>);
|
||||||
|
|
||||||
static_assert((50. * m / (100. * m)).in(percent).numerical_value() == 50);
|
static_assert((50. * m / (100. * m)).numerical_value_in(percent) == 50);
|
||||||
static_assert(50. * m / (100. * m) == 50 * percent);
|
static_assert(50. * m / (100. * m) == 50 * percent);
|
||||||
|
|
||||||
static_assert((50. * percent).in(one).numerical_value() == 0.5);
|
static_assert((50. * percent).numerical_value_in(one) == 0.5);
|
||||||
|
|
||||||
|
|
||||||
//////////////////
|
//////////////////
|
||||||
// value_cast
|
// value_cast
|
||||||
//////////////////
|
//////////////////
|
||||||
|
|
||||||
static_assert(value_cast<m>(2 * km).numerical_value() == 2000);
|
static_assert(value_cast<m>(2 * km).numerical_value_ == 2000);
|
||||||
static_assert(value_cast<km>(2000 * m).numerical_value() == 2);
|
static_assert(value_cast<km>(2000 * m).numerical_value_ == 2);
|
||||||
static_assert(value_cast<int>(1.23 * m).numerical_value() == 1);
|
static_assert(value_cast<int>(1.23 * m).numerical_value_ == 1);
|
||||||
static_assert(value_cast<km / h>(2000.0 * m / (3600.0 * s)).numerical_value() == 2);
|
static_assert(value_cast<km / h>(2000.0 * m / (3600.0 * s)).numerical_value_ == 2);
|
||||||
|
|
||||||
|
static_assert((2 * km).force_in(m).numerical_value_ == 2000);
|
||||||
|
static_assert((2000 * m).force_in(km).numerical_value_ == 2);
|
||||||
|
static_assert((2000.0 * m / (3600.0 * s)).force_in(km / h).numerical_value_ == 2);
|
||||||
|
|
||||||
//////////////////
|
//////////////////
|
||||||
// quantity_cast
|
// quantity_cast
|
||||||
|
Reference in New Issue
Block a user