From 7b22155bf3ea3992e9e524f2f57e9c5058089f77 Mon Sep 17 00:00:00 2001 From: Mateusz Pusz Date: Mon, 12 Jun 2023 11:47:30 +0300 Subject: [PATCH] feat: linear algebra library usage re-enabled --- conanfile.py | 2 +- .../mp-units/bits/representation_concepts.h | 8 +- .../include/mp-units/customization_points.h | 4 + test/unit_test/runtime/CMakeLists.txt | 6 + .../unit_test/runtime/linear_algebra_test.cpp | 158 ++++++++---------- 5 files changed, 86 insertions(+), 92 deletions(-) diff --git a/conanfile.py b/conanfile.py index 7d8daa44..67799033 100644 --- a/conanfile.py +++ b/conanfile.py @@ -80,7 +80,7 @@ class MPUnitsConan(ConanFile): @property def _skip_la(self): - return bool(self.conf.get("user.build:skip_la", default=True)) + return bool(self.conf.get("user.build:skip_la", default=False)) @property def _skip_docs(self): diff --git a/src/core/include/mp-units/bits/representation_concepts.h b/src/core/include/mp-units/bits/representation_concepts.h index 3a6f440e..503182ba 100644 --- a/src/core/include/mp-units/bits/representation_concepts.h +++ b/src/core/include/mp-units/bits/representation_concepts.h @@ -66,9 +66,11 @@ concept CastableNumber = CommonTypeWith && ScalableNumber -concept Scalable = - CastableNumber || (requires { typename T::value_type; } && CastableNumber && - ScalableNumber>); +concept Scalable = CastableNumber || + (requires { typename T::value_type; } && CastableNumber && + ScalableNumber>) || + (requires { typename T::element_type; } && CastableNumber && + ScalableNumber>); } // namespace detail diff --git a/src/core/include/mp-units/customization_points.h b/src/core/include/mp-units/customization_points.h index e6829f89..af099781 100644 --- a/src/core/include/mp-units/customization_points.h +++ b/src/core/include/mp-units/customization_points.h @@ -45,6 +45,10 @@ template requires requires { typename Rep::value_type; } inline constexpr bool treat_as_floating_point = treat_as_floating_point; +template + requires requires { typename Rep::element_type; } +inline constexpr bool treat_as_floating_point = treat_as_floating_point; + /** * @brief Specifies a type to have a scalar character * diff --git a/test/unit_test/runtime/CMakeLists.txt b/test/unit_test/runtime/CMakeLists.txt index d460233c..ae7936b6 100644 --- a/test/unit_test/runtime/CMakeLists.txt +++ b/test/unit_test/runtime/CMakeLists.txt @@ -27,6 +27,12 @@ find_package(Catch2 3 CONFIG REQUIRED) add_executable(unit_tests_runtime distribution_test.cpp fmt_test.cpp math_test.cpp) target_link_libraries(unit_tests_runtime PRIVATE mp-units::mp-units Catch2::Catch2WithMain) +if(${projectPrefix}BUILD_LA) + find_package(wg21_linear_algebra CONFIG REQUIRED) + target_sources(unit_tests_runtime PRIVATE linear_algebra_test.cpp) + target_link_libraries(unit_tests_runtime PRIVATE wg21_linear_algebra::wg21_linear_algebra) +endif() + if(CMAKE_CXX_COMPILER_ID STREQUAL "MSVC") target_compile_options( unit_tests_runtime PRIVATE /wd4244 # 'conversion' conversion from 'type1' to 'type2', possible loss of data diff --git a/test/unit_test/runtime/linear_algebra_test.cpp b/test/unit_test/runtime/linear_algebra_test.cpp index 2bf908e2..0ba7869a 100644 --- a/test/unit_test/runtime/linear_algebra_test.cpp +++ b/test/unit_test/runtime/linear_algebra_test.cpp @@ -31,56 +31,50 @@ #include #include + +template +using vector = STD_LA::fixed_size_column_vector; + +template +inline constexpr bool mp_units::is_vector> = true; + +template +[[nodiscard]] constexpr mp_units::quantity> operator*(const vector& lhs, R) +{ + return mp_units::make_quantity(lhs); +} + namespace STD_LA { -template -std::ostream& operator<<(std::ostream& os, const vector& v) +template +std::ostream& operator<<(std::ostream& os, const ::vector& v) { os << "|"; for (auto i = 0U; i < v.size(); ++i) { - os << STD_FMT::format(" {:>9}", v(i)); + os << UNITS_STD_FMT::format(" {:>9}", v(i)); } os << " |"; return os; } -template -std::ostream& operator<<(std::ostream& os, const matrix& v) -{ - for (auto i = 0U; i < v.rows(); ++i) { - os << "|"; - for (auto j = 0U; j < v.columns(); ++j) { - os << STD_FMT::format(" {:>9}", v(i, j)); - } - os << (i != v.rows() - 1U ? " |\n" : " |"); - } - return os; -} - } // namespace STD_LA +namespace { + using namespace mp_units; using namespace mp_units::si::unit_symbols; -template -using vector = std::math::fs_vector; - -template -inline constexpr bool mp_units::is_vector> = true; - -namespace { - template [[nodiscard]] auto get_magnitude(const vector& v) { using namespace std; - return hypot(v[0], v[1], v[2]); + return hypot(v(0), v(1), v(2)); } template [[nodiscard]] vector cross_product(const vector& a, const vector& b) { - return {a[1] * b[2] - a[2] * b[1], a[2] * b[0] - a[0] * b[2], a[0] * b[1] - a[1] * b[0]}; + return {a(1) * b(2) - a(2) * b(1), a(2) * b(0) - a(0) * b(2), a(0) * b(1) - a(1) * b(0)}; } template @@ -311,7 +305,7 @@ TEST_CASE("vector of quantities", "[la]") SECTION("to scalar magnitude") { const vector> v = {2 * (km / h), 3 * (km / h), 6 * (km / h)}; - const auto speed = get_magnitude(v).number() * isq::speed[v[0].unit]; // TODO can we do better here? + const auto speed = get_magnitude(v).number() * isq::speed[v(0).unit]; // TODO can we do better here? CHECK(speed.number() == 7); } @@ -336,23 +330,16 @@ TEST_CASE("vector of quantities", "[la]") } } - // TODO check if the below is a bug in mp-units or LA - // SECTION("divide by scalar value") - // { - // const vector> v = {isq::position_vector[m](2), isq::position_vector[m](4), - // isq::position_vector[m](6)}; + SECTION("divide by scalar value") + { + const vector> v = {2 * m, 4 * m, 6 * m}; - // SECTION("integral") - // { - // CHECK(v / 2 == vector>{ - // isq::position_vector[m](1), isq::position_vector[m](2), isq::position_vector[m](3)}); - // } - // SECTION("floating-point") - // { - // CHECK(v / 0.5 == vector>{ - // isq::position_vector[m](4.), isq::position_vector[m](8.), isq::position_vector[m](12.)}); - // } - // } + SECTION("integral") { CHECK(v / 2 == vector>{1 * m, 2 * m, 3 * m}); } + SECTION("floating-point") + { + CHECK(v / 0.5 == vector>{4. * m, 8. * m, 12. * m}); + } + } SECTION("add") { @@ -449,59 +436,54 @@ TEST_CASE("vector of quantities", "[la]") } } - // TODO check if the below is a bug in mp-units or LA - // SECTION("divide by scalar quantity") - // { - // const vector> pos = { - // isq::position_vector[km](30), isq::position_vector[km](20), isq::position_vector[km](10)}; + SECTION("divide by scalar quantity") + { + const vector> pos = {30 * km, 20 * km, 10 * km}; - // SECTION("integral") - // { - // const auto dur = 2 * isq::duration[h]; + SECTION("integral") + { + const auto dur = 2 * isq::duration[h]; - // SECTION("derived_quantity_spec") - // { - // CHECK(pos / dur == vector>{ - // isq::velocity[km / h](15), isq::velocity[km / h](10), isq::velocity[km / h](5)}); - // } + SECTION("derived_quantity_spec") + { + CHECK(pos / dur == vector>{15 * (km / h), 10 * (km / h), 5 * (km / h)}); + } - // // no way to apply quantity_cast to sub-components + // no way to apply quantity_cast to sub-components - // SECTION("quantity of velocity") - // { - // const vector> v = pos / dur; - // CHECK(v == vector>{isq::velocity[km / h](15), isq::velocity[km / h](10), - // isq::velocity[km / h](5)}); - // } - // } + SECTION("quantity of velocity") + { + const vector> v = pos / dur; + CHECK(v == vector>{15 * (km / h), 10 * (km / h), 5 * (km / h)}); + } + } - // SECTION("floating-point") - // { - // const auto dur = 0.5 * isq::duration[h]; + SECTION("floating-point") + { + const auto dur = 0.5 * isq::duration[h]; - // SECTION("derived_quantity_spec") - // { - // CHECK(pos / dur == vector>{ - // isq::velocity[km / h](60.), isq::velocity[km / h](40.), isq::velocity[km / h](20)}); - // } + SECTION("derived_quantity_spec") + { + CHECK(pos / dur == + vector>{60. * (km / h), 40. * (km / h), 20. * (km / h)}); + } - // // no way to apply quantity_cast to sub-components + // no way to apply quantity_cast to sub-components - // SECTION("quantity of velocity") - // { - // const vector> v = pos / dur; - // CHECK(v == vector>{ - // isq::velocity[km / h](60.), isq::velocity[km / h](40.), isq::velocity[km / h](20)}); - // } - // } - // } + SECTION("quantity of velocity") + { + const vector> v = pos / dur; + CHECK(v == vector>{60. * (km / h), 40. * (km / h), 20. * (km / h)}); + } + } + } - // SECTION("cross product with a vector of quantities") - // { - // const vector> r{ - // vector{isq::position_vector[m](3), isq::position_vector[m](0), isq::position_vector[m](0)}}; - // const vector> f{vector{isq::force[N](0), isq::force[N](10), isq::force[N](0)}}; + SECTION("cross product with a vector of quantities") + { + const vector> r = {3 * m, 0 * m, 0 * m}; + const vector> f = {0 * N, 10 * N, 0 * N}; - // CHECK(cross_product(r, f) == vector>{0, 0, 30})); - // } + CHECK(cross_product(r, f) == + vector>{0 * (N * m), 0 * (N * m), 30 * (N * m)}); + } }