19#ifndef MTCORE_UNITS_BASE_HPP
20#define MTCORE_UNITS_BASE_HPP
43 template<
typename Underlying,
typename Units>
56 template<
size_t UnitCategory,
typename S = std::ratio<1>,
int PiPow = 0,
typename Tr = std::ratio<0>,
int exp = 1>
58 static constexpr size_t Id = UnitCategory;
70 concept IsUnit = std::same_as<T, Unit<T::Id, typename T::Scale, T::PiPower, typename T::Translation, T::EXPONENT>>;
82 template<
size_t Id,
typename S,
int PiPow,
typename Tr,
int Exp,
IsUnit... Mappings>
83 struct Units<
Unit<Id, S, PiPow, Tr, Exp>, Mappings...> {
100 template<
typename L,
typename R>
103 template<IsUnit... LU, IsUnit... RU>
104 struct ConcatUnits<Units<LU...>, Units<RU...>> {
105 using T = Units<LU..., RU...>;
113 template<
size_t CategoryId,
typename T>
116 template<
size_t CategoryId,
typename S,
int PiPow,
int exp,
typename Tr,
typename... Mappings>
117 struct GetUnitsImpl<CategoryId, Units<Unit<CategoryId, S, PiPow, Tr, exp>, Mappings...>> {
118 using Rest = GetUnitsImpl<CategoryId, Units<Mappings...>>;
119 using T =
typename ConcatUnits<Units<Unit<CategoryId, S, PiPow, Tr, exp>>,
typename Rest::T>::T;
122 template<
size_t CategoryId,
size_t CurId,
typename S,
int PiPow,
int exp,
typename Tr,
typename... Mappings>
123 struct GetUnitsImpl<CategoryId, Units<Unit<CurId, S, PiPow, Tr, exp>, Mappings...>> {
124 using Rest = GetUnitsImpl<CategoryId, Units<Mappings...>>;
125 using T =
typename Rest::T;
128 template<
size_t CategoryId>
129 struct GetUnitsImpl<CategoryId, Units<>> {
138 template<
size_t CategoryId,
typename U>
139 struct GetUnits : GetUnitsImpl<CategoryId, std::remove_cvref_t<U>> {};
145 template<
size_t CategoryId,
typename T,
size_t Indx = 0>
148 template<
size_t CategoryId,
typename S,
int PiPow,
int exp,
typename Tr,
typename... Mappings,
size_t Indx>
149 struct GetUnitImpl<CategoryId, Units<Unit<CategoryId, S, PiPow, Tr, exp>, Mappings...>, Indx> {
150 using Rest = GetUnitImpl<CategoryId, Units<Mappings...>, Indx + 1>;
151 using Scale =
typename math::MultRatios<typename math::IntPowRatio<S, exp>::T,
typename Rest::Scale>::T;
152 static constexpr auto PiPower = PiPow * exp + Rest::PiPower;
153 using Translation =
typename math::AddRatios<typename math::NegateRatio<Tr>::T,
typename Rest::Translation>::T;
154 static constexpr int exponent = exp + Rest::exponent;
155 using T = Unit<CategoryId, Scale, PiPower, Translation, exponent>;
157 static constexpr auto index = Indx;
158 static constexpr bool present =
true;
161 template<
size_t CategoryId,
size_t CurId,
typename S,
int PiPow,
int exp,
typename Tr,
typename... Mappings,
163 struct GetUnitImpl<CategoryId, Units<Unit<CurId, S, PiPow, Tr, exp>, Mappings...>, Indx> {
164 using Rest = GetUnitImpl<CategoryId, Units<Mappings...>, Indx + 1>;
165 using Scale =
typename Rest::Scale;
166 static constexpr auto PiPower = Rest::PiPower;
167 using Translation =
typename Rest::Translation;
168 using T =
typename Rest::T;
169 using UNIT =
typename Rest::UNIT;
170 static constexpr int exponent = Rest::exponent;
171 static constexpr auto index = Rest::index;
172 static constexpr bool present = Rest::present;
175 template<
size_t CategoryId,
size_t Indx>
176 struct GetUnitImpl<CategoryId, Units<>, Indx> {
177 using Scale = std::ratio<1>;
178 static constexpr int PiPower = 0;
179 using Translation = std::ratio<0>;
180 using T = Unit<CategoryId, Scale, PiPower, Translation>;
182 static constexpr int exponent = 0;
183 static constexpr auto index = std::numeric_limits<size_t>::max();
184 static constexpr bool present =
false;
191 template<
size_t CategoryId,
typename U>
192 struct GetUnit : GetUnitImpl<CategoryId, std::remove_cvref_t<U>, 0> {};
194 static_assert(!GetUnit<4, Units<Unit<1>>>::present);
195 static_assert(GetUnit<4, Units<Unit<4>>>::present);
196 static_assert(GetUnit<4, Units<Unit<5>, Unit<4>>>::present);
197 static_assert(std::same_as<GetUnit<4, Units<Unit<5>, Unit<4>>>::Scale, std::ratio<1>>);
198 static_assert(std::same_as<GetUnit<4, Units<Unit<5>, Unit<4, std::ratio<2>>>>::Scale, std::ratio<2>>);
199 static_assert(std::same_as<GetUnit<4, Units<Unit<5>, Unit<4, std::ratio<2>>, Unit<4, std::ratio<1, 2>>>>::Scale,
201 static_assert(std::same_as<GetUnit<4, Units<Unit<5>, Unit<4, std::ratio<10>>, Unit<4, std::ratio<1, 2>>>>::Scale,
203 static_assert(std::same_as<GetUnit<4, Units<Unit<5>, Unit<4, std::ratio<10>>, Unit<4, std::ratio<1, 2>>,
204 Unit<4, std::ratio<1, 5>>>>::Scale,
206 static_assert(std::same_as<GetUnit<4, Units<Unit<5>, Unit<4, std::ratio<10>>, Unit<4, std::ratio<1, 2>>,
207 Unit<4, std::ratio<1, 10>>>>::Scale,
216 template<
int Id,
typename L,
typename R>
218 static constexpr auto value = GetUnit<Id, L>::exponent == GetUnit<Id, R>::exponent;
226 template<
bool present,
typename... U>
227 struct UniqIdSetImpl;
229 template<
typename U,
typename UNext,
typename... Us>
230 struct UniqIdSetImpl<true, Units<U, UNext, Us...>> {
231 using T =
typename UniqIdSetImpl<GetUnit<UNext::Id, Units<Us...>>::present, Units<UNext, Us...>>::T;
234 template<
typename U,
typename UNext,
typename... Us>
235 struct UniqIdSetImpl<false, Units<U, UNext, Us...>> {
236 using T =
typename meta::ConcatIntList<
237 meta::IntList<U::Id>,
238 typename UniqIdSetImpl<GetUnit<UNext::Id, Units<Us...>>::present, Units<UNext, Us...>>::T>::T;
242 struct UniqIdSetImpl<false, Units<U>> {
243 using T = meta::IntList<U::Id>;
247 struct UniqIdSetImpl<p, Units<>> {
248 using T = meta::IntList<>;
258 struct UniqIdSet<const Units<>> {
259 using T = meta::IntList<>;
263 struct UniqIdSet<Units<>> {
264 using T = meta::IntList<>;
267 template<IsUnit U, IsUnit... Us>
268 struct UniqIdSet<Units<U, Us...>> {
269 using T =
typename UniqIdSetImpl<GetUnit<U::Id, Units<Us...>>::present, Units<U, Us...>>::T;
272 template<IsUnit U, IsUnit... Us>
273 struct UniqIdSet<const Units<U, Us...>> {
274 using T =
typename UniqIdSetImpl<GetUnit<U::Id, Units<Us...>>::present, Units<U, Us...>>::T;
280 template<
typename Ids,
typename Left,
typename Right>
281 struct AllLeftInRightImpl;
283 template<
int... Ids,
typename Left,
typename Right>
284 struct AllLeftInRightImpl<meta::IntList<Ids...>, Left, Right> {
285 static constexpr auto value =
286 meta::And<GetUnit<Ids, Right>::present...>::value && meta::And<ExpEq<Ids, Left, Right>::value...>::value;
292 template<
typename Left,
typename Right>
293 struct AllLeftInRight : AllLeftInRightImpl<typename UniqIdSet<std::remove_cvref_t<Left>>::T,
294 std::remove_cvref_t<std::remove_cvref_t<Left>>,
295 std::remove_cvref_t<std::remove_cvref_t<Right>>> {};
297 static_assert(AllLeftInRight<Units<Unit<1>>, Units<Unit<1>>>::value);
298 static_assert(AllLeftInRight<Units<Unit<1>>, Units<Unit<1>>>::value);
299 static_assert(AllLeftInRight<Units<Unit<1>>, Units<Unit<1>, Unit<2>>>::value);
300 static_assert(AllLeftInRight<Units<Unit<1>, Unit<2>>, Units<Unit<1>, Unit<2>>>::value);
301 static_assert(!AllLeftInRight<Units<Unit<1>, Unit<2>, Unit<3>>, Units<Unit<1>, Unit<2>>>::value);
302 static_assert(!AllLeftInRight<Units<Unit<1>>, Units<Unit<1>, Unit<1>>>::value);
303 static_assert(!AllLeftInRight<Units<Unit<1>, Unit<1>>, Units<Unit<1>>>::value);
304 static_assert(AllLeftInRight<Units<Unit<1>, Unit<1>>, Units<Unit<1>, Unit<1>>>::value);
309 template<
typename Left,
typename Right>
310 struct CompatibleDimensions {
311 static constexpr bool value = AllLeftInRight<Left, Right>::value && AllLeftInRight<Right, Left>::value;
317 template<
typename From,
typename To>
318 concept Convertible = CompatibleDimensions<From, To>::value;
323 template<
typename T,
typename Us>
324 struct WithoutZeroExponentsImpl;
326 template<
typename Us>
327 struct WithoutZeroExponentsImpl<meta::IntList<>, Us> {
331 template<
int Cur,
int... Rest,
typename Us>
332 struct WithoutZeroExponentsImpl<meta::IntList<Cur, Rest...>, Us> {
333 using Nxt =
typename WithoutZeroExponentsImpl<meta::IntList<Rest...>, Us>::T;
334 using T =
typename meta::If<GetUnit<Cur, Us>::exponent == 0, Nxt,
335 typename ConcatUnits<typename GetUnits<Cur, Us>::T, Nxt>::T>::T;
342 struct WithoutZeroExponents;
345 struct WithoutZeroExponents<Units<>> {
349 template<
typename U,
typename... Us>
350 struct WithoutZeroExponents<Units<U, Us...>> {
351 using T =
typename WithoutZeroExponentsImpl<
typename UniqIdSet<Units<U, Us...>>::T, Units<U, Us...>>::T;
359 using T = Unit<U::Id,
typename U::Scale, U::PiPower,
typename U::Translation, -U::EXPONENT>;
362 static_assert(GetUnit<1, Units<Unit<1>, Unit<1>>>::exponent == 2);
363 static_assert(GetUnit<1, Units<Unit<1>,
typename FlipUnit<Unit<1>>::T>>::exponent == 0);
365 static_assert(GetUnit<1, Units<Unit<1>,
typename FlipUnit<Unit<1>>::T>>::present ==
true);
367 GetUnit<1, typename WithoutZeroExponents<Units<Unit<1>,
typename FlipUnit<Unit<1>>::T>>::T>::present ==
false);
368 static_assert(GetUnit<1, typename WithoutZeroExponents<Units<Unit<1>, Unit<1>>>::T>::present ==
true);
373 template<
typename Ids,
typename From,
typename To>
376 template<
typename From,
typename To>
377 struct ConvertImpl<meta::IntList<>, From, To> {
378 template<
bool,
typename U>
379 static constexpr U convert(
const U &v) {
384 template<
int Id,
int... Ids,
typename From,
typename To>
385 struct ConvertImpl<meta::IntList<Id, Ids...>, From, To> {
386 using FromScale =
typename GetUnit<Id, From>::Scale;
387 using FromTranslation =
typename GetUnit<Id, From>::Translation;
388 static constexpr auto FromPiScale = GetUnit<Id, From>::PiPower;
389 static constexpr auto FromExponent = GetUnit<Id, From>::exponent;
391 using ToScale =
typename GetUnit<Id, To>::Scale;
392 using ToTranslation =
typename GetUnit<Id, To>::Translation;
393 static constexpr auto ToPiScale = GetUnit<Id, To>::PiPower;
394 static constexpr auto ToExponent = GetUnit<Id, To>::exponent;
396 static constexpr auto FSNum = math::RatioParts<FromScale>::Numerator;
397 static constexpr auto FSDen = math::RatioParts<FromScale>::Denominator;
398 static constexpr auto FTNum = math::RatioParts<FromTranslation>::Numerator;
399 static constexpr auto FTDen = math::RatioParts<FromTranslation>::Denominator;
401 static constexpr auto TSNum = math::RatioParts<ToScale>::Numerator;
402 static constexpr auto TSDen = math::RatioParts<ToScale>::Denominator;
403 static constexpr auto TTNum = math::RatioParts<ToTranslation>::Numerator;
404 static constexpr auto TTDen = math::RatioParts<ToTranslation>::Denominator;
406 static constexpr auto ScaleMult =
static_cast<long double>(FSNum) *
static_cast<long double>(TSDen);
407 static constexpr auto ScaleDiv =
static_cast<long double>(FSDen) *
static_cast<long double>(TSNum);
408 static constexpr auto ScaleFactor =
static_cast<long double>(ScaleMult) /
static_cast<long double>(ScaleDiv);
409 static_assert(ScaleDiv != 0);
411 static constexpr auto factor = ScaleFactor;
413 template<
bool ignoreChecks,
typename U>
414 static constexpr U convert(U v) {
415 static_assert(!std::is_integral_v<U> || !(FSNum == TSNum && FSDen == TSDen) || (factor == 1) || ignoreChecks,
416 "Possible precision loss detected!");
417 if constexpr (FTNum != 0) {
418 v -=
static_cast<long double>(FTNum) /
static_cast<long double>(FTDen);
421 if constexpr (!std::is_integral_v<U> && std::is_convertible_v<U, long double>) {
422 v =
static_cast<U
>(
static_cast<long double>(v) * factor);
425 v =
static_cast<U
>((
static_cast<long double>(v) * ScaleMult) / ScaleDiv);
428 if constexpr (ToPiScale != 0) {
429 v *= std::pow(std::numbers::pi_v<long double>, -ToPiScale);
431 if constexpr (FromPiScale) {
432 v *= std::pow(std::numbers::pi_v<long double>, FromPiScale);
435 if constexpr (TTNum != 0) {
436 v +=
static_cast<long double>(TTNum) /
static_cast<long double>(TTDen);
438 return ConvertImpl<meta::IntList<Ids...>, From, To>::template convert<ignoreChecks>(
static_cast<U
>(v));
445 template<
typename From, Convertible<From> To>
446 struct Convert : ConvertImpl<typename UniqIdSet<std::remove_cvref_t<From>>::T, std::remove_cvref_t<From>,
447 std::remove_cvref_t<To>> {};
449 template<
typename T,
typename Dest>
450 concept ConvertibleTo = AllLeftInRight<T, Dest>::value && AllLeftInRight<Dest, T>::value;
453 constexpr bool gt(T l, T r) {
457 template<
typename From,
typename To>
458 struct ConvertMorePrecise {
459 using T =
typename meta::If<
460 gt(Convert<From, To>::template convert<true>(1.), Convert<To, From>::template convert<true>(1.)), To, From>::T;
470 template<
typename Underlying>
477 [[nodiscard]]
constexpr operator Underlying() const noexcept {
return val; }
483 *
this =
static_cast<UnitValue>((*this) + o);
492 *
this =
static_cast<UnitValue>((*this) + o);
512 constexpr auto operator<=>(
const Underlying &o)
const noexcept {
return val <=> o; }
514 constexpr auto operator==(
const Underlying &o)
const noexcept {
return val == o; }
516 constexpr auto operator<(
const Underlying &o)
const noexcept {
return val < o; }
518 constexpr auto operator<=(
const Underlying &o)
const noexcept {
return val <= o; }
520 constexpr auto operator>(
const Underlying &o)
const noexcept {
return val > o; }
522 constexpr auto operator>=(
const Underlying &o)
const noexcept {
return val >= o; }
524 constexpr auto operator!=(
const Underlying &o)
const noexcept {
return val != o; }
534 template<
typename Underlying,
typename U1,
typename... UnitsSub>
545 template<
typename OU, impl::Convertible<Us> OD>
547 if constexpr (std::is_same_v<OD, Us>) {
551 using Converter = impl::Convert<Us, OD>;
557 template<
typename Target,
typename U = Underlying,
bool ignoreChecks = false>
558 [[nodiscard]]
constexpr auto convert()
const {
559 using Converter = impl::Convert<Us, Target>;
564 template<
typename Target,
typename U = Underlying,
bool ignoreChecks = false>
565 [[nodiscard]]
constexpr auto to(Target)
const {
566 using Converter = impl::Convert<Us, Target>;
572 auto r =
val + o.val;
578 *
this =
static_cast<UnitValue>((*this) + o);
584 auto r =
val - o.val;
590 *
this =
static_cast<UnitValue>((*this) + o);
595 template<
typename OV, impl::Convertible<Us> OUs,
bool ignoreChecks = false>
601 return UnitValue<
decltype(r), Target>{r};
605 template<
typename OV, impl::Convertible<Us> OUs,
bool ignoreChecks = false>
612 template<
typename OV, impl::Convertible<Us> OUs,
bool ignoreChecks = false>
618 return UnitValue<
decltype(r), Target>{r};
622 template<
typename OV, impl::Convertible<Us> OUs,
bool ignoreChecks = false>
644 template<
typename OV, impl::Convertible<Us> OUs,
bool ignoreChecks = false>
646 using Target =
typename impl::ConvertMorePrecise<Us, OUs>::T;
652 template<
typename OV, impl::Convertible<Us> OUs,
bool ignoreChecks = false>
654 using Target =
typename impl::ConvertMorePrecise<Us, OUs>::T;
660 template<
typename OV, impl::Convertible<Us> OUs,
bool ignoreChecks = false>
662 using Target =
typename impl::ConvertMorePrecise<Us, OUs>::T;
668 template<
typename OV, impl::Convertible<Us> OUs,
bool ignoreChecks = false>
670 using Target =
typename impl::ConvertMorePrecise<Us, OUs>::T;
676 template<
typename OV, impl::Convertible<Us> OUs,
bool ignoreChecks = false>
678 using Target =
typename impl::ConvertMorePrecise<Us, OUs>::T;
684 template<
typename OV, impl::Convertible<Us> OUs,
bool ignoreChecks = false>
686 using Target =
typename impl::ConvertMorePrecise<Us, OUs>::T;
692 template<
typename OV, impl::Convertible<Us> OUs,
bool ignoreChecks = false>
694 using Target =
typename impl::ConvertMorePrecise<Us, OUs>::T;
727 template<std::floating_point Val,
typename... Dims>
733 template<std::integral Val,
typename... Dims>
734 constexpr UnitValue<Val, Units<Dims...>>
operator*(Val lhs,
const Units<Dims...> &) {
739 template<
typename... Dims1,
typename... Dims2>
741 return typename impl::WithoutZeroExponents<
typename impl::ConcatUnits<
Units<Dims1...>,
Units<Dims2...>>::T>::T{};
745 std::same_as<std::remove_cvref_t<
decltype(Units<Unit<1>>{} * Units<Unit<1>>{})>,
Units<Unit<1>,
Unit<1>>>);
748 template<
typename... Dims1,
typename... Dims2>
750 return typename impl::WithoutZeroExponents<
755 template<std::floating_point Val,
typename... Dims>
757 return UnitValue<Val,
typename impl::WithoutZeroExponents<
Units<
typename impl::FlipUnit<Dims...>::T>>::T>{lhs};
761 template<std::integral Val,
typename... Dims>
762 constexpr auto operator/(Val lhs,
const Units<Dims...> &) {
763 return UnitValue<Val,
typename impl::WithoutZeroExponents<Units<
typename impl::FlipUnit<Dims...>::T>>::T>{lhs};
769 template<
typename U1,
typename Us1,
typename U2,
typename Us2>
771 using RetUnits =
typename impl::ConcatUnits<std::remove_const_t<typename UnitValue<U1, Us1>::UnitsType>,
772 std::remove_const_t<typename UnitValue<U2, Us2>::UnitsType>>::T;
773 const auto r = lhs.val * rhs.val;
774 return UnitValue<std::remove_cvref_t<
decltype(r)>, RetUnits>{r};
778 template<
typename U1,
typename Us1,
typename U2,
typename Us2>
780 using RetUnits =
typename impl::ConcatUnits<std::remove_const_t<typename UnitValue<U1, Us1>::UnitsType>,
781 std::remove_const_t<typename UnitValue<U2, Us2>::UnitsType>>::T;
782 const auto r = lhs.val * rhs.val;
783 if constexpr (std::is_same_v<Units<>, RetUnits>) {
786 return UnitValue<std::remove_cvref_t<
decltype(r)>, RetUnits>{r};
790 template<std::
floating_po
int I,
typename U,
typename Us>
792 using RetUnits =
typename std::remove_const_t<
decltype(1 / std::declval<Us>())>::UnitsType;
797 template<std::
floating_po
int I,
typename U,
typename Us>
799 using RetUnits = std::remove_const_t<Us>;
804 template<std::
integral I,
typename U,
typename Us>
806 using RetUnits =
typename std::remove_const_t<
decltype(1 / std::declval<Us>())>::UnitsType;
811 template<std::
integral I,
typename U,
typename Us>
812 constexpr auto operator/(UnitValue<U, Us> lhs, I value) {
813 using RetUnits =
typename std::remove_const_t<
decltype(1 / std::declval<Us>())>::UnitsType;
814 return UnitValue<U, RetUnits>{lhs.val / value};
818 template<std::
floating_po
int Val,
typename U,
typename Us>
820 return {
static_cast<U
>(lhs) * rhs.val};
824 template<std::
floating_po
int Val,
typename U,
typename Us>
826 return {lhs *
static_cast<Val
>(rhs.val)};
830 template<std::
integral Val,
typename U,
typename Us>
831 constexpr UnitValue<U, Us>
operator*(
const UnitValue<U, Us> &lhs, Val rhs) {
832 return {
static_cast<U
>(lhs) * rhs.val};
836 template<std::
integral Val,
typename U,
typename Us>
838 return {lhs *
static_cast<Val
>(rhs.val)};
842 template<
typename U,
typename Us,
typename... Dims>
844 using RetUnits = std::remove_const_t<
decltype(std::declval<typename UnitValue<U, Us>::UnitsType>() * u)>;
849 template<
typename U,
typename Us,
typename... Dims>
851 using RetUnits = std::remove_const_t<
decltype(std::declval<typename UnitValue<U, Us>::UnitsType>() / u)>;
857 concept IsUnitValue =
requires(
const T &t,
const typename T::UnitsType UT) {
858 { t.template convert<typename T::UnitsType>() };
882#define MTCORE_DEF_UNIT_NAME_NO_ABBREV(NS, UNIT) \
884 struct UnitName<std::remove_cvref_t<decltype(NS::UNIT)>> { \
885 static constexpr std::string_view nameUs = #UNIT; \
886 static constexpr std::string_view name = #UNIT; \
887 static constexpr std::string_view abbrev = #UNIT; \
888 static constexpr std::string_view abbrevUs = #UNIT; \
889 static constexpr std::string_view abbrevAscii = #UNIT; \
890 static constexpr std::string_view symbol = ""; \
893#define MTCORE_DEF_UNIT_NAME_SYM(NS, UNIT, ABBREV, SYM) \
895 struct UnitName<std::remove_cvref_t<decltype(NS::UNIT)>> { \
896 static constexpr std::string_view nameUs = #UNIT; \
897 static constexpr std::string_view name = #UNIT; \
898 static constexpr std::string_view abbrev = #ABBREV; \
899 static constexpr std::string_view abbrevUs = #ABBREV; \
900 static constexpr std::string_view abbrevAscii = #ABBREV; \
901 static constexpr std::string_view symbol = SYM; \
904#define MTCORE_DEF_UNIT_NAME_STRS(NS, UNIT, NAME, US_NAME, ABBREV, ABBREV_ASCII, ABBREV_US, SYMBOL) \
906 struct UnitName<std::remove_cvref_t<decltype(NS::UNIT)>> { \
907 static constexpr std::string_view nameUs = US_NAME; \
908 static constexpr std::string_view name = NAME; \
909 static constexpr std::string_view abbrev = ABBREV; \
910 static constexpr std::string_view abbrevUs = ABBREV; \
911 static constexpr std::string_view abbrevAscii = ABBREV_ASCII; \
912 static constexpr std::string_view symbol = SYMBOL; \
915#define MTCORE_DEF_UNIT_NAME(NS, UNIT, ABBREV) \
917 struct UnitName<std::remove_cvref_t<decltype(NS::UNIT)>> { \
918 static constexpr std::string_view nameUs = #UNIT; \
919 static constexpr std::string_view name = #UNIT; \
920 static constexpr std::string_view abbrev = #ABBREV; \
921 static constexpr std::string_view abbrevUs = #ABBREV; \
922 static constexpr std::string_view abbrevAscii = #ABBREV; \
923 static constexpr std::string_view symbol = ""; \
926#define MTCORE_DEF_UNIT_NAME_DIFF_US(NS, UNIT, US_NAME, ABBREV) \
928 struct UnitName<std::remove_cvref_t<decltype(NS::UNIT)>> { \
929 static constexpr std::string_view nameUs = #US_NAME; \
930 static constexpr std::string_view name = #UNIT; \
931 static constexpr std::string_view abbrev = #ABBREV; \
932 static constexpr std::string_view abbrevUs = #ABBREV; \
933 static constexpr std::string_view abbrevAscii = #ABBREV; \
934 static constexpr std::string_view symbol = ""; \
937#define MTCORE_DEF_UNIT_NAME_UNIC_ABB(NS, UNIT, US_NAME, ABBREV, UNIC_ABB) \
939 struct UnitName<std::remove_cvref_t<decltype(NS::UNIT)>> { \
940 static constexpr std::string_view nameUs = #US_NAME; \
941 static constexpr std::string_view name = #UNIT; \
942 static constexpr std::string_view abbrev = #UNIC_ABB; \
943 static constexpr std::string_view abbrevUs = #UNIC_ABB; \
944 static constexpr std::string_view abbrevAscii = #ABBREV; \
945 static constexpr std::string_view symbol = ""; \
948#define MTCORE_DEF_UNIT_NAME_SI_PREFIXES_SMALL(NS, UNIT, US_NAME, ABBREV) \
949 MTCORE_DEF_UNIT_NAME_DIFF_US(NS, deci##UNIT, deci##US_NAME, d##ABBREV) \
950 MTCORE_DEF_UNIT_NAME_DIFF_US(NS, centi##UNIT, centi##US_NAME, c##ABBREV) \
951 MTCORE_DEF_UNIT_NAME_DIFF_US(NS, milli##UNIT, milli##US_NAME, m##ABBREV) \
952 MTCORE_DEF_UNIT_NAME_UNIC_ABB(NS, micro##UNIT, micro##US_NAME, u##ABBREV, μ##ABBREV) \
953 MTCORE_DEF_UNIT_NAME_DIFF_US(NS, nano##UNIT, nano##US_NAME, n##ABBREV) \
954 MTCORE_DEF_UNIT_NAME_DIFF_US(NS, pico##UNIT, pico##US_NAME, p##ABBREV) \
955 MTCORE_DEF_UNIT_NAME_DIFF_US(NS, femto##UNIT, femto##US_NAME, f##ABBREV)
957#define MTCORE_DEF_UNIT_NAME_SI_PREFIXES_LARGE(NS, UNIT, US_NAME, ABBREV) \
958 MTCORE_DEF_UNIT_NAME_DIFF_US(NS, deca##UNIT, deca##US_NAME, da##ABBREV) \
959 MTCORE_DEF_UNIT_NAME_DIFF_US(NS, hecto##UNIT, hecto##US_NAME, hm##ABBREV) \
960 MTCORE_DEF_UNIT_NAME_DIFF_US(NS, kilo##UNIT, kilo##US_NAME, km##ABBREV) \
961 MTCORE_DEF_UNIT_NAME_DIFF_US(NS, mega##UNIT, mega##US_NAME, M##ABBREV) \
962 MTCORE_DEF_UNIT_NAME_DIFF_US(NS, giga##UNIT, giga##US_NAME, G##ABBREV) \
963 MTCORE_DEF_UNIT_NAME_DIFF_US(NS, tera##UNIT, tera##US_NAME, T##ABBREV) \
964 MTCORE_DEF_UNIT_NAME_DIFF_US(NS, peta##UNIT, peta##US_NAME, P##ABBREV)
966#define MTCORE_DEF_UNIT_NAME_SI(NS, UNIT, US_NAME, ABBREV) \
967 MTCORE_DEF_UNIT_NAME_DIFF_US(NS, UNIT, US_NAME, ABBREV) \
968 MTCORE_DEF_UNIT_NAME_SI_PREFIXES_SMALL(NS, UNIT, US_NAME, ABBREV) \
969 MTCORE_DEF_UNIT_NAME_SI_PREFIXES_LARGE(NS, UNIT, US_NAME, ABBREV)
Concept to check something is a unit value.
Concept to check that a type is a unit.
constexpr UnitValue< Val, Units< Dims... > > operator*(Val lhs, const Units< Dims... > &)
Multiply a number with units to get a unit value.
constexpr auto operator/(const Units< Dims1... > &, const Units< Dims2... > &)
Divide units to combine them.
Represents prebuilt dimensions for units.
constexpr size_t LENGTH
For units representing length.
constexpr size_t STORAGE
For units representing storage.
constexpr size_t ANGLE
For units representing angles.
constexpr size_t CURRENT
For units representing current (electricity)
constexpr size_t LUMINOSITY
For units representing luminosity.
constexpr size_t TEMPERATURE
For units representing temperature.
constexpr size_t MASS
For units representing mass.
constexpr size_t SUBSTANCE
For units representing substance.
constexpr size_t TIME
For units representing time.
Base namespace for units.
Template for storing unit names.
Units< U1, UnitsSub... > Us
constexpr auto operator!=(const UnitValue &o) const noexcept
Compare with a unit of the same type.
constexpr auto operator<(const UnitValue< OV, OUs > &o) const
Compare with a unit of a convertible type.
constexpr auto operator+(const UnitValue &o) const
Add to a unit of the same type.
Underlying val
Underlying value.
constexpr auto operator==(const UnitValue &o) const noexcept
Compare with a unit of the same type.
constexpr auto operator>=(const UnitValue &o) const noexcept
Compare with a unit of the same type.
constexpr auto operator!=(const UnitValue< OV, OUs > &o) const
Compare with a unit of a convertible type.
constexpr auto convert() const
Convert to another unit value type.
constexpr auto to(Target) const
Convert to the specified unit.
constexpr auto operator<=(const UnitValue &o) const noexcept
Compare with a unit of the same type.
constexpr auto operator>(const UnitValue< OV, OUs > &o) const
Compare with a unit of a convertible type.
constexpr auto operator<=>(const UnitValue &o) const noexcept
Compare with a unit of the same type.
Underlying ValType
Value type.
constexpr auto operator==(const UnitValue< OV, OUs > &o) const
Compare with a unit of a convertible type.
constexpr UnitValue & operator+=(const UnitValue &o)
Add to a unit of the same type.
constexpr UnitValue & operator-=(const UnitValue< OV, OUs > &o)
Subtract from a unit of a compatible type.
constexpr auto operator-(const UnitValue &o) const
Subtract with a unit of the same type.
constexpr auto operator>=(const UnitValue< OV, OUs > &o) const
Compare with a unit of a convertible type.
constexpr auto operator<(const UnitValue &o) const noexcept
Compare with a unit of the same type.
constexpr auto operator<=(const UnitValue< OV, OUs > &o) const
Compare with a unit of a convertible type.
constexpr auto operator-(const UnitValue< OV, OUs > &o) const
Subtract from a unit of a compatible type.
constexpr UnitValue & operator-=(const UnitValue &o)
Subtract with a unit of the same type.
constexpr auto operator>(const UnitValue &o) const noexcept
Compare with a unit of the same type.
constexpr auto operator+(const UnitValue< OV, OUs > &o) const
Add to a unit of a compatible type.
constexpr UnitValue & operator+=(const UnitValue< OV, OUs > &o)
Add to a unit of a compatible type.
constexpr auto operator<=>(const UnitValue< OV, OUs > &o) const
Compare with a unit of a convertible type.
constexpr auto operator==(const Underlying &o) const noexcept
Compare with a number.
constexpr auto operator<=>(const Underlying &o) const noexcept
Compare with a number.
constexpr UnitValue & operator-=(const UnitValue &o)
Subtract a number.
constexpr auto operator>=(const UnitValue &o) const noexcept
Compare with another unitless value.
constexpr auto operator!=(const UnitValue &o) const noexcept
Compare with another unitless value.
constexpr auto operator>(const Underlying &o) const noexcept
Compare with a number.
constexpr auto operator<=(const Underlying &o) const noexcept
Compare with a number.
constexpr auto operator>=(const Underlying &o) const noexcept
Compare with a number.
constexpr UnitValue operator+(const UnitValue &o) const
Add a number.
constexpr auto operator>(const UnitValue &o) const noexcept
Compare with another unitless value.
constexpr UnitValue & operator+=(const UnitValue &o)
Add a number.
constexpr auto operator==(const UnitValue &o) const noexcept
Compare with another unitless value.
constexpr auto operator<(const UnitValue &o) const noexcept
Compare with another unitless value.
constexpr auto operator<=(const UnitValue &o) const noexcept
Compare with another unitless value.
constexpr UnitValue operator-(const UnitValue &o) const
Subtract a number.
constexpr auto operator<=>(const UnitValue &o) const noexcept
Compare with another unitless value.
constexpr auto operator<(const Underlying &o) const noexcept
Compare with a number.
constexpr auto operator!=(const Underlying &o) const noexcept
Compare with a number.
Represents a value with associated units.
Represents a single unit of measurement.
static constexpr size_t Id
static constexpr auto EXPONENT
static constexpr auto PiPower
Units< Mappings... > Rest
Unit< Id, S, PiPow, Tr, Exp > Head