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