refactor(utility): deprecate the mp_units:: rep shims and migrate consumers

The cartesian_vector and random distribution types now live in
mp_units::utility. Turn the transitional mp_units:: shims into proper
[[deprecated]] aliases (gcc-12 keeps a plain using-declaration because
CTAD through a deprecated alias template is broken there), and migrate
all in-tree consumers to mp_units::utility:: so the deprecations don't
trip -Werror. cartesian_tensor keeps no shim: it is unreleased (added in
2.6.0, never shipped), so it lives only at mp_units::utility.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Mateusz Pusz
2026-06-27 18:55:19 +02:00
parent 3ebb6076b6
commit ce833d344d
13 changed files with 432 additions and 409 deletions
+129 -123
View File
@@ -45,17 +45,23 @@ using namespace std::complex_literals;
// language narrowing rule: a floating-point target or a widening is implicit, while a
// floating-point -> integer element conversion is explicit (truncating). Same-field conversions
// (incl. integer narrowing) stay implicit, matching `implicitly_scalable` with no unit scaling.
static_assert(std::convertible_to<cartesian_vector<float>, cartesian_vector<double>>); // widen: implicit
static_assert(std::convertible_to<cartesian_vector<double>, cartesian_vector<float>>); // FP target: implicit
static_assert(std::convertible_to<cartesian_vector<int>, cartesian_vector<double>>); // int->FP: implicit
static_assert(std::convertible_to<cartesian_vector<int>, cartesian_vector<long long>>); // int->int: implicit
static_assert(!std::convertible_to<cartesian_vector<double>, cartesian_vector<int>>); // FP->int: explicit
static_assert(std::constructible_from<cartesian_vector<int>, cartesian_vector<double>>); // ...but constructible
static_assert(
std::convertible_to<utility::cartesian_vector<float>, utility::cartesian_vector<double>>); // widen: implicit
static_assert(
std::convertible_to<utility::cartesian_vector<double>, utility::cartesian_vector<float>>); // FP target: implicit
static_assert(
std::convertible_to<utility::cartesian_vector<int>, utility::cartesian_vector<double>>); // int->FP: implicit
static_assert(
std::convertible_to<utility::cartesian_vector<int>, utility::cartesian_vector<long long>>); // int->int: implicit
static_assert(
!std::convertible_to<utility::cartesian_vector<double>, utility::cartesian_vector<int>>); // FP->int: explicit
static_assert(
std::constructible_from<utility::cartesian_vector<int>, utility::cartesian_vector<double>>); // ...but constructible
// the per-axis dimension is queryable at compile time, both as a value and as a call
static_assert(cartesian_vector<double>::extent == 3); // default N
static_assert(cartesian_vector<double, 2>::extent == 2);
static_assert(cartesian_vector<double, 3>::extent() == 3);
static_assert(utility::cartesian_vector<double>::extent == 3); // default N
static_assert(utility::cartesian_vector<double, 2>::extent == 2);
static_assert(utility::cartesian_vector<double, 3>::extent() == 3);
// operations close at a single dimension N: mixing 2D and 3D is ill-formed (no implicit padding).
// Negative tests via named helper concepts asserted with static_assert (the `invalid_types` idiom).
@@ -71,12 +77,12 @@ concept scalar_producible = requires(A a, B b) { scalar_product(a, b); };
template<typename A, typename B>
concept vector_producible = requires(A a, B b) { vector_product(a, b); };
} // namespace
static_assert(!addable<cartesian_vector<double, 2>, cartesian_vector<double, 3>>);
static_assert(!subtractable<cartesian_vector<double, 2>, cartesian_vector<double, 3>>);
static_assert(!equality_comparable<cartesian_vector<double, 2>, cartesian_vector<double, 3>>);
static_assert(!scalar_producible<cartesian_vector<double, 2>, cartesian_vector<double, 3>>);
static_assert(!vector_producible<cartesian_vector<double, 2>, cartesian_vector<double, 3>>);
static_assert(!std::constructible_from<cartesian_vector<double, 3>, cartesian_vector<double, 2>>);
static_assert(!addable<utility::cartesian_vector<double, 2>, utility::cartesian_vector<double, 3>>);
static_assert(!subtractable<utility::cartesian_vector<double, 2>, utility::cartesian_vector<double, 3>>);
static_assert(!equality_comparable<utility::cartesian_vector<double, 2>, utility::cartesian_vector<double, 3>>);
static_assert(!scalar_producible<utility::cartesian_vector<double, 2>, utility::cartesian_vector<double, 3>>);
static_assert(!vector_producible<utility::cartesian_vector<double, 2>, utility::cartesian_vector<double, 3>>);
static_assert(!std::constructible_from<utility::cartesian_vector<double, 3>, utility::cartesian_vector<double, 2>>);
TEST_CASE("cartesian_vector operations", "[vector]")
{
@@ -84,7 +90,7 @@ TEST_CASE("cartesian_vector operations", "[vector]")
{
SECTION("no arguments")
{
cartesian_vector<double> v;
utility::cartesian_vector<double> v;
REQUIRE(v[0] == 0);
REQUIRE(v[1] == 0);
REQUIRE(v[2] == 0);
@@ -92,7 +98,7 @@ TEST_CASE("cartesian_vector operations", "[vector]")
SECTION("zero arguments")
{
cartesian_vector<double> v{};
utility::cartesian_vector<double> v{};
REQUIRE(v[0] == 0);
REQUIRE(v[1] == 0);
REQUIRE(v[2] == 0);
@@ -100,7 +106,7 @@ TEST_CASE("cartesian_vector operations", "[vector]")
SECTION("one argument")
{
cartesian_vector<double> v{1.0}; // explicit 3D: a single component cannot deduce a vector
utility::cartesian_vector<double> v{1.0}; // explicit 3D: a single component cannot deduce a vector
REQUIRE(v[0] == 1.0);
REQUIRE(v[1] == 0);
REQUIRE(v[2] == 0);
@@ -108,7 +114,7 @@ TEST_CASE("cartesian_vector operations", "[vector]")
SECTION("two arguments")
{
cartesian_vector<double> v{1.0, 2.0}; // explicit 3D, third component zero-padded
utility::cartesian_vector<double> v{1.0, 2.0}; // explicit 3D, third component zero-padded
REQUIRE(v[0] == 1.0);
REQUIRE(v[1] == 2.0);
REQUIRE(v[2] == 0);
@@ -116,18 +122,18 @@ TEST_CASE("cartesian_vector operations", "[vector]")
SECTION("deduced dimension")
{
cartesian_vector v2{1.0, 2.0}; // two components -> 2D
static_assert(std::is_same_v<decltype(v2), cartesian_vector<double, 2>>);
utility::cartesian_vector v2{1.0, 2.0}; // two components -> 2D
static_assert(std::is_same_v<decltype(v2), utility::cartesian_vector<double, 2>>);
REQUIRE(v2[0] == 1.0);
REQUIRE(v2[1] == 2.0);
cartesian_vector v3{1.0, 2.0, 3.0}; // three components -> 3D
static_assert(std::is_same_v<decltype(v3), cartesian_vector<double, 3>>);
utility::cartesian_vector v3{1.0, 2.0, 3.0}; // three components -> 3D
static_assert(std::is_same_v<decltype(v3), utility::cartesian_vector<double, 3>>);
}
SECTION("all arguments")
{
cartesian_vector v{1.0, 2.0, 3.0};
utility::cartesian_vector v{1.0, 2.0, 3.0};
REQUIRE(v[0] == 1.0);
REQUIRE(v[1] == 2.0);
REQUIRE(v[2] == 3.0);
@@ -135,7 +141,7 @@ TEST_CASE("cartesian_vector operations", "[vector]")
SECTION("convertible arguments")
{
cartesian_vector<double> v{1, 2, 3};
utility::cartesian_vector<double> v{1, 2, 3};
REQUIRE(v[0] == 1.0);
REQUIRE(v[1] == 2.0);
REQUIRE(v[2] == 3.0);
@@ -144,11 +150,11 @@ TEST_CASE("cartesian_vector operations", "[vector]")
SECTION("convertibility from another vector")
{
cartesian_vector v1{1, 2, 3};
utility::cartesian_vector v1{1, 2, 3};
SECTION("construction")
{
cartesian_vector<double> v2 = v1;
utility::cartesian_vector<double> v2 = v1;
REQUIRE(v2[0] == 1.0);
REQUIRE(v2[1] == 2.0);
REQUIRE(v2[2] == 3.0);
@@ -156,7 +162,7 @@ TEST_CASE("cartesian_vector operations", "[vector]")
SECTION("assignment")
{
cartesian_vector<double> v2{3.0, 2.0, 1.0};
utility::cartesian_vector<double> v2{3.0, 2.0, 1.0};
v2 = v1;
REQUIRE(v2[0] == 1.0);
REQUIRE(v2[1] == 2.0);
@@ -166,8 +172,8 @@ TEST_CASE("cartesian_vector operations", "[vector]")
SECTION("cartesian_vector compound assignment addition")
{
cartesian_vector v1{1.0, 2.0, 3.0};
cartesian_vector v2{4.0, 5.0, 6.0};
utility::cartesian_vector v1{1.0, 2.0, 3.0};
utility::cartesian_vector v2{4.0, 5.0, 6.0};
v1 += v2;
REQUIRE(v1[0] == 5.0);
REQUIRE(v1[1] == 7.0);
@@ -176,8 +182,8 @@ TEST_CASE("cartesian_vector operations", "[vector]")
SECTION("cartesian_vector compound assignment subtraction")
{
cartesian_vector v1{4.0, 5.0, 6.0};
cartesian_vector v2{1.0, 2.0, 3.0};
utility::cartesian_vector v1{4.0, 5.0, 6.0};
utility::cartesian_vector v2{1.0, 2.0, 3.0};
v1 -= v2;
REQUIRE(v1[0] == 3.0);
REQUIRE(v1[1] == 3.0);
@@ -186,7 +192,7 @@ TEST_CASE("cartesian_vector operations", "[vector]")
SECTION("cartesian_vector compound assignment scalar multiplication")
{
cartesian_vector v{1.0, 2.0, 3.0};
utility::cartesian_vector v{1.0, 2.0, 3.0};
v *= 2.0;
REQUIRE(v[0] == 2.0);
REQUIRE(v[1] == 4.0);
@@ -195,7 +201,7 @@ TEST_CASE("cartesian_vector operations", "[vector]")
SECTION("cartesian_vector compound assignment scalar division")
{
cartesian_vector v{2.0, 4.0, 6.0};
utility::cartesian_vector v{2.0, 4.0, 6.0};
v /= 2.0;
REQUIRE(v[0] == 1.0);
REQUIRE(v[1] == 2.0);
@@ -206,9 +212,9 @@ TEST_CASE("cartesian_vector operations", "[vector]")
{
SECTION("double + double")
{
cartesian_vector v1{1.0, 2.0, 3.0};
cartesian_vector v2{4.0, 5.0, 6.0};
cartesian_vector result = v1 + v2;
utility::cartesian_vector v1{1.0, 2.0, 3.0};
utility::cartesian_vector v2{4.0, 5.0, 6.0};
utility::cartesian_vector result = v1 + v2;
REQUIRE(result[0] == 5.0);
REQUIRE(result[1] == 7.0);
REQUIRE(result[2] == 9.0);
@@ -216,9 +222,9 @@ TEST_CASE("cartesian_vector operations", "[vector]")
SECTION("double + int")
{
cartesian_vector v1{1.0, 2.0, 3.0};
cartesian_vector v2{4, 5, 6};
cartesian_vector result = v1 + v2;
utility::cartesian_vector v1{1.0, 2.0, 3.0};
utility::cartesian_vector v2{4, 5, 6};
utility::cartesian_vector result = v1 + v2;
REQUIRE(result[0] == 5.0);
REQUIRE(result[1] == 7.0);
REQUIRE(result[2] == 9.0);
@@ -226,9 +232,9 @@ TEST_CASE("cartesian_vector operations", "[vector]")
SECTION("int + double")
{
cartesian_vector v1{1, 2, 3};
cartesian_vector v2{4.0, 5.0, 6.0};
cartesian_vector result = v1 + v2;
utility::cartesian_vector v1{1, 2, 3};
utility::cartesian_vector v2{4.0, 5.0, 6.0};
utility::cartesian_vector result = v1 + v2;
REQUIRE(result[0] == 5.0);
REQUIRE(result[1] == 7.0);
REQUIRE(result[2] == 9.0);
@@ -236,9 +242,9 @@ TEST_CASE("cartesian_vector operations", "[vector]")
SECTION("int + int")
{
cartesian_vector v1{1, 2, 3};
cartesian_vector v2{4, 5, 6};
cartesian_vector result = v1 + v2;
utility::cartesian_vector v1{1, 2, 3};
utility::cartesian_vector v2{4, 5, 6};
utility::cartesian_vector result = v1 + v2;
REQUIRE(result[0] == 5);
REQUIRE(result[1] == 7);
REQUIRE(result[2] == 9);
@@ -249,9 +255,9 @@ TEST_CASE("cartesian_vector operations", "[vector]")
{
SECTION("double - double")
{
cartesian_vector v1{4.0, 5.0, 6.0};
cartesian_vector v2{1.0, 2.0, 3.0};
cartesian_vector result = v1 - v2;
utility::cartesian_vector v1{4.0, 5.0, 6.0};
utility::cartesian_vector v2{1.0, 2.0, 3.0};
utility::cartesian_vector result = v1 - v2;
REQUIRE(result[0] == 3.0);
REQUIRE(result[1] == 3.0);
REQUIRE(result[2] == 3.0);
@@ -259,9 +265,9 @@ TEST_CASE("cartesian_vector operations", "[vector]")
SECTION("double - int")
{
cartesian_vector v1{4.0, 5.0, 6.0};
cartesian_vector v2{1, 2, 3};
cartesian_vector result = v1 - v2;
utility::cartesian_vector v1{4.0, 5.0, 6.0};
utility::cartesian_vector v2{1, 2, 3};
utility::cartesian_vector result = v1 - v2;
REQUIRE(result[0] == 3.0);
REQUIRE(result[1] == 3.0);
REQUIRE(result[2] == 3.0);
@@ -269,9 +275,9 @@ TEST_CASE("cartesian_vector operations", "[vector]")
SECTION("int - double")
{
cartesian_vector v1{4, 5, 6};
cartesian_vector v2{1.0, 2.0, 3.0};
cartesian_vector result = v1 - v2;
utility::cartesian_vector v1{4, 5, 6};
utility::cartesian_vector v2{1.0, 2.0, 3.0};
utility::cartesian_vector result = v1 - v2;
REQUIRE(result[0] == 3.0);
REQUIRE(result[1] == 3.0);
REQUIRE(result[2] == 3.0);
@@ -279,9 +285,9 @@ TEST_CASE("cartesian_vector operations", "[vector]")
SECTION("int - int")
{
cartesian_vector v1{4, 5, 6};
cartesian_vector v2{1, 2, 3};
cartesian_vector result = v1 - v2;
utility::cartesian_vector v1{4, 5, 6};
utility::cartesian_vector v2{1, 2, 3};
utility::cartesian_vector result = v1 - v2;
REQUIRE(result[0] == 3);
REQUIRE(result[1] == 3);
REQUIRE(result[2] == 3);
@@ -292,8 +298,8 @@ TEST_CASE("cartesian_vector operations", "[vector]")
{
SECTION("double * double")
{
cartesian_vector v{1.0, 2.0, 3.0};
cartesian_vector result = v * 2.0;
utility::cartesian_vector v{1.0, 2.0, 3.0};
utility::cartesian_vector result = v * 2.0;
REQUIRE(result[0] == 2.0);
REQUIRE(result[1] == 4.0);
REQUIRE(result[2] == 6.0);
@@ -301,8 +307,8 @@ TEST_CASE("cartesian_vector operations", "[vector]")
SECTION("double * int")
{
cartesian_vector v{1.0, 2.0, 3.0};
cartesian_vector result = v * 2;
utility::cartesian_vector v{1.0, 2.0, 3.0};
utility::cartesian_vector result = v * 2;
REQUIRE(result[0] == 2.0);
REQUIRE(result[1] == 4.0);
REQUIRE(result[2] == 6.0);
@@ -310,8 +316,8 @@ TEST_CASE("cartesian_vector operations", "[vector]")
SECTION("int * double")
{
cartesian_vector v{1, 2, 3};
cartesian_vector result = v * 2.0;
utility::cartesian_vector v{1, 2, 3};
utility::cartesian_vector result = v * 2.0;
REQUIRE(result[0] == 2.0);
REQUIRE(result[1] == 4.0);
REQUIRE(result[2] == 6.0);
@@ -319,8 +325,8 @@ TEST_CASE("cartesian_vector operations", "[vector]")
SECTION("int * int")
{
cartesian_vector v{1, 2, 3};
cartesian_vector result = v * 2;
utility::cartesian_vector v{1, 2, 3};
utility::cartesian_vector result = v * 2;
REQUIRE(result[0] == 2);
REQUIRE(result[1] == 4);
REQUIRE(result[2] == 6);
@@ -331,8 +337,8 @@ TEST_CASE("cartesian_vector operations", "[vector]")
{
SECTION("double / double")
{
cartesian_vector v{2.0, 4.0, 6.0};
cartesian_vector result = v / 2.0;
utility::cartesian_vector v{2.0, 4.0, 6.0};
utility::cartesian_vector result = v / 2.0;
REQUIRE(result[0] == 1.0);
REQUIRE(result[1] == 2.0);
REQUIRE(result[2] == 3.0);
@@ -340,8 +346,8 @@ TEST_CASE("cartesian_vector operations", "[vector]")
SECTION("double / int")
{
cartesian_vector v{2.0, 4.0, 6.0};
cartesian_vector result = v / 2;
utility::cartesian_vector v{2.0, 4.0, 6.0};
utility::cartesian_vector result = v / 2;
REQUIRE(result[0] == 1.0);
REQUIRE(result[1] == 2.0);
REQUIRE(result[2] == 3.0);
@@ -349,8 +355,8 @@ TEST_CASE("cartesian_vector operations", "[vector]")
SECTION("int / double")
{
cartesian_vector v{2, 4, 6};
cartesian_vector result = v / 2.0;
utility::cartesian_vector v{2, 4, 6};
utility::cartesian_vector result = v / 2.0;
REQUIRE(result[0] == 1.0);
REQUIRE(result[1] == 2.0);
REQUIRE(result[2] == 3.0);
@@ -358,8 +364,8 @@ TEST_CASE("cartesian_vector operations", "[vector]")
SECTION("int / int")
{
cartesian_vector v{2, 4, 6};
cartesian_vector result = v / 2;
utility::cartesian_vector v{2, 4, 6};
utility::cartesian_vector result = v / 2;
REQUIRE(result[0] == 1);
REQUIRE(result[1] == 2);
REQUIRE(result[2] == 3);
@@ -368,8 +374,8 @@ TEST_CASE("cartesian_vector operations", "[vector]")
SECTION("cartesian_vector norm")
{
cartesian_vector v1{3.0, 4.0, 0.0};
cartesian_vector v2{2.0, 3.0, 6.0};
utility::cartesian_vector v1{3.0, 4.0, 0.0};
utility::cartesian_vector v2{2.0, 3.0, 6.0};
REQUIRE(v1.norm() == 5.0);
REQUIRE(v2.norm() == 7.0);
REQUIRE(norm(v1) == 5.0);
@@ -378,8 +384,8 @@ TEST_CASE("cartesian_vector operations", "[vector]")
SECTION("cartesian_vector magnitude")
{
cartesian_vector v1{3.0, 4.0, 0.0};
cartesian_vector v2{2.0, 3.0, 6.0};
utility::cartesian_vector v1{3.0, 4.0, 0.0};
utility::cartesian_vector v2{2.0, 3.0, 6.0};
REQUIRE(v1.magnitude() == 5.0);
REQUIRE(v2.magnitude() == 7.0);
REQUIRE(magnitude(v1) == 5.0);
@@ -388,8 +394,8 @@ TEST_CASE("cartesian_vector operations", "[vector]")
SECTION("cartesian_vector unit vector")
{
cartesian_vector v{3.0, 4.0, 0.0};
cartesian_vector unit_v = v.unit();
utility::cartesian_vector v{3.0, 4.0, 0.0};
utility::cartesian_vector unit_v = v.unit();
REQUIRE_THAT(unit_v.norm(), WithinULP(1.0, 1));
REQUIRE_THAT(unit_v.magnitude(), WithinULP(1.0, 1));
REQUIRE_THAT(unit_v[0], WithinULP(3.0 / 5.0, 1));
@@ -401,11 +407,11 @@ TEST_CASE("cartesian_vector operations", "[vector]")
SECTION("cartesian_vector equality")
{
cartesian_vector v1{1.0, 2.0, 3.0};
cartesian_vector v2{1, 2, 3};
cartesian_vector v3{1.1, 2.0, 3.0};
cartesian_vector v4{1.0, 2.1, 3.0};
cartesian_vector v5{1.0, 2.0, 3.1};
utility::cartesian_vector v1{1.0, 2.0, 3.0};
utility::cartesian_vector v2{1, 2, 3};
utility::cartesian_vector v3{1.1, 2.0, 3.0};
utility::cartesian_vector v4{1.0, 2.1, 3.0};
utility::cartesian_vector v5{1.0, 2.0, 3.1};
REQUIRE(v1 == v2);
REQUIRE(v1 != v3);
REQUIRE(v1 != v4);
@@ -416,29 +422,29 @@ TEST_CASE("cartesian_vector operations", "[vector]")
{
SECTION("double * double")
{
cartesian_vector v1{1.0, 2.0, 3.0};
cartesian_vector v2{4.0, 5.0, 6.0};
utility::cartesian_vector v1{1.0, 2.0, 3.0};
utility::cartesian_vector v2{4.0, 5.0, 6.0};
REQUIRE(scalar_product(v1, v2) == 32.0);
}
SECTION("double * int")
{
cartesian_vector v1{1.0, 2.0, 3.0};
cartesian_vector v2{4, 5, 6};
utility::cartesian_vector v1{1.0, 2.0, 3.0};
utility::cartesian_vector v2{4, 5, 6};
REQUIRE(scalar_product(v1, v2) == 32.0);
}
SECTION("int * double")
{
cartesian_vector v1{1, 2, 3};
cartesian_vector v2{4.0, 5.0, 6.0};
utility::cartesian_vector v1{1, 2, 3};
utility::cartesian_vector v2{4.0, 5.0, 6.0};
REQUIRE(scalar_product(v1, v2) == 32.0);
}
SECTION("int * int")
{
cartesian_vector v1{1, 2, 3};
cartesian_vector v2{4, 5, 6};
utility::cartesian_vector v1{1, 2, 3};
utility::cartesian_vector v2{4, 5, 6};
REQUIRE(scalar_product(v1, v2) == 32);
}
}
@@ -447,9 +453,9 @@ TEST_CASE("cartesian_vector operations", "[vector]")
{
SECTION("double * double")
{
cartesian_vector v1{1.0, 2.0, 3.0};
cartesian_vector v2{4.0, 5.0, 6.0};
cartesian_vector result = vector_product(v1, v2);
utility::cartesian_vector v1{1.0, 2.0, 3.0};
utility::cartesian_vector v2{4.0, 5.0, 6.0};
utility::cartesian_vector result = vector_product(v1, v2);
REQUIRE(result[0] == -3.0);
REQUIRE(result[1] == 6.0);
REQUIRE(result[2] == -3.0);
@@ -457,9 +463,9 @@ TEST_CASE("cartesian_vector operations", "[vector]")
SECTION("double * int")
{
cartesian_vector v1{1.0, 2.0, 3.0};
cartesian_vector v2{4, 5, 6};
cartesian_vector result = vector_product(v1, v2);
utility::cartesian_vector v1{1.0, 2.0, 3.0};
utility::cartesian_vector v2{4, 5, 6};
utility::cartesian_vector result = vector_product(v1, v2);
REQUIRE(result[0] == -3.0);
REQUIRE(result[1] == 6.0);
REQUIRE(result[2] == -3.0);
@@ -467,9 +473,9 @@ TEST_CASE("cartesian_vector operations", "[vector]")
SECTION("int * double")
{
cartesian_vector v1{1, 2, 3};
cartesian_vector v2{4.0, 5.0, 6.0};
cartesian_vector result = vector_product(v1, v2);
utility::cartesian_vector v1{1, 2, 3};
utility::cartesian_vector v2{4.0, 5.0, 6.0};
utility::cartesian_vector result = vector_product(v1, v2);
REQUIRE(result[0] == -3.0);
REQUIRE(result[1] == 6.0);
REQUIRE(result[2] == -3.0);
@@ -477,9 +483,9 @@ TEST_CASE("cartesian_vector operations", "[vector]")
SECTION("int * int")
{
cartesian_vector v1{1, 2, 3};
cartesian_vector v2{4, 5, 6};
cartesian_vector result = vector_product(v1, v2);
utility::cartesian_vector v1{1, 2, 3};
utility::cartesian_vector v2{4, 5, 6};
utility::cartesian_vector result = vector_product(v1, v2);
REQUIRE(result[0] == -3);
REQUIRE(result[1] == 6);
REQUIRE(result[2] == -3);
@@ -487,8 +493,8 @@ TEST_CASE("cartesian_vector operations", "[vector]")
SECTION("two dimensions yields the perp-dot scalar")
{
cartesian_vector v1{1.0, 2.0};
cartesian_vector v2{4.0, 5.0};
utility::cartesian_vector v1{1.0, 2.0};
utility::cartesian_vector v2{4.0, 5.0};
auto result = vector_product(v1, v2); // perp-dot: v1[0]*v2[1] - v1[1]*v2[0]
static_assert(std::is_same_v<decltype(result), double>);
REQUIRE(result == -3.0);
@@ -502,7 +508,7 @@ TEST_CASE("cartesian_vector text output", "[vector][fmt][ostream]")
SECTION("integral representation")
{
cartesian_vector v{1, 2, 3};
utility::cartesian_vector v{1, 2, 3};
os << v;
SECTION("iostream") { CHECK(os.str() == "[1, 2, 3]"); }
@@ -511,7 +517,7 @@ TEST_CASE("cartesian_vector text output", "[vector][fmt][ostream]")
SECTION("floating-point representation")
{
cartesian_vector v{1.2, 2.3, 3.4};
utility::cartesian_vector v{1.2, 2.3, 3.4};
os << v;
SECTION("iostream") { CHECK(os.str() == "[1.2, 2.3, 3.4]"); }
@@ -526,23 +532,23 @@ TEST_CASE("cartesian_vector with a complex representation", "[vector][complex]")
SECTION("Hermitian magnitude is a real scalar")
{
// |(3+4i, 0, 0)| = |3+4i| = 5
cartesian_vector v{3. + 4.i, c{}, c{}};
utility::cartesian_vector v{3. + 4.i, c{}, c{}};
STATIC_CHECK(std::is_same_v<decltype(v.magnitude()), double>);
REQUIRE_THAT(v.magnitude(), WithinRel(5.0, 1e-12));
// |(1+i, 1+i, 1+i)| = sqrt(3 * 2) = sqrt(6)
cartesian_vector w{1. + 1.i, 1. + 1.i, 1. + 1.i};
utility::cartesian_vector w{1. + 1.i, 1. + 1.i, 1. + 1.i};
REQUIRE_THAT(w.magnitude(), WithinRel(std::sqrt(6.0), 1e-12));
}
SECTION("scalar_product is sesquilinear (conjugates the first argument)")
{
// <a, a> = |a|^2 is real and non-negative
cartesian_vector a{1. + 1.i, c{}, c{}};
utility::cartesian_vector a{1. + 1.i, c{}, c{}};
REQUIRE(scalar_product(a, a) == c{2.0, 0.0});
// <(1,0,0), (i,0,0)> = conj(1) * i = i
cartesian_vector e1{c{1.0}, c{}, c{}};
cartesian_vector ei{1.i, c{}, c{}};
utility::cartesian_vector e1{c{1.0}, c{}, c{}};
utility::cartesian_vector ei{1.i, c{}, c{}};
REQUIRE(scalar_product(e1, ei) == 1.i);
// anti-Hermitian symmetry: <b, a> = conj(<a, b>)
REQUIRE(scalar_product(ei, e1) == std::conj(scalar_product(e1, ei)));
@@ -550,8 +556,8 @@ TEST_CASE("cartesian_vector with a complex representation", "[vector][complex]")
SECTION("addition and scaling work componentwise")
{
cartesian_vector a{1. + 1.i, 2. + 0.i, 0. + 3.i};
cartesian_vector b{1. - 1.i, 0. + 2.i, 3. + 0.i};
utility::cartesian_vector a{1. + 1.i, 2. + 0.i, 0. + 3.i};
utility::cartesian_vector b{1. - 1.i, 0. + 2.i, 3. + 0.i};
auto s = a + b;
REQUIRE(s[0] == c{2.0, 0.0});
auto t = a * c{2.0, 0.0};
@@ -566,15 +572,15 @@ template<typename V>
concept projectable = requires(V v) { project(v); };
} // namespace
// embed only lifts 2D->3D and project only lowers 3D->2D (each defined for one source dimension)
static_assert(embeddable<cartesian_vector<double, 2>> && !embeddable<cartesian_vector<double, 3>>);
static_assert(projectable<cartesian_vector<double, 3>> && !projectable<cartesian_vector<double, 2>>);
static_assert(embeddable<utility::cartesian_vector<double, 2>> && !embeddable<utility::cartesian_vector<double, 3>>);
static_assert(projectable<utility::cartesian_vector<double, 3>> && !projectable<utility::cartesian_vector<double, 2>>);
TEST_CASE("cartesian_vector embed/project between 2D and 3D", "[vector]")
{
SECTION("embed zero-fills the new coordinate")
{
cartesian_vector v3 = embed(cartesian_vector{1.0, 2.0});
static_assert(std::is_same_v<decltype(v3), cartesian_vector<double, 3>>);
utility::cartesian_vector v3 = embed(utility::cartesian_vector{1.0, 2.0});
static_assert(std::is_same_v<decltype(v3), utility::cartesian_vector<double, 3>>);
REQUIRE(v3[0] == 1.0);
REQUIRE(v3[1] == 2.0);
REQUIRE(v3[2] == 0.0);
@@ -582,14 +588,14 @@ TEST_CASE("cartesian_vector embed/project between 2D and 3D", "[vector]")
SECTION("project drops the last coordinate")
{
cartesian_vector v2 = project(cartesian_vector{1.0, 2.0, 3.0});
static_assert(std::is_same_v<decltype(v2), cartesian_vector<double, 2>>);
utility::cartesian_vector v2 = project(utility::cartesian_vector{1.0, 2.0, 3.0});
static_assert(std::is_same_v<decltype(v2), utility::cartesian_vector<double, 2>>);
REQUIRE(v2[0] == 1.0);
REQUIRE(v2[1] == 2.0);
}
SECTION("project . embed is the identity on 2D")
{
REQUIRE(project(embed(cartesian_vector{1.0, 2.0})) == cartesian_vector{1.0, 2.0});
REQUIRE(project(embed(utility::cartesian_vector{1.0, 2.0})) == utility::cartesian_vector{1.0, 2.0});
}
}