refactor: relative() renamed to quantity_from_origin()

Resolves #479
This commit is contained in:
Mateusz Pusz
2023-08-18 18:44:52 +02:00
parent 7985ea2969
commit 07ce64d6e7
9 changed files with 149 additions and 126 deletions

View File

@@ -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.relative(); return t.quantity_from_origin();
}(kalman::get<0>(e.state)); }(kalman::get<0>(e.state));
std::string value_buffer; std::string value_buffer;

View File

@@ -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.relative(), current, next); measured.quantity_from_origin(), current, next);
} }
int main() int main()

View File

@@ -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.relative(), current, next); measured.quantity_from_origin(), current, next);
} }
int main() int main()

View File

@@ -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.relative(), current, next); measured.quantity_from_origin(), current, next);
} }
int main() int main()

View File

@@ -22,6 +22,7 @@
#pragma once #pragma once
#include <mp-units/bits/quantity_concepts.h>
#include <mp-units/bits/quantity_spec_concepts.h> #include <mp-units/bits/quantity_spec_concepts.h>
#include <mp-units/bits/reference_concepts.h> #include <mp-units/bits/reference_concepts.h>
#include <mp-units/bits/representation_concepts.h> #include <mp-units/bits/representation_concepts.h>
@@ -163,7 +164,7 @@ concept QuantityPointOf =
* all quantity_point-specific information. * all quantity_point-specific information.
*/ */
template<typename T> template<typename T>
concept QuantityPointLike = requires(T q) { concept QuantityPointLike = requires(T qp) {
quantity_point_like_traits<T>::reference; quantity_point_like_traits<T>::reference;
quantity_point_like_traits<T>::point_origin; quantity_point_like_traits<T>::point_origin;
typename quantity_point_like_traits<T>::rep; typename quantity_point_like_traits<T>::rep;
@@ -171,10 +172,11 @@ concept QuantityPointLike = requires(T q) {
requires PointOrigin<std::remove_const_t<decltype(quantity_point_like_traits<T>::point_origin)>>; requires PointOrigin<std::remove_const_t<decltype(quantity_point_like_traits<T>::point_origin)>>;
requires RepresentationOf<typename quantity_point_like_traits<T>::rep, requires RepresentationOf<typename quantity_point_like_traits<T>::rep,
get_quantity_spec(quantity_point_like_traits<T>::reference).character>; get_quantity_spec(quantity_point_like_traits<T>::reference).character>;
requires Quantity<std::remove_cvref_t<decltype(quantity_point_like_traits<T>::quantity_from_origin(qp))>>;
requires std::constructible_from< requires std::constructible_from<
typename quantity_point<quantity_point_like_traits<T>::reference, quantity_point_like_traits<T>::point_origin, quantity_point<quantity_point_like_traits<T>::reference, quantity_point_like_traits<T>::point_origin,
typename quantity_point_like_traits<T>::rep>::quantity_type, typename quantity_point_like_traits<T>::rep>,
decltype(quantity_point_like_traits<T>::relative(q))>; decltype(quantity_point_like_traits<T>::quantity_from_origin(qp))>;
}; };
} // namespace mp_units } // namespace mp_units

View File

@@ -149,8 +149,8 @@ struct quantity_like_traits;
* @brief Provides support for external quantity point-like types * @brief Provides support for external quantity point-like types
* *
* The type trait should provide nested @c reference and @c origin objects, * The type trait should provide nested @c reference and @c origin objects,
* a type alias @c rep, and a static member function @c relative(T) that will return * a type alias @c rep, and a static member function @c quantity_from_origin(T) that will
* the quantity-like value of the quantity point. * return the quantity being the offset of the point from the origin.
* *
* Usage example can be found in @c units/chrono.h header file. * Usage example can be found in @c units/chrono.h header file.
* *

View File

