|
TDLS 0.4.0
Tiny Device-callable Linear Solvers
|
Arrowhead solver with a compile-time shape. More...
#include <solver_static.hpp>
Public Types | |
| using | storage_map = ArrowheadStorageMap<Config.storage, Config.coupling, Config.layout> |
| Index of every entry of the matrix in its storage. | |
| using | StreamedBlock = detail::ArrowheadStreamedBlock<T, S, B, col, diag> |
| Block k of a streamed solve (detail::ArrowheadStreamedBlock): the working arrays of the solver, filled by the provider through the accessors. The type depends on T, the sizes, the layout and the coupling only, so that the solvers of two configurations that differ otherwise hand their providers the same type. | |
| using | RecomputedBlock = detail::ArrowheadRecomputedBlock<T, S, B, col, diag> |
| Block k of a recomputed solve (detail::ArrowheadRecomputedBlock): a StreamedBlock and the recovery flag. | |
| using | StreamedOutcome = detail::ArrowheadStreamedOutcome |
| Outcome of solve_inplace_streamed_or_tangent (detail::ArrowheadStreamedOutcome). | |
| using | RecomputedOutcome = detail::ArrowheadRecomputedOutcome |
| Outcome of solve_inplace_recomputed and solve_inplace_recomputed_or_tangent (detail::ArrowheadRecomputedOutcome). | |
Static Public Member Functions | |
| template<bool internal_rhs, bool internal_work, bool internal_matrix, int A_static_stride = dynamic_stride, int work_static_stride = dynamic_stride, int rhs_static_stride = dynamic_stride, typename Provider > | |
| static TDLS_HOST_DEVICE constexpr bool | solve_inplace_streamed (Provider &&provider, T *TDLS_RESTRICT A, const int A_stride, T *TDLS_RESTRICT work, const int work_stride, T *TDLS_RESTRICT y, const int rhs_stride, int &refused_count) noexcept |
| Solves A x = y in place, the blocks streamed: provider(k, blk) fills block k (StreamedBlock) when the solver needs it, k = 0, 1, ... in order, and the solver condenses it at once. The caller writes beforehand only the border: A_bb in A and the border rows of y. An accepted block leaves its recovery data in its storage; a refused one is stored as given for the second pass (the provider is called exactly once per block): the arithmetic, the pivot check and the second pass are those of solve_inplace, bit for bit under the same contraction of multiply-adds (see the file documentation). | |
| template<int ntan, bool internal_rhs, bool internal_work, bool internal_matrix, int A_static_stride = dynamic_stride, int work_static_stride = dynamic_stride, int rhs_static_stride = dynamic_stride, int x_static_stride = dynamic_stride, typename Provider , typename Converged , bool outlined = false> | |
| static TDLS_HOST_DEVICE constexpr StreamedOutcome | solve_inplace_streamed_or_tangent (Provider &&provider, Converged &&converged, T *TDLS_RESTRICT A, const int A_stride, T *TDLS_RESTRICT work, const int work_stride, T *TDLS_RESTRICT y, const int rhs_stride, const int col0, T *TDLS_RESTRICT x, const int x_stride, const std::size_t xcol_stride, int &refused_count) noexcept |
| One streamed pass of a Newton iteration: the blocks condensed as solve_inplace_streamed does, then converged() is called (the provider may compute the residual meanwhile). When it returns false, the pass ends as solve_inplace_streamed (y holds the correction). When it returns true, the correction is not computed: the border system condensed by the pass gives instead columns col0 .. col0 + ntan - 1 of the border block of A^-1 in x (the consistent tangent of a behaviour loaded through the border), refused blocks included (work then holds multirhs_workspace_size<ntan> entries). The provider is called exactly once per block, in order, and converged() once, after the last block. Bit for bit the results of solve_inplace_streamed, and those of solve_border_canonical_multirhs_streamed under the default rhs_pass_width (within rounding errors under another, see ArrowheadLUppConfig::rhs_pass_width). | |
| template<int nrhs, bool internal_rhs, bool internal_work, bool internal_matrix, int A_static_stride = dynamic_stride, int work_static_stride = dynamic_stride, int rhs_static_stride = dynamic_stride, typename Provider > | |
| static TDLS_HOST_DEVICE constexpr bool | solve_border_canonical_multirhs_streamed (Provider &&provider, T *TDLS_RESTRICT A, const int A_stride, T *TDLS_RESTRICT work, const int work_stride, const int col0, T *TDLS_RESTRICT x, const int rhs_stride, const std::size_t xcol_stride, int &refused_count) noexcept |
| solve_border_canonical_multirhs with the blocks streamed (see solve_inplace_streamed; blk.y is not read). | |
| template<bool internal_rhs, bool internal_work, bool internal_matrix, int A_static_stride = dynamic_stride, int work_static_stride = dynamic_stride, int rhs_static_stride = dynamic_stride> | |
| static TDLS_HOST_DEVICE constexpr bool | solve_inplace (T *TDLS_RESTRICT A, const int A_stride, T *TDLS_RESTRICT work, const int work_stride, T *TDLS_RESTRICT y, const int rhs_stride, int &refused_count) noexcept |
| Solves A x = y in place, counting the refused blocks. | |
| template<bool internal_rhs, bool internal_work, bool internal_matrix, int A_static_stride = dynamic_stride, int work_static_stride = dynamic_stride, int rhs_static_stride = dynamic_stride> | |
| static TDLS_HOST_DEVICE constexpr bool | solve_inplace (T *TDLS_RESTRICT A, const int A_stride, T *TDLS_RESTRICT work, const int work_stride, T *TDLS_RESTRICT y, const int rhs_stride) noexcept |
| Solves A x = y in place. | |
| template<bool internal_rhs, bool internal_work, bool internal_matrix, int A_static_stride = dynamic_stride, int work_static_stride = dynamic_stride, int rhs_static_stride = dynamic_stride> | |
| static TDLS_HOST_DEVICE constexpr bool | solve (T *TDLS_RESTRICT A, const int A_stride, T *TDLS_RESTRICT work, const int work_stride, const T *TDLS_RESTRICT b, T *TDLS_RESTRICT x, const int rhs_stride, int &refused_count) noexcept |
| Solves A x = b, b left untouched, counting the refused blocks: b is copied into x, then solved in place. | |
| template<bool internal_rhs, bool internal_work, bool internal_matrix, int A_static_stride = dynamic_stride, int work_static_stride = dynamic_stride, int rhs_static_stride = dynamic_stride> | |
| static TDLS_HOST_DEVICE constexpr bool | solve (T *TDLS_RESTRICT A, const int A_stride, T *TDLS_RESTRICT work, const int work_stride, const T *TDLS_RESTRICT b, T *TDLS_RESTRICT x, const int rhs_stride) noexcept |
| Solves A x = b, b left untouched. | |
| template<int nrhs, bool internal_rhs, bool internal_work, bool internal_matrix, int A_static_stride = dynamic_stride, int work_static_stride = dynamic_stride, int rhs_static_stride = dynamic_stride> | |
| static TDLS_HOST_DEVICE constexpr bool | solve_inplace_multirhs (T *TDLS_RESTRICT A, const int A_stride, T *TDLS_RESTRICT work, const int work_stride, T *TDLS_RESTRICT y, const int rhs_stride, const std::size_t xcol_stride, int &refused_count) noexcept |
| Solves A X = Y in place for nrhs right-hand sides, counting the refused blocks. The right-hand sides ride along the condensation, which runs once: each block solves [A_kb | Y_k] in passes of rhs_pass_width columns, the border system nrhs columns. Column m comes out bitwise identical to solve_inplace on it alone under the default rhs_pass_width, and within rounding errors under another (see ArrowheadLUppConfig::rhs_pass_width). | |
| template<int nrhs, bool internal_rhs, bool internal_work, bool internal_matrix, int A_static_stride = dynamic_stride, int work_static_stride = dynamic_stride, int rhs_static_stride = dynamic_stride> | |
| static TDLS_HOST_DEVICE constexpr bool | solve_inplace_multirhs (T *TDLS_RESTRICT A, const int A_stride, T *TDLS_RESTRICT work, const int work_stride, T *TDLS_RESTRICT y, const int rhs_stride, const std::size_t xcol_stride) noexcept |
| Solves A X = Y in place for nrhs right-hand sides. | |
| template<int nrhs, bool internal_rhs, bool internal_work, bool internal_matrix, int A_static_stride = dynamic_stride, int work_static_stride = dynamic_stride, int rhs_static_stride = dynamic_stride> | |
| static TDLS_HOST_DEVICE constexpr bool | solve_multirhs (T *TDLS_RESTRICT A, const int A_stride, T *TDLS_RESTRICT work, const int work_stride, const T *TDLS_RESTRICT b, T *TDLS_RESTRICT x, const int rhs_stride, const std::size_t xcol_stride, int &refused_count) noexcept |
| Solves A X = B for nrhs right-hand sides, B left untouched, counting the refused blocks: B is copied into X, then solved in place. | |
| template<int nrhs, bool internal_rhs, bool internal_work, bool internal_matrix, int A_static_stride = dynamic_stride, int work_static_stride = dynamic_stride, int rhs_static_stride = dynamic_stride> | |
| static TDLS_HOST_DEVICE constexpr bool | solve_multirhs (T *TDLS_RESTRICT A, const int A_stride, T *TDLS_RESTRICT work, const int work_stride, const T *TDLS_RESTRICT b, T *TDLS_RESTRICT x, const int rhs_stride, const std::size_t xcol_stride) noexcept |
| Solves A X = B for nrhs right-hand sides, B left untouched. | |
| template<int nrhs, bool internal_rhs, bool internal_work, bool internal_matrix, int A_static_stride = dynamic_stride, int work_static_stride = dynamic_stride, int rhs_static_stride = dynamic_stride> | |
| static TDLS_HOST_DEVICE constexpr bool | solve_border_canonical_multirhs (T *TDLS_RESTRICT A, const int A_stride, T *TDLS_RESTRICT work, const int work_stride, const int col0, T *TDLS_RESTRICT x, const int rhs_stride, const std::size_t xcol_stride, int &refused_count) noexcept |
| Columns col0 .. col0 + nrhs - 1 of the border block of A^-1, the inverse of the Schur complement of the border (col0 + nrhs <= border), counting the refused blocks: rows 0 .. border - 1 of the solutions of A X = [e_col0 .. e_col0+nrhs-1]. These right-hand sides vanish on the rows of the blocks: the blocks are condensed without right-hand side, and nothing is recovered, so no recovery data is stored. The cost is the condensation of the matrix and nrhs substitutions of the border system: the tangent operator of a behaviour whose loading enters the border equations only. Each column equals the border rows of solve_inplace on the unit column; a zero may differ in sign, the blocks contributing exact zeros where solve_inplace subtracts zero products. Under another rhs_pass_width than the default, the two agree within rounding errors (see ArrowheadLUppConfig::rhs_pass_width). A is only read, except the coupled border rows under schur_in_place, which receive the Schur complement of the accepted blocks: otherwise the same A serves the next columns. | |
| template<int nrhs, bool internal_rhs, bool internal_work, bool internal_matrix, int A_static_stride = dynamic_stride, int work_static_stride = dynamic_stride, int rhs_static_stride = dynamic_stride> | |
| static TDLS_HOST_DEVICE constexpr bool | solve_border_canonical_multirhs (T *TDLS_RESTRICT A, const int A_stride, T *TDLS_RESTRICT work, const int work_stride, const int col0, T *TDLS_RESTRICT x, const int rhs_stride, const std::size_t xcol_stride) noexcept |
| Columns col0 .. col0 + nrhs - 1 of the border block of A^-1 (col0 + nrhs <= border). | |
| template<int capacity, bool internal_rhs, bool internal_work, bool internal_matrix, int Abb_static_stride = dynamic_stride, int work_static_stride = dynamic_stride, int rhs_static_stride = dynamic_stride, typename Provider > | |
| static TDLS_HOST_DEVICE constexpr RecomputedOutcome | solve_inplace_recomputed (Provider &&provider, const T *TDLS_RESTRICT Abb, const int Abb_stride, T *TDLS_RESTRICT work, const int work_stride, T *TDLS_RESTRICT y, const int rhs_stride, int &refused_count) noexcept |
| Solves A x = y in place, the blocks recomputed: provider(k,
blk) fills block k (RecomputedBlock) once while the solver condenses it, k = 0, 1, ... in order, and once more, blk.recovery set, while it recovers the unknowns of the block, in decreasing k. Nothing of an accepted block is stored: the solver factors the block again and solves x_k = D_k^-1 (y_k - A_kb x_b). The matrix is never stored, and the workspace holds only the refused blocks, at most capacity of them, which the second pass eliminates as solve_inplace_streamed does. The provider must give the same entries every time it fills the same block, y_k included. The caller gives the border: A_bb, entry (r, c) at (r * border + c) * Abb_stride, or (c * border + r) * Abb_stride under the column-major layout, and the border rows of y. Nothing is written to y until the solution: y is untouched when the matrix is singular, or when more than capacity blocks are refused (deferred), so that the caller can solve that system with solve_inplace_streamed. A deferred solve stops at the refused block beyond the capacity: the provider is not called for the later blocks. | |
| template<int ntan, int capacity, bool internal_rhs, bool internal_work, bool internal_matrix, int Abb_static_stride = dynamic_stride, int work_static_stride = dynamic_stride, int rhs_static_stride = dynamic_stride, int x_static_stride = dynamic_stride, typename Provider , typename Converged > | |
| static TDLS_HOST_DEVICE constexpr RecomputedOutcome | solve_inplace_recomputed_or_tangent (Provider &&provider, Converged &&converged, const T *TDLS_RESTRICT Abb, const int Abb_stride, T *TDLS_RESTRICT work, const int work_stride, T *TDLS_RESTRICT y, const int rhs_stride, const int col0, T *TDLS_RESTRICT x, const int x_stride, const std::size_t xcol_stride, int &refused_count) noexcept |
| One recomputed pass of a Newton iteration: the blocks condensed as solve_inplace_recomputed condenses them, then converged() is called. When it returns false, the pass ends as solve_inplace_recomputed: the provider is asked for every accepted block once more and y holds the correction. When it returns true, the border system condensed by the pass gives instead columns col0 .. col0 + ntan - 1 of the border block of A^-1 in x (the consistent tangent of a behaviour loaded through the border), refused blocks included, and y is untouched: the provider is then called once per block. The tangent is that of solve_inplace_streamed_or_tangent bit for bit (under the same contraction of multiply-adds). When more than capacity blocks are refused, the pass stops there, deferred, before converged() is called; y and x are untouched. | |
Static Public Attributes | |
| static constexpr ArrowheadShape | shape = Shape |
| Shape of the matrix. | |
| static constexpr int | dimension = Shape.n() |
| Dimension of the matrix, border + block * blocks. | |
| static constexpr int | storage_size = storage_map::size(Shape) |
| Number of stored entries of the matrix. | |
| template<int nrhs> | |
| static constexpr int | multirhs_workspace_size |
| static constexpr int | workspace_size = multirhs_workspace_size<1> |
| static constexpr int | pass_width = rhs_pass == 0 ? B + 1 : rhs_pass |
| Columns [A_kb | y_k] solved per pass, one right-hand side. | |
| template<int capacity, int nrhs = 1> | |
| static constexpr int | recomputed_workspace_size = recomputed_size<capacity, nrhs>() |
| Entries of the workspace of solve_inplace_recomputed with a store of capacity refused blocks, and of solve_inplace_recomputed_or_tangent with nrhs tangent columns: the front of the second pass, the refused blocks in the Packed storage of a matrix of capacity blocks and their right-hand sides; none for a capacity of 0. | |
Friends | |
| template<typename U , ArrowheadShape OtherShape, ArrowheadLUppConfig< U > OtherConfig> | |
| struct | ArrowheadLUppSolverStatic |
Arrowhead solver with a compile-time shape.
| T | scalar type (float, double or long double) |
| Shape | shape of the matrix (valid for the storage and the coupling of Config) |
| Config | configuration (see ArrowheadLUppConfig) |
|
inlinestaticnodiscardconstexprnoexcept |
Solves A x = b, b left untouched.
| internal_rhs | b and x are caller-local arrays (stride ignored) |
| internal_work | work is a caller-local array (stride ignored) |
| internal_matrix | A is a caller-local array (stride ignored) |
| A_static_stride | compile-time stride of A, used instead of A_stride; tdls::dynamic_stride (the default) reads A_stride |
| work_static_stride | compile-time stride of work, used instead of work_stride; tdls::dynamic_stride (the default) reads work_stride |
| rhs_static_stride | compile-time stride of b and x, used instead of rhs_stride; tdls::dynamic_stride (the default) reads rhs_stride |
| [in,out] | A | matrix in its storage; recovery data on exit |
| [in] | A_stride | element stride of A |
| [out] | work | workspace of workspace_size entries |
| [in] | work_stride | element stride of work |
| [in] | b | right-hand side |
| [out] | x | solution |
| [in] | rhs_stride | element stride of b and x |
|
inlinestaticnodiscardconstexprnoexcept |
Solves A x = b, b left untouched, counting the refused blocks: b is copied into x, then solved in place.
| internal_rhs | b and x are caller-local arrays (stride ignored) |
| internal_work | work is a caller-local array (stride ignored) |
| internal_matrix | A is a caller-local array (stride ignored) |
| A_static_stride | compile-time stride of A, used instead of A_stride; tdls::dynamic_stride (the default) reads A_stride |
| work_static_stride | compile-time stride of work, used instead of work_stride; tdls::dynamic_stride (the default) reads work_stride |
| rhs_static_stride | compile-time stride of b and x, used instead of rhs_stride; tdls::dynamic_stride (the default) reads rhs_stride |
| [in,out] | A | matrix in its storage; recovery data on exit |
| [in] | A_stride | element stride of A |
| [out] | work | workspace of workspace_size entries |
| [in] | work_stride | element stride of work |
| [in] | b | right-hand side |
| [out] | x | solution |
| [in] | rhs_stride | element stride of b and x |
| [out] | refused_count | number of blocks refused by the pivot check |
|
inlinestaticnodiscardconstexprnoexcept |
Columns col0 .. col0 + nrhs - 1 of the border block of A^-1 (col0 + nrhs <= border).
| nrhs | number of unit columns, in [1, border] |
| internal_rhs | x is a caller-local array, column m from m * border (strides ignored) |
| internal_work | work is a caller-local array (stride ignored) |
| internal_matrix | A is a caller-local array (stride ignored) |
| A_static_stride | compile-time stride of A, used instead of A_stride; tdls::dynamic_stride (the default) reads A_stride |
| work_static_stride | compile-time stride of work, used instead of work_stride; tdls::dynamic_stride (the default) reads work_stride |
| rhs_static_stride | compile-time stride of x, used instead of rhs_stride; tdls::dynamic_stride (the default) reads rhs_stride |
| [in,out] | A | matrix in its storage; unchanged on exit, but under schur_in_place |
| [in] | A_stride | element stride of A |
| [out] | work | workspace of multirhs_workspace_size<nrhs> entries |
| [in] | work_stride | element stride of work |
| [in] | col0 | first unit column, col0 + nrhs <= border |
| [out] | x | the border rows, border entries per column |
| [in] | rhs_stride | element stride of x |
| [in] | xcol_stride | element stride between columns of x |
|
inlinestaticnodiscardconstexprnoexcept |
Columns col0 .. col0 + nrhs - 1 of the border block of A^-1, the inverse of the Schur complement of the border (col0 + nrhs <= border), counting the refused blocks: rows 0 .. border - 1 of the solutions of A X = [e_col0 .. e_col0+nrhs-1]. These right-hand sides vanish on the rows of the blocks: the blocks are condensed without right-hand side, and nothing is recovered, so no recovery data is stored. The cost is the condensation of the matrix and nrhs substitutions of the border system: the tangent operator of a behaviour whose loading enters the border equations only. Each column equals the border rows of solve_inplace on the unit column; a zero may differ in sign, the blocks contributing exact zeros where solve_inplace subtracts zero products. Under another rhs_pass_width than the default, the two agree within rounding errors (see ArrowheadLUppConfig::rhs_pass_width). A is only read, except the coupled border rows under schur_in_place, which receive the Schur complement of the accepted blocks: otherwise the same A serves the next columns.
| nrhs | number of unit columns, in [1, border] |
| internal_rhs | x is a caller-local array, column m from m * border (strides ignored) |
| internal_work | work is a caller-local array (stride ignored) |
| internal_matrix | A is a caller-local array (stride ignored) |
| A_static_stride | compile-time stride of A, used instead of A_stride; tdls::dynamic_stride (the default) reads A_stride |
| work_static_stride | compile-time stride of work, used instead of work_stride; tdls::dynamic_stride (the default) reads work_stride |
| rhs_static_stride | compile-time stride of x, used instead of rhs_stride; tdls::dynamic_stride (the default) reads rhs_stride |
| [in,out] | A | matrix in its storage; unchanged on exit, but under schur_in_place |
| [in] | A_stride | element stride of A |
| [out] | work | workspace of multirhs_workspace_size<nrhs> entries |
| [in] | work_stride | element stride of work |
| [in] | col0 | first unit column, col0 + nrhs <= border |
| [out] | x | the border rows, border entries per column |
| [in] | rhs_stride | element stride of x |
| [in] | xcol_stride | element stride between columns of x |
| [out] | refused_count | number of blocks refused by the pivot check |
|
inlinestaticnodiscardconstexprnoexcept |
solve_border_canonical_multirhs with the blocks streamed (see solve_inplace_streamed; blk.y is not read).
| nrhs | number of unit columns, in [1, border] |
| internal_rhs | x is a caller-local array, column m from m * border (strides ignored) |
| internal_work | work is a caller-local array (stride ignored) |
| internal_matrix | A is a caller-local array (stride ignored) |
| A_static_stride | compile-time stride of A, used instead of A_stride; tdls::dynamic_stride (the default) reads A_stride |
| work_static_stride | compile-time stride of work, used instead of work_stride; tdls::dynamic_stride (the default) reads work_stride |
| rhs_static_stride | compile-time stride of x, used instead of rhs_stride; tdls::dynamic_stride (the default) reads rhs_stride |
| Provider | callable (int k, StreamedBlock& blk) |
| [in] | provider | the source of the blocks |
| [in,out] | A | storage: A_bb on entry; on exit the refused blocks as given, the accepted ones not written (see solve_border_canonical_multirhs) |
| [in] | A_stride | element stride of A |
| [out] | work | workspace of multirhs_workspace_size<nrhs> entries |
| [in] | work_stride | element stride of work |
| [in] | col0 | first unit column, col0 + nrhs <= border |
| [out] | x | the border rows, border entries per column |
| [in] | rhs_stride | element stride of x |
| [in] | xcol_stride | element stride between columns of x |
| [out] | refused_count | number of refused blocks |
|
inlinestaticnodiscardconstexprnoexcept |
Solves A x = y in place.
| internal_rhs | y is a caller-local array (stride ignored) |
| internal_work | work is a caller-local array (stride ignored) |
| internal_matrix | A is a caller-local array (stride ignored) |
| A_static_stride | compile-time stride of A, used instead of A_stride; tdls::dynamic_stride (the default) reads A_stride |
| work_static_stride | compile-time stride of work, used instead of work_stride; tdls::dynamic_stride (the default) reads work_stride |
| rhs_static_stride | compile-time stride of y, used instead of rhs_stride; tdls::dynamic_stride (the default) reads rhs_stride |
| [in,out] | A | matrix in its storage; recovery data on exit |
| [in] | A_stride | element stride of A |
| [out] | work | workspace of workspace_size entries |
| [in] | work_stride | element stride of work |
| [in,out] | y | right-hand side on entry, solution on exit |
| [in] | rhs_stride | element stride of y |
|
inlinestaticnodiscardconstexprnoexcept |
Solves A x = y in place, counting the refused blocks.
| internal_rhs | y is a caller-local array (stride ignored) |
| internal_work | work is a caller-local array (stride ignored) |
| internal_matrix | A is a caller-local array (stride ignored) |
| A_static_stride | compile-time stride of A, used instead of A_stride; tdls::dynamic_stride (the default) reads A_stride |
| work_static_stride | compile-time stride of work, used instead of work_stride; tdls::dynamic_stride (the default) reads work_stride |
| rhs_static_stride | compile-time stride of y, used instead of rhs_stride; tdls::dynamic_stride (the default) reads rhs_stride |
| [in,out] | A | matrix in its storage (pattern entries only); recovery data on exit |
| [in] | A_stride | element stride of A |
| [out] | work | workspace of workspace_size entries, touched only when blocks are refused |
| [in] | work_stride | element stride of work |
| [in,out] | y | right-hand side on entry, solution on exit |
| [in] | rhs_stride | element stride of y |
| [out] | refused_count | number of blocks refused by the pivot check, eliminated by the second pass |
|
inlinestaticnodiscardconstexprnoexcept |
Solves A X = Y in place for nrhs right-hand sides.
| nrhs | number of right-hand sides, >= 1 |
| internal_rhs | y is a caller-local array, column m from m * dimension (strides ignored) |
| internal_work | work is a caller-local array (stride ignored) |
| internal_matrix | A is a caller-local array (stride ignored) |
| A_static_stride | compile-time stride of A, used instead of A_stride; tdls::dynamic_stride (the default) reads A_stride |
| work_static_stride | compile-time stride of work, used instead of work_stride; tdls::dynamic_stride (the default) reads work_stride |
| rhs_static_stride | compile-time stride of y, used instead of rhs_stride; tdls::dynamic_stride (the default) reads rhs_stride |
| [in,out] | A | matrix in its storage; recovery data on exit |
| [in] | A_stride | element stride of A |
| [out] | work | workspace of multirhs_workspace_size<nrhs> entries |
| [in] | work_stride | element stride of work |
| [in,out] | y | nrhs right-hand-side columns on entry, the solutions on exit |
| [in] | rhs_stride | element stride of y |
| [in] | xcol_stride | element stride between columns of y |
|
inlinestaticnodiscardconstexprnoexcept |
Solves A X = Y in place for nrhs right-hand sides, counting the refused blocks. The right-hand sides ride along the condensation, which runs once: each block solves [A_kb | Y_k] in passes of rhs_pass_width columns, the border system nrhs columns. Column m comes out bitwise identical to solve_inplace on it alone under the default rhs_pass_width, and within rounding errors under another (see ArrowheadLUppConfig::rhs_pass_width).
| nrhs | number of right-hand sides, >= 1 |
| internal_rhs | y is a caller-local array, column m from m * dimension (strides ignored) |
| internal_work | work is a caller-local array (stride ignored) |
| internal_matrix | A is a caller-local array (stride ignored) |
| A_static_stride | compile-time stride of A, used instead of A_stride; tdls::dynamic_stride (the default) reads A_stride |
| work_static_stride | compile-time stride of work, used instead of work_stride; tdls::dynamic_stride (the default) reads work_stride |
| rhs_static_stride | compile-time stride of y, used instead of rhs_stride; tdls::dynamic_stride (the default) reads rhs_stride |
| [in,out] | A | matrix in its storage (pattern entries only); recovery data on exit |
| [in] | A_stride | element stride of A |
| [out] | work | workspace of multirhs_workspace_size<nrhs> entries, touched only when blocks are refused |
| [in] | work_stride | element stride of work |
| [in,out] | y | nrhs right-hand-side columns on entry, the solutions on exit |
| [in] | rhs_stride | element stride of y |
| [in] | xcol_stride | element stride between columns of y |
| [out] | refused_count | number of blocks refused by the pivot check, eliminated by the second pass |
|
inlinestaticnodiscardconstexprnoexcept |
Solves A x = y in place, the blocks recomputed: provider(k, blk) fills block k (RecomputedBlock) once while the solver condenses it, k = 0, 1, ... in order, and once more, blk.recovery set, while it recovers the unknowns of the block, in decreasing k. Nothing of an accepted block is stored: the solver factors the block again and solves x_k = D_k^-1 (y_k - A_kb x_b). The matrix is never stored, and the workspace holds only the refused blocks, at most capacity of them, which the second pass eliminates as solve_inplace_streamed does. The provider must give the same entries every time it fills the same block, y_k included. The caller gives the border: A_bb, entry (r, c) at (r * border + c) * Abb_stride, or (c * border + r) * Abb_stride under the column-major layout, and the border rows of y. Nothing is written to y until the solution: y is untouched when the matrix is singular, or when more than capacity blocks are refused (deferred), so that the caller can solve that system with solve_inplace_streamed. A deferred solve stops at the refused block beyond the capacity: the provider is not called for the later blocks.
The border solution, and the unknowns of the refused blocks, are those of solve_inplace_streamed bit for bit (under the same contraction of multiply-adds); the unknowns of an accepted block agree within rounding errors, solved from one column instead of recovered from the solved columns [A_kb | y_k].
On GPU, the solve then streams nothing of the matrix through memory: one thread per system keeps the block and the Schur complement in registers (block_row_interchange). The cost is a second call of the provider, and a second factorization, per block: it pays where memory is the bound, on GPU, not on CPU, where the caches hold the recovery data.
| capacity | number of refused blocks the workspace holds, in [0, blocks] |
| internal_rhs | y is a caller-local array (stride ignored) |
| internal_work | work is a caller-local array (stride ignored) |
| internal_matrix | Abb is a caller-local array (stride ignored) |
| Abb_static_stride | compile-time stride of Abb, used instead of Abb_stride; tdls::dynamic_stride (the default) reads Abb_stride |
| work_static_stride | compile-time stride of work, used instead of work_stride; tdls::dynamic_stride (the default) reads work_stride |
| rhs_static_stride | compile-time stride of y, used instead of rhs_stride; tdls::dynamic_stride (the default) reads rhs_stride |
| Provider | callable (int k, StreamedBlock& blk) |
| [in] | provider | the source of the blocks |
| [in] | Abb | the border block A_bb, B x B in the layout of the configuration |
| [in] | Abb_stride | element stride of Abb |
| [out] | work | workspace of recomputed_workspace_size<capacity> entries (none for a capacity of 0) |
| [in] | work_stride | element stride of work |
| [in,out] | y | border rows of the right-hand side on entry, the solution on exit when solved |
| [in] | rhs_stride | element stride of y |
| [out] | refused_count | number of refused blocks |
|
inlinestaticnodiscardconstexprnoexcept |
One recomputed pass of a Newton iteration: the blocks condensed as solve_inplace_recomputed condenses them, then converged() is called. When it returns false, the pass ends as solve_inplace_recomputed: the provider is asked for every accepted block once more and y holds the correction. When it returns true, the border system condensed by the pass gives instead columns col0 .. col0 + ntan - 1 of the border block of A^-1 in x (the consistent tangent of a behaviour loaded through the border), refused blocks included, and y is untouched: the provider is then called once per block. The tangent is that of solve_inplace_streamed_or_tangent bit for bit (under the same contraction of multiply-adds). When more than capacity blocks are refused, the pass stops there, deferred, before converged() is called; y and x are untouched.
| ntan | number of tangent columns, in [1, border] |
| capacity | number of refused blocks the workspace holds, in [0, blocks] |
| internal_rhs | y and x are caller-local arrays, column m of x from m * border (strides ignored) |
| internal_work | work is a caller-local array (stride ignored) |
| internal_matrix | Abb is a caller-local array (stride ignored) |
| Abb_static_stride | compile-time stride of Abb, used instead of Abb_stride; tdls::dynamic_stride (the default) reads Abb_stride |
| work_static_stride | compile-time stride of work, used instead of work_stride; tdls::dynamic_stride (the default) reads work_stride |
| rhs_static_stride | compile-time stride of y, used instead of rhs_stride; tdls::dynamic_stride (the default) reads rhs_stride |
| x_static_stride | compile-time stride of x, used instead of x_stride; tdls::dynamic_stride (the default) reads x_stride |
| Provider | callable (int k, StreamedBlock& blk) |
| Converged | callable () returning bool |
| [in] | provider | the source of the blocks |
| [in] | converged | called after the last block: whether the tangent replaces the correction |
| [in] | Abb | the border block A_bb, B x B in the layout of the configuration |
| [in] | Abb_stride | element stride of Abb |
| [out] | work | workspace of recomputed_workspace_size<capacity, ntan> entries (none for a capacity of 0) |
| [in] | work_stride | element stride of work |
| [in,out] | y | border rows of the right-hand side on entry, the correction on exit when solved |
| [in] | rhs_stride | element stride of y |
| [in] | col0 | first tangent column, col0 + ntan <= border |
| [out] | x | the tangent columns (tangent), border entries per column |
| [in] | x_stride | element stride of x |
| [in] | xcol_stride | element stride between columns of x |
| [out] | refused_count | number of refused blocks |
|
inlinestaticnodiscardconstexprnoexcept |
Solves A x = y in place, the blocks streamed: provider(k, blk) fills block k (StreamedBlock) when the solver needs it, k = 0, 1, ... in order, and the solver condenses it at once. The caller writes beforehand only the border: A_bb in A and the border rows of y. An accepted block leaves its recovery data in its storage; a refused one is stored as given for the second pass (the provider is called exactly once per block): the arithmetic, the pivot check and the second pass are those of solve_inplace, bit for bit under the same contraction of multiply-adds (see the file documentation).
| internal_rhs | y is a caller-local array (stride ignored) |
| internal_work | work is a caller-local array (stride ignored) |
| internal_matrix | A is a caller-local array (stride ignored) |
| A_static_stride | compile-time stride of A, used instead of A_stride; tdls::dynamic_stride (the default) reads A_stride |
| work_static_stride | compile-time stride of work, used instead of work_stride; tdls::dynamic_stride (the default) reads work_stride |
| rhs_static_stride | compile-time stride of y, used instead of rhs_stride; tdls::dynamic_stride (the default) reads rhs_stride |
| Provider | callable (int k, StreamedBlock& blk) |
| [in] | provider | the source of the blocks |
| [in,out] | A | storage: A_bb on entry; recovery data on exit |
| [in] | A_stride | element stride of A |
| [out] | work | workspace of workspace_size entries |
| [in] | work_stride | element stride of work |
| [in,out] | y | border rows of the right-hand side on entry, the solution on exit |
| [in] | rhs_stride | element stride of y |
| [out] | refused_count | number of refused blocks |
|
inlinestaticnodiscardconstexprnoexcept |
One streamed pass of a Newton iteration: the blocks condensed as solve_inplace_streamed does, then converged() is called (the provider may compute the residual meanwhile). When it returns false, the pass ends as solve_inplace_streamed (y holds the correction). When it returns true, the correction is not computed: the border system condensed by the pass gives instead columns col0 .. col0 + ntan - 1 of the border block of A^-1 in x (the consistent tangent of a behaviour loaded through the border), refused blocks included (work then holds multirhs_workspace_size<ntan> entries). The provider is called exactly once per block, in order, and converged() once, after the last block. Bit for bit the results of solve_inplace_streamed, and those of solve_border_canonical_multirhs_streamed under the default rhs_pass_width (within rounding errors under another, see ArrowheadLUppConfig::rhs_pass_width).
| ntan | number of tangent columns, in [1, border] |
| internal_rhs | y and x are caller-local arrays, column m of x from m * border (strides ignored) |
| internal_work | work is a caller-local array (stride ignored) |
| internal_matrix | A is a caller-local array (stride ignored) |
| A_static_stride | compile-time stride of A, used instead of A_stride; tdls::dynamic_stride (the default) reads A_stride |
| work_static_stride | compile-time stride of work, used instead of work_stride; tdls::dynamic_stride (the default) reads work_stride |
| rhs_static_stride | compile-time stride of y, used instead of rhs_stride; tdls::dynamic_stride (the default) reads rhs_stride |
| x_static_stride | compile-time stride of x, used instead of x_stride; tdls::dynamic_stride (the default) reads x_stride |
| Provider | callable (int k, StreamedBlock& blk) |
| Converged | callable () returning bool |
| outlined | internal: set by the out-of-line call of ArrowheadLUppConfig::streamed_out_of_line, never by the caller |
| [in] | provider | the source of the blocks |
| [in] | converged | called after the last block: whether the tangent replaces the correction |
| [in,out] | A | storage: A_bb on entry; overwritten |
| [in] | A_stride | element stride of A |
| [out] | work | workspace of multirhs_workspace_size<ntan> entries |
| [in] | work_stride | element stride of work |
| [in,out] | y | border rows of the right-hand side on entry, the correction on exit (solved), intermediate values otherwise |
| [in] | rhs_stride | element stride of y |
| [in] | col0 | first tangent column, col0 + ntan <= border |
| [out] | x | the tangent columns (tangent), border entries per column |
| [in] | x_stride | element stride of x |
| [in] | xcol_stride | element stride between columns of x |
| [out] | refused_count | number of refused blocks |
|
inlinestaticnodiscardconstexprnoexcept |
Solves A X = B for nrhs right-hand sides, B left untouched.
| nrhs | number of right-hand sides, >= 1 |
| internal_rhs | b and x are caller-local arrays, column m from m * dimension (strides ignored) |
| internal_work | work is a caller-local array (stride ignored) |
| internal_matrix | A is a caller-local array (stride ignored) |
| A_static_stride | compile-time stride of A, used instead of A_stride; tdls::dynamic_stride (the default) reads A_stride |
| work_static_stride | compile-time stride of work, used instead of work_stride; tdls::dynamic_stride (the default) reads work_stride |
| rhs_static_stride | compile-time stride of b and x, used instead of rhs_stride; tdls::dynamic_stride (the default) reads rhs_stride |
| [in,out] | A | matrix in its storage; recovery data on exit |
| [in] | A_stride | element stride of A |
| [out] | work | workspace of multirhs_workspace_size<nrhs> entries |
| [in] | work_stride | element stride of work |
| [in] | b | nrhs right-hand-side columns |
| [out] | x | the nrhs solutions |
| [in] | rhs_stride | element stride of b and x |
| [in] | xcol_stride | element stride between columns of b and x |
|
inlinestaticnodiscardconstexprnoexcept |
Solves A X = B for nrhs right-hand sides, B left untouched, counting the refused blocks: B is copied into X, then solved in place.
| nrhs | number of right-hand sides, >= 1 |
| internal_rhs | b and x are caller-local arrays, column m from m * dimension (strides ignored) |
| internal_work | work is a caller-local array (stride ignored) |
| internal_matrix | A is a caller-local array (stride ignored) |
| A_static_stride | compile-time stride of A, used instead of A_stride; tdls::dynamic_stride (the default) reads A_stride |
| work_static_stride | compile-time stride of work, used instead of work_stride; tdls::dynamic_stride (the default) reads work_stride |
| rhs_static_stride | compile-time stride of b and x, used instead of rhs_stride; tdls::dynamic_stride (the default) reads rhs_stride |
| [in,out] | A | matrix in its storage; recovery data on exit |
| [in] | A_stride | element stride of A |
| [out] | work | workspace of multirhs_workspace_size<nrhs> entries |
| [in] | work_stride | element stride of work |
| [in] | b | nrhs right-hand-side columns |
| [out] | x | the nrhs solutions |
| [in] | rhs_stride | element stride of b and x |
| [in] | xcol_stride | element stride between columns of b and x |
| [out] | refused_count | number of blocks refused by the pivot check |
|
friend |
Every instantiation reaches the cores of the others (the side dispatch of nvc++).
|
staticconstexpr |
Entries of the workspace of the entry points with nrhs right-hand sides, used only when blocks are refused: the front grows by one column per right-hand side.
|
staticconstexpr |
Entries of the workspace of solve_inplace and solve, used only when blocks are refused.