29namespace detail::cpu_reference
32template <
class CoefficientMdspan,
class RhsMdspan>
consteval auto linear_solve_acceptance()
34 using coefficient_type = std::remove_cvref_t<CoefficientMdspan>;
35 using rhs_type = std::remove_cvref_t<RhsMdspan>;
36 using scalar_type =
typename coefficient_type::value_type;
37 using coefficient_index =
typename coefficient_type::index_type;
38 using rhs_index =
typename rhs_type::index_type;
41 std::same_as<scalar_type, typename rhs_type::value_type> &&
42 requires(CoefficientMdspan& coefficients, RhsMdspan& rhs, coefficient_index coefficient_i,
43 rhs_index rhs_i, scalar_type
value) {
44 static_cast<scalar_type
>(coefficients[coefficient_i, coefficient_i]);
45 static_cast<scalar_type
>(rhs[rhs_i, rhs_i]);
46 coefficients[coefficient_i, coefficient_i] =
value;
47 rhs[rhs_i, rhs_i] =
value;
56template <
class CoefficientMdspan,
class RhsMdspan>
57KernelAttempt linear_solve(CoefficientMdspan& coefficients, RhsMdspan& right_hand_sides, SolveInfo& info,
60 using coefficient_type = std::remove_cvref_t<CoefficientMdspan>;
61 using rhs_type = std::remove_cvref_t<RhsMdspan>;
62 using scalar_type =
typename coefficient_type::value_type;
64 using coefficient_index =
typename coefficient_type::index_type;
65 using rhs_index =
typename rhs_type::index_type;
67 CHECK_EQUAL(coefficients.extent(0), coefficients.extent(1));
68 CHECK_EQUAL(coefficients.extent(0), right_hand_sides.extent(0));
69 std::size_t
const order =
static_cast<std::size_t
>(coefficients.extent(0));
70 std::size_t
const rhs_count =
static_cast<std::size_t
>(right_hand_sides.extent(1));
72 require_solve_options(options);
79 for (std::size_t k = 0; k < order; ++k)
81 auto const coefficient_k =
static_cast<coefficient_index
>(k);
82 std::size_t pivot_row = k;
83 real_type pivot_value =
abs(
static_cast<scalar_type
>(coefficients[coefficient_k, coefficient_k]));
84 for (std::size_t
row = k + 1;
row < order; ++
row)
86 auto const coefficient_row =
static_cast<coefficient_index
>(
row);
87 real_type
const candidate =
abs(
static_cast<scalar_type
>(coefficients[coefficient_row, coefficient_k]));
88 if (candidate > pivot_value)
90 pivot_value = candidate;
96 swap_rows(coefficients, k, pivot_row, order);
97 swap_rows(right_hand_sides, k, pivot_row, rhs_count);
99 scalar_type
const pivot =
static_cast<scalar_type
>(coefficients[coefficient_k, coefficient_k]);
100 for (std::size_t
row = k + 1;
row < order; ++
row)
102 auto const coefficient_row =
static_cast<coefficient_index
>(
row);
103 scalar_type
const factor =
static_cast<scalar_type
>(coefficients[coefficient_row, coefficient_k]) / pivot;
104 if (factor == scalar_type{})
continue;
106 coefficients[coefficient_row, coefficient_k] = scalar_type{};
107 for (std::size_t col = k + 1; col < order; ++col)
109 auto const coefficient_col =
static_cast<coefficient_index
>(col);
110 scalar_type
value =
static_cast<scalar_type
>(coefficients[coefficient_row, coefficient_col]);
111 value -= factor *
static_cast<scalar_type
>(coefficients[coefficient_k, coefficient_col]);
117 coefficients[coefficient_row, coefficient_col] =
value;
119 for (std::size_t col = 0; col < rhs_count; ++col)
121 auto const rhs_row =
static_cast<rhs_index
>(
row);
122 auto const rhs_k =
static_cast<rhs_index
>(k);
123 auto const rhs_col =
static_cast<rhs_index
>(col);
124 scalar_type
value =
static_cast<scalar_type
>(right_hand_sides[rhs_row, rhs_col]);
125 value -= factor *
static_cast<scalar_type
>(right_hand_sides[rhs_k, rhs_col]);
131 right_hand_sides[rhs_row, rhs_col] =
value;
136 for (std::size_t
row = order;
row-- > 0;)
138 auto const coefficient_row =
static_cast<coefficient_index
>(
row);
139 scalar_type
const pivot =
static_cast<scalar_type
>(coefficients[coefficient_row, coefficient_row]);
140 for (std::size_t col = 0; col < rhs_count; ++col)
142 auto const rhs_row =
static_cast<rhs_index
>(
row);
143 auto const rhs_col =
static_cast<rhs_index
>(col);
144 scalar_type
value =
static_cast<scalar_type
>(right_hand_sides[rhs_row, rhs_col]);
145 for (std::size_t k =
row + 1; k < order; ++k)
147 auto const coefficient_k =
static_cast<coefficient_index
>(k);
148 auto const rhs_k =
static_cast<rhs_index
>(k);
149 value -=
static_cast<scalar_type
>(coefficients[coefficient_row, coefficient_k]) *
150 static_cast<scalar_type
>(right_hand_sides[rhs_k, rhs_col]);
158 right_hand_sides[rhs_row, rhs_col] =
value;
168template <uni20::MutableRankedMdspecLike<2> CoefficientMdspec, uni20::MutableRankedMdspecLike<2> RhsMdspec>
176 constexpr auto acceptance = detail::cpu_reference::linear_solve_acceptance<coefficient_span, rhs_span>();
184template <uni20::MutableRankedMdspecLike<2> CoefficientMdspec, uni20::MutableRankedMdspecLike<2> RhsMdspec>
187 RhsMdspec& right_hand_sides,
SolveInfo& info,
192 auto coefficient_span = coefficient_access.mdspan();
193 auto rhs_span = rhs_access.mdspan();
194 return detail::cpu_reference::linear_solve(coefficient_span, rhs_span, info, options);
198template <MutableRankedMdspecLike<2> A, MutableRankedMdspecLike<2> B>
200 has_runtime_precision_v<typename A::value_type> &&
201 std::same_as<typename A::value_type, typename B::value_type>
209template <MutableRankedMdspecLike<2> A, MutableRankedMdspecLike<2> B>
211 has_runtime_precision_v<typename A::value_type> &&
212 std::same_as<typename A::value_type, typename B::value_type>
218 ERROR_IF(a.extent(0) != a.extent(1) || a.extent(0) != b.extent(0),
"solve operand shapes do not agree");
219 detail::require_solve_options(options);
224 auto as = aa.mdspan();
225 auto bs = ba.mdspan();
226 if (!detail::solve_matrix_is_finite(as) || !detail::solve_matrix_is_finite(bs))
232 auto aw = av.mdspan();
233 auto bw = bv.mdspan();
234 if (!detail::solve_matrix_is_finite(aw) || !detail::solve_matrix_is_finite(bw))
240 std::vector<std::size_t> pivots(std::size_t(a.extent(0)));
241 detail::cpu_reference::lu_factor(aw, std::span(pivots),
nullptr, info, converted, scalar_at_precision<R>(0,
p));
243 if (info.succeeded())
245 detail::cpu_reference::lu_solve(aw, std::span<std::size_t const>(pivots), bw, info);
RAII leases that resolve device descriptors and tensor views to mdspans.
Exact arithmetic or an explicit binary working precision.
Definition core/precision.hpp:13
Mutable mdspec metadata supporting host write acquisition.
Definition access.hpp:694
Concept for types that are either real or complex.
Definition scalar_concepts.hpp:87
locale_t value
Definition data_table.cpp:49
Operation-tag backend dispatch over tensor-view operands.
typename make_real< T >::type make_real_t
Alias for the underlying real-valued type of T.
Definition scalar_traits.hpp:168
constexpr bool isfinite(I const &x) noexcept
Returns whether an integer scalar is finite.
Definition math.hpp:121
Mdspan concept and accessor extensions for Uni20.
void info(checked_format_string< Args... > format, Args &&... args)
Emit an informational display message.
Definition display.hpp:393
void unpack(Tensor const &source, Span &target)
Definition packed_matrix.hpp:33
auto pack(Span const &span, Precision p, bool read=true)
Definition packed_matrix.hpp:19
Definition linalg/async.hpp:28
KernelAttempt try_kernel(BlasBackend, gemm_op const &, C &c, S const &alpha, A &a, B &b, S const &beta)
Pack logical host values and execute GEMM through value-preserving provider conversion.
Definition linalg/backends/blas/binary80.hpp:30
KernelAttempt
Result of one runtime kernel backend attempt.
Definition kernel_attempt.hpp:27
@ nonfinite_input
An input coefficient or RHS component was nonfinite; both workspaces are preserved.
@ nonfinite_result
A factor, solution, reduction, or required magnitude became nonfinite.
constexpr KernelAcceptance< KernelTypeAcceptance::no > kernel_types_no
Report that a backend rejects the argument types.
Definition dispatch_error.hpp:34
consteval auto kernel_accepts_types(BlasBackend, gemm_op const &, C &, S const &, A &, B &, S const &)
Accept host-readable native binary80 operands, including transforming accessors.
Definition linalg/backends/blas/binary80.hpp:19
constexpr KernelAcceptance< KernelTypeAcceptance::yes > kernel_types_yes
Report that a backend accepts every instance of the argument types.
Definition dispatch_error.hpp:40
Definition data_table.cpp:8
constexpr auto abs(basic_half_int< T > value) -> basic_half_int< T >
Return the absolute value of a half-integer.
Definition half_int.hpp:431
std::remove_cvref_t< decltype(std::declval< detail::host_write_mdspan_lease_t< Mdspec > & >().mdspan())> host_write_mdspan_t
Writable mdspan type resolved by host descriptor acquisition.
Definition access.hpp:684
auto acquire_host_write_access_sync(Mdspan &mdspan)
Acquire a directly host-accessible writable mdspan.
Definition access.hpp:626
Logical host packing for value-converting BLAS and LAPACK adapters.
Backend value for the reference host CPU dense linalg oracle.
Definition backend_selector.hpp:55
Diagnostics written by a completed numerical attempt, independent of dispatch.
Definition solve_info.hpp:41
Real-scalar pivot policy for a square linear solve.
Definition solve_info.hpp:62
Real relative_pivot_tolerance
Reject nonzero pivots at or below this fraction of the original maximum entry magnitude.
Definition solve_info.hpp:64
Destructive dense general linear-system solve operation tag.
Definition operation_tags.hpp:155
Concepts for tensor-level objects that resolve mdspan kernel operands.
#define CHECK_EQUAL(a, b,...)
Definition trace.hpp:309
#define ERROR_IF(cond,...)
Definition trace.hpp:389