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>
`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>
`cartesian_vector<T, N>` and `cartesian_tensor<T, N>` now take a compile-time
dimension N in {2, 3} (default 3), so a planar model pays nothing for an unused
third component. Operations close at a matching N: tensor_product of two
N-vectors yields an N x N tensor, inner_product(N x N tensor, N-vector) yields
an N-vector, and mixing dimensions is ill-formed. vector_product is the 3D axial
vector for N=3 and the 2D perp-dot (pseudo)scalar for N=2. N is deduced from the
argument count (2/3 components -> 2D/3D vector; 4/9 -> 2x2/3x3 tensor).
Also:
- element conversions build via member initializer lists (no default-construct-
then-assign), and every constructing tensor operation builds through a new
cartesian_tensor_from helper instead of a default-constructed result, so the
element type need not be default-constructible
- a compile-time `extent` query (per-axis count, std::extent semantics) on both,
usable as both `x.extent` and `x.extent()`
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The converting and variadic constructors (and converting assignment) keyed their implicit/explicit
decision on `std::convertible_to` alone, which let a truncating floating-point -> integer element
conversion (e.g. `cartesian_vector<double>` -> `cartesian_vector<int>`) convert implicitly -
inconsistent with a quantity's rep, where the conversion must also be non-truncating.
Add a `detail::ImplicitlyConvertibleScalar` guard that keeps `std::convertible_to` (an element type
need not be fundamental and may define its own implicit-conversion rules) and defers the
non-truncating decision to the `implicitly_scalable` customization point, passing identical `one`
units so it degenerates to the rep-only decision. Deferring to the CPO rather than hardcoding its
`treat_as_floating_point`-based default keeps element conversions consistent with a user's
`implicitly_scalable` specialization. An FP target or a widening stays implicit; an FP -> integer
element conversion becomes explicit (still constructible). Converting assignment is restricted to the
implicit case for the same reason.
Adds static_assert coverage to the cartesian vector/tensor runtime tests.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Refine the requires-expressions of the `cartesian_vector` operators to
constrain on `const`-qualified operands, matching the fact that the
operators take their arguments by `const` reference. A type whose
`operator+` (etc.) is not const-correct would previously have wrongly
satisfied the constraint.
The compound-assignment constraints are ref-qualified as well (mutable
lhs, const rhs) while keeping the `-> std::same_as<T&>` return-type check.
Also strengthen the unit-vector test to assert the resulting component
values (not just that the norm is 1) and to exercise the free
`unit_vector()` function.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>