dimensional_analysis.cpp 2.4 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071
  1. // Copyright Louis Dionne 2013-2017
  2. // Distributed under the Boost Software License, Version 1.0.
  3. // (See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
  4. #include <boost/hana/equal.hpp>
  5. #include <boost/hana/minus.hpp>
  6. #include <boost/hana/plus.hpp>
  7. #include <boost/hana/tuple.hpp>
  8. #include <boost/hana/zip_with.hpp>
  9. #include <functional>
  10. namespace hana = boost::hana;
  11. //
  12. // Example of implementing basic dimensional analysis using Hana
  13. //
  14. // base dimensions M L T I K J N
  15. using mass = decltype(hana::tuple_c<int, 1, 0, 0, 0, 0, 0, 0>);
  16. using length = decltype(hana::tuple_c<int, 0, 1, 0, 0, 0, 0, 0>);
  17. using time_ = decltype(hana::tuple_c<int, 0, 0, 1, 0, 0, 0, 0>);
  18. using charge = decltype(hana::tuple_c<int, 0, 0, 0, 1, 0, 0, 0>);
  19. using temperature = decltype(hana::tuple_c<int, 0, 0, 0, 0, 1, 0, 0>);
  20. using intensity = decltype(hana::tuple_c<int, 0, 0, 0, 0, 0, 1, 0>);
  21. using amount = decltype(hana::tuple_c<int, 0, 0, 0, 0, 0, 0, 1>);
  22. // composite dimensions
  23. using velocity = decltype(hana::tuple_c<int, 0, 1, -1, 0, 0, 0, 0>); // M/T
  24. using acceleration = decltype(hana::tuple_c<int, 0, 1, -2, 0, 0, 0, 0>); // M/T^2
  25. using force = decltype(hana::tuple_c<int, 1, 1, -2, 0, 0, 0, 0>); // ML/T^2
  26. template <typename Dimensions>
  27. struct quantity {
  28. double value_;
  29. explicit quantity(double v) : value_(v) { }
  30. template <typename OtherDimensions>
  31. explicit quantity(quantity<OtherDimensions> other)
  32. : value_(other.value_)
  33. {
  34. static_assert(Dimensions{} == OtherDimensions{},
  35. "Constructing quantities with incompatible dimensions!");
  36. }
  37. explicit operator double() const { return value_; }
  38. };
  39. template <typename D1, typename D2>
  40. auto operator*(quantity<D1> a, quantity<D2> b) {
  41. using D = decltype(hana::zip_with(std::plus<>{}, D1{}, D2{}));
  42. return quantity<D>{static_cast<double>(a) * static_cast<double>(b)};
  43. }
  44. template <typename D1, typename D2>
  45. auto operator/(quantity<D1> a, quantity<D2> b) {
  46. using D = decltype(hana::zip_with(std::minus<>{}, D1{}, D2{}));
  47. return quantity<D>{static_cast<double>(a) / static_cast<double>(b)};
  48. }
  49. int main() {
  50. quantity<mass> m{10.3};
  51. quantity<length> d{3.6};
  52. quantity<time_> t{2.4};
  53. quantity<velocity> v{d / t};
  54. quantity<acceleration> a{3.9};
  55. quantity<force> f{m * a};
  56. }