|
Dedekind 0.0.0
A structuralist C++23 Module Library
|
Concept-side anchoring for the outer / dyadic / rank-1 product space (#535). More...
#include <concepts>#include <cstddef>#include <functional>import dedekind.geometry:linear_map;import dedekind.algebra;
Namespaces | |
| namespace | dedekind::geometry::detail_ops |
Concepts | |
| concept | dedekind::geometry::IsOuterProductSpace |
W carries the outer-product structure for factor spaces U and V: there is a dyad(u, v) → W constructor representing u ⊗ v in W. | |
Functions | |
| template<IsMatrixScalar F, std::size_t M, std::size_t N> requires dedekind::category::IsField<F, std::plus<F>, std::multiplies<F>> | |
| constexpr LinearMap< F, M, N > | dedekind::geometry::dyad (const Vector< F, M > &u, const Vector< F, N > &v) |
| template<IsMatrixScalar F, std::size_t M, std::size_t N> requires dedekind::category::IsField<F, std::plus<F>, std::multiplies<F>> | |
| constexpr LinearMap< F, M, N > | dedekind::geometry::operator* (const Vector< F, M > &u, const Covector< F, N > &phi) |
Concept-side anchoring for the outer / dyadic / rank-1 product space (#535).
@partition :outer_product
Before this partition the codebase had a single inhabitant of the outer product: the eager finite-dim free function geometry::outer(u, v) → LinearMap<F, M, N> in geometry:linear_map. No concept-level claim that the resulting carrier is the outer-product space U ⊗ V, no recognition that LinearMap inhabits such a space, and no static-assertable pin of the bilinearity / rank-1 entry laws.
This partition adds:
IsOuterProductSpace<W, U, V> — concept witnessing that W carries an outer-product structure for factor spaces U and V (universal-property shape: a dyad arrow U × V → W exists).dyad(u, v) — the outer-product constructor under the concept's expected name; today an alias to the existing geometry::outer(u, v) free function.Vector<double, 2> ⊗ Vector<double, 3> witness.The intensional / any-cardinality sibling dedekind::linear_algebra::OuterProduct<U, V> (slice e of #372, landing in #534) is the lazy face of the same mathematical object; a to_dense companion arrow at finite dimensions is tracked as a follow-up on #535 (it requires a partition that imports both geometry and linear_algebra:diagonal, which neither side currently does).
Mathematically, the outer product space U ⊗ V is the universal carrier of bilinear maps out of U × V: for any bilinear B: U × V → X there is a unique linear B̃: U ⊗ V → X with B(u, v) = B̃(u⊗. The v)IsOuterProductSpace concept here pins the construction arrow dyad: U × V → W and the bilinearity laws value-side; the universal property itself is asserted by documentation (the C++ type system can't witness universality directly without a category-theoretic encoding that the project does not lift to this layer today).
|
constexprexport |
dyad(u, v) is the outer-product constructor under the concept's expected name, gated to strict-field scalars (dedekind::category::IsField<F>). This deliberately tightens past IsMatrixScalar (which today admits double under the DEDEKIND_ENABLE_DOUBLE_REAL_PROXY policy gate) — double is not a strict field (rounding-non-associativity), so the new operator surface refuses it. Rational<long> / strict-field carriers will become admissible once Vector<F, N> / LinearMap<F, M, N> broaden their IsMatrixScalar gate to admit IsField carriers (tracked on #535).
Aliased: today the body delegates to the legacy geometry::outer(u, v), which carries the looser IsMatrixScalar constraint. At sites that pin IsField, the alias is strictly stronger; on the legacy path, geometry::outer remains available.
|
constexprexport |
Standard linear-algebra notation: a column vector multiplied by a row vector (covector) on the right gives the dyadic / outer product, a rank-1 LinearMap.
Vector<F, M> × Covector<F, N> → LinearMap<F, M, N>
This is the outer-product face of operator*; the dual inner-product face Covector × Vector → F lives in :inner_product. Same strict-IsField gate as dyad(u, v) above — the operator surface refuses non-field scalars (double in particular).