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