TSMatTDMatMultExpr.h
Go to the documentation of this file.
1 //=================================================================================================
33 //=================================================================================================
34 
35 #ifndef _BLAZE_MATH_EXPRESSIONS_TSMATTDMATMULTEXPR_H_
36 #define _BLAZE_MATH_EXPRESSIONS_TSMATTDMATMULTEXPR_H_
37 
38 
39 //*************************************************************************************************
40 // Includes
41 //*************************************************************************************************
42 
43 #include <stdexcept>
52 #include <blaze/math/Functions.h>
54 #include <blaze/math/shims/Reset.h>
90 #include <blaze/util/Assert.h>
91 #include <blaze/util/DisableIf.h>
92 #include <blaze/util/EnableIf.h>
93 #include <blaze/util/InvalidType.h>
95 #include <blaze/util/mpl/And.h>
96 #include <blaze/util/mpl/Or.h>
97 #include <blaze/util/SelectType.h>
98 #include <blaze/util/Types.h>
101 
102 
103 namespace blaze {
104 
105 //=================================================================================================
106 //
107 // CLASS SMATDMATMULTEXPR
108 //
109 //=================================================================================================
110 
111 //*************************************************************************************************
118 template< typename MT1 // Type of the left-hand side dense matrix
119  , typename MT2 > // Type of the right-hand side sparse matrix
120 class TSMatTDMatMultExpr : public DenseMatrix< TSMatTDMatMultExpr<MT1,MT2>, true >
121  , private MatMatMultExpr
122  , private Computation
123 {
124  private:
125  //**Type definitions****************************************************************************
126  typedef typename MT1::ResultType RT1;
127  typedef typename MT2::ResultType RT2;
128  typedef typename RT1::ElementType ET1;
129  typedef typename RT2::ElementType ET2;
130  typedef typename MT1::CompositeType CT1;
131  typedef typename MT2::CompositeType CT2;
132  //**********************************************************************************************
133 
134  //**********************************************************************************************
137  //**********************************************************************************************
138 
139  //**********************************************************************************************
141  enum { evaluateRight = IsComputation<MT2>::value || RequiresEvaluation<MT2>::value };
142  //**********************************************************************************************
143 
144  //**********************************************************************************************
146 
151  template< typename T1, typename T2, typename T3 >
152  struct CanExploitSymmetry {
153  enum { value = ( IsSymmetric<T2>::value || IsSymmetric<T3>::value ) };
154  };
156  //**********************************************************************************************
157 
158  //**********************************************************************************************
160 
164  template< typename T1, typename T2, typename T3 >
165  struct IsEvaluationRequired {
166  enum { value = ( evaluateLeft || evaluateRight ) &&
167  !CanExploitSymmetry<T1,T2,T3>::value };
168  };
170  //**********************************************************************************************
171 
172  //**********************************************************************************************
174 
178  template< typename T1, typename T2, typename T3 >
179  struct UseOptimizedKernel {
180  enum { value = !IsDiagonal<T3>::value &&
181  !IsResizable<typename T1::ElementType>::value &&
182  !IsResizable<ET1>::value };
183  };
185  //**********************************************************************************************
186 
187  //**********************************************************************************************
189 
192  template< typename T1, typename T2, typename T3 >
193  struct UseDefaultKernel {
194  enum { value = !UseOptimizedKernel<T1,T2,T3>::value };
195  };
197  //**********************************************************************************************
198 
199  public:
200  //**Type definitions****************************************************************************
206  typedef const ElementType ReturnType;
207  typedef const ResultType CompositeType;
208 
210  typedef typename SelectType< IsExpression<MT1>::value, const MT1, const MT1& >::Type LeftOperand;
211 
213  typedef typename SelectType< IsExpression<MT2>::value, const MT2, const MT2& >::Type RightOperand;
214 
217 
220  //**********************************************************************************************
221 
222  //**Compilation flags***************************************************************************
224  enum { vectorizable = 0 };
225 
227  enum { smpAssignable = !evaluateLeft && MT1::smpAssignable &&
228  !evaluateRight && MT2::smpAssignable };
229  //**********************************************************************************************
230 
231  //**Constructor*********************************************************************************
237  explicit inline TSMatTDMatMultExpr( const MT1& lhs, const MT2& rhs )
238  : lhs_( lhs ) // Left-hand side sparse matrix of the multiplication expression
239  , rhs_( rhs ) // Right-hand side dense matrix of the multiplication expression
240  {
241  BLAZE_INTERNAL_ASSERT( lhs.columns() == rhs.rows(), "Invalid matrix sizes" );
242  }
243  //**********************************************************************************************
244 
245  //**Access operator*****************************************************************************
252  inline ReturnType operator()( size_t i, size_t j ) const {
253  BLAZE_INTERNAL_ASSERT( i < lhs_.rows() , "Invalid row access index" );
254  BLAZE_INTERNAL_ASSERT( j < rhs_.columns(), "Invalid column access index" );
255 
256  const size_t kbegin( ( IsUpper<MT1>::value )
257  ?( ( IsLower<MT2>::value )
258  ?( max( ( IsStrictlyUpper<MT1>::value ? i+1UL : i )
259  , ( IsStrictlyLower<MT2>::value ? j+1UL : j ) ) )
260  :( IsStrictlyUpper<MT1>::value ? i+1UL : i ) )
261  :( ( IsLower<MT2>::value )
262  ?( IsStrictlyLower<MT2>::value ? j+1UL : j )
263  :( 0UL ) ) );
264  const size_t kend( ( IsLower<MT1>::value )
265  ?( ( IsUpper<MT2>::value )
266  ?( min( ( IsStrictlyLower<MT1>::value ? i : i+1UL )
267  , ( IsStrictlyUpper<MT2>::value ? j : j+1UL ) ) )
268  :( IsStrictlyLower<MT1>::value ? i : i+1UL ) )
269  :( ( IsUpper<MT2>::value )
270  ?( IsStrictlyUpper<MT2>::value ? j : j+1UL )
271  :( lhs_.columns() ) ) );
272 
273  if( lhs_.columns() == 0UL ||
274  ( ( IsTriangular<MT1>::value || IsTriangular<MT2>::value ) && kbegin >= kend ) )
275  return ElementType();
276 
277  ElementType tmp( lhs_(i,kbegin) * rhs_(kbegin,j) );
278  for( size_t k=kbegin+1UL; k<kend; ++k ) {
279  tmp += lhs_(i,k) * rhs_(k,j);
280  }
281 
282  return tmp;
283  }
284  //**********************************************************************************************
285 
286  //**Rows function*******************************************************************************
291  inline size_t rows() const {
292  return lhs_.rows();
293  }
294  //**********************************************************************************************
295 
296  //**Columns function****************************************************************************
301  inline size_t columns() const {
302  return rhs_.columns();
303  }
304  //**********************************************************************************************
305 
306  //**Left operand access*************************************************************************
311  inline LeftOperand leftOperand() const {
312  return lhs_;
313  }
314  //**********************************************************************************************
315 
316  //**Right operand access************************************************************************
321  inline RightOperand rightOperand() const {
322  return rhs_;
323  }
324  //**********************************************************************************************
325 
326  //**********************************************************************************************
332  template< typename T >
333  inline bool canAlias( const T* alias ) const {
334  return ( lhs_.isAliased( alias ) || rhs_.isAliased( alias ) );
335  }
336  //**********************************************************************************************
337 
338  //**********************************************************************************************
344  template< typename T >
345  inline bool isAliased( const T* alias ) const {
346  return ( lhs_.isAliased( alias ) || rhs_.isAliased( alias ) );
347  }
348  //**********************************************************************************************
349 
350  //**********************************************************************************************
355  inline bool isAligned() const {
356  return rhs_.isAligned();
357  }
358  //**********************************************************************************************
359 
360  //**********************************************************************************************
365  inline bool canSMPAssign() const {
366  return ( columns() > SMP_TSMATTDMATMULT_THRESHOLD );
367  }
368  //**********************************************************************************************
369 
370  private:
371  //**Member variables****************************************************************************
372  LeftOperand lhs_;
373  RightOperand rhs_;
374  //**********************************************************************************************
375 
376  //**Assignment to dense matrices****************************************************************
389  template< typename MT // Type of the target dense matrix
390  , bool SO > // Storage order of the target dense matrix
391  friend inline typename DisableIf< CanExploitSymmetry<MT,MT1,MT2> >::Type
392  assign( DenseMatrix<MT,SO>& lhs, const TSMatTDMatMultExpr& rhs )
393  {
395 
396  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
397  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
398 
399  LT A( serial( rhs.lhs_ ) ); // Evaluation of the right-hand side sparse matrix operand
400  RT B( serial( rhs.rhs_ ) ); // Evaluation of the left-hand side dense matrix operand
401 
402  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
403  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
404  BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
405  BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
406  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
407  BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
408 
409  TSMatTDMatMultExpr::selectAssignKernel( ~lhs, A, B );
410  }
412  //**********************************************************************************************
413 
414  //**Default assignment to dense matrices********************************************************
429  template< typename MT3 // Type of the left-hand side target matrix
430  , typename MT4 // Type of the left-hand side matrix operand
431  , typename MT5 > // Type of the right-hand side matrix operand
432  static inline typename EnableIf< UseDefaultKernel<MT3,MT4,MT5> >::Type
433  selectAssignKernel( MT3& C, const MT4& A, const MT5& B )
434  {
435  typedef typename MT4::ConstIterator ConstIterator;
436 
437  reset( C );
438 
440  {
441  for( size_t i=0UL; i<A.columns(); ++i )
442  {
443  const ConstIterator end( A.end(i) );
444  ConstIterator element( A.begin(i) );
445 
446  for( ; element!=end; ++element ) {
447  C(element->index(),i) = element->value() * B(i,i);
448  }
449  }
450  }
451  else
452  {
453  const size_t block( 64UL );
454 
455  for( size_t jj=0UL; jj<B.columns(); jj+=block )
456  {
457  const size_t jpos( ( jj+block > B.columns() )?( B.columns() ):( jj+block ) );
458 
459  for( size_t i=0UL; i<A.columns(); ++i )
460  {
461  const ConstIterator end( A.end(i) );
462  ConstIterator element( A.begin(i) );
463 
464  const size_t jbegin( ( IsUpper<MT5>::value )
465  ?( max( IsStrictlyUpper<MT5>::value ? i+1UL : i, jj ) )
466  :( jj ) );
467  const size_t jend( ( IsLower<MT5>::value )
468  ?( min( IsStrictlyLower<MT5>::value ? i : i+1UL, jpos ) )
469  :( jpos ) );
470 
471  if( jbegin >= jend )
472  continue;
473 
474  for( ; element!=end; ++element ) {
475  for( size_t j=jbegin; j<jend; ++j ) {
476  if( isDefault( C(element->index(),j) ) )
477  C(element->index(),j) = element->value() * B(i,j);
478  else
479  C(element->index(),j) += element->value() * B(i,j);
480  }
481  }
482  }
483  }
484  }
485  }
487  //**********************************************************************************************
488 
489  //**Optimized assignment to dense matrices******************************************************
504  template< typename MT3 // Type of the left-hand side target matrix
505  , typename MT4 // Type of the left-hand side matrix operand
506  , typename MT5 > // Type of the right-hand side matrix operand
507  static inline typename EnableIf< UseOptimizedKernel<MT3,MT4,MT5> >::Type
508  selectAssignKernel( MT3& C, const MT4& A, const MT5& B )
509  {
510  typedef typename MT4::ConstIterator ConstIterator;
511 
512  const size_t block( IsRowMajorMatrix<MT3>::value ? 128UL : 64UL );
513 
514  for( size_t jj=0UL; jj<B.columns(); jj+=block )
515  {
516  const size_t jpos( ( jj+block > B.columns() )?( B.columns() ):( jj+block ) );
517 
518  for( size_t i=0UL; i<A.rows(); ++i ) {
519  for( size_t j=jj; j<jpos; ++j ) {
520  reset( C(i,j) );
521  }
522  }
523 
524  for( size_t i=0UL; i<A.columns(); ++i )
525  {
526  const size_t jbegin( ( IsUpper<MT5>::value )
527  ?( max( IsStrictlyUpper<MT5>::value ? i+1UL : i, jj ) )
528  :( jj ) );
529  const size_t jend( ( IsLower<MT5>::value )
530  ?( min( IsStrictlyLower<MT5>::value ? i : i+1UL, jpos ) )
531  :( jpos ) );
532 
533  if( jbegin >= jend )
534  continue;
535 
536  const ConstIterator end( A.end(i) );
537  ConstIterator element( A.begin(i) );
538 
539  const size_t nonzeros( A.nonZeros(i) );
540  const size_t kpos( nonzeros & size_t(-4) );
541  BLAZE_INTERNAL_ASSERT( ( nonzeros - ( nonzeros % 4UL ) ) == kpos, "Invalid end calculation" );
542 
543  for( size_t k=0UL; k<kpos; k+=4UL )
544  {
545  const size_t i1( element->index() );
546  const ET1 v1( element->value() );
547  ++element;
548  const size_t i2( element->index() );
549  const ET1 v2( element->value() );
550  ++element;
551  const size_t i3( element->index() );
552  const ET1 v3( element->value() );
553  ++element;
554  const size_t i4( element->index() );
555  const ET1 v4( element->value() );
556  ++element;
557 
558  BLAZE_INTERNAL_ASSERT( i1 < i2 && i2 < i3 && i3 < i4, "Invalid sparse matrix index detected" );
559 
560  for( size_t j=jbegin; j<jend; ++j ) {
561  C(i1,j) += v1 * B(i,j);
562  C(i2,j) += v2 * B(i,j);
563  C(i3,j) += v3 * B(i,j);
564  C(i4,j) += v4 * B(i,j);
565  }
566  }
567 
568  for( ; element!=end; ++element ) {
569  for( size_t j=jbegin; j<jend; ++j ) {
570  C(element->index(),j) += element->value() * B(i,j);
571  }
572  }
573  }
574  }
575  }
577  //**********************************************************************************************
578 
579  //**Assignment to sparse matrices***************************************************************
592  template< typename MT // Type of the target sparse matrix
593  , bool SO > // Storage order of the target sparse matrix
594  friend inline typename DisableIf< CanExploitSymmetry<MT,MT1,MT2> >::Type
595  assign( SparseMatrix<MT,SO>& lhs, const TSMatTDMatMultExpr& rhs )
596  {
598 
599  typedef typename SelectType< SO, ResultType, OppositeType >::Type TmpType;
600 
607 
608  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
609  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
610 
611  const TmpType tmp( serial( rhs ) );
612  assign( ~lhs, tmp );
613  }
615  //**********************************************************************************************
616 
617  //**Restructuring assignment to row-major matrices**********************************************
632  template< typename MT > // Type of the target matrix
633  friend inline typename EnableIf< CanExploitSymmetry<MT,MT1,MT2> >::Type
634  assign( Matrix<MT,false>& lhs, const TSMatTDMatMultExpr& rhs )
635  {
637 
639 
640  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
641  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
642 
643  if( IsSymmetric<MT1>::value && IsSymmetric<MT2>::value )
644  assign( ~lhs, trans( rhs.lhs_ ) * trans( rhs.rhs_ ) );
645  else if( IsSymmetric<MT1>::value )
646  assign( ~lhs, trans( rhs.lhs_ ) * rhs.rhs_ );
647  else
648  assign( ~lhs, rhs.lhs_ * trans( rhs.rhs_ ) );
649  }
651  //**********************************************************************************************
652 
653  //**Restructuring assignment to column-major matrices*******************************************
668  template< typename MT > // Type of the target matrix
669  friend inline typename EnableIf< CanExploitSymmetry<MT,MT1,MT2> >::Type
670  assign( Matrix<MT,true>& lhs, const TSMatTDMatMultExpr& rhs )
671  {
673 
674  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
675  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
676 
677  if( IsSymmetric<MT1>::value )
678  assign( ~lhs, trans( rhs.lhs_ ) * rhs.rhs_ );
679  else
680  assign( ~lhs, rhs.lhs_ * trans( rhs.rhs_ ) );
681  }
683  //**********************************************************************************************
684 
685  //**Addition assignment to dense matrices*******************************************************
698  template< typename MT // Type of the target dense matrix
699  , bool SO > // Storage order of the target dense matrix
700  friend inline typename DisableIf< CanExploitSymmetry<MT,MT1,MT2> >::Type
701  addAssign( DenseMatrix<MT,SO>& lhs, const TSMatTDMatMultExpr& rhs )
702  {
704 
705  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
706  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
707 
708  LT A( serial( rhs.lhs_ ) ); // Evaluation of the right-hand side sparse matrix operand
709  RT B( serial( rhs.rhs_ ) ); // Evaluation of the left-hand side dense matrix operand
710 
711  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
712  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
713  BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
714  BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
715  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
716  BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
717 
718  TSMatTDMatMultExpr::selectAddAssignKernel( ~lhs, A, B );
719  }
721  //**********************************************************************************************
722 
723  //**Default addition assignment to dense matrices***********************************************
737  template< typename MT3 // Type of the left-hand side target matrix
738  , typename MT4 // Type of the left-hand side matrix operand
739  , typename MT5 > // Type of the right-hand side matrix operand
740  static inline typename EnableIf< UseDefaultKernel<MT3,MT4,MT5> >::Type
741  selectAddAssignKernel( MT3& C, const MT4& A, const MT5& B )
742  {
743  typedef typename MT4::ConstIterator ConstIterator;
744 
745  if( IsDiagonal<MT5>::value )
746  {
747  for( size_t i=0UL; i<A.columns(); ++i )
748  {
749  const ConstIterator end( A.end(i) );
750  ConstIterator element( A.begin(i) );
751 
752  for( ; element!=end; ++element ) {
753  C(element->index(),i) += element->value() * B(i,i);
754  }
755  }
756  }
757  else
758  {
759  const size_t block( 64UL );
760 
761  for( size_t jj=0UL; jj<B.columns(); jj+=block )
762  {
763  const size_t jpos( ( jj+block > B.columns() )?( B.columns() ):( jj+block ) );
764 
765  for( size_t i=0UL; i<A.columns(); ++i )
766  {
767  const ConstIterator end( A.end(i) );
768  ConstIterator element( A.begin(i) );
769 
770  const size_t jbegin( ( IsUpper<MT5>::value )
771  ?( max( IsStrictlyUpper<MT5>::value ? i+1UL : i, jj ) )
772  :( jj ) );
773  const size_t jend( ( IsLower<MT5>::value )
774  ?( min( IsStrictlyLower<MT5>::value ? i : i+1UL, jpos ) )
775  :( jpos ) );
776 
777  if( jbegin >= jend )
778  continue;
779 
780  for( ; element!=end; ++element ) {
781  for( size_t j=jbegin; j<jend; ++j ) {
782  C(element->index(),j) += element->value() * B(i,j);
783  }
784  }
785  }
786  }
787  }
788  }
790  //**********************************************************************************************
791 
792  //**Optimized addition assignment to dense matrices*********************************************
806  template< typename MT3 // Type of the left-hand side target matrix
807  , typename MT4 // Type of the left-hand side matrix operand
808  , typename MT5 > // Type of the right-hand side matrix operand
809  static inline typename EnableIf< UseOptimizedKernel<MT3,MT4,MT5> >::Type
810  selectAddAssignKernel( MT3& C, const MT4& A, const MT5& B )
811  {
812  typedef typename MT4::ConstIterator ConstIterator;
813 
814  const size_t block( IsRowMajorMatrix<MT3>::value ? 128UL : 64UL );
815 
816  for( size_t jj=0UL; jj<B.columns(); jj+=block )
817  {
818  const size_t jpos( ( jj+block > B.columns() )?( B.columns() ):( jj+block ) );
819 
820  for( size_t i=0UL; i<A.columns(); ++i )
821  {
822  const size_t jbegin( ( IsUpper<MT5>::value )
823  ?( max( IsStrictlyUpper<MT5>::value ? i+1UL : i, jj ) )
824  :( jj ) );
825  const size_t jend( ( IsLower<MT5>::value )
826  ?( min( IsStrictlyLower<MT5>::value ? i : i+1UL, jpos ) )
827  :( jpos ) );
828 
829  if( jbegin >= jend )
830  continue;
831 
832  const ConstIterator end( A.end(i) );
833  ConstIterator element( A.begin(i) );
834 
835  const size_t nonzeros( A.nonZeros(i) );
836  const size_t kpos( nonzeros & size_t(-4) );
837  BLAZE_INTERNAL_ASSERT( ( nonzeros - ( nonzeros % 4UL ) ) == kpos, "Invalid end calculation" );
838 
839  for( size_t k=0UL; k<kpos; k+=4UL )
840  {
841  const size_t i1( element->index() );
842  const ET1 v1( element->value() );
843  ++element;
844  const size_t i2( element->index() );
845  const ET1 v2( element->value() );
846  ++element;
847  const size_t i3( element->index() );
848  const ET1 v3( element->value() );
849  ++element;
850  const size_t i4( element->index() );
851  const ET1 v4( element->value() );
852  ++element;
853 
854  BLAZE_INTERNAL_ASSERT( i1 < i2 && i2 < i3 && i3 < i4, "Invalid sparse matrix index detected" );
855 
856  for( size_t j=jbegin; j<jend; ++j ) {
857  C(i1,j) += v1 * B(i,j);
858  C(i2,j) += v2 * B(i,j);
859  C(i3,j) += v3 * B(i,j);
860  C(i4,j) += v4 * B(i,j);
861  }
862  }
863 
864  for( ; element!=end; ++element ) {
865  for( size_t j=jbegin; j<jend; ++j ) {
866  C(element->index(),j) += element->value() * B(i,j);
867  }
868  }
869  }
870  }
871  }
873  //**********************************************************************************************
874 
875  //**Restructuring addition assignment to row-major matrices*************************************
890  template< typename MT > // Type of the target matrix
891  friend inline typename EnableIf< CanExploitSymmetry<MT,MT1,MT2> >::Type
892  addAssign( Matrix<MT,false>& lhs, const TSMatTDMatMultExpr& rhs )
893  {
895 
897 
898  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
899  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
900 
901  if( IsSymmetric<MT1>::value && IsSymmetric<MT2>::value )
902  addAssign( ~lhs, trans( rhs.lhs_ ) * trans( rhs.rhs_ ) );
903  else if( IsSymmetric<MT1>::value )
904  addAssign( ~lhs, trans( rhs.lhs_ ) * rhs.rhs_ );
905  else
906  addAssign( ~lhs, rhs.lhs_ * trans( rhs.rhs_ ) );
907  }
909  //**********************************************************************************************
910 
911  //**Restructuring addition assignment to column-major matrices**********************************
926  template< typename MT > // Type of the target matrix
927  friend inline typename EnableIf< CanExploitSymmetry<MT,MT1,MT2> >::Type
928  addAssign( Matrix<MT,true>& lhs, const TSMatTDMatMultExpr& rhs )
929  {
931 
932  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
933  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
934 
935  if( IsSymmetric<MT1>::value )
936  addAssign( ~lhs, trans( rhs.lhs_ ) * rhs.rhs_ );
937  else
938  addAssign( ~lhs, rhs.lhs_ * trans( rhs.rhs_ ) );
939  }
941  //**********************************************************************************************
942 
943  //**Addition assignment to sparse matrices******************************************************
944  // No special implementation for the addition assignment to sparse matrices.
945  //**********************************************************************************************
946 
947  //**Subtraction assignment to dense matrices****************************************************
960  template< typename MT // Type of the target dense matrix
961  , bool SO > // Storage order of the target dense matrix
962  friend inline typename DisableIf< CanExploitSymmetry<MT,MT1,MT2> >::Type
963  subAssign( DenseMatrix<MT,SO>& lhs, const TSMatTDMatMultExpr& rhs )
964  {
966 
967  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
968  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
969 
970  LT A( serial( rhs.lhs_ ) ); // Evaluation of the right-hand side sparse matrix operand
971  RT B( serial( rhs.rhs_ ) ); // Evaluation of the left-hand side dense matrix operand
972 
973  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
974  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
975  BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
976  BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
977  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
978  BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
979 
980  TSMatTDMatMultExpr::selectSubAssignKernel( ~lhs, A, B );
981  }
983  //**********************************************************************************************
984 
985  //**Default subtraction assignment to dense matrices********************************************
999  template< typename MT3 // Type of the left-hand side target matrix
1000  , typename MT4 // Type of the left-hand side matrix operand
1001  , typename MT5 > // Type of the right-hand side matrix operand
1002  static inline typename EnableIf< UseDefaultKernel<MT3,MT4,MT5> >::Type
1003  selectSubAssignKernel( MT3& C, const MT4& A, const MT5& B )
1004  {
1005  typedef typename MT4::ConstIterator ConstIterator;
1006 
1007  if( IsDiagonal<MT5>::value )
1008  {
1009  for( size_t i=0UL; i<A.columns(); ++i )
1010  {
1011  const ConstIterator end( A.end(i) );
1012  ConstIterator element( A.begin(i) );
1013 
1014  for( ; element!=end; ++element ) {
1015  C(element->index(),i) -= element->value() * B(i,i);
1016  }
1017  }
1018  }
1019  else
1020  {
1021  const size_t block( 64UL );
1022 
1023  for( size_t jj=0UL; jj<B.columns(); jj+=block )
1024  {
1025  const size_t jpos( ( jj+block > B.columns() )?( B.columns() ):( jj+block ) );
1026 
1027  for( size_t i=0UL; i<A.columns(); ++i )
1028  {
1029  const ConstIterator end( A.end(i) );
1030  ConstIterator element( A.begin(i) );
1031 
1032  const size_t jbegin( ( IsUpper<MT5>::value )
1033  ?( max( IsStrictlyUpper<MT5>::value ? i+1UL : i, jj ) )
1034  :( jj ) );
1035  const size_t jend( ( IsLower<MT5>::value )
1036  ?( min( IsStrictlyLower<MT5>::value ? i : i+1UL, jpos ) )
1037  :( jpos ) );
1038 
1039  if( jbegin >= jend )
1040  continue;
1041 
1042  for( ; element!=end; ++element ) {
1043  for( size_t j=jbegin; j<jend; ++j ) {
1044  C(element->index(),j) -= element->value() * B(i,j);
1045  }
1046  }
1047  }
1048  }
1049  }
1050  }
1052  //**********************************************************************************************
1053 
1054  //**Optimized subtraction assignment to dense matrices******************************************
1068  template< typename MT3 // Type of the left-hand side target matrix
1069  , typename MT4 // Type of the left-hand side matrix operand
1070  , typename MT5 > // Type of the right-hand side matrix operand
1071  static inline typename EnableIf< UseOptimizedKernel<MT3,MT4,MT5> >::Type
1072  selectSubAssignKernel( MT3& C, const MT4& A, const MT5& B )
1073  {
1074  typedef typename MT4::ConstIterator ConstIterator;
1075 
1076  const size_t block( IsRowMajorMatrix<MT3>::value ? 128UL : 64UL );
1077 
1078  for( size_t jj=0UL; jj<B.columns(); jj+=block )
1079  {
1080  const size_t jpos( ( jj+block > B.columns() )?( B.columns() ):( jj+block ) );
1081 
1082  for( size_t i=0UL; i<A.columns(); ++i )
1083  {
1084  const size_t jbegin( ( IsUpper<MT5>::value )
1085  ?( max( IsStrictlyUpper<MT5>::value ? i+1UL : i, jj ) )
1086  :( jj ) );
1087  const size_t jend( ( IsLower<MT5>::value )
1088  ?( min( IsStrictlyLower<MT5>::value ? i : i+1UL, jpos ) )
1089  :( jpos ) );
1090 
1091  if( jbegin >= jend )
1092  continue;
1093 
1094  const ConstIterator end( A.end(i) );
1095  ConstIterator element( A.begin(i) );
1096 
1097  const size_t nonzeros( A.nonZeros(i) );
1098  const size_t kpos( nonzeros & size_t(-4) );
1099  BLAZE_INTERNAL_ASSERT( ( nonzeros - ( nonzeros % 4UL ) ) == kpos, "Invalid end calculation" );
1100 
1101  for( size_t k=0UL; k<kpos; k+=4UL )
1102  {
1103  const size_t i1( element->index() );
1104  const ET1 v1( element->value() );
1105  ++element;
1106  const size_t i2( element->index() );
1107  const ET1 v2( element->value() );
1108  ++element;
1109  const size_t i3( element->index() );
1110  const ET1 v3( element->value() );
1111  ++element;
1112  const size_t i4( element->index() );
1113  const ET1 v4( element->value() );
1114  ++element;
1115 
1116  BLAZE_INTERNAL_ASSERT( i1 < i2 && i2 < i3 && i3 < i4, "Invalid sparse matrix index detected" );
1117 
1118  for( size_t j=jbegin; j<jend; ++j ) {
1119  C(i1,j) -= v1 * B(i,j);
1120  C(i2,j) -= v2 * B(i,j);
1121  C(i3,j) -= v3 * B(i,j);
1122  C(i4,j) -= v4 * B(i,j);
1123  }
1124  }
1125 
1126  for( ; element!=end; ++element ) {
1127  for( size_t j=jbegin; j<jend; ++j ) {
1128  C(element->index(),j) -= element->value() * B(i,j);
1129  }
1130  }
1131  }
1132  }
1133  }
1135  //**********************************************************************************************
1136 
1137  //**Restructuring subtraction assignment to row-major matrices**********************************
1153  template< typename MT > // Type of the target matrix
1154  friend inline typename EnableIf< CanExploitSymmetry<MT,MT1,MT2> >::Type
1155  subAssign( Matrix<MT,false>& lhs, const TSMatTDMatMultExpr& rhs )
1156  {
1158 
1160 
1161  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
1162  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
1163 
1164  if( IsSymmetric<MT1>::value && IsSymmetric<MT2>::value )
1165  subAssign( ~lhs, trans( rhs.lhs_ ) * trans( rhs.rhs_ ) );
1166  else if( IsSymmetric<MT1>::value )
1167  subAssign( ~lhs, trans( rhs.lhs_ ) * rhs.rhs_ );
1168  else
1169  subAssign( ~lhs, rhs.lhs_ * trans( rhs.rhs_ ) );
1170  }
1172  //**********************************************************************************************
1173 
1174  //**Restructuring subtraction assignment to column-major matrices*******************************
1190  template< typename MT > // Type of the target matrix
1191  friend inline typename EnableIf< CanExploitSymmetry<MT,MT1,MT2> >::Type
1192  subAssign( Matrix<MT,true>& lhs, const TSMatTDMatMultExpr& rhs )
1193  {
1195 
1196  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
1197  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
1198 
1199  if( IsSymmetric<MT1>::value )
1200  subAssign( ~lhs, trans( rhs.lhs_ ) * rhs.rhs_ );
1201  else
1202  subAssign( ~lhs, rhs.lhs_ * trans( rhs.rhs_ ) );
1203  }
1205  //**********************************************************************************************
1206 
1207  //**Subtraction assignment to sparse matrices***************************************************
1208  // No special implementation for the subtraction assignment to sparse matrices.
1209  //**********************************************************************************************
1210 
1211  //**Multiplication assignment to dense matrices*************************************************
1212  // No special implementation for the multiplication assignment to dense matrices.
1213  //**********************************************************************************************
1214 
1215  //**Multiplication assignment to sparse matrices************************************************
1216  // No special implementation for the multiplication assignment to sparse matrices.
1217  //**********************************************************************************************
1218 
1219  //**SMP 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  smpAssign( DenseMatrix<MT,SO>& lhs, const TSMatTDMatMultExpr& 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  smpAssign( ~lhs, A * B );
1256  }
1258  //**********************************************************************************************
1259 
1260  //**SMP assignment to sparse matrices***********************************************************
1276  template< typename MT // Type of the target sparse matrix
1277  , bool SO > // Storage order of the target sparse matrix
1278  friend inline typename EnableIf< IsEvaluationRequired<MT,MT1,MT2> >::Type
1279  smpAssign( SparseMatrix<MT,SO>& lhs, const TSMatTDMatMultExpr& rhs )
1280  {
1282 
1283  typedef typename SelectType< SO, ResultType, OppositeType >::Type TmpType;
1284 
1291 
1292  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
1293  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
1294 
1295  const TmpType tmp( rhs );
1296  smpAssign( ~lhs, tmp );
1297  }
1299  //**********************************************************************************************
1300 
1301  //**Restructuring SMP assignment to row-major matrices******************************************
1316  template< typename MT > // Type of the target matrix
1317  friend inline typename EnableIf< CanExploitSymmetry<MT,MT1,MT2> >::Type
1318  smpAssign( Matrix<MT,false>& lhs, const TSMatTDMatMultExpr& rhs )
1319  {
1321 
1323 
1324  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
1325  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
1326 
1327  if( IsSymmetric<MT1>::value && IsSymmetric<MT2>::value )
1328  smpAssign( ~lhs, trans( rhs.lhs_ ) * trans( rhs.rhs_ ) );
1329  else if( IsSymmetric<MT1>::value )
1330  smpAssign( ~lhs, trans( rhs.lhs_ ) * rhs.rhs_ );
1331  else
1332  smpAssign( ~lhs, rhs.lhs_ * trans( rhs.rhs_ ) );
1333  }
1335  //**********************************************************************************************
1336 
1337  //**Restructuring SMP assignment to column-major matrices***************************************
1352  template< typename MT > // Type of the target matrix
1353  friend inline typename EnableIf< CanExploitSymmetry<MT,MT1,MT2> >::Type
1354  smpAssign( Matrix<MT,true>& lhs, const TSMatTDMatMultExpr& rhs )
1355  {
1357 
1359 
1360  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
1361  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
1362 
1363  if( IsSymmetric<MT1>::value )
1364  smpAssign( ~lhs, trans( rhs.lhs_ ) * rhs.rhs_ );
1365  else
1366  smpAssign( ~lhs, rhs.lhs_ * trans( rhs.rhs_ ) );
1367  }
1369  //**********************************************************************************************
1370 
1371  //**SMP addition assignment to dense matrices***************************************************
1387  template< typename MT // Type of the target dense matrix
1388  , bool SO > // Storage order of the target dense matrix
1389  friend inline typename EnableIf< IsEvaluationRequired<MT,MT1,MT2> >::Type
1390  smpAddAssign( DenseMatrix<MT,SO>& lhs, const TSMatTDMatMultExpr& rhs )
1391  {
1393 
1394  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
1395  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
1396 
1397  LT A( rhs.lhs_ ); // Evaluation of the right-hand side sparse matrix operand
1398  RT B( rhs.rhs_ ); // Evaluation of the left-hand side dense matrix operand
1399 
1400  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
1401  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
1402  BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
1403  BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
1404  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
1405  BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
1406 
1407  smpAddAssign( ~lhs, A * B );
1408  }
1410  //**********************************************************************************************
1411 
1412  //**Restructuring SMP addition assignment to row-major matrices*********************************
1428  template< typename MT > // Type of the target matrix
1429  friend inline typename EnableIf< CanExploitSymmetry<MT,MT1,MT2> >::Type
1430  smpAddAssign( Matrix<MT,false>& lhs, const TSMatTDMatMultExpr& rhs )
1431  {
1433 
1435 
1436  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
1437  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
1438 
1439  if( IsSymmetric<MT1>::value && IsSymmetric<MT2>::value )
1440  smpAddAssign( ~lhs, trans( rhs.lhs_ ) * trans( rhs.rhs_ ) );
1441  else if( IsSymmetric<MT1>::value )
1442  smpAddAssign( ~lhs, trans( rhs.lhs_ ) * rhs.rhs_ );
1443  else
1444  smpAddAssign( ~lhs, rhs.lhs_ * trans( rhs.rhs_ ) );
1445  }
1447  //**********************************************************************************************
1448 
1449  //**Restructuring SMP addition assignment to column-major matrices******************************
1465  template< typename MT > // Type of the target matrix
1466  friend inline typename EnableIf< CanExploitSymmetry<MT,MT1,MT2> >::Type
1467  smpAddAssign( Matrix<MT,true>& lhs, const TSMatTDMatMultExpr& rhs )
1468  {
1470 
1471  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
1472  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
1473 
1474  if( IsSymmetric<MT1>::value )
1475  smpAddAssign( ~lhs, trans( rhs.lhs_ ) * rhs.rhs_ );
1476  else
1477  smpAddAssign( ~lhs, rhs.lhs_ * trans( rhs.rhs_ ) );
1478  }
1480  //**********************************************************************************************
1481 
1482  //**SMP addition assignment to sparse matrices**************************************************
1483  // No special implementation for the SMP addition assignment to sparse matrices.
1484  //**********************************************************************************************
1485 
1486  //**SMP subtraction assignment to dense matrices************************************************
1502  template< typename MT // Type of the target dense matrix
1503  , bool SO > // Storage order of the target dense matrix
1504  friend inline typename EnableIf< IsEvaluationRequired<MT,MT1,MT2> >::Type
1505  smpSubAssign( DenseMatrix<MT,SO>& lhs, const TSMatTDMatMultExpr& rhs )
1506  {
1508 
1509  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
1510  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
1511 
1512  LT A( rhs.lhs_ ); // Evaluation of the right-hand side sparse matrix operand
1513  RT B( rhs.rhs_ ); // Evaluation of the left-hand side dense matrix operand
1514 
1515  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
1516  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
1517  BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
1518  BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
1519  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
1520  BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
1521 
1522  smpSubAssign( ~lhs, A * B );
1523  }
1525  //**********************************************************************************************
1526 
1527  //**Restructuring SMP subtraction assignment to row-major matrices******************************
1543  template< typename MT > // Type of the target matrix
1544  friend inline typename EnableIf< CanExploitSymmetry<MT,MT1,MT2> >::Type
1545  smpSubAssign( Matrix<MT,false>& lhs, const TSMatTDMatMultExpr& rhs )
1546  {
1548 
1550 
1551  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
1552  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
1553 
1554  if( IsSymmetric<MT1>::value && IsSymmetric<MT2>::value )
1555  smpSubAssign( ~lhs, trans( rhs.lhs_ ) * trans( rhs.rhs_ ) );
1556  else if( IsSymmetric<MT1>::value )
1557  smpSubAssign( ~lhs, trans( rhs.lhs_ ) * rhs.rhs_ );
1558  else
1559  smpSubAssign( ~lhs, rhs.lhs_ * trans( rhs.rhs_ ) );
1560  }
1562  //**********************************************************************************************
1563 
1564  //**Restructuring SMP subtraction assignment to column-major matrices***************************
1580  template< typename MT > // Type of the target matrix
1581  friend inline typename EnableIf< CanExploitSymmetry<MT,MT1,MT2> >::Type
1582  smpSubAssign( Matrix<MT,true>& lhs, const TSMatTDMatMultExpr& rhs )
1583  {
1585 
1586  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
1587  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
1588 
1589  if( IsSymmetric<MT1>::value )
1590  smpSubAssign( ~lhs, trans( rhs.lhs_ ) * rhs.rhs_ );
1591  else
1592  smpSubAssign( ~lhs, rhs.lhs_ * trans( rhs.rhs_ ) );
1593  }
1595  //**********************************************************************************************
1596 
1597  //**SMP subtraction assignment to sparse matrices***********************************************
1598  // No special implementation for the SMP subtraction assignment to sparse matrices.
1599  //**********************************************************************************************
1600 
1601  //**SMP multiplication assignment to dense matrices*********************************************
1602  // No special implementation for the SMP multiplication assignment to dense matrices.
1603  //**********************************************************************************************
1604 
1605  //**SMP multiplication assignment to sparse matrices********************************************
1606  // No special implementation for the SMP multiplication assignment to sparse matrices.
1607  //**********************************************************************************************
1608 
1609  //**Compile time checks*************************************************************************
1617  //**********************************************************************************************
1618 };
1619 //*************************************************************************************************
1620 
1621 
1622 
1623 
1624 //=================================================================================================
1625 //
1626 // GLOBAL BINARY ARITHMETIC OPERATORS
1627 //
1628 //=================================================================================================
1629 
1630 //*************************************************************************************************
1659 template< typename T1 // Type of the left-hand side sparse matrix
1660  , typename T2 > // Type of the right-hand side dense matrix
1661 inline const TSMatTDMatMultExpr<T1,T2>
1663 {
1665 
1666  if( (~lhs).columns() != (~rhs).rows() )
1667  throw std::invalid_argument( "Matrix sizes do not match" );
1668 
1669  return TSMatTDMatMultExpr<T1,T2>( ~lhs, ~rhs );
1670 }
1671 //*************************************************************************************************
1672 
1673 
1674 
1675 
1676 //=================================================================================================
1677 //
1678 // ROWS SPECIALIZATIONS
1679 //
1680 //=================================================================================================
1681 
1682 //*************************************************************************************************
1684 template< typename MT1, typename MT2 >
1685 struct Rows< TSMatTDMatMultExpr<MT1,MT2> >
1686  : public Rows<MT1>
1687 {};
1689 //*************************************************************************************************
1690 
1691 
1692 
1693 
1694 //=================================================================================================
1695 //
1696 // COLUMNS SPECIALIZATIONS
1697 //
1698 //=================================================================================================
1699 
1700 //*************************************************************************************************
1702 template< typename MT1, typename MT2 >
1703 struct Columns< TSMatTDMatMultExpr<MT1,MT2> >
1704  : public Columns<MT2>
1705 {};
1707 //*************************************************************************************************
1708 
1709 
1710 
1711 
1712 //=================================================================================================
1713 //
1714 // ISLOWER SPECIALIZATIONS
1715 //
1716 //=================================================================================================
1717 
1718 //*************************************************************************************************
1720 template< typename MT1, typename MT2 >
1721 struct IsLower< TSMatTDMatMultExpr<MT1,MT2> >
1722  : public IsTrue< And< IsLower<MT1>, IsLower<MT2> >::value >
1723 {};
1725 //*************************************************************************************************
1726 
1727 
1728 
1729 
1730 //=================================================================================================
1731 //
1732 // ISUNILOWER SPECIALIZATIONS
1733 //
1734 //=================================================================================================
1735 
1736 //*************************************************************************************************
1738 template< typename MT1, typename MT2 >
1739 struct IsUniLower< TSMatTDMatMultExpr<MT1,MT2> >
1740  : public IsTrue< And< IsUniLower<MT1>, IsUniLower<MT2> >::value >
1741 {};
1743 //*************************************************************************************************
1744 
1745 
1746 
1747 
1748 //=================================================================================================
1749 //
1750 // ISSTRICTLYLOWER SPECIALIZATIONS
1751 //
1752 //=================================================================================================
1753 
1754 //*************************************************************************************************
1756 template< typename MT1, typename MT2 >
1757 struct IsStrictlyLower< TSMatTDMatMultExpr<MT1,MT2> >
1758  : public IsTrue< Or< And< IsStrictlyLower<MT1>, IsLower<MT2> >
1759  , And< IsStrictlyLower<MT2>, IsLower<MT1> > >::value >
1760 {};
1762 //*************************************************************************************************
1763 
1764 
1765 
1766 
1767 //=================================================================================================
1768 //
1769 // ISUPPER SPECIALIZATIONS
1770 //
1771 //=================================================================================================
1772 
1773 //*************************************************************************************************
1775 template< typename MT1, typename MT2 >
1776 struct IsUpper< TSMatTDMatMultExpr<MT1,MT2> >
1777  : public IsTrue< And< IsUpper<MT1>, IsUpper<MT2> >::value >
1778 {};
1780 //*************************************************************************************************
1781 
1782 
1783 
1784 
1785 //=================================================================================================
1786 //
1787 // ISUNIUPPER SPECIALIZATIONS
1788 //
1789 //=================================================================================================
1790 
1791 //*************************************************************************************************
1793 template< typename MT1, typename MT2 >
1794 struct IsUniUpper< TSMatTDMatMultExpr<MT1,MT2> >
1795  : public IsTrue< And< IsUniUpper<MT1>, IsUniUpper<MT2> >::value >
1796 {};
1798 //*************************************************************************************************
1799 
1800 
1801 
1802 
1803 //=================================================================================================
1804 //
1805 // ISSTRICTLYUPPER SPECIALIZATIONS
1806 //
1807 //=================================================================================================
1808 
1809 //*************************************************************************************************
1811 template< typename MT1, typename MT2 >
1812 struct IsStrictlyUpper< TSMatTDMatMultExpr<MT1,MT2> >
1813  : public IsTrue< Or< And< IsStrictlyUpper<MT1>, IsUpper<MT2> >
1814  , And< IsStrictlyUpper<MT2>, IsUpper<MT1> > >::value >
1815 {};
1817 //*************************************************************************************************
1818 
1819 
1820 
1821 
1822 //=================================================================================================
1823 //
1824 // EXPRESSION TRAIT SPECIALIZATIONS
1825 //
1826 //=================================================================================================
1827 
1828 //*************************************************************************************************
1830 template< typename MT1, typename MT2, typename VT >
1831 struct TDMatDVecMultExprTrait< TSMatTDMatMultExpr<MT1,MT2>, VT >
1832 {
1833  public:
1834  //**********************************************************************************************
1835  typedef typename SelectType< IsSparseMatrix<MT1>::value && IsColumnMajorMatrix<MT1>::value &&
1836  IsDenseMatrix<MT2>::value && IsColumnMajorMatrix<MT2>::value &&
1837  IsDenseVector<VT>::value && IsColumnVector<VT>::value
1838  , typename TSMatDVecMultExprTrait< MT1, typename TDMatDVecMultExprTrait<MT2,VT>::Type >::Type
1839  , INVALID_TYPE >::Type Type;
1840  //**********************************************************************************************
1841 };
1843 //*************************************************************************************************
1844 
1845 
1846 //*************************************************************************************************
1848 template< typename MT1, typename MT2, typename VT >
1849 struct TDMatSVecMultExprTrait< TSMatTDMatMultExpr<MT1,MT2>, VT >
1850 {
1851  public:
1852  //**********************************************************************************************
1853  typedef typename SelectType< IsSparseMatrix<MT1>::value && IsColumnMajorMatrix<MT1>::value &&
1854  IsDenseMatrix<MT2>::value && IsColumnMajorMatrix<MT2>::value &&
1855  IsSparseVector<VT>::value && IsColumnVector<VT>::value
1856  , typename TSMatDVecMultExprTrait< MT1, typename TDMatSVecMultExprTrait<MT2,VT>::Type >::Type
1857  , INVALID_TYPE >::Type Type;
1858  //**********************************************************************************************
1859 };
1861 //*************************************************************************************************
1862 
1863 
1864 //*************************************************************************************************
1866 template< typename VT, typename MT1, typename MT2 >
1867 struct TDVecTDMatMultExprTrait< VT, TSMatTDMatMultExpr<MT1,MT2> >
1868 {
1869  public:
1870  //**********************************************************************************************
1871  typedef typename SelectType< IsDenseVector<VT>::value && IsRowVector<VT>::value &&
1872  IsSparseMatrix<MT1>::value && IsColumnMajorMatrix<MT1>::value &&
1873  IsDenseMatrix<MT2>::value && IsColumnMajorMatrix<MT2>::value
1874  , typename TDVecTDMatMultExprTrait< typename TDVecTSMatMultExprTrait<VT,MT1>::Type, MT2 >::Type
1875  , INVALID_TYPE >::Type Type;
1876  //**********************************************************************************************
1877 };
1879 //*************************************************************************************************
1880 
1881 
1882 //*************************************************************************************************
1884 template< typename VT, typename MT1, typename MT2 >
1885 struct TSVecTDMatMultExprTrait< VT, TSMatTDMatMultExpr<MT1,MT2> >
1886 {
1887  public:
1888  //**********************************************************************************************
1889  typedef typename SelectType< IsSparseVector<VT>::value && IsRowVector<VT>::value &&
1890  IsSparseMatrix<MT1>::value && IsColumnMajorMatrix<MT1>::value &&
1891  IsDenseMatrix<MT2>::value && IsColumnMajorMatrix<MT2>::value
1892  , typename TSVecTDMatMultExprTrait< typename TSVecTSMatMultExprTrait<VT,MT1>::Type, MT2 >::Type
1893  , INVALID_TYPE >::Type Type;
1894  //**********************************************************************************************
1895 };
1897 //*************************************************************************************************
1898 
1899 
1900 //*************************************************************************************************
1902 template< typename MT1, typename MT2, bool AF >
1903 struct SubmatrixExprTrait< TSMatTDMatMultExpr<MT1,MT2>, AF >
1904 {
1905  public:
1906  //**********************************************************************************************
1907  typedef typename MultExprTrait< typename SubmatrixExprTrait<const MT1,AF>::Type
1908  , typename SubmatrixExprTrait<const MT2,AF>::Type >::Type Type;
1909  //**********************************************************************************************
1910 };
1912 //*************************************************************************************************
1913 
1914 
1915 //*************************************************************************************************
1917 template< typename MT1, typename MT2 >
1918 struct RowExprTrait< TSMatTDMatMultExpr<MT1,MT2> >
1919 {
1920  public:
1921  //**********************************************************************************************
1922  typedef typename MultExprTrait< typename RowExprTrait<const MT1>::Type, MT2 >::Type Type;
1923  //**********************************************************************************************
1924 };
1926 //*************************************************************************************************
1927 
1928 
1929 //*************************************************************************************************
1931 template< typename MT1, typename MT2 >
1932 struct ColumnExprTrait< TSMatTDMatMultExpr<MT1,MT2> >
1933 {
1934  public:
1935  //**********************************************************************************************
1936  typedef typename MultExprTrait< MT1, typename ColumnExprTrait<const MT2>::Type >::Type Type;
1937  //**********************************************************************************************
1938 };
1940 //*************************************************************************************************
1941 
1942 } // namespace blaze
1943 
1944 #endif
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.
MT1::CompositeType CT1
Composite type of the left-hand side sparse matrix expression.
Definition: TSMatTDMatMultExpr.h:130
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
RT2::ElementType ET2
Element type of the right-hand side sparse matrix expression.
Definition: TSMatTDMatMultExpr.h:129
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.
Expression object for transpose sparse matrix-transpose dense matrix multiplications.The TSMatTDMatMultExpr class represents the compile time expression for multiplications between a column-major sparse matrix and a column-major dense matrix.
Definition: Forward.h:143
TSMatTDMatMultExpr(const MT1 &lhs, const MT2 &rhs)
Constructor for the TSMatTDMatMultExpr class.
Definition: TSMatTDMatMultExpr.h:237
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.
TSMatTDMatMultExpr< MT1, MT2 > This
Type of this TSMatTDMatMultExpr instance.
Definition: TSMatTDMatMultExpr.h:201
RT1::ElementType ET1
Element type of the left-hand side dense matrix expression.
Definition: TSMatTDMatMultExpr.h:128
bool canAlias(const T *alias) const
Returns whether the expression can alias with the given address alias.
Definition: TSMatTDMatMultExpr.h:333
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
Header file for the And class template.
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
SelectType< evaluateRight, const RT2, CT2 >::Type RT
Type for the assignment of the right-hand side dense matrix operand.
Definition: TSMatTDMatMultExpr.h:219
ResultType::OppositeType OppositeType
Result type with opposite storage order for expression template evaluations.
Definition: TSMatTDMatMultExpr.h:203
Header file for the IsUniLower type trait.
bool isAliased(const T *alias) const
Returns whether the expression is aliased with the given address alias.
Definition: TSMatTDMatMultExpr.h:345
MT2::ResultType RT2
Result type of the right-hand side dense matrix expression.
Definition: TSMatTDMatMultExpr.h:127
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 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.
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.
const size_t SMP_TSMATTDMATMULT_THRESHOLD
SMP column-major sparse matrix/column-major dense matrix multiplication threshold.This threshold specifies when a column-major sparse matrix/column-major dense matrix multiplication can be executed in parallel. In case the number of rows/columns of the target matrix is larger or equal to this threshold, the operation is executed in parallel. If the number of rows/columns is below this threshold the operation is executed single-threaded.
Definition: Thresholds.h:1087
Header file for the multiplication trait.
Header file for the IsStrictlyUpper type trait.
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: StorageOrder.h:161
Header file for the TSVecTDMatMultExprTrait class template.
const Element * ConstIterator
Iterator over constant elements.
Definition: CompressedMatrix.h:2511
Header file for the Or class template.
Header file for the TDMatSVecMultExprTrait class template.
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.
Header file for the IsLower type trait.
RightOperand rhs_
Right-hand side dense matrix of the multiplication expression.
Definition: TSMatTDMatMultExpr.h:373
Compile time check for diagonal matrices.This type trait tests whether or not the given template para...
Definition: IsDiagonal.h:92
size_t rows() const
Returns the current number of rows of the matrix.
Definition: TSMatTDMatMultExpr.h:291
#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
Header file for the IsTriangular type trait.
Constraints on the storage order of matrix types.
const ElementType ReturnType
Return type for expression template evaluations.
Definition: TSMatTDMatMultExpr.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
SelectType< IsExpression< MT1 >::value, const MT1, const MT1 & >::Type LeftOperand
Composite type of the left-hand side sparse matrix expression.
Definition: TSMatTDMatMultExpr.h:210
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.
SelectType< evaluateLeft, const RT1, CT1 >::Type LT
Type for the assignment of the left-hand side sparse matrix operand.
Definition: TSMatTDMatMultExpr.h:216
#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
LeftOperand lhs_
Left-hand side sparse matrix of the multiplication expression.
Definition: TSMatTDMatMultExpr.h:372
const ResultType CompositeType
Data type for composite expression templates.
Definition: TSMatTDMatMultExpr.h:207
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
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
Substitution Failure Is Not An Error (SFINAE) class.The EnableIf class template is an auxiliary tool ...
Definition: EnableIf.h:184
bool canSMPAssign() const
Returns whether the expression can be used in SMP assignments.
Definition: TSMatTDMatMultExpr.h:365
MT2::CompositeType CT2
Composite type of the right-hand side dense matrix expression.
Definition: TSMatTDMatMultExpr.h:131
Header file for the reset shim.
SelectType< IsExpression< MT2 >::value, const MT2, const MT2 & >::Type RightOperand
Composite type of the right-hand side dense matrix expression.
Definition: TSMatTDMatMultExpr.h:213
Header file for the isDefault shim.
MT1::ResultType RT1
Result type of the left-hand side sparse matrix expression.
Definition: TSMatTDMatMultExpr.h:126
ResultType::TransposeType TransposeType
Transpose type for expression template evaluations.
Definition: TSMatTDMatMultExpr.h:204
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
MultTrait< RT1, RT2 >::Type ResultType
Result type for expression template evaluations.
Definition: TSMatTDMatMultExpr.h:202
#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.
RightOperand rightOperand() const
Returns the right-hand side transpose dense matrix operand.
Definition: TSMatTDMatMultExpr.h:321
Compile time check for strictly lower triangular matrices.This type trait tests whether or not the gi...
Definition: IsStrictlyLower.h:86
LeftOperand leftOperand() const
Returns the left-hand side transpose sparse matrix operand.
Definition: TSMatTDMatMultExpr.h:311
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.
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
ReturnType operator()(size_t i, size_t j) const
2D-access to the matrix elements.
Definition: TSMatTDMatMultExpr.h:252
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
bool isAligned() const
Returns whether the operands of the expression are properly aligned in memory.
Definition: TSMatTDMatMultExpr.h:355
This ResultType
Result type for expression template evaluations.
Definition: CompressedMatrix.h:2502
Header file for the IsTrue value trait.
size_t columns() const
Returns the current number of columns of the matrix.
Definition: TSMatTDMatMultExpr.h:301
Header file for the IsUpper type trait.
Header file for the IsColumnVector type trait.
Constraint on the data type.
Header file for the IsResizable type trait.
ResultType::ElementType ElementType
Resulting element type.
Definition: TSMatTDMatMultExpr.h:205
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