5#ifndef DUNE_GEOMETRY_UTILITY_DEFAULTMATRIXHELPER_HH
6#define DUNE_GEOMETRY_UTILITY_DEFAULTMATRIXHELPER_HH
20struct FieldMatrixHelper
25 template<
int m,
int n,
int p >
26 static void ATBT (
const FieldMatrix< ctype, m, n > &A,
const FieldMatrix< ctype, p, m > &B, FieldMatrix< ctype, n, p > &ret )
28 for(
int i = 0; i < n; ++i )
30 for(
int j = 0; j < p; ++j )
32 ret[ i ][ j ] = ctype( 0 );
33 for(
int k = 0; k < m; ++k )
34 ret[ i ][ j ] += A[ k ][ i ] * B[ j ][ k ];
40 template<
int m,
int n >
41 static void ATA_L (
const FieldMatrix< ctype, m, n > &A, FieldMatrix< ctype, n, n > &ret )
43 for(
int i = 0; i < n; ++i )
45 for(
int j = 0; j <= i; ++j )
47 ret[ i ][ j ] = ctype( 0 );
48 for(
int k = 0; k < m; ++k )
49 ret[ i ][ j ] += A[ k ][ i ] * A[ k ][ j ];
55 template<
int m,
int n >
56 static void AAT_L (
const FieldMatrix< ctype, m, n > &A, FieldMatrix< ctype, m, m > &ret )
58 for(
int i = 0; i < m; ++i )
60 for(
int j = 0; j <= i; ++j )
62 ctype &retij = ret[ i ][ j ];
63 retij = A[ i ][ 0 ] * A[ j ][ 0 ];
64 for(
int k = 1; k < n; ++k )
65 retij += A[ i ][ k ] * A[ j ][ k ];
71 template<
int m,
int n >
72 static void AAT (
const FieldMatrix< ctype, m, n > &A, FieldMatrix< ctype, m, m > &ret )
74 for(
int i = 0; i < m; ++i )
76 for(
int j = 0; j < i; ++j )
78 ret[ i ][ j ] = ctype( 0 );
79 for(
int k = 0; k < n; ++k )
80 ret[ i ][ j ] += A[ i ][ k ] * A[ j ][ k ];
81 ret[ j ][ i ] = ret[ i ][ j ];
83 ret[ i ][ i ] = ctype( 0 );
84 for(
int k = 0; k < n; ++k )
85 ret[ i ][ i ] += A[ i ][ k ] * A[ i ][ k ];
92 static void Lx (
const FieldMatrix< ctype, n, n > &L,
const FieldVector< ctype, n > &x, FieldVector< ctype, n > &ret )
94 for(
int i = 0; i < n; ++i )
96 ret[ i ] = ctype( 0 );
97 for(
int j = 0; j <= i; ++j )
98 ret[ i ] += L[ i ][ j ] * x[ j ];
105 static void LTx (
const FieldMatrix< ctype, n, n > &L,
const FieldVector< ctype, n > &x, FieldVector< ctype, n > &ret )
107 for(
int i = 0; i < n; ++i )
109 ret[ i ] = ctype( 0 );
110 for(
int j = i; j < n; ++j )
111 ret[ i ] += L[ j ][ i ] * x[ j ];
118 static void LTL (
const FieldMatrix< ctype, n, n > &L, FieldMatrix< ctype, n, n > &ret )
120 for(
int i = 0; i < n; ++i )
122 for(
int j = 0; j < i; ++j )
124 ret[ i ][ j ] = ctype( 0 );
125 for(
int k = i; k < n; ++k )
126 ret[ i ][ j ] += L[ k ][ i ] * L[ k ][ j ];
127 ret[ j ][ i ] = ret[ i ][ j ];
129 ret[ i ][ i ] = ctype( 0 );
130 for(
int k = i; k < n; ++k )
131 ret[ i ][ i ] += L[ k ][ i ] * L[ k ][ i ];
138 static void LLT (
const FieldMatrix< ctype, n, n > &L, FieldMatrix< ctype, n, n > &ret )
140 for(
int i = 0; i < n; ++i )
142 for(
int j = 0; j < i; ++j )
144 ret[ i ][ j ] = ctype( 0 );
145 for(
int k = 0; k <= j; ++k )
146 ret[ i ][ j ] += L[ i ][ k ] * L[ j ][ k ];
147 ret[ j ][ i ] = ret[ i ][ j ];
149 ret[ i ][ i ] = ctype( 0 );
150 for(
int k = 0; k <= i; ++k )
151 ret[ i ][ i ] += L[ i ][ k ] * L[ i ][ k ];
159 static bool cholesky_L (
const FieldMatrix< ctype, n, n > &A, FieldMatrix< ctype, n, n > &ret,
const bool checkSingular =
false )
162 for(
int i = 0; i < n; ++i )
164 ctype &rii = ret[ i ][ i ];
166 ctype xDiag = A[ i ][ i ];
167 for(
int j = 0; j < i; ++j )
168 xDiag -= ret[ i ][ j ] * ret[ i ][ j ];
172 if( checkSingular && ! ( xDiag > ctype( 0 )) )
176 assert( xDiag > ctype( 0 ) );
179 ctype invrii = ctype( 1 ) / rii;
180 for(
int k = i+1; k < n; ++k )
182 ctype x = A[ k ][ i ];
183 for(
int j = 0; j < i; ++j )
184 x -= ret[ i ][ j ] * ret[ k ][ j ];
185 ret[ k ][ i ] = invrii * x;
196 static ctype detL (
const FieldMatrix< ctype, n, n > &L )
199 for(
int i = 0; i < n; ++i )
207 static ctype invL ( FieldMatrix< ctype, n, n > &L )
210 for(
int i = 0; i < n; ++i )
212 ctype &lii = L[ i ][ i ];
214 lii = ctype( 1 ) / lii;
215 for(
int j = 0; j < i; ++j )
217 ctype &lij = L[ i ][ j ];
218 ctype x = lij * L[ j ][ j ];
219 for(
int k = j+1; k < i; ++k )
220 x += L[ i ][ k ] * L[ k ][ j ];
230 static void invLx ( FieldMatrix< ctype, n, n > &L, FieldVector< ctype, n > &x )
232 for(
int i = 0; i < n; ++i )
234 for(
int j = 0; j < i; ++j )
235 x[ i ] -= L[ i ][ j ] * x[ j ];
236 x[ i ] /= L[ i ][ i ];
243 static void invLTx ( FieldMatrix< ctype, n, n > &L, FieldVector< ctype, n > &x )
245 for(
int i = n; i > 0; --i )
247 for(
int j = i; j < n; ++j )
248 x[ i-1 ] -= L[ j ][ i-1 ] * x[ j ];
249 x[ i-1 ] /= L[ i-1 ][ i-1 ];
256 static ctype spdDetA (
const FieldMatrix< ctype, n, n > &A )
258 FieldMatrix< ctype, n, n > L;
266 static ctype spdInvA ( FieldMatrix< ctype, n, n > &A )
268 FieldMatrix< ctype, n, n > L;
270 const ctype det = invL( L );
278 static bool spdInvAx ( FieldMatrix< ctype, n, n > &A, FieldVector< ctype, n > &x,
const bool checkSingular =
false )
280 FieldMatrix< ctype, n, n > L;
281 const bool invertible = cholesky_L( A, L, checkSingular );
282 if( ! invertible )
return invertible ;
289 template<
int m,
int n >
290 static ctype detATA (
const FieldMatrix< ctype, m, n > &A )
292 if constexpr( m >= n )
294 FieldMatrix< ctype, n, n > ata;
296 return spdDetA( ata );
307 template<
int m,
int n >
308 static ctype sqrtDetAAT (
const FieldMatrix< ctype, m, n > &A )
315 if constexpr( (n == 2) && (m == 2) )
318 return abs( A[ 0 ][ 0 ]*A[ 1 ][ 1 ] - A[ 1 ][ 0 ]*A[ 0 ][ 1 ] );
320 else if constexpr( (n == 3) && (m == 3) )
323 const ctype v0 = A[ 0 ][ 1 ] * A[ 1 ][ 2 ] - A[ 1 ][ 1 ] * A[ 0 ][ 2 ];
324 const ctype v1 = A[ 0 ][ 2 ] * A[ 1 ][ 0 ] - A[ 1 ][ 2 ] * A[ 0 ][ 0 ];
325 const ctype v2 = A[ 0 ][ 0 ] * A[ 1 ][ 1 ] - A[ 1 ][ 0 ] * A[ 0 ][ 1 ];
326 return abs( v0 * A[ 2 ][ 0 ] + v1 * A[ 2 ][ 1 ] + v2 * A[ 2 ][ 2 ] );
328 else if constexpr( (n == 3) && (m == 2) )
331 const ctype v0 = A[ 0 ][ 0 ] * A[ 1 ][ 1 ] - A[ 0 ][ 1 ] * A[ 1 ][ 0 ];
332 const ctype v1 = A[ 0 ][ 0 ] * A[ 1 ][ 2 ] - A[ 1 ][ 0 ] * A[ 0 ][ 2 ];
333 const ctype v2 = A[ 0 ][ 1 ] * A[ 1 ][ 2 ] - A[ 0 ][ 2 ] * A[ 1 ][ 1 ];
334 return sqrt( v0*v0 + v1*v1 + v2*v2);
336 else if constexpr( n >= m )
339 FieldMatrix< ctype, m, m > aat;
341 return spdDetA( aat );
349 template<
int m,
int n >
350 static ctype leftInvA (
const FieldMatrix< ctype, m, n > &A, FieldMatrix< ctype, n, m > &ret )
353 if constexpr( (n == 2) && (m == 2) )
355 const ctype det = (A[ 0 ][ 0 ]*A[ 1 ][ 1 ] - A[ 1 ][ 0 ]*A[ 0 ][ 1 ]);
356 const ctype detInv = ctype( 1 ) / det;
357 ret[ 0 ][ 0 ] = A[ 1 ][ 1 ] * detInv;
358 ret[ 1 ][ 1 ] = A[ 0 ][ 0 ] * detInv;
359 ret[ 1 ][ 0 ] = -A[ 1 ][ 0 ] * detInv;
360 ret[ 0 ][ 1 ] = -A[ 0 ][ 1 ] * detInv;
365 FieldMatrix< ctype, n, n > ata;
367 const ctype det = spdInvA( ata );
374 template<
int m,
int n >
375 static bool leftInvAx (
const FieldMatrix< ctype, m, n > &A,
const FieldVector< ctype, m > &x, FieldVector< ctype, n > &y )
377 static_assert((m >= n),
"Matrix has no left inverse.");
378 FieldMatrix< ctype, n, n > ata;
381 return spdInvAx( ata, y,
true );
385 template<
int m,
int n >
386 static ctype rightInvA (
const FieldMatrix< ctype, m, n > &A, FieldMatrix< ctype, n, m > &ret )
388 static_assert((n >= m),
"Matrix has no right inverse.");
390 if constexpr( (n == 2) && (m == 2) )
392 const ctype det = (A[ 0 ][ 0 ]*A[ 1 ][ 1 ] - A[ 1 ][ 0 ]*A[ 0 ][ 1 ]);
393 const ctype detInv = ctype( 1 ) / det;
394 ret[ 0 ][ 0 ] = A[ 1 ][ 1 ] * detInv;
395 ret[ 1 ][ 1 ] = A[ 0 ][ 0 ] * detInv;
396 ret[ 1 ][ 0 ] = -A[ 1 ][ 0 ] * detInv;
397 ret[ 0 ][ 1 ] = -A[ 0 ][ 1 ] * detInv;
402 FieldMatrix< ctype, m , m > aat;
404 const ctype det = spdInvA( aat );
405 ATBT( A , aat , ret );
411 template<
int m,
int n >
412 static bool xTRightInvA (
const FieldMatrix< ctype, m, n > &A,
const FieldVector< ctype, n > &x, FieldVector< ctype, m > &y )
414 static_assert((n >= m),
"Matrix has no right inverse.");
415 FieldMatrix< ctype, m, m > aat;
419 return spdInvAx( aat, y,
true );