Rejected shapes

Translation units that must not compile. ctest builds each one and passes only when the diagnostic below appears, so the contracts cannot be dropped silently.

Sub-matrix view

The rows of a sub-matrix view, in red, are not one row length apart: the single-stride addressing cannot express it.

\[\begin{split} J = \begin{pmatrix} \textcolor{red}{j_{00}} & \textcolor{red}{j_{01}} & j_{02} & j_{03} \\ \textcolor{red}{j_{10}} & \textcolor{red}{j_{11}} & j_{12} & j_{13} \\ j_{20} & j_{21} & j_{22} & j_{23} \\ j_{30} & j_{31} & j_{32} & j_{33} \end{pmatrix}, \quad \text{rows of the block 4 elements apart, columns 1} \end{split}\]
// a 2 x 2 block of a 4 x 4 matrix: its rows are 4 elements apart, its columns 1
auto S = J.submatrix_view<0, 0, 2, 2>();

return tdls::factorize(S, piv) ? 0 : 1;

Diagnostic:

tdls adaptors: row-strided matrix views (sub-matrix views) cannot be expressed by the single-stride addressing of the TiledLUpp solvers

Derivative view

A derivative block, in red, mapped inside a larger jacobian: the same row stride problem.

\[\begin{split} J = \left(\begin{array}{c|c} \textcolor{red}{\partial f / \partial x} & \ast \\ \hline \ast & \ast \end{array}\right), \quad f, x \in \mathbb{R}^2, \quad J \in \mathbb{R}^{4 \times 4} \end{split}\]
// a 2 x 2 derivative block inside a 4 x 4 jacobian: rows 4 elements apart
using vector2 = tfel::math::tvector<2, double>;
auto D        = tfel::math::map_derivative<0, 0, vector2, vector2>(J);

return tdls::factorize(D, piv) ? 0 : 1;

Diagnostic:

tdls adaptors: row-strided matrix views (sub-matrix views) cannot be expressed by the single-stride addressing of the TiledLUpp solvers

Gather view

One pointer per element: no data pointer, no stride.

\[\begin{split} G = \begin{pmatrix} p_{00} & p_{01} & p_{02} & p_{03} \\ p_{10} & p_{11} & p_{12} & p_{13} \\ p_{20} & p_{21} & p_{22} & p_{23} \\ p_{30} & p_{31} & p_{32} & p_{33} \end{pmatrix}, \quad p_{ij} \text{ a pointer to the element} \end{split}\]
// one pointer per element: the view has no data() and no stride
auto G = tfel::math::map<tfel::math::tmatrix<4, 4, double>>(pointers);

return tdls::factorize(G, piv) ? 0 : 1;

Diagnostic:

tdls adaptors: A must be a dense object exposing data() and an indexing_policy type (a gather view holding one pointer per element is not one)

Column-major configuration

TFEL stores matrices row-major.

\[\begin{split} A = \begin{pmatrix} a_{00} & a_{01} \\ a_{10} & a_{11} \end{pmatrix} \ \text{is stored as}\ (a_{00}, a_{01}, a_{10}, a_{11}), \ \text{not as}\ (a_{00}, a_{10}, a_{01}, a_{11}) \end{split}\]
// TFEL stores matrices row-major: the layout knob cannot say otherwise here
constexpr auto colmajor = tdls::TiledLUppConfig<double>{.layout = tdls::MatrixLayout::ColMajor};

return tdls::factorize<colmajor>(A, piv) ? 0 : 1;

Diagnostic:

tdls adaptors: dense objects are addressed row-major, the TFEL convention; a column-major configuration cannot be used through the adaptors

Const matrix

The factorizing entry points write their matrix argument.

// factorize writes the factors into its matrix argument
const tfel::math::tmatrix<4, 4, double> A{};

return tdls::factorize(A, piv) ? 0 : 1;

Diagnostic:

tdls adaptors: A must not be const here (factorize writes it)

Extent mismatch

A right-hand side whose compile-time extent differs from the dimension.

\[ A \in \mathbb{R}^{4 \times 4}, \quad b \in \mathbb{R}^{3} \]
// a 3-vector against a 4 x 4 matrix: both extents are known at compile time
tfel::math::tvector<3, double> b{}, x;

return tdls::solve(A, piv, b, x) ? 0 : 1;

Diagnostic:

tdls adaptors: vector extent does not match the system dimension