28 #ifndef PHYS_UNITS_QUANTITY_HPP_INCLUDED 29 #define PHYS_UNITS_QUANTITY_HPP_INCLUDED 34 #include <type_traits> 44 #ifdef PHYS_UNITS_REP_TYPE 45 using Rep = PHYS_UNITS_REP_TYPE;
53 template <
typename Dims,
typename T = Rep>
60 template <
int D1,
int D2,
int D3,
int D4 = 0,
int D5 = 0,
int D6 = 0,
int D7 = 0,
73 is_all_zero = D1 == 0 && D2 == 0 && D3 == 0 && D4 == 0 && D5 == 0 && D6 == 0 &&
76 is_base = 1 == (D1 != 0) + (D2 != 0) + (D3 != 0) + (D4 != 0) + (D5 != 0) +
77 (D6 != 0) + (D7 != 0) + (D8 != 0) &&
78 1 == D1 + D2 + D3 + D4 + D5 + D6 + D7 + D8,
81 template <
int R1,
int R2,
int R3,
int R4,
int R5,
int R6,
int R7,
int R8>
83 return D1 == R1 && D2 == R2 && D3 == R3 && D4 == R4 && D5 == R5 && D6 == R6 &&
87 template <
int R1,
int R2,
int R3,
int R4,
int R5,
int R6,
int R7,
int R8>
88 constexpr
bool operator!=(
90 return !(*
this == rhs);
106 template <
typename D,
typename T>
111 template <
typename T>
116 template <
typename D,
typename T>
121 template <
typename X,
typename Y>
122 using PromoteAdd = decltype(std::declval<X>() + std::declval<Y>());
124 template <
typename X,
typename Y>
125 using PromoteMul = decltype(std::declval<X>() * std::declval<Y>());
135 template <
typename DX,
typename DY,
typename T>
138 d1 = DX::dim1 + DY::dim1,
139 d2 = DX::dim2 + DY::dim2,
140 d3 = DX::dim3 + DY::dim3,
141 d4 = DX::dim4 + DY::dim4,
142 d5 = DX::dim5 + DY::dim5,
143 d6 = DX::dim6 + DY::dim6,
144 d7 = DX::dim7 + DY::dim7,
145 d8 = DX::dim8 + DY::dim8
150 typedef Collapse<dim, T> type;
157 template <
typename DX,
typename DY>
160 template <
typename DX,
typename DY,
typename X,
typename Y>
166 template <
typename DX,
typename DY,
typename T>
169 d1 = DX::dim1 - DY::dim1,
170 d2 = DX::dim2 - DY::dim2,
171 d3 = DX::dim3 - DY::dim3,
172 d4 = DX::dim4 - DY::dim4,
173 d5 = DX::dim5 - DY::dim5,
174 d6 = DX::dim6 - DY::dim6,
175 d7 = DX::dim7 - DY::dim7,
176 d8 = DX::dim8 - DY::dim8
181 typedef Collapse<dim, T> type;
188 template <
typename DX,
typename DY>
191 template <
typename DX,
typename DY,
typename X,
typename Y>
197 template <
typename D,
typename T>
212 typedef Collapse<dim, T> type;
219 template <
typename DX,
typename DY>
222 template <
typename D,
typename X,
typename Y>
228 template <
typename D,
int N,
typename T>
243 typedef Collapse<dim, T> type;
250 template <
typename DX,
int N>
253 template <
typename D,
int N,
typename T>
254 using Power =
typename power<D, N, T>::type;
259 template <
typename D,
int N,
typename T>
262 all_even_multiples = D::dim1 % N == 0 && D::dim2 % N == 0 && D::dim3 % N == 0 &&
263 D::dim4 % N == 0 && D::dim5 % N == 0 && D::dim6 % N == 0 &&
264 D::dim7 % N == 0 && D::dim8 % N == 0
280 typedef Collapse<dim, T> type;
286 template <
typename D,
int N>
289 template <
typename D,
int N,
typename T>
290 using Root =
typename detail::root<D, N, T>::type;
302 template <
typename Dims,
typename T >
305 typedef Dims dimension_type;
307 typedef T value_type;
318 template <
typename X>
325 template <
typename X>
337 template <
typename DX,
typename X>
339 -> detail::Quotient<Dims, DX, T, X> {
346 constexpr value_type
magnitude()
const {
return m_value; }
351 constexpr dimension_type
dimension()
const {
return dimension_type{}; }
359 static constexpr quantity
zero() {
return quantity{value_type(0.0)}; }
368 return quantity{value_type(std::numeric_limits<value_type>::infinity())};
371 template <
typename _dim = dimension_type,
372 std::enable_if_t<std::is_same_v<_dim, dimensionless_d>,
bool> =
true>
373 operator double()
const {
381 constexpr
explicit quantity(value_type x)
387 enum { has_dimension = !Dims::is_all_zero };
397 template <
typename D,
typename X,
typename Y>
401 template <
typename D,
typename X>
404 template <
typename D,
typename X,
typename Y>
408 template <
typename D,
typename X,
typename Y>
412 template <
typename D,
typename X>
415 template <
typename D,
typename X,
typename Y>
419 template <
typename D,
typename X,
typename Y>
422 template <
typename D,
typename X,
typename Y>
426 template <
typename D,
typename X,
typename Y>
430 template <
typename DX,
typename DY,
typename X,
typename Y>
431 friend constexpr detail::Product<DX, DY, X, Y>
operator*(
434 template <
typename D,
typename X,
typename Y>
437 template <
typename D,
typename X,
typename Y>
441 template <
typename D,
typename X,
typename Y>
442 friend constexpr detail::Reciprocal<D, X, Y>
operator/(
const X& x,
445 template <
typename DX,
typename DY,
typename X,
typename Y>
451 template <
typename D,
typename X>
456 template <
int N,
typename D,
typename X>
459 template <
typename D,
typename X>
462 template <
typename D,
typename X>
465 template <
int N,
typename D,
typename X>
468 template <
typename D,
typename X>
471 template <
typename D,
typename X>
476 template <
typename D,
typename X,
typename Y>
479 template <
typename D,
typename X,
typename Y>
482 template <
typename D,
typename X,
typename Y>
483 friend constexpr
bool operator<(quantity<D, X>
const& x,
quantity<D, Y> const& y);
485 template <
typename D,
typename X,
typename Y>
486 friend constexpr
bool operator<=(quantity<D, X>
const& x,
quantity<D, Y> const& y);
488 template <
typename D,
typename X,
typename Y>
491 template <
typename D,
typename X,
typename Y>
496 template <
typename TNonQuantityType>
499 template <
typename Dims,
typename T>
502 template <
typename T>
520 template <
typename D,
typename X,
typename Y>
522 return x.m_value += y.m_value, x;
527 template <
typename D,
typename X>
534 template <
typename D,
typename X,
typename Y>
544 template <
typename D,
typename X,
typename Y>
546 return x.m_value -= y.m_value, x;
551 template <
typename D,
typename X>
558 template <
typename D,
typename X,
typename Y>
568 template <
typename D,
typename X,
typename Y>
570 return x.m_value *= y, x;
575 template <
typename D,
typename X,
typename Y>
583 template <
typename D,
typename X,
typename Y>
591 template <
typename DX,
typename DY,
typename X,
typename Y>
594 return detail::Product<DX, DY, X, Y>(lhs.m_value * rhs.m_value);
601 template <
typename D,
typename X,
typename Y>
603 return x.m_value /= y, x;
608 template <
typename D,
typename X,
typename Y>
616 template <
typename D,
typename X,
typename Y>
618 return detail::Reciprocal<D, X, Y>(x / y.m_value);
623 template <
typename DX,
typename DY,
typename X,
typename Y>
626 return detail::Quotient<DX, DY, X, Y>(x.m_value / y.m_value);
631 template <
typename D,
typename X>
640 template <
int N,
typename D,
typename X>
642 return detail::Power<D, N, X>(std::pow(x.m_value, X(N)));
649 template <
typename D,
typename X>
656 template <
typename D,
typename X>
665 template <
int N,
typename D,
typename X>
668 "root result dimensions must be integral");
670 return detail::Root<D, N, X>(std::pow(x.m_value, X(1.0) / N));
677 template <
typename D,
typename X>
680 "root result dimensions must be integral");
682 return detail::Root<D, 2, X>(
std::sqrt(x.m_value));
687 template <
typename D,
typename X>
690 "root result dimensions must be integral");
692 return detail::Root<D, 3, X>(
std::cbrt(x.m_value));
699 template <
typename D,
typename X,
typename Y>
701 return x.m_value == y.m_value;
706 template <
typename D,
typename X,
typename Y>
708 return x.m_value != y.m_value;
713 template <
typename D,
typename X,
typename Y>
715 return x.m_value < y.m_value;
720 template <
typename D,
typename X,
typename Y>
722 return x.m_value <= y.m_value;
727 template <
typename D,
typename X,
typename Y>
729 return x.m_value > y.m_value;
734 template <
typename D,
typename X,
typename Y>
736 return x.m_value >= y.m_value;
741 template <
typename DX,
typename X>
748 template <
typename DX,
typename X>
766 constexpr
long double quetta = 1e+30L;
767 constexpr
long double ronna = 1e+27L;
768 constexpr
long double yotta = 1e+24L;
769 constexpr
long double zetta = 1e+21L;
770 constexpr
long double exa = 1e+18L;
771 constexpr
long double peta = 1e+15L;
772 constexpr
long double tera = 1e+12L;
773 constexpr
long double giga = 1e+9L;
774 constexpr
long double mega = 1e+6L;
775 constexpr
long double kilo = 1e+3L;
776 constexpr
long double hecto = 1e+2L;
777 constexpr
long double deka = 1e+1L;
778 constexpr
long double deci = 1e-1L;
779 constexpr
long double centi = 1e-2L;
780 constexpr
long double milli = 1e-3L;
781 constexpr
long double micro = 1e-6L;
782 constexpr
long double nano = 1e-9L;
783 constexpr
long double pico = 1e-12L;
784 constexpr
long double femto = 1e-15L;
785 constexpr
long double atto = 1e-18L;
786 constexpr
long double zepto = 1e-21L;
787 constexpr
long double yocto = 1e-24L;
788 constexpr
long double ronto = 1e-27L;
789 constexpr
long double quecto = 1e-30L;
793 constexpr
long double kibi = 1024;
794 constexpr
long double mebi = 1024 * kibi;
795 constexpr
long double gibi = 1024 * mebi;
796 constexpr
long double tebi = 1024 * gibi;
797 constexpr
long double pebi = 1024 * tebi;
798 constexpr
long double exbi = 1024 * pebi;
799 constexpr
long double zebi = 1024 * exbi;
800 constexpr
long double yobi = 1024 * zebi;
872 constexpr Rep pi{Rep(3.141592653589793238462L)};
873 constexpr Rep percent{Rep(1) / 100};
880 constexpr Rep radian{Rep(1)};
881 constexpr Rep steradian{Rep(1)};
911 constexpr Rep degree_angle{pi / 180};
918 constexpr Rep minute_angle{pi / 10800};
923 constexpr Rep second_angle{pi / 648000L};
930 constexpr Rep deca{deka};
936 #define QUANTITY_DEFINE_SCALING_LITERAL(sfx, dim, factor) \ 937 constexpr quantity<dim, double> operator"" _##sfx(unsigned long long x) { \ 938 return quantity<dim, double>(detail::magnitude_tag, factor * x); \ 940 constexpr quantity<dim, double> operator"" _##sfx(long double x) { \ 941 return quantity<dim, double>(detail::magnitude_tag, factor * x); \ 944 #define QUANTITY_DEFINE_SCALING_LITERALS(pfx, dim, fact) \ 945 QUANTITY_DEFINE_SCALING_LITERAL(Q##pfx, dim, fact* quetta) \ 946 QUANTITY_DEFINE_SCALING_LITERAL(R##pfx, dim, fact* ronna) \ 947 QUANTITY_DEFINE_SCALING_LITERAL(Y##pfx, dim, fact* yotta) \ 948 QUANTITY_DEFINE_SCALING_LITERAL(Z##pfx, dim, fact* zetta) \ 949 QUANTITY_DEFINE_SCALING_LITERAL(E##pfx, dim, fact* exa) \ 950 QUANTITY_DEFINE_SCALING_LITERAL(P##pfx, dim, fact* peta) \ 951 QUANTITY_DEFINE_SCALING_LITERAL(T##pfx, dim, fact* tera) \ 952 QUANTITY_DEFINE_SCALING_LITERAL(G##pfx, dim, fact* giga) \ 953 QUANTITY_DEFINE_SCALING_LITERAL(M##pfx, dim, fact* mega) \ 954 QUANTITY_DEFINE_SCALING_LITERAL(k##pfx, dim, fact* kilo) \ 955 QUANTITY_DEFINE_SCALING_LITERAL(h##pfx, dim, fact* hecto) \ 956 QUANTITY_DEFINE_SCALING_LITERAL(da##pfx, dim, fact* deka) \ 957 QUANTITY_DEFINE_SCALING_LITERAL(pfx, dim, fact * 1) \ 958 QUANTITY_DEFINE_SCALING_LITERAL(d##pfx, dim, fact* deci) \ 959 QUANTITY_DEFINE_SCALING_LITERAL(c##pfx, dim, fact* centi) \ 960 QUANTITY_DEFINE_SCALING_LITERAL(m##pfx, dim, fact* milli) \ 961 QUANTITY_DEFINE_SCALING_LITERAL(u##pfx, dim, fact* micro) \ 962 QUANTITY_DEFINE_SCALING_LITERAL(n##pfx, dim, fact* nano) \ 963 QUANTITY_DEFINE_SCALING_LITERAL(p##pfx, dim, fact* pico) \ 964 QUANTITY_DEFINE_SCALING_LITERAL(f##pfx, dim, fact* femto) \ 965 QUANTITY_DEFINE_SCALING_LITERAL(a##pfx, dim, fact* atto) \ 966 QUANTITY_DEFINE_SCALING_LITERAL(z##pfx, dim, fact* zepto) \ 967 QUANTITY_DEFINE_SCALING_LITERAL(y##pfx, dim, fact* yocto) \ 968 QUANTITY_DEFINE_SCALING_LITERAL(r##pfx, dim, fact* ronto) \ 969 QUANTITY_DEFINE_SCALING_LITERAL(q##pfx, dim, fact* quecto) 971 #define QUANTITY_DEFINE_LITERALS(pfx, dim) QUANTITY_DEFINE_SCALING_LITERALS(pfx, dim, 1) 977 QUANTITY_DEFINE_SCALING_LITERALS(g, mass_d, 1e-3)
979 QUANTITY_DEFINE_LITERALS(m, length_d)
980 QUANTITY_DEFINE_LITERALS(s, time_interval_d)
981 QUANTITY_DEFINE_LITERALS(A, electric_current_d)
982 QUANTITY_DEFINE_LITERALS(K, thermodynamic_temperature_d)
983 QUANTITY_DEFINE_LITERALS(mol, amount_of_substance_d)
984 QUANTITY_DEFINE_LITERALS(cd, luminous_intensity_d)
991 #endif // PHYS_UNITS_QUANTITY_HPP_INCLUDED quantity< D, X > constexpr abs(quantity< D, X > const &x)
absolute value.
We could drag dimensions around individually, but it's much more convenient to package them...
detail::Root< D, N, X > constexpr nth_root(quantity< D, X > const &x)
n-th root.
constexpr auto to(quantity< DX, X > const &x) const -> detail::Quotient< Dims, DX, T, X >
convert to compatible unit, for example: (3._dm).to(meter) gives 0.3;
constexpr quantity< D, X > operator-(quantity< D, X > const &x)
dimensions< 0, 0, 0 > dimensionless_d
demensionless 'dimension'.
constexpr quantity< D, detail::PromoteMul< X, Y > > operator*(quantity< D, X > const &x, const Y &y)
quan * num
constexpr quantity(detail::magnitude_tag_t, X x)
public converting initializing constructor; requires magnitude_tag to prevent constructing a quantity...
reciprocal type generator.
constexpr quantity< D, detail::PromoteMul< X, Y > > operator/(quantity< D, X > const &x, const Y &y)
quan / num
The "collapse" template is used to avoid quantity< dimensions< 0, 0, 0 > >, i.e.
constexpr bool operator>=(quantity< D, X > const &x, quantity< D, Y > const &y)
greater-equal.
constexpr dimension_type dimension() const
the quantity's dimensions.
detail::Root< D, 3, X > constexpr cbrt(quantity< D, X > const &x)
cubic root.
constexpr detail::Power< D, 3, X > cube(quantity< D, X > const &x)
cube.
constexpr quantity< D, X > operator+(quantity< D, X > const &x)
static constexpr quantity infinity()
We also define "infinity" for each type.
constexpr quantity(quantity< Dims, X > const &x)
converting copy-assignment constructor.
typename reciprocal< DX, Rep >::dim reciprocal_d
convenience type for reciprocal dimension
constexpr DX dimension(quantity< DX, X > const &q)
quantity's dimension.
class "quantity" is the heart of the library.
tag to construct a quantity from a magnitude.
constexpr value_type magnitude() const
the quantity's magnitude.
constexpr detail::Power< D, 2, X > square(quantity< D, X > const &x)
square.
static constexpr quantity zero()
We need a "zero" of each type – for comparisons, to initialize running totals, etc.
typename root< D, N, Rep >::dim root_d
convenience type for root dimension
typename product< DX, DY, Rep >::dim product_d
convenience type for product dimension
constexpr quantity< D, X > & operator-=(quantity< D, X > &x, quantity< D, Y > const &y)
quan -= quan
detail::Root< D, 2, X > constexpr sqrt(quantity< D, X > const &x)
square root.
typename power< DX, N, Rep >::dim power_d
convenience type for power dimension
constexpr X magnitude(quantity< DX, X > const &q)
quantity's magnitude.
constexpr quantity< D, X > & operator*=(quantity< D, X > &x, const Y &y)
quan *= num
detail::Power< D, N, X > constexpr nth_power(quantity< D, X > const &x)
N-th power.
constexpr quantity< D, X > & operator+=(quantity< D, X > &x, quantity< D, Y > const &y)
quan += quan
typename quotient< DX, DY, Rep >::dim quotient_d
convenience type for quotient dimension
constexpr bool operator>(quantity< D, X > const &x, quantity< D, Y > const &y)
greater-than.
constexpr quantity< D, X > & operator/=(quantity< D, X > &x, const Y &y)
quan /= num