TSMatDMatMultExpr.h
Go to the documentation of this file.
1 //=================================================================================================
33 //=================================================================================================
34 
35 #ifndef _BLAZE_MATH_EXPRESSIONS_TSMATDMATMULTEXPR_H_
36 #define _BLAZE_MATH_EXPRESSIONS_TSMATDMATMULTEXPR_H_
37 
38 
39 //*************************************************************************************************
40 // Includes
41 //*************************************************************************************************
42 
43 #include <stdexcept>
52 #include <blaze/math/Functions.h>
54 #include <blaze/math/shims/Reset.h>
95 #include <blaze/util/Assert.h>
96 #include <blaze/util/DisableIf.h>
97 #include <blaze/util/EnableIf.h>
98 #include <blaze/util/InvalidType.h>
100 #include <blaze/util/SelectType.h>
101 #include <blaze/util/Types.h>
104 
105 
106 namespace blaze {
107 
108 //=================================================================================================
109 //
110 // CLASS SMATDMATMULTEXPR
111 //
112 //=================================================================================================
113 
114 //*************************************************************************************************
121 template< typename MT1 // Type of the left-hand side dense matrix
122  , typename MT2 > // Type of the right-hand side sparse matrix
123 class TSMatDMatMultExpr : public DenseMatrix< TSMatDMatMultExpr<MT1,MT2>, true >
124  , private MatMatMultExpr
125  , private Computation
126 {
127  private:
128  //**Type definitions****************************************************************************
129  typedef typename MT1::ResultType RT1;
130  typedef typename MT2::ResultType RT2;
131  typedef typename RT1::ElementType ET1;
132  typedef typename RT2::ElementType ET2;
133  typedef typename MT1::CompositeType CT1;
134  typedef typename MT2::CompositeType CT2;
135  //**********************************************************************************************
136 
137  //**********************************************************************************************
140  //**********************************************************************************************
141 
142  //**********************************************************************************************
144  enum { evaluateRight = IsComputation<MT2>::value || RequiresEvaluation<MT2>::value };
145  //**********************************************************************************************
146 
147  //**********************************************************************************************
149 
155  template< typename T1, typename T2, typename T3 >
156  struct CanExploitSymmetry {
157  enum { value = IsRowMajorMatrix<T1>::value && IsSymmetric<T2>::value };
158  };
160  //**********************************************************************************************
161 
162  //**********************************************************************************************
164 
168  template< typename T1, typename T2, typename T3 >
169  struct IsEvaluationRequired {
170  enum { value = ( evaluateLeft || evaluateRight ) &&
171  !CanExploitSymmetry<T1,T2,T3>::value };
172  };
174  //**********************************************************************************************
175 
176  //**********************************************************************************************
178 
182  template< typename T1, typename T2, typename T3 >
183  struct UseOptimizedKernel {
184  enum { value = !IsDiagonal<T3>::value &&
185  !IsResizable<typename T1::ElementType>::value &&
186  !IsResizable<ET1>::value };
187  };
189  //**********************************************************************************************
190 
191  //**********************************************************************************************
193 
196  template< typename T1, typename T2, typename T3 >
197  struct UseDefaultKernel {
198  enum { value = !UseOptimizedKernel<T1,T2,T3>::value };
199  };
201  //**********************************************************************************************
202 
203  public:
204  //**Type definitions****************************************************************************
210  typedef const ElementType ReturnType;
211  typedef const ResultType CompositeType;
212 
214  typedef typename SelectType< IsExpression<MT1>::value, const MT1, const MT1& >::Type LeftOperand;
215 
217  typedef typename SelectType< IsExpression<MT2>::value, const MT2, const MT2& >::Type RightOperand;
218 
221 
224  //**********************************************************************************************
225 
226  //**Compilation flags***************************************************************************
228  enum { vectorizable = 0 };
229 
231  enum { smpAssignable = !evaluateLeft && MT1::smpAssignable &&
232  !evaluateRight && MT2::smpAssignable };
233  //**********************************************************************************************
234 
235  //**Constructor*********************************************************************************
241  explicit inline TSMatDMatMultExpr( const MT1& lhs, const MT2& rhs )
242  : lhs_( lhs ) // Left-hand side sparse matrix of the multiplication expression
243  , rhs_( rhs ) // Right-hand side dense matrix of the multiplication expression
244  {
245  BLAZE_INTERNAL_ASSERT( lhs.columns() == rhs.rows(), "Invalid matrix sizes" );
246  }
247  //**********************************************************************************************
248 
249  //**Access operator*****************************************************************************
256  inline ReturnType operator()( size_t i, size_t j ) const {
257  BLAZE_INTERNAL_ASSERT( i < lhs_.rows() , "Invalid row access index" );
258  BLAZE_INTERNAL_ASSERT( j < rhs_.columns(), "Invalid column access index" );
259 
260  const size_t kbegin( ( IsUpper<MT1>::value )
261  ?( ( IsLower<MT2>::value )
262  ?( max( ( IsStrictlyUpper<MT1>::value ? i+1UL : i )
263  , ( IsStrictlyLower<MT2>::value ? j+1UL : j ) ) )
264  :( IsStrictlyUpper<MT1>::value ? i+1UL : i ) )
265  :( ( IsLower<MT2>::value )
266  ?( IsStrictlyLower<MT2>::value ? j+1UL : j )
267  :( 0UL ) ) );
268  const size_t kend( ( IsLower<MT1>::value )
269  ?( ( IsUpper<MT2>::value )
270  ?( min( ( IsStrictlyLower<MT1>::value ? i : i+1UL )
271  , ( IsStrictlyUpper<MT2>::value ? j : j+1UL ) ) )
272  :( IsStrictlyLower<MT1>::value ? i : i+1UL ) )
273  :( ( IsUpper<MT2>::value )
274  ?( IsStrictlyUpper<MT2>::value ? j : j+1UL )
275  :( lhs_.columns() ) ) );
276 
277  if( lhs_.columns() == 0UL ||
278  ( ( IsTriangular<MT1>::value || IsTriangular<MT2>::value ) && kbegin >= kend ) )
279  return ElementType();
280 
281  ElementType tmp( lhs_(i,kbegin) * rhs_(kbegin,j) );
282  for( size_t k=kbegin+1UL; k<kend; ++k ) {
283  tmp += lhs_(i,k) * rhs_(k,j);
284  }
285 
286  return tmp;
287  }
288  //**********************************************************************************************
289 
290  //**Rows function*******************************************************************************
295  inline size_t rows() const {
296  return lhs_.rows();
297  }
298  //**********************************************************************************************
299 
300  //**Columns function****************************************************************************
305  inline size_t columns() const {
306  return rhs_.columns();
307  }
308  //**********************************************************************************************
309 
310  //**Left operand access*************************************************************************
315  inline LeftOperand leftOperand() const {
316  return lhs_;
317  }
318  //**********************************************************************************************
319 
320  //**Right operand access************************************************************************
325  inline RightOperand rightOperand() const {
326  return rhs_;
327  }
328  //**********************************************************************************************
329 
330  //**********************************************************************************************
336  template< typename T >
337  inline bool canAlias( const T* alias ) const {
338  return ( lhs_.isAliased( alias ) || rhs_.isAliased( alias ) );
339  }
340  //**********************************************************************************************
341 
342  //**********************************************************************************************
348  template< typename T >
349  inline bool isAliased( const T* alias ) const {
350  return ( lhs_.isAliased( alias ) || rhs_.isAliased( alias ) );
351  }
352  //**********************************************************************************************
353 
354  //**********************************************************************************************
359  inline bool isAligned() const {
360  return rhs_.isAligned();
361  }
362  //**********************************************************************************************
363 
364  //**********************************************************************************************
369  inline bool canSMPAssign() const {
370  return ( columns() > SMP_TSMATDMATMULT_THRESHOLD );
371  }
372  //**********************************************************************************************
373 
374  private:
375  //**Member variables****************************************************************************
376  LeftOperand lhs_;
377  RightOperand rhs_;
378  //**********************************************************************************************
379 
380  //**Assignment to dense matrices****************************************************************
393  template< typename MT // Type of the target dense matrix
394  , bool SO > // Storage order of the target dense matrix
395  friend inline typename DisableIf< CanExploitSymmetry<MT,MT1,MT2> >::Type
396  assign( DenseMatrix<MT,SO>& lhs, const TSMatDMatMultExpr& rhs )
397  {
399 
400  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
401  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
402 
403  LT A( serial( rhs.lhs_ ) ); // Evaluation of the right-hand side sparse matrix operand
404  RT B( serial( rhs.rhs_ ) ); // Evaluation of the left-hand side dense matrix operand
405 
406  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
407  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
408  BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
409  BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
410  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
411  BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
412 
413  TSMatDMatMultExpr::selectAssignKernel( ~lhs, A, B );
414  }
416  //**********************************************************************************************
417 
418  //**Default assignment to dense matrices********************************************************
433  template< typename MT3 // Type of the left-hand side target matrix
434  , typename MT4 // Type of the left-hand side matrix operand
435  , typename MT5 > // Type of the right-hand side matrix operand
436  static inline typename EnableIf< UseDefaultKernel<MT3,MT4,MT5> >::Type
437  selectAssignKernel( MT3& C, const MT4& A, const MT5& B )
438  {
439  typedef typename MT4::ConstIterator ConstIterator;
440 
441  reset( C );
442 
444  {
445  for( size_t i=0UL; i<A.columns(); ++i )
446  {
447  const ConstIterator end( A.end(i) );
448  ConstIterator element( A.begin(i) );
449 
450  for( ; element!=end; ++element ) {
451  C(element->index(),i) = element->value() * B(i,i);
452  }
453  }
454  }
455  else
456  {
457  const size_t block( IsRowMajorMatrix<MT3>::value ? 256UL : 8UL );
458 
459  for( size_t jj=0UL; jj<B.columns(); jj+=block )
460  {
461  const size_t jpos( ( jj+block > B.columns() )?( B.columns() ):( jj+block ) );
462 
463  for( size_t i=0UL; i<A.columns(); ++i )
464  {
465  const ConstIterator end( A.end(i) );
466  ConstIterator element( A.begin(i) );
467 
468  const size_t jbegin( ( IsUpper<MT5>::value )
469  ?( max( IsStrictlyUpper<MT5>::value ? i+1UL : i, jj ) )
470  :( jj ) );
471  const size_t jend( ( IsLower<MT5>::value )
472  ?( min( IsStrictlyLower<MT5>::value ? i : i+1UL, jpos ) )
473  :( jpos ) );
474 
475  if( jbegin >= jend )
476  continue;
477 
478  for( ; element!=end; ++element ) {
479  for( size_t j=jbegin; j<jend; ++j ) {
480  if( isDefault( C(element->index(),j) ) )
481  C(element->index(),j) = element->value() * B(i,j);
482  else
483  C(element->index(),j) += element->value() * B(i,j);
484  }
485  }
486  }
487  }
488  }
489  }
491  //**********************************************************************************************
492 
493  //**Optimized assignment to dense matrices******************************************************
508  template< typename MT3 // Type of the left-hand side target matrix
509  , typename MT4 // Type of the left-hand side matrix operand
510  , typename MT5 > // Type of the right-hand side matrix operand
511  static inline typename EnableIf< UseOptimizedKernel<MT3,MT4,MT5> >::Type
512  selectAssignKernel( MT3& C, const MT4& A, const MT5& B )
513  {
514  typedef typename MT4::ConstIterator ConstIterator;
515 
516  const size_t block( ( IsRowMajorMatrix<MT3>::value )?( 256UL ):( 8UL ) );
517 
518  for( size_t jj=0UL; jj<B.columns(); jj+=block )
519  {
520  const size_t jpos( ( jj+block > B.columns() )?( B.columns() ):( jj+block ) );
521 
522  for( size_t i=0UL; i<A.rows(); ++i ) {
523  for( size_t j=jj; j<jpos; ++j ) {
524  reset( C(i,j) );
525  }
526  }
527 
528  for( size_t i=0UL; i<A.columns(); ++i )
529  {
530  const size_t jbegin( ( IsUpper<MT5>::value )
531  ?( max( IsStrictlyUpper<MT5>::value ? i+1UL : i, jj ) )
532  :( jj ) );
533  const size_t jend( ( IsLower<MT5>::value )
534  ?( min( IsStrictlyLower<MT5>::value ? i : i+1UL, jpos ) )
535  :( jpos ) );
536 
537  if( jbegin >= jend )
538  continue;
539 
540  const ConstIterator end( A.end(i) );
541  ConstIterator element( A.begin(i) );
542 
543  const size_t nonzeros( A.nonZeros(i) );
544  const size_t kpos( nonzeros & size_t(-4) );
545  BLAZE_INTERNAL_ASSERT( ( nonzeros - ( nonzeros % 4UL ) ) == kpos, "Invalid end calculation" );
546 
547  for( size_t k=0UL; k<kpos; k+=4UL )
548  {
549  const size_t i1( element->index() );
550  const ET1 v1( element->value() );
551  ++element;
552  const size_t i2( element->index() );
553  const ET1 v2( element->value() );
554  ++element;
555  const size_t i3( element->index() );
556  const ET1 v3( element->value() );
557  ++element;
558  const size_t i4( element->index() );
559  const ET1 v4( element->value() );
560  ++element;
561 
562  BLAZE_INTERNAL_ASSERT( i1 < i2 && i2 < i3 && i3 < i4, "Invalid sparse matrix index detected" );
563 
564  for( size_t j=jbegin; j<jend; ++j ) {
565  C(i1,j) += v1 * B(i,j);
566  C(i2,j) += v2 * B(i,j);
567  C(i3,j) += v3 * B(i,j);
568  C(i4,j) += v4 * B(i,j);
569  }
570  }
571 
572  for( ; element!=end; ++element ) {
573  for( size_t j=jbegin; j<jend; ++j ) {
574  C(element->index(),j) += element->value() * B(i,j);
575  }
576  }
577  }
578  }
579  }
581  //**********************************************************************************************
582 
583  //**Assignment to sparse matrices***************************************************************
596  template< typename MT // Type of the target sparse matrix
597  , bool SO > // Storage order of the target sparse matrix
598  friend inline typename DisableIf< CanExploitSymmetry<MT,MT1,MT2> >::Type
599  assign( SparseMatrix<MT,SO>& lhs, const TSMatDMatMultExpr& rhs )
600  {
602 
603  typedef typename SelectType< SO, ResultType, OppositeType >::Type TmpType;
604 
611 
612  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
613  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
614 
615  const TmpType tmp( serial( rhs ) );
616  assign( ~lhs, tmp );
617  }
619  //**********************************************************************************************
620 
621  //**Restructuring assignment to row-major matrices**********************************************
636  template< typename MT > // Type of the target matrix
637  friend inline typename EnableIf< CanExploitSymmetry<MT,MT1,MT2> >::Type
638  assign( Matrix<MT,false>& lhs, const TSMatDMatMultExpr& rhs )
639  {
641 
643 
644  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
645  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
646 
647  assign( ~lhs, trans( rhs.lhs_ ) * rhs.rhs_ );
648  }
650  //**********************************************************************************************
651 
652  //**Addition assignment to dense matrices*******************************************************
665  template< typename MT // Type of the target dense matrix
666  , bool SO > // Storage order of the target dense matrix
667  friend inline void addAssign( DenseMatrix<MT,SO>& lhs, const TSMatDMatMultExpr& rhs )
668  {
670 
671  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
672  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
673 
674  LT A( serial( rhs.lhs_ ) ); // Evaluation of the right-hand side sparse matrix operand
675  RT B( serial( rhs.rhs_ ) ); // Evaluation of the left-hand side dense matrix operand
676 
677  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
678  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
679  BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
680  BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
681  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
682  BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
683 
684  TSMatDMatMultExpr::selectAddAssignKernel( ~lhs, A, B );
685  }
687  //**********************************************************************************************
688 
689  //**Default addition assignment to dense matrices***********************************************
703  template< typename MT3 // Type of the left-hand side target matrix
704  , typename MT4 // Type of the left-hand side matrix operand
705  , typename MT5 > // Type of the right-hand side matrix operand
706  static inline typename EnableIf< UseDefaultKernel<MT3,MT4,MT5> >::Type
707  selectAddAssignKernel( MT3& C, const MT4& A, const MT5& B )
708  {
709  typedef typename MT4::ConstIterator ConstIterator;
710 
711  if( IsDiagonal<MT5>::value )
712  {
713  for( size_t i=0UL; i<A.columns(); ++i )
714  {
715  const ConstIterator end( A.end(i) );
716  ConstIterator element( A.begin(i) );
717 
718  for( ; element!=end; ++element ) {
719  C(element->index(),i) += element->value() * B(i,i);
720  }
721  }
722  }
723  else
724  {
725  const size_t block( IsRowMajorMatrix<MT3>::value ? 256UL : 8UL );
726 
727  for( size_t jj=0UL; jj<B.columns(); jj+=block )
728  {
729  const size_t jpos( ( jj+block > B.columns() )?( B.columns() ):( jj+block ) );
730 
731  for( size_t i=0UL; i<A.columns(); ++i )
732  {
733  const ConstIterator end( A.end(i) );
734  ConstIterator element( A.begin(i) );
735 
736  const size_t jbegin( ( IsUpper<MT5>::value )
737  ?( max( IsStrictlyUpper<MT5>::value ? i+1UL : i, jj ) )
738  :( jj ) );
739  const size_t jend( ( IsLower<MT5>::value )
740  ?( min( IsStrictlyLower<MT5>::value ? i : i+1UL, jpos ) )
741  :( jpos ) );
742 
743  if( jbegin >= jend )
744  continue;
745 
746  for( ; element!=end; ++element ) {
747  for( size_t j=jbegin; j<jend; ++j ) {
748  C(element->index(),j) += element->value() * B(i,j);
749  }
750  }
751  }
752  }
753  }
754  }
756  //**********************************************************************************************
757 
758  //**Optimized addition assignment to dense matrices*********************************************
772  template< typename MT3 // Type of the left-hand side target matrix
773  , typename MT4 // Type of the left-hand side matrix operand
774  , typename MT5 > // Type of the right-hand side matrix operand
775  static inline typename EnableIf< UseOptimizedKernel<MT3,MT4,MT5> >::Type
776  selectAddAssignKernel( MT3& C, const MT4& A, const MT5& B )
777  {
778  typedef typename MT4::ConstIterator ConstIterator;
779 
780  const size_t block( ( IsRowMajorMatrix<MT3>::value )?( 256UL ):( 8UL ) );
781 
782  for( size_t jj=0UL; jj<B.columns(); jj+=block )
783  {
784  const size_t jpos( ( jj+block > B.columns() )?( B.columns() ):( jj+block ) );
785 
786  for( size_t i=0UL; i<A.columns(); ++i )
787  {
788  const size_t jbegin( ( IsUpper<MT5>::value )
789  ?( max( IsStrictlyUpper<MT5>::value ? i+1UL : i, jj ) )
790  :( jj ) );
791  const size_t jend( ( IsLower<MT5>::value )
792  ?( min( IsStrictlyLower<MT5>::value ? i : i+1UL, jpos ) )
793  :( jpos ) );
794 
795  if( jbegin >= jend )
796  continue;
797 
798  const ConstIterator end( A.end(i) );
799  ConstIterator element( A.begin(i) );
800 
801  const size_t nonzeros( A.nonZeros(i) );
802  const size_t kpos( nonzeros & size_t(-4) );
803  BLAZE_INTERNAL_ASSERT( ( nonzeros - ( nonzeros % 4UL ) ) == kpos, "Invalid end calculation" );
804 
805  for( size_t k=0UL; k<kpos; k+=4UL )
806  {
807  const size_t i1( element->index() );
808  const ET1 v1( element->value() );
809  ++element;
810  const size_t i2( element->index() );
811  const ET1 v2( element->value() );
812  ++element;
813  const size_t i3( element->index() );
814  const ET1 v3( element->value() );
815  ++element;
816  const size_t i4( element->index() );
817  const ET1 v4( element->value() );
818  ++element;
819 
820  BLAZE_INTERNAL_ASSERT( i1 < i2 && i2 < i3 && i3 < i4, "Invalid sparse matrix index detected" );
821 
822  for( size_t j=jbegin; j<jend; ++j ) {
823  C(i1,j) += v1 * B(i,j);
824  C(i2,j) += v2 * B(i,j);
825  C(i3,j) += v3 * B(i,j);
826  C(i4,j) += v4 * B(i,j);
827  }
828  }
829 
830  for( ; element!=end; ++element ) {
831  for( size_t j=jbegin; j<jend; ++j ) {
832  C(element->index(),j) += element->value() * B(i,j);
833  }
834  }
835  }
836  }
837  }
839  //**********************************************************************************************
840 
841  //**Restructuring addition assignment to row-major matrices*************************************
856  template< typename MT > // Type of the target matrix
857  friend inline typename EnableIf< CanExploitSymmetry<MT,MT1,MT2> >::Type
858  addAssign( Matrix<MT,false>& lhs, const TSMatDMatMultExpr& rhs )
859  {
861 
863 
864  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
865  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
866 
867  addAssign( ~lhs, trans( rhs.lhs_ ) * rhs.rhs_ );
868  }
870  //**********************************************************************************************
871 
872  //**Addition assignment to sparse matrices******************************************************
873  // No special implementation for the addition assignment to sparse matrices.
874  //**********************************************************************************************
875 
876  //**Subtraction assignment to dense matrices****************************************************
889  template< typename MT // Type of the target dense matrix
890  , bool SO > // Storage order of the target dense matrix
891  friend inline void subAssign( DenseMatrix<MT,SO>& lhs, const TSMatDMatMultExpr& rhs )
892  {
894 
895  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
896  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
897 
898  LT A( serial( rhs.lhs_ ) ); // Evaluation of the right-hand side sparse matrix operand
899  RT B( serial( rhs.rhs_ ) ); // Evaluation of the left-hand side dense matrix operand
900 
901  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
902  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
903  BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
904  BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
905  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
906  BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
907 
908  TSMatDMatMultExpr::selectSubAssignKernel( ~lhs, A, B );
909  }
911  //**********************************************************************************************
912 
913  //**Default subtraction assignment to dense matrices********************************************
927  template< typename MT3 // Type of the left-hand side target matrix
928  , typename MT4 // Type of the left-hand side matrix operand
929  , typename MT5 > // Type of the right-hand side matrix operand
930  static inline typename EnableIf< UseDefaultKernel<MT3,MT4,MT5> >::Type
931  selectSubAssignKernel( MT3& C, const MT4& A, const MT5& B )
932  {
933  typedef typename MT4::ConstIterator ConstIterator;
934 
935  if( IsDiagonal<MT5>::value )
936  {
937  for( size_t i=0UL; i<A.columns(); ++i )
938  {
939  const ConstIterator end( A.end(i) );
940  ConstIterator element( A.begin(i) );
941 
942  for( ; element!=end; ++element ) {
943  C(element->index(),i) -= element->value() * B(i,i);
944  }
945  }
946  }
947  else
948  {
949  const size_t block( IsRowMajorMatrix<MT3>::value ? 256UL : 8UL );
950 
951  for( size_t jj=0UL; jj<B.columns(); jj+=block )
952  {
953  const size_t jpos( ( jj+block > B.columns() )?( B.columns() ):( jj+block ) );
954 
955  for( size_t i=0UL; i<A.columns(); ++i )
956  {
957  const ConstIterator end( A.end(i) );
958  ConstIterator element( A.begin(i) );
959 
960  const size_t jbegin( ( IsUpper<MT5>::value )
961  ?( max( IsStrictlyUpper<MT5>::value ? i+1UL : i, jj ) )
962  :( jj ) );
963  const size_t jend( ( IsLower<MT5>::value )
964  ?( min( IsStrictlyLower<MT5>::value ? i : i+1UL, jpos ) )
965  :( jpos ) );
966 
967  if( jbegin >= jend )
968  continue;
969 
970  for( ; element!=end; ++element ) {
971  for( size_t j=jbegin; j<jend; ++j ) {
972  C(element->index(),j) -= element->value() * B(i,j);
973  }
974  }
975  }
976  }
977  }
978  }
980  //**********************************************************************************************
981 
982  //**Optimized subtraction assignment to dense matrices******************************************
996  template< typename MT3 // Type of the left-hand side target matrix
997  , typename MT4 // Type of the left-hand side matrix operand
998  , typename MT5 > // Type of the right-hand side matrix operand
999  static inline typename EnableIf< UseOptimizedKernel<MT3,MT4,MT5> >::Type
1000  selectSubAssignKernel( MT3& C, const MT4& A, const MT5& B )
1001  {
1002  typedef typename MT4::ConstIterator ConstIterator;
1003 
1004  const size_t block( ( IsRowMajorMatrix<MT3>::value )?( 256UL ):( 8UL ) );
1005 
1006  for( size_t jj=0UL; jj<B.columns(); jj+=block )
1007  {
1008  const size_t jpos( ( jj+block > B.columns() )?( B.columns() ):( jj+block ) );
1009 
1010  for( size_t i=0UL; i<A.columns(); ++i )
1011  {
1012  const size_t jbegin( ( IsUpper<MT5>::value )
1013  ?( max( IsStrictlyUpper<MT5>::value ? i+1UL : i, jj ) )
1014  :( jj ) );
1015  const size_t jend( ( IsLower<MT5>::value )
1016  ?( min( IsStrictlyLower<MT5>::value ? i : i+1UL, jpos ) )
1017  :( jpos ) );
1018 
1019  if( jbegin >= jend )
1020  continue;
1021 
1022  const ConstIterator end( A.end(i) );
1023  ConstIterator element( A.begin(i) );
1024 
1025  const size_t nonzeros( A.nonZeros(i) );
1026  const size_t kpos( nonzeros & size_t(-4) );
1027  BLAZE_INTERNAL_ASSERT( ( nonzeros - ( nonzeros % 4UL ) ) == kpos, "Invalid end calculation" );
1028 
1029  for( size_t k=0UL; k<kpos; k+=4UL )
1030  {
1031  const size_t i1( element->index() );
1032  const ET1 v1( element->value() );
1033  ++element;
1034  const size_t i2( element->index() );
1035  const ET1 v2( element->value() );
1036  ++element;
1037  const size_t i3( element->index() );
1038  const ET1 v3( element->value() );
1039  ++element;
1040  const size_t i4( element->index() );
1041  const ET1 v4( element->value() );
1042  ++element;
1043 
1044  BLAZE_INTERNAL_ASSERT( i1 < i2 && i2 < i3 && i3 < i4, "Invalid sparse matrix index detected" );
1045 
1046  for( size_t j=jbegin; j<jend; ++j ) {
1047  C(i1,j) -= v1 * B(i,j);
1048  C(i2,j) -= v2 * B(i,j);
1049  C(i3,j) -= v3 * B(i,j);
1050  C(i4,j) -= v4 * B(i,j);
1051  }
1052  }
1053 
1054  for( ; element!=end; ++element ) {
1055  for( size_t j=jbegin; j<jend; ++j ) {
1056  C(element->index(),j) -= element->value() * B(i,j);
1057  }
1058  }
1059  }
1060  }
1061  }
1063  //**********************************************************************************************
1064 
1065  //**Restructuring subtraction assignment to row-major matrices**********************************
1080  template< typename MT > // Type of the target matrix
1081  friend inline typename EnableIf< CanExploitSymmetry<MT,MT1,MT2> >::Type
1082  subAssign( Matrix<MT,false>& lhs, const TSMatDMatMultExpr& rhs )
1083  {
1085 
1087 
1088  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
1089  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
1090 
1091  subAssign( ~lhs, trans( rhs.lhs_ ) * rhs.rhs_ );
1092  }
1094  //**********************************************************************************************
1095 
1096  //**Subtraction assignment to sparse matrices***************************************************
1097  // No special implementation for the subtraction assignment to sparse matrices.
1098  //**********************************************************************************************
1099 
1100  //**Multiplication assignment to dense matrices*************************************************
1101  // No special implementation for the multiplication assignment to dense matrices.
1102  //**********************************************************************************************
1103 
1104  //**Multiplication assignment to sparse matrices************************************************
1105  // No special implementation for the multiplication assignment to sparse matrices.
1106  //**********************************************************************************************
1107 
1108  //**SMP assignment to dense matrices************************************************************
1124  template< typename MT // Type of the target dense matrix
1125  , bool SO > // Storage order of the target dense matrix
1126  friend inline typename EnableIf< IsEvaluationRequired<MT,MT1,MT2> >::Type
1127  smpAssign( DenseMatrix<MT,SO>& lhs, const TSMatDMatMultExpr& rhs )
1128  {
1130 
1131  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
1132  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
1133 
1134  LT A( rhs.lhs_ ); // Evaluation of the right-hand side sparse matrix operand
1135  RT B( rhs.rhs_ ); // Evaluation of the left-hand side dense matrix operand
1136 
1137  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
1138  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
1139  BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
1140  BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
1141  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
1142  BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
1143 
1144  smpAssign( ~lhs, A * B );
1145  }
1147  //**********************************************************************************************
1148 
1149  //**SMP assignment to sparse matrices***********************************************************
1165  template< typename MT // Type of the target sparse matrix
1166  , bool SO > // Storage order of the target sparse matrix
1167  friend inline typename EnableIf< IsEvaluationRequired<MT,MT1,MT2> >::Type
1168  smpAssign( SparseMatrix<MT,SO>& lhs, const TSMatDMatMultExpr& rhs )
1169  {
1171 
1172  typedef typename SelectType< SO, ResultType, OppositeType >::Type TmpType;
1173 
1180 
1181  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
1182  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
1183 
1184  const TmpType tmp( rhs );
1185  smpAssign( ~lhs, tmp );
1186  }
1188  //**********************************************************************************************
1189 
1190  //**Restructuring SMP assignment to row-major matrices******************************************
1205  template< typename MT > // Type of the target matrix
1206  friend inline typename EnableIf< CanExploitSymmetry<MT,MT1,MT2> >::Type
1207  smpAssign( Matrix<MT,false>& lhs, const TSMatDMatMultExpr& rhs )
1208  {
1210 
1211  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
1212  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
1213 
1214  smpAssign( ~lhs, trans( rhs.lhs_ ) * rhs.rhs_ );
1215  }
1217  //**********************************************************************************************
1218 
1219  //**SMP addition assignment to dense matrices***************************************************
1235  template< typename MT // Type of the target dense matrix
1236  , bool SO > // Storage order of the target dense matrix
1237  friend inline typename EnableIf< IsEvaluationRequired<MT,MT1,MT2> >::Type
1238  smpAddAssign( DenseMatrix<MT,SO>& lhs, const TSMatDMatMultExpr& rhs )
1239  {
1241 
1242  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
1243  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
1244 
1245  LT A( rhs.lhs_ ); // Evaluation of the right-hand side sparse matrix operand
1246  RT B( rhs.rhs_ ); // Evaluation of the left-hand side dense matrix operand
1247 
1248  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
1249  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
1250  BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
1251  BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
1252  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
1253  BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
1254 
1255  smpAddAssign( ~lhs, A * B );
1256  }
1258  //**********************************************************************************************
1259 
1260  //**Restructuring SMP addition assignment to row-major matrices*********************************
1275  template< typename MT > // Type of the target matrix
1276  friend inline typename EnableIf< CanExploitSymmetry<MT,MT1,MT2> >::Type
1277  smpAddAssign( Matrix<MT,false>& lhs, const TSMatDMatMultExpr& rhs )
1278  {
1280 
1281  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
1282  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
1283 
1284  smpAddAssign( ~lhs, trans( rhs.lhs_ ) * rhs.rhs_ );
1285  }
1287  //**********************************************************************************************
1288 
1289  //**SMP addition assignment to sparse matrices**************************************************
1290  // No special implementation for the SMP addition assignment to sparse matrices.
1291  //**********************************************************************************************
1292 
1293  //**SMP subtraction assignment to dense matrices************************************************
1309  template< typename MT // Type of the target dense matrix
1310  , bool SO > // Storage order of the target dense matrix
1311  friend inline typename EnableIf< IsEvaluationRequired<MT,MT1,MT2> >::Type
1312  smpSubAssign( DenseMatrix<MT,SO>& lhs, const TSMatDMatMultExpr& rhs )
1313  {
1315 
1316  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
1317  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
1318 
1319  LT A( rhs.lhs_ ); // Evaluation of the right-hand side sparse matrix operand
1320  RT B( rhs.rhs_ ); // Evaluation of the left-hand side dense matrix operand
1321 
1322  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
1323  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
1324  BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
1325  BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
1326  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
1327  BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
1328 
1329  smpSubAssign( ~lhs, A * B );
1330  }
1332  //**********************************************************************************************
1333 
1334  //**Restructuring SMP subtraction assignment to row-major matrices******************************
1349  template< typename MT > // Type of the target matrix
1350  friend inline typename EnableIf< CanExploitSymmetry<MT,MT1,MT2> >::Type
1351  smpSubAssign( Matrix<MT,false>& lhs, const TSMatDMatMultExpr& rhs )
1352  {
1354 
1355  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
1356  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
1357 
1358  smpSubAssign( ~lhs, trans( rhs.lhs_ ) * rhs.rhs_ );
1359  }
1361  //**********************************************************************************************
1362 
1363  //**SMP subtraction assignment to sparse matrices***********************************************
1364  // No special implementation for the SMP subtraction assignment to sparse matrices.
1365  //**********************************************************************************************
1366 
1367  //**SMP multiplication assignment to dense matrices*********************************************
1368  // No special implementation for the SMP multiplication assignment to dense matrices.
1369  //**********************************************************************************************
1370 
1371  //**SMP multiplication assignment to sparse matrices********************************************
1372  // No special implementation for the SMP multiplication assignment to sparse matrices.
1373  //**********************************************************************************************
1374 
1375  //**Compile time checks*************************************************************************
1383  //**********************************************************************************************
1384 };
1385 //*************************************************************************************************
1386 
1387 
1388 
1389 
1390 //=================================================================================================
1391 //
1392 // GLOBAL BINARY ARITHMETIC OPERATORS
1393 //
1394 //=================================================================================================
1395 
1396 //*************************************************************************************************
1427 template< typename T1 // Type of the left-hand side sparse matrix
1428  , typename T2 > // Type of the right-hand side dense matrix
1429 inline const TSMatDMatMultExpr<T1,T2>
1431 {
1433 
1434  if( (~lhs).columns() != (~rhs).rows() )
1435  throw std::invalid_argument( "Matrix sizes do not match" );
1436 
1437  return TSMatDMatMultExpr<T1,T2>( ~lhs, ~rhs );
1438 }
1439 //*************************************************************************************************
1440 
1441 
1442 
1443 
1444 //=================================================================================================
1445 //
1446 // ROWS SPECIALIZATIONS
1447 //
1448 //=================================================================================================
1449 
1450 //*************************************************************************************************
1452 template< typename MT1, typename MT2 >
1453 struct Rows< TSMatDMatMultExpr<MT1,MT2> >
1454  : public Rows<MT1>
1455 {};
1457 //*************************************************************************************************
1458 
1459 
1460 
1461 
1462 //=================================================================================================
1463 //
1464 // COLUMNS SPECIALIZATIONS
1465 //
1466 //=================================================================================================
1467 
1468 //*************************************************************************************************
1470 template< typename MT1, typename MT2 >
1471 struct Columns< TSMatDMatMultExpr<MT1,MT2> >
1472  : public Columns<MT2>
1473 {};
1475 //*************************************************************************************************
1476 
1477 
1478 
1479 
1480 //=================================================================================================
1481 //
1482 // ISLOWER SPECIALIZATIONS
1483 //
1484 //=================================================================================================
1485 
1486 //*************************************************************************************************
1488 template< typename MT1, typename MT2 >
1489 struct IsLower< TSMatDMatMultExpr<MT1,MT2> >
1490  : public IsTrue< And< IsLower<MT1>, IsLower<MT2> >::value >
1491 {};
1493 //*************************************************************************************************
1494 
1495 
1496 
1497 
1498 //=================================================================================================
1499 //
1500 // ISUNILOWER SPECIALIZATIONS
1501 //
1502 //=================================================================================================
1503 
1504 //*************************************************************************************************
1506 template< typename MT1, typename MT2 >
1507 struct IsUniLower< TSMatDMatMultExpr<MT1,MT2> >
1508  : public IsTrue< And< IsUniLower<MT1>, IsUniLower<MT2> >::value >
1509 {};
1511 //*************************************************************************************************
1512 
1513 
1514 
1515 
1516 //=================================================================================================
1517 //
1518 // ISSTRICTLYLOWER SPECIALIZATIONS
1519 //
1520 //=================================================================================================
1521 
1522 //*************************************************************************************************
1524 template< typename MT1, typename MT2 >
1525 struct IsStrictlyLower< TSMatDMatMultExpr<MT1,MT2> >
1526  : public IsTrue< Or< And< IsStrictlyLower<MT1>, IsLower<MT2> >
1527  , And< IsStrictlyLower<MT2>, IsLower<MT1> > >::value >
1528 {};
1530 //*************************************************************************************************
1531 
1532 
1533 
1534 
1535 //=================================================================================================
1536 //
1537 // ISUPPER SPECIALIZATIONS
1538 //
1539 //=================================================================================================
1540 
1541 //*************************************************************************************************
1543 template< typename MT1, typename MT2 >
1544 struct IsUpper< TSMatDMatMultExpr<MT1,MT2> >
1545  : public IsTrue< And< IsUpper<MT1>, IsUpper<MT2> >::value >
1546 {};
1548 //*************************************************************************************************
1549 
1550 
1551 
1552 
1553 //=================================================================================================
1554 //
1555 // ISUNIUPPER SPECIALIZATIONS
1556 //
1557 //=================================================================================================
1558 
1559 //*************************************************************************************************
1561 template< typename MT1, typename MT2 >
1562 struct IsUniUpper< TSMatDMatMultExpr<MT1,MT2> >
1563  : public IsTrue< And< IsUniUpper<MT1>, IsUniUpper<MT2> >::value >
1564 {};
1566 //*************************************************************************************************
1567 
1568 
1569 
1570 
1571 //=================================================================================================
1572 //
1573 // ISSTRICTLYUPPER SPECIALIZATIONS
1574 //
1575 //=================================================================================================
1576 
1577 //*************************************************************************************************
1579 template< typename MT1, typename MT2 >
1580 struct IsStrictlyUpper< TSMatDMatMultExpr<MT1,MT2> >
1581  : public IsTrue< Or< And< IsStrictlyUpper<MT1>, IsUpper<MT2> >
1582  , And< IsStrictlyUpper<MT2>, IsUpper<MT1> > >::value >
1583 {};
1585 //*************************************************************************************************
1586 
1587 
1588 
1589 
1590 //=================================================================================================
1591 //
1592 // EXPRESSION TRAIT SPECIALIZATIONS
1593 //
1594 //=================================================================================================
1595 
1596 //*************************************************************************************************
1598 template< typename MT1, typename MT2, typename VT >
1599 struct TDMatDVecMultExprTrait< TSMatDMatMultExpr<MT1,MT2>, VT >
1600 {
1601  public:
1602  //**********************************************************************************************
1603  typedef typename SelectType< IsSparseMatrix<MT1>::value && IsColumnMajorMatrix<MT1>::value &&
1604  IsDenseMatrix<MT2>::value && IsRowMajorMatrix<MT2>::value &&
1605  IsDenseVector<VT>::value && IsColumnVector<VT>::value
1606  , typename TSMatDVecMultExprTrait< MT1, typename DMatDVecMultExprTrait<MT2,VT>::Type >::Type
1607  , INVALID_TYPE >::Type Type;
1608  //**********************************************************************************************
1609 };
1611 //*************************************************************************************************
1612 
1613 
1614 //*************************************************************************************************
1616 template< typename MT1, typename MT2, typename VT >
1617 struct TDMatSVecMultExprTrait< TSMatDMatMultExpr<MT1,MT2>, VT >
1618 {
1619  public:
1620  //**********************************************************************************************
1621  typedef typename SelectType< IsSparseMatrix<MT1>::value && IsColumnMajorMatrix<MT1>::value &&
1622  IsDenseMatrix<MT2>::value && IsRowMajorMatrix<MT2>::value &&
1623  IsSparseVector<VT>::value && IsColumnVector<VT>::value
1624  , typename TSMatDVecMultExprTrait< MT1, typename DMatSVecMultExprTrait<MT2,VT>::Type >::Type
1625  , INVALID_TYPE >::Type Type;
1626  //**********************************************************************************************
1627 };
1629 //*************************************************************************************************
1630 
1631 
1632 //*************************************************************************************************
1634 template< typename VT, typename MT1, typename MT2 >
1635 struct TDVecTDMatMultExprTrait< VT, TSMatDMatMultExpr<MT1,MT2> >
1636 {
1637  public:
1638  //**********************************************************************************************
1639  typedef typename SelectType< IsDenseVector<VT>::value && IsRowVector<VT>::value &&
1640  IsSparseMatrix<MT1>::value && IsColumnMajorMatrix<MT1>::value &&
1641  IsDenseMatrix<MT2>::value && IsRowMajorMatrix<MT2>::value
1642  , typename TDVecDMatMultExprTrait< typename TDVecTSMatMultExprTrait<VT,MT1>::Type, MT2 >::Type
1643  , INVALID_TYPE >::Type Type;
1644  //**********************************************************************************************
1645 };
1647 //*************************************************************************************************
1648 
1649 
1650 //*************************************************************************************************
1652 template< typename VT, typename MT1, typename MT2 >
1653 struct TSVecTDMatMultExprTrait< VT, TSMatDMatMultExpr<MT1,MT2> >
1654 {
1655  public:
1656  //**********************************************************************************************
1657  typedef typename SelectType< IsSparseVector<VT>::value && IsRowVector<VT>::value &&
1658  IsSparseMatrix<MT1>::value && IsColumnMajorMatrix<MT1>::value &&
1659  IsDenseMatrix<MT2>::value && IsRowMajorMatrix<MT2>::value
1660  , typename TDVecDMatMultExprTrait< typename TDVecTSMatMultExprTrait<VT,MT1>::Type, MT2 >::Type
1661  , INVALID_TYPE >::Type Type;
1662  //**********************************************************************************************
1663 };
1665 //*************************************************************************************************
1666 
1667 
1668 //*************************************************************************************************
1670 template< typename MT1, typename MT2, bool AF >
1671 struct SubmatrixExprTrait< TSMatDMatMultExpr<MT1,MT2>, AF >
1672 {
1673  public:
1674  //**********************************************************************************************
1675  typedef typename MultExprTrait< typename SubmatrixExprTrait<const MT1,AF>::Type
1676  , typename SubmatrixExprTrait<const MT2,AF>::Type >::Type Type;
1677  //**********************************************************************************************
1678 };
1680 //*************************************************************************************************
1681 
1682 
1683 //*************************************************************************************************
1685 template< typename MT1, typename MT2 >
1686 struct RowExprTrait< TSMatDMatMultExpr<MT1,MT2> >
1687 {
1688  public:
1689  //**********************************************************************************************
1690  typedef typename MultExprTrait< typename RowExprTrait<const MT1>::Type, MT2 >::Type Type;
1691  //**********************************************************************************************
1692 };
1694 //*************************************************************************************************
1695 
1696 
1697 //*************************************************************************************************
1699 template< typename MT1, typename MT2 >
1700 struct ColumnExprTrait< TSMatDMatMultExpr<MT1,MT2> >
1701 {
1702  public:
1703  //**********************************************************************************************
1704  typedef typename MultExprTrait< MT1, typename ColumnExprTrait<const MT2>::Type >::Type Type;
1705  //**********************************************************************************************
1706 };
1708 //*************************************************************************************************
1709 
1710 } // namespace blaze
1711 
1712 #endif
LeftOperand lhs_
Left-hand side sparse matrix of the multiplication expression.
Definition: TSMatDMatMultExpr.h:376
const MT::ElementType max(const DenseMatrix< MT, SO > &dm)
Returns the largest element of the dense matrix.
Definition: DenseMatrix.h:1649
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.
SelectType< evaluateLeft, const RT1, CT1 >::Type LT
Type for the assignment of the left-hand side sparse matrix operand.
Definition: TSMatDMatMultExpr.h:220
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:8247
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.
MT2::CompositeType CT2
Composite type of the right-hand side dense matrix expression.
Definition: TSMatDMatMultExpr.h:134
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:258
Header file for the IsSparseMatrix type trait.
Efficient implementation of a compressed matrix.The CompressedMatrix class template is the represent...
Definition: CompressedMatrix.h:209
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.
Header file for the IsColumnMajorMatrix type trait.
void reset(const DiagonalProxy< MT > &proxy)
Resetting the represented element to the default initial values.
Definition: DiagonalProxy.h:821
Header file for the TSVecTSMatMultExprTrait class template.
const This & CompositeType
Data type for composite expression templates.
Definition: CompressedMatrix.h:2507
Header file for the IsRowVector type trait.
Type ElementType
Type of the sparse matrix elements.
Definition: CompressedMatrix.h:261
Compile time check for lower triangular matrices.This type trait tests whether or not the given templ...
Definition: IsLower.h:90
const DMatSerialExpr< MT, SO > serial(const DenseMatrix< MT, SO > &dm)
Forces the serial evaluation of the given dense matrix expression dm.
Definition: DMatSerialExpr.h:699
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
size_t rows() const
Returns the current number of rows of the matrix.
Definition: TSMatDMatMultExpr.h:295
Header file for the IsUniLower type trait.
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:107
bool canSMPAssign() const
Returns whether the expression can be used in SMP assignments.
Definition: TSMatDMatMultExpr.h:369
bool isDefault(const DiagonalProxy< MT > &proxy)
Returns whether the represented element is in default state.
Definition: DiagonalProxy.h:861
Constraint on the data type.
Constraint on the data type.
Header file for the MultExprTrait class template.
size_t columns() const
Returns the current number of columns of the matrix.
Definition: TSMatDMatMultExpr.h:305
Compile time check to query the requirement to evaluate an expression.Via this type trait it is possi...
Definition: RequiresEvaluation.h:90
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.
SelectType< IsExpression< MT2 >::value, const MT2, const MT2 & >::Type RightOperand
Composite type of the right-hand side dense matrix expression.
Definition: TSMatDMatMultExpr.h:217
Header file for the multiplication trait.
Header file for the IsStrictlyUpper type trait.
Header file for the IsSymmetric type trait.
SelectType< evaluateRight, const RT2, CT2 >::Type RT
Type for the assignment of the right-hand side dense matrix operand.
Definition: TSMatDMatMultExpr.h:223
Namespace of the Blaze C++ math library.
Definition: Blaze.h:57
ResultType::OppositeType OppositeType
Result type with opposite storage order for expression template evaluations.
Definition: TSMatDMatMultExpr.h:207
#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: StorageOrder.h:161
ReturnType operator()(size_t i, size_t j) const
2D-access to the matrix elements.
Definition: TSMatDMatMultExpr.h:256
Header file for the TSVecTDMatMultExprTrait class template.
const Element * ConstIterator
Iterator over constant elements.
Definition: CompressedMatrix.h:2511
Header file for the TDMatSVecMultExprTrait class template.
bool isAliased(const T *alias) const
Returns whether the expression is aliased with the given address alias.
Definition: TSMatDMatMultExpr.h:349
Header file for the TDVecTSMatMultExprTrait class template.
const MT::ElementType min(const DenseMatrix< MT, SO > &dm)
Returns the smallest element of the dense matrix.
Definition: DenseMatrix.h:1602
Header file for the DenseMatrix base class.
BLAZE_ALWAYS_INLINE void assign(Matrix< MT1, SO1 > &lhs, const Matrix< MT2, SO2 > &rhs)
Default implementation of the assignment of a matrix to a matrix.
Definition: Matrix.h:635
Header file for the Columns type trait.
Header file for the TSMatDVecMultExprTrait class template.
const size_t SMP_TSMATDMATMULT_THRESHOLD
SMP column-major sparse matrix/row-major dense matrix multiplication threshold.This threshold specifi...
Definition: Thresholds.h:1064
Header file for the DMatDVecMultExprTrait class template.
Header file for the IsLower type trait.
Compile time check for diagonal matrices.This type trait tests whether or not the given template para...
Definition: IsDiagonal.h:92
TSMatDMatMultExpr(const MT1 &lhs, const MT2 &rhs)
Constructor for the TSMatDMatMultExpr class.
Definition: TSMatDMatMultExpr.h:241
#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
RT1::ElementType ET1
Element type of the left-hand side dense matrix expression.
Definition: TSMatDMatMultExpr.h:131
Header file for the IsTriangular type trait.
Constraints on the storage order of matrix types.
MultTrait< RT1, RT2 >::Type ResultType
Result type for expression template evaluations.
Definition: TSMatDMatMultExpr.h:206
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:2505
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.
bool isAligned() const
Returns whether the operands of the expression are properly aligned in memory.
Definition: TSMatDMatMultExpr.h:359
Header file for the EnableIf class template.
Header file for the IsStrictlyLower type trait.
MT1::ResultType RT1
Result type of the left-hand side sparse matrix expression.
Definition: TSMatDMatMultExpr.h:129
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::TransposeType TransposeType
Transpose type for expression template evaluations.
Definition: TSMatDMatMultExpr.h:208
TSMatDMatMultExpr< MT1, MT2 > This
Type of this TSMatDMatMultExpr instance.
Definition: TSMatDMatMultExpr.h:205
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
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: StorageOrder.h:81
const ElementType ReturnType
Return type for expression template evaluations.
Definition: TSMatDMatMultExpr.h:210
LeftOperand leftOperand() const
Returns the left-hand side transpose sparse matrix operand.
Definition: TSMatDMatMultExpr.h:315
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
Utility type for generic codes.
Base template for the MultTrait class.
Definition: MultTrait.h:150
BLAZE_ALWAYS_INLINE void addAssign(Matrix< MT1, SO1 > &lhs, const Matrix< MT2, SO2 > &rhs)
Default implementation of the addition assignment of a matrix to a matrix.
Definition: Matrix.h:742
RT2::ElementType ET2
Element type of the right-hand side sparse matrix expression.
Definition: TSMatDMatMultExpr.h:132
RightOperand rightOperand() const
Returns the right-hand side dense matrix operand.
Definition: TSMatDMatMultExpr.h:325
const ResultType CompositeType
Data type for composite expression templates.
Definition: TSMatDMatMultExpr.h:211
RightOperand rhs_
Right-hand side dense matrix of the multiplication expression.
Definition: TSMatDMatMultExpr.h:377
Substitution Failure Is Not An Error (SFINAE) class.The EnableIf class template is an auxiliary tool ...
Definition: EnableIf.h:184
Header file for the reset shim.
Header file for the isDefault shim.
MT1::CompositeType CT1
Composite type of the left-hand side sparse matrix expression.
Definition: TSMatDMatMultExpr.h:133
Header file for the RemoveReference type trait.
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:283
Header file for the IsDenseVector type trait.
bool canAlias(const T *alias) const
Returns whether the expression can alias with the given address alias.
Definition: TSMatDMatMultExpr.h:337
Compile time check for strictly lower triangular matrices.This type trait tests whether or not the gi...
Definition: IsStrictlyLower.h:86
Header file for the IsRowMajorMatrix type trait.
ResultType::ElementType ElementType
Resulting element type.
Definition: TSMatDMatMultExpr.h:209
const DMatTransExpr< MT,!SO > trans(const DenseMatrix< MT, SO > &dm)
Calculation of the transpose of the given dense matrix.
Definition: DMatTransExpr.h:937
Header file for the IsComputation type trait class.
MT2::ResultType RT2
Result type of the right-hand side dense matrix expression.
Definition: TSMatDMatMultExpr.h:130
Expression object for transpose sparse matrix-dense matrix multiplications.The TSMatDMatMultExpr clas...
Definition: Forward.h:137
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
Header file for the TDMatDVecMultExprTrait class template.
#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:2502
Header file for the IsTrue value trait.
Header file for the TSVecDMatMultExprTrait class template.
Header file for the IsUpper type trait.
Header file for the DMatSVecMultExprTrait class template.
Header file for the IsColumnVector type trait.
SelectType< IsExpression< MT1 >::value, const MT1, const MT1 & >::Type LeftOperand
Composite type of the left-hand side sparse matrix expression.
Definition: TSMatDMatMultExpr.h:214
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
Header file for the TDVecTDMatMultExprTrait class template.
#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.
BLAZE_ALWAYS_INLINE void subAssign(Matrix< MT1, SO1 > &lhs, const Matrix< MT2, SO2 > &rhs)
Default implementation of the subtraction assignment of a matrix to matrix.
Definition: Matrix.h:849