commit 22e782262b947e1bf689cb9f6332ef420c273e4d
parent 5945cb6a21f6ea0a8049b928d72eb5facd43ef3b
Author: Henry Wilson <henry@henryandlizzy.uk>
Date: Tue, 28 Feb 2023 23:10:40 +0000
dimensions: Add units with multiple dimensions example
Diffstat:
A | src/dimensions.cpp | | | 184 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
1 file changed, 184 insertions(+), 0 deletions(-)
diff --git a/src/dimensions.cpp b/src/dimensions.cpp
@@ -0,0 +1,184 @@
+#include <iostream>
+
+namespace system_of_units {
+
+struct dimensions
+{
+ static constexpr unsigned extent = 3;
+ int ds[extent] = {0,0,0};
+
+ constexpr dimensions operator *(dimensions rhs) const
+ {
+ dimensions res;
+ for (unsigned i = 0; i < extent; ++i)
+ res.ds[i] = ds[i] + rhs.ds[i];
+ return res;
+ }
+ constexpr dimensions operator /(dimensions rhs) const
+ {
+ dimensions res;
+ for (unsigned i = 0; i < extent; ++i)
+ res.ds[i] = ds[i] - rhs.ds[i];
+ return res;
+ }
+ constexpr dimensions operator ()(int power) const
+ {
+ dimensions res;
+ for (unsigned i = 0; i < extent; ++i)
+ res.ds[i] = ds[i] * power;
+ return res;
+ }
+};
+
+template <dimensions Us>
+struct unit
+{
+ long double v;
+
+ unit operator +(unit rhs) { return {v + rhs.v}; }
+ unit operator -(unit rhs) { return {v - rhs.v}; }
+
+ template <dimensions U2>
+ unit<Us*U2> operator *(unit<U2> rhs) { return {v * rhs.v}; }
+ template <dimensions U2>
+ unit<Us/U2> operator /(unit<U2> rhs) { return {v / rhs.v}; }
+};
+
+constexpr dimensions second{1,0,0};
+constexpr dimensions meter{0,1,0};
+constexpr dimensions kilogram{0,0,1};
+
+using dimensionless = unit<dimensions{}>;
+using time = unit<second>;
+using length = unit<meter>;
+using mass = unit<kilogram>;
+using frequency = unit<second(-1)>;
+using velocity = unit<meter/second>;
+using acceleration = unit<meter/second(2)>;
+using energy = unit<kilogram*meter(2)/second(2)>;
+using power = unit<kilogram*meter(2)/second(3)>;
+
+template <dimensions Us>
+std::ostream& operator <<(std::ostream& out, unit<Us> u)
+{
+ using U = decltype(u);
+
+ auto scale = abs(u.v);
+
+ if constexpr (std::is_same_v<U, dimensionless>)
+ {
+ if (scale < 2)
+ return out << u.v*100 << '%';
+ else
+ return out << u.v;
+ }
+ if constexpr (std::is_same_v<U, time>)
+ {
+ if (scale < 1)
+ return out << u.v*1000 << "ms";
+ else if (scale < 60)
+ return out << u.v << "s";
+ else if (scale < 3600)
+ return out << u.v/60 << "min";
+ else if (scale < 86400)
+ return out << u.v/3600 << "hour";
+ else
+ return out << u.v/86400 << "days";
+ }
+ if constexpr (std::is_same_v<U, mass>)
+ {
+ if (scale < 1)
+ return out << u.v << "g";
+ else if (scale < 1000)
+ return out << u.v << "kg";
+ else
+ return out << u.v/1000 << "t";
+ }
+
+ if (scale < 1)
+ out << u.v*1000 << 'm';
+ else if (scale < 1000)
+ out << u.v;
+ else if (scale < 1'000'000)
+ out << u.v/1000 << 'k';
+ else
+ out << u.v/1'000'000 << 'M';
+
+ if constexpr (std::is_same_v<U, length>)
+ return out << 'm';
+ if constexpr (std::is_same_v<U, frequency>)
+ return out << "Hz";
+ if constexpr (std::is_same_v<U, velocity>)
+ return out << "m/s";
+ if constexpr (std::is_same_v<U, acceleration>)
+ return out << "m/s²";
+ if constexpr (std::is_same_v<U, energy>)
+ return out << "J";
+ if constexpr (std::is_same_v<U, power>)
+ return out << "W";
+
+ out << '[';
+ for (auto d : Us.ds)
+ out << ' ' << d;
+
+ return out << " ]?";
+}
+
+dimensionless operator ""_mu(long double v) { return {v}; }
+time operator ""_s(long double v) { return {v}; }
+time operator ""_min(long double v) { return {v*60}; }
+time operator ""_hour(long double v) { return {v*3600}; }
+length operator ""_m(long double v) { return {v}; }
+length operator ""_km(long double v) { return {v*1000}; }
+length operator ""_mile(long double v) { return {v*1609.344}; }
+mass operator ""_kg(long double v) { return {v}; }
+mass operator ""_t(long double v) { return {v * 1000}; }
+frequency operator ""_Hz(long double v) { return {v}; }
+frequency operator ""_kHz(long double v) { return {v*1000}; }
+velocity operator ""_mps(long double v) { return {v}; }
+velocity operator ""_kmph(long double v) { return {v/3.6}; }
+velocity operator ""_mph(long double v) { return {v * 1609.344 / 3600}; }
+acceleration operator ""_mpsps(long double v) { return {v}; }
+energy operator ""_J(long double v) { return {v}; }
+energy operator ""_kJ(long double v) { return {v*1000}; }
+energy operator ""_MJ(long double v) { return {v*1'000'000}; }
+power operator ""_W(long double v) { return {v}; }
+power operator ""_kW(long double v) { return {v*1000}; }
+
+} // namespace system_of_units
+
+int main()
+{
+ using namespace system_of_units;
+ using std::cout, std::endl;
+
+ cout << 1._mu << endl;
+ cout << 1._s << endl;
+ cout << 1._min << endl;
+ cout << 1._hour << endl;
+ cout << 1._m << endl;
+ cout << 1._km << endl;
+ cout << 1._mile << endl;
+ cout << 1._kg << endl;
+ cout << 1._t << endl;
+ cout << 1._Hz << endl;
+ cout << 1._kHz << endl;
+ cout << 1._mps << endl;
+ cout << 1._kmph << endl;
+ cout << 1._mph << endl;
+ cout << 1._mpsps << endl;
+ cout << 1._J << endl;
+ cout << 1._kJ << endl;
+ cout << 1._MJ << endl;
+ cout << 1._W << endl;
+ cout << 1._kW << endl;
+ cout << endl;
+
+ auto m = 5._m;
+ auto t = 2._s;
+ cout << m/t << endl;
+ cout << 3000._mph << endl;
+ cout << t/t << endl;
+ cout << 11.1_t << endl;
+ cout << 10._mpsps << endl;
+}