feat(representation): add embed/project conversions between 2D and 3D cartesian types

`embed` is the canonical inclusion of the plane into space and `project` the
canonical projection back, for both vectors and tensors:
- vector: embed (x,y) -> (x,y,0); project (x,y,z) -> (x,y)
- tensor: embed the 2x2 into the top-left block of a zeroed 3x3; project keeps
  that top-left 2x2 block

They are explicit named free functions (no implicit cross-dimension conversion),
each defined for a single source dimension (embed: 2D only; project: 3D only).
The zero fill is the additive identity derived from a component (`x - x`), so no
value-initialization of the element type is required.

Also route `tensor_product` through `cartesian_tensor_from` instead of a
default-constructed result, matching the other constructing operations (the
element type need not be default-constructible).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Mateusz Pusz
2026-06-26 22:16:14 +02:00
parent f84e10aef2
commit 805bb969d2
4 changed files with 112 additions and 4 deletions
+35
View File
@@ -558,3 +558,38 @@ TEST_CASE("cartesian_vector with a complex representation", "[vector][complex]")
REQUIRE(t[0] == c{2.0, 2.0});
}
}
namespace {
template<typename V>
concept embeddable = requires(V v) { embed(v); };
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>>);
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>>);
REQUIRE(v3[0] == 1.0);
REQUIRE(v3[1] == 2.0);
REQUIRE(v3[2] == 0.0);
}
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>>);
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});
}
}