11 namespace dolfinx::math
17 inline T difference_of_products(T a, T b, T c, T d) noexcept
20 T err = std::fma(-b, c, w);
21 T diff = std::fma(a, d, -w);
27 template <
typename Matrix>
28 auto det(
const Matrix& A)
30 using value_type =
typename Matrix::value_type;
31 assert(A.shape(0) == A.shape(1));
32 assert(A.dimension() == 2);
34 const int nrows = A.shape(0);
40 return difference_of_products(A(0, 0), A(0, 1), A(1, 0), A(1, 1));
45 value_type w0 = difference_of_products(A(1, 1), A(1, 2), A(2, 1), A(2, 2));
46 value_type w1 = difference_of_products(A(1, 0), A(1, 2), A(2, 0), A(2, 2));
47 value_type w2 = difference_of_products(A(1, 0), A(1, 1), A(2, 0), A(2, 1));
48 value_type w3 = difference_of_products(A(0, 0), A(0, 1), w1, w0);
49 value_type w4 = std::fma(A(0, 2), w2, w3);
53 throw std::runtime_error(
"math::det is not implemented for "
54 + std::to_string(A.shape(0)) +
"x"
55 + std::to_string(A.shape(1)) +
" matrices.");
62 template <
typename U,
typename V>
63 void inv(
const U& A, V& B)
65 using value_type =
typename U::value_type;
66 const std::size_t nrows = A.shape(0);
70 B(0, 0) = 1 / A(0, 0);
74 value_type idet = 1. / det(A);
75 B(0, 0) = idet * A(1, 1);
76 B(0, 1) = -idet * A(0, 1);
77 B(1, 0) = -idet * A(1, 0);
78 B(1, 1) = idet * A(0, 0);
83 value_type w0 = difference_of_products(A(1, 1), A(1, 2), A(2, 1), A(2, 2));
84 value_type w1 = difference_of_products(A(1, 0), A(1, 2), A(2, 0), A(2, 2));
85 value_type w2 = difference_of_products(A(1, 0), A(1, 1), A(2, 0), A(2, 1));
86 value_type w3 = difference_of_products(A(0, 0), A(0, 1), w1, w0);
87 value_type det = std::fma(A(0, 2), w2, w3);
89 value_type idet = 1 / det;
94 B(0, 1) = difference_of_products(A(0, 2), A(0, 1), A(2, 2), A(2, 1)) * idet;
95 B(0, 2) = difference_of_products(A(0, 1), A(0, 2), A(1, 1), A(1, 2)) * idet;
96 B(1, 1) = difference_of_products(A(0, 0), A(0, 2), A(2, 0), A(2, 2)) * idet;
97 B(1, 2) = difference_of_products(A(1, 0), A(0, 0), A(1, 2), A(0, 2)) * idet;
98 B(2, 1) = difference_of_products(A(2, 0), A(0, 0), A(2, 1), A(0, 1)) * idet;
99 B(2, 2) = difference_of_products(A(0, 0), A(1, 0), A(0, 1), A(1, 1)) * idet;
103 throw std::runtime_error(
"math::inv is not implemented for "
104 + std::to_string(A.shape(0)) +
"x"
105 + std::to_string(A.shape(1)) +
" matrices.");