@@ -121,7 +121,7 @@ public:
q_([&] { q_([&] {
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.relative(); return qp.quantity_from_origin();
} else if constexpr (detail::is_derived_from_specialization_of_absolute_point_origin< } else if constexpr (detail::is_derived_from_specialization_of_absolute_point_origin<
std::remove_const_t<decltype(point_origin)>>) { std::remove_const_t<decltype(point_origin)>>) {
return qp.absolute(); return qp.absolute();
@@ -137,7 +137,8 @@ public:
std::remove_const_t<decltype(point_origin)>> && std::remove_const_t<decltype(point_origin)>> &&
std::convertible_to<typename detail::quantity_point_like_type<QP>::quantity_type, quantity_type> std::convertible_to<typename detail::quantity_point_like_type<QP>::quantity_type, quantity_type>
constexpr explicit quantity_point(const QP& qp) : constexpr explicit quantity_point(const QP& qp) :
q_(typename detail::quantity_point_like_type<QP>::quantity_type{quantity_point_like_traits<QP>::relative(qp)}) q_(typename detail::quantity_point_like_type<QP>::quantity_type{
quantity_point_like_traits<QP>::quantity_from_origin(qp)})
{ {
} }
@@ -161,24 +162,24 @@ public:
// data access // data access
#ifdef __cpp_explicit_this_parameter #ifdef __cpp_explicit_this_parameter
template<typename Self> template<typename Self>
[[nodiscard]] constexpr auto&& relative(this Self&& self) noexcept [[nodiscard]] constexpr auto&& quantity_from_origin(this Self&& self) noexcept
{ {
return std::forward<Self>(self).q_; return std::forward<Self>(self).q_;
} }
#else #else
[[nodiscard]] constexpr quantity_type& relative() & noexcept { return q_; } [[nodiscard]] constexpr quantity_type& quantity_from_origin() & noexcept { return q_; }
[[nodiscard]] constexpr const quantity_type& relative() const& noexcept { return q_; } [[nodiscard]] constexpr const quantity_type& quantity_from_origin() const& noexcept { return q_; }
[[nodiscard]] constexpr quantity_type&& relative() && noexcept { return std::move(q_); } [[nodiscard]] constexpr quantity_type&& quantity_from_origin() && noexcept { return std::move(q_); }
[[nodiscard]] constexpr const quantity_type&& relative() const&& noexcept { return std::move(q_); } [[nodiscard]] constexpr const quantity_type&& quantity_from_origin() const&& noexcept { return std::move(q_); }
#endif #endif
[[nodiscard]] constexpr Quantity auto absolute() const noexcept [[nodiscard]] constexpr Quantity auto absolute() const noexcept
{ {
if constexpr (detail::is_derived_from_specialization_of_absolute_point_origin< if constexpr (detail::is_derived_from_specialization_of_absolute_point_origin<
std::remove_const_t<decltype(point_origin)>>) std::remove_const_t<decltype(point_origin)>>)
return relative(); return quantity_from_origin();
else else
return point_origin.quantity_point.absolute() + relative(); return point_origin.quantity_point.absolute() + quantity_from_origin();
} }
template<Unit U> template<Unit U>
@@ -247,9 +248,9 @@ template<auto R1, auto PO1, typename Rep1, auto R2, typename Rep2>
requires ReferenceOf<std::remove_const_t<decltype(R2)>, get_quantity_spec(R1)> requires ReferenceOf<std::remove_const_t<decltype(R2)>, get_quantity_spec(R1)>
[[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.relative() + q; } requires requires { qp.quantity_from_origin() + q; }
{ {
auto temp = qp.relative() + q; auto temp = qp.quantity_from_origin() + q;
using q_type = decltype(temp); using q_type = decltype(temp);
return quantity_point<q_type::reference, PO1, typename q_type::rep>(std::move(temp)); return quantity_point<q_type::reference, PO1, typename q_type::rep>(std::move(temp));
} }
@@ -259,7 +260,7 @@ template<auto R1, typename Rep1, auto R2, auto PO2, typename Rep2>
requires ReferenceOf<std::remove_const_t<decltype(R1)>, get_quantity_spec(R2)> requires ReferenceOf<std::remove_const_t<decltype(R1)>, get_quantity_spec(R2)>
[[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.relative(); } requires requires { q + qp.quantity_from_origin(); }
{ {
return qp + q; return qp + q;
} }
@@ -283,9 +284,9 @@ template<auto R1, auto PO1, typename Rep1, auto R2, typename Rep2>
requires ReferenceOf<std::remove_const_t<decltype(R2)>, get_quantity_spec(R1)> requires ReferenceOf<std::remove_const_t<decltype(R2)>, get_quantity_spec(R1)>
[[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.relative() - q; } requires requires { qp.quantity_from_origin() - q; }
{ {
const auto temp = qp.relative() - q; const auto temp = qp.quantity_from_origin() - q;
using q_type = decltype(temp); using q_type = decltype(temp);
return quantity_point<q_type::reference, PO1, typename q_type::rep>(std::move(temp)); return quantity_point<q_type::reference, PO1, typename q_type::rep>(std::move(temp));
} }
@@ -306,7 +307,7 @@ template<QuantityPoint QP1, QuantityPointOf<QP1::absolute_point_origin> QP2>
std::remove_const_t<decltype(QP2::point_origin)>>) { std::remove_const_t<decltype(QP2::point_origin)>>) {
constexpr auto common_qs = common_quantity_spec(QP1::quantity_spec, QP1::point_origin.quantity_spec, constexpr auto common_qs = common_quantity_spec(QP1::quantity_spec, QP1::point_origin.quantity_spec,
QP2::quantity_spec, QP2::point_origin.quantity_spec); QP2::quantity_spec, QP2::point_origin.quantity_spec);
return quantity_cast<common_qs>(lhs.relative() - rhs.relative()); return quantity_cast<common_qs>(lhs.quantity_from_origin() - rhs.quantity_from_origin());
} else } else
return lhs.absolute() - rhs.absolute(); return lhs.absolute() - rhs.absolute();
} }
@@ -318,12 +319,12 @@ template<PointOrigin PO, QuantityPointOf<PO{}> QP>
constexpr auto common_qs = common_quantity_spec(PO::quantity_spec, QP::quantity_spec, QP::point_origin.quantity_spec); constexpr auto common_qs = common_quantity_spec(PO::quantity_spec, QP::quantity_spec, QP::point_origin.quantity_spec);
if constexpr (detail::is_derived_from_specialization_of_absolute_point_origin<PO>) { if constexpr (detail::is_derived_from_specialization_of_absolute_point_origin<PO>) {
if constexpr (is_same_v<std::remove_const_t<PO>, std::remove_const_t<decltype(QP::point_origin)>>) if constexpr (is_same_v<std::remove_const_t<PO>, std::remove_const_t<decltype(QP::point_origin)>>)
return quantity_cast<common_qs>(qp.relative()); return quantity_cast<common_qs>(qp.quantity_from_origin());
else else
return quantity_cast<common_qs>(qp.absolute()); return quantity_cast<common_qs>(qp.absolute());
} else { } else {
if constexpr (is_same_v<std::remove_const_t<PO>, std::remove_const_t<decltype(QP::point_origin)>>) if constexpr (is_same_v<std::remove_const_t<PO>, std::remove_const_t<decltype(QP::point_origin)>>)
return quantity_cast<common_qs>(qp.relative()); return quantity_cast<common_qs>(qp.quantity_from_origin());
else else
return quantity_cast<common_qs>(qp.absolute() - PO::quantity_point.absolute()); return quantity_cast<common_qs>(qp.absolute() - PO::quantity_point.absolute());
} }
@@ -358,7 +359,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.relative() <=> rhs.relative(); return lhs.quantity_from_origin() <=> rhs.quantity_from_origin();
else else
return lhs.absolute() <=> rhs.absolute(); return lhs.absolute() <=> rhs.absolute();
} }
@@ -369,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.relative() == rhs.relative(); return lhs.quantity_from_origin() == rhs.quantity_from_origin();
else else
return lhs.absolute() == rhs.absolute(); return lhs.absolute() == rhs.absolute();
} }

