DMatSMatMultExpr.h
Go to the documentation of this file.
1 //=================================================================================================
33 //=================================================================================================
34 
35 #ifndef _BLAZE_MATH_EXPRESSIONS_DMATSMATMULTEXPR_H_
36 #define _BLAZE_MATH_EXPRESSIONS_DMATSMATMULTEXPR_H_
37 
38 
39 //*************************************************************************************************
40 // Includes
41 //*************************************************************************************************
42 
54 #include <blaze/math/Functions.h>
56 #include <blaze/math/shims/Reset.h>
95 #include <blaze/util/Assert.h>
97 #include <blaze/util/DisableIf.h>
98 #include <blaze/util/EnableIf.h>
99 #include <blaze/util/Exception.h>
100 #include <blaze/util/InvalidType.h>
102 #include <blaze/util/mpl/And.h>
103 #include <blaze/util/mpl/Or.h>
104 #include <blaze/util/SelectType.h>
105 #include <blaze/util/Types.h>
107 
108 
109 namespace blaze {
110 
111 //=================================================================================================
112 //
113 // CLASS DMATSMATMULTEXPR
114 //
115 //=================================================================================================
116 
117 //*************************************************************************************************
124 template< typename MT1 // Type of the left-hand side dense matrix
125  , typename MT2 > // Type of the right-hand side sparse matrix
126 class DMatSMatMultExpr : public DenseMatrix< DMatSMatMultExpr<MT1,MT2>, false >
127  , private MatMatMultExpr
128  , private Computation
129 {
130  private:
131  //**Type definitions****************************************************************************
132  typedef typename MT1::ResultType RT1;
133  typedef typename MT2::ResultType RT2;
134  typedef typename RT1::ElementType ET1;
135  typedef typename RT2::ElementType ET2;
136  typedef typename MT1::CompositeType CT1;
137  typedef typename MT2::CompositeType CT2;
138  //**********************************************************************************************
139 
140  //**********************************************************************************************
143  //**********************************************************************************************
144 
145  //**********************************************************************************************
147  enum { evaluateRight = IsComputation<MT2>::value || RequiresEvaluation<MT2>::value };
148  //**********************************************************************************************
149 
150  //**********************************************************************************************
152 
157  template< typename T1, typename T2, typename T3 >
158  struct CanExploitSymmetry {
159  enum { value = ( IsSymmetric<T2>::value || IsSymmetric<T3>::value ) };
160  };
162  //**********************************************************************************************
163 
164  //**********************************************************************************************
166 
170  template< typename T1, typename T2, typename T3 >
171  struct IsEvaluationRequired {
172  enum { value = ( evaluateLeft || evaluateRight ) &&
173  !CanExploitSymmetry<T1,T2,T3>::value };
174  };
176  //**********************************************************************************************
177 
178  //**********************************************************************************************
180 
183  template< typename T1, typename T2, typename T3 >
184  struct UseOptimizedKernel {
185  enum { value = useOptimizedKernels &&
186  !IsDiagonal<T2>::value &&
187  !IsResizable<typename T1::ElementType>::value };
188  };
190  //**********************************************************************************************
191 
192  //**********************************************************************************************
194 
197  template< typename T1, typename T2, typename T3 >
198  struct UseDefaultKernel {
199  enum { value = !UseOptimizedKernel<T1,T2,T3>::value };
200  };
202  //**********************************************************************************************
203 
204  public:
205  //**Type definitions****************************************************************************
211  typedef const ElementType ReturnType;
212  typedef const ResultType CompositeType;
213 
215  typedef typename SelectType< IsExpression<MT1>::value, const MT1, const MT1& >::Type LeftOperand;
216 
218  typedef typename SelectType< IsExpression<MT2>::value, const MT2, const MT2& >::Type RightOperand;
219 
222 
225  //**********************************************************************************************
226 
227  //**Compilation flags***************************************************************************
229  enum { vectorizable = 0 };
230 
232  enum { smpAssignable = !evaluateLeft && MT1::smpAssignable &&
233  !evaluateRight && MT2::smpAssignable };
234  //**********************************************************************************************
235 
236  //**Constructor*********************************************************************************
242  explicit inline DMatSMatMultExpr( const MT1& lhs, const MT2& rhs )
243  : lhs_( lhs ) // Left-hand side dense matrix of the multiplication expression
244  , rhs_( rhs ) // Right-hand side sparse matrix of the multiplication expression
245  {
246  BLAZE_INTERNAL_ASSERT( lhs.columns() == rhs.rows(), "Invalid matrix sizes" );
247  }
248  //**********************************************************************************************
249 
250  //**Access operator*****************************************************************************
257  inline ReturnType operator()( size_t i, size_t j ) const {
258  BLAZE_INTERNAL_ASSERT( i < lhs_.rows() , "Invalid row access index" );
259  BLAZE_INTERNAL_ASSERT( j < rhs_.columns(), "Invalid column access index" );
260 
261  const size_t kbegin( ( IsUpper<MT1>::value )
262  ?( ( IsLower<MT2>::value )
263  ?( max( ( IsStrictlyUpper<MT1>::value ? i+1UL : i )
264  , ( IsStrictlyLower<MT2>::value ? j+1UL : j ) ) )
265  :( IsStrictlyUpper<MT1>::value ? i+1UL : i ) )
266  :( ( IsLower<MT2>::value )
267  ?( IsStrictlyLower<MT2>::value ? j+1UL : j )
268  :( 0UL ) ) );
269  const size_t kend( ( IsLower<MT1>::value )
270  ?( ( IsUpper<MT2>::value )
271  ?( min( ( IsStrictlyLower<MT1>::value ? i : i+1UL )
272  , ( IsStrictlyUpper<MT2>::value ? j : j+1UL ) ) )
273  :( IsStrictlyLower<MT1>::value ? i : i+1UL ) )
274  :( ( IsUpper<MT2>::value )
275  ?( IsStrictlyUpper<MT2>::value ? j : j+1UL )
276  :( lhs_.columns() ) ) );
277 
278  if( lhs_.columns() == 0UL ||
279  ( ( IsTriangular<MT1>::value || IsTriangular<MT2>::value ) && kbegin >= kend ) )
280  return ElementType();
281 
282  ElementType tmp( lhs_(i,kbegin) * rhs_(kbegin,j) );
283  for( size_t k=kbegin+1UL; k<kend; ++k ) {
284  tmp += lhs_(i,k) * rhs_(k,j);
285  }
286 
287  return tmp;
288  }
289  //**********************************************************************************************
290 
291  //**At function*********************************************************************************
299  inline ReturnType at( size_t i, size_t j ) const {
300  if( i >= lhs_.rows() ) {
301  BLAZE_THROW_OUT_OF_RANGE( "Invalid row access index" );
302  }
303  if( j >= rhs_.columns() ) {
304  BLAZE_THROW_OUT_OF_RANGE( "Invalid column access index" );
305  }
306  return (*this)(i,j);
307  }
308  //**********************************************************************************************
309 
310  //**Rows function*******************************************************************************
315  inline size_t rows() const {
316  return lhs_.rows();
317  }
318  //**********************************************************************************************
319 
320  //**Columns function****************************************************************************
325  inline size_t columns() const {
326  return rhs_.columns();
327  }
328  //**********************************************************************************************
329 
330  //**Left operand access*************************************************************************
335  inline LeftOperand leftOperand() const {
336  return lhs_;
337  }
338  //**********************************************************************************************
339 
340  //**Right operand access************************************************************************
345  inline RightOperand rightOperand() const {
346  return rhs_;
347  }
348  //**********************************************************************************************
349 
350  //**********************************************************************************************
356  template< typename T >
357  inline bool canAlias( const T* alias ) const {
358  return ( lhs_.isAliased( alias ) || rhs_.isAliased( alias ) );
359  }
360  //**********************************************************************************************
361 
362  //**********************************************************************************************
368  template< typename T >
369  inline bool isAliased( const T* alias ) const {
370  return ( lhs_.isAliased( alias ) || rhs_.isAliased( alias ) );
371  }
372  //**********************************************************************************************
373 
374  //**********************************************************************************************
379  inline bool isAligned() const {
380  return lhs_.isAligned();
381  }
382  //**********************************************************************************************
383 
384  //**********************************************************************************************
389  inline bool canSMPAssign() const {
390  return ( rows() > SMP_DMATSMATMULT_THRESHOLD );
391  }
392  //**********************************************************************************************
393 
394  private:
395  //**Member variables****************************************************************************
396  LeftOperand lhs_;
397  RightOperand rhs_;
398  //**********************************************************************************************
399 
400  //**Assignment to dense matrices****************************************************************
413  template< typename MT // Type of the target dense matrix
414  , bool SO > // Storage order of the target dense matrix
415  friend inline typename DisableIf< CanExploitSymmetry<MT,MT1,MT2> >::Type
416  assign( DenseMatrix<MT,SO>& lhs, const DMatSMatMultExpr& rhs )
417  {
419 
420  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
421  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
422 
423  LT A( serial( rhs.lhs_ ) ); // Evaluation of the left-hand side dense matrix operand
424  RT B( serial( rhs.rhs_ ) ); // Evaluation of the right-hand side sparse matrix operand
425 
426  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
427  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
428  BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
429  BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
430  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
431  BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
432 
433  DMatSMatMultExpr::selectAssignKernel( ~lhs, A, B );
434  }
436  //**********************************************************************************************
437 
438  //**Assignment to dense matrices (kernel selection)*********************************************
449  template< typename MT3 // Type of the left-hand side target matrix
450  , typename MT4 // Type of the left-hand side matrix operand
451  , typename MT5 > // Type of the right-hand side matrix operand
452  static inline void selectAssignKernel( MT3& C, const MT4& A, const MT5& B )
453  {
454  if( C.rows() * C.columns() < DMATSMATMULT_THRESHOLD )
455  selectSmallAssignKernel( C, A, B );
456  else
457  selectLargeAssignKernel( C, A, B );
458  }
460  //**********************************************************************************************
461 
462  //**Default assignment to dense matrices********************************************************
476  template< typename MT3 // Type of the left-hand side target matrix
477  , typename MT4 // Type of the left-hand side matrix operand
478  , typename MT5 > // Type of the right-hand side matrix operand
479  static inline void selectDefaultAssignKernel( MT3& C, const MT4& A, const MT5& B )
480  {
481  typedef typename MT5::ConstIterator ConstIterator;
482 
483  reset( C );
484 
485  for( size_t j=0UL; j<B.rows(); ++j )
486  {
487  if( IsDiagonal<MT4>::value )
488  {
489  ConstIterator element( B.begin(j) );
490  const ConstIterator end( B.end(j) );
491 
492  for( ; element!=end; ++element ) {
493  C(j,element->index()) = A(j,j) * element->value();
494  }
495  }
496  else
497  {
498  const size_t iibegin( ( IsLower<MT4>::value )
499  ?( IsStrictlyLower<MT4>::value ? j+1UL : j )
500  :( 0UL ) );
501  const size_t iiend( ( IsUpper<MT4>::value )
502  ?( IsStrictlyUpper<MT4>::value ? j : j+1UL )
503  :( A.rows() ) );
504  BLAZE_INTERNAL_ASSERT( iibegin <= iiend, "Invalid loop indices detected" );
505 
506  for( size_t ii=iibegin; ii<iiend; ii+=8UL )
507  {
508  ConstIterator element( B.begin(j) );
509  const ConstIterator end( B.end(j) );
510  const size_t iend( ( ii+8UL > iiend )?( iiend ):( ii+8UL ) );
511 
512  for( ; element!=end; ++element ) {
513  for( size_t i=ii; i<iend; ++i ) {
514  if( isDefault( C(i,element->index()) ) )
515  C(i,element->index()) = A(i,j) * element->value();
516  else
517  C(i,element->index()) += A(i,j) * element->value();
518  }
519  }
520  }
521  }
522  }
523  }
525  //**********************************************************************************************
526 
527  //**Default assignment to dense matrices (small matrices)***************************************
540  template< typename MT3 // Type of the left-hand side target matrix
541  , typename MT4 // Type of the left-hand side matrix operand
542  , typename MT5 > // Type of the right-hand side matrix operand
543  static inline typename EnableIf< UseDefaultKernel<MT3,MT4,MT5> >::Type
544  selectSmallAssignKernel( MT3& C, const MT4& A, const MT5& B )
545  {
546  selectDefaultAssignKernel( C, A, B );
547  }
549  //**********************************************************************************************
550 
551  //**Optimized assignment to dense matrices (small matrices)*************************************
566  template< typename MT3 // Type of the left-hand side target matrix
567  , typename MT4 // Type of the left-hand side matrix operand
568  , typename MT5 > // Type of the right-hand side matrix operand
569  static inline typename EnableIf< UseOptimizedKernel<MT3,MT4,MT5> >::Type
570  selectSmallAssignKernel( MT3& C, const MT4& A, const MT5& B )
571  {
572  typedef typename MT5::ConstIterator ConstIterator;
573 
574  reset( C );
575 
576  for( size_t j=0UL; j<B.rows(); ++j )
577  {
578  const size_t iibegin( ( IsLower<MT4>::value )
579  ?( IsStrictlyLower<MT4>::value ? j+1UL : j )
580  :( 0UL ) );
581  const size_t iiend( ( IsUpper<MT4>::value )
582  ?( IsStrictlyUpper<MT4>::value ? j : j+1UL )
583  :( A.rows() ) );
584  BLAZE_INTERNAL_ASSERT( iibegin <= iiend, "Invalid loop indices detected" );
585 
586  for( size_t ii=iibegin; ii<iiend; ii+=8UL )
587  {
588  ConstIterator element( B.begin(j) );
589  const ConstIterator end( B.end(j) );
590  const size_t iend( ( ii+8UL > iiend )?( iiend ):( ii+8UL ) );
591 
592  for( ; element!=end; ++element ) {
593  for( size_t i=ii; i<iend; ++i ) {
594  C(i,element->index()) += A(i,j) * element->value();
595  }
596  }
597  }
598  }
599  }
601  //**********************************************************************************************
602 
603  //**Default assignment to dense matrices (large matrices)***************************************
616  template< typename MT3 // Type of the left-hand side target matrix
617  , typename MT4 // Type of the left-hand side matrix operand
618  , typename MT5 > // Type of the right-hand side matrix operand
619  static inline typename EnableIf< UseDefaultKernel<MT3,MT4,MT5> >::Type
620  selectLargeAssignKernel( MT3& C, const MT4& A, const MT5& B )
621  {
622  selectDefaultAssignKernel( C, A, B );
623  }
625  //**********************************************************************************************
626 
627  //**Optimized assignment to dense matrices (large matrices)*************************************
642  template< typename MT3 // Type of the left-hand side target matrix
643  , typename MT4 // Type of the left-hand side matrix operand
644  , typename MT5 > // Type of the right-hand side matrix operand
645  static inline typename EnableIf< UseOptimizedKernel<MT3,MT4,MT5> >::Type
646  selectLargeAssignKernel( MT3& C, const MT4& A, const MT5& B )
647  {
649 
650  const typename MT5::OppositeType tmp( serial( B ) );
651  assign( C, A * tmp );
652  }
654  //**********************************************************************************************
655 
656  //**Assignment to sparse matrices***************************************************************
669  template< typename MT // Type of the target sparse matrix
670  , bool SO > // Storage order of the target sparse matrix
671  friend inline typename DisableIf< CanExploitSymmetry<MT,MT1,MT2> >::Type
672  assign( SparseMatrix<MT,SO>& lhs, const DMatSMatMultExpr& rhs )
673  {
675 
676  typedef typename SelectType< SO, OppositeType, ResultType >::Type TmpType;
677 
684 
685  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
686  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
687 
688  const TmpType tmp( serial( rhs ) );
689  assign( ~lhs, tmp );
690  }
692  //**********************************************************************************************
693 
694  //**Restructuring assignment********************************************************************
709  template< typename MT // Type of the target matrix
710  , bool SO > // Storage order of the target matrix
711  friend inline typename EnableIf< CanExploitSymmetry<MT,MT1,MT2> >::Type
712  assign( Matrix<MT,SO>& lhs, const DMatSMatMultExpr& rhs )
713  {
715 
717 
718  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
719  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
720 
721  if( IsSymmetric<MT1>::value && IsSymmetric<MT2>::value )
722  assign( ~lhs, trans( rhs.lhs_ ) * trans( rhs.rhs_ ) );
723  else if( IsSymmetric<MT1>::value )
724  assign( ~lhs, trans( rhs.lhs_ ) * rhs.rhs_ );
725  else
726  assign( ~lhs, rhs.lhs_ * trans( rhs.rhs_ ) );
727  }
729  //**********************************************************************************************
730 
731  //**Addition assignment to dense matrices*******************************************************
744  template< typename MT // Type of the target dense matrix
745  , bool SO > // Storage order of the target dense matrix
746  friend inline typename DisableIf< CanExploitSymmetry<MT,MT1,MT2> >::Type
747  addAssign( DenseMatrix<MT,SO>& lhs, const DMatSMatMultExpr& rhs )
748  {
750 
751  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
752  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
753 
754  LT A( serial( rhs.lhs_ ) ); // Evaluation of the left-hand side dense matrix operand
755  RT B( serial( rhs.rhs_ ) ); // Evaluation of the right-hand side sparse matrix operand
756 
757  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
758  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
759  BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
760  BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
761  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
762  BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
763 
764  DMatSMatMultExpr::selectAddAssignKernel( ~lhs, A, B );
765  }
767  //**********************************************************************************************
768 
769  //**Addition assignment to dense matrices (kernel selection)************************************
780  template< typename MT3 // Type of the left-hand side target matrix
781  , typename MT4 // Type of the left-hand side matrix operand
782  , typename MT5 > // Type of the right-hand side matrix operand
783  static inline void selectAddAssignKernel( MT3& C, const MT4& A, const MT5& B )
784  {
785  if( C.rows() * C.columns() < DMATSMATMULT_THRESHOLD )
786  selectSmallAddAssignKernel( C, A, B );
787  else
788  selectLargeAddAssignKernel( C, A, B );
789  }
791  //**********************************************************************************************
792 
793  //**Optimized addition assignment to dense matrices (small matrices)****************************
807  template< typename MT3 // Type of the left-hand side target matrix
808  , typename MT4 // Type of the left-hand side matrix operand
809  , typename MT5 > // Type of the right-hand side matrix operand
810  static inline void selectSmallAddAssignKernel( MT3& C, const MT4& A, const MT5& B )
811  {
812  typedef typename MT5::ConstIterator ConstIterator;
813 
814  for( size_t j=0UL; j<B.rows(); ++j )
815  {
816  if( IsDiagonal<MT4>::value )
817  {
818  ConstIterator element( B.begin(j) );
819  const ConstIterator end( B.end(j) );
820 
821  for( ; element!=end; ++element ) {
822  C(j,element->index()) += A(j,j) * element->value();
823  }
824  }
825  else
826  {
827  const size_t iibegin( ( IsLower<MT4>::value )
828  ?( IsStrictlyLower<MT4>::value ? j+1UL : j )
829  :( 0UL ) );
830  const size_t iiend( ( IsUpper<MT4>::value )
831  ?( IsStrictlyUpper<MT4>::value ? j : j+1UL )
832  :( A.rows() ) );
833  BLAZE_INTERNAL_ASSERT( iibegin <= iiend, "Invalid loop indices detected" );
834 
835  for( size_t ii=iibegin; ii<iiend; ii+=8UL )
836  {
837  ConstIterator element( B.begin(j) );
838  const ConstIterator end( B.end(j) );
839  const size_t iend( ( ii+8UL > iiend )?( iiend ):( ii+8UL ) );
840 
841  for( ; element!=end; ++element ) {
842  for( size_t i=ii; i<iend; ++i ) {
843  C(i,element->index()) += A(i,j) * element->value();
844  }
845  }
846  }
847  }
848  }
849  }
851  //**********************************************************************************************
852 
853  //**Optimized addition assignment to dense matrices (large matrices)****************************
867  template< typename MT3 // Type of the left-hand side target matrix
868  , typename MT4 // Type of the left-hand side matrix operand
869  , typename MT5 > // Type of the right-hand side matrix operand
870  static inline void selectLargeAddAssignKernel( MT3& C, const MT4& A, const MT5& B )
871  {
873 
874  const typename MT5::OppositeType tmp( serial( B ) );
875  addAssign( C, A * tmp );
876  }
878  //**********************************************************************************************
879 
880  //**Restructuring addition assignment***********************************************************
895  template< typename MT // Type of the target matrix
896  , bool SO > // Storage order of the target matrix
897  friend inline typename EnableIf< CanExploitSymmetry<MT,MT1,MT2> >::Type
898  addAssign( Matrix<MT,SO>& lhs, const DMatSMatMultExpr& rhs )
899  {
901 
903 
904  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
905  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
906 
907  if( IsSymmetric<MT1>::value && IsSymmetric<MT2>::value )
908  addAssign( ~lhs, trans( rhs.lhs_ ) * trans( rhs.rhs_ ) );
909  else if( IsSymmetric<MT1>::value )
910  addAssign( ~lhs, trans( rhs.lhs_ ) * rhs.rhs_ );
911  else
912  addAssign( ~lhs, rhs.lhs_ * trans( rhs.rhs_ ) );
913  }
915  //**********************************************************************************************
916 
917  //**Addition assignment to sparse matrices******************************************************
918  // No special implementation for the addition assignment to sparse matrices.
919  //**********************************************************************************************
920 
921  //**Subtraction assignment to dense matrices****************************************************
934  template< typename MT // Type of the target dense matrix
935  , bool SO > // Storage order of the target dense matrix
936  friend inline typename DisableIf< CanExploitSymmetry<MT,MT1,MT2> >::Type
937  subAssign( DenseMatrix<MT,SO>& lhs, const DMatSMatMultExpr& rhs )
938  {
940 
941  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
942  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
943 
944  LT A( serial( rhs.lhs_ ) ); // Evaluation of the left-hand side dense matrix operand
945  RT B( serial( rhs.rhs_ ) ); // Evaluation of the right-hand side sparse matrix operand
946 
947  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
948  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
949  BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
950  BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
951  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
952  BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
953 
954  DMatSMatMultExpr::selectSubAssignKernel( ~lhs, A, B );
955  }
957  //**********************************************************************************************
958 
959  //**Subtraction assignment to dense matrices (kernel selection)*********************************
970  template< typename MT3 // Type of the left-hand side target matrix
971  , typename MT4 // Type of the left-hand side matrix operand
972  , typename MT5 > // Type of the right-hand side matrix operand
973  static inline void selectSubAssignKernel( MT3& C, const MT4& A, const MT5& B )
974  {
975  if( C.rows() * C.columns() < DMATSMATMULT_THRESHOLD )
976  selectSmallSubAssignKernel( C, A, B );
977  else
978  selectLargeSubAssignKernel( C, A, B );
979  }
981  //**********************************************************************************************
982 
983  //**Optimized subtraction assignment to dense matrices (small matrices)*************************
997  template< typename MT3 // Type of the left-hand side target matrix
998  , typename MT4 // Type of the left-hand side matrix operand
999  , typename MT5 > // Type of the right-hand side matrix operand
1000  static inline void selectSmallSubAssignKernel( MT3& C, const MT4& A, const MT5& B )
1001  {
1002  typedef typename MT5::ConstIterator ConstIterator;
1003 
1004  for( size_t j=0UL; j<B.rows(); ++j )
1005  {
1006  if( IsDiagonal<MT4>::value )
1007  {
1008  ConstIterator element( B.begin(j) );
1009  const ConstIterator end( B.end(j) );
1010 
1011  for( ; element!=end; ++element ) {
1012  C(j,element->index()) -= A(j,j) * element->value();
1013  }
1014  }
1015  else
1016  {
1017  const size_t iibegin( ( IsLower<MT4>::value )
1018  ?( IsStrictlyLower<MT4>::value ? j+1UL : j )
1019  :( 0UL ) );
1020  const size_t iiend( ( IsUpper<MT4>::value )
1021  ?( IsStrictlyUpper<MT4>::value ? j : j+1UL )
1022  :( A.rows() ) );
1023  BLAZE_INTERNAL_ASSERT( iibegin <= iiend, "Invalid loop indices detected" );
1024 
1025  for( size_t ii=iibegin; ii<iiend; ii+=8UL )
1026  {
1027  ConstIterator element( B.begin(j) );
1028  const ConstIterator end( B.end(j) );
1029  const size_t iend( ( ii+8UL > iiend )?( iiend ):( ii+8UL ) );
1030 
1031  for( ; element!=end; ++element ) {
1032  for( size_t i=ii; i<iend; ++i ) {
1033  C(i,element->index()) -= A(i,j) * element->value();
1034  }
1035  }
1036  }
1037  }
1038  }
1039  }
1041  //**********************************************************************************************
1042 
1043  //**Optimized subtraction assignment to dense matrices (large matrices)*************************
1057  template< typename MT3 // Type of the left-hand side target matrix
1058  , typename MT4 // Type of the left-hand side matrix operand
1059  , typename MT5 > // Type of the right-hand side matrix operand
1060  static inline void selectLargeSubAssignKernel( MT3& C, const MT4& A, const MT5& B )
1061  {
1063 
1064  const typename MT5::OppositeType tmp( serial( B ) );
1065  subAssign( C, A * tmp );
1066  }
1068  //**********************************************************************************************
1069 
1070  //**Restructuring subtraction assignment********************************************************
1085  template< typename MT // Type of the target matrix
1086  , bool SO > // Storage order of the target matrix
1087  friend inline typename EnableIf< CanExploitSymmetry<MT,MT1,MT2> >::Type
1088  subAssign( Matrix<MT,SO>& lhs, const DMatSMatMultExpr& rhs )
1089  {
1091 
1093 
1094  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
1095  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
1096 
1097  if( IsSymmetric<MT1>::value && IsSymmetric<MT2>::value )
1098  subAssign( ~lhs, trans( rhs.lhs_ ) * trans( rhs.rhs_ ) );
1099  else if( IsSymmetric<MT1>::value )
1100  subAssign( ~lhs, trans( rhs.lhs_ ) * rhs.rhs_ );
1101  else
1102  subAssign( ~lhs, rhs.lhs_ * trans( rhs.rhs_ ) );
1103  }
1105  //**********************************************************************************************
1106 
1107  //**Subtraction assignment to sparse matrices***************************************************
1108  // No special implementation for the subtraction assignment to sparse matrices.
1109  //**********************************************************************************************
1110 
1111  //**Multiplication assignment to dense matrices*************************************************
1112  // No special implementation for the multiplication assignment to dense matrices.
1113  //**********************************************************************************************
1114 
1115  //**Multiplication assignment to sparse matrices************************************************
1116  // No special implementation for the multiplication assignment to sparse matrices.
1117  //**********************************************************************************************
1118 
1119  //**SMP assignment to dense matrices************************************************************
1134  template< typename MT // Type of the target dense matrix
1135  , bool SO > // Storage order of the target dense matrix
1136  friend inline typename EnableIf< IsEvaluationRequired<MT,MT1,MT2> >::Type
1137  smpAssign( DenseMatrix<MT,SO>& lhs, const DMatSMatMultExpr& rhs )
1138  {
1140 
1141  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
1142  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
1143 
1144  LT A( rhs.lhs_ ); // Evaluation of the left-hand side dense matrix operand
1145  RT B( rhs.rhs_ ); // Evaluation of the right-hand side sparse matrix operand
1146 
1147  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
1148  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
1149  BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
1150  BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
1151  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
1152  BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
1153 
1154  smpAssign( ~lhs, A * B );
1155  }
1157  //**********************************************************************************************
1158 
1159  //**SMP assignment to sparse matrices***********************************************************
1174  template< typename MT // Type of the target sparse matrix
1175  , bool SO > // Storage order of the target sparse matrix
1176  friend inline typename EnableIf< IsEvaluationRequired<MT,MT1,MT2> >::Type
1177  smpAssign( SparseMatrix<MT,SO>& lhs, const DMatSMatMultExpr& rhs )
1178  {
1180 
1181  typedef typename SelectType< SO, OppositeType, ResultType >::Type TmpType;
1182 
1189 
1190  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
1191  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
1192 
1193  const TmpType tmp( rhs );
1194  smpAssign( ~lhs, tmp );
1195  }
1197  //**********************************************************************************************
1198 
1199  //**Restructuring SMP assignment****************************************************************
1214  template< typename MT // Type of the target matrix
1215  , bool SO > // Storage order of the target matrix
1216  friend inline typename EnableIf< CanExploitSymmetry<MT,MT1,MT2> >::Type
1217  smpAssign( Matrix<MT,SO>& lhs, const DMatSMatMultExpr& rhs )
1218  {
1220 
1222 
1223  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
1224  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
1225 
1226  if( IsSymmetric<MT1>::value && IsSymmetric<MT2>::value )
1227  smpAssign( ~lhs, trans( rhs.lhs_ ) * trans( rhs.rhs_ ) );
1228  else if( IsSymmetric<MT1>::value )
1229  smpAssign( ~lhs, trans( rhs.lhs_ ) * rhs.rhs_ );
1230  else
1231  smpAssign( ~lhs, rhs.lhs_ * trans( rhs.rhs_ ) );
1232  }
1234  //**********************************************************************************************
1235 
1236  //**SMP addition assignment to dense matrices***************************************************
1251  template< typename MT // Type of the target dense matrix
1252  , bool SO > // Storage order of the target sparse matrix
1253  friend inline typename EnableIf< IsEvaluationRequired<MT,MT1,MT2> >::Type
1254  smpAddAssign( DenseMatrix<MT,SO>& lhs, const DMatSMatMultExpr& rhs )
1255  {
1257 
1258  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
1259  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
1260 
1261  LT A( rhs.lhs_ ); // Evaluation of the left-hand side dense matrix operand
1262  RT B( rhs.rhs_ ); // Evaluation of the right-hand side sparse matrix operand
1263 
1264  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
1265  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
1266  BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
1267  BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
1268  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
1269  BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
1270 
1271  smpAddAssign( ~lhs, A * B );
1272  }
1274  //**********************************************************************************************
1275 
1276  //**Restructuring SMP addition assignment*******************************************************
1291  template< typename MT // Type of the target matrix
1292  , bool SO > // Storage order of the target matrix
1293  friend inline typename EnableIf< CanExploitSymmetry<MT,MT1,MT2> >::Type
1294  smpAddAssign( Matrix<MT,SO>& lhs, const DMatSMatMultExpr& rhs )
1295  {
1297 
1299 
1300  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
1301  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
1302 
1303  if( IsSymmetric<MT1>::value && IsSymmetric<MT2>::value )
1304  smpAddAssign( ~lhs, trans( rhs.lhs_ ) * trans( rhs.rhs_ ) );
1305  else if( IsSymmetric<MT1>::value )
1306  smpAddAssign( ~lhs, trans( rhs.lhs_ ) * rhs.rhs_ );
1307  else
1308  smpAddAssign( ~lhs, rhs.lhs_ * trans( rhs.rhs_ ) );
1309  }
1311  //**********************************************************************************************
1312 
1313  //**SMP addition assignment to sparse matrices**************************************************
1314  // No special implementation for the SMP addition assignment to sparse matrices.
1315  //**********************************************************************************************
1316 
1317  //**SMP subtraction assignment to dense matrices************************************************
1333  template< typename MT // Type of the target dense matrix
1334  , bool SO > // Storage order of the target sparse matrix
1335  friend inline typename EnableIf< IsEvaluationRequired<MT,MT1,MT2> >::Type
1336  smpSubAssign( DenseMatrix<MT,SO>& lhs, const DMatSMatMultExpr& rhs )
1337  {
1339 
1340  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
1341  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
1342 
1343  LT A( rhs.lhs_ ); // Evaluation of the left-hand side dense matrix operand
1344  RT B( rhs.rhs_ ); // Evaluation of the right-hand side sparse matrix operand
1345 
1346  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
1347  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
1348  BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
1349  BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
1350  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
1351  BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
1352 
1353  smpSubAssign( ~lhs, A * B );
1354  }
1356  //**********************************************************************************************
1357 
1358  //**Restructuring SMP subtraction assignment****************************************************
1373  template< typename MT // Type of the target matrix
1374  , bool SO > // Storage order of the target matrix
1375  friend inline typename EnableIf< CanExploitSymmetry<MT,MT1,MT2> >::Type
1376  smpSubAssign( Matrix<MT,SO>& lhs, const DMatSMatMultExpr& rhs )
1377  {
1379 
1381 
1382  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
1383  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
1384 
1385  if( IsSymmetric<MT1>::value && IsSymmetric<MT2>::value )
1386  smpSubAssign( ~lhs, trans( rhs.lhs_ ) * trans( rhs.rhs_ ) );
1387  else if( IsSymmetric<MT1>::value )
1388  smpSubAssign( ~lhs, trans( rhs.lhs_ ) * rhs.rhs_ );
1389  else
1390  smpSubAssign( ~lhs, rhs.lhs_ * trans( rhs.rhs_ ) );
1391  }
1393  //**********************************************************************************************
1394 
1395  //**SMP subtraction assignment to sparse matrices***********************************************
1396  // No special implementation for the SMP subtraction assignment to sparse matrices.
1397  //**********************************************************************************************
1398 
1399  //**SMP multiplication assignment to dense matrices*********************************************
1400  // No special implementation for the SMP multiplication assignment to dense matrices.
1401  //**********************************************************************************************
1402 
1403  //**SMP multiplication assignment to sparse matrices********************************************
1404  // No special implementation for the SMP multiplication assignment to sparse matrices.
1405  //**********************************************************************************************
1406 
1407  //**Compile time checks*************************************************************************
1415  //**********************************************************************************************
1416 };
1417 //*************************************************************************************************
1418 
1419 
1420 
1421 
1422 //=================================================================================================
1423 //
1424 // GLOBAL BINARY ARITHMETIC OPERATORS
1425 //
1426 //=================================================================================================
1427 
1428 //*************************************************************************************************
1457 template< typename T1 // Type of the left-hand side dense matrix
1458  , typename T2 > // Type of the right-hand side sparse matrix
1459 inline const DMatSMatMultExpr<T1,T2>
1461 {
1463 
1464  if( (~lhs).columns() != (~rhs).rows() ) {
1465  BLAZE_THROW_INVALID_ARGUMENT( "Matrix sizes do not match" );
1466  }
1467 
1468  return DMatSMatMultExpr<T1,T2>( ~lhs, ~rhs );
1469 }
1470 //*************************************************************************************************
1471 
1472 
1473 
1474 
1475 //=================================================================================================
1476 //
1477 // ROWS SPECIALIZATIONS
1478 //
1479 //=================================================================================================
1480 
1481 //*************************************************************************************************
1483 template< typename MT1, typename MT2 >
1484 struct Rows< DMatSMatMultExpr<MT1,MT2> > : public Rows<MT1>
1485 {};
1487 //*************************************************************************************************
1488 
1489 
1490 
1491 
1492 //=================================================================================================
1493 //
1494 // COLUMNS SPECIALIZATIONS
1495 //
1496 //=================================================================================================
1497 
1498 //*************************************************************************************************
1500 template< typename MT1, typename MT2 >
1501 struct Columns< DMatSMatMultExpr<MT1,MT2> > : public Columns<MT2>
1502 {};
1504 //*************************************************************************************************
1505 
1506 
1507 
1508 
1509 //=================================================================================================
1510 //
1511 // ISALIGNED SPECIALIZATIONS
1512 //
1513 //=================================================================================================
1514 
1515 //*************************************************************************************************
1517 template< typename MT1, typename MT2 >
1518 struct IsAligned< DMatSMatMultExpr<MT1,MT2> > : public IsTrue< IsAligned<MT1>::value >
1519 {};
1521 //*************************************************************************************************
1522 
1523 
1524 
1525 
1526 //=================================================================================================
1527 //
1528 // ISLOWER SPECIALIZATIONS
1529 //
1530 //=================================================================================================
1531 
1532 //*************************************************************************************************
1534 template< typename MT1, typename MT2 >
1535 struct IsLower< DMatSMatMultExpr<MT1,MT2> >
1536  : public IsTrue< And< IsLower<MT1>, IsLower<MT2> >::value >
1537 {};
1539 //*************************************************************************************************
1540 
1541 
1542 
1543 
1544 //=================================================================================================
1545 //
1546 // ISUNILOWER SPECIALIZATIONS
1547 //
1548 //=================================================================================================
1549 
1550 //*************************************************************************************************
1552 template< typename MT1, typename MT2 >
1553 struct IsUniLower< DMatSMatMultExpr<MT1,MT2> >
1554  : public IsTrue< And< IsUniLower<MT1>, IsUniLower<MT2> >::value >
1555 {};
1557 //*************************************************************************************************
1558 
1559 
1560 
1561 
1562 //=================================================================================================
1563 //
1564 // ISSTRICTLYLOWER SPECIALIZATIONS
1565 //
1566 //=================================================================================================
1567 
1568 //*************************************************************************************************
1570 template< typename MT1, typename MT2 >
1571 struct IsStrictlyLower< DMatSMatMultExpr<MT1,MT2> >
1572  : public IsTrue< Or< And< IsStrictlyLower<MT1>, IsLower<MT2> >
1573  , And< IsStrictlyLower<MT2>, IsLower<MT1> > >::value >
1574 {};
1576 //*************************************************************************************************
1577 
1578 
1579 
1580 
1581 //=================================================================================================
1582 //
1583 // ISUPPER SPECIALIZATIONS
1584 //
1585 //=================================================================================================
1586 
1587 //*************************************************************************************************
1589 template< typename MT1, typename MT2 >
1590 struct IsUpper< DMatSMatMultExpr<MT1,MT2> >
1591  : public IsTrue< And< IsUpper<MT1>, IsUpper<MT2> >::value >
1592 {};
1594 //*************************************************************************************************
1595 
1596 
1597 
1598 
1599 //=================================================================================================
1600 //
1601 // ISUNIUPPER SPECIALIZATIONS
1602 //
1603 //=================================================================================================
1604 
1605 //*************************************************************************************************
1607 template< typename MT1, typename MT2 >
1608 struct IsUniUpper< DMatSMatMultExpr<MT1,MT2> >
1609  : public IsTrue< And< IsUniUpper<MT1>, IsUniUpper<MT2> >::value >
1610 {};
1612 //*************************************************************************************************
1613 
1614 
1615 
1616 
1617 //=================================================================================================
1618 //
1619 // ISSTRICTLYUPPER SPECIALIZATIONS
1620 //
1621 //=================================================================================================
1622 
1623 //*************************************************************************************************
1625 template< typename MT1, typename MT2 >
1626 struct IsStrictlyUpper< DMatSMatMultExpr<MT1,MT2> >
1627  : public IsTrue< Or< And< IsStrictlyUpper<MT1>, IsUpper<MT2> >
1628  , And< IsStrictlyUpper<MT2>, IsUpper<MT1> > >::value >
1629 {};
1631 //*************************************************************************************************
1632 
1633 
1634 
1635 
1636 //=================================================================================================
1637 //
1638 // EXPRESSION TRAIT SPECIALIZATIONS
1639 //
1640 //=================================================================================================
1641 
1642 //*************************************************************************************************
1644 template< typename MT1, typename MT2, typename VT >
1645 struct DMatDVecMultExprTrait< DMatSMatMultExpr<MT1,MT2>, VT >
1646 {
1647  public:
1648  //**********************************************************************************************
1649  typedef typename SelectType< IsDenseMatrix<MT1>::value && IsRowMajorMatrix<MT1>::value &&
1650  IsSparseMatrix<MT2>::value && IsRowMajorMatrix<MT2>::value &&
1651  IsDenseVector<VT>::value && IsColumnVector<VT>::value
1652  , typename DMatDVecMultExprTrait< MT1, typename SMatDVecMultExprTrait<MT2,VT>::Type >::Type
1653  , INVALID_TYPE >::Type Type;
1654  //**********************************************************************************************
1655 };
1657 //*************************************************************************************************
1658 
1659 
1660 //*************************************************************************************************
1662 template< typename MT1, typename MT2, typename VT >
1663 struct DMatSVecMultExprTrait< DMatSMatMultExpr<MT1,MT2>, VT >
1664 {
1665  public:
1666  //**********************************************************************************************
1667  typedef typename SelectType< IsDenseMatrix<MT1>::value && IsRowMajorMatrix<MT1>::value &&
1668  IsSparseMatrix<MT2>::value && IsRowMajorMatrix<MT2>::value &&
1669  IsSparseVector<VT>::value && IsColumnVector<VT>::value
1670  , typename DMatSVecMultExprTrait< MT1, typename SMatSVecMultExprTrait<MT2,VT>::Type >::Type
1671  , INVALID_TYPE >::Type Type;
1672  //**********************************************************************************************
1673 };
1675 //*************************************************************************************************
1676 
1677 
1678 //*************************************************************************************************
1680 template< typename VT, typename MT1, typename MT2 >
1681 struct TDVecDMatMultExprTrait< VT, DMatSMatMultExpr<MT1,MT2> >
1682 {
1683  public:
1684  //**********************************************************************************************
1685  typedef typename SelectType< IsDenseVector<VT>::value && IsRowVector<VT>::value &&
1686  IsDenseMatrix<MT1>::value && IsRowMajorMatrix<MT1>::value &&
1687  IsSparseMatrix<MT2>::value && IsRowMajorMatrix<MT2>::value
1688  , typename TDVecSMatMultExprTrait< typename TDVecDMatMultExprTrait<VT,MT1>::Type, MT2 >::Type
1689  , INVALID_TYPE >::Type Type;
1690  //**********************************************************************************************
1691 };
1693 //*************************************************************************************************
1694 
1695 
1696 //*************************************************************************************************
1698 template< typename VT, typename MT1, typename MT2 >
1699 struct TSVecDMatMultExprTrait< VT, DMatSMatMultExpr<MT1,MT2> >
1700 {
1701  public:
1702  //**********************************************************************************************
1703  typedef typename SelectType< IsSparseVector<VT>::value && IsRowVector<VT>::value &&
1704  IsDenseMatrix<MT1>::value && IsRowMajorMatrix<MT1>::value &&
1705  IsSparseMatrix<MT2>::value && IsRowMajorMatrix<MT2>::value
1706  , typename TDVecSMatMultExprTrait< typename TDVecDMatMultExprTrait<VT,MT1>::Type, MT2 >::Type
1707  , INVALID_TYPE >::Type Type;
1708  //**********************************************************************************************
1709 };
1711 //*************************************************************************************************
1712 
1713 
1714 //*************************************************************************************************
1716 template< typename MT1, typename MT2, bool AF >
1717 struct SubmatrixExprTrait< DMatSMatMultExpr<MT1,MT2>, AF >
1718 {
1719  public:
1720  //**********************************************************************************************
1721  typedef typename MultExprTrait< typename SubmatrixExprTrait<const MT1,AF>::Type
1722  , typename SubmatrixExprTrait<const MT2,AF>::Type >::Type Type;
1723  //**********************************************************************************************
1724 };
1726 //*************************************************************************************************
1727 
1728 
1729 //*************************************************************************************************
1731 template< typename MT1, typename MT2 >
1732 struct RowExprTrait< DMatSMatMultExpr<MT1,MT2> >
1733 {
1734  public:
1735  //**********************************************************************************************
1736  typedef typename MultExprTrait< typename RowExprTrait<const MT1>::Type, MT2 >::Type Type;
1737  //**********************************************************************************************
1738 };
1740 //*************************************************************************************************
1741 
1742 
1743 //*************************************************************************************************
1745 template< typename MT1, typename MT2 >
1746 struct ColumnExprTrait< DMatSMatMultExpr<MT1,MT2> >
1747 {
1748  public:
1749  //**********************************************************************************************
1750  typedef typename MultExprTrait< MT1, typename ColumnExprTrait<const MT2>::Type >::Type Type;
1751  //**********************************************************************************************
1752 };
1754 //*************************************************************************************************
1755 
1756 } // namespace blaze
1757 
1758 #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
ResultType::TransposeType TransposeType
Transpose type for expression template evaluations.
Definition: DMatSMatMultExpr.h:209
const MT::ElementType max(const DenseMatrix< MT, SO > &dm)
Returns the largest element of the dense matrix.
Definition: DenseMatrix.h:1729
Compile time check whether the given type is a computational expression template.This type trait clas...
Definition: IsComputation.h:89
Header file for mathematical functions.
RightOperand rhs_
Right-hand side sparse matrix of the multiplication expression.
Definition: DMatSMatMultExpr.h:397
Header file for the SMatDVecMultExprTrait class template.
Header file for the Rows type trait.
Header file for the IsUniUpper type trait.
const DMatDMatMultExpr< T1, T2 > operator*(const DenseMatrix< T1, false > &lhs, const DenseMatrix< T2, false > &rhs)
Multiplication operator for the multiplication of two row-major dense matrices ( ).
Definition: DMatDMatMultExpr.h:7820
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.
const ResultType CompositeType
Data type for composite expression templates.
Definition: DMatSMatMultExpr.h:212
ReturnType operator()(size_t i, size_t j) const
2D-access to the matrix elements.
Definition: DMatSMatMultExpr.h:257
const ElementType ReturnType
Return type for expression template evaluations.
Definition: DMatSMatMultExpr.h:211
BLAZE_ALWAYS_INLINE MT::Iterator end(Matrix< MT, SO > &matrix, size_t i)
Returns an iterator just past the last element of row/column i.
Definition: Matrix.h:250
SelectType< evaluateRight, const RT2, CT2 >::Type RT
Type for the assignment of the right-hand side sparse matrix operand.
Definition: DMatSMatMultExpr.h:224
Header file for the IsSparseMatrix type trait.
Efficient implementation of a compressed matrix.The CompressedMatrix class template is the represent...
Definition: CompressedMatrix.h:207
Header file for the IsDiagonal type trait.
#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
Header file for the ColumnExprTrait class template.
void reset(const DiagonalProxy< MT > &proxy)
Resetting the represented element to the default initial values.
Definition: DiagonalProxy.h:507
const This & CompositeType
Data type for composite expression templates.
Definition: CompressedMatrix.h:2588
Header file for the IsRowVector type trait.
Type ElementType
Type of the sparse matrix elements.
Definition: CompressedMatrix.h:259
Header file for the And class template.
size_t columns() const
Returns the current number of columns of the matrix.
Definition: DMatSMatMultExpr.h:325
Compile time check for lower triangular matrices.This type trait tests whether or not the given templ...
Definition: IsLower.h:90
bool isAligned() const
Returns whether the operands of the expression are properly aligned in memory.
Definition: DMatSMatMultExpr.h:379
MT2::ResultType RT2
Result type of the right-hand side sparse matrix expression.
Definition: DMatSMatMultExpr.h:133
Header file for the TDVecSMatMultExprTrait class template.
MultTrait< RT1, RT2 >::Type ResultType
Result type for expression template evaluations.
Definition: DMatSMatMultExpr.h:207
const DMatSerialExpr< MT, SO > serial(const DenseMatrix< MT, SO > &dm)
Forces the serial evaluation of the given dense matrix expression dm.
Definition: DMatSerialExpr.h:721
Header file for the Computation base class.
Header file for the MatMatMultExpr base class.
Compile time check for upper triangular matrices.This type trait tests whether or not the given templ...
Definition: IsUpper.h:90
Constraints on the storage order of matrix types.
Header file for the RequiresEvaluation type trait.
System settings for performance optimizations.
Header file for the IsUniLower type trait.
CompressedMatrix< Type, false > OppositeType
Result type with opposite storage order for expression template evaluations.
Definition: CompressedMatrix.h:2584
Base class for dense matrices.The DenseMatrix class is a base class for all dense matrix classes...
Definition: DenseMatrix.h:70
Base class for sparse matrices.The SparseMatrix class is a base class for all sparse matrix classes...
Definition: Forward.h:117
bool isDefault(const DiagonalProxy< MT > &proxy)
Returns whether the represented element is in default state.
Definition: DiagonalProxy.h:547
Constraint on the data type.
Constraint on the data type.
Constraint on the data type.
Header file for the MultExprTrait class template.
Compile time check to query the requirement to evaluate an expression.Via this type trait it is possi...
Definition: RequiresEvaluation.h:90
SelectType< IsExpression< MT2 >::value, const MT2, const MT2 & >::Type RightOperand
Composite type of the right-hand side sparse matrix expression.
Definition: DMatSMatMultExpr.h:218
LeftOperand lhs_
Left-hand side dense matrix of the multiplication expression.
Definition: DMatSMatMultExpr.h:396
size_t rows() const
Returns the current number of rows of the matrix.
Definition: DMatSMatMultExpr.h:315
Compile time type selection.The SelectType class template selects one of the two given types T1 and T...
Definition: SelectType.h:59
Header file for the DisableIf class template.
Header file for the multiplication trait.
Header file for the IsStrictlyUpper type trait.
MT1::ResultType RT1
Result type of the left-hand side dense matrix expression.
Definition: DMatSMatMultExpr.h:132
Header file for the IsSymmetric type trait.
Namespace of the Blaze C++ math library.
Definition: Blaze.h:57
#define BLAZE_CONSTRAINT_MUST_BE_COLUMN_MAJOR_MATRIX_TYPE(T)
Constraint on the data type.In case the given data type T is not a column-major dense or sparse matri...
Definition: ColumnMajorMatrix.h:79
const Element * ConstIterator
Iterator over constant elements.
Definition: CompressedMatrix.h:2592
LeftOperand leftOperand() const
Returns the left-hand side dense matrix operand.
Definition: DMatSMatMultExpr.h:335
Header file for the Or class template.
#define BLAZE_THROW_OUT_OF_RANGE(MESSAGE)
Macro for the emission of a std::out_of_range exceptionThis macro encapsulates the default way of Bla...
Definition: Exception.h:331
const MT::ElementType min(const DenseMatrix< MT, SO > &dm)
Returns the smallest element of the dense matrix.
Definition: DenseMatrix.h:1682
Header file for the DenseMatrix base class.
Header file for the Columns type trait.
ResultType::OppositeType OppositeType
Result type with opposite storage order for expression template evaluations.
Definition: DMatSMatMultExpr.h:208
Header file for the DMatDVecMultExprTrait class template.
Header file for the IsLower type trait.
RT2::ElementType ET2
Element type of the right-hand side sparse matrix expression.
Definition: DMatSMatMultExpr.h:135
Header file for the IsAligned type trait.
Header file for the SMatSVecMultExprTrait class template.
#define BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE(T)
Constraint on the data type.In case the given data type T is not a reference type, a compilation error is created.
Definition: Reference.h:78
bool canSMPAssign() const
Returns whether the expression can be used in SMP assignments.
Definition: DMatSMatMultExpr.h:389
Header file for the IsTriangular type trait.
Constraints on the storage order of matrix types.
SelectType< evaluateLeft, const RT1, CT1 >::Type LT
Type for the assignment of the left-hand side dense matrix operand.
Definition: DMatSMatMultExpr.h:221
Compile time check for strictly upper triangular matrices.This type trait tests whether or not the gi...
Definition: IsStrictlyUpper.h:86
Type ElementType
Type of the sparse matrix elements.
Definition: CompressedMatrix.h:2586
Header file for the SelectType class template.
Header file for the RowExprTrait class template.
Header file for all forward declarations for expression class templates.
Header file for the IsDenseMatrix type trait.
Header file for the EnableIf class template.
Header file for the IsStrictlyLower type trait.
Header file for the serial shim.
#define BLAZE_CONSTRAINT_MUST_FORM_VALID_MATMATMULTEXPR(T1, T2)
Constraint on the data type.In case the given data types T1 and T2 do not form a valid matrix/matrix ...
Definition: MatMatMultExpr.h:165
ResultType::ElementType ElementType
Resulting element type.
Definition: DMatSMatMultExpr.h:210
MT1::CompositeType CT1
Composite type of the left-hand side dense matrix expression.
Definition: DMatSMatMultExpr.h:136
RT1::ElementType ET1
Element type of the left-hand side dense matrix expression.
Definition: DMatSMatMultExpr.h:134
Base class for all matrix/matrix multiplication expression templates.The MatMatMultExpr class serves ...
Definition: MatMatMultExpr.h:65
EnableIf< IsDenseMatrix< MT1 > >::Type smpSubAssign(Matrix< MT1, SO1 > &lhs, const Matrix< MT2, SO2 > &rhs)
Default implementation of the SMP subtraction assignment of a matrix to dense matrix.
Definition: DenseMatrix.h:160
ReturnType at(size_t i, size_t j) const
Checked access to the matrix elements.
Definition: DMatSMatMultExpr.h:299
Header file for the IsSparseVector type trait.
#define BLAZE_CONSTRAINT_MUST_NOT_BE_SYMMETRIC_MATRIX_TYPE(T)
Constraint on the data type.In case the given data type T is a symmetric matrix type, a compilation error is created.
Definition: Symmetric.h:116
Header file for the SubmatrixExprTrait class template.
#define BLAZE_CONSTRAINT_MUST_BE_ROW_MAJOR_MATRIX_TYPE(T)
Constraint on the data type.In case the given data type T is not a row-major dense or sparse matrix t...
Definition: RowMajorMatrix.h:79
bool canAlias(const T *alias) const
Returns whether the expression can alias with the given address alias.
Definition: DMatSMatMultExpr.h:357
Header file for run time assertion macros.
EnableIf< IsDenseMatrix< MT1 > >::Type smpAssign(Matrix< MT1, SO1 > &lhs, const Matrix< MT2, SO2 > &rhs)
Default implementation of the SMP assignment of a matrix to a dense matrix.
Definition: DenseMatrix.h:98
bool isAliased(const T *alias) const
Returns whether the expression is aliased with the given address alias.
Definition: DMatSMatMultExpr.h:369
Utility type for generic codes.
Base template for the MultTrait class.
Definition: MultTrait.h:138
Expression object for dense matrix-sparse matrix multiplications.The DMatSMatMultExpr class represent...
Definition: DMatSMatMultExpr.h:126
const bool useOptimizedKernels
Configuration switch for optimized kernels.This configuration switch enables/disables all optimized c...
Definition: Optimizations.h:84
Header file for the reset shim.
Header file for the isDefault shim.
Constraint on the data type.
Constraints on the storage order of matrix types.
Substitution Failure Is Not An Error (SFINAE) class.The DisableIf class template is an auxiliary tool...
Definition: DisableIf.h:184
#define BLAZE_CONSTRAINT_MATRICES_MUST_HAVE_SAME_STORAGE_ORDER(T1, T2)
Constraint on the data type.In case either of the two given data types T1 or T2 is not a matrix type ...
Definition: StorageOrder.h:122
MT2::CompositeType CT2
Composite type of the right-hand side sparse matrix expression.
Definition: DMatSMatMultExpr.h:137
Header file for the IsDenseVector type trait.
Compile time check for strictly lower triangular matrices.This type trait tests whether or not the gi...
Definition: IsStrictlyLower.h:86
SelectType< IsExpression< MT1 >::value, const MT1, const MT1 & >::Type LeftOperand
Composite type of the left-hand side dense matrix expression.
Definition: DMatSMatMultExpr.h:215
Header file for the IsRowMajorMatrix type trait.
const DMatTransExpr< MT,!SO > trans(const DenseMatrix< MT, SO > &dm)
Calculation of the transpose of the given dense matrix.
Definition: DMatTransExpr.h:944
Header file for the IsComputation type trait class.
Base class for all compute expression templates.The Computation class serves as a tag for all computa...
Definition: Computation.h:59
Header file for the TDVecDMatMultExprTrait class template.
EnableIf< IsDenseMatrix< MT1 > >::Type smpAddAssign(Matrix< MT1, SO1 > &lhs, const Matrix< MT2, SO2 > &rhs)
Default implementation of the SMP addition assignment of a matrix to a dense matrix.
Definition: DenseMatrix.h:129
#define BLAZE_FUNCTION_TRACE
Function trace macro.This macro can be used to reliably trace function calls. In case function tracin...
Definition: FunctionTrace.h:157
This ResultType
Result type for expression template evaluations.
Definition: CompressedMatrix.h:2583
Header file for the IsTrue value trait.
DMatSMatMultExpr(const MT1 &lhs, const MT2 &rhs)
Constructor for the DMatSMatMultExpr class.
Definition: DMatSMatMultExpr.h:242
Header file for the TSVecDMatMultExprTrait class template.
DMatSMatMultExpr< MT1, MT2 > This
Type of this DMatSMatMultExpr instance.
Definition: DMatSMatMultExpr.h:206
Header file for the IsUpper type trait.
Header file for exception macros.
Header file for the DMatSVecMultExprTrait class template.
Header file for the IsColumnVector type trait.
Constraint on the data type.
Header file for the IsResizable type trait.
Header file for the thresholds for matrix/vector and matrix/matrix multiplications.
#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
#define BLAZE_CONSTRAINT_MUST_BE_SPARSE_MATRIX_TYPE(T)
Constraint on the data type.In case the given data type T is not a sparse, N-dimensional matrix type...
Definition: SparseMatrix.h:79
Header file for the IsExpression type trait class.
Header file for the FunctionTrace class.
RightOperand rightOperand() const
Returns the right-hand side sparse matrix operand.
Definition: DMatSMatMultExpr.h:345