22 typename Mass = std::ratio<0>,
typename Length = std::ratio<0>,
typename Time = std::ratio<0>,
23 typename Current = std::ratio<0>,
typename Angle = std::ratio<0>,
24 typename Temperature = std::ratio<0>,
typename Luminosity = std::ratio<0>,
25 typename Moles = std::ratio<0>>
32 using length = Length;
34 using current = Current;
37 using luminosity = Luminosity;
41 static constexpr bool is_dimensionless = std::is_same_v<Self, Quantity<>>;
52 requires(!is_dimensionless)
61 requires is_dimensionless
70 constexpr Quantity(
double value, Self unit) : value(value * unit.value) {}
77 constexpr operator double() const
78 requires is_dimensionless
88 constexpr Quantity(
const Self& other) =
default;
95 constexpr double internal()
const {
return value; }
101 constexpr double to(Self unit)
const {
return value / unit.value; }
105 value += other.value;
114 requires is_dimensionless
122 value -= other.value;
131 requires is_dimensionless
154 requires is_dimensionless
166 typename Mass = std::ratio<0>,
typename Length = std::ratio<0>,
typename Time = std::ratio<0>,
167 typename Current = std::ratio<0>,
typename Angle = std::ratio<0>,
168 typename Temperature = std::ratio<0>,
typename Luminosity = std::ratio<0>,
169 typename Moles = std::ratio<0>>
182template <IsQuantity Q>
183constexpr Q
from(
double value, Q unit) {
184 return Q(value * unit.internal());
188template <
typename Q,
typename... Quantities>
190 ((std::convertible_to<Q, Quantities> && std::convertible_to<Quantities, Q>) && ...);
193template <IsQuantity Q1, IsQuantity Q2>
195 std::ratio_add<typename Q1::mass, typename Q2::mass>,
196 std::ratio_add<typename Q1::length, typename Q2::length>,
197 std::ratio_add<typename Q1::time, typename Q2::time>,
198 std::ratio_add<typename Q1::current, typename Q2::current>,
199 std::ratio_add<typename Q1::angle, typename Q2::angle>,
200 std::ratio_add<typename Q1::temperature, typename Q2::temperature>,
201 std::ratio_add<typename Q1::luminosity, typename Q2::luminosity>,
202 std::ratio_add<typename Q1::moles, typename Q2::moles>>;
205template <IsQuantity Q1, IsQuantity Q2>
207 std::ratio_subtract<typename Q1::mass, typename Q2::mass>,
208 std::ratio_subtract<typename Q1::length, typename Q2::length>,
209 std::ratio_subtract<typename Q1::time, typename Q2::time>,
210 std::ratio_subtract<typename Q1::current, typename Q2::current>,
211 std::ratio_subtract<typename Q1::angle, typename Q2::angle>,
212 std::ratio_subtract<typename Q1::temperature, typename Q2::temperature>,
213 std::ratio_subtract<typename Q1::luminosity, typename Q2::luminosity>,
214 std::ratio_subtract<typename Q1::moles, typename Q2::moles>>;
217template <IsQuantity Q,
typename factor>
219 std::ratio_multiply<typename Q::mass, factor>, std::ratio_multiply<typename Q::length, factor>,
220 std::ratio_multiply<typename Q::time, factor>, std::ratio_multiply<typename Q::current, factor>,
221 std::ratio_multiply<typename Q::angle, factor>,
222 std::ratio_multiply<typename Q::temperature, factor>,
223 std::ratio_multiply<typename Q::luminosity, factor>,
224 std::ratio_multiply<typename Q::moles, factor>>;
227template <IsQuantity Q,
typename quotient>
229 std::ratio_divide<typename Q::mass, quotient>, std::ratio_divide<typename Q::length, quotient>,
230 std::ratio_divide<typename Q::time, quotient>, std::ratio_divide<typename Q::current, quotient>,
231 std::ratio_divide<typename Q::angle, quotient>,
232 std::ratio_divide<typename Q::temperature, quotient>,
233 std::ratio_divide<typename Q::luminosity, quotient>,
234 std::ratio_divide<typename Q::moles, quotient>>;
236template <IsQuantity Q>
237constexpr Q operator+(Q rhs) {
242template <IsQuantity Q, IsQuantity R>
243constexpr Q operator+(Q lhs, R rhs)
246 return Q(lhs.internal() + rhs.internal());
250template <IsQuantity Q>
252 return Q(-rhs.internal());
256template <IsQuantity Q, IsQuantity R>
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) {
292template <IsQuantity Q1, IsQuantity Q2>
298template <IsQuantity Q1, IsQuantity Q2>
304template <IsQuantity Q, IsQuantity R>
308 return (lhs.internal() == rhs.internal());
312template <IsQuantity Q, IsQuantity R>
316 return (lhs.internal() != rhs.internal());
320template <IsQuantity Q, IsQuantity R>
324 return (lhs.internal() <= rhs.internal());
328template <IsQuantity Q, IsQuantity R>
332 return (lhs.internal() >= rhs.internal());
336template <IsQuantity Q, IsQuantity R>
340 return (lhs.internal() < rhs.internal());
344template <IsQuantity Q, IsQuantity R>
348 return (lhs.internal() > rhs.internal());
366#define NEW_UNIT(Name, long_suffix, suffix, m, l, t, i, a, o, j, n) \
367 using Name = Quantity< \
368 std::ratio<m>, std::ratio<l>, std::ratio<t>, std::ratio<i>, std::ratio<a>, std::ratio<o>, \
369 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) { \
377 std::ratio<m>, std::ratio<l>, std::ratio<t>, std::ratio<i>, std::ratio<a>, \
378 std::ratio<o>, std::ratio<j>, std::ratio<n>>(static_cast<double>(value)) \
381 constexpr Name operator""_##long_suffix(unsigned long long value) { \
384 std::ratio<m>, std::ratio<l>, std::ratio<t>, std::ratio<i>, std::ratio<a>, \
385 std::ratio<o>, std::ratio<j>, std::ratio<n>>(static_cast<double>(value)) \
388 constexpr Name operator""_##suffix(long double value) { \
391 std::ratio<m>, std::ratio<l>, std::ratio<t>, std::ratio<i>, std::ratio<a>, \
392 std::ratio<o>, std::ratio<j>, std::ratio<n>>(static_cast<double>(value)) \
395 constexpr Name operator""_##suffix(unsigned long long value) { \
398 std::ratio<m>, std::ratio<l>, std::ratio<t>, std::ratio<i>, std::ratio<a>, \
399 std::ratio<o>, std::ratio<j>, std::ratio<n>>(static_cast<double>(value)) \
404#define NEW_UNIT_LITERAL(Name, long_suffix, suffix, multiple) \
406 constexpr Name suffix = multiple; \
407 constexpr Name long_suffix = multiple; \
408 namespace literals { \
409 constexpr Name operator""_##long_suffix(long double value) { \
410 return static_cast<double>(value) * multiple; \
412 constexpr Name operator""_##suffix(long double value) { \
413 return static_cast<double>(value) * multiple; \
415 constexpr Name operator""_##long_suffix(unsigned long long value) { \
416 return static_cast<double>(value) * multiple; \
418 constexpr Name operator""_##suffix(unsigned long long value) { \
419 return static_cast<double>(value) * multiple; \
423#define NEW_METRIC_PREFIXES(Name, long_base, base) \
424 NEW_UNIT_LITERAL(Name, tera##long_base, T##base, base * 1E12) \
425 NEW_UNIT_LITERAL(Name, giga##long_base, G##base, base * 1E9) \
426 NEW_UNIT_LITERAL(Name, mega##long_base, M##base, base * 1E6) \
427 NEW_UNIT_LITERAL(Name, kilo##long_base, k##base, base * 1E3) \
428 NEW_UNIT_LITERAL(Name, centi##long_base, c##base, base / 1E2) \
429 NEW_UNIT_LITERAL(Name, milli##long_base, m##base, base / 1E3) \
430 NEW_UNIT_LITERAL(Name, micro##long_base, u##base, base / 1E6) \
431 NEW_UNIT_LITERAL(Name, nano##long_base, n##base, base / 1E9) \
432 NEW_UNIT_LITERAL(Name, pico##long_base, p##base, base / 1E12)
434NEW_UNIT(Mass, kilograms, kg, 1, 0, 0, 0, 0, 0, 0, 0)
435NEW_UNIT_LITERAL(Mass, grams, g, kg / 1000)
436NEW_UNIT_LITERAL(Mass, ounces, oz, g * 28.349523125)
437NEW_UNIT_LITERAL(Mass, pounds_mass, lbm, oz * 16)
438NEW_UNIT_LITERAL(Mass, tons, ton, lbm * 2000)
440NEW_UNIT(Time, seconds, s, 0, 0, 1, 0, 0, 0, 0, 0)
441NEW_METRIC_PREFIXES(Time, seconds, s)
442NEW_UNIT_LITERAL(Time, minutes, mins, s * 60)
443NEW_UNIT_LITERAL(Time, hours, hr, mins * 60)
444NEW_UNIT_LITERAL(Time, days, day, hr * 24)
446NEW_UNIT(Length, meters, m, 0, 1, 0, 0, 0, 0, 0, 0)
447NEW_METRIC_PREFIXES(Length, meters, m)
448NEW_UNIT_LITERAL(Length, inches, in, cm * 2.54)
449NEW_UNIT_LITERAL(Length, feet, ft, in * 12)
450NEW_UNIT_LITERAL(Length, yards, yd, ft * 3)
451NEW_UNIT_LITERAL(Length, miles, mi, ft * 5280)
453NEW_UNIT_LITERAL(Length, tiles, tile, in * 23.75)
454NEW_UNIT_LITERAL(Length, football_fields, football_field, yd * 100)
455NEW_UNIT_LITERAL(Length, big_macs, big_mac, 9 * cm)
457NEW_UNIT(Area, square_meters, m2, 0, 2, 0, 0, 0, 0, 0, 0)
458NEW_UNIT_LITERAL(Area, square_yards, yd2, yd* yd)
459NEW_UNIT_LITERAL(Area, square_feet, ft2, ft* ft)
460NEW_UNIT_LITERAL(Area, square_inches, in2, in* in)
461NEW_UNIT_LITERAL(Area, acres, acre, yd2 * 4840)
463NEW_UNIT(Volume, cubic_meters, m3, 0, 3, 0, 0, 0, 0, 0, 0)
464NEW_UNIT_LITERAL(Volume, cubic_feet, ft3, ft * ft * ft)
465NEW_UNIT_LITERAL(Volume, cubic_inches, in3, in * in * in)
466NEW_UNIT_LITERAL(Volume, liters, liter, m3 * 0.001)
467NEW_UNIT_LITERAL(Volume, gallons, gal, in3 * 231)
469NEW_UNIT(Velocity, meters_per_second, mps, 0, 1, -1, 0, 0, 0, 0, 0)
470NEW_METRIC_PREFIXES(Velocity, mps, mps)
471NEW_UNIT_LITERAL(Velocity, inches_per_second, inps, in / s)
472NEW_UNIT_LITERAL(Velocity, feet_per_second, ftps, ft / s)
473NEW_UNIT_LITERAL(Velocity, miles_per_hour, miph, mi / hr)
475NEW_UNIT(Acceleration, meters_per_second_squared, mps2, 0, 1, -2, 0, 0, 0, 0, 0)
476NEW_METRIC_PREFIXES(Acceleration, mps2, mps2)
477NEW_UNIT_LITERAL(Acceleration, inches_per_second_squared, inps2, in / (s * s))
479NEW_UNIT(Jerk, meters_per_second_cubed, mps3, 0, 1, -3, 0, 0, 0, 0, 0)
480NEW_METRIC_PREFIXES(Jerk, mps3, mps3)
481NEW_UNIT_LITERAL(Jerk, inches_per_second_cubed, inps3, in / (s * s * s))
483NEW_UNIT(Absement, meter_seconds, m_s, 0, 1, 1, 0, 0, 0, 0, 0)
484NEW_UNIT_LITERAL(Absement, inch_seconds, in_s, in* s)
486NEW_UNIT(Angle, radians, rad, 0, 0, 0, 0, 1, 0, 0, 0)
487NEW_UNIT_LITERAL(Angle, degrees, deg, rad* std::numbers::pi / 180)
488NEW_UNIT_LITERAL(Angle, revolutions, rev, rad* std::numbers::pi * 2)
489NEW_UNIT_LITERAL(Angle, gradians, grad, deg * 0.9)
491NEW_UNIT(AngularVelocity, radians_per_second, radps, 0, 0, -1, 0, 1, 0, 0, 0)
492NEW_UNIT_LITERAL(AngularVelocity, degrees_per_second, dps, deg / s)
493NEW_UNIT_LITERAL(AngularVelocity, revolutions_per_second, revps, rev / s)
494NEW_UNIT_LITERAL(AngularVelocity, revolutions_per_minute, rpm, rev / mins)
496NEW_UNIT(AngularAcceleration, radians_per_second_squared, radps2, 0, 0, -2, 0, 1, 0, 0, 0)
497NEW_UNIT_LITERAL(AngularAcceleration, degrees_per_second_squared, dps2, deg / (s * s))
498NEW_UNIT_LITERAL(AngularAcceleration, revolutions_per_second_squared, revps2, rev / (s * s))
500NEW_UNIT(AngularJerk, radians_per_second_cubed, radps3, 0, 0, -3, 0, 1, 0, 0, 0)
501NEW_UNIT_LITERAL(AngularJerk, degrees_per_second_cubed, dps3, deg / (s * s * s))
502NEW_UNIT_LITERAL(AngularJerk, revolutions_per_second_cubed, revps3, rev / (s * s * s))
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, -1, 0, 0, 0, 0)
568NEW_UNIT_LITERAL(LinearVelocityFeedforward, volts_per_inch_per_second, VpInps, V / inps)
570NEW_UNIT(LinearProportionalGain, volts_per_meter, VpM, 1, 1, -3, -1, 0, 0, 0, 0)
571NEW_UNIT_LITERAL(LinearProportionalGain, volts_per_inch, VpIn, V / in)
573NEW_UNIT(LinearIntegralGain, volts_per_meter_second, VpMS, 1, 1, -4, -1, 0, 0, 0, 0)
574NEW_UNIT_LITERAL(LinearIntegralGain, volts_per_inch_second, VpInS, V / (in * s))
577 LinearAccelerationFeedforward, volts_per_meter_per_second_squared, VpMps2, 1, 1, -1, -1, 0, 0,
581 LinearAccelerationFeedforward, volts_per_inch_per_second_squared, VpInps2, V / inps2
584NEW_UNIT(LinearDerivativeGain, volt_seconds_per_meter, VspM, 1, 1, -2, -1, 0, 0, 0, 0)
585NEW_UNIT_LITERAL(LinearDerivativeGain, volt_seconds_per_inch, VspIn, V / inps)
591using LinearVelocityProportionalGain = LinearDerivativeGain;
594 LinearVelocityDerivativeGain, volt_seconds_squared_per_meter, Vs2pM, 1, 1, -1, -1, 0, 0, 0, 0
596NEW_UNIT_LITERAL(LinearVelocityDerivativeGain, volt_seconds_squared_per_inch, Vs2pIn, V / inps2)
598using LinearVelocityIntegralGain = LinearProportionalGain;
601 AngularVelocityFeedforward, volts_per_radian_per_second, VpRadPs, 1, 2, -2, -1, -1, 0, 0, 0
603NEW_UNIT_LITERAL(AngularVelocityFeedforward, volts_per_degree_per_second, VpDegPs, V / dps)
605NEW_UNIT(AngularProportionalGain, volts_per_radian, VpRad, 1, 2, -3, -1, -1, 0, 0, 0)
606NEW_UNIT_LITERAL(AngularProportionalGain, volts_per_degree, VpDeg, V / deg)
608NEW_UNIT(AngularIntegralGain, volts_per_radian_second, VpRadS, 1, 2, -4, -1, -1, 0, 0, 0)
609NEW_UNIT_LITERAL(AngularIntegralGain, volts_per_degree_second, VpDegS, V / (deg * s))
612 AngularAccelerationFeedforward, volts_per_radian_per_second_squared, VpRadPs2, 1, 2, -1, -1, -1,
616 AngularAccelerationFeedforward, volts_per_degree_per_second_squared, VpDegPs2, V / dps2
619NEW_UNIT(AngularDerivativeGain, volt_seconds_per_radian, VspRad, 1, 2, -2, -1, -1, 0, 0, 0)
620NEW_UNIT_LITERAL(AngularDerivativeGain, volt_seconds_per_degree, VspDeg, V / dps)
622using AngularVelocityProportionalGain = AngularDerivativeGain;
625 AngularVelocityDerivativeGain, volt_seconds_squared_per_radian, Vs2pRad, 1, 2, -1, -1, -1, 0, 0,
628NEW_UNIT_LITERAL(AngularVelocityDerivativeGain, volt_seconds_squared_per_degree, Vs2pDeg, V / dps2)
630using AngularVelocityIntegralGain = AngularProportionalGain;
632#undef NEW_METRIC_PREFIXES
633#undef NEW_UNIT_LITERAL
640using TemperatureQuantity =
Quantity<
641 std::ratio<0>, std::ratio<0>, std::ratio<0>, std::ratio<0>, std::ratio<0>, std::ratio<1>,
642 std::ratio<0>, std::ratio<0>>;
644enum class TemperatureUnit { Kelvin, Celsius, Fahrenheit };
646class Temperature :
public TemperatureQuantity {
648 explicit constexpr Temperature() =
default;
649 explicit constexpr Temperature(
double kelvins) : TemperatureQuantity(kelvins) {}
651 constexpr double to(TemperatureUnit unit)
const;
653 constexpr Temperature& operator+=(Temperature) =
delete;
654 constexpr Temperature& operator-=(Temperature) =
delete;
657constexpr TemperatureUnit kelvin = TemperatureUnit::Kelvin;
658constexpr TemperatureUnit K = kelvin;
659constexpr TemperatureUnit celsius = TemperatureUnit::Celsius;
660constexpr TemperatureUnit fahrenheit = TemperatureUnit::Fahrenheit;
664 case TemperatureUnit::Kelvin:
666 case TemperatureUnit::Celsius:
668 case TemperatureUnit::Fahrenheit:
669 return Temperature((value - 32.0) * (5.0 / 9.0) + 273.15);
671 return Temperature(value);
674constexpr double Temperature::to(TemperatureUnit unit)
const {
676 case TemperatureUnit::Kelvin:
678 case TemperatureUnit::Celsius:
680 case TemperatureUnit::Fahrenheit:
681 return (
internal() - 273.15) * (9.0 / 5.0) + 32.0;
693constexpr Temperature operator""_kelvin(
long double value) {
694 return from(
static_cast<double>(value), kelvin);
697constexpr Temperature operator""_kelvin(
unsigned long long value) {
698 return from(
static_cast<double>(value), kelvin);
701constexpr Temperature operator""_K(
long double value) {
702 return from(
static_cast<double>(value), kelvin);
705constexpr Temperature operator""_K(
unsigned long long value) {
706 return from(
static_cast<double>(value), kelvin);
709constexpr Temperature operator""_celsius(
long double value) {
710 return from(
static_cast<double>(value), celsius);
713constexpr Temperature operator""_celsius(
unsigned long long value) {
714 return from(
static_cast<double>(value), celsius);
717constexpr Temperature operator""_fahrenheit(
long double value) {
718 return from(
static_cast<double>(value), fahrenheit);
721constexpr Temperature operator""_fahrenheit(
unsigned long long value) {
722 return from(
static_cast<double>(value), fahrenheit);
733 if constexpr (std::is_arithmetic_v<T>)
740using quantity_type =
decltype(
to_quantity(std::declval<T>()));
742template <
typename T,
typename... U>
753constexpr auto abs(
const T& lhs) {
755 using Q =
decltype(q);
757 return Q(cevalm::abs(q.internal()));
759 return Q(std::abs(q.internal()));
763template <
typename T,
typename U>
765constexpr auto max(
const T& lhs,
const U& rhs) {
768 return (qlhs > qrhs ? qlhs : qrhs);
771template <
typename T,
typename U>
772 requires IsomorphicValues<T, U>
773constexpr auto min(
const T& lhs,
const U& rhs) {
776 return (qlhs < qrhs ? qlhs : qrhs);
780constexpr auto sgn(
const T& lhs) {
782 if (q.internal() > 0)
return Number(1);
783 if (q.internal() < 0)
return Number(-1);
787template <
int R,
typename T>
789constexpr auto pow(
const T& lhs) {
790 if constexpr (R == 0) {
794 using Q =
decltype(q);
797 return S(cevalm::pow(q.internal(), R));
799 return S(std::pow(q.internal(), R));
805constexpr auto square(
const T& lhs) {
810constexpr auto cube(
const T& lhs) {
811 return lhs * lhs * lhs;
814template <
int R,
typename T>
815constexpr auto root(
const T& lhs)
819 using Q =
decltype(q);
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);
852constexpr auto sqrt(
const T& lhs) {
857constexpr auto cbrt(
const T& lhs) {
861template <
typename T,
typename U>
863constexpr auto hypot(
const T& lhs,
const U& rhs) {
867 return decltype(qlhs)(cevalm::hypot(qlhs.internal(), qrhs.internal()));
869 return decltype(qlhs)(std::hypot(qlhs.internal(), qrhs.internal()));
873template <
typename T,
typename U>
875constexpr auto mod(
const T& lhs,
const U& rhs) {
879 return decltype(qlhs)(cevalm::fmod(qlhs.internal(), qrhs.internal()));
881 return decltype(qlhs)(std::fmod(qlhs.internal(), qrhs.internal()));
885template <
typename T,
typename U>
886constexpr auto copysign(
const T& lhs,
const U& rhs) {
890 return decltype(qlhs)(cevalm::copysign(qlhs.internal(), qrhs.internal()));
892 return decltype(qlhs)(std::copysign(qlhs.internal(), qrhs.internal()));
897constexpr auto signbit(
const T& lhs) {
899 return std::signbit(q.internal());
902template <
typename T,
typename U,
typename V>
904constexpr auto clamp(
const T& lhs,
const U& lo,
const V& hi) {
908 return decltype(qlhs)(std::clamp(qlhs.internal(), qlo.internal(), qhi.internal()));
911template <
typename T,
typename U>
913constexpr auto ceil(
const T& lhs,
const U& rhs) {
917 return decltype(qlhs)(cevalm::ceil(qlhs.internal() / qrhs.internal()) * qrhs.internal());
919 return decltype(qlhs)(std::ceil(qlhs.internal() / qrhs.internal()) * qrhs.internal());
923template <
typename T,
typename U>
925constexpr auto floor(
const T& lhs,
const U& rhs) {
929 return decltype(qlhs)(cevalm::floor(qlhs.internal() / qrhs.internal()) * qrhs.internal());
931 return decltype(qlhs)(std::floor(qlhs.internal() / qrhs.internal()) * qrhs.internal());
935template <
typename T,
typename U>
937constexpr auto trunc(
const T& lhs,
const U& rhs) {
941 return decltype(qlhs)(cevalm::trunc(qlhs.internal() / qrhs.internal()) * qrhs.internal());
943 return decltype(qlhs)(std::trunc(qlhs.internal() / qrhs.internal()) * qrhs.internal());
947template <
typename T,
typename U>
949constexpr auto round(
const T& lhs,
const U& rhs) {
953 return decltype(qlhs)(cevalm::round(qlhs.internal() / qrhs.internal()) * qrhs.internal());
955 return decltype(qlhs)(std::round(qlhs.internal() / qrhs.internal()) * qrhs.internal());
962 std::ratio_equal_v<typename Q::current, std::ratio<0>> &&
963 std::ratio_equal_v<typename Q::temperature, std::ratio<0>> &&
964 std::ratio_equal_v<typename Q::luminosity, std::ratio<0>> &&
965 std::ratio_equal_v<typename Q::moles, std::ratio<0>>;
971template <KinematicQuantity Q>
972 requires std::ratio_equal_v<typename Q::angle, std::ratio<1>> &&
973 std::ratio_equal_v<typename Q::length, std::ratio<0>>
974constexpr auto to_linear(Q angular_distance, Length diameter) {
975 return angular_distance * (diameter / 2.0) / rad;
982template <KinematicQuantity Q>
983 requires std::ratio_equal_v<typename Q::length, std::ratio<1>> &&
984 std::ratio_equal_v<typename Q::angle, std::ratio<0>>
985constexpr auto to_angular(Q linear_distance, Length diameter) {
986 return linear_distance / (diameter / 2.0) * rad;
990constexpr Number sin(Angle angle) {
992 return Number(cevalm::sin(angle.internal()));
994 return Number(std::sin(angle.internal()));
998constexpr Number cos(Angle angle) {
1000 return Number(cevalm::cos(angle.internal()));
1002 return Number(std::cos(angle.internal()));
1006constexpr Number tan(Angle angle) {
1008 return Number(cevalm::tan(angle.internal()));
1010 return Number(std::tan(angle.internal()));
1014constexpr Angle asin(
Number value) {
1016 return Angle(cevalm::asin(value.internal()));
1018 return Angle(std::asin(value.internal()));
1022constexpr Angle acos(
Number value) {
1024 return Angle(cevalm::acos(value.internal()));
1026 return Angle(std::acos(value.internal()));
1030constexpr Angle atan(
Number value) {
1032 return Angle(cevalm::atan(value.internal()));
1034 return Angle(std::atan(value.internal()));
1038template <
typename T,
typename U>
1040constexpr Angle atan2(
const T& y,
const U& x) {
1044 return Angle(cevalm::atan2(qy.internal(), qx.internal()));
1046 return Angle(std::atan2(qy.internal(), qx.internal()));
1051constexpr Angle wrap_positive(Angle angle) {
1052 Angle wrapped = mod(angle, rev);
1053 return wrapped < Angle(0) ? wrapped + rev : wrapped;
1056constexpr Angle wrap_signed(Angle angle) {
return wrap_positive(angle + rev / 2.0) - rev / 2.0; }
1058constexpr Angle shortest_difference(Angle start, Angle end) {
return wrap_signed(end - start); }