feat: linear algebra library usage re-enabled

This commit is contained in:
Mateusz Pusz
2023-06-12 11:47:30 +03:00
parent 272a8d8b5c
commit 7b22155bf3
5 changed files with 86 additions and 92 deletions

View File

@@ -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):

View File

@@ -66,9 +66,11 @@ concept CastableNumber = CommonTypeWith<T, std::intmax_t> && ScalableNumber<std:
// TODO Fix it according to sudo_cast implementation
template<typename T>
concept Scalable =
CastableNumber<T> || (requires { typename T::value_type; } && CastableNumber<typename T::value_type> &&
ScalableNumber<T, std::common_type_t<typename T::value_type, std::intmax_t>>);
concept Scalable = CastableNumber<T> ||
(requires { typename T::value_type; } && CastableNumber<typename T::value_type> &&
ScalableNumber<T, std::common_type_t<typename T::value_type, std::intmax_t>>) ||
(requires { typename T::element_type; } && CastableNumber<typename T::element_type> &&
ScalableNumber<T, std::common_type_t<typename T::element_type, std::intmax_t>>);
} // namespace detail

View File

@@ -45,6 +45,10 @@ template<typename Rep>
requires requires { typename Rep::value_type; }
inline constexpr bool treat_as_floating_point<Rep> = treat_as_floating_point<typename Rep::value_type>;
template<typename Rep>
requires requires { typename Rep::element_type; }
inline constexpr bool treat_as_floating_point<Rep> = treat_as_floating_point<typename Rep::element_type>;
/**
* @brief Specifies a type to have a scalar character
*

View File

@@ -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

View File

@@ -31,56 +31,50 @@
#include <cmath>
#include <matrix>
template<typename Rep = double>
using vector = STD_LA::fixed_size_column_vector<Rep, 3>;
template<typename Rep>
inline constexpr bool mp_units::is_vector<vector<Rep>> = true;
template<typename Rep, mp_units::Reference R>
[[nodiscard]] constexpr mp_units::quantity<R{}, vector<Rep>> operator*(const vector<Rep>& lhs, R)
{
return mp_units::make_quantity<R{}>(lhs);
}
namespace STD_LA {
template<class ET, class OT>
std::ostream& operator<<(std::ostream& os, const vector<ET, OT>& v)
template<typename Rep>
std::ostream& operator<<(std::ostream& os, const ::vector<Rep>& 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<class ET, class OT>
std::ostream& operator<<(std::ostream& os, const matrix<ET, OT>& 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<typename Rep = double>
using vector = std::math::fs_vector<Rep, 3>;
template<typename Rep>
inline constexpr bool mp_units::is_vector<vector<Rep>> = true;
namespace {
template<typename T>
[[nodiscard]] auto get_magnitude(const vector<T>& v)
{
using namespace std;
return hypot(v[0], v[1], v[2]);
return hypot(v(0), v(1), v(2));
}
template<typename T, typename U>
[[nodiscard]] vector<decltype(T{} * U{})> cross_product(const vector<T>& a, const vector<U>& 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<Quantity Q1, Quantity Q2>
@@ -311,7 +305,7 @@ TEST_CASE("vector of quantities", "[la]")
SECTION("to scalar magnitude")
{
const vector<quantity<isq::velocity[km / h], int>> 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<quantity<isq::position_vector[m], int>> v = {isq::position_vector[m](2), isq::position_vector[m](4),
// isq::position_vector[m](6)};
SECTION("divide by scalar value")
{
const vector<quantity<isq::position_vector[m], int>> v = {2 * m, 4 * m, 6 * m};
// SECTION("integral")
// {
// CHECK(v / 2 == vector<quantity<isq::position_vector[m], int>>{
// isq::position_vector[m](1), isq::position_vector[m](2), isq::position_vector[m](3)});
// }
// SECTION("floating-point")
// {
// CHECK(v / 0.5 == vector<quantity<isq::position_vector[m], double>>{
// isq::position_vector[m](4.), isq::position_vector[m](8.), isq::position_vector[m](12.)});
// }
// }
SECTION("integral") { CHECK(v / 2 == vector<quantity<isq::position_vector[m], int>>{1 * m, 2 * m, 3 * m}); }
SECTION("floating-point")
{
CHECK(v / 0.5 == vector<quantity<isq::position_vector[m], double>>{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<quantity<isq::position_vector[km], int>> pos = {
// isq::position_vector[km](30), isq::position_vector[km](20), isq::position_vector[km](10)};
SECTION("divide by scalar quantity")
{
const vector<quantity<isq::position_vector[km], int>> 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<quantity<isq::velocity[km / h], int>>{
// isq::velocity[km / h](15), isq::velocity[km / h](10), isq::velocity[km / h](5)});
// }
SECTION("derived_quantity_spec")
{
CHECK(pos / dur == vector<quantity<isq::velocity[km / h], int>>{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<quantity<isq::velocity[km / h], int>> v = pos / dur;
// CHECK(v == vector<quantity<isq::velocity[km / h], int>>{isq::velocity[km / h](15), isq::velocity[km / h](10),
// isq::velocity[km / h](5)});
// }
// }
SECTION("quantity of velocity")
{
const vector<quantity<isq::velocity[km / h], int>> v = pos / dur;
CHECK(v == vector<quantity<isq::velocity[km / h], int>>{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<quantity<isq::velocity[km / h], double>>{
// isq::velocity[km / h](60.), isq::velocity[km / h](40.), isq::velocity[km / h](20)});
// }
SECTION("derived_quantity_spec")
{
CHECK(pos / dur ==
vector<quantity<isq::velocity[km / h], double>>{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<quantity<isq::velocity[km / h], double>> v = pos / dur;
// CHECK(v == vector<quantity<isq::velocity[km / h], double>>{
// isq::velocity[km / h](60.), isq::velocity[km / h](40.), isq::velocity[km / h](20)});
// }
// }
// }
SECTION("quantity of velocity")
{
const vector<quantity<isq::velocity[km / h], double>> v = pos / dur;
CHECK(v == vector<quantity<isq::velocity[km / h], double>>{60. * (km / h), 40. * (km / h), 20. * (km / h)});
}
}
}
// SECTION("cross product with a vector of quantities")
// {
// const vector<quantity<isq::position_vector[m], int>> r{
// vector<int>{isq::position_vector[m](3), isq::position_vector[m](0), isq::position_vector[m](0)}};
// const vector<quantity<isq::force[N], int>> f{vector<int>{isq::force[N](0), isq::force[N](10), isq::force[N](0)}};
SECTION("cross product with a vector of quantities")
{
const vector<quantity<isq::position_vector[m], int>> r = {3 * m, 0 * m, 0 * m};
const vector<quantity<isq::force[N], int>> f = {0 * N, 10 * N, 0 * N};
// CHECK(cross_product(r, f) == vector<quantity<isq::moment_of_force[N * m], int>>{0, 0, 30}));
// }
CHECK(cross_product(r, f) ==
vector<quantity<isq::moment_of_force[N * m], int>>{0 * (N * m), 0 * (N * m), 30 * (N * m)});
}
}