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>
82 #include <blaze/math/views/Check.h>
87 #include <blaze/util/Assert.h>
88 #include <blaze/util/DisableIf.h>
89 #include <blaze/util/EnableIf.h>
91 #include <blaze/util/mpl/And.h>
92 #include <blaze/util/mpl/Bool.h>
93 #include <blaze/util/mpl/If.h>
94 #include <blaze/util/mpl/Or.h>
95 #include <blaze/util/TrueType.h>
96 #include <blaze/util/Types.h>
99 
100 
101 namespace blaze {
102 
103 //=================================================================================================
104 //
105 // CLASS DMATTSMATMULTEXPR
106 //
107 //=================================================================================================
108 
109 //*************************************************************************************************
116 template< typename MT1 // Type of the left-hand side dense matrix
117  , typename MT2 // Type of the right-hand side sparse matrix
118  , bool SF // Symmetry flag
119  , bool HF // Hermitian flag
120  , bool LF // Lower flag
121  , bool UF > // Upper flag
123  : public MatMatMultExpr< DenseMatrix< DMatTSMatMultExpr<MT1,MT2,SF,HF,LF,UF>, false > >
124  , private Computation
125 {
126  private:
127  //**Type definitions****************************************************************************
134  //**********************************************************************************************
135 
136  //**********************************************************************************************
138  enum : bool { evaluateLeft = IsComputation<MT1>::value || RequiresEvaluation<MT1>::value };
139  //**********************************************************************************************
140 
141  //**********************************************************************************************
143  enum : bool { evaluateRight = IsComputation<MT2>::value || RequiresEvaluation<MT2>::value };
144  //**********************************************************************************************
145 
146  //**********************************************************************************************
148  enum : bool {
149  SYM = ( SF && !( HF || LF || UF ) ),
150  HERM = ( HF && !( LF || UF ) ),
151  LOW = ( LF || ( ( SF || HF ) && UF ) ),
152  UPP = ( UF || ( ( SF || HF ) && LF ) )
153  };
154  //**********************************************************************************************
155 
156  //**********************************************************************************************
158 
163  template< typename T1, typename T2, typename T3 >
164  struct CanExploitSymmetry {
165  enum : bool { value = IsSymmetric<T2>::value };
166  };
168  //**********************************************************************************************
169 
170  //**********************************************************************************************
172 
176  template< typename T1, typename T2, typename T3 >
177  struct IsEvaluationRequired {
178  enum : bool { value = ( evaluateLeft || evaluateRight ) &&
179  !CanExploitSymmetry<T1,T2,T3>::value };
180  };
182  //**********************************************************************************************
183 
184  //**********************************************************************************************
186 
189  template< typename T1, typename T2, typename T3 >
190  struct UseOptimizedKernel {
191  enum : bool { value = useOptimizedKernels &&
193  !IsResizable< ElementType_<T1> >::value &&
195  };
197  //**********************************************************************************************
198 
199  //**********************************************************************************************
201 
204  using ForwardFunctor = IfTrue_< HERM
205  , DeclHerm
206  , IfTrue_< SYM
207  , DeclSym
208  , IfTrue_< LOW
209  , IfTrue_< UPP
210  , DeclDiag
211  , DeclLow >
212  , IfTrue_< UPP
213  , DeclUpp
214  , Noop > > > >;
216  //**********************************************************************************************
217 
218  public:
219  //**Type definitions****************************************************************************
222 
227  using ReturnType = const ElementType;
228  using CompositeType = const ResultType;
229 
231  using LeftOperand = If_< IsExpression<MT1>, const MT1, const MT1& >;
232 
234  using RightOperand = If_< IsExpression<MT2>, const MT2, const MT2& >;
235 
238 
241  //**********************************************************************************************
242 
243  //**Compilation flags***************************************************************************
245  enum : bool { simdEnabled = false };
246 
248  enum : bool { smpAssignable = !evaluateLeft && MT1::smpAssignable &&
249  !evaluateRight && MT2::smpAssignable };
250  //**********************************************************************************************
251 
252  //**Constructor*********************************************************************************
258  explicit inline DMatTSMatMultExpr( const MT1& lhs, const MT2& rhs ) noexcept
259  : lhs_( lhs ) // Left-hand side dense matrix of the multiplication expression
260  , rhs_( rhs ) // Right-hand side sparse matrix of the multiplication expression
261  {
262  BLAZE_INTERNAL_ASSERT( lhs.columns() == rhs.rows(), "Invalid matrix sizes" );
263  }
264  //**********************************************************************************************
265 
266  //**Access operator*****************************************************************************
273  inline ReturnType operator()( size_t i, size_t j ) const {
274  BLAZE_INTERNAL_ASSERT( i < lhs_.rows() , "Invalid row access index" );
275  BLAZE_INTERNAL_ASSERT( j < rhs_.columns(), "Invalid column access index" );
276 
277  if( IsDiagonal<MT1>::value ) {
278  return lhs_(i,i) * rhs_(i,j);
279  }
280  else if( IsDiagonal<MT2>::value ) {
281  return lhs_(i,j) * rhs_(j,j);
282  }
284  const size_t begin( ( IsUpper<MT1>::value )
285  ?( ( IsLower<MT2>::value )
286  ?( max( ( IsStrictlyUpper<MT1>::value ? i+1UL : i )
287  , ( IsStrictlyLower<MT2>::value ? j+1UL : j ) ) )
288  :( IsStrictlyUpper<MT1>::value ? i+1UL : i ) )
289  :( ( IsLower<MT2>::value )
290  ?( IsStrictlyLower<MT2>::value ? j+1UL : j )
291  :( 0UL ) ) );
292  const size_t end( ( IsLower<MT1>::value )
293  ?( ( IsUpper<MT2>::value )
294  ?( min( ( IsStrictlyLower<MT1>::value ? i : i+1UL )
295  , ( IsStrictlyUpper<MT2>::value ? j : j+1UL ) ) )
296  :( IsStrictlyLower<MT1>::value ? i : i+1UL ) )
297  :( ( IsUpper<MT2>::value )
298  ?( IsStrictlyUpper<MT2>::value ? j : j+1UL )
299  :( lhs_.columns() ) ) );
300 
301  if( begin >= end ) return ElementType();
302 
303  const size_t n( end - begin );
304 
305  return subvector( row( lhs_, i, unchecked ), begin, n, unchecked ) *
306  subvector( column( rhs_, j, unchecked ), begin, n, unchecked );
307  }
308  else {
309  return row( lhs_, i, unchecked ) * column( rhs_, j, unchecked );
310  }
311  }
312  //**********************************************************************************************
313 
314  //**At function*********************************************************************************
322  inline ReturnType at( size_t i, size_t j ) const {
323  if( i >= lhs_.rows() ) {
324  BLAZE_THROW_OUT_OF_RANGE( "Invalid row access index" );
325  }
326  if( j >= rhs_.columns() ) {
327  BLAZE_THROW_OUT_OF_RANGE( "Invalid column access index" );
328  }
329  return (*this)(i,j);
330  }
331  //**********************************************************************************************
332 
333  //**Rows function*******************************************************************************
338  inline size_t rows() const noexcept {
339  return lhs_.rows();
340  }
341  //**********************************************************************************************
342 
343  //**Columns function****************************************************************************
348  inline size_t columns() const noexcept {
349  return rhs_.columns();
350  }
351  //**********************************************************************************************
352 
353  //**Left operand access*************************************************************************
358  inline LeftOperand leftOperand() const noexcept {
359  return lhs_;
360  }
361  //**********************************************************************************************
362 
363  //**Right operand access************************************************************************
368  inline RightOperand rightOperand() const noexcept {
369  return rhs_;
370  }
371  //**********************************************************************************************
372 
373  //**********************************************************************************************
379  template< typename T >
380  inline bool canAlias( const T* alias ) const noexcept {
381  return ( lhs_.isAliased( alias ) || rhs_.isAliased( alias ) );
382  }
383  //**********************************************************************************************
384 
385  //**********************************************************************************************
391  template< typename T >
392  inline bool isAliased( const T* alias ) const noexcept {
393  return ( lhs_.isAliased( alias ) || rhs_.isAliased( alias ) );
394  }
395  //**********************************************************************************************
396 
397  //**********************************************************************************************
402  inline bool isAligned() const noexcept {
403  return lhs_.isAligned();
404  }
405  //**********************************************************************************************
406 
407  //**********************************************************************************************
412  inline bool canSMPAssign() const noexcept {
413  return ( rows() * columns() >= SMP_DMATTSMATMULT_THRESHOLD ) && !IsDiagonal<MT1>::value;
414  }
415  //**********************************************************************************************
416 
417  private:
418  //**Member variables****************************************************************************
421  //**********************************************************************************************
422 
423  //**Assignment to dense matrices****************************************************************
436  template< typename MT // Type of the target dense matrix
437  , bool SO > // Storage order of the target dense matrix
439  assign( DenseMatrix<MT,SO>& lhs, const DMatTSMatMultExpr& rhs )
440  {
442 
443  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
444  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
445 
446  LT A( serial( rhs.lhs_ ) ); // Evaluation of the left-hand side dense matrix operand
447  RT B( serial( rhs.rhs_ ) ); // Evaluation of the right-hand side sparse matrix operand
448 
449  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
450  BLAZE_INTERNAL_ASSERT( A.columns() == B.rows() , "Invalid matrix sizes" );
451  BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns(), "Invalid number of columns" );
452 
453  DMatTSMatMultExpr::selectAssignKernel( ~lhs, A, B );
454  }
456  //**********************************************************************************************
457 
458  //**Default assignment to dense matrices********************************************************
472  template< typename MT3 // Type of the left-hand side target matrix
473  , typename MT4 // Type of the left-hand side matrix operand
474  , typename MT5 > // Type of the right-hand side matrix operand
476  selectAssignKernel( MT3& C, const MT4& A, const MT5& B )
477  {
479 
480  const size_t M( A.rows() );
481  const size_t N( B.columns() );
482 
483  BLAZE_INTERNAL_ASSERT( !( SYM || HERM || LOW || UPP ) || M == N, "Broken invariant detected" );
484 
485  if( LOW && UPP ) {
486  reset( C );
487  }
488 
489  {
490  size_t i( 0UL );
491 
492  for( ; (i+4UL) <= M; i+=4UL ) {
493  for( size_t j=( SYM || HERM || UPP ? i : 0UL ); j<( LOW ? i+4UL : N ); ++j )
494  {
496  ?( IsStrictlyUpper<MT4>::value ? B.upperBound(i,j) : B.lowerBound(i,j) )
497  :( B.begin(j) ) );
499  ?( IsStrictlyLower<MT4>::value ? B.lowerBound(i+4UL,j) : B.upperBound(i+4UL,j) )
500  :( B.end(j) ) );
501 
502  if( element == end ) {
503  reset( C(i ,j) );
504  reset( C(i+1UL,j) );
505  reset( C(i+2UL,j) );
506  reset( C(i+3UL,j) );
507  continue;
508  }
509 
510  C(i ,j) = A(i ,element->index()) * element->value();
511  C(i+1UL,j) = A(i+1UL,element->index()) * element->value();
512  C(i+2UL,j) = A(i+2UL,element->index()) * element->value();
513  C(i+3UL,j) = A(i+3UL,element->index()) * element->value();
514  ++element;
515  for( ; element!=end; ++element ) {
516  C(i ,j) += A(i ,element->index()) * element->value();
517  C(i+1UL,j) += A(i+1UL,element->index()) * element->value();
518  C(i+2UL,j) += A(i+2UL,element->index()) * element->value();
519  C(i+3UL,j) += A(i+3UL,element->index()) * element->value();
520  }
521  }
522  }
523 
524  for( ; (i+2UL) <= M; i+=2UL ) {
525  for( size_t j=( SYM || HERM || UPP ? i : 0UL ); j<( LOW ? i+2UL : N ); ++j )
526  {
528  ?( IsStrictlyUpper<MT4>::value ? B.upperBound(i,j) : B.lowerBound(i,j) )
529  :( B.begin(j) ) );
531  ?( IsStrictlyLower<MT4>::value ? B.lowerBound(i+2UL,j) : B.upperBound(i+2UL,j) )
532  :( B.end(j) ) );
533 
534  if( element == end ) {
535  reset( C(i ,j) );
536  reset( C(i+1UL,j) );
537  continue;
538  }
539 
540  C(i ,j) = A(i ,element->index()) * element->value();
541  C(i+1UL,j) = A(i+1UL,element->index()) * element->value();
542  ++element;
543  for( ; element!=end; ++element ) {
544  C(i ,j) += A(i ,element->index()) * element->value();
545  C(i+1UL,j) += A(i+1UL,element->index()) * element->value();
546  }
547  }
548  }
549 
550  for( ; i<M; ++i ) {
551  for( size_t j=( SYM || HERM || UPP ? i : 0UL ); j<( LOW ? i+1UL : N ); ++j )
552  {
554  ?( IsStrictlyUpper<MT4>::value ? B.upperBound(i,j) : B.lowerBound(i,j) )
555  :( B.begin(j) ) );
557  ?( IsStrictlyLower<MT4>::value ? B.lowerBound(i,j) : B.upperBound(i,j) )
558  :( B.end(j) ) );
559 
560  if( element == end ) {
561  reset( C(i,j) );
562  continue;
563  }
564 
565  C(i,j) = A(i,element->index()) * element->value();
566  ++element;
567  for( ; element!=end; ++element )
568  C(i,j) += A(i,element->index()) * element->value();
569  }
570  }
571  }
572 
573  if( SYM || HERM ) {
574  for( size_t i=1UL; i<M; ++i ) {
575  for( size_t j=0UL; j<i; ++j ) {
576  C(i,j) = HERM ? conj( C(j,i) ) : C(j,i);
577  }
578  }
579  }
580  else if( LOW && !UPP ) {
581  for( size_t j=1UL; j<N; ++j ) {
582  for( size_t i=0UL; i<j; ++i ) {
583  reset( C(i,j) );
584  }
585  }
586  }
587  else if( !LOW && UPP ) {
588  for( size_t i=1UL; i<M; ++i ) {
589  for( size_t j=0UL; j<i; ++j ) {
590  reset( C(i,j) );
591  }
592  }
593  }
594  }
596  //**********************************************************************************************
597 
598  //**Optimized assignment to dense matrices******************************************************
612  template< typename MT3 // Type of the left-hand side target matrix
613  , typename MT4 // Type of the left-hand side matrix operand
614  , typename MT5 > // Type of the right-hand side matrix operand
616  selectAssignKernel( MT3& C, const MT4& A, const MT5& B )
617  {
619 
620  const size_t M( A.rows() );
621  const size_t N( B.columns() );
622 
623  BLAZE_INTERNAL_ASSERT( !( SYM || HERM || LOW || UPP ) || M == N, "Broken invariant detected" );
624 
625  reset( C );
626 
627  {
628  size_t i( 0UL );
629 
630  for( ; (i+4UL) <= M; i+=4UL ) {
631  for( size_t j=( SYM || HERM || UPP ? i : 0UL ); j<( LOW ? i+4UL : N ); ++j )
632  {
634  ?( IsStrictlyUpper<MT4>::value ? B.upperBound(i,j) : B.lowerBound(i,j) )
635  :( B.begin(j) ) );
637  ?( IsStrictlyLower<MT4>::value ? B.lowerBound(i+4UL,j) : B.upperBound(i+4UL,j) )
638  :( B.end(j) ) );
639 
640  const size_t nonzeros( end - element );
641  const size_t kpos( nonzeros & size_t(-4) );
642  BLAZE_INTERNAL_ASSERT( ( nonzeros - ( nonzeros % 4UL ) ) == kpos, "Invalid end calculation" );
643 
644  for( size_t k=0UL; k<kpos; k+=4UL )
645  {
646  const size_t j1( element->index() );
647  const ET2 v1( element->value() );
648  ++element;
649  const size_t j2( element->index() );
650  const ET2 v2( element->value() );
651  ++element;
652  const size_t j3( element->index() );
653  const ET2 v3( element->value() );
654  ++element;
655  const size_t j4( element->index() );
656  const ET2 v4( element->value() );
657  ++element;
658 
659  BLAZE_INTERNAL_ASSERT( j1 < j2 && j2 < j3 && j3 < j4, "Invalid sparse matrix index detected" );
660 
661  C(i ,j) += A(i ,j1) * v1 + A(i ,j2) * v2 + A(i ,j3) * v3 + A(i ,j4) * v4;
662  C(i+1UL,j) += A(i+1UL,j1) * v1 + A(i+1UL,j2) * v2 + A(i+1UL,j3) * v3 + A(i+1UL,j4) * v4;
663  C(i+2UL,j) += A(i+2UL,j1) * v1 + A(i+2UL,j2) * v2 + A(i+2UL,j3) * v3 + A(i+2UL,j4) * v4;
664  C(i+3UL,j) += A(i+3UL,j1) * v1 + A(i+3UL,j2) * v2 + A(i+3UL,j3) * v3 + A(i+3UL,j4) * v4;
665  }
666 
667  for( ; element!=end; ++element )
668  {
669  const size_t j1( element->index() );
670  const ET2 v1( element->value() );
671 
672  C(i ,j) += A(i ,j1) * v1;
673  C(i+1UL,j) += A(i+1UL,j1) * v1;
674  C(i+2UL,j) += A(i+2UL,j1) * v1;
675  C(i+3UL,j) += A(i+3UL,j1) * v1;
676  }
677  }
678  }
679 
680  for( ; (i+2UL) <= M; i+=2UL ) {
681  for( size_t j=( SYM || HERM || UPP ? i : 0UL ); j<( LOW ? i+2UL : N ); ++j )
682  {
684  ?( IsStrictlyUpper<MT4>::value ? B.upperBound(i,j) : B.lowerBound(i,j) )
685  :( B.begin(j) ) );
687  ?( IsStrictlyLower<MT4>::value ? B.lowerBound(i+2UL,j) : B.upperBound(i+2UL,j) )
688  :( B.end(j) ) );
689 
690  const size_t nonzeros( end - element );
691  const size_t kpos( nonzeros & size_t(-4) );
692  BLAZE_INTERNAL_ASSERT( ( nonzeros - ( nonzeros % 4UL ) ) == kpos, "Invalid end calculation" );
693 
694  for( size_t k=0UL; k<kpos; k+=4UL )
695  {
696  const size_t j1( element->index() );
697  const ET2 v1( element->value() );
698  ++element;
699  const size_t j2( element->index() );
700  const ET2 v2( element->value() );
701  ++element;
702  const size_t j3( element->index() );
703  const ET2 v3( element->value() );
704  ++element;
705  const size_t j4( element->index() );
706  const ET2 v4( element->value() );
707  ++element;
708 
709  BLAZE_INTERNAL_ASSERT( j1 < j2 && j2 < j3 && j3 < j4, "Invalid sparse matrix index detected" );
710 
711  C(i ,j) += A(i ,j1) * v1 + A(i ,j2) * v2 + A(i ,j3) * v3 + A(i ,j4) * v4;
712  C(i+1UL,j) += A(i+1UL,j1) * v1 + A(i+1UL,j2) * v2 + A(i+1UL,j3) * v3 + A(i+1UL,j4) * v4;
713  }
714 
715  for( ; element!=end; ++element )
716  {
717  const size_t j1( element->index() );
718  const ET2 v1( element->value() );
719 
720  C(i ,j) += A(i ,j1) * v1;
721  C(i+1UL,j) += A(i+1UL,j1) * v1;
722  }
723  }
724  }
725 
726  for( ; i<M; ++i ) {
727  for( size_t j=( SYM || HERM || UPP ? i : 0UL ); j<( LOW ? i+1UL : N ); ++j )
728  {
730  ?( IsStrictlyUpper<MT4>::value ? B.upperBound(i,j) : B.lowerBound(i,j) )
731  :( B.begin(j) ) );
733  ?( IsStrictlyLower<MT4>::value ? B.lowerBound(i,j) : B.upperBound(i,j) )
734  :( B.end(j) ) );
735 
736  const size_t nonzeros( end - element );
737  const size_t kpos( nonzeros & size_t(-4) );
738  BLAZE_INTERNAL_ASSERT( ( nonzeros - ( nonzeros % 4UL ) ) == kpos, "Invalid end calculation" );
739 
740  for( size_t k=0UL; k<kpos; k+=4UL )
741  {
742  const size_t j1( element->index() );
743  const ET2 v1( element->value() );
744  ++element;
745  const size_t j2( element->index() );
746  const ET2 v2( element->value() );
747  ++element;
748  const size_t j3( element->index() );
749  const ET2 v3( element->value() );
750  ++element;
751  const size_t j4( element->index() );
752  const ET2 v4( element->value() );
753  ++element;
754 
755  BLAZE_INTERNAL_ASSERT( j1 < j2 && j2 < j3 && j3 < j4, "Invalid sparse matrix index detected" );
756 
757  C(i,j) += A(i,j1) * v1 + A(i,j2) * v2 + A(i,j3) * v3 + A(i,j4) * v4;
758  }
759 
760  for( ; element!=end; ++element )
761  {
762  const size_t j1( element->index() );
763  const ET2 v1( element->value() );
764 
765  C(i,j) += A(i,j1) * v1;
766  }
767  }
768  }
769  }
770 
771  if( SYM || HERM ) {
772  for( size_t i=1UL; i<M; ++i ) {
773  for( size_t j=0UL; j<i; ++j ) {
774  C(i,j) = HERM ? conj( C(j,i) ) : C(j,i);
775  }
776  }
777  }
778  }
780  //**********************************************************************************************
781 
782  //**Assignment to sparse matrices***************************************************************
795  template< typename MT // Type of the target sparse matrix
796  , bool SO > // Storage order of the target sparse matrix
798  assign( SparseMatrix<MT,SO>& lhs, const DMatTSMatMultExpr& rhs )
799  {
801 
803 
810 
811  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
812  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
813 
814  const ForwardFunctor fwd;
815 
816  const TmpType tmp( serial( rhs ) );
817  assign( ~lhs, fwd( tmp ) );
818  }
820  //**********************************************************************************************
821 
822  //**Restructuring assignment********************************************************************
837  template< typename MT // Type of the target matrix
838  , bool SO > // Storage order of the target matrix
840  assign( Matrix<MT,SO>& lhs, const DMatTSMatMultExpr& rhs )
841  {
843 
844  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
845  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
846 
847  const ForwardFunctor fwd;
848 
849  assign( ~lhs, fwd( trans( rhs.lhs_ ) * rhs.rhs_ ) );
850  }
852  //**********************************************************************************************
853 
854  //**Addition assignment to dense matrices*******************************************************
867  template< typename MT // Type of the target dense matrix
868  , bool SO > // Storage order of the target dense matrix
870  addAssign( DenseMatrix<MT,SO>& lhs, const DMatTSMatMultExpr& rhs )
871  {
873 
874  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
875  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
876 
877  LT A( serial( rhs.lhs_ ) ); // Evaluation of the left-hand side dense matrix operand
878  RT B( serial( rhs.rhs_ ) ); // Evaluation of the right-hand side sparse matrix operand
879 
880  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
881  BLAZE_INTERNAL_ASSERT( A.columns() == B.rows() , "Invalid matrix sizes" );
882  BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns(), "Invalid number of columns" );
883 
884  DMatTSMatMultExpr::selectAddAssignKernel( ~lhs, A, B );
885  }
887  //**********************************************************************************************
888 
889  //**Default addition assignment to dense matrices***********************************************
903  template< typename MT3 // Type of the left-hand side target matrix
904  , typename MT4 // Type of the left-hand side matrix operand
905  , typename MT5 > // Type of the right-hand side matrix operand
907  selectAddAssignKernel( MT3& C, const MT4& A, const MT5& B )
908  {
910 
911  const size_t M( A.rows() );
912  const size_t N( B.columns() );
913 
914  BLAZE_INTERNAL_ASSERT( !( LOW || UPP ) || M == N, "Broken invariant detected" );
915 
916  {
917  size_t i( 0UL );
918 
919  for( ; (i+4UL) <= M; i+=4UL ) {
920  for( size_t j=( UPP ? i : 0UL ); j<( LOW ? i+4UL : N ); ++j )
921  {
923  ?( IsStrictlyUpper<MT4>::value ? B.upperBound(i,j) : B.lowerBound(i,j) )
924  :( B.begin(j) ) );
926  ?( IsStrictlyLower<MT4>::value ? B.lowerBound(i+4UL,j) : B.upperBound(i+4UL,j) )
927  :( B.end(j) ) );
928 
929  for( ; element!=end; ++element ) {
930  C(i ,j) += A(i ,element->index()) * element->value();
931  C(i+1UL,j) += A(i+1UL,element->index()) * element->value();
932  C(i+2UL,j) += A(i+2UL,element->index()) * element->value();
933  C(i+3UL,j) += A(i+3UL,element->index()) * element->value();
934  }
935  }
936  }
937 
938  for( ; (i+2UL) <= M; i+=2UL ) {
939  for( size_t j=( UPP ? i : 0UL ); j<( LOW ? i+2UL : N ); ++j )
940  {
942  ?( IsStrictlyUpper<MT4>::value ? B.upperBound(i,j) : B.lowerBound(i,j) )
943  :( B.begin(j) ) );
945  ?( IsStrictlyLower<MT4>::value ? B.lowerBound(i+2UL,j) : B.upperBound(i+2UL,j) )
946  :( B.end(j) ) );
947 
948  for( ; element!=end; ++element ) {
949  C(i ,j) += A(i ,element->index()) * element->value();
950  C(i+1UL,j) += A(i+1UL,element->index()) * element->value();
951  }
952  }
953  }
954 
955  for( ; i<M; ++i ) {
956  for( size_t j=( UPP ? i : 0UL ); j<( LOW ? i+1UL : N ); ++j )
957  {
959  ?( IsStrictlyUpper<MT4>::value ? B.upperBound(i,j) : B.lowerBound(i,j) )
960  :( B.begin(j) ) );
962  ?( IsStrictlyLower<MT4>::value ? B.lowerBound(i,j) : B.upperBound(i,j) )
963  :( B.end(j) ) );
964 
965  for( ; element!=end; ++element )
966  C(i,j) += A(i,element->index()) * element->value();
967  }
968  }
969  }
970  }
972  //**********************************************************************************************
973 
974  //**Optimized addition assignment to dense matrices*********************************************
988  template< typename MT3 // Type of the left-hand side target matrix
989  , typename MT4 // Type of the left-hand side matrix operand
990  , typename MT5 > // Type of the right-hand side matrix operand
992  selectAddAssignKernel( MT3& C, const MT4& A, const MT5& B )
993  {
995 
996  const size_t M( A.rows() );
997  const size_t N( B.columns() );
998 
999  BLAZE_INTERNAL_ASSERT( !( LOW || UPP ) || M == N, "Broken invariant detected" );
1000 
1001  {
1002  size_t i( 0UL );
1003 
1004  for( ; (i+4UL) <= M; i+=4UL ) {
1005  for( size_t j=( UPP ? i : 0UL ); j<( LOW ? i+4UL : N ); ++j )
1006  {
1007  ConstIterator element( ( IsUpper<MT4>::value )
1008  ?( IsStrictlyUpper<MT4>::value ? B.upperBound(i,j) : B.lowerBound(i,j) )
1009  :( B.begin(j) ) );
1011  ?( IsStrictlyLower<MT4>::value ? B.lowerBound(i+4UL,j) : B.upperBound(i+4UL,j) )
1012  :( B.end(j) ) );
1013 
1014  const size_t nonzeros( end - element );
1015  const size_t kpos( nonzeros & size_t(-4) );
1016  BLAZE_INTERNAL_ASSERT( ( nonzeros - ( nonzeros % 4UL ) ) == kpos, "Invalid end calculation" );
1017 
1018  for( size_t k=0UL; k<kpos; k+=4UL )
1019  {
1020  const size_t j1( element->index() );
1021  const ET2 v1( element->value() );
1022  ++element;
1023  const size_t j2( element->index() );
1024  const ET2 v2( element->value() );
1025  ++element;
1026  const size_t j3( element->index() );
1027  const ET2 v3( element->value() );
1028  ++element;
1029  const size_t j4( element->index() );
1030  const ET2 v4( element->value() );
1031  ++element;
1032 
1033  BLAZE_INTERNAL_ASSERT( j1 < j2 && j2 < j3 && j3 < j4, "Invalid sparse matrix index detected" );
1034 
1035  C(i ,j) += A(i ,j1) * v1 + A(i ,j2) * v2 + A(i ,j3) * v3 + A(i ,j4) * v4;
1036  C(i+1UL,j) += A(i+1UL,j1) * v1 + A(i+1UL,j2) * v2 + A(i+1UL,j3) * v3 + A(i+1UL,j4) * v4;
1037  C(i+2UL,j) += A(i+2UL,j1) * v1 + A(i+2UL,j2) * v2 + A(i+2UL,j3) * v3 + A(i+2UL,j4) * v4;
1038  C(i+3UL,j) += A(i+3UL,j1) * v1 + A(i+3UL,j2) * v2 + A(i+3UL,j3) * v3 + A(i+3UL,j4) * v4;
1039  }
1040 
1041  for( ; element!=end; ++element )
1042  {
1043  const size_t j1( element->index() );
1044  const ET2 v1( element->value() );
1045 
1046  C(i ,j) += A(i ,j1) * v1;
1047  C(i+1UL,j) += A(i+1UL,j1) * v1;
1048  C(i+2UL,j) += A(i+2UL,j1) * v1;
1049  C(i+3UL,j) += A(i+3UL,j1) * v1;
1050  }
1051  }
1052  }
1053 
1054  for( ; (i+2UL) <= M; i+=2UL ) {
1055  for( size_t j=( UPP ? i : 0UL ); j<( LOW ? i+2UL : N ); ++j )
1056  {
1057  ConstIterator element( ( IsUpper<MT4>::value )
1058  ?( IsStrictlyUpper<MT4>::value ? B.upperBound(i,j) : B.lowerBound(i,j) )
1059  :( B.begin(j) ) );
1061  ?( IsStrictlyLower<MT4>::value ? B.lowerBound(i+2UL,j) : B.upperBound(i+2UL,j) )
1062  :( B.end(j) ) );
1063 
1064  const size_t nonzeros( end - element );
1065  const size_t kpos( nonzeros & size_t(-4) );
1066  BLAZE_INTERNAL_ASSERT( ( nonzeros - ( nonzeros % 4UL ) ) == kpos, "Invalid end calculation" );
1067 
1068  for( size_t k=0UL; k<kpos; k+=4UL )
1069  {
1070  const size_t j1( element->index() );
1071  const ET2 v1( element->value() );
1072  ++element;
1073  const size_t j2( element->index() );
1074  const ET2 v2( element->value() );
1075  ++element;
1076  const size_t j3( element->index() );
1077  const ET2 v3( element->value() );
1078  ++element;
1079  const size_t j4( element->index() );
1080  const ET2 v4( element->value() );
1081  ++element;
1082 
1083  BLAZE_INTERNAL_ASSERT( j1 < j2 && j2 < j3 && j3 < j4, "Invalid sparse matrix index detected" );
1084 
1085  C(i ,j) += A(i ,j1) * v1 + A(i ,j2) * v2 + A(i ,j3) * v3 + A(i ,j4) * v4;
1086  C(i+1UL,j) += A(i+1UL,j1) * v1 + A(i+1UL,j2) * v2 + A(i+1UL,j3) * v3 + A(i+1UL,j4) * v4;
1087  }
1088 
1089  for( ; element!=end; ++element )
1090  {
1091  const size_t j1( element->index() );
1092  const ET2 v1( element->value() );
1093 
1094  C(i ,j) += A(i ,j1) * v1;
1095  C(i+1UL,j) += A(i+1UL,j1) * v1;
1096  }
1097  }
1098  }
1099 
1100  for( ; i<M; ++i ) {
1101  for( size_t j=( UPP ? i : 0UL ); j<( LOW ? i+1UL : N ); ++j )
1102  {
1103  ConstIterator element( ( IsUpper<MT4>::value )
1104  ?( IsStrictlyUpper<MT4>::value ? B.upperBound(i,j) : B.lowerBound(i,j) )
1105  :( B.begin(j) ) );
1107  ?( IsStrictlyLower<MT4>::value ? B.lowerBound(i,j) : B.upperBound(i,j) )
1108  :( B.end(j) ) );
1109 
1110  const size_t nonzeros( end - element );
1111  const size_t kpos( nonzeros & size_t(-4) );
1112  BLAZE_INTERNAL_ASSERT( ( nonzeros - ( nonzeros % 4UL ) ) == kpos, "Invalid end calculation" );
1113 
1114  for( size_t k=0UL; k<kpos; k+=4UL )
1115  {
1116  const size_t j1( element->index() );
1117  const ET2 v1( element->value() );
1118  ++element;
1119  const size_t j2( element->index() );
1120  const ET2 v2( element->value() );
1121  ++element;
1122  const size_t j3( element->index() );
1123  const ET2 v3( element->value() );
1124  ++element;
1125  const size_t j4( element->index() );
1126  const ET2 v4( element->value() );
1127  ++element;
1128 
1129  BLAZE_INTERNAL_ASSERT( j1 < j2 && j2 < j3 && j3 < j4, "Invalid sparse matrix index detected" );
1130 
1131  C(i,j) += A(i,j1) * v1 + A(i,j2) * v2 + A(i,j3) * v3 + A(i,j4) * v4;
1132  }
1133 
1134  for( ; element!=end; ++element )
1135  {
1136  const size_t j1( element->index() );
1137  const ET2 v1( element->value() );
1138 
1139  C(i,j) += A(i,j1) * v1;
1140  }
1141  }
1142  }
1143  }
1144  }
1146  //**********************************************************************************************
1147 
1148  //**Restructuring addition assignment***********************************************************
1163  template< typename MT // Type of the target matrix
1164  , bool SO > // Storage order of the target matrix
1166  addAssign( Matrix<MT,SO>& lhs, const DMatTSMatMultExpr& rhs )
1167  {
1169 
1171 
1172  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
1173  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
1174 
1175  const ForwardFunctor fwd;
1176 
1177  addAssign( ~lhs, fwd( trans( rhs.lhs_ ) * rhs.rhs_ ) );
1178  }
1180  //**********************************************************************************************
1181 
1182  //**Addition assignment to sparse matrices******************************************************
1183  // No special implementation for the addition assignment to sparse matrices.
1184  //**********************************************************************************************
1185 
1186  //**Subtraction assignment to dense matrices****************************************************
1199  template< typename MT // Type of the target dense matrix
1200  , bool SO > // Storage order of the target dense matrix
1202  subAssign( DenseMatrix<MT,SO>& lhs, const DMatTSMatMultExpr& rhs )
1203  {
1205 
1206  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
1207  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
1208 
1209  LT A( serial( rhs.lhs_ ) ); // Evaluation of the left-hand side dense matrix operand
1210  RT B( serial( rhs.rhs_ ) ); // Evaluation of the right-hand side sparse matrix operand
1211 
1212  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
1213  BLAZE_INTERNAL_ASSERT( A.columns() == B.rows() , "Invalid matrix sizes" );
1214  BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns(), "Invalid number of columns" );
1215 
1216  DMatTSMatMultExpr::selectSubAssignKernel( ~lhs, A, B );
1217  }
1219  //**********************************************************************************************
1220 
1221  //**Default subtraction assignment to dense matrices********************************************
1235  template< typename MT3 // Type of the left-hand side target matrix
1236  , typename MT4 // Type of the left-hand side matrix operand
1237  , typename MT5 > // Type of the right-hand side matrix operand
1239  selectSubAssignKernel( MT3& C, const MT4& A, const MT5& B )
1240  {
1242 
1243  const size_t M( A.rows() );
1244  const size_t N( B.columns() );
1245 
1246  BLAZE_INTERNAL_ASSERT( !( LOW || UPP ) || M == N, "Broken invariant detected" );
1247 
1248  {
1249  size_t i( 0UL );
1250 
1251  for( ; (i+4UL) <= M; i+=4UL ) {
1252  for( size_t j=( UPP ? i : 0UL ); j<( LOW ? i+4UL : N ); ++j )
1253  {
1254  ConstIterator element( ( IsUpper<MT4>::value )
1255  ?( IsStrictlyUpper<MT4>::value ? B.upperBound(i,j) : B.lowerBound(i,j) )
1256  :( B.begin(j) ) );
1258  ?( IsStrictlyLower<MT4>::value ? B.lowerBound(i+4UL,j) : B.upperBound(i+4UL,j) )
1259  :( B.end(j) ) );
1260 
1261  for( ; element!=end; ++element ) {
1262  C(i ,j) -= A(i ,element->index()) * element->value();
1263  C(i+1UL,j) -= A(i+1UL,element->index()) * element->value();
1264  C(i+2UL,j) -= A(i+2UL,element->index()) * element->value();
1265  C(i+3UL,j) -= A(i+3UL,element->index()) * element->value();
1266  }
1267  }
1268  }
1269 
1270  for( ; (i+2UL) <= M; i+=2UL ) {
1271  for( size_t j=( UPP ? i : 0UL ); j<( LOW ? i+2UL : N ); ++j )
1272  {
1273  ConstIterator element( ( IsUpper<MT4>::value )
1274  ?( IsStrictlyUpper<MT4>::value ? B.upperBound(i,j) : B.lowerBound(i,j) )
1275  :( B.begin(j) ) );
1277  ?( IsStrictlyLower<MT4>::value ? B.lowerBound(i+2UL,j) : B.upperBound(i+2UL,j) )
1278  :( B.end(j) ) );
1279 
1280  for( ; element!=end; ++element ) {
1281  C(i ,j) -= A(i ,element->index()) * element->value();
1282  C(i+1UL,j) -= A(i+1UL,element->index()) * element->value();
1283  }
1284  }
1285  }
1286 
1287  for( ; i<M; ++i ) {
1288  for( size_t j=( UPP ? i : 0UL ); j<( LOW ? i+1UL : N ); ++j )
1289  {
1290  ConstIterator element( ( IsUpper<MT4>::value )
1291  ?( IsStrictlyUpper<MT4>::value ? B.upperBound(i,j) : B.lowerBound(i,j) )
1292  :( B.begin(j) ) );
1294  ?( IsStrictlyLower<MT4>::value ? B.lowerBound(i,j) : B.upperBound(i,j) )
1295  :( B.end(j) ) );
1296 
1297  for( ; element!=end; ++element )
1298  C(i,j) -= A(i,element->index()) * element->value();
1299  }
1300  }
1301  }
1302  }
1304  //**********************************************************************************************
1305 
1306  //**Optimized subtraction assignment to dense matrices******************************************
1320  template< typename MT3 // Type of the left-hand side target matrix
1321  , typename MT4 // Type of the left-hand side matrix operand
1322  , typename MT5 > // Type of the right-hand side matrix operand
1324  selectSubAssignKernel( MT3& C, const MT4& A, const MT5& B )
1325  {
1327 
1328  const size_t M( A.rows() );
1329  const size_t N( B.columns() );
1330 
1331  BLAZE_INTERNAL_ASSERT( !( LOW || UPP ) || M == N, "Broken invariant detected" );
1332 
1333  {
1334  size_t i( 0UL );
1335 
1336  for( ; (i+4UL) <= M; i+=4UL ) {
1337  for( size_t j=( UPP ? i : 0UL ); j<( LOW ? i+4UL : N ); ++j )
1338  {
1339  ConstIterator element( ( IsUpper<MT4>::value )
1340  ?( IsStrictlyUpper<MT4>::value ? B.upperBound(i,j) : B.lowerBound(i,j) )
1341  :( B.begin(j) ) );
1343  ?( IsStrictlyLower<MT4>::value ? B.lowerBound(i+4UL,j) : B.upperBound(i+4UL,j) )
1344  :( B.end(j) ) );
1345 
1346  const size_t nonzeros( end - element );
1347  const size_t kpos( nonzeros & size_t(-4) );
1348  BLAZE_INTERNAL_ASSERT( ( nonzeros - ( nonzeros % 4UL ) ) == kpos, "Invalid end calculation" );
1349 
1350  for( size_t k=0UL; k<kpos; k+=4UL )
1351  {
1352  const size_t j1( element->index() );
1353  const ET2 v1( element->value() );
1354  ++element;
1355  const size_t j2( element->index() );
1356  const ET2 v2( element->value() );
1357  ++element;
1358  const size_t j3( element->index() );
1359  const ET2 v3( element->value() );
1360  ++element;
1361  const size_t j4( element->index() );
1362  const ET2 v4( element->value() );
1363  ++element;
1364 
1365  BLAZE_INTERNAL_ASSERT( j1 < j2 && j2 < j3 && j3 < j4, "Invalid sparse matrix index detected" );
1366 
1367  C(i ,j) -= A(i ,j1) * v1 + A(i ,j2) * v2 + A(i ,j3) * v3 + A(i ,j4) * v4;
1368  C(i+1UL,j) -= A(i+1UL,j1) * v1 + A(i+1UL,j2) * v2 + A(i+1UL,j3) * v3 + A(i+1UL,j4) * v4;
1369  C(i+2UL,j) -= A(i+2UL,j1) * v1 + A(i+2UL,j2) * v2 + A(i+2UL,j3) * v3 + A(i+2UL,j4) * v4;
1370  C(i+3UL,j) -= A(i+3UL,j1) * v1 + A(i+3UL,j2) * v2 + A(i+3UL,j3) * v3 + A(i+3UL,j4) * v4;
1371  }
1372 
1373  for( ; element!=end; ++element )
1374  {
1375  const size_t j1( element->index() );
1376  const ET2 v1( element->value() );
1377 
1378  C(i ,j) -= A(i ,j1) * v1;
1379  C(i+1UL,j) -= A(i+1UL,j1) * v1;
1380  C(i+2UL,j) -= A(i+2UL,j1) * v1;
1381  C(i+3UL,j) -= A(i+3UL,j1) * v1;
1382  }
1383  }
1384  }
1385 
1386  for( ; (i+2UL) <= M; i+=2UL ) {
1387  for( size_t j=( UPP ? i : 0UL ); j<( LOW ? i+2UL : N ); ++j )
1388  {
1389  ConstIterator element( ( IsUpper<MT4>::value )
1390  ?( IsStrictlyUpper<MT4>::value ? B.upperBound(i,j) : B.lowerBound(i,j) )
1391  :( B.begin(j) ) );
1393  ?( IsStrictlyLower<MT4>::value ? B.lowerBound(i+2UL,j) : B.upperBound(i+2UL,j) )
1394  :( B.end(j) ) );
1395 
1396  const size_t nonzeros( end - element );
1397  const size_t kpos( nonzeros & size_t(-4) );
1398  BLAZE_INTERNAL_ASSERT( ( nonzeros - ( nonzeros % 4UL ) ) == kpos, "Invalid end calculation" );
1399 
1400  for( size_t k=0UL; k<kpos; k+=4UL )
1401  {
1402  const size_t j1( element->index() );
1403  const ET2 v1( element->value() );
1404  ++element;
1405  const size_t j2( element->index() );
1406  const ET2 v2( element->value() );
1407  ++element;
1408  const size_t j3( element->index() );
1409  const ET2 v3( element->value() );
1410  ++element;
1411  const size_t j4( element->index() );
1412  const ET2 v4( element->value() );
1413  ++element;
1414 
1415  BLAZE_INTERNAL_ASSERT( j1 < j2 && j2 < j3 && j3 < j4, "Invalid sparse matrix index detected" );
1416 
1417  C(i ,j) -= A(i ,j1) * v1 + A(i ,j2) * v2 + A(i ,j3) * v3 + A(i ,j4) * v4;
1418  C(i+1UL,j) -= A(i+1UL,j1) * v1 + A(i+1UL,j2) * v2 + A(i+1UL,j3) * v3 + A(i+1UL,j4) * v4;
1419  }
1420 
1421  for( ; element!=end; ++element )
1422  {
1423  const size_t j1( element->index() );
1424  const ET2 v1( element->value() );
1425 
1426  C(i ,j) -= A(i ,j1) * v1;
1427  C(i+1UL,j) -= A(i+1UL,j1) * v1;
1428  }
1429  }
1430  }
1431 
1432  for( ; i<M; ++i ) {
1433  for( size_t j=( UPP ? i : 0UL ); j<( LOW ? i+1UL : N ); ++j )
1434  {
1435  ConstIterator element( ( IsUpper<MT4>::value )
1436  ?( IsStrictlyUpper<MT4>::value ? B.upperBound(i,j) : B.lowerBound(i,j) )
1437  :( B.begin(j) ) );
1439  ?( IsStrictlyLower<MT4>::value ? B.lowerBound(i,j) : B.upperBound(i,j) )
1440  :( B.end(j) ) );
1441 
1442  const size_t nonzeros( end - element );
1443  const size_t kpos( nonzeros & size_t(-4) );
1444  BLAZE_INTERNAL_ASSERT( ( nonzeros - ( nonzeros % 4UL ) ) == kpos, "Invalid end calculation" );
1445 
1446  for( size_t k=0UL; k<kpos; k+=4UL )
1447  {
1448  const size_t j1( element->index() );
1449  const ET2 v1( element->value() );
1450  ++element;
1451  const size_t j2( element->index() );
1452  const ET2 v2( element->value() );
1453  ++element;
1454  const size_t j3( element->index() );
1455  const ET2 v3( element->value() );
1456  ++element;
1457  const size_t j4( element->index() );
1458  const ET2 v4( element->value() );
1459  ++element;
1460 
1461  BLAZE_INTERNAL_ASSERT( j1 < j2 && j2 < j3 && j3 < j4, "Invalid sparse matrix index detected" );
1462 
1463  C(i,j) -= A(i,j1) * v1 + A(i,j2) * v2 + A(i,j3) * v3 + A(i,j4) * v4;
1464  }
1465 
1466  for( ; element!=end; ++element )
1467  {
1468  const size_t j1( element->index() );
1469  const ET2 v1( element->value() );
1470 
1471  C(i,j) -= A(i,j1) * v1;
1472  }
1473  }
1474  }
1475  }
1476  }
1478  //**********************************************************************************************
1479 
1480  //**Restructuring subtraction assignment********************************************************
1495  template< typename MT // Type of the target matrix
1496  , bool SO > // Storage order of the target matrix
1498  subAssign( Matrix<MT,SO>& lhs, const DMatTSMatMultExpr& rhs )
1499  {
1501 
1503 
1504  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
1505  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
1506 
1507  const ForwardFunctor fwd;
1508 
1509  subAssign( ~lhs, fwd( trans( rhs.lhs_ ) * rhs.rhs_ ) );
1510  }
1512  //**********************************************************************************************
1513 
1514  //**Subtraction assignment to sparse matrices***************************************************
1515  // No special implementation for the subtraction assignment to sparse matrices.
1516  //**********************************************************************************************
1517 
1518  //**Schur product assignment to dense matrices**************************************************
1531  template< typename MT // Type of the target dense matrix
1532  , bool SO > // Storage order of the target dense matrix
1533  friend inline void schurAssign( DenseMatrix<MT,SO>& lhs, const DMatTSMatMultExpr& rhs )
1534  {
1536 
1540 
1541  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
1542  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
1543 
1544  const ResultType tmp( serial( rhs ) );
1545  schurAssign( ~lhs, tmp );
1546  }
1548  //**********************************************************************************************
1549 
1550  //**Schur product assignment to sparse matrices*************************************************
1551  // No special implementation for the Schur product assignment to sparse matrices.
1552  //**********************************************************************************************
1553 
1554  //**Multiplication assignment to dense matrices*************************************************
1555  // No special implementation for the multiplication assignment to dense matrices.
1556  //**********************************************************************************************
1557 
1558  //**Multiplication assignment to sparse matrices************************************************
1559  // No special implementation for the multiplication assignment to sparse matrices.
1560  //**********************************************************************************************
1561 
1562  //**SMP assignment to dense matrices************************************************************
1577  template< typename MT // Type of the target dense matrix
1578  , bool SO > // Storage order of the target dense matrix
1580  smpAssign( DenseMatrix<MT,SO>& lhs, const DMatTSMatMultExpr& rhs )
1581  {
1583 
1584  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
1585  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
1586 
1587  LT A( rhs.lhs_ ); // Evaluation of the left-hand side dense matrix operand
1588  RT B( rhs.rhs_ ); // Evaluation of the right-hand side sparse matrix operand
1589 
1590  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
1591  BLAZE_INTERNAL_ASSERT( A.columns() == B.rows() , "Invalid matrix sizes" );
1592  BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns(), "Invalid number of columns" );
1593 
1594  smpAssign( ~lhs, A * B );
1595  }
1597  //**********************************************************************************************
1598 
1599  //**SMP assignment to sparse matrices***********************************************************
1614  template< typename MT // Type of the target sparse matrix
1615  , bool SO > // Storage order of the target sparse matrix
1617  smpAssign( SparseMatrix<MT,SO>& lhs, const DMatTSMatMultExpr& rhs )
1618  {
1620 
1622 
1629 
1630  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
1631  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
1632 
1633  const ForwardFunctor fwd;
1634 
1635  const TmpType tmp( rhs );
1636  smpAssign( ~lhs, fwd( tmp ) );
1637  }
1639  //**********************************************************************************************
1640 
1641  //**Restructuring SMP assignment****************************************************************
1656  template< typename MT // Type of the target matrix
1657  , bool SO > // Storage order of the target matrix
1659  smpAssign( Matrix<MT,SO>& lhs, const DMatTSMatMultExpr& rhs )
1660  {
1662 
1664 
1665  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
1666  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
1667 
1668  const ForwardFunctor fwd;
1669 
1670  smpAssign( ~lhs, fwd( trans( rhs.lhs_ ) * rhs.rhs_ ) );
1671  }
1673  //**********************************************************************************************
1674 
1675  //**SMP addition assignment to dense matrices***************************************************
1691  template< typename MT // Type of the target dense matrix
1692  , bool SO > // Storage order of the target dense matrix
1695  {
1697 
1698  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
1699  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
1700 
1701  LT A( rhs.lhs_ ); // Evaluation of the left-hand side dense matrix operand
1702  RT B( rhs.rhs_ ); // Evaluation of the right-hand side sparse matrix operand
1703 
1704  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
1705  BLAZE_INTERNAL_ASSERT( A.columns() == B.rows() , "Invalid matrix sizes" );
1706  BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns(), "Invalid number of columns" );
1707 
1708  smpAddAssign( ~lhs, A * B );
1709  }
1711  //**********************************************************************************************
1712 
1713  //**Restructuring SMP addition assignment*******************************************************
1728  template< typename MT // Type of the target matrix
1729  , bool SO > // Storage order of the target matrix
1731  smpAddAssign( Matrix<MT,SO>& lhs, const DMatTSMatMultExpr& rhs )
1732  {
1734 
1736 
1737  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
1738  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
1739 
1740  const ForwardFunctor fwd;
1741 
1742  smpAddAssign( ~lhs, fwd( trans( rhs.lhs_ ) * rhs.rhs_ ) );
1743  }
1745  //**********************************************************************************************
1746 
1747  //**SMP addition assignment to sparse matrices**************************************************
1748  // No special implementation for the SMP addition assignment to sparse matrices.
1749  //**********************************************************************************************
1750 
1751  //**SMP subtraction assignment to dense matrices************************************************
1767  template< typename MT // Type of the target dense matrix
1768  , bool SO > // Storage order of the target dense matrix
1771  {
1773 
1774  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
1775  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
1776 
1777  LT A( rhs.lhs_ ); // Evaluation of the left-hand side dense matrix operand
1778  RT B( rhs.rhs_ ); // Evaluation of the right-hand side sparse matrix operand
1779 
1780  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
1781  BLAZE_INTERNAL_ASSERT( A.columns() == B.rows() , "Invalid matrix sizes" );
1782  BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns(), "Invalid number of columns" );
1783 
1784  smpSubAssign( ~lhs, A * B );
1785  }
1787  //**********************************************************************************************
1788 
1789  //**Restructuring SMP subtraction assignment****************************************************
1804  template< typename MT // Type of the target matrix
1805  , bool SO > // Storage order of the target matrix
1807  smpSubAssign( Matrix<MT,SO>& lhs, const DMatTSMatMultExpr& rhs )
1808  {
1810 
1812 
1813  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
1814  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
1815 
1816  const ForwardFunctor fwd;
1817 
1818  smpSubAssign( ~lhs, fwd( trans( rhs.lhs_ ) * rhs.rhs_ ) );
1819  }
1821  //**********************************************************************************************
1822 
1823  //**SMP subtraction assignment to sparse matrices***********************************************
1824  // No special implementation for the SMP subtraction assignment to sparse matrices.
1825  //**********************************************************************************************
1826 
1827  //**SMP Schur product assignment to dense matrices**********************************************
1840  template< typename MT // Type of the target dense matrix
1841  , bool SO > // Storage order of the target dense matrix
1842  friend inline void smpSchurAssign( DenseMatrix<MT,SO>& lhs, const DMatTSMatMultExpr& rhs )
1843  {
1845 
1849 
1850  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
1851  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
1852 
1853  const ResultType tmp( rhs );
1854  smpSchurAssign( ~lhs, tmp );
1855  }
1857  //**********************************************************************************************
1858 
1859  //**SMP Schur product assignment to sparse matrices*********************************************
1860  // No special implementation for the SMP Schur product assignment to sparse matrices.
1861  //**********************************************************************************************
1862 
1863  //**SMP multiplication assignment to dense matrices*********************************************
1864  // No special implementation for the SMP multiplication assignment to dense matrices.
1865  //**********************************************************************************************
1866 
1867  //**SMP multiplication assignment to sparse matrices********************************************
1868  // No special implementation for the SMP multiplication assignment to sparse matrices.
1869  //**********************************************************************************************
1870 
1871  //**Compile time checks*************************************************************************
1879  //**********************************************************************************************
1880 };
1881 //*************************************************************************************************
1882 
1883 
1884 
1885 
1886 //=================================================================================================
1887 //
1888 // GLOBAL BINARY ARITHMETIC OPERATORS
1889 //
1890 //=================================================================================================
1891 
1892 //*************************************************************************************************
1922 template< typename MT1 // Type of the left-hand side dense matrix
1923  , typename MT2 > // Type of the right-hand side sparse matrix
1924 inline decltype(auto)
1925  operator*( const DenseMatrix<MT1,false>& lhs, const SparseMatrix<MT2,true>& rhs )
1926 {
1928 
1929  if( (~lhs).columns() != (~rhs).rows() ) {
1930  BLAZE_THROW_INVALID_ARGUMENT( "Matrix sizes do not match" );
1931  }
1932 
1934  return ReturnType( ~lhs, ~rhs );
1935 }
1936 //*************************************************************************************************
1937 
1938 
1939 
1940 
1941 //=================================================================================================
1942 //
1943 // GLOBAL FUNCTIONS
1944 //
1945 //=================================================================================================
1946 
1947 //*************************************************************************************************
1971 template< typename MT1 // Type of the left-hand side dense matrix
1972  , typename MT2 // Type of the right-hand side sparse matrix
1973  , bool SF // Symmetry flag
1974  , bool HF // Hermitian flag
1975  , bool LF // Lower flag
1976  , bool UF > // Upper flag
1977 inline decltype(auto) declsym( const DMatTSMatMultExpr<MT1,MT2,SF,HF,LF,UF>& dm )
1978 {
1980 
1981  if( !isSquare( dm ) ) {
1982  BLAZE_THROW_INVALID_ARGUMENT( "Invalid symmetric matrix specification" );
1983  }
1984 
1986  return ReturnType( dm.leftOperand(), dm.rightOperand() );
1987 }
1989 //*************************************************************************************************
1990 
1991 
1992 //*************************************************************************************************
2016 template< typename MT1 // Type of the left-hand side dense matrix
2017  , typename MT2 // Type of the right-hand side sparse matrix
2018  , bool SF // Symmetry flag
2019  , bool HF // Hermitian flag
2020  , bool LF // Lower flag
2021  , bool UF > // Upper flag
2022 inline decltype(auto) declherm( const DMatTSMatMultExpr<MT1,MT2,SF,HF,LF,UF>& dm )
2023 {
2025 
2026  if( !isSquare( dm ) ) {
2027  BLAZE_THROW_INVALID_ARGUMENT( "Invalid Hermitian matrix specification" );
2028  }
2029 
2031  return ReturnType( dm.leftOperand(), dm.rightOperand() );
2032 }
2034 //*************************************************************************************************
2035 
2036 
2037 //*************************************************************************************************
2061 template< typename MT1 // Type of the left-hand side dense matrix
2062  , typename MT2 // Type of the right-hand side sparse matrix
2063  , bool SF // Symmetry flag
2064  , bool HF // Hermitian flag
2065  , bool LF // Lower flag
2066  , bool UF > // Upper flag
2067 inline decltype(auto) decllow( const DMatTSMatMultExpr<MT1,MT2,SF,HF,LF,UF>& dm )
2068 {
2070 
2071  if( !isSquare( dm ) ) {
2072  BLAZE_THROW_INVALID_ARGUMENT( "Invalid lower matrix specification" );
2073  }
2074 
2076  return ReturnType( dm.leftOperand(), dm.rightOperand() );
2077 }
2079 //*************************************************************************************************
2080 
2081 
2082 //*************************************************************************************************
2106 template< typename MT1 // Type of the left-hand side dense matrix
2107  , typename MT2 // Type of the right-hand side sparse matrix
2108  , bool SF // Symmetry flag
2109  , bool HF // Hermitian flag
2110  , bool LF // Lower flag
2111  , bool UF > // Upper flag
2112 inline decltype(auto) declupp( const DMatTSMatMultExpr<MT1,MT2,SF,HF,LF,UF>& dm )
2113 {
2115 
2116  if( !isSquare( dm ) ) {
2117  BLAZE_THROW_INVALID_ARGUMENT( "Invalid upper matrix specification" );
2118  }
2119 
2121  return ReturnType( dm.leftOperand(), dm.rightOperand() );
2122 }
2124 //*************************************************************************************************
2125 
2126 
2127 //*************************************************************************************************
2151 template< typename MT1 // Type of the left-hand side dense matrix
2152  , typename MT2 // Type of the right-hand side sparse matrix
2153  , bool SF // Symmetry flag
2154  , bool HF // Hermitian flag
2155  , bool LF // Lower flag
2156  , bool UF > // Upper flag
2157 inline decltype(auto) decldiag( const DMatTSMatMultExpr<MT1,MT2,SF,HF,LF,UF>& dm )
2158 {
2160 
2161  if( !isSquare( dm ) ) {
2162  BLAZE_THROW_INVALID_ARGUMENT( "Invalid diagonal matrix specification" );
2163  }
2164 
2166  return ReturnType( dm.leftOperand(), dm.rightOperand() );
2167 }
2169 //*************************************************************************************************
2170 
2171 
2172 
2173 
2174 //=================================================================================================
2175 //
2176 // SIZE SPECIALIZATIONS
2177 //
2178 //=================================================================================================
2179 
2180 //*************************************************************************************************
2182 template< typename MT1, typename MT2, bool SF, bool HF, bool LF, bool UF >
2183 struct Size< DMatTSMatMultExpr<MT1,MT2,SF,HF,LF,UF>, 0UL >
2184  : public Size<MT1,0UL>
2185 {};
2186 
2187 template< typename MT1, typename MT2, bool SF, bool HF, bool LF, bool UF >
2188 struct Size< DMatTSMatMultExpr<MT1,MT2,SF,HF,LF,UF>, 1UL >
2189  : public Size<MT2,1UL>
2190 {};
2192 //*************************************************************************************************
2193 
2194 
2195 
2196 
2197 //=================================================================================================
2198 //
2199 // ISALIGNED SPECIALIZATIONS
2200 //
2201 //=================================================================================================
2202 
2203 //*************************************************************************************************
2205 template< typename MT1, typename MT2, bool SF, bool HF, bool LF, bool UF >
2206 struct IsAligned< DMatTSMatMultExpr<MT1,MT2,SF,HF,LF,UF> >
2207  : public IsAligned<MT1>
2208 {};
2210 //*************************************************************************************************
2211 
2212 
2213 
2214 
2215 //=================================================================================================
2216 //
2217 // ISSYMMETRIC SPECIALIZATIONS
2218 //
2219 //=================================================================================================
2220 
2221 //*************************************************************************************************
2223 template< typename MT1, typename MT2, bool SF, bool HF, bool LF, bool UF >
2224 struct IsSymmetric< DMatTSMatMultExpr<MT1,MT2,SF,HF,LF,UF> >
2225  : public Or< Bool<SF>
2226  , And< Bool<HF>
2227  , IsBuiltin< ElementType_< DMatTSMatMultExpr<MT1,MT2,false,true,false,false> > > >
2228  , And< Bool<LF>, Bool<UF> > >
2229 {};
2231 //*************************************************************************************************
2232 
2233 
2234 
2235 
2236 //=================================================================================================
2237 //
2238 // ISHERMITIAN SPECIALIZATIONS
2239 //
2240 //=================================================================================================
2241 
2242 //*************************************************************************************************
2244 template< typename MT1, typename MT2, bool SF, bool LF, bool UF >
2245 struct IsHermitian< DMatTSMatMultExpr<MT1,MT2,SF,true,LF,UF> >
2246  : public TrueType
2247 {};
2249 //*************************************************************************************************
2250 
2251 
2252 
2253 
2254 //=================================================================================================
2255 //
2256 // ISLOWER SPECIALIZATIONS
2257 //
2258 //=================================================================================================
2259 
2260 //*************************************************************************************************
2262 template< typename MT1, typename MT2, bool SF, bool HF, bool LF, bool UF >
2263 struct IsLower< DMatTSMatMultExpr<MT1,MT2,SF,HF,LF,UF> >
2264  : public Or< Bool<LF>
2265  , And< IsLower<MT1>, IsLower<MT2> >
2266  , And< Or< Bool<SF>, Bool<HF> >
2267  , IsUpper<MT1>, IsUpper<MT2> > >
2268 {};
2270 //*************************************************************************************************
2271 
2272 
2273 
2274 
2275 //=================================================================================================
2276 //
2277 // ISUNILOWER SPECIALIZATIONS
2278 //
2279 //=================================================================================================
2280 
2281 //*************************************************************************************************
2283 template< typename MT1, typename MT2, bool SF, bool HF, bool LF, bool UF >
2284 struct IsUniLower< DMatTSMatMultExpr<MT1,MT2,SF,HF,LF,UF> >
2285  : public Or< And< IsUniLower<MT1>, IsUniLower<MT2> >
2286  , And< Or< Bool<SF>, Bool<HF> >
2287  , IsUniUpper<MT1>, IsUniUpper<MT2> > >
2288 {};
2290 //*************************************************************************************************
2291 
2292 
2293 
2294 
2295 //=================================================================================================
2296 //
2297 // ISSTRICTLYLOWER SPECIALIZATIONS
2298 //
2299 //=================================================================================================
2300 
2301 //*************************************************************************************************
2303 template< typename MT1, typename MT2, bool SF, bool HF, bool LF, bool UF >
2304 struct IsStrictlyLower< DMatTSMatMultExpr<MT1,MT2,SF,HF,LF,UF> >
2305  : public Or< And< IsStrictlyLower<MT1>, IsLower<MT2> >
2306  , And< IsStrictlyLower<MT2>, IsLower<MT1> >
2307  , And< Or< Bool<SF>, Bool<HF> >
2308  , Or< And< IsStrictlyUpper<MT1>, IsUpper<MT2> >
2309  , And< IsStrictlyUpper<MT2>, IsUpper<MT1> > > > >
2310 {};
2312 //*************************************************************************************************
2313 
2314 
2315 
2316 
2317 //=================================================================================================
2318 //
2319 // ISUPPER SPECIALIZATIONS
2320 //
2321 //=================================================================================================
2322 
2323 //*************************************************************************************************
2325 template< typename MT1, typename MT2, bool SF, bool HF, bool LF, bool UF >
2326 struct IsUpper< DMatTSMatMultExpr<MT1,MT2,SF,HF,LF,UF> >
2327  : public Or< Bool<UF>
2328  , And< IsUpper<MT1>, IsUpper<MT2> >
2329  , And< Or< Bool<SF>, Bool<HF> >
2330  , IsLower<MT1>, IsLower<MT2> > >
2331 {};
2333 //*************************************************************************************************
2334 
2335 
2336 
2337 
2338 //=================================================================================================
2339 //
2340 // ISUNIUPPER SPECIALIZATIONS
2341 //
2342 //=================================================================================================
2343 
2344 //*************************************************************************************************
2346 template< typename MT1, typename MT2, bool SF, bool HF, bool LF, bool UF >
2347 struct IsUniUpper< DMatTSMatMultExpr<MT1,MT2,SF,HF,LF,UF> >
2348  : public Or< And< IsUniUpper<MT1>, IsUniUpper<MT2> >
2349  , And< Or< Bool<SF>, Bool<HF> >
2350  , IsUniLower<MT1>, IsUniLower<MT2> > >
2351 {};
2353 //*************************************************************************************************
2354 
2355 
2356 
2357 
2358 //=================================================================================================
2359 //
2360 // ISSTRICTLYUPPER SPECIALIZATIONS
2361 //
2362 //=================================================================================================
2363 
2364 //*************************************************************************************************
2366 template< typename MT1, typename MT2, bool SF, bool HF, bool LF, bool UF >
2367 struct IsStrictlyUpper< DMatTSMatMultExpr<MT1,MT2,SF,HF,LF,UF> >
2368  : public Or< And< IsStrictlyUpper<MT1>, IsUpper<MT2> >
2369  , And< IsStrictlyUpper<MT2>, IsUpper<MT1> >
2370  , And< Or< Bool<SF>, Bool<HF> >
2371  , Or< And< IsStrictlyLower<MT1>, IsLower<MT2> >
2372  , And< IsStrictlyLower<MT2>, IsLower<MT1> > > > >
2373 {};
2375 //*************************************************************************************************
2376 
2377 } // namespace blaze
2378 
2379 #endif
CompositeType_< MT1 > CT1
Composite type of the left-hand side dense matrix expression.
Definition: DMatTSMatMultExpr.h:132
decltype(auto) subvector(Vector< VT, TF > &, RSAs...)
Creating a view on a specific subvector of the given vector.
Definition: Subvector.h:329
#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:130
Header file for auxiliary alias declarations.
decltype(auto) column(Matrix< MT, SO > &matrix, RCAs... args)
Creating a view on a specific column of the given matrix.
Definition: Column.h:131
Headerfile for the generic min algorithm.
Header file for the blaze::checked and blaze::unchecked instances.
Compile time check whether the given type is a computational expression template.This type trait clas...
Definition: IsComputation.h:71
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 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:86
Header file for basic type definitions.
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:348
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:364
void reset(const DiagonalProxy< MT > &proxy)
Resetting the represented element to the default initial values.
Definition: DiagonalProxy.h:588
DMatTSMatMultExpr(const MT1 &lhs, const MT2 &rhs) noexcept
Constructor for the DMatTSMatMultExpr class.
Definition: DMatTSMatMultExpr.h:258
LeftOperand leftOperand() const noexcept
Returns the left-hand side dense matrix operand.
Definition: DMatTSMatMultExpr.h:358
constexpr Unchecked unchecked
Global Unchecked instance.The blaze::unchecked instance is an optional token for the creation of view...
Definition: Check.h:138
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:1903
Compile time check for lower triangular matrices.This type trait tests whether or not the given templ...
Definition: IsLower.h:87
ReturnType at(size_t i, size_t j) const
Checked access to the matrix elements.
Definition: DMatTSMatMultExpr.h:322
bool canSMPAssign() const noexcept
Returns whether the expression can be used in SMP assignments.
Definition: DMatTSMatMultExpr.h:412
decltype(auto) declupp(const DenseMatrix< MT, SO > &dm)
Declares the given dense matrix expression dm as upper.
Definition: DMatDeclUppExpr.h:1026
typename MultTrait< T1, T2 >::Type MultTrait_
Auxiliary alias declaration for the MultTrait class template.The MultTrait_ alias declaration provide...
Definition: MultTrait.h:291
Header file for the Computation base class.
OppositeType_< ResultType > OppositeType
Result type with opposite storage order for expression template evaluations.
Definition: DMatTSMatMultExpr.h:224
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:87
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:237
System settings for performance optimizations.
ResultType_< MT2 > RT2
Result type of the right-hand side sparse matrix expression.
Definition: DMatTSMatMultExpr.h:129
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:1950
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:80
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
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:71
RightOperand rhs_
Right-hand side sparse matrix of the multiplication expression.
Definition: DMatTSMatMultExpr.h:420
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.
Flag for upper matrices.
Definition: DMatTSMatMultExpr.h:152
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:58
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:392
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:380
#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.
const Element * ConstIterator
Iterator over constant elements.
Definition: CompressedMatrix.h:3085
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:368
decltype(auto) decllow(const DenseMatrix< MT, SO > &dm)
Declares the given dense matrix expression dm as lower.
Definition: DMatDeclLowExpr.h:1026
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:89
Flag for symmetric matrices.
Definition: DMatTSMatMultExpr.h:149
Generic wrapper for the null function.
Definition: Noop.h:59
Header file for the IsTriangular type trait.
Constraints on the storage order of matrix types.
Flag for Hermitian matrices.
Definition: DMatTSMatMultExpr.h:150
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:338
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:430
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:402
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:107
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.
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
decltype(auto) row(Matrix< MT, SO > &, RRAs...)
Creating a view on a specific row of the given matrix.
Definition: Row.h:131
LeftOperand lhs_
Left-hand side dense matrix of the multiplication expression.
Definition: DMatTSMatMultExpr.h:419
Header file for the reset shim.
ElementType_< RT2 > ET2
Element type of the right-hand side sparse matrix expression.
Definition: DMatTSMatMultExpr.h:131
#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
decltype(auto) declsym(const DenseMatrix< MT, SO > &dm)
Declares the given dense matrix expression dm as symmetric.
Definition: DMatDeclSymExpr.h:1028
Compile time check for Hermitian matrices.This type trait tests whether or not the given template par...
Definition: IsHermitian.h:85
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:122
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:816
Header file for the Noop functor.
CompositeType_< MT2 > CT2
Composite type of the right-hand side sparse matrix expression.
Definition: DMatTSMatMultExpr.h:133
Flag for lower matrices.
Definition: DMatTSMatMultExpr.h:151
#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:234
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:227
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:3080
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:789
const ResultType CompositeType
Data type for composite expression templates.
Definition: DMatTSMatMultExpr.h:228
decltype(auto) declherm(const DenseMatrix< MT, SO > &dm)
Declares the given dense matrix expression dm as Hermitian.
Definition: DMatDeclHermExpr.h:1028
ResultType_< MT1 > RT1
Result type of the left-hand side dense matrix expression.
Definition: DMatTSMatMultExpr.h:128
Header file for the IsComputation type trait class.
MultTrait_< RT1, RT2 > ResultType
Result type for expression template evaluations.
Definition: DMatTSMatMultExpr.h:223
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
Compile time logical &#39;or&#39; evaluation.The Or alias declaration performs at compile time a logical &#39;or&#39;...
Definition: Or.h:76
Compile time evaluation of the size of vectors and matrices.The Size type trait evaluates the size of...
Definition: Size.h:80
TransposeType_< ResultType > TransposeType
Transpose type for expression template evaluations.
Definition: DMatTSMatMultExpr.h:225
Generic wrapper for the decldiag() function.
Definition: DeclDiag.h:58
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:240
BLAZE_ALWAYS_INLINE bool isSquare(const Matrix< MT, SO > &matrix) noexcept
Checks if the given matrix is a square matrix.
Definition: Matrix.h:908
Header file for the IsResizable type trait.
ElementType_< ResultType > ElementType
Resulting element type.
Definition: DMatTSMatMultExpr.h:226
Header file for the Size type trait.
Header file for the thresholds for matrix/vector and matrix/matrix multiplications.
#define BLAZE_INTERNAL_ASSERT(expr, msg)
Run time assertion macro for internal checks.In case of an invalid run time expression, the program execution is terminated. The BLAZE_INTERNAL_ASSERT macro can be disabled by setting the BLAZE_USER_ASSERTION flag to zero or by defining NDEBUG during the compilation.
Definition: Assert.h:101
Header file for the 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:273
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:231