feat: 💥 initial implementation of implicit point origins
This commit is contained in:
1 parent
a114b9b9a3
commit
10a2e6dc0d
8 files changed
+108
-69
No files matched your search
@@ -71,13 +71,28 @@ template<PointOrigin PO1, PointOrigin PO2>
|
||||
else if constexpr (detail::RelativePointOrigin<PO1> && detail::RelativePointOrigin<PO2>)
|
||||
return PO1::quantity_point == PO2::quantity_point;
|
||||
else if constexpr (detail::RelativePointOrigin<PO1>)
|
||||
return detail::same_absolute_point_origins(po1, po2) &&
|
||||
return same_absolute_point_origins(po1, po2) &&
|
||||
detail::is_eq_zero(PO1::quantity_point.quantity_from(PO1::quantity_point.absolute_point_origin));
|
||||
else if constexpr (detail::RelativePointOrigin<PO2>)
|
||||
return detail::same_absolute_point_origins(po1, po2) &&
|
||||
return same_absolute_point_origins(po1, po2) &&
|
||||
detail::is_eq_zero(PO2::quantity_point.quantity_from(PO2::quantity_point.absolute_point_origin));
|
||||
}
|
||||
|
||||
template<QuantitySpec auto QS>
|
||||
struct implicit_zeroth_point_origin_ : absolute_point_origin<implicit_zeroth_point_origin_<QS>, QS> {};
|
||||
|
||||
template<QuantitySpec auto QS>
|
||||
inline constexpr implicit_zeroth_point_origin_<QS> implicit_zeroth_point_origin;
|
||||
|
||||
template<Reference R>
|
||||
[[nodiscard]] consteval PointOriginFor<get_quantity_spec(R{})> auto zeroth_point_origin(R)
|
||||
{
|
||||
if constexpr (requires { get_unit(R{}).point_origin; })
|
||||
return get_unit(R{}).point_origin;
|
||||
else
|
||||
return implicit_zeroth_point_origin<get_quantity_spec(R{})>;
|
||||
}
|
||||
|
||||
namespace detail {
|
||||
|
||||
template<PointOrigin PO>
|
||||
@@ -100,7 +115,7 @@ template<PointOrigin PO>
|
||||
* @tparam PO a type that represents the origin point from which the quantity point is measured from
|
||||
* @tparam Rep a type to be used to represent values of a quantity point
|
||||
*/
|
||||
template<Reference auto R, PointOriginFor<get_quantity_spec(R)> auto PO,
|
||||
template<Reference auto R, PointOriginFor<get_quantity_spec(R)> auto PO = zeroth_point_origin(R),
|
||||
RepresentationOf<get_quantity_spec(R).character> Rep = double>
|
||||
class quantity_point {
|
||||
public:
|
||||
@@ -135,7 +150,14 @@ public:
|
||||
quantity_point(quantity_point&&) = default;
|
||||
|
||||
template<typename Q>
|
||||
requires std::same_as<std::remove_cvref_t<Q>, quantity_type>
|
||||
requires QuantityOf<std::remove_cvref_t<Q>, get_quantity_spec(R)> && std::constructible_from<quantity_type, Q> &&
|
||||
(point_origin == zeroth_point_origin(R)) && (point_origin == zeroth_point_origin(Q::reference))
|
||||
constexpr explicit quantity_point(Q&& q) : quantity_from_origin_is_an_implementation_detail_(std::forward<Q>(q))
|
||||
{
|
||||
}
|
||||
|
||||
template<typename Q>
|
||||
requires QuantityOf<std::remove_cvref_t<Q>, get_quantity_spec(R)> && std::constructible_from<quantity_type, Q>
|
||||
constexpr quantity_point(Q&& q, std::remove_const_t<decltype(PO)>) :
|
||||
quantity_from_origin_is_an_implementation_detail_(std::forward<Q>(q))
|
||||
{
|
||||
@@ -219,6 +241,20 @@ public:
|
||||
return *this - PO2{};
|
||||
}
|
||||
|
||||
// returns always a value relative to the unit's zero
|
||||
// available only if point is defined in terms of a unit's zero point origin
|
||||
[[nodiscard]] constexpr Quantity auto quantity_from_zero() const
|
||||
requires(detail::same_absolute_point_origins(absolute_point_origin, zeroth_point_origin(R)))
|
||||
{
|
||||
// original quantity point unit can be lost in the below operation
|
||||
const auto q = quantity_from(zeroth_point_origin(R));
|
||||
if constexpr (requires { q.in(unit); })
|
||||
// restore it if possible (non-truncating)
|
||||
return q.in(unit);
|
||||
else
|
||||
return q;
|
||||
}
|
||||
|
||||
// unit conversions
|
||||
template<UnitCompatibleWith<unit, quantity_spec> U>
|
||||
requires detail::QuantityConvertibleTo<quantity_type, quantity<detail::make_reference(quantity_spec, U{}), Rep>>
|
||||
@@ -322,6 +358,9 @@ public:
|
||||
};
|
||||
|
||||
// CTAD
|
||||
template<Quantity Q>
|
||||
quantity_point(Q q) -> quantity_point<Q::reference, zeroth_point_origin(Q::reference), typename Q::rep>;
|
||||
|
||||
template<Quantity Q, PointOriginFor<Q::quantity_spec> PO>
|
||||
quantity_point(Q q, PO) -> quantity_point<Q::reference, PO{}, typename Q::rep>;
|
||||
|
||||
|
||||
@@ -29,6 +29,7 @@
|
||||
#include <mp-units/bits/external/type_traits.h>
|
||||
#include <mp-units/bits/get_associated_quantity.h>
|
||||
#include <mp-units/bits/magnitude.h>
|
||||
#include <mp-units/bits/quantity_point_concepts.h>
|
||||
#include <mp-units/bits/quantity_spec_concepts.h>
|
||||
#include <mp-units/bits/ratio.h>
|
||||
#include <mp-units/bits/symbol_text.h>
|
||||
@@ -116,6 +117,14 @@ struct named_unit<Symbol, QS> {
|
||||
static constexpr auto quantity_spec = QS;
|
||||
};
|
||||
|
||||
template<basic_symbol_text Symbol, detail::QuantityKindSpec auto QS, PointOrigin auto PO>
|
||||
requires(!Symbol.empty()) && detail::BaseDimension<std::remove_const_t<decltype(QS.dimension)>>
|
||||
struct named_unit<Symbol, QS, PO> {
|
||||
static constexpr auto symbol = Symbol; ///< Unique base unit identifier
|
||||
static constexpr auto quantity_spec = QS;
|
||||
static constexpr auto point_origin = PO;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Specialization for a unit that can be reused by several base quantities
|
||||
*
|
||||
@@ -132,6 +141,13 @@ struct named_unit<Symbol> {
|
||||
static constexpr auto symbol = Symbol; ///< Unique base unit identifier
|
||||
};
|
||||
|
||||
template<basic_symbol_text Symbol, PointOrigin auto PO>
|
||||
requires(!Symbol.empty())
|
||||
struct named_unit<Symbol, PO> {
|
||||
static constexpr auto symbol = Symbol; ///< Unique base unit identifier
|
||||
static constexpr auto point_origin = PO;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Specialization for a unit with special name
|
||||
*
|
||||
@@ -146,6 +162,13 @@ struct named_unit<Symbol, U> : std::remove_const_t<decltype(U)> {
|
||||
static constexpr auto symbol = Symbol; ///< Unique unit identifier
|
||||
};
|
||||
|
||||
template<basic_symbol_text Symbol, Unit auto U, PointOrigin auto PO>
|
||||
requires(!Symbol.empty())
|
||||
struct named_unit<Symbol, U, PO> : std::remove_const_t<decltype(U)> {
|
||||
static constexpr auto symbol = Symbol; ///< Unique unit identifier
|
||||
static constexpr auto point_origin = PO;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Specialization for a unit with special name valid only for a specific quantity
|
||||
*
|
||||
@@ -162,6 +185,14 @@ struct named_unit<Symbol, U, QS> : std::remove_const_t<decltype(U)> {
|
||||
static constexpr auto quantity_spec = QS;
|
||||
};
|
||||
|
||||
template<basic_symbol_text Symbol, AssociatedUnit auto U, detail::QuantityKindSpec auto QS, PointOrigin auto PO>
|
||||
requires(!Symbol.empty()) && (QS.dimension == detail::get_associated_quantity(U).dimension)
|
||||
struct named_unit<Symbol, U, QS, PO> : std::remove_const_t<decltype(U)> {
|
||||
static constexpr auto symbol = Symbol; ///< Unique unit identifier
|
||||
static constexpr auto quantity_spec = QS;
|
||||
static constexpr auto point_origin = PO;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief A prefixed unit
|
||||
*
|
||||
@@ -286,14 +317,14 @@ canonical_unit(M, U) -> canonical_unit<M, U>;
|
||||
|
||||
#endif
|
||||
|
||||
template<Unit T, basic_symbol_text Symbol, detail::QuantityKindSpec auto Q>
|
||||
[[nodiscard]] consteval auto get_canonical_unit_impl(T t, const named_unit<Symbol, Q>&);
|
||||
template<Unit T, basic_symbol_text Symbol, detail::QuantityKindSpec auto Q, auto... Args>
|
||||
[[nodiscard]] consteval auto get_canonical_unit_impl(T t, const named_unit<Symbol, Q, Args...>&);
|
||||
|
||||
template<Unit T, basic_symbol_text Symbol>
|
||||
[[nodiscard]] consteval auto get_canonical_unit_impl(T t, const named_unit<Symbol>&);
|
||||
template<Unit T, basic_symbol_text Symbol, auto... Args>
|
||||
[[nodiscard]] consteval auto get_canonical_unit_impl(T t, const named_unit<Symbol, Args...>&);
|
||||
|
||||
template<Unit T, basic_symbol_text Symbol, Unit auto U>
|
||||
[[nodiscard]] consteval auto get_canonical_unit_impl(T, const named_unit<Symbol, U>&);
|
||||
template<Unit T, basic_symbol_text Symbol, Unit auto U, auto... Args>
|
||||
[[nodiscard]] consteval auto get_canonical_unit_impl(T, const named_unit<Symbol, U, Args...>&);
|
||||
|
||||
template<typename T, typename F, int Num, int... Den>
|
||||
[[nodiscard]] consteval auto get_canonical_unit_impl(T, const power<F, Num, Den...>&);
|
||||
@@ -308,20 +339,20 @@ template<Unit T, auto M, typename U>
|
||||
return canonical_unit{M * base.mag, base.reference_unit};
|
||||
}
|
||||
|
||||
template<Unit T, basic_symbol_text Symbol, detail::QuantityKindSpec auto Q>
|
||||
[[nodiscard]] consteval auto get_canonical_unit_impl(T t, const named_unit<Symbol, Q>&)
|
||||
template<Unit T, basic_symbol_text Symbol, detail::QuantityKindSpec auto Q, auto... Args>
|
||||
[[nodiscard]] consteval auto get_canonical_unit_impl(T t, const named_unit<Symbol, Q, Args...>&)
|
||||
{
|
||||
return canonical_unit{mag<1>, t};
|
||||
}
|
||||
|
||||
template<Unit T, basic_symbol_text Symbol>
|
||||
[[nodiscard]] consteval auto get_canonical_unit_impl(T t, const named_unit<Symbol>&)
|
||||
template<Unit T, basic_symbol_text Symbol, auto... Args>
|
||||
[[nodiscard]] consteval auto get_canonical_unit_impl(T t, const named_unit<Symbol, Args...>&)
|
||||
{
|
||||
return canonical_unit{mag<1>, t};
|
||||
}
|
||||
|
||||
template<Unit T, basic_symbol_text Symbol, Unit auto U>
|
||||
[[nodiscard]] consteval auto get_canonical_unit_impl(T, const named_unit<Symbol, U>&)
|
||||
template<Unit T, basic_symbol_text Symbol, Unit auto U, auto... Args>
|
||||
[[nodiscard]] consteval auto get_canonical_unit_impl(T, const named_unit<Symbol, U, Args...>&)
|
||||
{
|
||||
return get_canonical_unit_impl(U, U);
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user