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 <boost/cast.hpp>
55 #include <blaze/util/Assert.h>
56 #include <blaze/util/Exception.h>
57 #include <blaze/util/Types.h>
58 #include <blaze/util/UniqueArray.h>
59 
60 
61 namespace blaze {
62 
63 //=================================================================================================
64 //
65 // DETERMINANT FUNCTIONS
66 //
67 //=================================================================================================
68 
69 //*************************************************************************************************
72 template< typename MT, bool SO >
73 inline typename MT::ElementType det( const DenseMatrix<MT,SO>& dm );
75 //*************************************************************************************************
76 
77 
78 //*************************************************************************************************
89 template< typename MT // Type of the dense matrix
90  , bool SO > // Storage order of the dense matrix
91 inline typename MT::ElementType det2x2( const DenseMatrix<MT,SO>& dm )
92 {
93  BLAZE_INTERNAL_ASSERT( (~dm).rows() == 2UL, "Invalid number of rows detected" );
94  BLAZE_INTERNAL_ASSERT( (~dm).columns() == 2UL, "Invalid number of columns detected" );
95 
96  typename MT::CompositeType A( ~dm );
97 
98  return A(0,0)*A(1,1) - A(0,1)*A(1,0);
99 }
101 //*************************************************************************************************
102 
103 
104 //*************************************************************************************************
115 template< typename MT // Type of the dense matrix
116  , bool SO > // Storage order of the dense matrix
117 inline typename MT::ElementType det3x3( const DenseMatrix<MT,SO>& dm )
118 {
119  BLAZE_INTERNAL_ASSERT( (~dm).rows() == 3UL, "Invalid number of rows detected" );
120  BLAZE_INTERNAL_ASSERT( (~dm).columns() == 3UL, "Invalid number of columns detected" );
121 
122  typename MT::CompositeType A( ~dm );
123 
124  return A(0,0) * ( A(1,1)*A(2,2) - A(1,2)*A(2,1) ) +
125  A(0,1) * ( A(1,2)*A(2,0) - A(1,0)*A(2,2) ) +
126  A(0,2) * ( A(1,0)*A(2,1) - A(1,1)*A(2,0) );
127 }
129 //*************************************************************************************************
130 
131 
132 //*************************************************************************************************
143 template< typename MT // Type of the dense matrix
144  , bool SO > // Storage order of the dense matrix
145 inline typename MT::ElementType det4x4( const DenseMatrix<MT,SO>& dm )
146 {
147  BLAZE_INTERNAL_ASSERT( (~dm).rows() == 4UL, "Invalid number of rows detected" );
148  BLAZE_INTERNAL_ASSERT( (~dm).columns() == 4UL, "Invalid number of columns detected" );
149 
150  typedef typename MT::ElementType ET;
151 
152  typename MT::CompositeType A( ~dm );
153 
154  const ET tmp1( A(2,2)*A(3,3) - A(2,3)*A(3,2) );
155  const ET tmp2( A(2,1)*A(3,3) - A(2,3)*A(3,1) );
156  const ET tmp3( A(2,1)*A(3,2) - A(2,2)*A(3,1) );
157  const ET tmp4( A(2,0)*A(3,3) - A(2,3)*A(3,0) );
158  const ET tmp5( A(2,0)*A(3,2) - A(2,2)*A(3,0) );
159  const ET tmp6( A(2,0)*A(3,1) - A(2,1)*A(3,0) );
160 
161  return A(0,0) * ( A(1,1) * tmp1 - A(1,2) * tmp2 + A(1,3) * tmp3 ) -
162  A(0,1) * ( A(1,0) * tmp1 - A(1,2) * tmp4 + A(1,3) * tmp5 ) +
163  A(0,2) * ( A(1,0) * tmp2 - A(1,1) * tmp4 + A(1,3) * tmp6 ) -
164  A(0,3) * ( A(1,0) * tmp3 - A(1,1) * tmp5 + A(1,2) * tmp6 );
165 }
167 //*************************************************************************************************
168 
169 
170 //*************************************************************************************************
181 template< typename MT // Type of the dense matrix
182  , bool SO > // Storage order of the dense matrix
183 inline typename MT::ElementType det5x5( const DenseMatrix<MT,SO>& dm )
184 {
185  BLAZE_INTERNAL_ASSERT( (~dm).rows() == 5UL, "Invalid number of rows detected" );
186  BLAZE_INTERNAL_ASSERT( (~dm).columns() == 5UL, "Invalid number of columns detected" );
187 
188  typedef typename MT::ElementType ET;
189 
190  typename MT::CompositeType A( ~dm );
191 
192  const ET tmp1 ( A(3,3)*A(4,4) - A(3,4)*A(4,3) );
193  const ET tmp2 ( A(3,2)*A(4,4) - A(3,4)*A(4,2) );
194  const ET tmp3 ( A(3,2)*A(4,3) - A(3,3)*A(4,2) );
195  const ET tmp4 ( A(3,1)*A(4,4) - A(3,4)*A(4,1) );
196  const ET tmp5 ( A(3,1)*A(4,3) - A(3,3)*A(4,1) );
197  const ET tmp6 ( A(3,1)*A(4,2) - A(3,2)*A(4,1) );
198  const ET tmp7 ( A(3,0)*A(4,4) - A(3,4)*A(4,0) );
199  const ET tmp8 ( A(3,0)*A(4,3) - A(3,3)*A(4,0) );
200  const ET tmp9 ( A(3,0)*A(4,2) - A(3,2)*A(4,0) );
201  const ET tmp10( A(3,0)*A(4,1) - A(3,1)*A(4,0) );
202 
203  const ET tmp11( A(2,2)*tmp1 - A(2,3)*tmp2 + A(2,4)*tmp3 );
204  const ET tmp12( A(2,1)*tmp1 - A(2,3)*tmp4 + A(2,4)*tmp5 );
205  const ET tmp13( A(2,1)*tmp2 - A(2,2)*tmp4 + A(2,4)*tmp6 );
206  const ET tmp14( A(2,1)*tmp3 - A(2,2)*tmp5 + A(2,3)*tmp6 );
207  const ET tmp15( A(2,0)*tmp1 - A(2,3)*tmp7 + A(2,4)*tmp8 );
208  const ET tmp16( A(2,0)*tmp2 - A(2,2)*tmp7 + A(2,4)*tmp9 );
209  const ET tmp17( A(2,0)*tmp3 - A(2,2)*tmp8 + A(2,3)*tmp9 );
210  const ET tmp18( A(2,0)*tmp4 - A(2,1)*tmp7 + A(2,4)*tmp10 );
211  const ET tmp19( A(2,0)*tmp5 - A(2,1)*tmp8 + A(2,3)*tmp10 );
212  const ET tmp20( A(2,0)*tmp6 - A(2,1)*tmp9 + A(2,2)*tmp10 );
213 
214  return A(0,0) * ( A(1,1)*tmp11 - A(1,2)*tmp12 + A(1,3)*tmp13 - A(1,4)*tmp14 ) -
215  A(0,1) * ( A(1,0)*tmp11 - A(1,2)*tmp15 + A(1,3)*tmp16 - A(1,4)*tmp17 ) +
216  A(0,2) * ( A(1,0)*tmp12 - A(1,1)*tmp15 + A(1,3)*tmp18 - A(1,4)*tmp19 ) -
217  A(0,3) * ( A(1,0)*tmp13 - A(1,1)*tmp16 + A(1,2)*tmp18 - A(1,4)*tmp20 ) +
218  A(0,4) * ( A(1,0)*tmp14 - A(1,1)*tmp17 + A(1,2)*tmp19 - A(1,3)*tmp20 );
219 }
221 //*************************************************************************************************
222 
223 
224 //*************************************************************************************************
235 template< typename MT // Type of the dense matrix
236  , bool SO > // Storage order of the dense matrix
237 inline typename MT::ElementType det6x6( const DenseMatrix<MT,SO>& dm )
238 {
239  BLAZE_INTERNAL_ASSERT( (~dm).rows() == 6UL, "Invalid number of rows detected" );
240  BLAZE_INTERNAL_ASSERT( (~dm).columns() == 6UL, "Invalid number of columns detected" );
241 
242  typedef typename MT::ElementType ET;
243 
244  typename MT::CompositeType A( ~dm );
245 
246  const ET tmp1 ( A(4,4)*A(5,5) - A(4,5)*A(5,4) );
247  const ET tmp2 ( A(4,3)*A(5,5) - A(4,5)*A(5,3) );
248  const ET tmp3 ( A(4,3)*A(5,4) - A(4,4)*A(5,3) );
249  const ET tmp4 ( A(4,2)*A(5,5) - A(4,5)*A(5,2) );
250  const ET tmp5 ( A(4,2)*A(5,4) - A(4,4)*A(5,2) );
251  const ET tmp6 ( A(4,2)*A(5,3) - A(4,3)*A(5,2) );
252  const ET tmp7 ( A(4,1)*A(5,5) - A(4,5)*A(5,1) );
253  const ET tmp8 ( A(4,1)*A(5,4) - A(4,4)*A(5,1) );
254  const ET tmp9 ( A(4,1)*A(5,3) - A(4,3)*A(5,1) );
255  const ET tmp10( A(4,1)*A(5,2) - A(4,2)*A(5,1) );
256  const ET tmp11( A(4,0)*A(5,5) - A(4,5)*A(5,0) );
257  const ET tmp12( A(4,0)*A(5,4) - A(4,4)*A(5,0) );
258  const ET tmp13( A(4,0)*A(5,3) - A(4,3)*A(5,0) );
259  const ET tmp14( A(4,0)*A(5,2) - A(4,2)*A(5,0) );
260  const ET tmp15( A(4,0)*A(5,1) - A(4,1)*A(5,0) );
261 
262  const ET tmp16( A(3,3)*tmp1 - A(3,4)*tmp2 + A(3,5)*tmp3 );
263  const ET tmp17( A(3,2)*tmp1 - A(3,4)*tmp4 + A(3,5)*tmp5 );
264  const ET tmp18( A(3,2)*tmp2 - A(3,3)*tmp4 + A(3,5)*tmp6 );
265  const ET tmp19( A(3,2)*tmp3 - A(3,3)*tmp5 + A(3,4)*tmp6 );
266  const ET tmp20( A(3,1)*tmp1 - A(3,4)*tmp7 + A(3,5)*tmp8 );
267  const ET tmp21( A(3,1)*tmp2 - A(3,3)*tmp7 + A(3,5)*tmp9 );
268  const ET tmp22( A(3,1)*tmp3 - A(3,3)*tmp8 + A(3,4)*tmp9 );
269  const ET tmp23( A(3,1)*tmp4 - A(3,2)*tmp7 + A(3,5)*tmp10 );
270  const ET tmp24( A(3,1)*tmp5 - A(3,2)*tmp8 + A(3,4)*tmp10 );
271  const ET tmp25( A(3,1)*tmp6 - A(3,2)*tmp9 + A(3,3)*tmp10 );
272  const ET tmp26( A(3,0)*tmp1 - A(3,4)*tmp11 + A(3,5)*tmp12 );
273  const ET tmp27( A(3,0)*tmp2 - A(3,3)*tmp11 + A(3,5)*tmp13 );
274  const ET tmp28( A(3,0)*tmp3 - A(3,3)*tmp12 + A(3,4)*tmp13 );
275  const ET tmp29( A(3,0)*tmp4 - A(3,2)*tmp11 + A(3,5)*tmp14 );
276  const ET tmp30( A(3,0)*tmp5 - A(3,2)*tmp12 + A(3,4)*tmp14 );
277  const ET tmp31( A(3,0)*tmp6 - A(3,2)*tmp13 + A(3,3)*tmp14 );
278  const ET tmp32( A(3,0)*tmp7 - A(3,1)*tmp11 + A(3,5)*tmp15 );
279  const ET tmp33( A(3,0)*tmp8 - A(3,1)*tmp12 + A(3,4)*tmp15 );
280  const ET tmp34( A(3,0)*tmp9 - A(3,1)*tmp13 + A(3,3)*tmp15 );
281  const ET tmp35( A(3,0)*tmp10 - A(3,1)*tmp14 + A(3,2)*tmp15 );
282 
283  const ET tmp36( A(2,2)*tmp16 - A(2,3)*tmp17 + A(2,4)*tmp18 - A(2,5)*tmp19 );
284  const ET tmp37( A(2,1)*tmp16 - A(2,3)*tmp20 + A(2,4)*tmp21 - A(2,5)*tmp22 );
285  const ET tmp38( A(2,1)*tmp17 - A(2,2)*tmp20 + A(2,4)*tmp23 - A(2,5)*tmp24 );
286  const ET tmp39( A(2,1)*tmp18 - A(2,2)*tmp21 + A(2,3)*tmp23 - A(2,5)*tmp25 );
287  const ET tmp40( A(2,1)*tmp19 - A(2,2)*tmp22 + A(2,3)*tmp24 - A(2,4)*tmp25 );
288  const ET tmp41( A(2,0)*tmp16 - A(2,3)*tmp26 + A(2,4)*tmp27 - A(2,5)*tmp28 );
289  const ET tmp42( A(2,0)*tmp17 - A(2,2)*tmp26 + A(2,4)*tmp29 - A(2,5)*tmp30 );
290  const ET tmp43( A(2,0)*tmp18 - A(2,2)*tmp27 + A(2,3)*tmp29 - A(2,5)*tmp31 );
291  const ET tmp44( A(2,0)*tmp19 - A(2,2)*tmp28 + A(2,3)*tmp30 - A(2,4)*tmp31 );
292  const ET tmp45( A(2,0)*tmp20 - A(2,1)*tmp26 + A(2,4)*tmp32 - A(2,5)*tmp33 );
293  const ET tmp46( A(2,0)*tmp21 - A(2,1)*tmp27 + A(2,3)*tmp32 - A(2,5)*tmp34 );
294  const ET tmp47( A(2,0)*tmp22 - A(2,1)*tmp28 + A(2,3)*tmp33 - A(2,4)*tmp34 );
295  const ET tmp48( A(2,0)*tmp23 - A(2,1)*tmp29 + A(2,2)*tmp32 - A(2,5)*tmp35 );
296  const ET tmp49( A(2,0)*tmp24 - A(2,1)*tmp30 + A(2,2)*tmp33 - A(2,4)*tmp35 );
297  const ET tmp50( A(2,0)*tmp25 - A(2,1)*tmp31 + A(2,2)*tmp34 - A(2,3)*tmp35 );
298 
299  return A(0,0) * ( A(1,1)*tmp36 - A(1,2)*tmp37 + A(1,3)*tmp38 - A(1,4)*tmp39 + A(1,5)*tmp40 ) -
300  A(0,1) * ( A(1,0)*tmp36 - A(1,2)*tmp41 + A(1,3)*tmp42 - A(1,4)*tmp43 + A(1,5)*tmp44 ) +
301  A(0,2) * ( A(1,0)*tmp37 - A(1,1)*tmp41 + A(1,3)*tmp45 - A(1,4)*tmp46 + A(1,5)*tmp47 ) -
302  A(0,3) * ( A(1,0)*tmp38 - A(1,1)*tmp42 + A(1,2)*tmp45 - A(1,4)*tmp48 + A(1,5)*tmp49 ) +
303  A(0,4) * ( A(1,0)*tmp39 - A(1,1)*tmp43 + A(1,2)*tmp46 - A(1,3)*tmp48 + A(1,5)*tmp50 ) -
304  A(0,5) * ( A(1,0)*tmp40 - A(1,1)*tmp44 + A(1,2)*tmp47 - A(1,3)*tmp49 + A(1,4)*tmp50 );
305 }
307 //*************************************************************************************************
308 
309 
310 //*************************************************************************************************
321 template< typename MT // Type of the dense matrix
322  , bool SO > // Storage order of the dense matrix
323 typename MT::ElementType detNxN( const DenseMatrix<MT,SO>& dm )
324 {
325  BLAZE_INTERNAL_ASSERT( isSquare( ~dm ), "Non-square symmetric matrix detected" );
326 
327  typedef typename MT::ResultType RT;
328  typedef typename MT::ElementType ET;
329  typedef typename RemoveAdaptor<RT>::Type URT;
330 
335 
336  URT A( ~dm );
337 
338  int n ( boost::numeric_cast<int>( A.rows() ) );
339  int lda ( boost::numeric_cast<int>( A.spacing() ) );
340  int info( 0 );
341 
342  const UniqueArray<int> ipiv( new int[n] );
343 
344  getrf( n, n, A.data(), lda, ipiv.get(), &info );
345 
346  if( info > 0 ) {
347  return ET(0);
348  }
349 
350  ET determinant = ET(1);
351 
352  for( int i=0; i<n; ++i ) {
353  determinant *= ( ipiv[i] == (i+1) )?( A(i,i) ):( -A(i,i) );
354  }
355 
356  return determinant;
357 }
359 //*************************************************************************************************
360 
361 
362 //*************************************************************************************************
380 template< typename MT // Type of the dense matrix
381  , bool SO > // Storage order of the dense matrix
382 inline typename MT::ElementType det( const DenseMatrix<MT,SO>& dm )
383 {
384  typedef typename MT::ElementType ET;
385 
386  if( !isSquare( ~dm ) ) {
387  BLAZE_THROW_INVALID_ARGUMENT( "Invalid non-square matrix provided" );
388  }
389 
390  const size_t N( (~dm).rows() );
391 
392  if( IsStrictlyTriangular<MT>::value || N == 0UL ) {
393  return ET(0);
394  }
395 
397  return ET(1);
398  }
399 
400  if( N == 1UL ) {
401  return (~dm)(0,0);
402  }
403 
405  ET determinant( (~dm)(0,0) );
406 
407  for( size_t i=1UL; i<N; ++i ) {
408  determinant *= (~dm)(i,i);
409  }
410 
411  return determinant;
412  }
413 
414  switch( N ) {
415  case 2UL: return det2x2( ~dm );
416  case 3UL: return det3x3( ~dm );
417  case 4UL: return det4x4( ~dm );
418  case 5UL: return det5x5( ~dm );
419  case 6UL: return det6x6( ~dm );
420  default : return detNxN( ~dm );
421  }
422 }
423 //*************************************************************************************************
424 
425 } // namespace blaze
426 
427 #endif
#define BLAZE_THROW_INVALID_ARGUMENT(MESSAGE)
Macro for the emission of a std::invalid_argument exceptionThis macro encapsulates the default way of...
Definition: Exception.h:187
Log level for high-level information.
Definition: LogLevel.h:80
#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:79
Compile time check for triangular matrix types.This type trait tests whether or not the given templat...
Definition: IsTriangular.h:105
Header file for basic type definitions.
BLAZE_ALWAYS_INLINE bool isSquare(const Matrix< MT, SO > &matrix)
Checks if the given matrix is a square matrix.
Definition: Matrix.h:603
#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:79
MT::ElementType det(const DenseMatrix< MT, SO > &dm)
Computation of the determinant of the given dense square matrix.
Definition: DMatDetExpr.h:382
const This & CompositeType
Data type for composite expression templates.
Definition: CompressedMatrix.h:2588
BLAZE_ALWAYS_INLINE size_t rows(const Matrix< MT, SO > &matrix)
Returns the current number of rows of the matrix.
Definition: Matrix.h:308
Base class for dense matrices.The DenseMatrix class is a base class for all dense matrix classes...
Definition: DenseMatrix.h:70
Header file for the IsSquare type trait.
Constraint on the data type.
Namespace of the Blaze C++ math library.
Definition: Blaze.h:57
Header file for the DenseMatrix base class.
Compile time check for strictly triangular matrix types.This type trait tests whether or not the give...
Definition: IsStrictlyTriangular.h:105
Header file for the IsUniTriangular type trait.
Header file for the IsStrictlyTriangular type trait.
Header file for the IsTriangular type trait.
Type ElementType
Type of the sparse matrix elements.
Definition: CompressedMatrix.h:2586
Constraint on the data type.
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:139
Header file for run time assertion macros.
Header file for the UniqueArray smart pointer class.
#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:79
#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:118
This ResultType
Result type for expression template evaluations.
Definition: CompressedMatrix.h:2583
BLAZE_ALWAYS_INLINE size_t columns(const Matrix< MT, SO > &matrix)
Returns the current number of columns of the matrix.
Definition: Matrix.h:324
Header file for exception macros.
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
Compile time check for unitriangular matrix types.This type trait tests whether or not the given temp...
Definition: IsUniTriangular.h:105