DMatTSMatMultExpr.h
Go to the documentation of this file.
1 //=================================================================================================
33 //=================================================================================================
34 
35 #ifndef _BLAZE_MATH_EXPRESSIONS_DMATTSMATMULTEXPR_H_
36 #define _BLAZE_MATH_EXPRESSIONS_DMATTSMATMULTEXPR_H_
37 
38 
39 //*************************************************************************************************
40 // Includes
41 //*************************************************************************************************
42 
43 #include <blaze/math/Aliases.h>
52 #include <blaze/math/Exception.h>
64 #include <blaze/math/shims/Reset.h>
87 #include <blaze/util/Assert.h>
88 #include <blaze/util/DisableIf.h>
89 #include <blaze/util/EnableIf.h>
92 #include <blaze/util/InvalidType.h>
93 #include <blaze/util/mpl/And.h>
94 #include <blaze/util/mpl/Bool.h>
95 #include <blaze/util/mpl/If.h>
96 #include <blaze/util/mpl/Or.h>
97 #include <blaze/util/TrueType.h>
98 #include <blaze/util/Types.h>
101 
102 
103 namespace blaze {
104 
105 //=================================================================================================
106 //
107 // CLASS DMATTSMATMULTEXPR
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  , bool SF // Symmetry flag
121  , bool HF // Hermitian flag
122  , bool LF // Lower flag
123  , bool UF > // Upper flag
125  : public MatMatMultExpr< DenseMatrix< DMatTSMatMultExpr<MT1,MT2,SF,HF,LF,UF>, false > >
126  , private Computation
127 {
128  private:
129  //**Type definitions****************************************************************************
136  //**********************************************************************************************
137 
138  //**********************************************************************************************
140  enum : bool { evaluateLeft = IsComputation<MT1>::value || RequiresEvaluation<MT1>::value };
141  //**********************************************************************************************
142 
143  //**********************************************************************************************
145  enum : bool { evaluateRight = IsComputation<MT2>::value || RequiresEvaluation<MT2>::value };
146  //**********************************************************************************************
147 
148  //**********************************************************************************************
150  enum : bool {
151  SYM = ( SF && !( HF || LF || UF ) ),
152  HERM = ( HF && !( LF || UF ) ),
153  LOW = ( LF || ( ( SF || HF ) && UF ) ),
154  UPP = ( UF || ( ( SF || HF ) && LF ) )
155  };
156  //**********************************************************************************************
157 
158  //**********************************************************************************************
160 
165  template< typename T1, typename T2, typename T3 >
166  struct CanExploitSymmetry {
167  enum : bool { value = IsSymmetric<T2>::value };
168  };
170  //**********************************************************************************************
171 
172  //**********************************************************************************************
174 
178  template< typename T1, typename T2, typename T3 >
179  struct IsEvaluationRequired {
180  enum : bool { value = ( evaluateLeft || evaluateRight ) &&
181  !CanExploitSymmetry<T1,T2,T3>::value };
182  };
184  //**********************************************************************************************
185 
186  //**********************************************************************************************
188 
191  template< typename T1, typename T2, typename T3 >
192  struct UseOptimizedKernel {
193  enum : bool { value = useOptimizedKernels &&
195  !IsResizable< ElementType_<T1> >::value &&
197  };
199  //**********************************************************************************************
200 
201  //**********************************************************************************************
203 
206  using ForwardFunctor = IfTrue_< HERM
207  , DeclHerm
208  , IfTrue_< SYM
209  , DeclSym
210  , IfTrue_< LOW
211  , IfTrue_< UPP
212  , DeclDiag
213  , DeclLow >
214  , IfTrue_< UPP
215  , DeclUpp
216  , Noop > > > >;
218  //**********************************************************************************************
219 
220  public:
221  //**Type definitions****************************************************************************
224 
229  using ReturnType = const ElementType;
230  using CompositeType = const ResultType;
231 
233  using LeftOperand = If_< IsExpression<MT1>, const MT1, const MT1& >;
234 
236  using RightOperand = If_< IsExpression<MT2>, const MT2, const MT2& >;
237 
240 
243  //**********************************************************************************************
244 
245  //**Compilation flags***************************************************************************
247  enum : bool { simdEnabled = false };
248 
250  enum : bool { smpAssignable = !evaluateLeft && MT1::smpAssignable &&
251  !evaluateRight && MT2::smpAssignable };
252  //**********************************************************************************************
253 
254  //**Constructor*********************************************************************************
260  explicit inline DMatTSMatMultExpr( const MT1& lhs, const MT2& rhs ) noexcept
261  : lhs_( lhs ) // Left-hand side dense matrix of the multiplication expression
262  , rhs_( rhs ) // Right-hand side sparse matrix of the multiplication expression
263  {
264  BLAZE_INTERNAL_ASSERT( lhs.columns() == rhs.rows(), "Invalid matrix sizes" );
265  }
266  //**********************************************************************************************
267 
268  //**Access operator*****************************************************************************
275  inline ReturnType operator()( size_t i, size_t j ) const {
276  BLAZE_INTERNAL_ASSERT( i < lhs_.rows() , "Invalid row access index" );
277  BLAZE_INTERNAL_ASSERT( j < rhs_.columns(), "Invalid column access index" );
278 
279  if( IsDiagonal<MT1>::value ) {
280  return lhs_(i,i) * rhs_(i,j);
281  }
282  else if( IsDiagonal<MT2>::value ) {
283  return lhs_(i,j) * rhs_(j,j);
284  }
286  const size_t begin( ( IsUpper<MT1>::value )
287  ?( ( IsLower<MT2>::value )
288  ?( max( ( IsStrictlyUpper<MT1>::value ? i+1UL : i )
289  , ( IsStrictlyLower<MT2>::value ? j+1UL : j ) ) )
290  :( IsStrictlyUpper<MT1>::value ? i+1UL : i ) )
291  :( ( IsLower<MT2>::value )
292  ?( IsStrictlyLower<MT2>::value ? j+1UL : j )
293  :( 0UL ) ) );
294  const size_t end( ( IsLower<MT1>::value )
295  ?( ( IsUpper<MT2>::value )
296  ?( min( ( IsStrictlyLower<MT1>::value ? i : i+1UL )
297  , ( IsStrictlyUpper<MT2>::value ? j : j+1UL ) ) )
298  :( IsStrictlyLower<MT1>::value ? i : i+1UL ) )
299  :( ( IsUpper<MT2>::value )
300  ?( IsStrictlyUpper<MT2>::value ? j : j+1UL )
301  :( lhs_.columns() ) ) );
302 
303  if( begin >= end ) return ElementType();
304 
305  const size_t n( end - begin );
306 
307  return subvector( row( lhs_, i ), begin, n ) * subvector( column( rhs_, j ), begin, n );
308  }
309  else {
310  return row( lhs_, i ) * column( rhs_, j );
311  }
312  }
313  //**********************************************************************************************
314 
315  //**At function*********************************************************************************
323  inline ReturnType at( size_t i, size_t j ) const {
324  if( i >= lhs_.rows() ) {
325  BLAZE_THROW_OUT_OF_RANGE( "Invalid row access index" );
326  }
327  if( j >= rhs_.columns() ) {
328  BLAZE_THROW_OUT_OF_RANGE( "Invalid column access index" );
329  }
330  return (*this)(i,j);
331  }
332  //**********************************************************************************************
333 
334  //**Rows function*******************************************************************************
339  inline size_t rows() const noexcept {
340  return lhs_.rows();
341  }
342  //**********************************************************************************************
343 
344  //**Columns function****************************************************************************
349  inline size_t columns() const noexcept {
350  return rhs_.columns();
351  }
352  //**********************************************************************************************
353 
354  //**Left operand access*************************************************************************
359  inline LeftOperand leftOperand() const noexcept {
360  return lhs_;
361  }
362  //**********************************************************************************************
363 
364  //**Right operand access************************************************************************
369  inline RightOperand rightOperand() const noexcept {
370  return rhs_;
371  }
372  //**********************************************************************************************
373 
374  //**********************************************************************************************
380  template< typename T >
381  inline bool canAlias( const T* alias ) const noexcept {
382  return ( lhs_.isAliased( alias ) || rhs_.isAliased( alias ) );
383  }
384  //**********************************************************************************************
385 
386  //**********************************************************************************************
392  template< typename T >
393  inline bool isAliased( const T* alias ) const noexcept {
394  return ( lhs_.isAliased( alias ) || rhs_.isAliased( alias ) );
395  }
396  //**********************************************************************************************
397 
398  //**********************************************************************************************
403  inline bool isAligned() const noexcept {
404  return lhs_.isAligned();
405  }
406  //**********************************************************************************************
407 
408  //**********************************************************************************************
413  inline bool canSMPAssign() const noexcept {
414  return ( rows() * columns() >= SMP_DMATTSMATMULT_THRESHOLD ) && !IsDiagonal<MT1>::value;
415  }
416  //**********************************************************************************************
417 
418  private:
419  //**Member variables****************************************************************************
422  //**********************************************************************************************
423 
424  //**Assignment to dense matrices****************************************************************
437  template< typename MT // Type of the target dense matrix
438  , bool SO > // Storage order of the target dense matrix
440  assign( DenseMatrix<MT,SO>& lhs, const DMatTSMatMultExpr& rhs )
441  {
443 
444  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
445  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
446 
447  LT A( serial( rhs.lhs_ ) ); // Evaluation of the left-hand side dense matrix operand
448  RT B( serial( rhs.rhs_ ) ); // Evaluation of the right-hand side sparse matrix operand
449 
450  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
451  BLAZE_INTERNAL_ASSERT( A.columns() == B.rows() , "Invalid matrix sizes" );
452  BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns(), "Invalid number of columns" );
453 
454  DMatTSMatMultExpr::selectAssignKernel( ~lhs, A, B );
455  }
457  //**********************************************************************************************
458 
459  //**Default assignment to dense matrices********************************************************
473  template< typename MT3 // Type of the left-hand side target matrix
474  , typename MT4 // Type of the left-hand side matrix operand
475  , typename MT5 > // Type of the right-hand side matrix operand
477  selectAssignKernel( MT3& C, const MT4& A, const MT5& B )
478  {
480 
481  const size_t M( A.rows() );
482  const size_t N( B.columns() );
483 
484  BLAZE_INTERNAL_ASSERT( !( SYM || HERM || LOW || UPP ) || M == N, "Broken invariant detected" );
485 
486  if( LOW && UPP ) {
487  reset( C );
488  }
489 
490  {
491  size_t i( 0UL );
492 
493  for( ; (i+4UL) <= M; i+=4UL ) {
494  for( size_t j=( SYM || HERM || UPP ? i : 0UL ); j<( LOW ? i+4UL : N ); ++j )
495  {
497  ?( IsStrictlyUpper<MT4>::value ? B.upperBound(i,j) : B.lowerBound(i,j) )
498  :( B.begin(j) ) );
500  ?( IsStrictlyLower<MT4>::value ? B.lowerBound(i+4UL,j) : B.upperBound(i+4UL,j) )
501  :( B.end(j) ) );
502 
503  if( element == end ) {
504  reset( C(i ,j) );
505  reset( C(i+1UL,j) );
506  reset( C(i+2UL,j) );
507  reset( C(i+3UL,j) );
508  continue;
509  }
510 
511  C(i ,j) = A(i ,element->index()) * element->value();
512  C(i+1UL,j) = A(i+1UL,element->index()) * element->value();
513  C(i+2UL,j) = A(i+2UL,element->index()) * element->value();
514  C(i+3UL,j) = A(i+3UL,element->index()) * element->value();
515  ++element;
516  for( ; element!=end; ++element ) {
517  C(i ,j) += A(i ,element->index()) * element->value();
518  C(i+1UL,j) += A(i+1UL,element->index()) * element->value();
519  C(i+2UL,j) += A(i+2UL,element->index()) * element->value();
520  C(i+3UL,j) += A(i+3UL,element->index()) * element->value();
521  }
522  }
523  }
524 
525  for( ; (i+2UL) <= M; i+=2UL ) {
526  for( size_t j=( SYM || HERM || UPP ? i : 0UL ); j<( LOW ? i+2UL : N ); ++j )
527  {
529  ?( IsStrictlyUpper<MT4>::value ? B.upperBound(i,j) : B.lowerBound(i,j) )
530  :( B.begin(j) ) );
532  ?( IsStrictlyLower<MT4>::value ? B.lowerBound(i+2UL,j) : B.upperBound(i+2UL,j) )
533  :( B.end(j) ) );
534 
535  if( element == end ) {
536  reset( C(i ,j) );
537  reset( C(i+1UL,j) );
538  continue;
539  }
540 
541  C(i ,j) = A(i ,element->index()) * element->value();
542  C(i+1UL,j) = A(i+1UL,element->index()) * element->value();
543  ++element;
544  for( ; element!=end; ++element ) {
545  C(i ,j) += A(i ,element->index()) * element->value();
546  C(i+1UL,j) += A(i+1UL,element->index()) * element->value();
547  }
548  }
549  }
550 
551  for( ; i<M; ++i ) {
552  for( size_t j=( SYM || HERM || UPP ? i : 0UL ); j<( LOW ? i+1UL : N ); ++j )
553  {
555  ?( IsStrictlyUpper<MT4>::value ? B.upperBound(i,j) : B.lowerBound(i,j) )
556  :( B.begin(j) ) );
558  ?( IsStrictlyLower<MT4>::value ? B.lowerBound(i,j) : B.upperBound(i,j) )
559  :( B.end(j) ) );
560 
561  if( element == end ) {
562  reset( C(i,j) );
563  continue;
564  }
565 
566  C(i,j) = A(i,element->index()) * element->value();
567  ++element;
568  for( ; element!=end; ++element )
569  C(i,j) += A(i,element->index()) * element->value();
570  }
571  }
572  }
573 
574  if( SYM || HERM ) {
575  for( size_t i=1UL; i<M; ++i ) {
576  for( size_t j=0UL; j<i; ++j ) {
577  C(i,j) = HERM ? conj( C(j,i) ) : C(j,i);
578  }
579  }
580  }
581  else if( LOW && !UPP ) {
582  for( size_t j=1UL; j<N; ++j ) {
583  for( size_t i=0UL; i<j; ++i ) {
584  reset( C(i,j) );
585  }
586  }
587  }
588  else if( !LOW && UPP ) {
589  for( size_t i=1UL; i<M; ++i ) {
590  for( size_t j=0UL; j<i; ++j ) {
591  reset( C(i,j) );
592  }
593  }
594  }
595  }
597  //**********************************************************************************************
598 
599  //**Optimized assignment to dense matrices******************************************************
613  template< typename MT3 // Type of the left-hand side target matrix
614  , typename MT4 // Type of the left-hand side matrix operand
615  , typename MT5 > // Type of the right-hand side matrix operand
617  selectAssignKernel( MT3& C, const MT4& A, const MT5& B )
618  {
620 
621  const size_t M( A.rows() );
622  const size_t N( B.columns() );
623 
624  BLAZE_INTERNAL_ASSERT( !( SYM || HERM || LOW || UPP ) || M == N, "Broken invariant detected" );
625 
626  reset( C );
627 
628  {
629  size_t i( 0UL );
630 
631  for( ; (i+4UL) <= M; i+=4UL ) {
632  for( size_t j=( SYM || HERM || UPP ? i : 0UL ); j<( LOW ? i+4UL : N ); ++j )
633  {
635  ?( IsStrictlyUpper<MT4>::value ? B.upperBound(i,j) : B.lowerBound(i,j) )
636  :( B.begin(j) ) );
638  ?( IsStrictlyLower<MT4>::value ? B.lowerBound(i+4UL,j) : B.upperBound(i+4UL,j) )
639  :( B.end(j) ) );
640 
641  const size_t nonzeros( end - element );
642  const size_t kpos( nonzeros & size_t(-4) );
643  BLAZE_INTERNAL_ASSERT( ( nonzeros - ( nonzeros % 4UL ) ) == kpos, "Invalid end calculation" );
644 
645  for( size_t k=0UL; k<kpos; k+=4UL )
646  {
647  const size_t j1( element->index() );
648  const ET2 v1( element->value() );
649  ++element;
650  const size_t j2( element->index() );
651  const ET2 v2( element->value() );
652  ++element;
653  const size_t j3( element->index() );
654  const ET2 v3( element->value() );
655  ++element;
656  const size_t j4( element->index() );
657  const ET2 v4( element->value() );
658  ++element;
659 
660  BLAZE_INTERNAL_ASSERT( j1 < j2 && j2 < j3 && j3 < j4, "Invalid sparse matrix index detected" );
661 
662  C(i ,j) += A(i ,j1) * v1 + A(i ,j2) * v2 + A(i ,j3) * v3 + A(i ,j4) * v4;
663  C(i+1UL,j) += A(i+1UL,j1) * v1 + A(i+1UL,j2) * v2 + A(i+1UL,j3) * v3 + A(i+1UL,j4) * v4;
664  C(i+2UL,j) += A(i+2UL,j1) * v1 + A(i+2UL,j2) * v2 + A(i+2UL,j3) * v3 + A(i+2UL,j4) * v4;
665  C(i+3UL,j) += A(i+3UL,j1) * v1 + A(i+3UL,j2) * v2 + A(i+3UL,j3) * v3 + A(i+3UL,j4) * v4;
666  }
667 
668  for( ; element!=end; ++element )
669  {
670  const size_t j1( element->index() );
671  const ET2 v1( element->value() );
672 
673  C(i ,j) += A(i ,j1) * v1;
674  C(i+1UL,j) += A(i+1UL,j1) * v1;
675  C(i+2UL,j) += A(i+2UL,j1) * v1;
676  C(i+3UL,j) += A(i+3UL,j1) * v1;
677  }
678  }
679  }
680 
681  for( ; (i+2UL) <= M; i+=2UL ) {
682  for( size_t j=( SYM || HERM || UPP ? i : 0UL ); j<( LOW ? i+2UL : N ); ++j )
683  {
685  ?( IsStrictlyUpper<MT4>::value ? B.upperBound(i,j) : B.lowerBound(i,j) )
686  :( B.begin(j) ) );
688  ?( IsStrictlyLower<MT4>::value ? B.lowerBound(i+2UL,j) : B.upperBound(i+2UL,j) )
689  :( B.end(j) ) );
690 
691  const size_t nonzeros( end - element );
692  const size_t kpos( nonzeros & size_t(-4) );
693  BLAZE_INTERNAL_ASSERT( ( nonzeros - ( nonzeros % 4UL ) ) == kpos, "Invalid end calculation" );
694 
695  for( size_t k=0UL; k<kpos; k+=4UL )
696  {
697  const size_t j1( element->index() );
698  const ET2 v1( element->value() );
699  ++element;
700  const size_t j2( element->index() );
701  const ET2 v2( element->value() );
702  ++element;
703  const size_t j3( element->index() );
704  const ET2 v3( element->value() );
705  ++element;
706  const size_t j4( element->index() );
707  const ET2 v4( element->value() );
708  ++element;
709 
710  BLAZE_INTERNAL_ASSERT( j1 < j2 && j2 < j3 && j3 < j4, "Invalid sparse matrix index detected" );
711 
712  C(i ,j) += A(i ,j1) * v1 + A(i ,j2) * v2 + A(i ,j3) * v3 + A(i ,j4) * v4;
713  C(i+1UL,j) += A(i+1UL,j1) * v1 + A(i+1UL,j2) * v2 + A(i+1UL,j3) * v3 + A(i+1UL,j4) * v4;
714  }
715 
716  for( ; element!=end; ++element )
717  {
718  const size_t j1( element->index() );
719  const ET2 v1( element->value() );
720 
721  C(i ,j) += A(i ,j1) * v1;
722  C(i+1UL,j) += A(i+1UL,j1) * v1;
723  }
724  }
725  }
726 
727  for( ; i<M; ++i ) {
728  for( size_t j=( SYM || HERM || UPP ? i : 0UL ); j<( LOW ? i+1UL : N ); ++j )
729  {
731  ?( IsStrictlyUpper<MT4>::value ? B.upperBound(i,j) : B.lowerBound(i,j) )
732  :( B.begin(j) ) );
734  ?( IsStrictlyLower<MT4>::value ? B.lowerBound(i,j) : B.upperBound(i,j) )
735  :( B.end(j) ) );
736 
737  const size_t nonzeros( end - element );
738  const size_t kpos( nonzeros & size_t(-4) );
739  BLAZE_INTERNAL_ASSERT( ( nonzeros - ( nonzeros % 4UL ) ) == kpos, "Invalid end calculation" );
740 
741  for( size_t k=0UL; k<kpos; k+=4UL )
742  {
743  const size_t j1( element->index() );
744  const ET2 v1( element->value() );
745  ++element;
746  const size_t j2( element->index() );
747  const ET2 v2( element->value() );
748  ++element;
749  const size_t j3( element->index() );
750  const ET2 v3( element->value() );
751  ++element;
752  const size_t j4( element->index() );
753  const ET2 v4( element->value() );
754  ++element;
755 
756  BLAZE_INTERNAL_ASSERT( j1 < j2 && j2 < j3 && j3 < j4, "Invalid sparse matrix index detected" );
757 
758  C(i,j) += A(i,j1) * v1 + A(i,j2) * v2 + A(i,j3) * v3 + A(i,j4) * v4;
759  }
760 
761  for( ; element!=end; ++element )
762  {
763  const size_t j1( element->index() );
764  const ET2 v1( element->value() );
765 
766  C(i,j) += A(i,j1) * v1;
767  }
768  }
769  }
770  }
771 
772  if( SYM || HERM ) {
773  for( size_t i=1UL; i<M; ++i ) {
774  for( size_t j=0UL; j<i; ++j ) {
775  C(i,j) = HERM ? conj( C(j,i) ) : C(j,i);
776  }
777  }
778  }
779  }
781  //**********************************************************************************************
782 
783  //**Assignment to sparse matrices***************************************************************
796  template< typename MT // Type of the target sparse matrix
797  , bool SO > // Storage order of the target sparse matrix
799  assign( SparseMatrix<MT,SO>& lhs, const DMatTSMatMultExpr& rhs )
800  {
802 
804 
811 
812  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
813  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
814 
815  const ForwardFunctor fwd;
816 
817  const TmpType tmp( serial( rhs ) );
818  assign( ~lhs, fwd( tmp ) );
819  }
821  //**********************************************************************************************
822 
823  //**Restructuring assignment********************************************************************
838  template< typename MT // Type of the target matrix
839  , bool SO > // Storage order of the target matrix
841  assign( Matrix<MT,SO>& lhs, const DMatTSMatMultExpr& rhs )
842  {
844 
845  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
846  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
847 
848  const ForwardFunctor fwd;
849 
850  assign( ~lhs, fwd( trans( rhs.lhs_ ) * rhs.rhs_ ) );
851  }
853  //**********************************************************************************************
854 
855  //**Addition assignment to dense matrices*******************************************************
868  template< typename MT // Type of the target dense matrix
869  , bool SO > // Storage order of the target dense matrix
871  addAssign( DenseMatrix<MT,SO>& lhs, const DMatTSMatMultExpr& rhs )
872  {
874 
875  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
876  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
877 
878  LT A( serial( rhs.lhs_ ) ); // Evaluation of the left-hand side dense matrix operand
879  RT B( serial( rhs.rhs_ ) ); // Evaluation of the right-hand side sparse matrix operand
880 
881  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
882  BLAZE_INTERNAL_ASSERT( A.columns() == B.rows() , "Invalid matrix sizes" );
883  BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns(), "Invalid number of columns" );
884 
885  DMatTSMatMultExpr::selectAddAssignKernel( ~lhs, A, B );
886  }
888  //**********************************************************************************************
889 
890  //**Default addition assignment to dense matrices***********************************************
904  template< typename MT3 // Type of the left-hand side target matrix
905  , typename MT4 // Type of the left-hand side matrix operand
906  , typename MT5 > // Type of the right-hand side matrix operand
908  selectAddAssignKernel( MT3& C, const MT4& A, const MT5& B )
909  {
911 
912  const size_t M( A.rows() );
913  const size_t N( B.columns() );
914 
915  BLAZE_INTERNAL_ASSERT( !( LOW || UPP ) || M == N, "Broken invariant detected" );
916 
917  {
918  size_t i( 0UL );
919 
920  for( ; (i+4UL) <= M; i+=4UL ) {
921  for( size_t j=( UPP ? i : 0UL ); j<( LOW ? i+4UL : N ); ++j )
922  {
924  ?( IsStrictlyUpper<MT4>::value ? B.upperBound(i,j) : B.lowerBound(i,j) )
925  :( B.begin(j) ) );
927  ?( IsStrictlyLower<MT4>::value ? B.lowerBound(i+4UL,j) : B.upperBound(i+4UL,j) )
928  :( B.end(j) ) );
929 
930  for( ; element!=end; ++element ) {
931  C(i ,j) += A(i ,element->index()) * element->value();
932  C(i+1UL,j) += A(i+1UL,element->index()) * element->value();
933  C(i+2UL,j) += A(i+2UL,element->index()) * element->value();
934  C(i+3UL,j) += A(i+3UL,element->index()) * element->value();
935  }
936  }
937  }
938 
939  for( ; (i+2UL) <= M; i+=2UL ) {
940  for( size_t j=( UPP ? i : 0UL ); j<( LOW ? i+2UL : N ); ++j )
941  {
943  ?( IsStrictlyUpper<MT4>::value ? B.upperBound(i,j) : B.lowerBound(i,j) )
944  :( B.begin(j) ) );
946  ?( IsStrictlyLower<MT4>::value ? B.lowerBound(i+2UL,j) : B.upperBound(i+2UL,j) )
947  :( B.end(j) ) );
948 
949  for( ; element!=end; ++element ) {
950  C(i ,j) += A(i ,element->index()) * element->value();
951  C(i+1UL,j) += A(i+1UL,element->index()) * element->value();
952  }
953  }
954  }
955 
956  for( ; i<M; ++i ) {
957  for( size_t j=( UPP ? i : 0UL ); j<( LOW ? i+1UL : N ); ++j )
958  {
960  ?( IsStrictlyUpper<MT4>::value ? B.upperBound(i,j) : B.lowerBound(i,j) )
961  :( B.begin(j) ) );
963  ?( IsStrictlyLower<MT4>::value ? B.lowerBound(i,j) : B.upperBound(i,j) )
964  :( B.end(j) ) );
965 
966  for( ; element!=end; ++element )
967  C(i,j) += A(i,element->index()) * element->value();
968  }
969  }
970  }
971  }
973  //**********************************************************************************************
974 
975  //**Optimized addition assignment to dense matrices*********************************************
989  template< typename MT3 // Type of the left-hand side target matrix
990  , typename MT4 // Type of the left-hand side matrix operand
991  , typename MT5 > // Type of the right-hand side matrix operand
993  selectAddAssignKernel( MT3& C, const MT4& A, const MT5& B )
994  {
996 
997  const size_t M( A.rows() );
998  const size_t N( B.columns() );
999 
1000  BLAZE_INTERNAL_ASSERT( !( LOW || UPP ) || M == N, "Broken invariant detected" );
1001 
1002  {
1003  size_t i( 0UL );
1004 
1005  for( ; (i+4UL) <= M; i+=4UL ) {
1006  for( size_t j=( UPP ? i : 0UL ); j<( LOW ? i+4UL : N ); ++j )
1007  {
1008  ConstIterator element( ( IsUpper<MT4>::value )
1009  ?( IsStrictlyUpper<MT4>::value ? B.upperBound(i,j) : B.lowerBound(i,j) )
1010  :( B.begin(j) ) );
1012  ?( IsStrictlyLower<MT4>::value ? B.lowerBound(i+4UL,j) : B.upperBound(i+4UL,j) )
1013  :( B.end(j) ) );
1014 
1015  const size_t nonzeros( end - element );
1016  const size_t kpos( nonzeros & size_t(-4) );
1017  BLAZE_INTERNAL_ASSERT( ( nonzeros - ( nonzeros % 4UL ) ) == kpos, "Invalid end calculation" );
1018 
1019  for( size_t k=0UL; k<kpos; k+=4UL )
1020  {
1021  const size_t j1( element->index() );
1022  const ET2 v1( element->value() );
1023  ++element;
1024  const size_t j2( element->index() );
1025  const ET2 v2( element->value() );
1026  ++element;
1027  const size_t j3( element->index() );
1028  const ET2 v3( element->value() );
1029  ++element;
1030  const size_t j4( element->index() );
1031  const ET2 v4( element->value() );
1032  ++element;
1033 
1034  BLAZE_INTERNAL_ASSERT( j1 < j2 && j2 < j3 && j3 < j4, "Invalid sparse matrix index detected" );
1035 
1036  C(i ,j) += A(i ,j1) * v1 + A(i ,j2) * v2 + A(i ,j3) * v3 + A(i ,j4) * v4;
1037  C(i+1UL,j) += A(i+1UL,j1) * v1 + A(i+1UL,j2) * v2 + A(i+1UL,j3) * v3 + A(i+1UL,j4) * v4;
1038  C(i+2UL,j) += A(i+2UL,j1) * v1 + A(i+2UL,j2) * v2 + A(i+2UL,j3) * v3 + A(i+2UL,j4) * v4;
1039  C(i+3UL,j) += A(i+3UL,j1) * v1 + A(i+3UL,j2) * v2 + A(i+3UL,j3) * v3 + A(i+3UL,j4) * v4;
1040  }
1041 
1042  for( ; element!=end; ++element )
1043  {
1044  const size_t j1( element->index() );
1045  const ET2 v1( element->value() );
1046 
1047  C(i ,j) += A(i ,j1) * v1;
1048  C(i+1UL,j) += A(i+1UL,j1) * v1;
1049  C(i+2UL,j) += A(i+2UL,j1) * v1;
1050  C(i+3UL,j) += A(i+3UL,j1) * v1;
1051  }
1052  }
1053  }
1054 
1055  for( ; (i+2UL) <= M; i+=2UL ) {
1056  for( size_t j=( UPP ? i : 0UL ); j<( LOW ? i+2UL : N ); ++j )
1057  {
1058  ConstIterator element( ( IsUpper<MT4>::value )
1059  ?( IsStrictlyUpper<MT4>::value ? B.upperBound(i,j) : B.lowerBound(i,j) )
1060  :( B.begin(j) ) );
1062  ?( IsStrictlyLower<MT4>::value ? B.lowerBound(i+2UL,j) : B.upperBound(i+2UL,j) )
1063  :( B.end(j) ) );
1064 
1065  const size_t nonzeros( end - element );
1066  const size_t kpos( nonzeros & size_t(-4) );
1067  BLAZE_INTERNAL_ASSERT( ( nonzeros - ( nonzeros % 4UL ) ) == kpos, "Invalid end calculation" );
1068 
1069  for( size_t k=0UL; k<kpos; k+=4UL )
1070  {
1071  const size_t j1( element->index() );
1072  const ET2 v1( element->value() );
1073  ++element;
1074  const size_t j2( element->index() );
1075  const ET2 v2( element->value() );
1076  ++element;
1077  const size_t j3( element->index() );
1078  const ET2 v3( element->value() );
1079  ++element;
1080  const size_t j4( element->index() );
1081  const ET2 v4( element->value() );
1082  ++element;
1083 
1084  BLAZE_INTERNAL_ASSERT( j1 < j2 && j2 < j3 && j3 < j4, "Invalid sparse matrix index detected" );
1085 
1086  C(i ,j) += A(i ,j1) * v1 + A(i ,j2) * v2 + A(i ,j3) * v3 + A(i ,j4) * v4;
1087  C(i+1UL,j) += A(i+1UL,j1) * v1 + A(i+1UL,j2) * v2 + A(i+1UL,j3) * v3 + A(i+1UL,j4) * v4;
1088  }
1089 
1090  for( ; element!=end; ++element )
1091  {
1092  const size_t j1( element->index() );
1093  const ET2 v1( element->value() );
1094 
1095  C(i ,j) += A(i ,j1) * v1;
1096  C(i+1UL,j) += A(i+1UL,j1) * v1;
1097  }
1098  }
1099  }
1100 
1101  for( ; i<M; ++i ) {
1102  for( size_t j=( UPP ? i : 0UL ); j<( LOW ? i+1UL : N ); ++j )
1103  {
1104  ConstIterator element( ( IsUpper<MT4>::value )
1105  ?( IsStrictlyUpper<MT4>::value ? B.upperBound(i,j) : B.lowerBound(i,j) )
1106  :( B.begin(j) ) );
1108  ?( IsStrictlyLower<MT4>::value ? B.lowerBound(i,j) : B.upperBound(i,j) )
1109  :( B.end(j) ) );
1110 
1111  const size_t nonzeros( end - element );
1112  const size_t kpos( nonzeros & size_t(-4) );
1113  BLAZE_INTERNAL_ASSERT( ( nonzeros - ( nonzeros % 4UL ) ) == kpos, "Invalid end calculation" );
1114 
1115  for( size_t k=0UL; k<kpos; k+=4UL )
1116  {
1117  const size_t j1( element->index() );
1118  const ET2 v1( element->value() );
1119  ++element;
1120  const size_t j2( element->index() );
1121  const ET2 v2( element->value() );
1122  ++element;
1123  const size_t j3( element->index() );
1124  const ET2 v3( element->value() );
1125  ++element;
1126  const size_t j4( element->index() );
1127  const ET2 v4( element->value() );
1128  ++element;
1129 
1130  BLAZE_INTERNAL_ASSERT( j1 < j2 && j2 < j3 && j3 < j4, "Invalid sparse matrix index detected" );
1131 
1132  C(i,j) += A(i,j1) * v1 + A(i,j2) * v2 + A(i,j3) * v3 + A(i,j4) * v4;
1133  }
1134 
1135  for( ; element!=end; ++element )
1136  {
1137  const size_t j1( element->index() );
1138  const ET2 v1( element->value() );
1139 
1140  C(i,j) += A(i,j1) * v1;
1141  }
1142  }
1143  }
1144  }
1145  }
1147  //**********************************************************************************************
1148 
1149  //**Restructuring addition assignment***********************************************************
1164  template< typename MT // Type of the target matrix
1165  , bool SO > // Storage order of the target matrix
1167  addAssign( Matrix<MT,SO>& lhs, const DMatTSMatMultExpr& rhs )
1168  {
1170 
1172 
1173  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
1174  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
1175 
1176  const ForwardFunctor fwd;
1177 
1178  addAssign( ~lhs, fwd( trans( rhs.lhs_ ) * rhs.rhs_ ) );
1179  }
1181  //**********************************************************************************************
1182 
1183  //**Addition assignment to sparse matrices******************************************************
1184  // No special implementation for the addition assignment to sparse matrices.
1185  //**********************************************************************************************
1186 
1187  //**Subtraction assignment to dense matrices****************************************************
1200  template< typename MT // Type of the target dense matrix
1201  , bool SO > // Storage order of the target dense matrix
1203  subAssign( DenseMatrix<MT,SO>& lhs, const DMatTSMatMultExpr& rhs )
1204  {
1206 
1207  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
1208  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
1209 
1210  LT A( serial( rhs.lhs_ ) ); // Evaluation of the left-hand side dense matrix operand
1211  RT B( serial( rhs.rhs_ ) ); // Evaluation of the right-hand side sparse matrix operand
1212 
1213  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
1214  BLAZE_INTERNAL_ASSERT( A.columns() == B.rows() , "Invalid matrix sizes" );
1215  BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns(), "Invalid number of columns" );
1216 
1217  DMatTSMatMultExpr::selectSubAssignKernel( ~lhs, A, B );
1218  }
1220  //**********************************************************************************************
1221 
1222  //**Default subtraction assignment to dense matrices********************************************
1236  template< typename MT3 // Type of the left-hand side target matrix
1237  , typename MT4 // Type of the left-hand side matrix operand
1238  , typename MT5 > // Type of the right-hand side matrix operand
1240  selectSubAssignKernel( MT3& C, const MT4& A, const MT5& B )
1241  {
1243 
1244  const size_t M( A.rows() );
1245  const size_t N( B.columns() );
1246 
1247  BLAZE_INTERNAL_ASSERT( !( LOW || UPP ) || M == N, "Broken invariant detected" );
1248 
1249  {
1250  size_t i( 0UL );
1251 
1252  for( ; (i+4UL) <= M; i+=4UL ) {
1253  for( size_t j=( UPP ? i : 0UL ); j<( LOW ? i+4UL : N ); ++j )
1254  {
1255  ConstIterator element( ( IsUpper<MT4>::value )
1256  ?( IsStrictlyUpper<MT4>::value ? B.upperBound(i,j) : B.lowerBound(i,j) )
1257  :( B.begin(j) ) );
1259  ?( IsStrictlyLower<MT4>::value ? B.lowerBound(i+4UL,j) : B.upperBound(i+4UL,j) )
1260  :( B.end(j) ) );
1261 
1262  for( ; element!=end; ++element ) {
1263  C(i ,j) -= A(i ,element->index()) * element->value();
1264  C(i+1UL,j) -= A(i+1UL,element->index()) * element->value();
1265  C(i+2UL,j) -= A(i+2UL,element->index()) * element->value();
1266  C(i+3UL,j) -= A(i+3UL,element->index()) * element->value();
1267  }
1268  }
1269  }
1270 
1271  for( ; (i+2UL) <= M; i+=2UL ) {
1272  for( size_t j=( UPP ? i : 0UL ); j<( LOW ? i+2UL : N ); ++j )
1273  {
1274  ConstIterator element( ( IsUpper<MT4>::value )
1275  ?( IsStrictlyUpper<MT4>::value ? B.upperBound(i,j) : B.lowerBound(i,j) )
1276  :( B.begin(j) ) );
1278  ?( IsStrictlyLower<MT4>::value ? B.lowerBound(i+2UL,j) : B.upperBound(i+2UL,j) )
1279  :( B.end(j) ) );
1280 
1281  for( ; element!=end; ++element ) {
1282  C(i ,j) -= A(i ,element->index()) * element->value();
1283  C(i+1UL,j) -= A(i+1UL,element->index()) * element->value();
1284  }
1285  }
1286  }
1287 
1288  for( ; i<M; ++i ) {
1289  for( size_t j=( UPP ? i : 0UL ); j<( LOW ? i+1UL : N ); ++j )
1290  {
1291  ConstIterator element( ( IsUpper<MT4>::value )
1292  ?( IsStrictlyUpper<MT4>::value ? B.upperBound(i,j) : B.lowerBound(i,j) )
1293  :( B.begin(j) ) );
1295  ?( IsStrictlyLower<MT4>::value ? B.lowerBound(i,j) : B.upperBound(i,j) )
1296  :( B.end(j) ) );
1297 
1298  for( ; element!=end; ++element )
1299  C(i,j) -= A(i,element->index()) * element->value();
1300  }
1301  }
1302  }
1303  }
1305  //**********************************************************************************************
1306 
1307  //**Optimized subtraction assignment to dense matrices******************************************
1321  template< typename MT3 // Type of the left-hand side target matrix
1322  , typename MT4 // Type of the left-hand side matrix operand
1323  , typename MT5 > // Type of the right-hand side matrix operand
1325  selectSubAssignKernel( MT3& C, const MT4& A, const MT5& B )
1326  {
1328 
1329  const size_t M( A.rows() );
1330  const size_t N( B.columns() );
1331 
1332  BLAZE_INTERNAL_ASSERT( !( LOW || UPP ) || M == N, "Broken invariant detected" );
1333 
1334  {
1335  size_t i( 0UL );
1336 
1337  for( ; (i+4UL) <= M; i+=4UL ) {
1338  for( size_t j=( UPP ? i : 0UL ); j<( LOW ? i+4UL : N ); ++j )
1339  {
1340  ConstIterator element( ( IsUpper<MT4>::value )
1341  ?( IsStrictlyUpper<MT4>::value ? B.upperBound(i,j) : B.lowerBound(i,j) )
1342  :( B.begin(j) ) );
1344  ?( IsStrictlyLower<MT4>::value ? B.lowerBound(i+4UL,j) : B.upperBound(i+4UL,j) )
1345  :( B.end(j) ) );
1346 
1347  const size_t nonzeros( end - element );
1348  const size_t kpos( nonzeros & size_t(-4) );
1349  BLAZE_INTERNAL_ASSERT( ( nonzeros - ( nonzeros % 4UL ) ) == kpos, "Invalid end calculation" );
1350 
1351  for( size_t k=0UL; k<kpos; k+=4UL )
1352  {
1353  const size_t j1( element->index() );
1354  const ET2 v1( element->value() );
1355  ++element;
1356  const size_t j2( element->index() );
1357  const ET2 v2( element->value() );
1358  ++element;
1359  const size_t j3( element->index() );
1360  const ET2 v3( element->value() );
1361  ++element;
1362  const size_t j4( element->index() );
1363  const ET2 v4( element->value() );
1364  ++element;
1365 
1366  BLAZE_INTERNAL_ASSERT( j1 < j2 && j2 < j3 && j3 < j4, "Invalid sparse matrix index detected" );
1367 
1368  C(i ,j) -= A(i ,j1) * v1 + A(i ,j2) * v2 + A(i ,j3) * v3 + A(i ,j4) * v4;
1369  C(i+1UL,j) -= A(i+1UL,j1) * v1 + A(i+1UL,j2) * v2 + A(i+1UL,j3) * v3 + A(i+1UL,j4) * v4;
1370  C(i+2UL,j) -= A(i+2UL,j1) * v1 + A(i+2UL,j2) * v2 + A(i+2UL,j3) * v3 + A(i+2UL,j4) * v4;
1371  C(i+3UL,j) -= A(i+3UL,j1) * v1 + A(i+3UL,j2) * v2 + A(i+3UL,j3) * v3 + A(i+3UL,j4) * v4;
1372  }
1373 
1374  for( ; element!=end; ++element )
1375  {
1376  const size_t j1( element->index() );
1377  const ET2 v1( element->value() );
1378 
1379  C(i ,j) -= A(i ,j1) * v1;
1380  C(i+1UL,j) -= A(i+1UL,j1) * v1;
1381  C(i+2UL,j) -= A(i+2UL,j1) * v1;
1382  C(i+3UL,j) -= A(i+3UL,j1) * v1;
1383  }
1384  }
1385  }
1386 
1387  for( ; (i+2UL) <= M; i+=2UL ) {
1388  for( size_t j=( UPP ? i : 0UL ); j<( LOW ? i+2UL : N ); ++j )
1389  {
1390  ConstIterator element( ( IsUpper<MT4>::value )
1391  ?( IsStrictlyUpper<MT4>::value ? B.upperBound(i,j) : B.lowerBound(i,j) )
1392  :( B.begin(j) ) );
1394  ?( IsStrictlyLower<MT4>::value ? B.lowerBound(i+2UL,j) : B.upperBound(i+2UL,j) )
1395  :( B.end(j) ) );
1396 
1397  const size_t nonzeros( end - element );
1398  const size_t kpos( nonzeros & size_t(-4) );
1399  BLAZE_INTERNAL_ASSERT( ( nonzeros - ( nonzeros % 4UL ) ) == kpos, "Invalid end calculation" );
1400 
1401  for( size_t k=0UL; k<kpos; k+=4UL )
1402  {
1403  const size_t j1( element->index() );
1404  const ET2 v1( element->value() );
1405  ++element;
1406  const size_t j2( element->index() );
1407  const ET2 v2( element->value() );
1408  ++element;
1409  const size_t j3( element->index() );
1410  const ET2 v3( element->value() );
1411  ++element;
1412  const size_t j4( element->index() );
1413  const ET2 v4( element->value() );
1414  ++element;
1415 
1416  BLAZE_INTERNAL_ASSERT( j1 < j2 && j2 < j3 && j3 < j4, "Invalid sparse matrix index detected" );
1417 
1418  C(i ,j) -= A(i ,j1) * v1 + A(i ,j2) * v2 + A(i ,j3) * v3 + A(i ,j4) * v4;
1419  C(i+1UL,j) -= A(i+1UL,j1) * v1 + A(i+1UL,j2) * v2 + A(i+1UL,j3) * v3 + A(i+1UL,j4) * v4;
1420  }
1421 
1422  for( ; element!=end; ++element )
1423  {
1424  const size_t j1( element->index() );
1425  const ET2 v1( element->value() );
1426 
1427  C(i ,j) -= A(i ,j1) * v1;
1428  C(i+1UL,j) -= A(i+1UL,j1) * v1;
1429  }
1430  }
1431  }
1432 
1433  for( ; i<M; ++i ) {
1434  for( size_t j=( UPP ? i : 0UL ); j<( LOW ? i+1UL : N ); ++j )
1435  {
1436  ConstIterator element( ( IsUpper<MT4>::value )
1437  ?( IsStrictlyUpper<MT4>::value ? B.upperBound(i,j) : B.lowerBound(i,j) )
1438  :( B.begin(j) ) );
1440  ?( IsStrictlyLower<MT4>::value ? B.lowerBound(i,j) : B.upperBound(i,j) )
1441  :( B.end(j) ) );
1442 
1443  const size_t nonzeros( end - element );
1444  const size_t kpos( nonzeros & size_t(-4) );
1445  BLAZE_INTERNAL_ASSERT( ( nonzeros - ( nonzeros % 4UL ) ) == kpos, "Invalid end calculation" );
1446 
1447  for( size_t k=0UL; k<kpos; k+=4UL )
1448  {
1449  const size_t j1( element->index() );
1450  const ET2 v1( element->value() );
1451  ++element;
1452  const size_t j2( element->index() );
1453  const ET2 v2( element->value() );
1454  ++element;
1455  const size_t j3( element->index() );
1456  const ET2 v3( element->value() );
1457  ++element;
1458  const size_t j4( element->index() );
1459  const ET2 v4( element->value() );
1460  ++element;
1461 
1462  BLAZE_INTERNAL_ASSERT( j1 < j2 && j2 < j3 && j3 < j4, "Invalid sparse matrix index detected" );
1463 
1464  C(i,j) -= A(i,j1) * v1 + A(i,j2) * v2 + A(i,j3) * v3 + A(i,j4) * v4;
1465  }
1466 
1467  for( ; element!=end; ++element )
1468  {
1469  const size_t j1( element->index() );
1470  const ET2 v1( element->value() );
1471 
1472  C(i,j) -= A(i,j1) * v1;
1473  }
1474  }
1475  }
1476  }
1477  }
1479  //**********************************************************************************************
1480 
1481  //**Restructuring subtraction assignment********************************************************
1496  template< typename MT // Type of the target matrix
1497  , bool SO > // Storage order of the target matrix
1499  subAssign( Matrix<MT,SO>& lhs, const DMatTSMatMultExpr& rhs )
1500  {
1502 
1504 
1505  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
1506  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
1507 
1508  const ForwardFunctor fwd;
1509 
1510  subAssign( ~lhs, fwd( trans( rhs.lhs_ ) * rhs.rhs_ ) );
1511  }
1513  //**********************************************************************************************
1514 
1515  //**Subtraction assignment to sparse matrices***************************************************
1516  // No special implementation for the subtraction assignment to sparse matrices.
1517  //**********************************************************************************************
1518 
1519  //**Schur product assignment to dense matrices**************************************************
1532  template< typename MT // Type of the target dense matrix
1533  , bool SO > // Storage order of the target dense matrix
1534  friend inline void schurAssign( DenseMatrix<MT,SO>& lhs, const DMatTSMatMultExpr& rhs )
1535  {
1537 
1541 
1542  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
1543  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
1544 
1545  const ResultType tmp( serial( rhs ) );
1546  schurAssign( ~lhs, tmp );
1547  }
1549  //**********************************************************************************************
1550 
1551  //**Schur product assignment to sparse matrices*************************************************
1552  // No special implementation for the Schur product assignment to sparse matrices.
1553  //**********************************************************************************************
1554 
1555  //**Multiplication assignment to dense matrices*************************************************
1556  // No special implementation for the multiplication assignment to dense matrices.
1557  //**********************************************************************************************
1558 
1559  //**Multiplication assignment to sparse matrices************************************************
1560  // No special implementation for the multiplication assignment to sparse matrices.
1561  //**********************************************************************************************
1562 
1563  //**SMP assignment to dense matrices************************************************************
1578  template< typename MT // Type of the target dense matrix
1579  , bool SO > // Storage order of the target dense matrix
1581  smpAssign( DenseMatrix<MT,SO>& lhs, const DMatTSMatMultExpr& rhs )
1582  {
1584 
1585  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
1586  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
1587 
1588  LT A( rhs.lhs_ ); // Evaluation of the left-hand side dense matrix operand
1589  RT B( rhs.rhs_ ); // Evaluation of the right-hand side sparse matrix operand
1590 
1591  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
1592  BLAZE_INTERNAL_ASSERT( A.columns() == B.rows() , "Invalid matrix sizes" );
1593  BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns(), "Invalid number of columns" );
1594 
1595  smpAssign( ~lhs, A * B );
1596  }
1598  //**********************************************************************************************
1599 
1600  //**SMP assignment to sparse matrices***********************************************************
1615  template< typename MT // Type of the target sparse matrix
1616  , bool SO > // Storage order of the target sparse matrix
1618  smpAssign( SparseMatrix<MT,SO>& lhs, const DMatTSMatMultExpr& rhs )
1619  {
1621 
1623 
1630 
1631  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
1632  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
1633 
1634  const ForwardFunctor fwd;
1635 
1636  const TmpType tmp( rhs );
1637  smpAssign( ~lhs, fwd( tmp ) );
1638  }
1640  //**********************************************************************************************
1641 
1642  //**Restructuring SMP assignment****************************************************************
1657  template< typename MT // Type of the target matrix
1658  , bool SO > // Storage order of the target matrix
1660  smpAssign( Matrix<MT,SO>& lhs, const DMatTSMatMultExpr& rhs )
1661  {
1663 
1665 
1666  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
1667  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
1668 
1669  const ForwardFunctor fwd;
1670 
1671  smpAssign( ~lhs, fwd( trans( rhs.lhs_ ) * rhs.rhs_ ) );
1672  }
1674  //**********************************************************************************************
1675 
1676  //**SMP addition assignment to dense matrices***************************************************
1692  template< typename MT // Type of the target dense matrix
1693  , bool SO > // Storage order of the target dense matrix
1696  {
1698 
1699  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
1700  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
1701 
1702  LT A( rhs.lhs_ ); // Evaluation of the left-hand side dense matrix operand
1703  RT B( rhs.rhs_ ); // Evaluation of the right-hand side sparse matrix operand
1704 
1705  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
1706  BLAZE_INTERNAL_ASSERT( A.columns() == B.rows() , "Invalid matrix sizes" );
1707  BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns(), "Invalid number of columns" );
1708 
1709  smpAddAssign( ~lhs, A * B );
1710  }
1712  //**********************************************************************************************
1713 
1714  //**Restructuring SMP addition assignment*******************************************************
1729  template< typename MT // Type of the target matrix
1730  , bool SO > // Storage order of the target matrix
1732  smpAddAssign( Matrix<MT,SO>& lhs, const DMatTSMatMultExpr& rhs )
1733  {
1735 
1737 
1738  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
1739  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
1740 
1741  const ForwardFunctor fwd;
1742 
1743  smpAddAssign( ~lhs, fwd( trans( rhs.lhs_ ) * rhs.rhs_ ) );
1744  }
1746  //**********************************************************************************************
1747 
1748  //**SMP addition assignment to sparse matrices**************************************************
1749  // No special implementation for the SMP addition assignment to sparse matrices.
1750  //**********************************************************************************************
1751 
1752  //**SMP subtraction assignment to dense matrices************************************************
1768  template< typename MT // Type of the target dense matrix
1769  , bool SO > // Storage order of the target dense matrix
1772  {
1774 
1775  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
1776  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
1777 
1778  LT A( rhs.lhs_ ); // Evaluation of the left-hand side dense matrix operand
1779  RT B( rhs.rhs_ ); // Evaluation of the right-hand side sparse matrix operand
1780 
1781  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
1782  BLAZE_INTERNAL_ASSERT( A.columns() == B.rows() , "Invalid matrix sizes" );
1783  BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns(), "Invalid number of columns" );
1784 
1785  smpSubAssign( ~lhs, A * B );
1786  }
1788  //**********************************************************************************************
1789 
1790  //**Restructuring SMP subtraction assignment****************************************************
1805  template< typename MT // Type of the target matrix
1806  , bool SO > // Storage order of the target matrix
1808  smpSubAssign( Matrix<MT,SO>& lhs, const DMatTSMatMultExpr& rhs )
1809  {
1811 
1813 
1814  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
1815  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
1816 
1817  const ForwardFunctor fwd;
1818 
1819  smpSubAssign( ~lhs, fwd( trans( rhs.lhs_ ) * rhs.rhs_ ) );
1820  }
1822  //**********************************************************************************************
1823 
1824  //**SMP subtraction assignment to sparse matrices***********************************************
1825  // No special implementation for the SMP subtraction assignment to sparse matrices.
1826  //**********************************************************************************************
1827 
1828  //**SMP Schur product assignment to dense matrices**********************************************
1841  template< typename MT // Type of the target dense matrix
1842  , bool SO > // Storage order of the target dense matrix
1843  friend inline void smpSchurAssign( DenseMatrix<MT,SO>& lhs, const DMatTSMatMultExpr& rhs )
1844  {
1846 
1850 
1851  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
1852  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
1853 
1854  const ResultType tmp( rhs );
1855  smpSchurAssign( ~lhs, tmp );
1856  }
1858  //**********************************************************************************************
1859 
1860  //**SMP Schur product assignment to sparse matrices*********************************************
1861  // No special implementation for the SMP Schur product assignment to sparse matrices.
1862  //**********************************************************************************************
1863 
1864  //**SMP multiplication assignment to dense matrices*********************************************
1865  // No special implementation for the SMP multiplication assignment to dense matrices.
1866  //**********************************************************************************************
1867 
1868  //**SMP multiplication assignment to sparse matrices********************************************
1869  // No special implementation for the SMP multiplication assignment to sparse matrices.
1870  //**********************************************************************************************
1871 
1872  //**Compile time checks*************************************************************************
1880  //**********************************************************************************************
1881 };
1882 //*************************************************************************************************
1883 
1884 
1885 
1886 
1887 //=================================================================================================
1888 //
1889 // GLOBAL BINARY ARITHMETIC OPERATORS
1890 //
1891 //=================================================================================================
1892 
1893 //*************************************************************************************************
1923 template< typename MT1 // Type of the left-hand side dense matrix
1924  , typename MT2 > // Type of the right-hand side sparse matrix
1925 inline decltype(auto)
1926  operator*( const DenseMatrix<MT1,false>& lhs, const SparseMatrix<MT2,true>& rhs )
1927 {
1929 
1930  if( (~lhs).columns() != (~rhs).rows() ) {
1931  BLAZE_THROW_INVALID_ARGUMENT( "Matrix sizes do not match" );
1932  }
1933 
1935  return ReturnType( ~lhs, ~rhs );
1936 }
1937 //*************************************************************************************************
1938 
1939 
1940 
1941 
1942 //=================================================================================================
1943 //
1944 // GLOBAL FUNCTIONS
1945 //
1946 //=================================================================================================
1947 
1948 //*************************************************************************************************
1972 template< typename MT1 // Type of the left-hand side dense matrix
1973  , typename MT2 // Type of the right-hand side sparse matrix
1974  , bool SF // Symmetry flag
1975  , bool HF // Hermitian flag
1976  , bool LF // Lower flag
1977  , bool UF > // Upper flag
1978 inline decltype(auto) declsym( const DMatTSMatMultExpr<MT1,MT2,SF,HF,LF,UF>& dm )
1979 {
1981 
1982  if( !isSquare( dm ) ) {
1983  BLAZE_THROW_INVALID_ARGUMENT( "Invalid symmetric matrix specification" );
1984  }
1985 
1987  return ReturnType( dm.leftOperand(), dm.rightOperand() );
1988 }
1990 //*************************************************************************************************
1991 
1992 
1993 //*************************************************************************************************
2017 template< typename MT1 // Type of the left-hand side dense matrix
2018  , typename MT2 // Type of the right-hand side sparse matrix
2019  , bool SF // Symmetry flag
2020  , bool HF // Hermitian flag
2021  , bool LF // Lower flag
2022  , bool UF > // Upper flag
2023 inline decltype(auto) declherm( const DMatTSMatMultExpr<MT1,MT2,SF,HF,LF,UF>& dm )
2024 {
2026 
2027  if( !isSquare( dm ) ) {
2028  BLAZE_THROW_INVALID_ARGUMENT( "Invalid Hermitian matrix specification" );
2029  }
2030 
2032  return ReturnType( dm.leftOperand(), dm.rightOperand() );
2033 }
2035 //*************************************************************************************************
2036 
2037 
2038 //*************************************************************************************************
2062 template< typename MT1 // Type of the left-hand side dense matrix
2063  , typename MT2 // Type of the right-hand side sparse matrix
2064  , bool SF // Symmetry flag
2065  , bool HF // Hermitian flag
2066  , bool LF // Lower flag
2067  , bool UF > // Upper flag
2068 inline decltype(auto) decllow( const DMatTSMatMultExpr<MT1,MT2,SF,HF,LF,UF>& dm )
2069 {
2071 
2072  if( !isSquare( dm ) ) {
2073  BLAZE_THROW_INVALID_ARGUMENT( "Invalid lower matrix specification" );
2074  }
2075 
2077  return ReturnType( dm.leftOperand(), dm.rightOperand() );
2078 }
2080 //*************************************************************************************************
2081 
2082 
2083 //*************************************************************************************************
2107 template< typename MT1 // Type of the left-hand side dense matrix
2108  , typename MT2 // Type of the right-hand side sparse matrix
2109  , bool SF // Symmetry flag
2110  , bool HF // Hermitian flag
2111  , bool LF // Lower flag
2112  , bool UF > // Upper flag
2113 inline decltype(auto) declupp( const DMatTSMatMultExpr<MT1,MT2,SF,HF,LF,UF>& dm )
2114 {
2116 
2117  if( !isSquare( dm ) ) {
2118  BLAZE_THROW_INVALID_ARGUMENT( "Invalid upper matrix specification" );
2119  }
2120 
2122  return ReturnType( dm.leftOperand(), dm.rightOperand() );
2123 }
2125 //*************************************************************************************************
2126 
2127 
2128 //*************************************************************************************************
2152 template< typename MT1 // Type of the left-hand side dense matrix
2153  , typename MT2 // Type of the right-hand side sparse matrix
2154  , bool SF // Symmetry flag
2155  , bool HF // Hermitian flag
2156  , bool LF // Lower flag
2157  , bool UF > // Upper flag
2158 inline decltype(auto) decldiag( const DMatTSMatMultExpr<MT1,MT2,SF,HF,LF,UF>& dm )
2159 {
2161 
2162  if( !isSquare( dm ) ) {
2163  BLAZE_THROW_INVALID_ARGUMENT( "Invalid diagonal matrix specification" );
2164  }
2165 
2167  return ReturnType( dm.leftOperand(), dm.rightOperand() );
2168 }
2170 //*************************************************************************************************
2171 
2172 
2173 
2174 
2175 //=================================================================================================
2176 //
2177 // ROWS SPECIALIZATIONS
2178 //
2179 //=================================================================================================
2180 
2181 //*************************************************************************************************
2183 template< typename MT1, typename MT2, bool SF, bool HF, bool LF, bool UF >
2184 struct Rows< DMatTSMatMultExpr<MT1,MT2,SF,HF,LF,UF> >
2185  : public Rows<MT1>
2186 {};
2188 //*************************************************************************************************
2189 
2190 
2191 
2192 
2193 //=================================================================================================
2194 //
2195 // COLUMNS SPECIALIZATIONS
2196 //
2197 //=================================================================================================
2198 
2199 //*************************************************************************************************
2201 template< typename MT1, typename MT2, bool SF, bool HF, bool LF, bool UF >
2202 struct Columns< DMatTSMatMultExpr<MT1,MT2,SF,HF,LF,UF> >
2203  : public Columns<MT2>
2204 {};
2206 //*************************************************************************************************
2207 
2208 
2209 
2210 
2211 //=================================================================================================
2212 //
2213 // ISALIGNED SPECIALIZATIONS
2214 //
2215 //=================================================================================================
2216 
2217 //*************************************************************************************************
2219 template< typename MT1, typename MT2, bool SF, bool HF, bool LF, bool UF >
2220 struct IsAligned< DMatTSMatMultExpr<MT1,MT2,SF,HF,LF,UF> >
2221  : public BoolConstant< IsAligned<MT1>::value >
2222 {};
2224 //*************************************************************************************************
2225 
2226 
2227 
2228 
2229 //=================================================================================================
2230 //
2231 // ISSYMMETRIC SPECIALIZATIONS
2232 //
2233 //=================================================================================================
2234 
2235 //*************************************************************************************************
2237 template< typename MT1, typename MT2, bool SF, bool HF, bool LF, bool UF >
2238 struct IsSymmetric< DMatTSMatMultExpr<MT1,MT2,SF,HF,LF,UF> >
2239  : public BoolConstant< Or< Bool<SF>
2240  , And< Bool<HF>
2241  , IsBuiltin< ElementType_< DMatTSMatMultExpr<MT1,MT2,false,true,false,false> > > >
2242  , And< Bool<LF>, Bool<UF> > >::value >
2243 {};
2245 //*************************************************************************************************
2246 
2247 
2248 
2249 
2250 //=================================================================================================
2251 //
2252 // ISHERMITIAN SPECIALIZATIONS
2253 //
2254 //=================================================================================================
2255 
2256 //*************************************************************************************************
2258 template< typename MT1, typename MT2, bool SF, bool LF, bool UF >
2259 struct IsHermitian< DMatTSMatMultExpr<MT1,MT2,SF,true,LF,UF> >
2260  : public TrueType
2261 {};
2263 //*************************************************************************************************
2264 
2265 
2266 
2267 
2268 //=================================================================================================
2269 //
2270 // ISLOWER SPECIALIZATIONS
2271 //
2272 //=================================================================================================
2273 
2274 //*************************************************************************************************
2276 template< typename MT1, typename MT2, bool SF, bool HF, bool LF, bool UF >
2277 struct IsLower< DMatTSMatMultExpr<MT1,MT2,SF,HF,LF,UF> >
2278  : public BoolConstant< Or< Bool<LF>
2279  , And< IsLower<MT1>, IsLower<MT2> >
2280  , And< Or< Bool<SF>, Bool<HF> >
2281  , IsUpper<MT1>, IsUpper<MT2> > >::value >
2282 {};
2284 //*************************************************************************************************
2285 
2286 
2287 
2288 
2289 //=================================================================================================
2290 //
2291 // ISUNILOWER SPECIALIZATIONS
2292 //
2293 //=================================================================================================
2294 
2295 //*************************************************************************************************
2297 template< typename MT1, typename MT2, bool SF, bool HF, bool LF, bool UF >
2298 struct IsUniLower< DMatTSMatMultExpr<MT1,MT2,SF,HF,LF,UF> >
2299  : public BoolConstant< Or< And< IsUniLower<MT1>, IsUniLower<MT2> >
2300  , And< Or< Bool<SF>, Bool<HF> >
2301  , IsUniUpper<MT1>, IsUniUpper<MT2> > >::value >
2302 {};
2304 //*************************************************************************************************
2305 
2306 
2307 
2308 
2309 //=================================================================================================
2310 //
2311 // ISSTRICTLYLOWER SPECIALIZATIONS
2312 //
2313 //=================================================================================================
2314 
2315 //*************************************************************************************************
2317 template< typename MT1, typename MT2, bool SF, bool HF, bool LF, bool UF >
2318 struct IsStrictlyLower< DMatTSMatMultExpr<MT1,MT2,SF,HF,LF,UF> >
2319  : public BoolConstant< Or< And< IsStrictlyLower<MT1>, IsLower<MT2> >
2320  , And< IsStrictlyLower<MT2>, IsLower<MT1> >
2321  , And< Or< Bool<SF>, Bool<HF> >
2322  , Or< And< IsStrictlyUpper<MT1>, IsUpper<MT2> >
2323  , And< IsStrictlyUpper<MT2>, IsUpper<MT1> > > > >::value >
2324 {};
2326 //*************************************************************************************************
2327 
2328 
2329 
2330 
2331 //=================================================================================================
2332 //
2333 // ISUPPER SPECIALIZATIONS
2334 //
2335 //=================================================================================================
2336 
2337 //*************************************************************************************************
2339 template< typename MT1, typename MT2, bool SF, bool HF, bool LF, bool UF >
2340 struct IsUpper< DMatTSMatMultExpr<MT1,MT2,SF,HF,LF,UF> >
2341  : public BoolConstant< Or< Bool<UF>
2342  , And< IsUpper<MT1>, IsUpper<MT2> >
2343  , And< Or< Bool<SF>, Bool<HF> >
2344  , IsLower<MT1>, IsLower<MT2> > >::value >
2345 {};
2347 //*************************************************************************************************
2348 
2349 
2350 
2351 
2352 //=================================================================================================
2353 //
2354 // ISUNIUPPER SPECIALIZATIONS
2355 //
2356 //=================================================================================================
2357 
2358 //*************************************************************************************************
2360 template< typename MT1, typename MT2, bool SF, bool HF, bool LF, bool UF >
2361 struct IsUniUpper< DMatTSMatMultExpr<MT1,MT2,SF,HF,LF,UF> >
2362  : public BoolConstant< Or< And< IsUniUpper<MT1>, IsUniUpper<MT2> >
2363  , And< Or< Bool<SF>, Bool<HF> >
2364  , IsUniLower<MT1>, IsUniLower<MT2> > >::value >
2365 {};
2367 //*************************************************************************************************
2368 
2369 
2370 
2371 
2372 //=================================================================================================
2373 //
2374 // ISSTRICTLYUPPER SPECIALIZATIONS
2375 //
2376 //=================================================================================================
2377 
2378 //*************************************************************************************************
2380 template< typename MT1, typename MT2, bool SF, bool HF, bool LF, bool UF >
2381 struct IsStrictlyUpper< DMatTSMatMultExpr<MT1,MT2,SF,HF,LF,UF> >
2382  : public BoolConstant< Or< And< IsStrictlyUpper<MT1>, IsUpper<MT2> >
2383  , And< IsStrictlyUpper<MT2>, IsUpper<MT1> >
2384  , And< Or< Bool<SF>, Bool<HF> >
2385  , Or< And< IsStrictlyLower<MT1>, IsLower<MT2> >
2386  , And< IsStrictlyLower<MT2>, IsLower<MT1> > > > >::value >
2387 {};
2389 //*************************************************************************************************
2390 
2391 } // namespace blaze
2392 
2393 #endif
CompositeType_< MT1 > CT1
Composite type of the left-hand side dense matrix expression.
Definition: DMatTSMatMultExpr.h:134
#define BLAZE_THROW_INVALID_ARGUMENT(MESSAGE)
Macro for the emission of a std::invalid_argument exception.This macro encapsulates the default way o...
Definition: Exception.h:235
ElementType_< RT1 > ET1
Element type of the left-hand side dense matrix expression.
Definition: DMatTSMatMultExpr.h:132
Header file for auxiliary alias declarations.
Headerfile for the generic min algorithm.
Compile time check whether the given type is a computational expression template.This type trait clas...
Definition: IsComputation.h:72
decltype(auto) decldiag(const DenseMatrix< MT, SO > &dm)
Declares the given dense matrix expression dm as diagonal.
Definition: DMatDeclDiagExpr.h:996
Header file for the Rows type trait.
Header file for the IsUniUpper type trait.
EnableIf_< IsDenseMatrix< MT1 > > smpSchurAssign(Matrix< MT1, SO1 > &lhs, const Matrix< MT2, SO2 > &rhs)
Default implementation of the SMP Schur product assignment of a matrix to dense matrix.
Definition: DenseMatrix.h:196
Compile time check for triangular matrix types.This type trait tests whether or not the given templat...
Definition: IsTriangular.h:87
Header file for basic type definitions.
Subvector< VT, AF > subvector(Vector< VT, TF > &vector, size_t index, size_t size)
Creating a view on a specific subvector of the given vector.
Definition: Subvector.h:322
EnableIf_< IsDenseMatrix< MT1 > > 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:164
size_t columns() const noexcept
Returns the current number of columns of the matrix.
Definition: DMatTSMatMultExpr.h:349
Header file for the serial shim.
Header file for the IsDiagonal type trait.
Generic wrapper for a compile time constant integral value.The IntegralConstant class template repres...
Definition: IntegralConstant.h:71
#define BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE(T)
Constraint on the data type.In case the given data type T is not a dense, N-dimensional matrix type...
Definition: DenseMatrix.h:61
Header file for the DeclUpp functor.
BLAZE_ALWAYS_INLINE MT::Iterator begin(Matrix< MT, SO > &matrix, size_t i)
Returns an iterator to the first element of row/column i.
Definition: Matrix.h:198
void reset(const DiagonalProxy< MT > &proxy)
Resetting the represented element to the default initial values.
Definition: DiagonalProxy.h:560
DMatTSMatMultExpr(const MT1 &lhs, const MT2 &rhs) noexcept
Constructor for the DMatTSMatMultExpr class.
Definition: DMatTSMatMultExpr.h:260
LeftOperand leftOperand() const noexcept
Returns the left-hand side dense matrix operand.
Definition: DMatTSMatMultExpr.h:359
typename DisableIf< Condition, T >::Type DisableIf_
Auxiliary type for the DisableIf class template.The DisableIf_ alias declaration provides a convenien...
Definition: DisableIf.h:224
Header file for the And class template.
const ElementType_< MT > min(const DenseMatrix< MT, SO > &dm)
Returns the smallest element of the dense matrix.
Definition: DenseMatrix.h:1762
Compile time check for lower triangular matrices.This type trait tests whether or not the given templ...
Definition: IsLower.h:88
ReturnType at(size_t i, size_t j) const
Checked access to the matrix elements.
Definition: DMatTSMatMultExpr.h:323
bool canSMPAssign() const noexcept
Returns whether the expression can be used in SMP assignments.
Definition: DMatTSMatMultExpr.h:413
decltype(auto) declupp(const DenseMatrix< MT, SO > &dm)
Declares the given dense matrix expression dm as upper.
Definition: DMatDeclUppExpr.h:1027
typename MultTrait< T1, T2 >::Type MultTrait_
Auxiliary alias declaration for the MultTrait class template.The MultTrait_ alias declaration provide...
Definition: MultTrait.h:250
Column< MT > column(Matrix< MT, SO > &matrix, size_t index)
Creating a view on a specific column of the given matrix.
Definition: Column.h:124
Header file for the Computation base class.
OppositeType_< ResultType > OppositeType
Result type with opposite storage order for expression template evaluations.
Definition: DMatTSMatMultExpr.h:226
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:88
Constraints on the storage order of matrix types.
Header file for the RequiresEvaluation type trait.
IfTrue_< evaluateLeft, const RT1, CT1 > LT
Type for the assignment of the left-hand side dense matrix operand.
Definition: DMatTSMatMultExpr.h:239
System settings for performance optimizations.
ResultType_< MT2 > RT2
Result type of the right-hand side sparse matrix expression.
Definition: DMatTSMatMultExpr.h:131
Header file for the IsUniLower type trait.
typename T::ResultType ResultType_
Alias declaration for nested ResultType type definitions.The ResultType_ alias declaration provides a...
Definition: Aliases.h:343
const ElementType_< MT > max(const DenseMatrix< MT, SO > &dm)
Returns the largest element of the dense matrix.
Definition: DenseMatrix.h:1809
EnableIf_< IsDenseMatrix< MT1 > > 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:133
Base class for dense matrices.The DenseMatrix class is a base class for all dense matrix classes...
Definition: DenseMatrix.h:78
Base class for sparse matrices.The SparseMatrix class is a base class for all sparse matrix classes...
Definition: Forward.h:129
typename IfTrue< Condition, T1, T2 >::Type IfTrue_
Auxiliary alias declaration for the IfTrue class template.The IfTrue_ alias declaration provides a co...
Definition: If.h:109
Row< MT > row(Matrix< MT, SO > &matrix, size_t index)
Creating a view on a specific row of the given matrix.
Definition: Row.h:124
Compile time check for the alignment of data types.This type trait tests whether the given data type ...
Definition: IsAligned.h:87
Constraint on the data type.
Constraint on the data type.
Compile time check to query the requirement to evaluate an expression.Via this type trait it is possi...
Definition: RequiresEvaluation.h:72
RightOperand rhs_
Right-hand side sparse matrix of the multiplication expression.
Definition: DMatTSMatMultExpr.h:421
typename T::CompositeType CompositeType_
Alias declaration for nested CompositeType type definitions.The CompositeType_ alias declaration prov...
Definition: Aliases.h:83
Compile time check for upper unitriangular matrices.This type trait tests whether or not the given te...
Definition: IsUniUpper.h:86
Headerfile for the generic max algorithm.
Header file for the DisableIf class template.
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
Header file for the DeclLow functor.
bool isAliased(const T *alias) const noexcept
Returns whether the expression is aliased with the given address alias.
Definition: DMatTSMatMultExpr.h:393
Header file for the If class template.
bool canAlias(const T *alias) const noexcept
Returns whether the expression can alias with the given address alias.
Definition: DMatTSMatMultExpr.h:381
#define BLAZE_CONSTRAINT_MUST_BE_COLUMN_MAJOR_MATRIX_TYPE(T)
Constraint on the data type.In case the given data type T is not a column-major dense or sparse matri...
Definition: ColumnMajorMatrix.h:61
Generic wrapper for the decllow() function.
Definition: DeclLow.h:58
EnableIf_< IsDenseMatrix< MT1 > > 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:102
Header file for the Or class template.
#define BLAZE_THROW_OUT_OF_RANGE(MESSAGE)
Macro for the emission of a std::out_of_range exception.This macro encapsulates the default way of Bl...
Definition: Exception.h:331
Header file for the DenseMatrix base class.
Header file for the Columns type trait.
const Element * ConstIterator
Iterator over constant elements.
Definition: CompressedMatrix.h:3087
typename T::ElementType ElementType_
Alias declaration for nested ElementType type definitions.The ElementType_ alias declaration provides...
Definition: Aliases.h:163
RightOperand rightOperand() const noexcept
Returns the right-hand side transpose sparse matrix operand.
Definition: DMatTSMatMultExpr.h:369
decltype(auto) decllow(const DenseMatrix< MT, SO > &dm)
Declares the given dense matrix expression dm as lower.
Definition: DMatDeclLowExpr.h:1027
Header file for the IsLower type trait.
Header file for the IsAligned type trait.
Compile time check for diagonal matrices.This type trait tests whether or not the given template para...
Definition: IsDiagonal.h:90
Flag for Hermitian matrices.
Definition: DMatTSMatMultExpr.h:152
Generic wrapper for the null function.
Definition: Noop.h:58
Header file for the IsTriangular type trait.
Constraints on the storage order of matrix types.
Compile time check for symmetric matrices.This type trait tests whether or not the given template par...
Definition: IsSymmetric.h:85
Header file for the exception macros of the math module.
Compile time check for strictly upper triangular matrices.This type trait tests whether or not the gi...
Definition: IsStrictlyUpper.h:86
size_t rows() const noexcept
Returns the current number of rows of the matrix.
Definition: DMatTSMatMultExpr.h:339
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:264
Header file for the DeclDiag functor.
Constraint on the data type.
Header file for all forward declarations for expression class templates.
bool isAligned() const noexcept
Returns whether the operands of the expression are properly aligned in memory.
Definition: DMatTSMatMultExpr.h:403
Flag for upper matrices.
Definition: DMatTSMatMultExpr.h:154
Header file for the EnableIf class template.
Header file for the IsStrictlyLower type trait.
#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:108
Compile time check for lower unitriangular matrices.This type trait tests whether or not the given te...
Definition: IsUniLower.h:86
Header file for the conjugate shim.
Compile time check for resizable data types.This type trait tests whether the given data type is a re...
Definition: IsResizable.h:75
Base class for all matrix/matrix multiplication expression templates.The MatMatMultExpr class serves ...
Definition: MatMatMultExpr.h:67
#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:79
#define BLAZE_CONSTRAINT_MUST_BE_ROW_MAJOR_MATRIX_TYPE(T)
Constraint on the data type.In case the given data type T is not a row-major dense or sparse matrix t...
Definition: RowMajorMatrix.h:61
Header file for run time assertion macros.
Utility type for generic codes.
typename If< T1, T2, T3 >::Type If_
Auxiliary alias declaration for the If class template.The If_ alias declaration provides a convenient...
Definition: If.h:154
LeftOperand lhs_
Left-hand side dense matrix of the multiplication expression.
Definition: DMatTSMatMultExpr.h:420
Header file for the reset shim.
ElementType_< RT2 > ET2
Element type of the right-hand side sparse matrix expression.
Definition: DMatTSMatMultExpr.h:133
#define BLAZE_FUNCTION_TRACE
Function trace macro.This macro can be used to reliably trace function calls. In case function tracin...
Definition: FunctionTrace.h:94
Flag for symmetric matrices.
Definition: DMatTSMatMultExpr.h:151
decltype(auto) declsym(const DenseMatrix< MT, SO > &dm)
Declares the given dense matrix expression dm as symmetric.
Definition: DMatDeclSymExpr.h:1029
Compile time check for Hermitian matrices.This type trait tests whether or not the given template par...
Definition: IsHermitian.h:85
Flag for lower matrices.
Definition: DMatTSMatMultExpr.h:153
Base class for matrices.The Matrix class is a base class for all dense and sparse matrix classes with...
Definition: Forward.h:101
Expression object for dense matrix-transpose sparse matrix multiplications.The DMatTSMatMultExpr clas...
Definition: DMatTSMatMultExpr.h:124
Constraint on the data type.
Constraints on the storage order of matrix types.
Generic wrapper for the declherm() function.
Definition: DeclHerm.h:58
decltype(auto) serial(const DenseMatrix< MT, SO > &dm)
Forces the serial evaluation of the given dense matrix expression dm.
Definition: DMatSerialExpr.h:819
Header file for the Noop functor.
CompositeType_< MT2 > CT2
Composite type of the right-hand side sparse matrix expression.
Definition: DMatTSMatMultExpr.h:135
#define BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION(T)
Constraint on the data type.In case the given data type T requires an intermediate evaluation within ...
Definition: RequiresEvaluation.h:81
Header file for the RemoveReference type trait.
typename EnableIf< Condition, T >::Type EnableIf_
Auxiliary alias declaration for the EnableIf class template.The EnableIf_ alias declaration provides ...
Definition: EnableIf.h:224
If_< IsExpression< MT2 >, const MT2, const MT2 &> RightOperand
Composite type of the right-hand side sparse matrix expression.
Definition: DMatTSMatMultExpr.h:236
typename T::OppositeType OppositeType_
Alias declaration for nested OppositeType type definitions.The OppositeType_ alias declaration provid...
Definition: Aliases.h:263
#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:84
const ElementType ReturnType
Return type for expression template evaluations.
Definition: DMatTSMatMultExpr.h:229
Generic wrapper for the declupp() function.
Definition: DeclUpp.h:58
Compile time check for strictly lower triangular matrices.This type trait tests whether or not the gi...
Definition: IsStrictlyLower.h:86
const Type & ReturnType
Return type for expression template evaluations.
Definition: CompressedMatrix.h:3082
typename T::ConstIterator ConstIterator_
Alias declaration for nested ConstIterator type definitions.The ConstIterator_ alias declaration prov...
Definition: Aliases.h:103
decltype(auto) trans(const DenseMatrix< MT, SO > &dm)
Calculation of the transpose of the given dense matrix.
Definition: DMatTransExpr.h:790
const ResultType CompositeType
Data type for composite expression templates.
Definition: DMatTSMatMultExpr.h:230
decltype(auto) declherm(const DenseMatrix< MT, SO > &dm)
Declares the given dense matrix expression dm as Hermitian.
Definition: DMatDeclHermExpr.h:1029
ResultType_< MT1 > RT1
Result type of the left-hand side dense matrix expression.
Definition: DMatTSMatMultExpr.h:130
Header file for the IsComputation type trait class.
MultTrait_< RT1, RT2 > ResultType
Result type for expression template evaluations.
Definition: DMatTSMatMultExpr.h:225
Header file for the IsBuiltin type trait.
Base class for all compute expression templates.The Computation class serves as a tag for all computa...
Definition: Computation.h:66
TransposeType_< ResultType > TransposeType
Transpose type for expression template evaluations.
Definition: DMatTSMatMultExpr.h:227
Header file for the IntegralConstant class template.
Compile time evaluation of the number of columns of a matrix.The Columns type trait evaluates the num...
Definition: Columns.h:75
Generic wrapper for the decldiag() function.
Definition: DeclDiag.h:58
Compile time evaluation of the number of rows of a matrix.The Rows type trait evaluates the number of...
Definition: Rows.h:75
Header file for the DeclHerm functor.
typename T::TransposeType TransposeType_
Alias declaration for nested TransposeType type definitions.The TransposeType_ alias declaration prov...
Definition: Aliases.h:423
Header file for the IsUpper type trait.
decltype(auto) conj(const DenseMatrix< MT, SO > &dm)
Returns a matrix containing the complex conjugate of each single element of dm.
Definition: DMatMapExpr.h:1321
Constraint on the data type.
Generic wrapper for the declsym() function.
Definition: DeclSym.h:58
IfTrue_< evaluateRight, const RT2, CT2 > RT
Type for the assignment of the right-hand side sparse matrix operand.
Definition: DMatTSMatMultExpr.h:242
BLAZE_ALWAYS_INLINE bool isSquare(const Matrix< MT, SO > &matrix) noexcept
Checks if the given matrix is a square matrix.
Definition: Matrix.h:742
Header file for the IsResizable type trait.
ElementType_< ResultType > ElementType
Resulting element type.
Definition: DMatTSMatMultExpr.h:228
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 Bool class template.
Header file for the DeclSym functor.
#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:61
ReturnType operator()(size_t i, size_t j) const
2D-access to the matrix elements.
Definition: DMatTSMatMultExpr.h:275
Header file for the TrueType type/value trait base class.
Header file for the IsExpression type trait class.
Header file for the function trace functionality.
If_< IsExpression< MT1 >, const MT1, const MT1 &> LeftOperand
Composite type of the left-hand side dense matrix expression.
Definition: DMatTSMatMultExpr.h:233