21template <
typename Mass = std::ratio<0>,
typename Length = std::ratio<0>,
22 typename Time = std::ratio<0>,
typename Current = std::ratio<0>,
23 typename Angle = std::ratio<0>,
typename Temperature = std::ratio<0>,
24 typename Luminosity = std::ratio<0>,
typename Moles = std::ratio<0>>
31 using length = Length;
33 using current = Current;
35 using temperature = Temperature;
36 using luminosity = Luminosity;
39 using Self =
Quantity<Mass, Length, Time, Current, Angle, Temperature,
41 static constexpr bool is_dimensionless = std::is_same_v<Self, Quantity<>>;
53 requires(!is_dimensionless)
62 requires is_dimensionless
71 constexpr Quantity(
double value, Self unit) : value(value * unit.value) {}
78 constexpr operator double() const
79 requires is_dimensionless
89 constexpr Quantity(
const Self &other) =
default;
96 constexpr double internal()
const {
return value; }
102 constexpr double to(Self unit)
const {
return value / unit.value; }
107 value += other.value;
116 requires is_dimensionless
125 value -= other.value;
134 requires is_dimensionless
157 requires is_dimensionless
165using Number = Quantity<>;
168template <
typename Mass = std::ratio<0>,
typename Length = std::ratio<0>,
169 typename Time = std::ratio<0>,
typename Current = std::ratio<0>,
170 typename Angle = std::ratio<0>,
typename Temperature = std::ratio<0>,
171 typename Luminosity = std::ratio<0>,
typename Moles = std::ratio<0>>
172void quantity_checker(Quantity<Mass, Length, Time, Current, Angle, Temperature,
173 Luminosity, Moles>) {}
183template <IsQuantity Q>
constexpr Q from(
double value, Q unit) {
184 return Q(value * unit.internal());
188template <
typename Q,
typename... Quantities>
190 std::convertible_to<Quantities, Q>) &&
194template <IsQuantity Q1, IsQuantity Q2>
197 std::ratio_add<typename Q1::length, typename Q2::length>,
198 std::ratio_add<typename Q1::time, typename Q2::time>,
199 std::ratio_add<typename Q1::current, typename Q2::current>,
200 std::ratio_add<typename Q1::angle, typename Q2::angle>,
201 std::ratio_add<typename Q1::temperature, typename Q2::temperature>,
202 std::ratio_add<typename Q1::luminosity, typename Q2::luminosity>,
203 std::ratio_add<typename Q1::moles, typename Q2::moles>>;
206template <IsQuantity Q1, IsQuantity Q2>
208 std::ratio_subtract<typename Q1::mass, typename Q2::mass>,
209 std::ratio_subtract<typename Q1::length, typename Q2::length>,
210 std::ratio_subtract<typename Q1::time, typename Q2::time>,
211 std::ratio_subtract<typename Q1::current, typename Q2::current>,
212 std::ratio_subtract<typename Q1::angle, typename Q2::angle>,
213 std::ratio_subtract<typename Q1::temperature, typename Q2::temperature>,
214 std::ratio_subtract<typename Q1::luminosity, typename Q2::luminosity>,
215 std::ratio_subtract<typename Q1::moles, typename Q2::moles>>;
218template <IsQuantity Q,
typename factor>
221 std::ratio_multiply<typename Q::length, factor>,
222 std::ratio_multiply<typename Q::time, factor>,
223 std::ratio_multiply<typename Q::current, factor>,
224 std::ratio_multiply<typename Q::angle, factor>,
225 std::ratio_multiply<typename Q::temperature, factor>,
226 std::ratio_multiply<typename Q::luminosity, factor>,
227 std::ratio_multiply<typename Q::moles, factor>>;
230template <IsQuantity Q,
typename quotient>
232 std::ratio_divide<typename Q::length, quotient>,
233 std::ratio_divide<typename Q::time, quotient>,
234 std::ratio_divide<typename Q::current, quotient>,
235 std::ratio_divide<typename Q::angle, quotient>,
236 std::ratio_divide<typename Q::temperature, quotient>,
237 std::ratio_divide<typename Q::luminosity, quotient>,
238 std::ratio_divide<typename Q::moles, quotient>>;
240template <IsQuantity Q>
constexpr Q operator+(Q rhs) {
return rhs; }
243template <IsQuantity Q, IsQuantity R>
244constexpr Q operator+(Q lhs, R rhs)
247 return Q(lhs.internal() + rhs.internal());
251template <IsQuantity Q>
constexpr Q operator-(Q rhs) {
252 return Q(-rhs.internal());
256template <IsQuantity Q, IsQuantity R>
257constexpr Q operator-(Q lhs, R rhs)
260 return Q(lhs.internal() - rhs.internal());
264template <IsQuantity Q>
265 requires(!std::is_same_v<Q, Number>)
266constexpr Q
operator*(Q quantity, Number multiple) {
267 return Q(quantity.internal() * multiple.internal());
271template <IsQuantity Q>
272 requires(!std::is_same_v<Q, Number>)
273constexpr Q
operator*(Number multiple, Q quantity) {
274 return Q(quantity.internal() * multiple.internal());
278template <IsQuantity Q>
279 requires(!std::is_same_v<Q, Number>)
280constexpr Q
operator/(Q quantity, Number divisor) {
281 return Q(quantity.internal() / divisor.internal());
285template <IsQuantity Q>
286 requires(!std::is_same_v<Q, Number>)
287constexpr auto operator/(Number enumerator, Q divisor) {
288 return Divided<Number, Q>(enumerator.internal() / divisor.internal());
292template <IsQuantity Q1, IsQuantity Q2>
293constexpr auto operator*(Q1 lhs, Q2 rhs) {
294 return Multiplied<Q1, Q2>(lhs.internal() * rhs.internal());
298template <IsQuantity Q1, IsQuantity Q2>
299constexpr auto operator/(Q1 lhs, Q2 rhs) {
300 return Divided<Q1, Q2>(lhs.internal() / rhs.internal());
304template <IsQuantity Q, IsQuantity R>
305constexpr bool operator==(
const Q &lhs,
const R &rhs)
308 return (lhs.internal() == rhs.internal());
312template <IsQuantity Q, IsQuantity R>
313constexpr bool operator!=(
const Q &lhs,
const R &rhs)
316 return (lhs.internal() != rhs.internal());
320template <IsQuantity Q, IsQuantity R>
321constexpr bool operator<=(
const Q &lhs,
const R &rhs)
324 return (lhs.internal() <= rhs.internal());
328template <IsQuantity Q, IsQuantity R>
329constexpr bool operator>=(
const Q &lhs,
const R &rhs)
332 return (lhs.internal() >= rhs.internal());
336template <IsQuantity Q, IsQuantity R>
337constexpr bool operator<(
const Q &lhs,
const R &rhs)
340 return (lhs.internal() < rhs.internal());
344template <IsQuantity Q, IsQuantity R>
345constexpr bool operator>(
const Q &lhs,
const R &rhs)
348 return (lhs.internal() > rhs.internal());
366#define NEW_UNIT(Name, long_suffix, suffix, m, l, t, i, a, o, j, n) \
368 Quantity<std::ratio<m>, std::ratio<l>, std::ratio<t>, std::ratio<i>, \
369 std::ratio<a>, std::ratio<o>, std::ratio<j>, std::ratio<n>>; \
371 constexpr Name long_suffix = Name(1.0); \
372 constexpr Name suffix = long_suffix; \
373 namespace literals { \
374 constexpr Name operator""_##long_suffix(long double value) { \
376 Quantity<std::ratio<m>, std::ratio<l>, std::ratio<t>, std::ratio<i>, \
377 std::ratio<a>, std::ratio<o>, std::ratio<j>, std::ratio<n>>( \
378 static_cast<double>(value))); \
380 constexpr Name operator""_##long_suffix(unsigned long long value) { \
382 Quantity<std::ratio<m>, std::ratio<l>, std::ratio<t>, std::ratio<i>, \
383 std::ratio<a>, std::ratio<o>, std::ratio<j>, std::ratio<n>>( \
384 static_cast<double>(value))); \
386 constexpr Name operator""_##suffix(long double value) { \
388 Quantity<std::ratio<m>, std::ratio<l>, std::ratio<t>, std::ratio<i>, \
389 std::ratio<a>, std::ratio<o>, std::ratio<j>, std::ratio<n>>( \
390 static_cast<double>(value))); \
392 constexpr Name operator""_##suffix(unsigned long long value) { \
394 Quantity<std::ratio<m>, std::ratio<l>, std::ratio<t>, std::ratio<i>, \
395 std::ratio<a>, std::ratio<o>, std::ratio<j>, std::ratio<n>>( \
396 static_cast<double>(value))); \
400#define NEW_UNIT_LITERAL(Name, long_suffix, suffix, multiple) \
402 constexpr Name suffix = multiple; \
403 constexpr Name long_suffix = multiple; \
404 namespace literals { \
405 constexpr Name operator""_##long_suffix(long double value) { \
406 return static_cast<double>(value) * multiple; \
408 constexpr Name operator""_##suffix(long double value) { \
409 return static_cast<double>(value) * multiple; \
411 constexpr Name operator""_##long_suffix(unsigned long long value) { \
412 return static_cast<double>(value) * multiple; \
414 constexpr Name operator""_##suffix(unsigned long long value) { \
415 return static_cast<double>(value) * multiple; \
419#define NEW_METRIC_PREFIXES(Name, long_base, base) \
420 NEW_UNIT_LITERAL(Name, tera##long_base, T##base, base * 1E12) \
421 NEW_UNIT_LITERAL(Name, giga##long_base, G##base, base * 1E9) \
422 NEW_UNIT_LITERAL(Name, mega##long_base, M##base, base * 1E6) \
423 NEW_UNIT_LITERAL(Name, kilo##long_base, k##base, base * 1E3) \
424 NEW_UNIT_LITERAL(Name, centi##long_base, c##base, base / 1E2) \
425 NEW_UNIT_LITERAL(Name, milli##long_base, m##base, base / 1E3) \
426 NEW_UNIT_LITERAL(Name, micro##long_base, u##base, base / 1E6) \
427 NEW_UNIT_LITERAL(Name, nano##long_base, n##base, base / 1E9) \
428 NEW_UNIT_LITERAL(Name, pico##long_base, p##base, base / 1E12)
430NEW_UNIT(Mass, kilograms, kg, 1, 0, 0, 0, 0, 0, 0, 0)
431NEW_UNIT_LITERAL(Mass, grams, g, kg / 1000)
432NEW_UNIT_LITERAL(Mass, ounces, oz, g * 28.349523125)
433NEW_UNIT_LITERAL(Mass, pounds_mass, lbm, oz * 16)
434NEW_UNIT_LITERAL(Mass, tons, ton, lbm * 2000)
436NEW_UNIT(Time, seconds, s, 0, 0, 1, 0, 0, 0, 0, 0)
437NEW_METRIC_PREFIXES(Time, seconds, s)
438NEW_UNIT_LITERAL(Time, minutes, mins, s * 60)
439NEW_UNIT_LITERAL(Time, hours, hr, mins * 60)
440NEW_UNIT_LITERAL(Time, days, day, hr * 24)
442NEW_UNIT(Length, meters, m, 0, 1, 0, 0, 0, 0, 0, 0)
443NEW_METRIC_PREFIXES(Length, meters, m)
444NEW_UNIT_LITERAL(Length, inches, in, cm * 2.54)
445NEW_UNIT_LITERAL(Length, feet, ft, in * 12)
446NEW_UNIT_LITERAL(Length, yards, yd, ft * 3)
447NEW_UNIT_LITERAL(Length, miles, mi, ft * 5280)
449NEW_UNIT_LITERAL(Length, tiles, tile, in * 23.75)
450NEW_UNIT_LITERAL(Length, football_fields, football_field, yd * 100)
451NEW_UNIT_LITERAL(Length, big_macs, big_mac, 9 * cm)
453NEW_UNIT(Area, square_meters, m2, 0, 2, 0, 0, 0, 0, 0, 0)
454NEW_UNIT_LITERAL(Area, square_yards, yd2, yd * yd)
455NEW_UNIT_LITERAL(Area, square_feet, ft2, ft * ft)
456NEW_UNIT_LITERAL(Area, square_inches, in2, in * in)
457NEW_UNIT_LITERAL(Area, acres, acre, yd2 * 4840)
459NEW_UNIT(Volume, cubic_meters, m3, 0, 3, 0, 0, 0, 0, 0, 0)
460NEW_UNIT_LITERAL(Volume, cubic_feet, ft3, ft * ft * ft)
461NEW_UNIT_LITERAL(Volume, cubic_inches, in3, in * in * in)
462NEW_UNIT_LITERAL(Volume, liters, liter, m3 * 0.001)
463NEW_UNIT_LITERAL(Volume, gallons, gal, in3 * 231)
465NEW_UNIT(Velocity, meters_per_second, mps, 0, 1, -1, 0, 0, 0, 0, 0)
466NEW_METRIC_PREFIXES(Velocity, mps, mps)
467NEW_UNIT_LITERAL(Velocity, inches_per_second, inps, in / s)
468NEW_UNIT_LITERAL(Velocity, feet_per_second, ftps, ft / s)
469NEW_UNIT_LITERAL(Velocity, miles_per_hour, miph, mi / hr)
471NEW_UNIT(Acceleration, meters_per_second_squared, mps2, 0, 1, -2, 0, 0, 0, 0, 0)
472NEW_METRIC_PREFIXES(Acceleration, mps2, mps2)
473NEW_UNIT_LITERAL(Acceleration, inches_per_second_squared, inps2, in / (s * s))
475NEW_UNIT(Jerk, meters_per_second_cubed, mps3, 0, 1, -3, 0, 0, 0, 0, 0)
476NEW_METRIC_PREFIXES(Jerk, mps3, mps3)
477NEW_UNIT_LITERAL(Jerk, inches_per_second_cubed, inps3, in / (s * s * s))
479NEW_UNIT(Absement, meter_seconds, m_s, 0, 1, 1, 0, 0, 0, 0, 0)
480NEW_UNIT_LITERAL(Absement, inch_seconds, in_s, in * s)
482NEW_UNIT(Angle, radians, rad, 0, 0, 0, 0, 1, 0, 0, 0)
483NEW_UNIT_LITERAL(Angle, degrees, deg, rad * std::numbers::pi / 180)
484NEW_UNIT_LITERAL(Angle, revolutions, rev, rad * std::numbers::pi * 2)
485NEW_UNIT_LITERAL(Angle, gradians, grad, deg * 0.9)
487NEW_UNIT(AngularVelocity, radians_per_second, radps, 0, 0, -1, 0, 1, 0, 0, 0)
488NEW_UNIT_LITERAL(AngularVelocity, degrees_per_second, dps, deg / s)
489NEW_UNIT_LITERAL(AngularVelocity, revolutions_per_second, revps, rev / s)
490NEW_UNIT_LITERAL(AngularVelocity, revolutions_per_minute, rpm, rev / mins)
492NEW_UNIT(AngularAcceleration, radians_per_second_squared, radps2, 0, 0, -2, 0,
494NEW_UNIT_LITERAL(AngularAcceleration, degrees_per_second_squared, dps2,
496NEW_UNIT_LITERAL(AngularAcceleration, revolutions_per_second_squared, revps2,
499NEW_UNIT(AngularJerk, radians_per_second_cubed, radps3, 0, 0, -3, 0, 1, 0, 0, 0)
500NEW_UNIT_LITERAL(AngularJerk, degrees_per_second_cubed, dps3, deg / (s * s * s))
501NEW_UNIT_LITERAL(AngularJerk, revolutions_per_second_cubed, revps3,
504NEW_UNIT(AngularAbsement, radian_seconds, rad_s, 0, 0, 1, 0, 1, 0, 0, 0)
505NEW_UNIT_LITERAL(AngularAbsement, degree_seconds, d_s, deg * s)
506NEW_UNIT_LITERAL(AngularAbsement, revolution_seconds, rev_s, rev * s)
508NEW_UNIT(Curvature, radians_per_meter, radpm, 0, -1, 0, 0, 1, 0, 0, 0)
509NEW_UNIT_LITERAL(Curvature, degrees_per_meter, degpm, deg / m)
510NEW_UNIT_LITERAL(Curvature, radians_per_inch, radpin, rad / in)
511NEW_UNIT_LITERAL(Curvature, degrees_per_inch, degpin, deg / in)
513NEW_UNIT(Frequency, hertz, Hz, 0, 0, -1, 0, 0, 0, 0, 0)
514NEW_METRIC_PREFIXES(Frequency, hertz, Hz)
516NEW_UNIT(Charge, coulombs, coulomb, 0, 0, 1, 1, 0, 0, 0, 0)
518NEW_UNIT(Voltage, volts, V, 1, 2, -3, -1, 0, 0, 0, 0)
519NEW_METRIC_PREFIXES(Voltage, volts, V)
521NEW_UNIT(Resistance, ohms, ohm, 1, 2, -3, -2, 0, 0, 0, 0)
522NEW_METRIC_PREFIXES(Resistance, ohms, ohm)
524NEW_UNIT(Conductance, siemens, S, -1, -2, 3, 2, 0, 0, 0, 0)
525NEW_METRIC_PREFIXES(Conductance, siemens, S)
527NEW_UNIT(Capacitance, farads, F, -1, -2, 4, 2, 0, 0, 0, 0)
528NEW_METRIC_PREFIXES(Capacitance, farads, F)
530NEW_UNIT(Inductance, henries, H, 1, 2, -2, -2, 0, 0, 0, 0)
531NEW_METRIC_PREFIXES(Inductance, henries, H)
533NEW_UNIT(Force, newtons, N, 1, 1, -2, 0, 0, 0, 0, 0)
534NEW_METRIC_PREFIXES(Force, newtons, N)
535NEW_UNIT_LITERAL(Force, pounds_force, lbf, lbm * 9.80665 * m / (s * s))
537NEW_UNIT(Power, watts, W, 1, 2, -3, 0, 0, 0, 0, 0)
538NEW_METRIC_PREFIXES(Power, watts, W)
540NEW_UNIT(Momentum, kilogram_meters_per_second, kgmps, 1, 1, -1, 0, 0, 0, 0, 0)
541NEW_UNIT_LITERAL(Momentum, newton_seconds, Ns, N * s)
548NEW_UNIT(Inertia, kilogram_meters_squared, kgm2, 1, 2, 0, 0, -2, 0, 0, 0)
550NEW_UNIT(Energy, joules, J, 1, 2, -2, 0, 0, 0, 0, 0)
551NEW_METRIC_PREFIXES(Energy, joules, J)
557NEW_UNIT(Torque, newton_meters, Nm, 1, 2, -2, 0, -1, 0, 0, 0)
558NEW_UNIT_LITERAL(Torque, pound_feet, lbft, Nm * 1.3558179483)
560NEW_UNIT(Current, amps, A, 0, 0, 0, 1, 0, 0, 0, 0)
561NEW_METRIC_PREFIXES(Current, amps, A)
563NEW_UNIT(LuminousIntensity, candelas, candela, 0, 0, 0, 0, 0, 0, 1, 0)
565NEW_UNIT(Amount, moles, mol, 0, 0, 0, 0, 0, 0, 0, 1)
567NEW_UNIT(LinearVelocityFeedforward, volts_per_meter_per_second, VpMps, 1, 1, -2,
569NEW_UNIT_LITERAL(LinearVelocityFeedforward, volts_per_inch_per_second, VpInps,
572NEW_UNIT(LinearProportionalGain, volts_per_meter, VpM, 1, 1, -3, -1, 0, 0, 0, 0)
573NEW_UNIT_LITERAL(LinearProportionalGain, volts_per_inch, VpIn, V / in)
575NEW_UNIT(LinearIntegralGain, volts_per_meter_second, VpMS, 1, 1, -4, -1, 0, 0,
577NEW_UNIT_LITERAL(LinearIntegralGain, volts_per_inch_second, VpInS, V / (in * s))
579NEW_UNIT(LinearAccelerationFeedforward, volts_per_meter_per_second_squared,
580 VpMps2, 1, 1, -1, -1, 0, 0, 0, 0)
581NEW_UNIT_LITERAL(LinearAccelerationFeedforward,
582 volts_per_inch_per_second_squared, VpInps2, V / inps2)
584NEW_UNIT(LinearDerivativeGain, volt_seconds_per_meter, VspM, 1, 1, -2, -1, 0, 0,
586NEW_UNIT_LITERAL(LinearDerivativeGain, volt_seconds_per_inch, VspIn, V / inps)
592using LinearVelocityProportionalGain = LinearDerivativeGain;
594NEW_UNIT(LinearVelocityDerivativeGain, volt_seconds_squared_per_meter, Vs2pM, 1,
595 1, -1, -1, 0, 0, 0, 0)
596NEW_UNIT_LITERAL(LinearVelocityDerivativeGain, volt_seconds_squared_per_inch,
599using LinearVelocityIntegralGain = LinearProportionalGain;
601NEW_UNIT(AngularVelocityFeedforward, volts_per_radian_per_second, VpRadPs, 1, 2,
603NEW_UNIT_LITERAL(AngularVelocityFeedforward, volts_per_degree_per_second,
606NEW_UNIT(AngularProportionalGain, volts_per_radian, VpRad, 1, 2, -3, -1, -1, 0,
608NEW_UNIT_LITERAL(AngularProportionalGain, volts_per_degree, VpDeg, V / deg)
610NEW_UNIT(AngularIntegralGain, volts_per_radian_second, VpRadS, 1, 2, -4, -1, -1,
612NEW_UNIT_LITERAL(AngularIntegralGain, volts_per_degree_second, VpDegS,
615NEW_UNIT(AngularAccelerationFeedforward, volts_per_radian_per_second_squared,
616 VpRadPs2, 1, 2, -1, -1, -1, 0, 0, 0)
617NEW_UNIT_LITERAL(AngularAccelerationFeedforward,
618 volts_per_degree_per_second_squared, VpDegPs2, V / dps2)
620NEW_UNIT(AngularDerivativeGain, volt_seconds_per_radian, VspRad, 1, 2, -2, -1,
622NEW_UNIT_LITERAL(AngularDerivativeGain, volt_seconds_per_degree, VspDeg,
625using AngularVelocityProportionalGain = AngularDerivativeGain;
627NEW_UNIT(AngularVelocityDerivativeGain, volt_seconds_squared_per_radian,
628 Vs2pRad, 1, 2, -1, -1, -1, 0, 0, 0)
629NEW_UNIT_LITERAL(AngularVelocityDerivativeGain, volt_seconds_squared_per_degree,
632using AngularVelocityIntegralGain = AngularProportionalGain;
634#undef NEW_METRIC_PREFIXES
635#undef NEW_UNIT_LITERAL
642using TemperatureQuantity =
644 std::ratio<0>, std::ratio<1>, std::ratio<0>, std::ratio<0>>;
646enum class TemperatureUnit { Kelvin, Celsius, Fahrenheit };
648class Temperature :
public TemperatureQuantity {
650 explicit constexpr Temperature() =
default;
651 explicit constexpr Temperature(
double kelvins)
652 : TemperatureQuantity(kelvins) {}
654 constexpr double to(TemperatureUnit unit)
const;
656 constexpr Temperature &operator+=(Temperature) =
delete;
657 constexpr Temperature &operator-=(Temperature) =
delete;
660constexpr TemperatureUnit kelvin = TemperatureUnit::Kelvin;
661constexpr TemperatureUnit K = kelvin;
662constexpr TemperatureUnit celsius = TemperatureUnit::Celsius;
663constexpr TemperatureUnit fahrenheit = TemperatureUnit::Fahrenheit;
665constexpr Temperature from(
double value, TemperatureUnit unit) {
667 case TemperatureUnit::Kelvin:
668 return Temperature(value);
669 case TemperatureUnit::Celsius:
670 return Temperature(value + 273.15);
671 case TemperatureUnit::Fahrenheit:
672 return Temperature((value - 32.0) * (5.0 / 9.0) + 273.15);
674 return Temperature(value);
677constexpr double Temperature::to(TemperatureUnit unit)
const {
679 case TemperatureUnit::Kelvin:
681 case TemperatureUnit::Celsius:
683 case TemperatureUnit::Fahrenheit:
684 return (
internal() - 273.15) * (9.0 / 5.0) + 32.0;
689constexpr Temperature operator+(Temperature) =
delete;
690constexpr Temperature operator-(Temperature) =
delete;
691constexpr Temperature operator+(Temperature, Temperature) =
delete;
692constexpr Temperature operator-(Temperature, Temperature) =
delete;
696constexpr Temperature
operator""_kelvin(
long double value) {
697 return from(
static_cast<double>(value), kelvin);
700constexpr Temperature
operator""_kelvin(
unsigned long long value) {
701 return from(
static_cast<double>(value), kelvin);
704constexpr Temperature
operator""_K(
long double value) {
705 return from(
static_cast<double>(value), kelvin);
708constexpr Temperature
operator""_K(
unsigned long long value) {
709 return from(
static_cast<double>(value), kelvin);
712constexpr Temperature
operator""_celsius(
long double value) {
713 return from(
static_cast<double>(value), celsius);
716constexpr Temperature
operator""_celsius(
unsigned long long value) {
717 return from(
static_cast<double>(value), celsius);
720constexpr Temperature
operator""_fahrenheit(
long double value) {
721 return from(
static_cast<double>(value), fahrenheit);
724constexpr Temperature
operator""_fahrenheit(
unsigned long long value) {
725 return from(
static_cast<double>(value), fahrenheit);
735constexpr auto to_quantity(T value)
736 -> std::conditional_t<std::is_arithmetic_v<T>, Number, T> {
737 if constexpr (std::is_arithmetic_v<T>)
738 return Number(value);
744using quantity_type =
decltype(to_quantity(std::declval<T>()));
746template <
typename T,
typename... U>
756template <
typename T>
constexpr auto abs(
const T &lhs) {
757 auto q = to_quantity(lhs);
758 using Q =
decltype(q);
760 return Q(cevalm::abs(q.internal()));
762 return Q(std::abs(q.internal()));
766template <
typename T,
typename U>
767 requires IsomorphicValues<T, U>
768constexpr auto max(
const T &lhs,
const U &rhs) {
769 auto qlhs = to_quantity(lhs);
770 auto qrhs = to_quantity(rhs);
771 return (qlhs > qrhs ? qlhs : qrhs);
774template <
typename T,
typename U>
775 requires IsomorphicValues<T, U>
776constexpr auto min(
const T &lhs,
const U &rhs) {
777 auto qlhs = to_quantity(lhs);
778 auto qrhs = to_quantity(rhs);
779 return (qlhs < qrhs ? qlhs : qrhs);
782template <
typename T>
constexpr auto sgn(
const T &lhs) {
783 auto q = to_quantity(lhs);
784 if (q.internal() > 0)
786 if (q.internal() < 0)
791template <
int R,
typename T>
793constexpr auto pow(
const T &lhs) {
794 if constexpr (R == 0) {
797 auto q = to_quantity(lhs);
798 using Q =
decltype(q);
799 using S = Exponentiated<Q, std::ratio<R>>;
801 return S(cevalm::pow(q.internal(), R));
803 return S(std::pow(q.internal(), R));
808template <
typename T>
constexpr auto square(
const T &lhs) {
return lhs * lhs; }
810template <
typename T>
constexpr auto cube(
const T &lhs) {
811 return lhs * lhs * lhs;
814template <
int R,
typename T>
815constexpr auto root(
const T &lhs)
818 auto q = to_quantity(lhs);
819 using Q =
decltype(q);
820 using S = Rooted<Q, std::ratio<R>>;
822 const double val = q.internal();
823 const bool odd_and_negative = (R % 2 != 0) && (val < 0);
824 const double base = odd_and_negative ? -val : val;
830 res = cevalm::sqrt(base);
832 res = std::sqrt(base);
836 res = cevalm::cbrt(base);
838 res = std::cbrt(base);
842 res = cevalm::pow(base, 1.0 / R);
844 res = std::pow(base, 1.0 / R);
848 return S(odd_and_negative ? -res : res);
851template <
typename T>
constexpr auto sqrt(
const T &lhs) {
return root<2>(lhs); }
853template <
typename T>
constexpr auto cbrt(
const T &lhs) {
return root<3>(lhs); }
855template <
typename T,
typename U>
856 requires IsomorphicValues<T, U>
857constexpr auto hypot(
const T &lhs,
const U &rhs) {
858 auto qlhs = to_quantity(lhs);
859 auto qrhs = to_quantity(rhs);
861 return decltype(qlhs)(cevalm::hypot(qlhs.internal(), qrhs.internal()));
863 return decltype(qlhs)(std::hypot(qlhs.internal(), qrhs.internal()));
867template <
typename T,
typename U>
868 requires IsomorphicValues<T, U>
869constexpr auto mod(
const T &lhs,
const U &rhs) {
870 auto qlhs = to_quantity(lhs);
871 auto qrhs = to_quantity(rhs);
873 return decltype(qlhs)(cevalm::fmod(qlhs.internal(), qrhs.internal()));
875 return decltype(qlhs)(std::fmod(qlhs.internal(), qrhs.internal()));
879template <
typename T,
typename U>
880constexpr auto copysign(
const T &lhs,
const U &rhs) {
881 auto qlhs = to_quantity(lhs);
882 auto qrhs = to_quantity(rhs);
884 return decltype(qlhs)(cevalm::copysign(qlhs.internal(), qrhs.internal()));
886 return decltype(qlhs)(std::copysign(qlhs.internal(), qrhs.internal()));
890template <
typename T>
constexpr auto signbit(
const T &lhs) {
891 auto q = to_quantity(lhs);
892 return std::signbit(q.internal());
895template <
typename T,
typename U,
typename V>
896 requires IsomorphicValues<T, U, V>
897constexpr auto clamp(
const T &lhs,
const U &lo,
const V &hi) {
898 auto qlhs = to_quantity(lhs);
899 auto qlo = to_quantity(lo);
900 auto qhi = to_quantity(hi);
901 return decltype(qlhs)(
902 std::clamp(qlhs.internal(), qlo.internal(), qhi.internal()));
905template <
typename T,
typename U>
906 requires IsomorphicValues<T, U>
907constexpr auto ceil(
const T &lhs,
const U &rhs) {
908 auto qlhs = to_quantity(lhs);
909 auto qrhs = to_quantity(rhs);
911 return decltype(qlhs)(cevalm::ceil(qlhs.internal() / qrhs.internal()) *
914 return decltype(qlhs)(std::ceil(qlhs.internal() / qrhs.internal()) *
919template <
typename T,
typename U>
920 requires IsomorphicValues<T, U>
921constexpr auto floor(
const T &lhs,
const U &rhs) {
922 auto qlhs = to_quantity(lhs);
923 auto qrhs = to_quantity(rhs);
925 return decltype(qlhs)(cevalm::floor(qlhs.internal() / qrhs.internal()) *
928 return decltype(qlhs)(std::floor(qlhs.internal() / qrhs.internal()) *
933template <
typename T,
typename U>
934 requires IsomorphicValues<T, U>
935constexpr auto trunc(
const T &lhs,
const U &rhs) {
936 auto qlhs = to_quantity(lhs);
937 auto qrhs = to_quantity(rhs);
939 return decltype(qlhs)(cevalm::trunc(qlhs.internal() / qrhs.internal()) *
942 return decltype(qlhs)(std::trunc(qlhs.internal() / qrhs.internal()) *
947template <
typename T,
typename U>
948 requires IsomorphicValues<T, U>
949constexpr auto round(
const T &lhs,
const U &rhs) {
950 auto qlhs = to_quantity(lhs);
951 auto qrhs = to_quantity(rhs);
953 return decltype(qlhs)(cevalm::round(qlhs.internal() / qrhs.internal()) *
956 return decltype(qlhs)(std::round(qlhs.internal() / qrhs.internal()) *
964 IsQuantity<Q> && std::ratio_equal_v<typename Q::mass, std::ratio<0>> &&
965 std::ratio_equal_v<typename Q::current, std::ratio<0>> &&
966 std::ratio_equal_v<typename Q::temperature, std::ratio<0>> &&
967 std::ratio_equal_v<typename Q::luminosity, std::ratio<0>> &&
968 std::ratio_equal_v<typename Q::moles, std::ratio<0>>;
974template <KinematicQuantity Q>
975 requires std::ratio_equal_v<typename Q::angle, std::ratio<1>> &&
976 std::ratio_equal_v<typename Q::length, std::ratio<0>>
977constexpr auto to_linear(Q angular_distance, Length diameter) {
978 return angular_distance * (diameter / 2.0) / rad;
985template <KinematicQuantity Q>
986 requires std::ratio_equal_v<typename Q::length, std::ratio<1>> &&
987 std::ratio_equal_v<typename Q::angle, std::ratio<0>>
988constexpr auto to_angular(Q linear_distance, Length diameter) {
989 return linear_distance / (diameter / 2.0) * rad;
993constexpr Number sin(Angle angle) {
995 return Number(cevalm::sin(angle.internal()));
997 return Number(std::sin(angle.internal()));
1001constexpr Number cos(Angle angle) {
1003 return Number(cevalm::cos(angle.internal()));
1005 return Number(std::cos(angle.internal()));
1009constexpr Number tan(Angle angle) {
1011 return Number(cevalm::tan(angle.internal()));
1013 return Number(std::tan(angle.internal()));
1017constexpr Angle asin(Number value) {
1019 return Angle(cevalm::asin(value.internal()));
1021 return Angle(std::asin(value.internal()));
1025constexpr Angle acos(Number value) {
1027 return Angle(cevalm::acos(value.internal()));
1029 return Angle(std::acos(value.internal()));
1033constexpr Angle atan(Number value) {
1035 return Angle(cevalm::atan(value.internal()));
1037 return Angle(std::atan(value.internal()));
1041template <
typename T,
typename U>
1042 requires IsomorphicValues<T, U>
1043constexpr Angle atan2(
const T &y,
const U &x) {
1044 auto qy = to_quantity(y);
1045 auto qx = to_quantity(x);
1047 return Angle(cevalm::atan2(qy.internal(), qx.internal()));
1049 return Angle(std::atan2(qy.internal(), qx.internal()));
1054constexpr Angle wrap_positive(Angle angle) {
1055 Angle wrapped = mod(angle, rev);
1056 return wrapped < Angle(0) ? wrapped + rev : wrapped;
1059constexpr Angle wrap_signed(Angle angle) {
1060 return wrap_positive(angle + rev / 2.0) - rev / 2.0;
1063constexpr Angle shortest_difference(Angle start, Angle end) {
1064 return wrap_signed(end - start);
constexpr Quantity()
Default to value of 0.
Definition units.h:45
constexpr Self & operator*=(double scalar)
Multiplies this quantity by a scalar.
Definition units.h:141
constexpr Self & operator/=(double divisor)
Divides this quantity by a scalar.
Definition units.h:147
constexpr Quantity(double value)
Definition units.h:52
constexpr Self & operator+=(double other)
Definition units.h:115
constexpr double internal() const
Definition units.h:96
constexpr Self & operator-=(Self other)
Subtracts another quantity's value from this.
Definition units.h:124
constexpr double to(Self unit) const
Definition units.h:102
constexpr Self & operator+=(Self other)
Adds another quantity's value to this.
Definition units.h:106
constexpr Quantity(double value)
Definition units.h:61
constexpr Quantity(double value, Self unit)
Definition units.h:71
constexpr Self & operator=(const double &rhs)
Definition units.h:156
constexpr Self & operator-=(double other)
Definition units.h:133
constexpr Quantity(const Self &other)=default
Used to require a Quantity be passed in a template (instead of typename Q).
Definition units.h:177
Isomorphic concept checks whether dimensions are the same between quantities.
Definition units.h:189
Only allows nonzero length, time, angle for the next two functions.
Definition units.h:963