10#if !defined(MiniTensor_Inverse_h)
11#define MiniTensor_Inverse_h
26template<
typename T, Index N>
36template<
typename T, Index N>
46template<
typename T, Index N>
57template<
typename T, Index N>
68template<
typename T, Index N>
77template<
typename T, Index N>
80rank_one_left(T
const & beta, Vector<T, N>
const & v, Tensor<T, N> & A);
86template<
typename T, Index N>
89rank_one_right(T
const & beta, Vector<T, N>
const & v, Tensor<T, N> & A);
106template <
typename T, Index N,
typename RHS>
108 Tensor<T, N>
const &A, RHS
const &B);
122template <
typename T, Index N,
typename RHS>
123RHS
solve(Tensor<T, N>
const &A, RHS
const &b,
126template<
typename T, Index N,
typename RHS>
137template<
typename T, Index N>
146 for (
Index k = 0; k < dimension; ++k) {
147 std::swap(A(i, k), A(j, k));
159template<
typename T, Index N>
168 for (
Index k = 0; k < dimension; ++k) {
169 std::swap(A(k, i), A(k, j));
179template<
typename T, Index N>
194template<
typename T, Index N>
203 B = identity<T, N>(dimension);
214template<
typename T, Index N>
225 if (dimension == 1) {
229 if constexpr (dimension_reachable<N, 2>) {
230 if (dimension == 2) {
231 T
const determinant =
det(A);
232 assert(determinant != 0.0);
233 return Tensor<T, N>(A(1,1), -A(0,1), -A(1,0), A(0,0)) / determinant;
237 if constexpr (dimension_reachable<N, 3>) {
238 if (dimension == 3) {
239 T
const determinant =
det(A);
240 assert(determinant != 0.0);
242 -A(1,2)*A(2,1) + A(1,1)*A(2,2),
243 A(0,2)*A(2,1) - A(0,1)*A(2,2),
244 -A(0,2)*A(1,1) + A(0,1)*A(1,2),
245 A(1,2)*A(2,0) - A(1,0)*A(2,2),
246 -A(0,2)*A(2,0) + A(0,0)*A(2,2),
247 A(0,2)*A(1,0) - A(0,0)*A(1,2),
248 -A(1,1)*A(2,0) + A(1,0)*A(2,1),
249 A(0,1)*A(2,0) - A(0,0)*A(2,1),
250 -A(0,1)*A(1,0) + A(0,0)*A(1,1)
255 if constexpr (dimension_reachable<N, 4>) {
271template<
typename T, Index N,
typename RHS>
282 if (dimension > maximum_dimension) {
283 MT_ERROR_EXIT(
"Max dim (%d) exceeded: %d.", dimension, maximum_dimension);
290 num_rhs{B.get_num_cols()};
295 for (
Index i{0}; i < num_rhs; ++i) {
296 B(0, i) = b(0, i) / A(0, 0);
309 intact_rows{
static_cast<Index>((1UL << dimension) - 1)};
312 intact_cols{
static_cast<Index>((1UL << dimension) - 1)};
315 for (
Index k{0}; k < dimension; ++k) {
322 pivot_row{dimension};
325 pivot_col{dimension};
329 if (!(intact_rows & (1 <<
row)))
continue;
333 if (!(intact_cols & (1 <<
col)))
continue;
352 if (pivot_row >= dimension || pivot_col >= dimension) {
353 MT_ERROR_EXIT(
"Full-pivot solve failed: singular or non-finite matrix.");
358 t{S(pivot_row, pivot_col)};
360 for (
Index j{0}; j < dimension; ++j) {
361 S(pivot_row, j) /= t;
363 for (
Index j{0}; j < num_rhs; ++j) {
364 B(pivot_row, j) /= t;
367 for (
Index i{0}; i < dimension; ++i) {
368 if (i == pivot_row)
continue;
373 for (
Index j = 0; j < dimension; ++j) {
374 S(i, j) -= c * S(pivot_row, j);
376 for (
Index j = 0; j < num_rhs; ++j) {
377 B(i, j) -= c * B(pivot_row, j);
382 intact_rows &= ~(1 << pivot_row);
383 intact_cols &= ~(1 << pivot_col);
396template<
typename T, Index N>
401 A -= beta *
dyad(v,
dot(v, A));
408template<
typename T, Index N>
413 A -= beta *
dyad(
dot(A, v), v);
423template <
typename T, Index N,
typename RHS>
424std::pair<Tensor<T, N>, RHS> identity_precon(Tensor<T, N>
const &A,
426 return std::make_pair(A, B);
432template <
typename T, Index N,
typename RHS>
433std::pair<Tensor<T, N>, RHS> diagonal_precon(Tensor<T, N>
const &A,
444 return std::make_pair(P * A, P * B);
450template <
typename T, Index N,
typename RHS>
451std::pair<Tensor<T, N>, RHS> maxabsrow_precon(Tensor<T, N>
const &A, RHS &B) {
453 dimension = A.get_dimension();
458 for (
Index i{0}; i < dimension; ++i) {
462 return std::make_pair(P * A, P * B);
470template <
typename T, Index N,
typename RHS>
482 return impl::diagonal_precon(A, B);
485 return impl::maxabsrow_precon(A, B);
488 return std::make_pair(A, B);
499template <
typename T, Index N,
typename RHS>
507 std::tie(PA, Pb) =
precon(pt, A, b);
#define KOKKOS_INLINE_FUNCTION
#define MT_ERROR_EXIT(...)
KOKKOS_INLINE_FUNCTION Tensor< typename Promote< S, T >::type, N > dyad(Vector< S, N > const &u, Vector< T, N > const &v)
KOKKOS_INLINE_FUNCTION Vector< T, M > col(Matrix< T, M, N > const &A, Index const j)
KOKKOS_INLINE_FUNCTION Index get_dimension() const
KOKKOS_INLINE_FUNCTION Tensor< T, N > diag(Vector< T, N > const &v)
KOKKOS_INLINE_FUNCTION Vector< typename Promote< S, T >::type, M > dot(Matrix< T, M, N > const &A, Vector< S, N > const &u)
KOKKOS_INLINE_FUNCTION Matrix< typename Promote< S, T >::type, M, N > t_dot(Matrix< S, P, M > const &A, Matrix< T, P, N > const &B)
KOKKOS_INLINE_FUNCTION Vector< T, N > row(Matrix< T, M, N > const &A, Index const i)
KOKKOS_INLINE_FUNCTION void swap_col(Tensor< T, N > &A, Index const i, Index const j)
KOKKOS_INLINE_FUNCTION RHS solve_full_pivot(Tensor< T, N > const &A, RHS const &b)
KOKKOS_INLINE_FUNCTION void rank_one_right(T const &beta, Vector< T, N > const &v, Tensor< T, N > &A)
KOKKOS_INLINE_FUNCTION Tensor< T, N > inverse_full_pivot(Tensor< T, N > const &A)
KOKKOS_INLINE_FUNCTION Tensor< T, N > inverse(Tensor< T, N > const &A)
KOKKOS_INLINE_FUNCTION void swap_row(Tensor< T, N > &A, Index const i, Index const j)
KOKKOS_INLINE_FUNCTION void rank_one_left(T const &beta, Vector< T, N > const &v, Tensor< T, N > &A)
std::pair< Tensor< T, N >, RHS > precon(PreconditionerType const pt, Tensor< T, N > const &A, RHS const &B)
RHS solve(Tensor< T, N > const &A, RHS const &b, PreconditionerType const pt=PreconditionerType::IDENTITY)
KOKKOS_INLINE_FUNCTION Tensor< T, N > inverse_fast23(Tensor< T, N > const &A)
KOKKOS_INLINE_FUNCTION T det(Tensor< T, N > const &A)
KOKKOS_INLINE_FUNCTION T norm_infinity(Tensor< T, N > const &A)
uint32_t Index
Indexing type.
constexpr Index INDEX_SIZE