Uni20
Asynchronous tensor and runtime library.
Loading...
Searching...
No Matches
linear_solve_common.hpp
Go to the documentation of this file.
1#pragma once
2
4#include <uni20/core/math.hpp>
7
8#include <cmath>
9
10namespace uni20::linalg::detail
11{
12
13template <class Matrix> bool solve_matrix_is_finite(Matrix const& matrix)
14{
15 using scalar_type = typename Matrix::value_type;
16 for (typename Matrix::index_type row = 0; row < matrix.extent(0); ++row)
17 for (typename Matrix::index_type col = 0; col < matrix.extent(1); ++col)
18 if (!uni20::isfinite(static_cast<scalar_type>(matrix[row, col]))) return false;
19 return true;
20}
21
22template <uni20::Real Real> void require_solve_options(SolveOptions<Real> const& options)
23{
24 ERROR_IF(!uni20::isfinite(options.relative_pivot_tolerance) || options.relative_pivot_tolerance < Real{},
25 "solve requires a finite nonnegative relative pivot tolerance");
26}
27
28// Called only after a backend has committed to execution; a numerical failure
29// writes diagnostics but must still return KernelAttempt::success to dispatch.
30template <class Matrix, class Rhs, class Real>
31bool prepare_linear_solve(Matrix const& coefficients, Rhs const& rhs, Real& scale, SolveInfo& info)
32{
33 info = {};
34 if (!solve_matrix_is_finite(coefficients) || !solve_matrix_is_finite(rhs))
35 {
37 return false;
38 }
39 using std::abs;
40 using scalar_type = typename Matrix::value_type;
41 for (typename Matrix::index_type row = 0; row < coefficients.extent(0); ++row)
42 for (typename Matrix::index_type col = 0; col < coefficients.extent(1); ++col)
43 {
44 Real const magnitude = abs(static_cast<scalar_type>(coefficients[row, col]));
45 if (!uni20::isfinite(magnitude))
46 {
48 return false;
49 }
50 if (magnitude > scale) scale = magnitude;
51 }
52 return true;
53}
54
55template <class Real>
56bool check_solve_pivot(Real magnitude, Real scale, SolveOptions<Real> const& options, std::size_t column,
57 SolveInfo& info)
58{
59 if (!uni20::isfinite(magnitude))
61 else if (magnitude == Real{})
62 info = {.status = SolveStatus::singular, .pivot = column};
63 else if (options.relative_pivot_tolerance > Real{} && magnitude / scale <= options.relative_pivot_tolerance)
64 info = {.status = SolveStatus::small_pivot, .pivot = column};
65 return info.succeeded();
66}
67
68} // namespace uni20::linalg::detail
constexpr bool isfinite(I const &x) noexcept
Returns whether an integer scalar is finite.
Definition math.hpp:121
Scalar math helper utilities.
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
@ nonfinite_input
An input coefficient or RHS component was nonfinite; both workspaces are preserved.
@ singular
An exactly zero elimination pivot was found.
@ nonfinite_result
A factor, solution, reduction, or required magnitude became nonfinite.
@ small_pivot
A nonzero pivot failed the requested relative threshold.
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
#define ERROR_IF(cond,...)
Definition trace.hpp:389