Quantity.hpp 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406
  1. /*
  2. * @brief Defines and implements classes to define physical SI units
  3. * @file types/Quantity.hpp
  4. * @author Sven Czarnian <devel@svcz.de>
  5. * @copyright Copyright 2020-2021 Sven Czarnian
  6. * @license This project is published under the GNU General Public License v3 (GPLv3)
  7. */
  8. #pragma once
  9. #include <cmath>
  10. #include <ratio>
  11. #include <aman/helper/Math.h>
  12. namespace aman {
  13. /**
  14. * @brief Defines the base class to define different physical SI units
  15. * @ingroup types
  16. *
  17. * The template arguments are used to define the exponent of the SI unit.
  18. * These Quantity definitions are the base to describe all physical relations.
  19. *
  20. * By use of this implementation is it possible to ensure, that the SI units
  21. * are as expected after the calculations.
  22. *
  23. * This avoids logical errors and it is useful to avoid the auto-keyword otherwise
  24. * is it not possible to check the correctness of the SI units.
  25. *
  26. * @tparam M The exponent of the mass parts
  27. * @tparam L The exponent of the length parts
  28. * @tparam T The exponent of the time parts
  29. * @tparam A The exponent of the angular parts
  30. */
  31. template <typename M, typename L, typename T, typename A>
  32. class Quantity {
  33. private:
  34. float m_value;
  35. public:
  36. /**
  37. * @brief Initializes a quantity with the default value
  38. */
  39. constexpr Quantity() noexcept : m_value(0.0f) { }
  40. /**
  41. * @brief Initializes the quantity with a given value
  42. * @param[in] value The set value
  43. */
  44. explicit constexpr Quantity(float value) : m_value(value) { }
  45. /**
  46. * @brief Adds rhs into this instance and returns the updated instance
  47. * @param[in] rhs The right-hand-side component
  48. * @return The resulting quantity with the updated value
  49. */
  50. constexpr Quantity const& operator+=(const Quantity& rhs) {
  51. this->m_value += rhs.m_value;
  52. return *this;
  53. }
  54. /**
  55. * @brief Substracts rhs into this instance and returns the updated instance
  56. * @param[in] rhs The right-hand-side component
  57. * @return The resulting quantity with the updated value
  58. */
  59. constexpr Quantity const& operator-=(const Quantity& rhs) {
  60. this->m_value -= rhs.m_value;
  61. return *this;
  62. }
  63. /**
  64. * @brief Returns the value in SI units
  65. * @return The contained value
  66. */
  67. constexpr float value() const {
  68. return this->m_value;
  69. }
  70. /**
  71. * @brief Sets the value in SI units
  72. * @param[in] value The new SI unit based value
  73. */
  74. constexpr void setValue(float value) {
  75. this->m_value = value;
  76. }
  77. /**
  78. * @brief Converts the value into a specific unit
  79. * @param[in] rhs The scaling factor to convert the value
  80. * @return The converted value
  81. */
  82. constexpr float convert(const Quantity& rhs) const {
  83. return this->m_value / rhs.m_value;
  84. }
  85. /**
  86. * @brief Calculates the square-root and updates the SI units as well
  87. * @return The resulting instance with updated template arguments
  88. */
  89. constexpr Quantity<std::ratio_divide<M, std::ratio<2>>, std::ratio_divide<L, std::ratio<2>>,
  90. std::ratio_divide<T, std::ratio<2>>, std::ratio_divide<A, std::ratio<2>>> sqrt() const {
  91. return Quantity<std::ratio_divide<M, std::ratio<2>>, std::ratio_divide<L, std::ratio<2>>,
  92. std::ratio_divide<T, std::ratio<2>>, std::ratio_divide<A, std::ratio<2>>>(std::sqrtf(this->m_value));
  93. }
  94. /**
  95. * @brief Calculates the absolute of the contained value and returns it as a new Quantity instance
  96. * @return The absolute value instance
  97. */
  98. constexpr Quantity<M, L, T, A> abs() const {
  99. return Quantity<M, L, T, A>(std::abs(this->m_value));
  100. }
  101. };
  102. /** The mass specialization [kg] */
  103. typedef Quantity<std::ratio<1>, std::ratio<0>, std::ratio<0>, std::ratio<0>> Mass;
  104. /** The length specialization [m] */
  105. typedef Quantity<std::ratio<0>, std::ratio<1>, std::ratio<0>, std::ratio<0>> Length;
  106. /** The time specialization [s] */
  107. typedef Quantity<std::ratio<0>, std::ratio<0>, std::ratio<1>, std::ratio<0>> Time;
  108. /** The angle specialization [rad] */
  109. typedef Quantity<std::ratio<0>, std::ratio<0>, std::ratio<0>, std::ratio<1>> Angle;
  110. /** The velocity specialization [m/s] */
  111. typedef Quantity<std::ratio<0>, std::ratio<1>, std::ratio<-1>, std::ratio<0>> Velocity;
  112. /** The acceleration specialization [m/(s*s)] */
  113. typedef Quantity<std::ratio<0>, std::ratio<1>, std::ratio<-2>, std::ratio<0>> Acceleration;
  114. /** The angular velocity specialization [1/s] */
  115. typedef Quantity<std::ratio<0>, std::ratio<0>, std::ratio<-1>, std::ratio<1>> AngularVelocity;
  116. /** The angular acceleration specialization [1/(s*s)] */
  117. typedef Quantity<std::ratio<0>, std::ratio<0>, std::ratio<-2>, std::ratio<1>> AngularAcceleration;
  118. /**
  119. * @brief Adds rhs to lhs and returns a new instance
  120. * @param[in] lhs The left-hand-side component
  121. * @param[in] rhs The right-hand-side component
  122. * @return The resulting quantity with the updated value
  123. */
  124. template <typename M, typename L, typename T, typename A>
  125. constexpr Quantity<M, L, T, A> operator+(const Quantity<M, L, T, A>& lhs, const Quantity<M, L, T, A>& rhs) {
  126. return Quantity<M, L, T, A>(lhs.value() + rhs.value());
  127. }
  128. /**
  129. * @brief Substracts rhs to lhs and returns a new instance
  130. * @param[in] lhs The left-hand-side component
  131. * @param[in] rhs The right-hand-side component
  132. * @return The resulting quantity with the updated value
  133. */
  134. template <typename M, typename L, typename T, typename A>
  135. constexpr Quantity<M, L, T, A> operator-(const Quantity<M, L, T, A>& lhs, const Quantity<M, L, T, A>& rhs) {
  136. return Quantity<M, L, T, A>(lhs.value() - rhs.value());
  137. }
  138. /**
  139. * @brief Multiplies rhs to lhs and returns a new instance
  140. * @param[in] lhs The left-hand-side component
  141. * @param[in] rhs The right-hand-side component
  142. * @return The resulting quantity with the updated value
  143. */
  144. template <typename M1, typename L1, typename T1, typename A1,
  145. typename M2, typename L2, typename T2, typename A2>
  146. constexpr Quantity<std::ratio_add<M1, M2>, std::ratio_add<L1, L2>,
  147. std::ratio_add<T1, T2>, std::ratio_add<A1, A2>>
  148. operator*(const Quantity<M1, L1, T1, A1>& lhs, const Quantity<M2, L2, T2, A2>& rhs) {
  149. return Quantity<std::ratio_add<M1, M2>, std::ratio_add<L1, L2>,
  150. std::ratio_add<T1, T2>, std::ratio_add<A1, A2>>(lhs.value() * rhs.value());
  151. }
  152. /**
  153. * @brief Multiplies lhs to rhs and returns a new instance
  154. * @param[in] lhs The SI-unit free factor
  155. * @param[in] rhs The right-hand-side component
  156. * @return The resulting quantity with the updated value
  157. */
  158. template <typename M, typename L, typename T, typename A>
  159. constexpr Quantity<M, L, T, A> operator*(const float& lhs, const Quantity<M, L, T, A>& rhs) {
  160. return Quantity<M, L, T, A>(lhs * rhs.value());
  161. }
  162. /**
  163. * @brief Multiplies rhs to lhs and returns a new instance
  164. * @param[in] lhs The left-hand-side component
  165. * @param[in] rhs The SI-unit free factor
  166. * @return The resulting quantity with the updated value
  167. */
  168. template <typename M, typename L, typename T, typename A>
  169. constexpr Quantity<M, L, T, A> operator*(const Quantity<M, L, T, A>& lhs, const float& rhs) {
  170. return Quantity<M, L, T, A>(lhs.value() * rhs);
  171. }
  172. /**
  173. * @brief Divides rhs from lhs and returns a new instance
  174. * @param[in] lhs The left-hand-side component
  175. * @param[in] rhs The right-hand-side component
  176. * @return The resulting quantity with the updated value
  177. */
  178. template <typename M1, typename L1, typename T1, typename A1,
  179. typename M2, typename L2, typename T2, typename A2>
  180. constexpr Quantity<std::ratio_subtract<M1, M2>, std::ratio_subtract<L1, L2>,
  181. std::ratio_subtract<T1, T2>, std::ratio_subtract<A1, A2>>
  182. operator/(const Quantity<M1, L1, T1, A1>& lhs, const Quantity<M2, L2, T2, A2>& rhs) {
  183. return Quantity<std::ratio_subtract<M1, M2>, std::ratio_subtract<L1, L2>,
  184. std::ratio_subtract<T1, T2>, std::ratio_subtract<A1, A2>>(lhs.value() / rhs.value());
  185. }
  186. /**
  187. * @brief Divides rhs from lhs and returns a new instance
  188. * @param[in] lhs The SI-unit free factor
  189. * @param[in] rhs The right-hand-side component
  190. * @return The resulting quantity with the updated value
  191. */
  192. template <typename M, typename L, typename T, typename A>
  193. constexpr Quantity<std::ratio_subtract<std::ratio<0>, M>, std::ratio_subtract<std::ratio<0>, L>,
  194. std::ratio_subtract<std::ratio<0>, T>, std::ratio_subtract<std::ratio<0>, A>>
  195. operator/(const float& lhs, const Quantity<M, L, T, A>& rhs) {
  196. return Quantity<std::ratio_subtract<std::ratio<0>, M>, std::ratio_subtract<std::ratio<0>, L>,
  197. std::ratio_subtract<std::ratio<0>, T>, std::ratio_subtract<std::ratio<0>, A>>(lhs / rhs.value());
  198. }
  199. /**
  200. * @brief Multiplies lhs from rhs and returns a new instance
  201. * @param[in] lhs The left-hand-side component
  202. * @param[in] rhs The SI-unit free factor
  203. * @return The resulting quantity with the updated value
  204. */
  205. template <typename M, typename L, typename T, typename A>
  206. constexpr Quantity<M, L, T, A> operator/(const Quantity<M, L, T, A>& lhs, const float& rhs) {
  207. return Quantity<M, L, T, A>(lhs.value() / rhs);
  208. }
  209. /**
  210. * @brief Compares if two instance are equal or almost equal
  211. * @param[in] lhs The left-hand-side component
  212. * @param[in] rhs The right-hand-side component
  213. * @return True if the instances are almost equal, else false
  214. */
  215. template <typename M, typename L, typename T, typename A>
  216. constexpr bool operator==(const Quantity<M, L, T, A>& lhs, const Quantity<M, L, T, A>& rhs) {
  217. return true == Math::almostEqual(lhs.value(), rhs.value(), 1e-8f);
  218. }
  219. /**
  220. * @brief Compares if two instance are not equal
  221. * @param[in] lhs The left-hand-side component
  222. * @param[in] rhs The right-hand-side component
  223. * @return True if the instances are not equal
  224. */
  225. template <typename M, typename L, typename T, typename A>
  226. constexpr bool operator!=(const Quantity<M, L, T, A>& lhs, const Quantity<M, L, T, A>& rhs) {
  227. return false == Math::almostEqual(lhs.value(), rhs.value(), 1e-8f);
  228. }
  229. /**
  230. * @brief Compares if lhs is smaller or equal compared to rhs
  231. * @param[in] lhs The left-hand-side component
  232. * @param[in] rhs The right-hand-side component
  233. * @return True if lhs is smaller or equal compared to rhs
  234. */
  235. template <typename M, typename L, typename T, typename A>
  236. constexpr bool operator<=(const Quantity<M, L, T, A>& lhs, const Quantity<M, L, T, A>& rhs) {
  237. return lhs.value() <= rhs.value();
  238. }
  239. /**
  240. * @brief Compares if lhs is smaller compared to rhs
  241. * @param[in] lhs The left-hand-side component
  242. * @param[in] rhs The right-hand-side component
  243. * @return True if lhs is smaller compared to rhs
  244. */
  245. template <typename M, typename L, typename T, typename A>
  246. constexpr bool operator<(const Quantity<M, L, T, A>& lhs, const Quantity<M, L, T, A>& rhs) {
  247. return lhs.value() < rhs.value();
  248. }
  249. /**
  250. * @brief Compares if lhs is greater or equal compared to rhs
  251. * @param[in] lhs The left-hand-side component
  252. * @param[in] rhs The right-hand-side component
  253. * @return True if lhs is greater or equal compared to rhs
  254. */
  255. template <typename M, typename L, typename T, typename A>
  256. constexpr bool operator>=(const Quantity<M, L, T, A>& lhs, const Quantity<M, L, T, A>& rhs) {
  257. return lhs.value() >= rhs.value();
  258. }
  259. /**
  260. * @brief Compares if lhs is greater compared to rhs
  261. * @param[in] lhs The left-hand-side component
  262. * @param[in] rhs The right-hand-side component
  263. * @return True if lhs is greater compared to rhs
  264. */
  265. template <typename M, typename L, typename T, typename A>
  266. constexpr bool operator>(const Quantity<M, L, T, A>& lhs, const Quantity<M, L, T, A>& rhs) {
  267. return lhs.value() > rhs.value();
  268. }
  269. /**< Defines a kilogram */
  270. constexpr Mass kilogram(1.0f);
  271. constexpr Mass pound = 0.453592f * kilogram;
  272. /**< Defines the literal of kilograms */
  273. constexpr Mass operator"" _kg(long double value) { return Mass(static_cast<float>(value)); }
  274. /**< Defines the literal of kilograms */
  275. constexpr Mass operator"" _kg(unsigned long long int value) { return Mass(static_cast<float>(value)); }
  276. /**< Defines the literal of pounds */
  277. constexpr Mass operator"" _lbs(long double value) { return static_cast<float>(value) * pound; }
  278. /**< Defines the literal of pounds */
  279. constexpr Mass operator"" _lbs(unsigned long long int value) { return static_cast<float>(value) * pound; }
  280. /**< Defines a metres */
  281. constexpr Length metre(1.0f);
  282. /**< Defines a feet */
  283. constexpr Length feet = 0.3048f * metre;
  284. /**< Defines a kilometres */
  285. constexpr Length kilometre = 1000.0f * metre;
  286. /**< Defines a nautical mile */
  287. constexpr Length nauticmile = 1852.0f * metre;
  288. /**< Defines the literal of metres */
  289. constexpr Length operator"" _m(long double value) { return Length(static_cast<float>(value)); }
  290. /**< Defines the literal of metres */
  291. constexpr Length operator"" _m(unsigned long long int value) { return Length(static_cast<float>(value)); }
  292. /**< Defines the literal of feets */
  293. constexpr Length operator"" _ft(long double value) { return static_cast<float>(value) * feet; }
  294. /**< Defines the literal of feets */
  295. constexpr Length operator"" _ft(unsigned long long int value) { return static_cast<float>(value) * feet; }
  296. /**< Defines the literal of kilometres */
  297. constexpr Length operator"" _km(long double value) { return static_cast<float>(value)* kilometre; }
  298. /**< Defines the literal of kilometres */
  299. constexpr Length operator"" _km(unsigned long long int value) { return static_cast<float>(value)* kilometre; }
  300. /**< Defines the literal of nautical miles */
  301. constexpr Length operator"" _nm(long double value) { return static_cast<float>(value)* nauticmile; }
  302. /**< Defines the literal of nautical miles */
  303. constexpr Length operator"" _nm(unsigned long long int value) { return static_cast<float>(value)* nauticmile; }
  304. /**< Defines a second */
  305. constexpr Time second(1.0f);
  306. /**< Defines a millisecond */
  307. constexpr Time millisecond = second / 1000.0f;
  308. /**< Defines a minute */
  309. constexpr Time minute = 60.0f * second;
  310. /**< Defines a hour */
  311. constexpr Time hour = 60.0f * minute;
  312. /**< Defines the literal of milliseconds */
  313. constexpr Time operator"" _ms(long double value) { return static_cast<float>(value) * millisecond; }
  314. /**< Defines the literal of milliseconds */
  315. constexpr Time operator"" _ms(unsigned long long int value) { return static_cast<float>(value) * millisecond; }
  316. /**< Defines the literal of seconds */
  317. constexpr Time operator"" _s(long double value) { return static_cast<float>(value) * second; }
  318. /**< Defines the literal of seconds */
  319. constexpr Time operator"" _s(unsigned long long int value) { return static_cast<float>(value) * second; }
  320. /**< Defines the literal of minutes */
  321. constexpr Time operator"" _min(long double value) { return static_cast<float>(value) * minute; }
  322. /**< Defines the literal of minutes */
  323. constexpr Time operator"" _min(unsigned long long int value) { return static_cast<float>(value) * minute; }
  324. /**< Defines the literal of hours */
  325. constexpr Time operator"" _h(long double value) { return static_cast<float>(value) * hour; }
  326. /**< Defines the literal of hours */
  327. constexpr Time operator"" _h(unsigned long long int value) { return static_cast<float>(value) * hour; }
  328. /**< Defines the literal of PI */
  329. constexpr float operator"" _pi(long double value) { return static_cast<float>(value) * 3.1415926535897932384626433832795f; }
  330. /**< Defines the literal of PI */
  331. constexpr float operator"" _pi(unsigned long long int value) { return static_cast<float>(value) * 3.1415926535897932384626433832795f; }
  332. /**< Defines a degree */
  333. constexpr Angle degree = Angle(1.0f);
  334. /**< Defines a radian */
  335. constexpr Angle radian = 180.0f / 1_pi * degree;
  336. /**< Defines the literal of radians */
  337. constexpr Angle operator"" _rad(long double value) { return static_cast<float>(value) * radian; }
  338. /**< Defines the literal of radians */
  339. constexpr Angle operator"" _rad(unsigned long long int value) { return static_cast<float>(value) * radian; }
  340. /**< Defines the literal of degrees */
  341. constexpr Angle operator"" _deg(long double value) { return static_cast<float>(value) * degree; }
  342. /**< Defines the literal of degrees */
  343. constexpr Angle operator"" _deg(unsigned long long int value) { return static_cast<float>(value) * degree; }
  344. /**< Defines a knot */
  345. constexpr Velocity knot = 0.51444f * metre / second;
  346. /**< Defines the literal of metre per second */
  347. constexpr Velocity operator"" _mps(long double value) { return Velocity(static_cast<float>(value)); }
  348. /**< Defines the literal of metre per second */
  349. constexpr Velocity operator"" _mps(unsigned long long int value) { return Velocity(static_cast<float>(value)); }
  350. /**< Defines the literal of feet per minute */
  351. constexpr Velocity operator"" _ftpmin(long double value) { return static_cast<float>(value) * feet / minute; }
  352. /**< Defines the literal of feet per minute */
  353. constexpr Velocity operator"" _ftpmin(unsigned long long int value) { return static_cast<float>(value) * feet / minute; }
  354. /**< Defines the literal of kilometre per hour */
  355. constexpr Velocity operator"" _kmph(long double value) { return static_cast<float>(value) * kilometre / hour; }
  356. /**< Defines the literal of kilometre per hour */
  357. constexpr Velocity operator"" _kmph(unsigned long long int value) { return static_cast<float>(value) * kilometre / hour; }
  358. /**< Defines the literal of knots */
  359. constexpr Velocity operator"" _kn(long double value) { return static_cast<float>(value) * knot; }
  360. /**< Defines the literal of knots */
  361. constexpr Velocity operator"" _kn(unsigned long long int value) { return static_cast<float>(value) * knot; }
  362. /**< Defines the gravity */
  363. constexpr Acceleration G = 9.80665f * metre / (second* second);
  364. /**< Defines the literal of metre per square-second */
  365. constexpr Acceleration operator"" _mps2(long double value) { return Acceleration(static_cast<float>(value)); }
  366. /**< Defines the literal of metre per square-second */
  367. constexpr Acceleration operator"" _mps2(unsigned long long int value) { return Acceleration(static_cast<float>(value)); }
  368. /**< Defines the literal of gravities */
  369. constexpr Acceleration operator"" _g(long double value) { return static_cast<float>(value) * G; }
  370. /**< Defines the literal of gravities */
  371. constexpr Acceleration operator"" _g(unsigned long long int value) { return static_cast<float>(value) * G; }
  372. /**< Defines the literal of radian per second */
  373. constexpr AngularVelocity operator"" _radps(long double value) { return AngularVelocity(static_cast<float>(value)); }
  374. /**< Defines the literal of radian per second */
  375. constexpr AngularVelocity operator"" _radps(unsigned long long int value) { return AngularVelocity(static_cast<float>(value)); }
  376. /**< Defines the literal of degree per second */
  377. constexpr AngularVelocity operator"" _degps(long double value) { return static_cast<float>(value) * degree / second; }
  378. /**< Defines the literal of degree per second */
  379. constexpr AngularVelocity operator"" _degps(unsigned long long int value) { return static_cast<float>(value) * degree / second; }
  380. /**< Defines the literal of radian per square-second */
  381. constexpr AngularAcceleration operator"" _radps2(long double value) { return AngularAcceleration(static_cast<float>(value)); }
  382. /**< Defines the literal of radian per square-second */
  383. constexpr AngularAcceleration operator"" _radps2(unsigned long long int value) { return AngularAcceleration(static_cast<float>(value)); }
  384. /**< Defines the literal of degree per square-second */
  385. constexpr AngularAcceleration operator"" _degps2(long double value) { return static_cast<float>(value) * degree / (second * second); }
  386. /**< Defines the literal of degree per square-second */
  387. constexpr AngularAcceleration operator"" _degps2(unsigned long long int value) { return static_cast<float>(value) * degree / (second * second); }
  388. }