Blaze 3.9
DMatDetExpr.h
Go to the documentation of this file.
1//=================================================================================================
33//=================================================================================================
34
35#ifndef _BLAZE_MATH_EXPRESSIONS_DMATDETEXPR_H_
36#define _BLAZE_MATH_EXPRESSIONS_DMATDETEXPR_H_
37
38
39//*************************************************************************************************
40// Includes
41//*************************************************************************************************
42
43#include <memory>
44#include <blaze/math/Aliases.h>
57#include <blaze/util/Assert.h>
59#include <blaze/util/Types.h>
60
61
62namespace blaze {
63
64//=================================================================================================
65//
66// DETERMINANT FUNCTIONS
67//
68//=================================================================================================
69
70//*************************************************************************************************
73template< typename MT, bool SO >
74inline ElementType_t<MT> det( const DenseMatrix<MT,SO>& dm );
76//*************************************************************************************************
77
78
79//*************************************************************************************************
90template< typename MT // Type of the dense matrix
91 , bool SO > // Storage order of the dense matrix
92inline ElementType_t<MT> det2x2( const DenseMatrix<MT,SO>& dm )
93{
94 BLAZE_INTERNAL_ASSERT( (*dm).rows() == 2UL, "Invalid number of rows detected" );
95 BLAZE_INTERNAL_ASSERT( (*dm).columns() == 2UL, "Invalid number of columns detected" );
96
97 CompositeType_t<MT> A( *dm );
98
99 return A(0,0)*A(1,1) - A(0,1)*A(1,0);
100}
102//*************************************************************************************************
103
104
105//*************************************************************************************************
116template< typename MT // Type of the dense matrix
117 , bool SO > // Storage order of the dense matrix
118inline ElementType_t<MT> det3x3( const DenseMatrix<MT,SO>& dm )
119{
120 BLAZE_INTERNAL_ASSERT( (*dm).rows() == 3UL, "Invalid number of rows detected" );
121 BLAZE_INTERNAL_ASSERT( (*dm).columns() == 3UL, "Invalid number of columns detected" );
122
123 CompositeType_t<MT> A( *dm );
124
125 return A(0,0) * ( A(1,1)*A(2,2) - A(1,2)*A(2,1) ) +
126 A(0,1) * ( A(1,2)*A(2,0) - A(1,0)*A(2,2) ) +
127 A(0,2) * ( A(1,0)*A(2,1) - A(1,1)*A(2,0) );
128}
130//*************************************************************************************************
131
132
133//*************************************************************************************************
144template< typename MT // Type of the dense matrix
145 , bool SO > // Storage order of the dense matrix
146inline ElementType_t<MT> det4x4( const DenseMatrix<MT,SO>& dm )
147{
148 BLAZE_INTERNAL_ASSERT( (*dm).rows() == 4UL, "Invalid number of rows detected" );
149 BLAZE_INTERNAL_ASSERT( (*dm).columns() == 4UL, "Invalid number of columns detected" );
150
151 using ET = ElementType_t<MT>;
152
153 CompositeType_t<MT> A( *dm );
154
155 const ET tmp1( A(2,2)*A(3,3) - A(2,3)*A(3,2) );
156 const ET tmp2( A(2,1)*A(3,3) - A(2,3)*A(3,1) );
157 const ET tmp3( A(2,1)*A(3,2) - A(2,2)*A(3,1) );
158 const ET tmp4( A(2,0)*A(3,3) - A(2,3)*A(3,0) );
159 const ET tmp5( A(2,0)*A(3,2) - A(2,2)*A(3,0) );
160 const ET tmp6( A(2,0)*A(3,1) - A(2,1)*A(3,0) );
161
162 return A(0,0) * ( A(1,1) * tmp1 - A(1,2) * tmp2 + A(1,3) * tmp3 ) -
163 A(0,1) * ( A(1,0) * tmp1 - A(1,2) * tmp4 + A(1,3) * tmp5 ) +
164 A(0,2) * ( A(1,0) * tmp2 - A(1,1) * tmp4 + A(1,3) * tmp6 ) -
165 A(0,3) * ( A(1,0) * tmp3 - A(1,1) * tmp5 + A(1,2) * tmp6 );
166}
168//*************************************************************************************************
169
170
171//*************************************************************************************************
182template< typename MT // Type of the dense matrix
183 , bool SO > // Storage order of the dense matrix
184inline ElementType_t<MT> det5x5( const DenseMatrix<MT,SO>& dm )
185{
186 BLAZE_INTERNAL_ASSERT( (*dm).rows() == 5UL, "Invalid number of rows detected" );
187 BLAZE_INTERNAL_ASSERT( (*dm).columns() == 5UL, "Invalid number of columns detected" );
188
189 using ET = ElementType_t<MT>;
190
191 CompositeType_t<MT> A( *dm );
192
193 const ET tmp1 ( A(3,3)*A(4,4) - A(3,4)*A(4,3) );
194 const ET tmp2 ( A(3,2)*A(4,4) - A(3,4)*A(4,2) );
195 const ET tmp3 ( A(3,2)*A(4,3) - A(3,3)*A(4,2) );
196 const ET tmp4 ( A(3,1)*A(4,4) - A(3,4)*A(4,1) );
197 const ET tmp5 ( A(3,1)*A(4,3) - A(3,3)*A(4,1) );
198 const ET tmp6 ( A(3,1)*A(4,2) - A(3,2)*A(4,1) );
199 const ET tmp7 ( A(3,0)*A(4,4) - A(3,4)*A(4,0) );
200 const ET tmp8 ( A(3,0)*A(4,3) - A(3,3)*A(4,0) );
201 const ET tmp9 ( A(3,0)*A(4,2) - A(3,2)*A(4,0) );
202 const ET tmp10( A(3,0)*A(4,1) - A(3,1)*A(4,0) );
203
204 const ET tmp11( A(2,2)*tmp1 - A(2,3)*tmp2 + A(2,4)*tmp3 );
205 const ET tmp12( A(2,1)*tmp1 - A(2,3)*tmp4 + A(2,4)*tmp5 );
206 const ET tmp13( A(2,1)*tmp2 - A(2,2)*tmp4 + A(2,4)*tmp6 );
207 const ET tmp14( A(2,1)*tmp3 - A(2,2)*tmp5 + A(2,3)*tmp6 );
208 const ET tmp15( A(2,0)*tmp1 - A(2,3)*tmp7 + A(2,4)*tmp8 );
209 const ET tmp16( A(2,0)*tmp2 - A(2,2)*tmp7 + A(2,4)*tmp9 );
210 const ET tmp17( A(2,0)*tmp3 - A(2,2)*tmp8 + A(2,3)*tmp9 );
211 const ET tmp18( A(2,0)*tmp4 - A(2,1)*tmp7 + A(2,4)*tmp10 );
212 const ET tmp19( A(2,0)*tmp5 - A(2,1)*tmp8 + A(2,3)*tmp10 );
213 const ET tmp20( A(2,0)*tmp6 - A(2,1)*tmp9 + A(2,2)*tmp10 );
214
215 return A(0,0) * ( A(1,1)*tmp11 - A(1,2)*tmp12 + A(1,3)*tmp13 - A(1,4)*tmp14 ) -
216 A(0,1) * ( A(1,0)*tmp11 - A(1,2)*tmp15 + A(1,3)*tmp16 - A(1,4)*tmp17 ) +
217 A(0,2) * ( A(1,0)*tmp12 - A(1,1)*tmp15 + A(1,3)*tmp18 - A(1,4)*tmp19 ) -
218 A(0,3) * ( A(1,0)*tmp13 - A(1,1)*tmp16 + A(1,2)*tmp18 - A(1,4)*tmp20 ) +
219 A(0,4) * ( A(1,0)*tmp14 - A(1,1)*tmp17 + A(1,2)*tmp19 - A(1,3)*tmp20 );
220}
222//*************************************************************************************************
223
224
225//*************************************************************************************************
236template< typename MT // Type of the dense matrix
237 , bool SO > // Storage order of the dense matrix
238inline ElementType_t<MT> det6x6( const DenseMatrix<MT,SO>& dm )
239{
240 BLAZE_INTERNAL_ASSERT( (*dm).rows() == 6UL, "Invalid number of rows detected" );
241 BLAZE_INTERNAL_ASSERT( (*dm).columns() == 6UL, "Invalid number of columns detected" );
242
243 using ET = ElementType_t<MT>;
244
245 CompositeType_t<MT> A( *dm );
246
247 const ET tmp1 ( A(4,4)*A(5,5) - A(4,5)*A(5,4) );
248 const ET tmp2 ( A(4,3)*A(5,5) - A(4,5)*A(5,3) );
249 const ET tmp3 ( A(4,3)*A(5,4) - A(4,4)*A(5,3) );
250 const ET tmp4 ( A(4,2)*A(5,5) - A(4,5)*A(5,2) );
251 const ET tmp5 ( A(4,2)*A(5,4) - A(4,4)*A(5,2) );
252 const ET tmp6 ( A(4,2)*A(5,3) - A(4,3)*A(5,2) );
253 const ET tmp7 ( A(4,1)*A(5,5) - A(4,5)*A(5,1) );
254 const ET tmp8 ( A(4,1)*A(5,4) - A(4,4)*A(5,1) );
255 const ET tmp9 ( A(4,1)*A(5,3) - A(4,3)*A(5,1) );
256 const ET tmp10( A(4,1)*A(5,2) - A(4,2)*A(5,1) );
257 const ET tmp11( A(4,0)*A(5,5) - A(4,5)*A(5,0) );
258 const ET tmp12( A(4,0)*A(5,4) - A(4,4)*A(5,0) );
259 const ET tmp13( A(4,0)*A(5,3) - A(4,3)*A(5,0) );
260 const ET tmp14( A(4,0)*A(5,2) - A(4,2)*A(5,0) );
261 const ET tmp15( A(4,0)*A(5,1) - A(4,1)*A(5,0) );
262
263 const ET tmp16( A(3,3)*tmp1 - A(3,4)*tmp2 + A(3,5)*tmp3 );
264 const ET tmp17( A(3,2)*tmp1 - A(3,4)*tmp4 + A(3,5)*tmp5 );
265 const ET tmp18( A(3,2)*tmp2 - A(3,3)*tmp4 + A(3,5)*tmp6 );
266 const ET tmp19( A(3,2)*tmp3 - A(3,3)*tmp5 + A(3,4)*tmp6 );
267 const ET tmp20( A(3,1)*tmp1 - A(3,4)*tmp7 + A(3,5)*tmp8 );
268 const ET tmp21( A(3,1)*tmp2 - A(3,3)*tmp7 + A(3,5)*tmp9 );
269 const ET tmp22( A(3,1)*tmp3 - A(3,3)*tmp8 + A(3,4)*tmp9 );
270 const ET tmp23( A(3,1)*tmp4 - A(3,2)*tmp7 + A(3,5)*tmp10 );
271 const ET tmp24( A(3,1)*tmp5 - A(3,2)*tmp8 + A(3,4)*tmp10 );
272 const ET tmp25( A(3,1)*tmp6 - A(3,2)*tmp9 + A(3,3)*tmp10 );
273 const ET tmp26( A(3,0)*tmp1 - A(3,4)*tmp11 + A(3,5)*tmp12 );
274 const ET tmp27( A(3,0)*tmp2 - A(3,3)*tmp11 + A(3,5)*tmp13 );
275 const ET tmp28( A(3,0)*tmp3 - A(3,3)*tmp12 + A(3,4)*tmp13 );
276 const ET tmp29( A(3,0)*tmp4 - A(3,2)*tmp11 + A(3,5)*tmp14 );
277 const ET tmp30( A(3,0)*tmp5 - A(3,2)*tmp12 + A(3,4)*tmp14 );
278 const ET tmp31( A(3,0)*tmp6 - A(3,2)*tmp13 + A(3,3)*tmp14 );
279 const ET tmp32( A(3,0)*tmp7 - A(3,1)*tmp11 + A(3,5)*tmp15 );
280 const ET tmp33( A(3,0)*tmp8 - A(3,1)*tmp12 + A(3,4)*tmp15 );
281 const ET tmp34( A(3,0)*tmp9 - A(3,1)*tmp13 + A(3,3)*tmp15 );
282 const ET tmp35( A(3,0)*tmp10 - A(3,1)*tmp14 + A(3,2)*tmp15 );
283
284 const ET tmp36( A(2,2)*tmp16 - A(2,3)*tmp17 + A(2,4)*tmp18 - A(2,5)*tmp19 );
285 const ET tmp37( A(2,1)*tmp16 - A(2,3)*tmp20 + A(2,4)*tmp21 - A(2,5)*tmp22 );
286 const ET tmp38( A(2,1)*tmp17 - A(2,2)*tmp20 + A(2,4)*tmp23 - A(2,5)*tmp24 );
287 const ET tmp39( A(2,1)*tmp18 - A(2,2)*tmp21 + A(2,3)*tmp23 - A(2,5)*tmp25 );
288 const ET tmp40( A(2,1)*tmp19 - A(2,2)*tmp22 + A(2,3)*tmp24 - A(2,4)*tmp25 );
289 const ET tmp41( A(2,0)*tmp16 - A(2,3)*tmp26 + A(2,4)*tmp27 - A(2,5)*tmp28 );
290 const ET tmp42( A(2,0)*tmp17 - A(2,2)*tmp26 + A(2,4)*tmp29 - A(2,5)*tmp30 );
291 const ET tmp43( A(2,0)*tmp18 - A(2,2)*tmp27 + A(2,3)*tmp29 - A(2,5)*tmp31 );
292 const ET tmp44( A(2,0)*tmp19 - A(2,2)*tmp28 + A(2,3)*tmp30 - A(2,4)*tmp31 );
293 const ET tmp45( A(2,0)*tmp20 - A(2,1)*tmp26 + A(2,4)*tmp32 - A(2,5)*tmp33 );
294 const ET tmp46( A(2,0)*tmp21 - A(2,1)*tmp27 + A(2,3)*tmp32 - A(2,5)*tmp34 );
295 const ET tmp47( A(2,0)*tmp22 - A(2,1)*tmp28 + A(2,3)*tmp33 - A(2,4)*tmp34 );
296 const ET tmp48( A(2,0)*tmp23 - A(2,1)*tmp29 + A(2,2)*tmp32 - A(2,5)*tmp35 );
297 const ET tmp49( A(2,0)*tmp24 - A(2,1)*tmp30 + A(2,2)*tmp33 - A(2,4)*tmp35 );
298 const ET tmp50( A(2,0)*tmp25 - A(2,1)*tmp31 + A(2,2)*tmp34 - A(2,3)*tmp35 );
299
300 return A(0,0) * ( A(1,1)*tmp36 - A(1,2)*tmp37 + A(1,3)*tmp38 - A(1,4)*tmp39 + A(1,5)*tmp40 ) -
301 A(0,1) * ( A(1,0)*tmp36 - A(1,2)*tmp41 + A(1,3)*tmp42 - A(1,4)*tmp43 + A(1,5)*tmp44 ) +
302 A(0,2) * ( A(1,0)*tmp37 - A(1,1)*tmp41 + A(1,3)*tmp45 - A(1,4)*tmp46 + A(1,5)*tmp47 ) -
303 A(0,3) * ( A(1,0)*tmp38 - A(1,1)*tmp42 + A(1,2)*tmp45 - A(1,4)*tmp48 + A(1,5)*tmp49 ) +
304 A(0,4) * ( A(1,0)*tmp39 - A(1,1)*tmp43 + A(1,2)*tmp46 - A(1,3)*tmp48 + A(1,5)*tmp50 ) -
305 A(0,5) * ( A(1,0)*tmp40 - A(1,1)*tmp44 + A(1,2)*tmp47 - A(1,3)*tmp49 + A(1,4)*tmp50 );
306}
308//*************************************************************************************************
309
310
311//*************************************************************************************************
322template< typename MT // Type of the dense matrix
323 , bool SO > // Storage order of the dense matrix
324ElementType_t<MT> detNxN( const DenseMatrix<MT,SO>& dm )
325{
326 BLAZE_INTERNAL_ASSERT( isSquare( *dm ), "Non-square symmetric matrix detected" );
327
328 using RT = ResultType_t<MT>;
329 using ET = ElementType_t<MT>;
330 using URT = RemoveAdaptor_t<RT>;
331
336
337 URT A( *dm );
338
339 blas_int_t n ( numeric_cast<blas_int_t>( A.rows() ) );
340 blas_int_t lda ( numeric_cast<blas_int_t>( A.spacing() ) );
341 blas_int_t info( 0 );
342
343 const std::unique_ptr<blas_int_t[]> ipiv( new blas_int_t[n] );
344
345 getrf( n, n, A.data(), lda, ipiv.get(), &info );
346
347 if( info > 0 ) {
348 return ET(0);
349 }
350
351 ET determinant = ET(1);
352
353 for( int i=0; i<n; ++i ) {
354 determinant *= ( ipiv[i] == (i+1) )?( A(i,i) ):( -A(i,i) );
355 }
356
357 return determinant;
358}
360//*************************************************************************************************
361
362
363//*************************************************************************************************
382template< typename MT // Type of the dense matrix
383 , bool SO > // Storage order of the dense matrix
385{
386 using ET = ElementType_t<MT>;
387
388 if( !isSquare( *dm ) ) {
389 BLAZE_THROW_INVALID_ARGUMENT( "Invalid non-square matrix provided" );
390 }
391
392 const size_t N( (*dm).rows() );
393
394 if( IsStrictlyTriangular_v<MT> || N == 0UL ) {
395 return ET(0);
396 }
397
398 if( IsUniTriangular_v<MT> ) {
399 return ET(1);
400 }
401
402 if( N == 1UL ) {
403 return (*dm)(0,0);
404 }
405
406 if( IsTriangular_v<MT> ) {
407 ET determinant( (*dm)(0,0) );
408
409 for( size_t i=1UL; i<N; ++i ) {
410 determinant *= (*dm)(i,i);
411 }
412
413 return determinant;
414 }
415
416 switch( N ) {
417 case 2UL: return det2x2( *dm );
418 case 3UL: return det3x3( *dm );
419 case 4UL: return det4x4( *dm );
420 case 5UL: return det5x5( *dm );
421 case 6UL: return det6x6( *dm );
422 default : return detNxN( *dm );
423 }
424}
425//*************************************************************************************************
426
427} // namespace blaze
428
429#endif
Header file for auxiliary alias declarations.
typename T::ElementType ElementType_t
Alias declaration for nested ElementType type definitions.
Definition: Aliases.h:190
Header file for run time assertion macros.
Constraint on the data type.
Header file for the IsSquare type trait.
Header file for the IsStrictlyTriangular type trait.
Header file for the IsTriangular type trait.
Header file for the IsUniTriangular type trait.
Constraint on the data type.
Cast operators for numeric types.
Header file for the RemoveAdaptor type trait.
Base class for dense matrices.
Definition: DenseMatrix.h:82
Constraint on the data type.
Constraint on the data type.
Header file for the DenseMatrix base class.
Header file for the LAPACK LU decomposition functions (getrf)
ElementType_t< MT > det(const DenseMatrix< MT, SO > &dm)
Computation of the determinant of the given dense square matrix.
Definition: DMatDetExpr.h:384
void getrf(blas_int_t m, blas_int_t n, float *A, blas_int_t lda, blas_int_t *ipiv, blas_int_t *info)
LAPACK kernel for the LU decomposition of the given dense general single precision column-major matri...
Definition: getrf.h:140
#define BLAZE_CONSTRAINT_MUST_BE_BLAS_COMPATIBLE_TYPE(T)
Constraint on the data type.
Definition: BLASCompatible.h:61
#define BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION(T)
Constraint on the data type.
Definition: RequiresEvaluation.h:81
#define BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE(T)
Constraint on the data type.
Definition: DenseMatrix.h:61
#define BLAZE_CONSTRAINT_MUST_HAVE_MUTABLE_DATA_ACCESS(T)
Constraint on the data type.
Definition: MutableDataAccess.h:61
int32_t blas_int_t
Signed integer type used in the BLAS/LAPACK wrapper functions.
Definition: Types.h:64
bool isSquare(const Matrix< MT, SO > &matrix) noexcept
Checks if the given matrix is a square matrix.
Definition: Matrix.h:1383
#define BLAZE_INTERNAL_ASSERT(expr, msg)
Run time assertion macro for internal checks.
Definition: Assert.h:101
#define BLAZE_THROW_INVALID_ARGUMENT(MESSAGE)
Macro for the emission of a std::invalid_argument exception.
Definition: Exception.h:235
Header file for the exception macros of the math module.
Header file for basic type definitions.