examples

Toy examples in single C files.
git clone git://henryandlizzy.uk/examples
Log | Files | Refs

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:
Asrc/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; +}