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>
49 #include <blaze/math/Exception.h>
57 #include <blaze/util/Assert.h>
58 #include <blaze/util/NumericCast.h>
59 #include <blaze/util/Types.h>
60 
61 
62 namespace blaze {
63 
64 //=================================================================================================
65 //
66 // DETERMINANT FUNCTIONS
67 //
68 //=================================================================================================
69 
70 //*************************************************************************************************
73 template< typename MT, bool SO >
74 inline ElementType_t<MT> det( const DenseMatrix<MT,SO>& dm );
76 //*************************************************************************************************
77 
78 
79 //*************************************************************************************************
90 template< typename MT // Type of the dense matrix
91  , bool SO > // Storage order of the dense matrix
92 inline 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 //*************************************************************************************************
116 template< typename MT // Type of the dense matrix
117  , bool SO > // Storage order of the dense matrix
118 inline 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 //*************************************************************************************************
144 template< typename MT // Type of the dense matrix
145  , bool SO > // Storage order of the dense matrix
146 inline 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 //*************************************************************************************************
182 template< typename MT // Type of the dense matrix
183  , bool SO > // Storage order of the dense matrix
184 inline 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 //*************************************************************************************************
236 template< typename MT // Type of the dense matrix
237  , bool SO > // Storage order of the dense matrix
238 inline 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 //*************************************************************************************************
322 template< typename MT // Type of the dense matrix
323  , bool SO > // Storage order of the dense matrix
324 ElementType_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  int n ( numeric_cast<int>( A.rows() ) );
340  int lda ( numeric_cast<int>( A.spacing() ) );
341  int info( 0 );
342 
343  const std::unique_ptr<int[]> ipiv( new int[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 //*************************************************************************************************
382 template< 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
#define BLAZE_THROW_INVALID_ARGUMENT(MESSAGE)
Macro for the emission of a std::invalid_argument exception.This macro encapsulates the default way o...
Definition: Exception.h:235
Header file for auxiliary alias declarations.
#define BLAZE_CONSTRAINT_MUST_HAVE_MUTABLE_DATA_ACCESS(T)
Constraint on the data type.In case the given data type T does not provide low-level data access to m...
Definition: MutableDataAccess.h:61
Header file for basic type definitions.
ElementType_t< MT > det(const DenseMatrix< MT, SO > &dm)
Computation of the determinant of the given dense square matrix.
Definition: DMatDetExpr.h:384
#define BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE(T)
Constraint on the data type.In case the given data type T is not a dense, N-dimensional matrix type...
Definition: DenseMatrix.h:61
Cast operators for numeric types.
constexpr size_t columns(const Matrix< MT, SO > &matrix) noexcept
Returns the current number of columns of the matrix.
Definition: Matrix.h:514
Base class for dense matrices.The DenseMatrix class is a base class for all dense matrix classes...
Definition: DenseMatrix.h:80
typename T::ElementType ElementType_t
Alias declaration for nested ElementType type definitions.The ElementType_t alias declaration provide...
Definition: Aliases.h:170
Header file for the IsSquare type trait.
Constraint on the data type.
Constraint on the data type.
Namespace of the Blaze C++ math library.
Definition: Blaze.h:58
Header file for the DenseMatrix base class.
Header file for the IsUniTriangular type trait.
Header file for the IsStrictlyTriangular type trait.
Header file for the IsTriangular type trait.
Header file for the exception macros of the math module.
Header file for the RemoveAdaptor type trait.
Constraint on the data type.
Constraint on the data type.
void getrf(int m, int n, float *A, int lda, int *ipiv, int *info)
LAPACK kernel for the LU decomposition of the given dense general single precision column-major matri...
Definition: getrf.h:131
Header file for run time assertion macros.
#define BLAZE_CONSTRAINT_MUST_BE_BLAS_COMPATIBLE_TYPE(T)
Constraint on the data type.In case the given data type T is not a BLAS compatible data type (i...
Definition: BLASCompatible.h:61
#define BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION(T)
Constraint on the data type.In case the given data type T requires an intermediate evaluation within ...
Definition: RequiresEvaluation.h:81
constexpr size_t rows(const Matrix< MT, SO > &matrix) noexcept
Returns the current number of rows of the matrix.
Definition: Matrix.h:498
bool isSquare(const Matrix< MT, SO > &matrix) noexcept
Checks if the given matrix is a square matrix.
Definition: Matrix.h:951
Header file for the LAPACK LU decomposition functions (getrf)
#define BLAZE_INTERNAL_ASSERT(expr, msg)
Run time assertion macro for internal checks.In case of an invalid run time expression, the program execution is terminated. The BLAZE_INTERNAL_ASSERT macro can be disabled by setting the BLAZE_USER_ASSERTION flag to zero or by defining NDEBUG during the compilation.
Definition: Assert.h:101