2023-01-04 19:06:25 +01:00
|
|
|
// The MIT License (MIT)
|
|
|
|
//
|
|
|
|
// Copyright (c) 2018 Mateusz Pusz
|
|
|
|
//
|
|
|
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
|
|
// of this software and associated documentation files (the "Software"), to deal
|
|
|
|
// in the Software without restriction, including without limitation the rights
|
|
|
|
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
|
|
// copies of the Software, and to permit persons to whom the Software is
|
|
|
|
// furnished to do so, subject to the following conditions:
|
|
|
|
//
|
|
|
|
// The above copyright notice and this permission notice shall be included in all
|
|
|
|
// copies or substantial portions of the Software.
|
|
|
|
//
|
|
|
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
|
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
|
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
|
|
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
|
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
|
|
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
|
|
// SOFTWARE.
|
|
|
|
|
|
|
|
#include <catch2/catch_test_macros.hpp>
|
2024-01-06 08:51:01 +01:00
|
|
|
#include <mp-units/compat_macros.h>
|
2024-06-10 22:13:37 +02:00
|
|
|
#include <mp-units/ext/format.h>
|
2024-07-16 17:36:00 +02:00
|
|
|
#ifdef MP_UNITS_IMPORT_STD
|
|
|
|
import std;
|
|
|
|
#else
|
2024-01-06 08:51:00 +01:00
|
|
|
#include <matrix>
|
2024-04-24 20:53:54 +02:00
|
|
|
#include <ostream>
|
2024-07-16 17:36:00 +02:00
|
|
|
#endif
|
2024-01-06 08:51:00 +01:00
|
|
|
#ifdef MP_UNITS_MODULES
|
|
|
|
import mp_units;
|
|
|
|
#else
|
2023-05-25 12:47:10 +02:00
|
|
|
#include <mp-units/math.h>
|
|
|
|
#include <mp-units/systems/isq/mechanics.h>
|
|
|
|
#include <mp-units/systems/isq/space_and_time.h>
|
2024-04-25 16:30:52 +02:00
|
|
|
#include <mp-units/systems/si.h>
|
2024-01-06 08:51:00 +01:00
|
|
|
#endif
|
2023-01-04 19:06:25 +01:00
|
|
|
|
2023-06-12 11:47:30 +03:00
|
|
|
template<typename Rep = double>
|
|
|
|
using vector = STD_LA::fixed_size_column_vector<Rep, 3>;
|
|
|
|
|
|
|
|
template<typename Rep>
|
2023-08-23 16:46:15 +02:00
|
|
|
std::ostream& operator<<(std::ostream& os, const vector<Rep>& v)
|
2023-01-04 19:06:25 +01:00
|
|
|
{
|
|
|
|
os << "|";
|
|
|
|
for (auto i = 0U; i < v.size(); ++i) {
|
2023-06-21 18:05:21 +02:00
|
|
|
os << MP_UNITS_STD_FMT::format(" {:>9}", v(i));
|
2023-01-04 19:06:25 +01:00
|
|
|
}
|
|
|
|
os << " |";
|
|
|
|
return os;
|
|
|
|
}
|
|
|
|
|
2023-06-12 11:47:30 +03:00
|
|
|
namespace {
|
|
|
|
|
2023-01-04 19:06:25 +01:00
|
|
|
using namespace mp_units;
|
|
|
|
using namespace mp_units::si::unit_symbols;
|
|
|
|
|
2023-09-13 19:53:32 +02:00
|
|
|
template<QuantitySpec auto QS, QuantityOf<QS> Q>
|
2025-02-11 17:26:19 +01:00
|
|
|
requires(Q::quantity_spec.character == quantity_character::vector) &&
|
|
|
|
(QS.character == quantity_character::real_scalar)
|
2023-09-26 19:15:57 +02:00
|
|
|
[[nodiscard]] constexpr QuantityOf<QS> auto get_magnitude(const Q& q)
|
2023-01-04 19:06:25 +01:00
|
|
|
{
|
2023-09-13 19:53:32 +02:00
|
|
|
const auto& v = q.numerical_value_ref_in(q.unit);
|
2023-09-26 19:15:57 +02:00
|
|
|
return hypot(v(0) * QS[Q::unit], v(1) * QS[Q::unit], v(2) * QS[Q::unit]);
|
2023-09-13 19:53:32 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
template<QuantitySpec auto QS, QuantityOf<QS> T>
|
2025-02-11 17:26:19 +01:00
|
|
|
requires(T::quantity_spec.character == quantity_character::vector) &&
|
|
|
|
(QS.character == quantity_character::real_scalar)
|
2023-09-26 19:15:57 +02:00
|
|
|
[[nodiscard]] constexpr QuantityOf<QS> auto get_magnitude(const vector<T>& v)
|
2023-09-13 19:53:32 +02:00
|
|
|
{
|
|
|
|
return hypot(QS(v(0)), QS(v(1)), QS(v(2)));
|
2023-01-04 19:06:25 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
template<typename T, typename U>
|
2023-09-26 19:15:57 +02:00
|
|
|
[[nodiscard]] constexpr vector<decltype(T{} * U{})> cross_product(const vector<T>& a, const vector<U>& b)
|
2023-01-04 19:06:25 +01:00
|
|
|
{
|
2023-06-12 11:47:30 +03:00
|
|
|
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)};
|
2023-01-04 19:06:25 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
template<Quantity Q1, Quantity Q2>
|
2023-09-26 19:15:57 +02:00
|
|
|
[[nodiscard]] constexpr QuantityOf<Q1::quantity_spec * Q2::quantity_spec> auto cross_product(const Q1& q1, const Q2& q2)
|
2023-01-04 19:06:25 +01:00
|
|
|
{
|
2023-08-27 20:19:26 +02:00
|
|
|
return cross_product(q1.numerical_value_ref_in(q1.unit), q2.numerical_value_ref_in(q2.unit)) *
|
|
|
|
(Q1::reference * Q2::reference);
|
2023-01-04 19:06:25 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
} // namespace
|
|
|
|
|
|
|
|
TEST_CASE("vector quantity", "[la]")
|
|
|
|
{
|
|
|
|
SECTION("cast of unit")
|
|
|
|
{
|
|
|
|
SECTION("non-truncating")
|
|
|
|
{
|
2024-11-06 18:46:01 +01:00
|
|
|
const auto v = vector<int>{3, 2, 1} * isq::displacement[km];
|
2023-08-27 20:19:26 +02:00
|
|
|
CHECK(v.numerical_value_in(m) == vector<int>{3000, 2000, 1000});
|
2023-01-04 19:06:25 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
SECTION("truncating")
|
|
|
|
{
|
2024-11-06 18:46:01 +01:00
|
|
|
const auto v = vector<int>{1001, 1002, 1003} * isq::displacement[m];
|
2023-09-12 16:33:02 +02:00
|
|
|
CHECK(v.force_numerical_value_in(km) == vector<int>{1, 1, 1});
|
2023-01-04 19:06:25 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
SECTION("to scalar magnitude")
|
|
|
|
{
|
2023-02-13 19:05:58 +01:00
|
|
|
const auto v = vector<int>{2, 3, 6} * isq::velocity[km / h];
|
2023-09-13 19:53:32 +02:00
|
|
|
const auto speed = get_magnitude<isq::speed>(v);
|
2023-08-27 20:19:26 +02:00
|
|
|
CHECK(speed.numerical_value_ref_in(km / h) == 7);
|
2023-01-04 19:06:25 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
SECTION("multiply by scalar value")
|
|
|
|
{
|
2024-11-06 18:46:01 +01:00
|
|
|
const auto v = vector<int>{1, 2, 3} * isq::displacement[m];
|
2023-01-04 19:06:25 +01:00
|
|
|
|
|
|
|
SECTION("integral")
|
|
|
|
{
|
2023-10-17 14:16:22 +02:00
|
|
|
SECTION("scalar on LHS") { CHECK((2 * v).numerical_value_in(m) == vector<int>{2, 4, 6}); }
|
|
|
|
SECTION("scalar on RHS") { CHECK((v * 2).numerical_value_in(m) == vector<int>{2, 4, 6}); }
|
2023-01-04 19:06:25 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
SECTION("floating-point")
|
|
|
|
{
|
2023-10-17 14:16:22 +02:00
|
|
|
SECTION("scalar on LHS") { CHECK((0.5 * v).numerical_value_in(m) == vector<double>{0.5, 1., 1.5}); }
|
|
|
|
SECTION("scalar on RHS") { CHECK((v * 0.5).numerical_value_in(m) == vector<double>{0.5, 1., 1.5}); }
|
2023-01-04 19:06:25 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
SECTION("divide by scalar value")
|
|
|
|
{
|
2024-11-06 18:46:01 +01:00
|
|
|
const auto v = vector<int>{2, 4, 6} * isq::displacement[m];
|
2023-01-04 19:06:25 +01:00
|
|
|
|
2023-10-17 14:16:22 +02:00
|
|
|
SECTION("integral") { CHECK((v / 2).numerical_value_in(m) == vector<int>{1, 2, 3}); }
|
|
|
|
SECTION("floating-point") { CHECK((v / 0.5).numerical_value_in(m) == vector<double>{4., 8., 12.}); }
|
2023-01-04 19:06:25 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
SECTION("add")
|
|
|
|
{
|
2024-11-06 18:46:01 +01:00
|
|
|
const auto v = vector<int>{1, 2, 3} * isq::displacement[m];
|
2023-01-04 19:06:25 +01:00
|
|
|
|
|
|
|
SECTION("same unit")
|
|
|
|
{
|
2024-11-06 18:46:01 +01:00
|
|
|
const auto u = vector<int>{3, 2, 1} * isq::displacement[m];
|
2023-10-17 14:16:22 +02:00
|
|
|
CHECK((v + u).numerical_value_in(m) == vector<int>{4, 4, 4});
|
2023-01-04 19:06:25 +01:00
|
|
|
}
|
|
|
|
SECTION("different units")
|
|
|
|
{
|
2024-11-06 18:46:01 +01:00
|
|
|
const auto u = vector<int>{3, 2, 1} * isq::displacement[km];
|
2023-10-17 14:16:22 +02:00
|
|
|
CHECK((v + u).numerical_value_in(m) == vector<int>{3001, 2002, 1003});
|
2023-01-04 19:06:25 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
SECTION("subtract")
|
|
|
|
{
|
2024-11-06 18:46:01 +01:00
|
|
|
const auto v = vector<int>{1, 2, 3} * isq::displacement[m];
|
2023-01-04 19:06:25 +01:00
|
|
|
|
|
|
|
SECTION("same unit")
|
|
|
|
{
|
2024-11-06 18:46:01 +01:00
|
|
|
const auto u = vector<int>{3, 2, 1} * isq::displacement[m];
|
2023-10-17 14:16:22 +02:00
|
|
|
CHECK((v - u).numerical_value_in(m) == vector<int>{-2, 0, 2});
|
2023-01-04 19:06:25 +01:00
|
|
|
}
|
|
|
|
SECTION("different units")
|
|
|
|
{
|
2024-11-06 18:46:01 +01:00
|
|
|
const auto u = vector<int>{3, 2, 1} * isq::displacement[km];
|
2023-10-17 14:16:22 +02:00
|
|
|
CHECK((v - u).numerical_value_in(m) == vector<int>{-2999, -1998, -997});
|
2023-01-04 19:06:25 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
SECTION("multiply by scalar quantity")
|
|
|
|
{
|
2023-02-13 19:05:58 +01:00
|
|
|
const auto v = vector<int>{1, 2, 3} * isq::velocity[m / s];
|
2023-01-04 19:06:25 +01:00
|
|
|
|
|
|
|
SECTION("integral")
|
|
|
|
{
|
|
|
|
const auto mass = 2 * isq::mass[kg];
|
|
|
|
|
|
|
|
SECTION("derived_quantity_spec")
|
|
|
|
{
|
2023-10-17 14:16:22 +02:00
|
|
|
SECTION("scalar on LHS") { CHECK((mass * v).numerical_value_in(kg * m / s) == vector<int>{2, 4, 6}); }
|
|
|
|
SECTION("scalar on RHS") { CHECK((v * mass).numerical_value_in(kg * m / s) == vector<int>{2, 4, 6}); }
|
2023-01-04 19:06:25 +01:00
|
|
|
}
|
|
|
|
SECTION("quantity_cast to momentum")
|
|
|
|
{
|
2023-08-30 11:30:35 +02:00
|
|
|
SECTION("scalar on LHS")
|
|
|
|
{
|
2023-10-17 14:16:22 +02:00
|
|
|
CHECK(quantity_cast<isq::momentum>(mass * v).numerical_value_in(N * s) == vector<int>{2, 4, 6});
|
2023-08-30 11:30:35 +02:00
|
|
|
}
|
|
|
|
SECTION("scalar on RHS")
|
|
|
|
{
|
2023-10-17 14:16:22 +02:00
|
|
|
CHECK(quantity_cast<isq::momentum>(v * mass).numerical_value_in(N * s) == vector<int>{2, 4, 6});
|
2023-08-30 11:30:35 +02:00
|
|
|
}
|
2023-01-04 19:06:25 +01:00
|
|
|
}
|
|
|
|
SECTION("quantity of momentum")
|
|
|
|
{
|
|
|
|
SECTION("scalar on LHS")
|
|
|
|
{
|
2023-02-14 12:29:45 +01:00
|
|
|
const quantity<isq::momentum[N * s], vector<int>> momentum = mass * v;
|
2023-10-17 14:16:22 +02:00
|
|
|
CHECK(momentum.numerical_value_ref_in(N * s) == vector<int>{2, 4, 6});
|
2023-01-04 19:06:25 +01:00
|
|
|
}
|
|
|
|
SECTION("scalar on RHS")
|
|
|
|
{
|
2023-02-14 12:29:45 +01:00
|
|
|
const quantity<isq::momentum[N * s], vector<int>> momentum = v * mass;
|
2023-10-17 14:16:22 +02:00
|
|
|
CHECK(momentum.numerical_value_ref_in(N * s) == vector<int>{2, 4, 6});
|
2023-01-04 19:06:25 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
SECTION("floating-point")
|
|
|
|
{
|
|
|
|
const auto mass = 0.5 * isq::mass[kg];
|
|
|
|
|
|
|
|
SECTION("derived_quantity_spec")
|
|
|
|
{
|
2023-10-17 14:16:22 +02:00
|
|
|
SECTION("scalar on LHS") { CHECK((mass * v).numerical_value_in(kg * m / s) == vector<double>{0.5, 1., 1.5}); }
|
|
|
|
SECTION("scalar on RHS") { CHECK((v * mass).numerical_value_in(kg * m / s) == vector<double>{0.5, 1., 1.5}); }
|
2023-01-04 19:06:25 +01:00
|
|
|
}
|
|
|
|
SECTION("quantity_cast to momentum")
|
|
|
|
{
|
|
|
|
SECTION("scalar on LHS")
|
|
|
|
{
|
2023-10-17 14:16:22 +02:00
|
|
|
CHECK(quantity_cast<isq::momentum>(mass * v).numerical_value_in(N * s) == vector<double>{0.5, 1., 1.5});
|
2023-01-04 19:06:25 +01:00
|
|
|
}
|
|
|
|
SECTION("scalar on RHS")
|
|
|
|
{
|
2023-10-17 14:16:22 +02:00
|
|
|
CHECK(quantity_cast<isq::momentum>(v * mass).numerical_value_in(N * s) == vector<double>{0.5, 1., 1.5});
|
2023-01-04 19:06:25 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
SECTION("quantity of momentum")
|
|
|
|
{
|
|
|
|
SECTION("scalar on LHS")
|
|
|
|
{
|
2023-02-14 12:29:45 +01:00
|
|
|
const quantity<isq::momentum[N * s], vector<double>> momentum = mass * v;
|
2023-10-17 14:16:22 +02:00
|
|
|
CHECK(momentum.numerical_value_ref_in(N * s) == vector<double>{0.5, 1., 1.5});
|
2023-01-04 19:06:25 +01:00
|
|
|
}
|
|
|
|
SECTION("scalar on RHS")
|
|
|
|
{
|
2023-02-14 12:29:45 +01:00
|
|
|
const quantity<isq::momentum[N * s], vector<double>> momentum = v * mass;
|
2023-10-17 14:16:22 +02:00
|
|
|
CHECK(momentum.numerical_value_ref_in(N * s) == vector<double>{0.5, 1., 1.5});
|
2023-01-04 19:06:25 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
SECTION("divide by scalar quantity")
|
|
|
|
{
|
2024-11-06 18:46:01 +01:00
|
|
|
const auto pos = vector<int>{30, 20, 10} * isq::displacement[km];
|
2023-01-04 19:06:25 +01:00
|
|
|
|
|
|
|
SECTION("integral")
|
|
|
|
{
|
|
|
|
const auto dur = 2 * isq::duration[h];
|
|
|
|
|
2023-10-17 14:16:22 +02:00
|
|
|
SECTION("derived_quantity_spec") { CHECK((pos / dur).numerical_value_in(km / h) == vector<int>{15, 10, 5}); }
|
2023-01-04 19:06:25 +01:00
|
|
|
SECTION("quantity_cast to velocity")
|
|
|
|
{
|
2023-10-17 14:16:22 +02:00
|
|
|
CHECK(quantity_cast<isq::velocity>(pos / dur).numerical_value_in(km / h) == vector<int>{15, 10, 5});
|
2023-01-04 19:06:25 +01:00
|
|
|
}
|
|
|
|
SECTION("quantity of velocity")
|
|
|
|
{
|
|
|
|
const quantity<isq::velocity[km / h], vector<int>> v = pos / dur;
|
2023-10-17 14:16:22 +02:00
|
|
|
CHECK(v.numerical_value_ref_in(km / h) == vector<int>{15, 10, 5});
|
2023-01-04 19:06:25 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
SECTION("floating-point")
|
|
|
|
{
|
|
|
|
const auto dur = 0.5 * isq::duration[h];
|
|
|
|
|
2023-10-17 14:16:22 +02:00
|
|
|
SECTION("derived_quantity_spec") { CHECK((pos / dur).numerical_value_in(km / h) == vector<double>{60, 40, 20}); }
|
2023-01-04 19:06:25 +01:00
|
|
|
SECTION("quantity_cast to velocity")
|
|
|
|
{
|
2023-10-17 14:16:22 +02:00
|
|
|
CHECK(quantity_cast<isq::velocity>(pos / dur).numerical_value_in(km / h) == vector<double>{60, 40, 20});
|
2023-01-04 19:06:25 +01:00
|
|
|
}
|
|
|
|
SECTION("quantity of velocity")
|
|
|
|
{
|
|
|
|
const quantity<isq::velocity[km / h], vector<double>> v = pos / dur;
|
2023-10-17 14:16:22 +02:00
|
|
|
CHECK(v.numerical_value_ref_in(km / h) == vector<double>{60, 40, 20});
|
2023-01-04 19:06:25 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
SECTION("cross product with a vector quantity")
|
|
|
|
{
|
2024-11-06 18:46:01 +01:00
|
|
|
const auto r = vector<int>{3, 0, 0} * isq::displacement[m];
|
2023-02-14 12:29:45 +01:00
|
|
|
const auto f = vector<int>{0, 10, 0} * isq::force[N];
|
2023-01-04 19:06:25 +01:00
|
|
|
|
2023-02-14 12:29:45 +01:00
|
|
|
CHECK(cross_product(r, f) == vector<int>{0, 0, 30} * isq::moment_of_force[N * m]);
|
2023-01-04 19:06:25 +01:00
|
|
|
}
|
|
|
|
}
|
2023-02-14 12:29:45 +01:00
|
|
|
|
|
|
|
TEST_CASE("vector of quantities", "[la]")
|
|
|
|
{
|
|
|
|
SECTION("cast of unit")
|
|
|
|
{
|
|
|
|
SECTION("non-truncating")
|
|
|
|
{
|
2024-11-06 18:46:01 +01:00
|
|
|
const vector<quantity<isq::displacement[km], int>> v = {3 * km, 2 * km, 1 * km};
|
2023-02-14 12:29:45 +01:00
|
|
|
|
2024-11-06 18:46:01 +01:00
|
|
|
CHECK(vector<quantity<isq::displacement[m], int>>(v) ==
|
|
|
|
vector<quantity<isq::displacement[m], int>>{3000 * m, 2000 * m, 1000 * m});
|
2023-02-14 12:29:45 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
// truncating not possible (no way to apply quantity_cast to sub-components of a vector)
|
|
|
|
}
|
|
|
|
|
|
|
|
SECTION("to scalar magnitude")
|
|
|
|
{
|
2023-09-29 21:40:24 -06:00
|
|
|
const vector<quantity<isq::velocity[km / h], int>> v = {2 * km / h, 3 * km / h, 6 * km / h};
|
2023-09-13 19:53:32 +02:00
|
|
|
const auto speed = get_magnitude<isq::speed>(v);
|
2023-08-27 20:19:26 +02:00
|
|
|
CHECK(speed.numerical_value_ref_in(km / h) == 7);
|
2023-02-14 12:29:45 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
SECTION("multiply by scalar value")
|
|
|
|
{
|
2024-11-06 18:46:01 +01:00
|
|
|
const vector<quantity<isq::displacement[m], int>> v = {1 * m, 2 * m, 3 * m};
|
2023-02-14 12:29:45 +01:00
|
|
|
|
|
|
|
SECTION("integral")
|
|
|
|
{
|
2024-11-06 18:46:01 +01:00
|
|
|
const vector<quantity<isq::displacement[m], int>> result = {2 * m, 4 * m, 6 * m};
|
2023-02-14 12:29:45 +01:00
|
|
|
|
|
|
|
SECTION("scalar on LHS") { CHECK(2 * v == result); }
|
|
|
|
SECTION("scalar on RHS") { CHECK(v * 2 == result); }
|
|
|
|
}
|
|
|
|
|
|
|
|
SECTION("floating-point")
|
|
|
|
{
|
2024-11-06 18:46:01 +01:00
|
|
|
const vector<quantity<isq::displacement[m], double>> result = {0.5 * m, 1. * m, 1.5 * m};
|
2023-02-14 12:29:45 +01:00
|
|
|
|
|
|
|
SECTION("scalar on LHS") { CHECK(0.5 * v == result); }
|
|
|
|
SECTION("scalar on RHS") { CHECK(v * 0.5 == result); }
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-06-12 11:47:30 +03:00
|
|
|
SECTION("divide by scalar value")
|
|
|
|
{
|
2024-11-06 18:46:01 +01:00
|
|
|
const vector<quantity<isq::displacement[m], int>> v = {2 * m, 4 * m, 6 * m};
|
2023-06-12 11:47:30 +03:00
|
|
|
|
2024-11-06 18:46:01 +01:00
|
|
|
SECTION("integral") { CHECK(v / 2 == vector<quantity<isq::displacement[m], int>>{1 * m, 2 * m, 3 * m}); }
|
2023-06-12 11:47:30 +03:00
|
|
|
SECTION("floating-point")
|
|
|
|
{
|
2024-11-06 18:46:01 +01:00
|
|
|
CHECK(v / 0.5 == vector<quantity<isq::displacement[m], double>>{4. * m, 8. * m, 12. * m});
|
2023-06-12 11:47:30 +03:00
|
|
|
}
|
|
|
|
}
|
2023-02-14 12:29:45 +01:00
|
|
|
|
|
|
|
SECTION("add")
|
|
|
|
{
|
2024-11-06 18:46:01 +01:00
|
|
|
const vector<quantity<isq::displacement[m], int>> v = {1 * m, 2 * m, 3 * m};
|
2023-02-14 12:29:45 +01:00
|
|
|
|
|
|
|
SECTION("same unit")
|
|
|
|
{
|
2024-11-06 18:46:01 +01:00
|
|
|
const vector<quantity<isq::displacement[m], int>> u = {3 * m, 2 * m, 1 * m};
|
2023-02-14 12:29:45 +01:00
|
|
|
|
2024-11-06 18:46:01 +01:00
|
|
|
CHECK(v + u == vector<quantity<isq::displacement[m], int>>{4 * m, 4 * m, 4 * m});
|
2023-02-14 12:29:45 +01:00
|
|
|
}
|
|
|
|
SECTION("different units")
|
|
|
|
{
|
2024-11-06 18:46:01 +01:00
|
|
|
const vector<quantity<isq::displacement[km], int>> u = {3 * km, 2 * km, 1 * km};
|
2023-02-14 12:29:45 +01:00
|
|
|
|
2024-11-06 18:46:01 +01:00
|
|
|
CHECK(v + u == vector<quantity<isq::displacement[m], int>>{3001 * m, 2002 * m, 1003 * m});
|
2023-02-14 12:29:45 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
SECTION("subtract")
|
|
|
|
{
|
2024-11-06 18:46:01 +01:00
|
|
|
const vector<quantity<isq::displacement[m], int>> v = {1 * m, 2 * m, 3 * m};
|
2023-02-14 12:29:45 +01:00
|
|
|
|
|
|
|
SECTION("same unit")
|
|
|
|
{
|
2024-11-06 18:46:01 +01:00
|
|
|
const vector<quantity<isq::displacement[m], int>> u = {3 * m, 2 * m, 1 * m};
|
|
|
|
CHECK(v - u == vector<quantity<isq::displacement[m], int>>{-2 * m, 0 * m, 2 * m});
|
2023-02-14 12:29:45 +01:00
|
|
|
}
|
|
|
|
SECTION("different units")
|
|
|
|
{
|
2024-11-06 18:46:01 +01:00
|
|
|
const vector<quantity<isq::displacement[km], int>> u = {3 * km, 2 * km, 1 * km};
|
|
|
|
CHECK(v - u == vector<quantity<isq::displacement[m], int>>{-2999 * m, -1998 * m, -997 * m});
|
2023-02-14 12:29:45 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
SECTION("multiply by scalar quantity")
|
|
|
|
{
|
2023-09-29 21:40:24 -06:00
|
|
|
const vector<quantity<isq::velocity[m / s], int>> v = {1 * m / s, 2 * m / s, 3 * m / s};
|
2023-02-14 12:29:45 +01:00
|
|
|
|
|
|
|
SECTION("integral")
|
|
|
|
{
|
|
|
|
const auto mass = 2 * isq::mass[kg];
|
2023-09-29 21:40:24 -06:00
|
|
|
const auto result = vector<quantity<isq::momentum[N * s], int>>{2 * N * s, 4 * N * s, 6 * N * s};
|
2023-02-14 12:29:45 +01:00
|
|
|
|
|
|
|
SECTION("derived_quantity_spec")
|
|
|
|
{
|
|
|
|
SECTION("scalar on LHS") { CHECK(mass * v == result); }
|
|
|
|
SECTION("scalar on RHS") { CHECK(v * mass == result); }
|
|
|
|
}
|
|
|
|
|
|
|
|
// no way to apply quantity_cast to sub-components
|
|
|
|
|
|
|
|
SECTION("quantity of momentum")
|
|
|
|
{
|
|
|
|
SECTION("scalar on LHS")
|
|
|
|
{
|
|
|
|
const vector<quantity<isq::momentum[N * s], int>> momentum = mass * v;
|
|
|
|
CHECK(momentum == result);
|
|
|
|
}
|
|
|
|
SECTION("scalar on RHS")
|
|
|
|
{
|
|
|
|
const vector<quantity<isq::momentum[N * s], int>> momentum = v * mass;
|
|
|
|
CHECK(momentum == result);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
SECTION("floating-point")
|
|
|
|
{
|
|
|
|
const auto mass = 0.5 * isq::mass[kg];
|
2023-09-29 21:40:24 -06:00
|
|
|
const auto result = vector<quantity<isq::momentum[N * s], double>>{0.5 * N * s, 1. * N * s, 1.5 * N * s};
|
2023-02-14 12:29:45 +01:00
|
|
|
|
|
|
|
SECTION("derived_quantity_spec")
|
|
|
|
{
|
|
|
|
SECTION("scalar on LHS") { CHECK(mass * v == result); }
|
|
|
|
SECTION("scalar on RHS") { CHECK(v * mass == result); }
|
|
|
|
}
|
|
|
|
|
|
|
|
// no way to apply quantity_cast to sub-components
|
|
|
|
|
|
|
|
SECTION("quantity of momentum")
|
|
|
|
{
|
|
|
|
SECTION("scalar on LHS")
|
|
|
|
{
|
|
|
|
const vector<quantity<isq::momentum[N * s], double>> momentum = mass * v;
|
|
|
|
CHECK(momentum == result);
|
|
|
|
}
|
|
|
|
SECTION("scalar on RHS")
|
|
|
|
{
|
|
|
|
const vector<quantity<isq::momentum[N * s], double>> momentum = v * mass;
|
|
|
|
CHECK(momentum == result);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-06-12 11:47:30 +03:00
|
|
|
SECTION("divide by scalar quantity")
|
|
|
|
{
|
2024-11-06 18:46:01 +01:00
|
|
|
const vector<quantity<isq::displacement[km], int>> pos = {30 * km, 20 * km, 10 * km};
|
2023-06-12 11:47:30 +03:00
|
|
|
|
|
|
|
SECTION("integral")
|
|
|
|
{
|
|
|
|
const auto dur = 2 * isq::duration[h];
|
|
|
|
|
|
|
|
SECTION("derived_quantity_spec")
|
|
|
|
{
|
2023-09-29 21:40:24 -06:00
|
|
|
CHECK(pos / dur == vector<quantity<isq::velocity[km / h], int>>{15 * km / h, 10 * km / h, 5 * km / h});
|
2023-06-12 11:47:30 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
// no way to apply quantity_cast to sub-components
|
|
|
|
|
|
|
|
SECTION("quantity of velocity")
|
|
|
|
{
|
|
|
|
const vector<quantity<isq::velocity[km / h], int>> v = pos / dur;
|
2023-09-29 21:40:24 -06:00
|
|
|
CHECK(v == vector<quantity<isq::velocity[km / h], int>>{15 * km / h, 10 * km / h, 5 * km / h});
|
2023-06-12 11:47:30 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
SECTION("floating-point")
|
|
|
|
{
|
|
|
|
const auto dur = 0.5 * isq::duration[h];
|
|
|
|
|
|
|
|
SECTION("derived_quantity_spec")
|
|
|
|
{
|
2023-09-29 21:40:24 -06:00
|
|
|
CHECK(pos / dur == vector<quantity<isq::velocity[km / h], double>>{60. * km / h, 40. * km / h, 20. * km / h});
|
2023-06-12 11:47:30 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
// no way to apply quantity_cast to sub-components
|
|
|
|
|
|
|
|
SECTION("quantity of velocity")
|
|
|
|
{
|
|
|
|
const vector<quantity<isq::velocity[km / h], double>> v = pos / dur;
|
2023-09-29 21:40:24 -06:00
|
|
|
CHECK(v == vector<quantity<isq::velocity[km / h], double>>{60. * km / h, 40. * km / h, 20. * km / h});
|
2023-06-12 11:47:30 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
SECTION("cross product with a vector of quantities")
|
|
|
|
{
|
2024-11-06 18:46:01 +01:00
|
|
|
const vector<quantity<isq::displacement[m], int>> r = {3 * m, 0 * m, 0 * m};
|
2023-06-12 11:47:30 +03:00
|
|
|
const vector<quantity<isq::force[N], int>> f = {0 * N, 10 * N, 0 * N};
|
|
|
|
|
2023-09-29 21:40:24 -06:00
|
|
|
CHECK(cross_product(r, f) == vector<quantity<isq::moment_of_force[N * m], int>>{0 * N * m, 0 * N * m, 30 * N * m});
|
2023-06-12 11:47:30 +03:00
|
|
|
}
|
2023-02-14 12:29:45 +01:00
|
|
|
}
|