Phyth v0.1.0
A dimensional safe C++ header-only mechanics and electromagnetics simulation library.
Loading...
Searching...
No Matches
Quantity.hpp
Go to the documentation of this file.
1#ifndef PHYTH_QUANTITY_HPP
2#define PHYTH_QUANTITY_HPP
3
4#include "Dimension.hpp"
5#include "Unit.hpp"
8#include <sstream>
9#include <type_traits>
10
11namespace Phyth {
26 template<typename UnitT>
27 struct Quantity {
28 static_assert(is_unit_v<UnitT>, "UnitT must be a unit type");
29
31 double value;
32
34 constexpr Quantity(const double v = 0.0) : value(v) {
35 }
36
45 template<typename OtherUnit>
47 : value(other.value * OtherUnit::scale / UnitT::scale) {
48 static_assert(std::is_same_v<typename UnitT::DimensionT, typename OtherUnit::DimensionT>,
49 "Cannot convert between different dimensions");
50 }
51
62 template<typename TargetUnit>
63 constexpr auto As() const {
64 static_assert(std::is_same_v<typename UnitT::DimensionT,
65 typename TargetUnit::DimensionT>,
66 "Cannot convert between different dimensions");
67 return Quantity<TargetUnit>(value * UnitT::scale / TargetUnit::scale);
68 }
69
76 template<typename TargetType>
77 constexpr auto To() const {
78 return static_cast<TargetType>(value);
79 }
80
88 template<typename OtherUnit>
90 static_assert(std::is_same_v<typename UnitT::DimensionT, typename OtherUnit::DimensionT>,
91 "Cannot add different dimensions");
92 value += other.value * OtherUnit::scale / UnitT::scale;
93 return *this;
94 }
95
103 template<typename OtherUnit>
105 static_assert(std::is_same_v<typename UnitT::DimensionT, typename OtherUnit::DimensionT>,
106 "Cannot subtract different dimensions");
107 value -= other.value * OtherUnit::scale / UnitT::scale;
108 return *this;
109 }
110
112 constexpr Quantity &operator*=(const double scalar) {
113 value *= scalar;
114 return *this;
115 }
116
118 constexpr Quantity &operator/=(const double scalar) {
119 value /= scalar;
120 return *this;
121 }
122
124 constexpr Quantity &operator++() {
125 ++value;
126 return *this;
127 }
128
130 constexpr Quantity &operator--() {
131 --value;
132 return *this;
133 }
134
136 constexpr Quantity operator++(int) {
137 Quantity temp = *this;
138 ++value;
139 return temp;
140 }
141
143 constexpr Quantity operator--(int) {
144 Quantity temp = *this;
145 --value;
146 return temp;
147 }
148 };
149
153 template<typename>
154 struct is_quantity : std::false_type {
155 };
156
157 template<typename UnitT>
158 struct is_quantity<Quantity<UnitT> > : std::true_type {
159 };
160
164 template<typename T>
165 inline constexpr bool is_quantity_v = is_quantity<T>::value;
166
167
181 template<typename U1, typename U2>
183 static_assert(std::is_same_v<typename U1::DimensionT, typename U2::DimensionT>,
184 "Cannot compare different dimensions");
185 return a.value == b.value * (U2::scale / U1::scale);
186 }
187
201 template<typename U1, typename U2>
203 return !(a == b);
204 }
205
219 template<typename U1, typename U2>
221 static_assert(std::is_same_v<typename U1::DimensionT, typename U2::DimensionT>,
222 "Cannot compare different dimensions");
223 return a.value < b.value * (U2::scale / U1::scale);
224 }
225
239 template<typename U1, typename U2>
241 return b < a;
242 }
243
258 template<typename U1, typename U2>
260 return !(a > b);
261 }
262
277 template<typename U1, typename U2>
279 return !(a < b);
280 }
281
294 template<typename UnitT>
295 constexpr bool operator==(Quantity<UnitT> a, double scalar) {
296 static_assert(is_dimensionless_v<UnitT>,
297 "Cannot compare a dimensionful quantity with a scalar");
298 return a.value == scalar;
299 }
300
313 template<typename UnitT>
314 constexpr bool operator==(double scalar, Quantity<UnitT> a) {
315 static_assert(is_dimensionless_v<UnitT>,
316 "Cannot compare a dimensionful quantity with a scalar");
317 return scalar == a.value;
318 }
319
328 template<typename UnitT>
329 constexpr bool operator!=(Quantity<UnitT> a, double scalar) {
330 static_assert(is_dimensionless_v<UnitT>,
331 "Cannot compare a dimensionful quantity with a scalar");
332 return a.value != scalar;
333 }
334
343 template<typename UnitT>
344 constexpr bool operator!=(double scalar, Quantity<UnitT> a) {
345 static_assert(is_dimensionless_v<UnitT>,
346 "Cannot compare a dimensionful quantity with a scalar");
347 return scalar != a.value;
348 }
349
358 template<typename UnitT>
359 constexpr bool operator<(Quantity<UnitT> a, double scalar) {
360 static_assert(is_dimensionless_v<UnitT>,
361 "Cannot compare a dimensionful quantity with a scalar");
362 return a.value < scalar;
363 }
364
373 template<typename UnitT>
374 constexpr bool operator<(double scalar, Quantity<UnitT> a) {
375 static_assert(is_dimensionless_v<UnitT>,
376 "Cannot compare a dimensionful quantity with a scalar");
377 return scalar < a.value;
378 }
379
388 template<typename UnitT>
389 constexpr bool operator>(Quantity<UnitT> a, double scalar) {
390 static_assert(is_dimensionless_v<UnitT>,
391 "Cannot compare a dimensionful quantity with a scalar");
392 return a.value > scalar;
393 }
394
403 template<typename UnitT>
404 constexpr bool operator>(double scalar, Quantity<UnitT> a) {
405 static_assert(is_dimensionless_v<UnitT>,
406 "Cannot compare a dimensionful quantity with a scalar");
407 return scalar > a.value;
408 }
409
418 template<typename UnitT>
419 constexpr bool operator<=(Quantity<UnitT> a, double scalar) {
420 static_assert(is_dimensionless_v<UnitT>,
421 "Cannot compare a dimensionful quantity with a scalar");
422 return a.value <= scalar;
423 }
424
433 template<typename UnitT>
434 constexpr bool operator<=(double scalar, Quantity<UnitT> a) {
435 static_assert(is_dimensionless_v<UnitT>,
436 "Cannot compare a dimensionful quantity with a scalar");
437 return scalar <= a.value;
438 }
439
448 template<typename UnitT>
449 constexpr bool operator>=(Quantity<UnitT> a, double scalar) {
450 static_assert(is_dimensionless_v<UnitT>,
451 "Cannot compare a dimensionful quantity with a scalar");
452 return a.value >= scalar;
453 }
454
463 template<typename UnitT>
464 constexpr bool operator>=(double scalar, Quantity<UnitT> a) {
465 static_assert(is_dimensionless_v<UnitT>,
466 "Cannot compare a dimensionful quantity with a scalar");
467 return scalar >= a.value;
468 }
469
482 template<typename U1, typename U2>
484 static_assert(std::is_same_v<typename U1::DimensionT, typename U2::DimensionT>,
485 "Cannot add different dimensions");
486 return Quantity<U1>(a.value + b.value * (U2::scale / U1::scale));
487 }
488
501 template<typename U1, typename U2>
503 static_assert(std::is_same_v<typename U1::DimensionT, typename U2::DimensionT>,
504 "Cannot subtract different dimensions");
505 return Quantity<U1>(a.value - b.value * (U2::scale / U1::scale));
506 }
507
523 template<typename U1, typename U2>
525 return Quantity<UnitMulT<U1, U2> >(a.value * b.value);
526 }
527
543 template<typename U1, typename U2>
545 return Quantity<UnitDivT<U1, U2> >(a.value / b.value);
546 }
547
556 template<typename UnitT>
557 constexpr auto operator+(Quantity<UnitT> a, double scalar) {
558 static_assert(is_dimensionless_v<UnitT>,
559 "Cannot add a dimensionful quantity with a scalar");
560 return Quantity<UnitT>(a.value + scalar);
561 }
562
571 template<typename UnitT>
572 constexpr auto operator+(double scalar, Quantity<UnitT> a) {
573 static_assert(is_dimensionless_v<UnitT>,
574 "Cannot add a dimensionful quantity with a scalar");
575 return Quantity<UnitT>(scalar + a.value);
576 }
577
586 template<typename UnitT>
587 constexpr auto operator-(Quantity<UnitT> a, double scalar) {
588 static_assert(is_dimensionless_v<UnitT>,
589 "Cannot subtract a scalar from a dimensionful quantity");
590 return Quantity<UnitT>(a.value - scalar);
591 }
592
601 template<typename UnitT>
602 constexpr auto operator-(double scalar, Quantity<UnitT> a) {
603 static_assert(is_dimensionless_v<UnitT>,
604 "Cannot subtract a dimensionful quantity from a scalar");
605 return Quantity<UnitT>(scalar - a.value);
606 }
607
615 template<typename UnitT>
616 constexpr auto operator*(Quantity<UnitT> a, double scalar) {
617 return Quantity<UnitT>(a.value * scalar);
618 }
619
627 template<typename UnitT>
628 constexpr auto operator*(double scalar, Quantity<UnitT> a) {
629 return Quantity<UnitT>(scalar * a.value);
630 }
631
639 template<typename UnitT>
640 constexpr auto operator/(Quantity<UnitT> a, double scalar) {
641 return Quantity<UnitT>(a.value / scalar);
642 }
643
658 template<typename UnitT>
659 constexpr auto operator/(double scalar, Quantity<UnitT> a) {
660 using DimT = typename UnitT::DimensionT;
663 return Quantity<ResultUnit>(scalar / a.value);
664 }
665
672 template<typename UnitT>
673 constexpr auto operator-(Quantity<UnitT> a) {
674 return Quantity<UnitT>(-a.value);
675 }
676
683 template<typename UnitT>
684 constexpr auto operator+(Quantity<UnitT> a) {
685 return Quantity<UnitT>(+a.value);
686 }
687
694 template<typename UnitT>
695 std::string UnitSymbol() {
697 }
698
705 template<typename UnitT>
706 std::string UnitName() {
708 }
709
718 inline std::string FormatValue(const double value) {
719 std::ostringstream oss;
720 oss << value;
721 return oss.str();
722 }
723
737 template<typename UnitT>
738 std::string QuantityToString(const Quantity<UnitT> &q) {
739 using DimT = typename UnitT::DimensionT;
741 return FormatValue(q.value) + " " + DimToString<DimT>::value();
742 }
743 const double display_value = q.value / UnitT::scale;
744 std::string unit = UnitSymbol<UnitT>();
745 if (unit.empty()) {
747 }
748 if (unit.empty()) {
750 }
751 return FormatValue(display_value) + " " + unit;
752 }
753
762 template<typename UnitT>
763 std::ostream &operator<<(std::ostream &os, const Quantity<UnitT> &q) {
765 return os;
766 }
767}
768
782template<typename U1, typename U2, typename = void>
784
785template<typename U1, typename U2>
786struct common_type_impl<U1, U2, std::enable_if_t<Phyth::is_unit_v<U1> && Phyth::is_unit_v<U2>> > {
788};
789
790template<typename U1, typename U2>
791struct common_type_impl<U1, U2, void> {
792};
793
794template<typename U1, typename U2>
795struct std::common_type<Phyth::Quantity<U1>, Phyth::Quantity<U2> >
796 : common_type_impl<U1, U2> {
797};
798
799#endif // PHYTH_QUANTITY_HPP
std::string GetName() const
Get the full name of a unit type.
static UnitRegistry & GetInstance()
Get the singleton instance.
std::string GetSymbol() const
Get the symbol of a unit type.
auto output_mode
Definition Config.hpp:12
constexpr bool operator<(Quantity< U1 > a, Quantity< U2 > b)
Less-than comparison between two quantities.
Definition Quantity.hpp:220
constexpr auto operator/(Quantity< U1 > a, Quantity< U2 > b)
Divide one quantity by another.
Definition Quantity.hpp:544
std::string UnitSymbol()
Get the symbol string for a unit type (e.g., "m", "kg", "N")
Definition Quantity.hpp:695
std::ostream & operator<<(std::ostream &os, const Quantity< UnitT > &q)
Stream insertion operator for Quantity.
Definition Quantity.hpp:763
typename DimDiv< D1, D2 >::type DimDivT
Convenience alias for DimDiv.
Definition Dimension.hpp:91
constexpr auto operator+(Quantity< U1 > a, Quantity< U2 > b)
Add two quantities of the same dimension.
Definition Quantity.hpp:483
constexpr bool operator>=(Quantity< U1 > a, Quantity< U2 > b)
Greater-than-or-equal comparison between two quantities.
Definition Quantity.hpp:278
std::string UnitName()
Get the full name string for a unit type (e.g., "meter", "kilogram")
Definition Quantity.hpp:706
constexpr auto operator*(Quantity< U1 > a, Quantity< U2 > b)
Multiply two quantities.
Definition Quantity.hpp:524
constexpr bool operator==(Quantity< U1 > a, Quantity< U2 > b)
Equality comparison between two quantities.
Definition Quantity.hpp:182
constexpr bool operator>(Quantity< U1 > a, Quantity< U2 > b)
Greater-than comparison between two quantities.
Definition Quantity.hpp:240
std::string QuantityToString(const Quantity< UnitT > &q)
Convert a Quantity to a human-readable string.
Definition Quantity.hpp:738
constexpr bool operator!=(Quantity< U1 > a, Quantity< U2 > b)
Inequality comparison between two quantities.
Definition Quantity.hpp:202
constexpr auto operator-(Quantity< U1 > a, Quantity< U2 > b)
Subtract two quantities of the same dimension.
Definition Quantity.hpp:502
std::string FormatValue(const double value)
Format a raw numeric value for string output.
Definition Quantity.hpp:718
constexpr bool is_unit_v
Definition Unit.hpp:79
constexpr bool operator<=(Quantity< U1 > a, Quantity< U2 > b)
Less-than-or-equal comparison between two quantities.
Definition Quantity.hpp:259
constexpr bool is_quantity_v
Convenience variable template for is_quantity.
Definition Quantity.hpp:165
Convert a Dimension to a human-readable string.
Physical quantity with a value and a compile-time unit.
Definition Quantity.hpp:27
constexpr Quantity operator++(int)
Post-increment: increase value by 1, return old value.
Definition Quantity.hpp:136
constexpr Quantity & operator++()
Pre-increment: increase value by 1.
Definition Quantity.hpp:124
constexpr Quantity & operator+=(Quantity< OtherUnit > other)
Add another quantity of the same dimension.
Definition Quantity.hpp:89
constexpr Quantity & operator-=(Quantity< OtherUnit > other)
Subtract another quantity of the same dimension.
Definition Quantity.hpp:104
constexpr Quantity(Quantity< OtherUnit > other)
Convert from another unit of the same dimension.
Definition Quantity.hpp:46
constexpr auto As() const
Convert this quantity to a different unit of the same dimension.
Definition Quantity.hpp:63
constexpr Quantity & operator/=(const double scalar)
Divide the value by a scalar.
Definition Quantity.hpp:118
constexpr Quantity(const double v=0.0)
Construct a quantity with a given value (default: 0)
Definition Quantity.hpp:34
constexpr auto To() const
Extract the numeric value as a different type.
Definition Quantity.hpp:77
constexpr Quantity & operator*=(const double scalar)
Multiply the value by a scalar.
Definition Quantity.hpp:112
constexpr Quantity & operator--()
Pre-decrement: decrease value by 1.
Definition Quantity.hpp:130
constexpr Quantity operator--(int)
Post-decrement: decrease value by 1, return old value.
Definition Quantity.hpp:143
Physical unit with dimension and scale factor relative to SI base.
Definition Unit.hpp:41
Trait: check if a type is a Quantity instantiation.
Definition Quantity.hpp:154
std::common_type specialization for Quantity
Definition Quantity.hpp:783