8namespace uni20::linalg::detail
11template <
class Matrix, Real R>
void capture_lu_norms(Matrix
const& a, LuNorms<R>* norms, R
const& zero)
14 *norms = {zero, zero};
15 std::vector<R> row_sums(std::size_t(a.extent(0)), zero);
16 for (std::size_t j = 0; j < std::size_t(a.extent(1)); ++j)
19 for (std::size_t i = 0; i < std::size_t(a.extent(0)); ++i)
25 norms->one = std::max(norms->one,
sum);
27 for (
auto const&
sum : row_sums)
28 norms->infinity =
std::max(norms->infinity,
sum);
33template <Real R>
struct LuMagnitude
39template <RealOrComplex S>
auto lu_magnitude(S
const&
value)
41 using R = make_real_t<S>;
44 if constexpr (Complex<S>)
47 if (other > scale) std::swap(other, scale);
50 auto ratio = other / scale;
54 return LuMagnitude<R>{std::move(scale), std::move(unit)};
57template <Real R>
bool lu_magnitude_less(LuMagnitude<R>
const& a, LuMagnitude<R>
const& b)
59 if (b.scale == 0)
return false;
60 if (a.scale <= b.scale)
return (a.scale / b.scale) * a.unit < b.unit;
61 return a.unit < (b.scale / a.scale) * b.unit;
64template <Real R>
bool lu_small_pivot(LuMagnitude<R>
const& pivot, LuMagnitude<R>
const& scale, R
const& tolerance)
66 if (tolerance == 0)
return false;
67 if (pivot.scale <= scale.scale)
return (pivot.scale / scale.scale) * (pivot.unit / scale.unit) <= tolerance;
70 return scalar_like(tolerance, 1) / tolerance <= (scale.scale / pivot.scale) * (scale.unit / pivot.unit);
73template <
class Matrix, Real R>
auto lu_input_scale(Matrix
const& a, R
const& zero)
76 for (std::size_t j = 0; j < std::size_t(a.extent(1)); ++j)
77 for (std::size_t i = 0; i < std::size_t(a.extent(0)); ++i)
79 auto next = lu_magnitude(
static_cast<typename Matrix::value_type
>(a[i, j]));
80 if (lu_magnitude_less(scale, next)) scale = std::move(next);
85template <
class Matrix, Real R>
86bool check_lu_diagonal(Matrix
const& a, LuMagnitude<R>
const& scale, R
const& tolerance, SolveInfo& info)
88 for (std::size_t k = 0; k < std::size_t(a.extent(0)); ++k)
90 auto magnitude = lu_magnitude(
static_cast<typename Matrix::value_type
>(a[k, k]));
93 else if (lu_small_pivot(magnitude, scale, tolerance))
95 if (!
info.succeeded())
return false;
102template <
class Matrix>
void require_lu_shape(Matrix
const& a, std::size_t pivot_count)
104 ERROR_IF(a.extent(0) != a.extent(1),
"LU requires a square matrix");
105 ERROR_IF(std::size_t(a.extent(0)) != pivot_count,
"LU pivot count mismatch");
107template <
class Matrix,
class Rhs>
108void require_lu_solve_shape(Matrix
const& a, std::span<std::size_t const> pivots, Rhs
const& b)
110 require_lu_shape(a, pivots.size());
111 ERROR_IF(a.extent(0) != b.extent(0),
"LU solve RHS row count mismatch");
locale_t value
Definition data_table.cpp:49
void info(checked_format_string< Args... > format, Args &&... args)
Emit an informational display message.
Definition display.hpp:393
DiagnosticMagnitude< R > magnitude(R const &value)
Definition gmres_diagnostics.hpp:98
R ratio(DiagnosticMagnitude< R > const &a, DiagnosticMagnitude< R > const &b)
Definition gmres_diagnostics.hpp:125
@ singular
An exactly zero elimination pivot was found.
@ small_pivot
A nonzero pivot failed the requested relative threshold.
constexpr detail::scalar_math::sqrt_fn sqrt
Square root; exact inputs requiring approximation need an explicit finite precision.
Definition math.hpp:461
constexpr detail::scalar_math::abs_fn abs
Absolute value or complex magnitude, preserving the selected scalar implementation.
Definition math.hpp:459
void sum(BackendSelector selector, async::Async< OutputTensor > &output, async::Async< InputTensor > const &input)
Schedule a full sum into an explicit async scalar tensor.
Definition linalg/async/reductions.hpp:309
constexpr auto scalar_like(S const &exemplar, Value const &value) -> S
Construct a scalar using an exemplar's type and numerical precision.
Definition math.hpp:195
#define ERROR_IF(cond,...)
Definition trace.hpp:389