SimiLie
Loading...
Searching...
No Matches
determinant.hpp
1// SPDX-FileCopyrightText: 2024 Baptiste Legouix
2// SPDX-License-Identifier: MIT
3
4#pragma once
5
6#include <ddc/ddc.hpp>
7
8#include <similie/misc/specialization.hpp>
9
10#include "tensor_impl.hpp"
11
12namespace sil {
13
14namespace tensor {
15
16// ChatGPT-generated, TODO rely on KokkosKernels LU factorization. It overwrite matrix
17template <misc::Specialization<Kokkos::View> ViewType>
18KOKKOS_FUNCTION typename ViewType::value_type determinant(const ViewType& matrix)
19{
20 assert(matrix.extent(0) == matrix.extent(1)
21 && "Matrix should be squared to compute its determinant");
22
23 const std::size_t N = matrix.extent(0);
24
25 // Permutation sign (to account for row swaps)
26 int permutation_sign = 1;
27
28 // Perform LU decomposition with partial pivoting
29 for (std::size_t i = 0; i < N; ++i) {
30 // Pivoting (find the largest element in the current column)
31 std::size_t pivot = i;
32 typename ViewType::value_type max_val = Kokkos::abs(matrix(i, i));
33 for (std::size_t j = i + 1; j < N; ++j) {
34 if (Kokkos::abs(matrix(j, i)) > max_val) {
35 pivot = j;
36 max_val = Kokkos::abs(matrix(j, i));
37 }
38 }
39
40 // Swap rows if necessary
41 if (pivot != i) {
42 permutation_sign *= -1; // Track the effect of row swaps
43 for (std::size_t k = 0; k < N; ++k) {
44 Kokkos::kokkos_swap(matrix(i, k), matrix(pivot, k));
45 }
46 }
47
48 // Check for singular matrix
49 if (matrix(i, i) == 0.0) {
50 return 0.0; // Determinant is zero for singular matrices
51 }
52
53 // Perform elimination below the pivot
54 for (std::size_t j = i + 1; j < N; ++j) {
55 matrix(j, i) /= matrix(i, i);
56 for (std::size_t k = i + 1; k < N; ++k) {
57 matrix(j, k) -= matrix(j, i) * matrix(i, k);
58 }
59 }
60 }
61
62 // Compute the determinant as the product of the diagonal elements
63 typename ViewType::value_type det = permutation_sign;
64 for (std::size_t i = 0; i < N; ++i) {
65 det *= matrix(i, i);
66 }
67
68 return det;
69}
70
71// TODO port on GPU
72template <misc::Specialization<Tensor> TensorType>
73TensorType::element_type determinant(TensorType tensor)
74{
75 static_assert(TensorType::natural_domain_t::rank() == 2);
76 auto extents = ddc::detail::array(tensor.natural_domain().extents());
77 assert(extents[0] == extents[1] && "Matrix should be squared to compute its determinant");
78 const std::size_t n = extents[0];
79
80 Kokkos::View<typename TensorType::element_type**, Kokkos::LayoutRight, Kokkos::HostSpace>
81 buffer("determinant_buffer", n, n);
82 ddc::parallel_for_each(
83 Kokkos::DefaultHostExecutionSpace(),
84 tensor.accessor().natural_domain(),
85 [&](auto index) {
86 buffer(ddc::detail::array(index)[0], ddc::detail::array(index)[1])
87 = tensor(tensor.access_element(index));
88 });
89 return determinant(buffer);
90}
91
92} // namespace tensor
93
94} // namespace sil
KOKKOS_FUNCTION ViewType::value_type determinant(const ViewType &matrix)
The top-level namespace of SimiLie.
Definition csr.hpp:14