View File

@@ -80,9 +80,10 @@ struct quantity_point_like_traits<std::chrono::time_point<C, std::chrono::durati
static constexpr auto reference = detail::time_unit_from_chrono_period<Period>(); static constexpr auto reference = detail::time_unit_from_chrono_period<Period>();
static constexpr auto point_origin = chrono_point_origin<C>; static constexpr auto point_origin = chrono_point_origin<C>;
using rep = Rep; using rep = Rep;
[[nodiscard]] static constexpr auto relative(const std::chrono::time_point<C, std::chrono::duration<Rep, Period>>& qp) [[nodiscard]] static constexpr auto quantity_from_origin(
const std::chrono::time_point<C, std::chrono::duration<Rep, Period>>& qp)
{ {
return qp.time_since_epoch(); return quantity{qp.time_since_epoch()};
} }
}; };

View File

@@ -198,15 +198,20 @@ static_assert(is_same_v<quantity_point<isq::length[m], absolute_point_origin<isq
// static member functions // static member functions
//////////////////////////// ////////////////////////////
static_assert(quantity_point<isq::length[m]>::zero().relative().number() == 0); static_assert(quantity_point<isq::length[m]>::zero().quantity_from_origin().number() == 0);
static_assert(quantity_point<isq::length[m]>::min().relative().number() == std::numeric_limits<double>::lowest()); static_assert(quantity_point<isq::length[m]>::min().quantity_from_origin().number() ==
static_assert(quantity_point<isq::length[m]>::max().relative().number() == std::numeric_limits<double>::max()); std::numeric_limits<double>::lowest());
static_assert(quantity_point<isq::length[m], absolute_point_origin<isq::length>{}, int>::zero().relative().number() == static_assert(quantity_point<isq::length[m]>::max().quantity_from_origin().number() ==
0); std::numeric_limits<double>::max());
static_assert(quantity_point<isq::length[m], absolute_point_origin<isq::length>{}, int>::min().relative().number() == static_assert(
std::numeric_limits<int>::lowest()); quantity_point<isq::length[m], absolute_point_origin<isq::length>{}, int>::zero().quantity_from_origin().number() ==
static_assert(quantity_point<isq::length[m], absolute_point_origin<isq::length>{}, int>::max().relative().number() == 0);
std::numeric_limits<int>::max()); static_assert(
quantity_point<isq::length[m], absolute_point_origin<isq::length>{}, int>::min().quantity_from_origin().number() ==
std::numeric_limits<int>::lowest());
static_assert(
quantity_point<isq::length[m], absolute_point_origin<isq::length>{}, int>::max().quantity_from_origin().number() ==
std::numeric_limits<int>::max());
////////////////////////////// //////////////////////////////
@@ -383,42 +388,51 @@ static_assert(!std::convertible_to<sys_seconds, quantity_point<isq::time[s]>>);
// obtaining a relative quantity // obtaining a relative quantity
////////////////////////////////// //////////////////////////////////
static_assert(quantity_point(42 * m).relative() == 42 * m); static_assert(quantity_point(42 * m).quantity_from_origin() == 42 * m);
static_assert(quantity_point(isq::height(42 * m)).relative() == 42 * m); static_assert(quantity_point(isq::height(42 * m)).quantity_from_origin() == 42 * m);
static_assert(quantity_point(1 * one).relative() == 1 * one); static_assert(quantity_point(1 * one).quantity_from_origin() == 1 * one);
static_assert(quantity_point(dimensionless(1 * one)).relative() == 1 * one); static_assert(quantity_point(dimensionless(1 * one)).quantity_from_origin() == 1 * one);
static_assert(quantity_point<isq::height[m], mean_sea_level>(42 * m).relative() == 42 * m); static_assert(quantity_point<isq::height[m], mean_sea_level>(42 * m).quantity_from_origin() == 42 * m);
static_assert(quantity_point<isq::height[m], ground_level>(42 * m).relative() == 42 * m); static_assert(quantity_point<isq::height[m], ground_level>(42 * m).quantity_from_origin() == 42 * m);
static_assert(quantity_point<isq::height[m], tower_peak>(42 * m).relative() == 42 * m); static_assert(quantity_point<isq::height[m], tower_peak>(42 * m).quantity_from_origin() == 42 * m);
static_assert(quantity_point<isq::height[m], mean_sea_level>(quantity_point<isq::height[m], ground_level>(42 * m)) static_assert(quantity_point<isq::height[m], mean_sea_level>(quantity_point<isq::height[m], ground_level>(42 * m))
.relative() == 84 * m); .quantity_from_origin() == 84 * m);
static_assert(quantity_point<isq::height[m], mean_sea_level>(quantity_point<isq::height[m], tower_peak>(42 * m)) static_assert(quantity_point<isq::height[m], mean_sea_level>(quantity_point<isq::height[m], tower_peak>(42 * m))
.relative() == 126 * m); .quantity_from_origin() == 126 * m);
static_assert(quantity_point<isq::height[m], ground_level>(quantity_point<isq::height[m], mean_sea_level>(84 * m)) static_assert(quantity_point<isq::height[m], ground_level>(quantity_point<isq::height[m], mean_sea_level>(84 * m))
.relative() == 42 * m); .quantity_from_origin() == 42 * m);
static_assert(quantity_point<isq::height[m], ground_level>(quantity_point<isq::height[m], tower_peak>(42 * m)) static_assert(quantity_point<isq::height[m], ground_level>(quantity_point<isq::height[m], tower_peak>(42 * m))
.relative() == 84 * m); .quantity_from_origin() == 84 * m);
static_assert(quantity_point<isq::height[m], tower_peak>(quantity_point<isq::height[m], mean_sea_level>(42 * m)) static_assert(quantity_point<isq::height[m], tower_peak>(quantity_point<isq::height[m], mean_sea_level>(42 * m))
.relative() == -42 * m); .quantity_from_origin() == -42 * m);
static_assert(quantity_point<isq::height[m], tower_peak>(quantity_point<isq::height[m], ground_level>(84 * m)) static_assert(quantity_point<isq::height[m], tower_peak>(quantity_point<isq::height[m], ground_level>(84 * m))
.relative() == 42 * m); .quantity_from_origin() == 42 * m);
static_assert(quantity_point<isq::height[m], mean_sea_level>(42 * m).point_from(mean_sea_level).relative() == 42 * m); static_assert(
static_assert(quantity_point<isq::height[m], ground_level>(42 * m).point_from(mean_sea_level).relative() == 84 * m); quantity_point<isq::height[m], mean_sea_level>(42 * m).point_from(mean_sea_level).quantity_from_origin() == 42 * m);
static_assert(quantity_point<isq::height[m], tower_peak>(42 * m).point_from(mean_sea_level).relative() == 126 * m); static_assert(quantity_point<isq::height[m], ground_level>(42 * m).point_from(mean_sea_level).quantity_from_origin() ==
84 * m);
static_assert(quantity_point<isq::height[m], tower_peak>(42 * m).point_from(mean_sea_level).quantity_from_origin() ==
126 * m);
static_assert(quantity_point<isq::height[m], ground_level>(84 * m).point_from(ground_level).relative() == 84 * m); static_assert(quantity_point<isq::height[m], ground_level>(84 * m).point_from(ground_level).quantity_from_origin() ==
static_assert(quantity_point<isq::height[m], mean_sea_level>(84 * m).point_from(ground_level).relative() == 42 * m); 84 * m);
static_assert(quantity_point<isq::height[m], tower_peak>(42 * m).point_from(ground_level).relative() == 84 * m); static_assert(quantity_point<isq::height[m], mean_sea_level>(84 * m).point_from(ground_level).quantity_from_origin() ==
42 * m);
static_assert(quantity_point<isq::height[m], tower_peak>(42 * m).point_from(ground_level).quantity_from_origin() ==
84 * m);
static_assert(quantity_point<isq::height[m], tower_peak>(42 * m).point_from(tower_peak).relative() == 42 * m); static_assert(quantity_point<isq::height[m], tower_peak>(42 * m).point_from(tower_peak).quantity_from_origin() ==
static_assert(quantity_point<isq::height[m], mean_sea_level>(42 * m).point_from(tower_peak).relative() == -42 * m); 42 * m);
static_assert(quantity_point<isq::height[m], ground_level>(84 * m).point_from(tower_peak).relative() == 42 * m); static_assert(quantity_point<isq::height[m], mean_sea_level>(42 * m).point_from(tower_peak).quantity_from_origin() ==
-42 * m);
static_assert(quantity_point<isq::height[m], ground_level>(84 * m).point_from(tower_peak).quantity_from_origin() ==
42 * m);
static_assert(is_of_type<quantity_point<isq::height[m], ground_level, short>(42 * m).point_from(mean_sea_level), static_assert(is_of_type<quantity_point<isq::height[m], ground_level, short>(42 * m).point_from(mean_sea_level),
quantity_point<isq::height[m], mean_sea_level, int>>); quantity_point<isq::height[m], mean_sea_level, int>>);
@@ -468,13 +482,15 @@ static_assert(quantity_point<isq::height[m], ground_level>(84 * m).point_from(to
// converting to a different unit // converting to a different unit
/////////////////////////////////// ///////////////////////////////////
static_assert(quantity_point<isq::length[km]>(2. * km)[km].relative().number() == 2.); static_assert(quantity_point<isq::length[km]>(2. * km)[km].quantity_from_origin().number() == 2.);
static_assert(quantity_point<isq::length[km]>(2. * km)[m].relative().number() == 2000.); static_assert(quantity_point<isq::length[km]>(2. * km)[m].quantity_from_origin().number() == 2000.);
static_assert(quantity_point<isq::length[m]>(2000. * m)[km].relative().number() == 2.); static_assert(quantity_point<isq::length[m]>(2000. * m)[km].quantity_from_origin().number() == 2.);
static_assert( static_assert(quantity_point<isq::length[km], absolute_point_origin<isq::length>{}, int>(2 * km)[km]
quantity_point<isq::length[km], absolute_point_origin<isq::length>{}, int>(2 * km)[km].relative().number() == 2); .quantity_from_origin()
static_assert( .number() == 2);
quantity_point<isq::length[km], absolute_point_origin<isq::length>{}, int>(2 * km)[m].relative().number() == 2000); static_assert(quantity_point<isq::length[km], absolute_point_origin<isq::length>{}, int>(2 * km)[m]
.quantity_from_origin()
.number() == 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, auto, typename> typename QP> template<template<auto, auto, typename> typename QP>
@@ -521,18 +537,18 @@ static_assert(([]() {
quantity_point l1{1 * m}, l2{2 * m}; quantity_point l1{1 * m}, l2{2 * m};
return l2 = l1; return l2 = l1;
}()) }())
.relative() == 1 * m); .quantity_from_origin() == 1 * m);
static_assert(([]() { static_assert(([]() {
const quantity_point l1{1 * m}; const quantity_point l1{1 * m};
quantity_point l2{2 * m}; quantity_point l2{2 * m};
return l2 = l1; return l2 = l1;
}()) }())
.relative() == 1 * m); .quantity_from_origin() == 1 * m);
static_assert(([]() { static_assert(([]() {
quantity_point l1{1 * m}, l2{2 * m}; quantity_point l1{1 * m}, l2{2 * m};
return l2 = std::move(l1); return l2 = std::move(l1);
}()) }())
.relative() == 1 * m); .quantity_from_origin() == 1 * m);
//////////////////// ////////////////////
@@ -562,14 +578,14 @@ static_assert([](auto v) {
//////////////////////// ////////////////////////
// same type // same type
static_assert((quantity_point(1 * m) += 1 * m).relative().number() == 2); static_assert((quantity_point(1 * m) += 1 * m).quantity_from_origin().number() == 2);
static_assert((quantity_point(2 * m) -= 1 * m).relative().number() == 1); static_assert((quantity_point(2 * m) -= 1 * m).quantity_from_origin().number() == 1);
// different types // different types
static_assert((quantity_point(2.5 * m) += 3 * m).relative().number() == 5.5); static_assert((quantity_point(2.5 * m) += 3 * m).quantity_from_origin().number() == 5.5);
static_assert((quantity_point(123 * m) += 1 * km).relative().number() == 1123); static_assert((quantity_point(123 * m) += 1 * km).quantity_from_origin().number() == 1123);
static_assert((quantity_point(5.5 * m) -= 3 * m).relative().number() == 2.5); static_assert((quantity_point(5.5 * m) -= 3 * m).quantity_from_origin().number() == 2.5);
static_assert((quantity_point(1123 * m) -= 1 * km).relative().number() == 123); static_assert((quantity_point(1123 * m) -= 1 * km).quantity_from_origin().number() == 123);
template<template<auto, auto, typename> typename QP> template<template<auto, auto, typename> typename QP>
@@ -950,18 +966,21 @@ 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( static_assert(
is_same_v<decltype((quantity_point{std::uint8_t(0) * m} + std::uint8_t(0) * m).relative().number()), int&&>); is_same_v<decltype((quantity_point{std::uint8_t(0) * m} + std::uint8_t(0) * m).quantity_from_origin().number()),
int&&>);
static_assert( static_assert(
is_same_v<decltype((std::uint8_t(0) * m + quantity_point{std::uint8_t(0) * m}).relative().number()), int&&>); is_same_v<decltype((std::uint8_t(0) * m + quantity_point{std::uint8_t(0) * m}).quantity_from_origin().number()),
int&&>);
static_assert( static_assert(
is_same_v<decltype((quantity_point{std::uint8_t(0) * m} - std::uint8_t(0) * m).relative().number()), int&&>); is_same_v<decltype((quantity_point{std::uint8_t(0) * m} - std::uint8_t(0) * m).quantity_from_origin().number()),
int&&>);
static_assert( static_assert(
is_same_v<decltype((quantity_point{std::uint8_t(0) * m} - quantity_point{std::uint8_t(0) * m}).number()), int&&>); is_same_v<decltype((quantity_point{std::uint8_t(0) * m} - quantity_point{std::uint8_t(0) * m}).number()), int&&>);
static_assert((quantity_point{std::uint8_t(128) * m} + std::uint8_t(128) * m).relative().number() == static_assert((quantity_point{std::uint8_t(128) * m} + std::uint8_t(128) * m).quantity_from_origin().number() ==
std::uint8_t(128) + std::uint8_t(128)); std::uint8_t(128) + std::uint8_t(128));
static_assert((std::uint8_t(128) * m + quantity_point{std::uint8_t(128) * m}).relative().number() == static_assert((std::uint8_t(128) * m + quantity_point{std::uint8_t(128) * m}).quantity_from_origin().number() ==
std::uint8_t(128) + std::uint8_t(128)); std::uint8_t(128) + std::uint8_t(128));
static_assert((quantity_point{std::uint8_t(0) * m} - std::uint8_t(1) * m).relative().number() == static_assert((quantity_point{std::uint8_t(0) * m} - std::uint8_t(1) * m).quantity_from_origin().number() ==
std::uint8_t(0) - std::uint8_t(1)); std::uint8_t(0) - std::uint8_t(1));
static_assert((quantity_point{std::uint8_t(0) * m} - quantity_point{std::uint8_t(1) * m}).number() == static_assert((quantity_point{std::uint8_t(0) * m} - quantity_point{std::uint8_t(1) * m}).number() ==
std::uint8_t(0) - std::uint8_t(1)); std::uint8_t(0) - std::uint8_t(1));
@@ -1051,32 +1070,32 @@ static_assert(is_of_type<quantity_point{1 * km} - quantity_point{1. * m}, quanti
static_assert(is_of_type<quantity_point{1. * km} - quantity_point{1. * m}, quantity<si::metre, double>>); static_assert(is_of_type<quantity_point{1. * km} - quantity_point{1. * m}, quantity<si::metre, double>>);
static_assert((quantity_point{1 * m} + 1 * m).relative().number() == 2); static_assert((quantity_point{1 * m} + 1 * m).quantity_from_origin().number() == 2);
static_assert((1 * m + quantity_point{1 * m}).relative().number() == 2); static_assert((1 * m + quantity_point{1 * m}).quantity_from_origin().number() == 2);
static_assert((quantity_point{1 * m} + 1 * km).relative().number() == 1001); static_assert((quantity_point{1 * m} + 1 * km).quantity_from_origin().number() == 1001);
static_assert((1 * m + quantity_point{1 * km}).relative().number() == 1001); static_assert((1 * m + quantity_point{1 * km}).quantity_from_origin().number() == 1001);
static_assert((quantity_point{1 * km} + 1 * m).relative().number() == 1001); static_assert((quantity_point{1 * km} + 1 * m).quantity_from_origin().number() == 1001);
static_assert((1 * km + quantity_point{1 * m}).relative().number() == 1001); static_assert((1 * km + quantity_point{1 * m}).quantity_from_origin().number() == 1001);
static_assert((quantity_point{2 * m} - 1 * m).relative().number() == 1); static_assert((quantity_point{2 * m} - 1 * m).quantity_from_origin().number() == 1);
static_assert((quantity_point{1 * km} - 1 * m).relative().number() == 999); static_assert((quantity_point{1 * km} - 1 * m).quantity_from_origin().number() == 999);
static_assert((quantity_point{1.5 * m} + 1 * m).relative().number() == 2.5); static_assert((quantity_point{1.5 * m} + 1 * m).quantity_from_origin().number() == 2.5);
static_assert((1.5 * m + quantity_point{1 * m}).relative().number() == 2.5); static_assert((1.5 * m + quantity_point{1 * m}).quantity_from_origin().number() == 2.5);
static_assert((quantity_point{1.5 * m} + 1 * km).relative().number() == 1001.5); static_assert((quantity_point{1.5 * m} + 1 * km).quantity_from_origin().number() == 1001.5);
static_assert((1.5 * m + quantity_point{1 * km}).relative().number() == 1001.5); static_assert((1.5 * m + quantity_point{1 * km}).quantity_from_origin().number() == 1001.5);
static_assert((quantity_point{1.5 * km} + 1 * m).relative().number() == 1501); static_assert((quantity_point{1.5 * km} + 1 * m).quantity_from_origin().number() == 1501);
static_assert((1.5 * km + quantity_point{1 * m}).relative().number() == 1501); static_assert((1.5 * km + quantity_point{1 * m}).quantity_from_origin().number() == 1501);
static_assert((quantity_point{2.5 * m} - 1 * m).relative().number() == 1.5); static_assert((quantity_point{2.5 * m} - 1 * m).quantity_from_origin().number() == 1.5);
static_assert((quantity_point{1.5 * km} - 1 * m).relative().number() == 1499); static_assert((quantity_point{1.5 * km} - 1 * m).quantity_from_origin().number() == 1499);
static_assert((quantity_point{1 * m} + 1.5 * m).relative().number() == 2.5); static_assert((quantity_point{1 * m} + 1.5 * m).quantity_from_origin().number() == 2.5);
static_assert((1 * m + quantity_point{1.5 * m}).relative().number() == 2.5); static_assert((1 * m + quantity_point{1.5 * m}).quantity_from_origin().number() == 2.5);
static_assert((quantity_point{1 * m} + 1.5 * km).relative().number() == 1501); static_assert((quantity_point{1 * m} + 1.5 * km).quantity_from_origin().number() == 1501);
static_assert((1 * m + quantity_point{1.5 * km}).relative().number() == 1501); static_assert((1 * m + quantity_point{1.5 * km}).quantity_from_origin().number() == 1501);
static_assert((quantity_point{1 * km} + 1.5 * m).relative().number() == 1001.5); static_assert((quantity_point{1 * km} + 1.5 * m).quantity_from_origin().number() == 1001.5);
static_assert((1 * km + quantity_point{1.5 * m}).relative().number() == 1001.5); static_assert((1 * km + quantity_point{1.5 * m}).quantity_from_origin().number() == 1001.5);
static_assert((quantity_point{2 * m} - 1.5 * m).relative().number() == 0.5); static_assert((quantity_point{2 * m} - 1.5 * m).quantity_from_origin().number() == 0.5);
static_assert((quantity_point{1 * km} - 1.5 * m).relative().number() == 998.5); static_assert((quantity_point{1 * km} - 1.5 * m).quantity_from_origin().number() == 998.5);
static_assert((quantity_point{2 * m} - quantity_point{1 * m}).number() == 1); static_assert((quantity_point{2 * m} - quantity_point{1 * m}).number() == 1);
static_assert((quantity_point{1 * km} - quantity_point{1 * m}).number() == 999); static_assert((quantity_point{1 * km} - quantity_point{1 * m}).number() == 999);
@@ -1098,18 +1117,18 @@ static_assert(quantity_point(42 * m, tower_peak) - quantity_point(42 * m, other_
// commutativity and associativity // commutativity and associativity
static_assert((quantity_point{10 * isq::length[si::metre] / (2 * isq::time[s])} + 5 * isq::speed[m / s]).relative() == static_assert((quantity_point{10 * isq::length[si::metre] / (2 * isq::time[s])} + 5 * isq::speed[m / s])
10 * isq::speed[m / s]); .quantity_from_origin() == 10 * isq::speed[m / s]);
static_assert((10 * isq::length[si::metre] / (2 * isq::time[s]) + quantity_point{5 * isq::speed[m / s]}).relative() == static_assert((10 * isq::length[si::metre] / (2 * isq::time[s]) + quantity_point{5 * isq::speed[m / s]})
10 * isq::speed[m / s]); .quantity_from_origin() == 10 * isq::speed[m / s]);
static_assert((quantity_point{5 * isq::speed[m / s]} + 10 * isq::length[m] / (2 * isq::time[s])).relative() == static_assert((quantity_point{5 * isq::speed[m / s]} + 10 * isq::length[m] / (2 * isq::time[s]))
10 * isq::speed[m / s]); .quantity_from_origin() == 10 * isq::speed[m / s]);
static_assert((5 * isq::speed[m / s] + quantity_point{10 * isq::length[m] / (2 * isq::time[s])}).relative() == static_assert((5 * isq::speed[m / s] + quantity_point{10 * isq::length[m] / (2 * isq::time[s])})
10 * isq::speed[m / s]); .quantity_from_origin() == 10 * isq::speed[m / s]);
static_assert((quantity_point{10 * isq::length[m] / (2 * isq::time[s])} - 5 * isq::speed[m / s]).relative() == static_assert((quantity_point{10 * isq::length[m] / (2 * isq::time[s])} - 5 * isq::speed[m / s])
0 * isq::speed[m / s]); .quantity_from_origin() == 0 * isq::speed[m / s]);
static_assert((quantity_point{5 * isq::speed[m / s]} - 10 * isq::length[m] / (2 * isq::time[s])).relative() == static_assert((quantity_point{5 * isq::speed[m / s]} - 10 * isq::length[m] / (2 * isq::time[s]))
0 * isq::speed[m / s]); .quantity_from_origin() == 0 * isq::speed[m / s]);
static_assert(quantity_point{10 * isq::length[m] / (2 * isq::time[s])} - quantity_point{5 * isq::speed[m / s]} == static_assert(quantity_point{10 * isq::length[m] / (2 * isq::time[s])} - quantity_point{5 * isq::speed[m / s]} ==
0 * isq::speed[m / s]); 0 * isq::speed[m / s]);
static_assert(quantity_point{5 * isq::speed[m / s]} - quantity_point{10 * isq::length[m] / (2 * isq::time[s])} == static_assert(quantity_point{5 * isq::speed[m / s]} - quantity_point{10 * isq::length[m] / (2 * isq::time[s])} ==
@@ -1136,17 +1155,17 @@ static_assert(
quantity<isq::speed[m / s], int>>); quantity<isq::speed[m / s], int>>);
// NOTE: 1 / isq::time[s] works for quantities but not for quantity_point (origin can't be weakened) // NOTE: 1 / isq::time[s] works for quantities but not for quantity_point (origin can't be weakened)
static_assert((quantity_point{10 / (2 * isq::period_duration[s])} + 5 * isq::frequency[Hz]).relative() == static_assert((quantity_point{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]) + quantity_point{5 * isq::frequency[Hz]}).relative() == static_assert((10 / (2 * isq::period_duration[s]) + quantity_point{5 * isq::frequency[Hz]}).quantity_from_origin() ==
10 * isq::frequency[Hz]); 10 * isq::frequency[Hz]);
static_assert((quantity_point{5 * isq::frequency[Hz]} + 10 / (2 * isq::period_duration[s])).relative() == static_assert((quantity_point{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] + quantity_point{10 / (2 * isq::period_duration[s])}).relative() == static_assert((5 * isq::frequency[Hz] + quantity_point{10 / (2 * isq::period_duration[s])}).quantity_from_origin() ==
10 * isq::frequency[Hz]); 10 * isq::frequency[Hz]);
static_assert((quantity_point{10 / (2 * isq::period_duration[s])} - 5 * isq::frequency[Hz]).relative() == static_assert((quantity_point{10 / (2 * isq::period_duration[s])} - 5 * isq::frequency[Hz]).quantity_from_origin() ==
0 * isq::frequency[Hz]); 0 * isq::frequency[Hz]);
static_assert((quantity_point{5 * isq::frequency[Hz]} - 10 / (2 * isq::period_duration[s])).relative() == static_assert((quantity_point{5 * isq::frequency[Hz]} - 10 / (2 * isq::period_duration[s])).quantity_from_origin() ==
0 * isq::frequency[Hz]); 0 * isq::frequency[Hz]);
static_assert(quantity_point{10 / (2 * isq::period_duration[s])} - quantity_point{5 * isq::frequency[Hz]} == static_assert(quantity_point{10 / (2 * isq::period_duration[s])} - quantity_point{5 * isq::frequency[Hz]} ==
0 * isq::frequency[Hz]); 0 * isq::frequency[Hz]);