SMatTDMatMultExpr.h
Go to the documentation of this file.
1 //=================================================================================================
33 //=================================================================================================
34 
35 #ifndef _BLAZE_MATH_EXPRESSIONS_SMATTDMATMULTEXPR_H_
36 #define _BLAZE_MATH_EXPRESSIONS_SMATTDMATMULTEXPR_H_
37 
38 
39 //*************************************************************************************************
40 // Includes
41 //*************************************************************************************************
42 
43 #include <blaze/math/Aliases.h>
51 #include <blaze/math/Exception.h>
63 #include <blaze/math/shims/Reset.h>
84 #include <blaze/util/Assert.h>
85 #include <blaze/util/DisableIf.h>
86 #include <blaze/util/EnableIf.h>
89 #include <blaze/util/InvalidType.h>
90 #include <blaze/util/mpl/And.h>
91 #include <blaze/util/mpl/Bool.h>
92 #include <blaze/util/mpl/If.h>
93 #include <blaze/util/mpl/Or.h>
94 #include <blaze/util/TrueType.h>
95 #include <blaze/util/Types.h>
98 
99 
100 namespace blaze {
101 
102 //=================================================================================================
103 //
104 // CLASS SMATTDMATMULTEXPR
105 //
106 //=================================================================================================
107 
108 //*************************************************************************************************
115 template< typename MT1 // Type of the left-hand side sparse matrix
116  , typename MT2 // Type of the right-hand side dense matrix
117  , bool SF // Symmetry flag
118  , bool HF // Hermitian flag
119  , bool LF // Lower flag
120  , bool UF > // Upper flag
121 class SMatTDMatMultExpr
122  : public MatMatMultExpr< DenseMatrix< SMatTDMatMultExpr<MT1,MT2,SF,HF,LF,UF>, false > >
123  , private Computation
124 {
125  private:
126  //**Type definitions****************************************************************************
133  //**********************************************************************************************
134 
135  //**********************************************************************************************
137  enum : bool { evaluateLeft = IsComputation<MT1>::value || RequiresEvaluation<MT1>::value };
138  //**********************************************************************************************
139 
140  //**********************************************************************************************
142  enum : bool { evaluateRight = IsComputation<MT2>::value || RequiresEvaluation<MT2>::value };
143  //**********************************************************************************************
144 
145  //**********************************************************************************************
147  enum : bool {
148  SYM = ( SF && !( HF || LF || UF ) ),
149  HERM = ( HF && !( LF || UF ) ),
150  LOW = ( LF || ( ( SF || HF ) && UF ) ),
151  UPP = ( UF || ( ( SF || HF ) && LF ) )
152  };
153  //**********************************************************************************************
154 
155  //**********************************************************************************************
157 
162  template< typename T1, typename T2, typename T3 >
163  struct CanExploitSymmetry {
164  enum : bool { value = IsSymmetric<T3>::value };
165  };
167  //**********************************************************************************************
168 
169  //**********************************************************************************************
171 
175  template< typename T1, typename T2, typename T3 >
176  struct IsEvaluationRequired {
177  enum : bool { value = ( evaluateLeft || evaluateRight ) &&
178  CanExploitSymmetry<T1,T2,T3>::value };
179  };
181  //**********************************************************************************************
182 
183  //**********************************************************************************************
185 
188  template< typename T1, typename T2, typename T3 >
189  struct UseOptimizedKernel {
190  enum : bool { value = useOptimizedKernels &&
192  !IsResizable< ElementType_<T1> >::value &&
194  };
196  //**********************************************************************************************
197 
198  //**********************************************************************************************
200 
203  using ForwardFunctor = IfTrue_< HERM
204  , DeclHerm
205  , IfTrue_< SYM
206  , DeclSym
207  , IfTrue_< LOW
208  , IfTrue_< UPP
209  , DeclDiag
210  , DeclLow >
211  , IfTrue_< UPP
212  , DeclUpp
213  , Noop > > > >;
215  //**********************************************************************************************
216 
217  public:
218  //**Type definitions****************************************************************************
221 
226  using ReturnType = const ElementType;
227  using CompositeType = const ResultType;
228 
230  using LeftOperand = If_< IsExpression<MT1>, const MT1, const MT1& >;
231 
233  using RightOperand = If_< IsExpression<MT2>, const MT2, const MT2& >;
234 
237 
240  //**********************************************************************************************
241 
242  //**Compilation flags***************************************************************************
244  enum : bool { simdEnabled = false };
245 
247  enum : bool { smpAssignable = !evaluateLeft && MT1::smpAssignable &&
248  !evaluateRight && MT2::smpAssignable };
249  //**********************************************************************************************
250 
251  //**Constructor*********************************************************************************
257  explicit inline SMatTDMatMultExpr( const MT1& lhs, const MT2& rhs ) noexcept
258  : lhs_( lhs ) // Left-hand side sparse matrix of the multiplication expression
259  , rhs_( rhs ) // Right-hand side dense matrix of the multiplication expression
260  {
261  BLAZE_INTERNAL_ASSERT( lhs.columns() == rhs.rows(), "Invalid matrix sizes" );
262  }
263  //**********************************************************************************************
264 
265  //**Access operator*****************************************************************************
272  inline ReturnType operator()( size_t i, size_t j ) const {
273  BLAZE_INTERNAL_ASSERT( i < lhs_.rows() , "Invalid row access index" );
274  BLAZE_INTERNAL_ASSERT( j < rhs_.columns(), "Invalid column access index" );
275 
276  if( IsDiagonal<MT1>::value ) {
277  return lhs_(i,i) * rhs_(i,j);
278  }
279  else if( IsDiagonal<MT2>::value ) {
280  return lhs_(i,j) * rhs_(j,j);
281  }
283  const size_t begin( ( IsUpper<MT1>::value )
284  ?( ( IsLower<MT2>::value )
285  ?( max( ( IsStrictlyUpper<MT1>::value ? i+1UL : i )
286  , ( IsStrictlyLower<MT2>::value ? j+1UL : j ) ) )
287  :( IsStrictlyUpper<MT1>::value ? i+1UL : i ) )
288  :( ( IsLower<MT2>::value )
289  ?( IsStrictlyLower<MT2>::value ? j+1UL : j )
290  :( 0UL ) ) );
291  const size_t end( ( IsLower<MT1>::value )
292  ?( ( IsUpper<MT2>::value )
293  ?( min( ( IsStrictlyLower<MT1>::value ? i : i+1UL )
294  , ( IsStrictlyUpper<MT2>::value ? j : j+1UL ) ) )
295  :( IsStrictlyLower<MT1>::value ? i : i+1UL ) )
296  :( ( IsUpper<MT2>::value )
297  ?( IsStrictlyUpper<MT2>::value ? j : j+1UL )
298  :( lhs_.columns() ) ) );
299 
300  if( begin >= end ) return ElementType();
301 
302  const size_t n( end - begin );
303 
304  return subvector( row( lhs_, i ), begin, n ) * subvector( column( rhs_, j ), begin, n );
305  }
306  else {
307  return row( lhs_, i ) * column( rhs_, j );
308  }
309  }
310  //**********************************************************************************************
311 
312  //**At function*********************************************************************************
320  inline ReturnType at( size_t i, size_t j ) const {
321  if( i >= lhs_.rows() ) {
322  BLAZE_THROW_OUT_OF_RANGE( "Invalid row access index" );
323  }
324  if( j >= rhs_.columns() ) {
325  BLAZE_THROW_OUT_OF_RANGE( "Invalid column access index" );
326  }
327  return (*this)(i,j);
328  }
329  //**********************************************************************************************
330 
331  //**Rows function*******************************************************************************
336  inline size_t rows() const noexcept {
337  return lhs_.rows();
338  }
339  //**********************************************************************************************
340 
341  //**Columns function****************************************************************************
346  inline size_t columns() const noexcept {
347  return rhs_.columns();
348  }
349  //**********************************************************************************************
350 
351  //**Left operand access*************************************************************************
356  inline LeftOperand leftOperand() const noexcept {
357  return lhs_;
358  }
359  //**********************************************************************************************
360 
361  //**Right operand access************************************************************************
366  inline RightOperand rightOperand() const noexcept {
367  return rhs_;
368  }
369  //**********************************************************************************************
370 
371  //**********************************************************************************************
377  template< typename T >
378  inline bool canAlias( const T* alias ) const noexcept {
379  return ( lhs_.isAliased( alias ) || rhs_.isAliased( alias ) );
380  }
381  //**********************************************************************************************
382 
383  //**********************************************************************************************
389  template< typename T >
390  inline bool isAliased( const T* alias ) const noexcept {
391  return ( lhs_.isAliased( alias ) || rhs_.isAliased( alias ) );
392  }
393  //**********************************************************************************************
394 
395  //**********************************************************************************************
400  inline bool isAligned() const noexcept {
401  return rhs_.isAligned();
402  }
403  //**********************************************************************************************
404 
405  //**********************************************************************************************
410  inline bool canSMPAssign() const noexcept {
411  return ( rows() * columns() >= SMP_SMATTDMATMULT_THRESHOLD ) && !IsDiagonal<MT2>::value;
412  }
413  //**********************************************************************************************
414 
415  private:
416  //**Member variables****************************************************************************
419  //**********************************************************************************************
420 
421  //**Assignment to dense matrices****************************************************************
434  template< typename MT // Type of the target dense matrix
435  , bool SO > // Storage order of the target dense matrix
437  assign( DenseMatrix<MT,SO>& lhs, const SMatTDMatMultExpr& rhs )
438  {
440 
441  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
442  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
443 
444  LT A( serial( rhs.lhs_ ) ); // Evaluation of the left-hand side sparse matrix operand
445  RT B( serial( rhs.rhs_ ) ); // Evaluation of the right-hand side dense matrix operand
446 
447  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
448  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
449  BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
450  BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
451  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
452  BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
453 
454  SMatTDMatMultExpr::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  {
487  size_t j( 0UL );
488 
489  for( ; (j+4UL) <= N; j+=4UL ) {
490  for( size_t i=( SYM || HERM || LOW ? j : 0UL ); i<( UPP ? j+4UL : M ); ++i )
491  {
493  ?( IsStrictlyUpper<MT5>::value ? A.lowerBound(i,j+4UL) : A.upperBound(i,j+4UL) )
494  :( A.end(i) ) );
496  ?( IsStrictlyLower<MT5>::value ? A.upperBound(i,j) : A.lowerBound(i,j) )
497  :( A.begin(i) ) );
498 
499  if( element == end ) {
500  reset( C(i,j ) );
501  reset( C(i,j+1UL) );
502  reset( C(i,j+2UL) );
503  reset( C(i,j+3UL) );
504  continue;
505  }
506 
507  C(i,j ) = element->value() * B(element->index(),j );
508  C(i,j+1UL) = element->value() * B(element->index(),j+1UL);
509  C(i,j+2UL) = element->value() * B(element->index(),j+2UL);
510  C(i,j+3UL) = element->value() * B(element->index(),j+3UL);
511  ++element;
512  for( ; element!=end; ++element ) {
513  C(i,j ) += element->value() * B(element->index(),j );
514  C(i,j+1UL) += element->value() * B(element->index(),j+1UL);
515  C(i,j+2UL) += element->value() * B(element->index(),j+2UL);
516  C(i,j+3UL) += element->value() * B(element->index(),j+3UL);
517  }
518  }
519  }
520 
521  for( ; (j+2UL) <= N; j+=2UL ) {
522  for( size_t i=( SYM || HERM || LOW ? j : 0UL ); i<( UPP ? j+2UL : M ); ++i )
523  {
525  ?( IsStrictlyUpper<MT5>::value ? A.lowerBound(i,j+2UL) : A.upperBound(i,j+2UL) )
526  :( A.end(i) ) );
528  ?( IsStrictlyLower<MT5>::value ? A.upperBound(i,j) : A.lowerBound(i,j) )
529  :( A.begin(i) ) );
530 
531  if( element == end ) {
532  reset( C(i,j ) );
533  reset( C(i,j+1UL) );
534  continue;
535  }
536 
537  C(i,j ) = element->value() * B(element->index(),j );
538  C(i,j+1UL) = element->value() * B(element->index(),j+1UL);
539  ++element;
540  for( ; element!=end; ++element ) {
541  C(i,j ) += element->value() * B(element->index(),j );
542  C(i,j+1UL) += element->value() * B(element->index(),j+1UL);
543  }
544  }
545  }
546 
547  for( ; j<N; ++j ) {
548  for( size_t i=( SYM || HERM || LOW ? j : 0UL ); i<( UPP ? j+1UL : M ); ++i )
549  {
551  ?( IsStrictlyUpper<MT5>::value ? A.lowerBound(i,j) : A.upperBound(i,j) )
552  :( A.end(i) ) );
554  ?( IsStrictlyLower<MT5>::value ? A.upperBound(i,j) : A.lowerBound(i,j) )
555  :( A.begin(i) ) );
556 
557  if( element == end ) {
558  reset( C(i,j) );
559  continue;
560  }
561 
562  C(i,j) = element->value() * B(element->index(),j);
563  ++element;
564  for( ; element!=end; ++element ) {
565  C(i,j) += element->value() * B(element->index(),j);
566  }
567  }
568  }
569  }
570 
571  if( SYM || HERM ) {
572  for( size_t j=1UL; j<N; ++j ) {
573  for( size_t i=0UL; i<j; ++i ) {
574  C(i,j) = HERM ? conj( C(j,i) ) : C(j,i);
575  }
576  }
577  }
578  else if( LOW && !UPP ) {
579  for( size_t j=1UL; j<N; ++j ) {
580  for( size_t i=0UL; i<j; ++i ) {
581  reset( C(i,j) );
582  }
583  }
584  }
585  else if( !LOW && UPP ) {
586  for( size_t i=1UL; i<M; ++i ) {
587  for( size_t j=0UL; j<i; ++j ) {
588  reset( C(i,j) );
589  }
590  }
591  }
592  }
594  //**********************************************************************************************
595 
596  //**Optimized assignment to dense matrices******************************************************
610  template< typename MT3 // Type of the left-hand side target matrix
611  , typename MT4 // Type of the left-hand side matrix operand
612  , typename MT5 > // Type of the right-hand side matrix operand
614  selectAssignKernel( MT3& C, const MT4& A, const MT5& B )
615  {
617 
618  const size_t M( A.rows() );
619  const size_t N( B.columns() );
620 
621  BLAZE_INTERNAL_ASSERT( !( SYM || HERM || LOW || UPP ) || M == N, "Broken invariant detected" );
622 
623  reset( C );
624 
625  {
626  size_t j( 0UL );
627 
628  for( ; (j+4UL) <= N; j+=4UL ) {
629  for( size_t i=( SYM || HERM || LOW ? j : 0UL ); i<( UPP ? j+4UL : M ); ++i )
630  {
632  ?( IsStrictlyUpper<MT5>::value ? A.lowerBound(i,j+4UL) : A.upperBound(i,j+4UL) )
633  :( A.end(i) ) );
635  ?( IsStrictlyLower<MT5>::value ? A.upperBound(i,j) : A.lowerBound(i,j) )
636  :( A.begin(i) ) );
637 
638  const size_t nonzeros( end - element );
639  const size_t kpos( nonzeros & size_t(-4) );
640  BLAZE_INTERNAL_ASSERT( ( nonzeros - ( nonzeros % 4UL ) ) == kpos, "Invalid end calculation" );
641 
642  for( size_t k=0UL; k<kpos; k+=4UL )
643  {
644  const size_t i1( element->index() );
645  const ET1 v1( element->value() );
646  ++element;
647  const size_t i2( element->index() );
648  const ET1 v2( element->value() );
649  ++element;
650  const size_t i3( element->index() );
651  const ET1 v3( element->value() );
652  ++element;
653  const size_t i4( element->index() );
654  const ET1 v4( element->value() );
655  ++element;
656 
657  BLAZE_INTERNAL_ASSERT( i1 < i2 && i2 < i3 && i3 < i4, "Invalid sparse matrix index detected" );
658 
659  C(i,j ) += v1 * B(i1,j ) + v2 * B(i2,j ) + v3 * B(i3,j ) + v4 * B(i4,j );
660  C(i,j+1UL) += v1 * B(i1,j+1UL) + v2 * B(i2,j+1UL) + v3 * B(i3,j+1UL) + v4 * B(i4,j+1UL);
661  C(i,j+2UL) += v1 * B(i1,j+2UL) + v2 * B(i2,j+2UL) + v3 * B(i3,j+2UL) + v4 * B(i4,j+2UL);
662  C(i,j+3UL) += v1 * B(i1,j+3UL) + v2 * B(i2,j+3UL) + v3 * B(i3,j+3UL) + v4 * B(i4,j+3UL);
663  }
664 
665  for( ; element!=end; ++element )
666  {
667  const size_t i1( element->index() );
668  const ET1 v1( element->value() );
669 
670  C(i,j ) += v1 * B(i1,j );
671  C(i,j+1UL) += v1 * B(i1,j+1UL);
672  C(i,j+2UL) += v1 * B(i1,j+2UL);
673  C(i,j+3UL) += v1 * B(i1,j+3UL);
674  }
675  }
676  }
677 
678  for( ; (j+2UL) <= N; j+=2UL ) {
679  for( size_t i=( SYM || HERM || LOW ? j : 0UL ); i<( UPP ? j+2UL : M ); ++i )
680  {
682  ?( IsStrictlyUpper<MT5>::value ? A.lowerBound(i,j+2UL) : A.upperBound(i,j+2UL) )
683  :( A.end(i) ) );
685  ?( IsStrictlyLower<MT5>::value ? A.upperBound(i,j) : A.lowerBound(i,j) )
686  :( A.begin(i) ) );
687 
688  const size_t nonzeros( end - element );
689  const size_t kpos( nonzeros & size_t(-4) );
690  BLAZE_INTERNAL_ASSERT( ( nonzeros - ( nonzeros % 4UL ) ) == kpos, "Invalid end calculation" );
691 
692  for( size_t k=0UL; k<kpos; k+=4UL )
693  {
694  const size_t i1( element->index() );
695  const ET1 v1( element->value() );
696  ++element;
697  const size_t i2( element->index() );
698  const ET1 v2( element->value() );
699  ++element;
700  const size_t i3( element->index() );
701  const ET1 v3( element->value() );
702  ++element;
703  const size_t i4( element->index() );
704  const ET1 v4( element->value() );
705  ++element;
706 
707  BLAZE_INTERNAL_ASSERT( i1 < i2 && i2 < i3 && i3 < i4, "Invalid sparse matrix index detected" );
708 
709  C(i,j ) += v1 * B(i1,j ) + v2 * B(i2,j ) + v3 * B(i3,j ) + v4 * B(i4,j );
710  C(i,j+1UL) += v1 * B(i1,j+1UL) + v2 * B(i2,j+1UL) + v3 * B(i3,j+1UL) + v4 * B(i4,j+1UL);
711  }
712 
713  for( ; element!=end; ++element )
714  {
715  const size_t i1( element->index() );
716  const ET1 v1( element->value() );
717 
718  C(i,j ) += v1 * B(i1,j );
719  C(i,j+1UL) += v1 * B(i1,j+1UL);
720  }
721  }
722  }
723 
724  for( ; j<N; ++j ) {
725  for( size_t i=( SYM || HERM || LOW ? j : 0UL ); i<( UPP ? j+1UL : M ); ++i )
726  {
728  ?( IsStrictlyUpper<MT5>::value ? A.lowerBound(i,j) : A.upperBound(i,j) )
729  :( A.end(i) ) );
731  ?( IsStrictlyLower<MT5>::value ? A.upperBound(i,j) : A.lowerBound(i,j) )
732  :( A.begin(i) ) );
733 
734  const size_t nonzeros( end - element );
735  const size_t kpos( nonzeros & size_t(-4) );
736  BLAZE_INTERNAL_ASSERT( ( nonzeros - ( nonzeros % 4UL ) ) == kpos, "Invalid end calculation" );
737 
738  for( size_t k=0UL; k<kpos; k+=4UL )
739  {
740  const size_t i1( element->index() );
741  const ET1 v1( element->value() );
742  ++element;
743  const size_t i2( element->index() );
744  const ET1 v2( element->value() );
745  ++element;
746  const size_t i3( element->index() );
747  const ET1 v3( element->value() );
748  ++element;
749  const size_t i4( element->index() );
750  const ET1 v4( element->value() );
751  ++element;
752 
753  BLAZE_INTERNAL_ASSERT( i1 < i2 && i2 < i3 && i3 < i4, "Invalid sparse matrix index detected" );
754 
755  C(i,j) += v1 * B(i1,j) + v2 * B(i2,j) + v3 * B(i3,j) + v4 * B(i4,j);
756  }
757 
758  for( ; element!=end; ++element )
759  {
760  const size_t i1( element->index() );
761  const ET1 v1( element->value() );
762 
763  C(i,j) += v1 * B(i1,j);
764  }
765  }
766  }
767  }
768 
769  if( SYM || HERM ) {
770  for( size_t j=1UL; j<N; ++j ) {
771  for( size_t i=0UL; i<j; ++i ) {
772  C(i,j) = HERM ? conj( C(j,i) ) : C(j,i);
773  }
774  }
775  }
776  }
778  //**********************************************************************************************
779 
780  //**Assignment to sparse matrices***************************************************************
793  template< typename MT // Type of the target sparse matrix
794  , bool SO > // Storage order of the target sparse matrix
796  assign( SparseMatrix<MT,SO>& lhs, const SMatTDMatMultExpr& rhs )
797  {
799 
801 
808 
809  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
810  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
811 
812  const ForwardFunctor fwd;
813 
814  const TmpType tmp( serial( rhs ) );
815  assign( ~lhs, fwd( tmp ) );
816  }
818  //**********************************************************************************************
819 
820  //**Restructuring assignment********************************************************************
835  template< typename MT // Type of the target matrix
836  , bool SO > // Storage order of the target matrix
838  assign( Matrix<MT,SO>& lhs, const SMatTDMatMultExpr& rhs )
839  {
841 
842  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
843  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
844 
845  const ForwardFunctor fwd;
846 
847  assign( ~lhs, fwd( rhs.lhs_ * trans( rhs.rhs_ ) ) );
848  }
850  //**********************************************************************************************
851 
852  //**Addition assignment to dense matrices*******************************************************
865  template< typename MT // Type of the target dense matrix
866  , bool SO > // Storage order of the target dense matrix
868  addAssign( DenseMatrix<MT,SO>& lhs, const SMatTDMatMultExpr& rhs )
869  {
871 
872  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
873  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
874 
875  LT A( serial( rhs.lhs_ ) ); // Evaluation of the left-hand side sparse matrix operand
876  RT B( serial( rhs.rhs_ ) ); // Evaluation of the right-hand side dense matrix operand
877 
878  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
879  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
880  BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
881  BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
882  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
883  BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
884 
885  SMatTDMatMultExpr::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 j( 0UL );
919 
920  for( ; (j+4UL) <= N; j+=4UL ) {
921  for( size_t i=( LOW ? j : 0UL ); i<( UPP ? j+4UL : M ); ++i )
922  {
924  ?( IsStrictlyUpper<MT5>::value ? A.lowerBound(i,j+4UL) : A.upperBound(i,j+4UL) )
925  :( A.end(i) ) );
927  ?( IsStrictlyLower<MT5>::value ? A.upperBound(i,j) : A.lowerBound(i,j) )
928  :( A.begin(i) ) );
929 
930  for( ; element!=end; ++element ) {
931  C(i,j ) += element->value() * B(element->index(),j );
932  C(i,j+1UL) += element->value() * B(element->index(),j+1UL);
933  C(i,j+2UL) += element->value() * B(element->index(),j+2UL);
934  C(i,j+3UL) += element->value() * B(element->index(),j+3UL);
935  }
936  }
937  }
938 
939  for( ; (j+2UL) <= N; j+=2UL ) {
940  for( size_t i=( LOW ? j : 0UL ); i<( UPP ? j+2UL : M ); ++i )
941  {
943  ?( IsStrictlyUpper<MT5>::value ? A.lowerBound(i,j+2UL) : A.upperBound(i,j+2UL) )
944  :( A.end(i) ) );
946  ?( IsStrictlyLower<MT5>::value ? A.upperBound(i,j) : A.lowerBound(i,j) )
947  :( A.begin(i) ) );
948 
949  for( ; element!=end; ++element ) {
950  C(i,j ) += element->value() * B(element->index(),j );
951  C(i,j+1UL) += element->value() * B(element->index(),j+1UL);
952  }
953  }
954  }
955 
956  for( ; j<N; ++j ) {
957  for( size_t i=( LOW ? j : 0UL ); i<( UPP ? j+1UL : M ); ++i )
958  {
960  ?( IsStrictlyUpper<MT5>::value ? A.lowerBound(i,j) : A.upperBound(i,j) )
961  :( A.end(i) ) );
963  ?( IsStrictlyLower<MT5>::value ? A.upperBound(i,j) : A.lowerBound(i,j) )
964  :( A.begin(i) ) );
965 
966  for( ; element!=end; ++element ) {
967  C(i,j) += element->value() * B(element->index(),j);
968  }
969  }
970  }
971  }
972  }
974  //**********************************************************************************************
975 
976  //**Optimized addition assignment to dense matrices*********************************************
990  template< typename MT3 // Type of the left-hand side target matrix
991  , typename MT4 // Type of the left-hand side matrix operand
992  , typename MT5 > // Type of the right-hand side matrix operand
994  selectAddAssignKernel( MT3& C, const MT4& A, const MT5& B )
995  {
997 
998  const size_t M( A.rows() );
999  const size_t N( B.columns() );
1000 
1001  BLAZE_INTERNAL_ASSERT( !( LOW || UPP ) || M == N, "Broken invariant detected" );
1002 
1003  {
1004  size_t j( 0UL );
1005 
1006  for( ; (j+4UL) <= N; j+=4UL ) {
1007  for( size_t i=( LOW ? j : 0UL ); i<( UPP ? j+4UL : M ); ++i )
1008  {
1010  ?( IsStrictlyUpper<MT5>::value ? A.lowerBound(i,j+4UL) : A.upperBound(i,j+4UL) )
1011  :( A.end(i) ) );
1012  ConstIterator element( ( IsLower<MT5>::value )
1013  ?( IsStrictlyLower<MT5>::value ? A.upperBound(i,j) : A.lowerBound(i,j) )
1014  :( A.begin(i) ) );
1015 
1016  const size_t nonzeros( end - element );
1017  const size_t kpos( nonzeros & size_t(-4) );
1018  BLAZE_INTERNAL_ASSERT( ( nonzeros - ( nonzeros % 4UL ) ) == kpos, "Invalid end calculation" );
1019 
1020  for( size_t k=0UL; k<kpos; k+=4UL )
1021  {
1022  const size_t i1( element->index() );
1023  const ET1 v1( element->value() );
1024  ++element;
1025  const size_t i2( element->index() );
1026  const ET1 v2( element->value() );
1027  ++element;
1028  const size_t i3( element->index() );
1029  const ET1 v3( element->value() );
1030  ++element;
1031  const size_t i4( element->index() );
1032  const ET1 v4( element->value() );
1033  ++element;
1034 
1035  BLAZE_INTERNAL_ASSERT( i1 < i2 && i2 < i3 && i3 < i4, "Invalid sparse matrix index detected" );
1036 
1037  C(i,j ) += v1 * B(i1,j ) + v2 * B(i2,j ) + v3 * B(i3,j ) + v4 * B(i4,j );
1038  C(i,j+1UL) += v1 * B(i1,j+1UL) + v2 * B(i2,j+1UL) + v3 * B(i3,j+1UL) + v4 * B(i4,j+1UL);
1039  C(i,j+2UL) += v1 * B(i1,j+2UL) + v2 * B(i2,j+2UL) + v3 * B(i3,j+2UL) + v4 * B(i4,j+2UL);
1040  C(i,j+3UL) += v1 * B(i1,j+3UL) + v2 * B(i2,j+3UL) + v3 * B(i3,j+3UL) + v4 * B(i4,j+3UL);
1041  }
1042 
1043  for( ; element!=end; ++element )
1044  {
1045  const size_t i1( element->index() );
1046  const ET1 v1( element->value() );
1047 
1048  C(i,j ) += v1 * B(i1,j );
1049  C(i,j+1UL) += v1 * B(i1,j+1UL);
1050  C(i,j+2UL) += v1 * B(i1,j+2UL);
1051  C(i,j+3UL) += v1 * B(i1,j+3UL);
1052  }
1053  }
1054  }
1055 
1056  for( ; (j+2UL) <= N; j+=2UL ) {
1057  for( size_t i=( LOW ? j : 0UL ); i<( UPP ? j+2UL : M ); ++i )
1058  {
1060  ?( IsStrictlyUpper<MT5>::value ? A.lowerBound(i,j+2UL) : A.upperBound(i,j+2UL) )
1061  :( A.end(i) ) );
1062  ConstIterator element( ( IsLower<MT5>::value )
1063  ?( IsStrictlyLower<MT5>::value ? A.upperBound(i,j) : A.lowerBound(i,j) )
1064  :( A.begin(i) ) );
1065 
1066  const size_t nonzeros( end - element );
1067  const size_t kpos( nonzeros & size_t(-4) );
1068  BLAZE_INTERNAL_ASSERT( ( nonzeros - ( nonzeros % 4UL ) ) == kpos, "Invalid end calculation" );
1069 
1070  for( size_t k=0UL; k<kpos; k+=4UL )
1071  {
1072  const size_t i1( element->index() );
1073  const ET1 v1( element->value() );
1074  ++element;
1075  const size_t i2( element->index() );
1076  const ET1 v2( element->value() );
1077  ++element;
1078  const size_t i3( element->index() );
1079  const ET1 v3( element->value() );
1080  ++element;
1081  const size_t i4( element->index() );
1082  const ET1 v4( element->value() );
1083  ++element;
1084 
1085  BLAZE_INTERNAL_ASSERT( i1 < i2 && i2 < i3 && i3 < i4, "Invalid sparse matrix index detected" );
1086 
1087  C(i,j ) += v1 * B(i1,j ) + v2 * B(i2,j ) + v3 * B(i3,j ) + v4 * B(i4,j );
1088  C(i,j+1UL) += v1 * B(i1,j+1UL) + v2 * B(i2,j+1UL) + v3 * B(i3,j+1UL) + v4 * B(i4,j+1UL);
1089  }
1090 
1091  for( ; element!=end; ++element )
1092  {
1093  const size_t i1( element->index() );
1094  const ET1 v1( element->value() );
1095 
1096  C(i,j ) += v1 * B(i1,j );
1097  C(i,j+1UL) += v1 * B(i1,j+1UL);
1098  }
1099  }
1100  }
1101 
1102  for( ; j<N; ++j ) {
1103  for( size_t i=( LOW ? j : 0UL ); i<( UPP ? j+1UL : M ); ++i )
1104  {
1106  ?( IsStrictlyUpper<MT5>::value ? A.lowerBound(i,j) : A.upperBound(i,j) )
1107  :( A.end(i) ) );
1108  ConstIterator element( ( IsLower<MT5>::value )
1109  ?( IsStrictlyLower<MT5>::value ? A.upperBound(i,j) : A.lowerBound(i,j) )
1110  :( A.begin(i) ) );
1111 
1112  const size_t nonzeros( end - element );
1113  const size_t kpos( nonzeros & size_t(-4) );
1114  BLAZE_INTERNAL_ASSERT( ( nonzeros - ( nonzeros % 4UL ) ) == kpos, "Invalid end calculation" );
1115 
1116  for( size_t k=0UL; k<kpos; k+=4UL )
1117  {
1118  const size_t i1( element->index() );
1119  const ET1 v1( element->value() );
1120  ++element;
1121  const size_t i2( element->index() );
1122  const ET1 v2( element->value() );
1123  ++element;
1124  const size_t i3( element->index() );
1125  const ET1 v3( element->value() );
1126  ++element;
1127  const size_t i4( element->index() );
1128  const ET1 v4( element->value() );
1129  ++element;
1130 
1131  BLAZE_INTERNAL_ASSERT( i1 < i2 && i2 < i3 && i3 < i4, "Invalid sparse matrix index detected" );
1132 
1133  C(i,j) += v1 * B(i1,j) + v2 * B(i2,j) + v3 * B(i3,j) + v4 * B(i4,j);
1134  }
1135 
1136  for( ; element!=end; ++element )
1137  {
1138  const size_t i1( element->index() );
1139  const ET1 v1( element->value() );
1140 
1141  C(i,j) += v1 * B(i1,j);
1142  }
1143  }
1144  }
1145  }
1146  }
1148  //**********************************************************************************************
1149 
1150  //**Restructuring addition assignment***********************************************************
1165  template< typename MT // Type of the target matrix
1166  , bool SO > // Storage order of the target matrix
1168  addAssign( Matrix<MT,SO>& lhs, const SMatTDMatMultExpr& rhs )
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( rhs.lhs_ * trans( 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 SMatTDMatMultExpr& 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 sparse matrix operand
1210  RT B( serial( rhs.rhs_ ) ); // Evaluation of the right-hand side dense matrix operand
1211 
1212  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
1213  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
1214  BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
1215  BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
1216  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
1217  BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
1218 
1219  SMatTDMatMultExpr::selectSubAssignKernel( ~lhs, A, B );
1220  }
1222  //**********************************************************************************************
1223 
1224  //**Default subtraction assignment to dense matrices********************************************
1238  template< typename MT3 // Type of the left-hand side target matrix
1239  , typename MT4 // Type of the left-hand side matrix operand
1240  , typename MT5 > // Type of the right-hand side matrix operand
1242  selectSubAssignKernel( MT3& C, const MT4& A, const MT5& B )
1243  {
1245 
1246  const size_t M( A.rows() );
1247  const size_t N( B.columns() );
1248 
1249  BLAZE_INTERNAL_ASSERT( !( LOW || UPP ) || M == N, "Broken invariant detected" );
1250 
1251  {
1252  size_t j( 0UL );
1253 
1254  for( ; (j+4UL) <= N; j+=4UL ) {
1255  for( size_t i=( LOW ? j : 0UL ); i<( UPP ? j+4UL : M ); ++i )
1256  {
1258  ?( IsStrictlyUpper<MT5>::value ? A.lowerBound(i,j+4UL) : A.upperBound(i,j+4UL) )
1259  :( A.end(i) ) );
1260  ConstIterator element( ( IsLower<MT5>::value )
1261  ?( IsStrictlyLower<MT5>::value ? A.upperBound(i,j) : A.lowerBound(i,j) )
1262  :( A.begin(i) ) );
1263 
1264  for( ; element!=end; ++element ) {
1265  C(i,j ) -= element->value() * B(element->index(),j );
1266  C(i,j+1UL) -= element->value() * B(element->index(),j+1UL);
1267  C(i,j+2UL) -= element->value() * B(element->index(),j+2UL);
1268  C(i,j+3UL) -= element->value() * B(element->index(),j+3UL);
1269  }
1270  }
1271  }
1272 
1273  for( ; (j+2UL) <= N; j+=2UL ) {
1274  for( size_t i=( LOW ? j : 0UL ); i<( UPP ? j+2UL : M ); ++i )
1275  {
1277  ?( IsStrictlyUpper<MT5>::value ? A.lowerBound(i,j+2UL) : A.upperBound(i,j+2UL) )
1278  :( A.end(i) ) );
1279  ConstIterator element( ( IsLower<MT5>::value )
1280  ?( IsStrictlyLower<MT5>::value ? A.upperBound(i,j) : A.lowerBound(i,j) )
1281  :( A.begin(i) ) );
1282 
1283  for( ; element!=end; ++element ) {
1284  C(i,j ) -= element->value() * B(element->index(),j );
1285  C(i,j+1UL) -= element->value() * B(element->index(),j+1UL);
1286  }
1287  }
1288  }
1289 
1290  for( ; j<N; ++j ) {
1291  for( size_t i=( LOW ? j : 0UL ); i<( UPP ? j+1UL : M ); ++i )
1292  {
1294  ?( IsStrictlyUpper<MT5>::value ? A.lowerBound(i,j) : A.upperBound(i,j) )
1295  :( A.end(i) ) );
1296  ConstIterator element( ( IsLower<MT5>::value )
1297  ?( IsStrictlyLower<MT5>::value ? A.upperBound(i,j) : A.lowerBound(i,j) )
1298  :( A.begin(i) ) );
1299 
1300  for( ; element!=end; ++element ) {
1301  C(i,j) -= element->value() * B(element->index(),j);
1302  }
1303  }
1304  }
1305  }
1306  }
1308  //**********************************************************************************************
1309 
1310  //**Optimized subtraction assignment to dense matrices******************************************
1324  template< typename MT3 // Type of the left-hand side target matrix
1325  , typename MT4 // Type of the left-hand side matrix operand
1326  , typename MT5 > // Type of the right-hand side matrix operand
1328  selectSubAssignKernel( MT3& C, const MT4& A, const MT5& B )
1329  {
1331 
1332  const size_t M( A.rows() );
1333  const size_t N( B.columns() );
1334 
1335  BLAZE_INTERNAL_ASSERT( !( LOW || UPP ) || M == N, "Broken invariant detected" );
1336 
1337  {
1338  size_t j( 0UL );
1339 
1340  for( ; (j+4UL) <= N; j+=4UL ) {
1341  for( size_t i=( LOW ? j : 0UL ); i<( UPP ? j+4UL : M ); ++i )
1342  {
1344  ?( IsStrictlyUpper<MT5>::value ? A.lowerBound(i,j+4UL) : A.upperBound(i,j+4UL) )
1345  :( A.end(i) ) );
1346  ConstIterator element( ( IsLower<MT5>::value )
1347  ?( IsStrictlyLower<MT5>::value ? A.upperBound(i,j) : A.lowerBound(i,j) )
1348  :( A.begin(i) ) );
1349 
1350  const size_t nonzeros( end - element );
1351  const size_t kpos( nonzeros & size_t(-4) );
1352  BLAZE_INTERNAL_ASSERT( ( nonzeros - ( nonzeros % 4UL ) ) == kpos, "Invalid end calculation" );
1353 
1354  for( size_t k=0UL; k<kpos; k+=4UL )
1355  {
1356  const size_t i1( element->index() );
1357  const ET1 v1( element->value() );
1358  ++element;
1359  const size_t i2( element->index() );
1360  const ET1 v2( element->value() );
1361  ++element;
1362  const size_t i3( element->index() );
1363  const ET1 v3( element->value() );
1364  ++element;
1365  const size_t i4( element->index() );
1366  const ET1 v4( element->value() );
1367  ++element;
1368 
1369  BLAZE_INTERNAL_ASSERT( i1 < i2 && i2 < i3 && i3 < i4, "Invalid sparse matrix index detected" );
1370 
1371  C(i,j ) -= v1 * B(i1,j ) + v2 * B(i2,j ) + v3 * B(i3,j ) + v4 * B(i4,j );
1372  C(i,j+1UL) -= v1 * B(i1,j+1UL) + v2 * B(i2,j+1UL) + v3 * B(i3,j+1UL) + v4 * B(i4,j+1UL);
1373  C(i,j+2UL) -= v1 * B(i1,j+2UL) + v2 * B(i2,j+2UL) + v3 * B(i3,j+2UL) + v4 * B(i4,j+2UL);
1374  C(i,j+3UL) -= v1 * B(i1,j+3UL) + v2 * B(i2,j+3UL) + v3 * B(i3,j+3UL) + v4 * B(i4,j+3UL);
1375  }
1376 
1377  for( ; element!=end; ++element )
1378  {
1379  const size_t i1( element->index() );
1380  const ET1 v1( element->value() );
1381 
1382  C(i,j ) -= v1 * B(i1,j );
1383  C(i,j+1UL) -= v1 * B(i1,j+1UL);
1384  C(i,j+2UL) -= v1 * B(i1,j+2UL);
1385  C(i,j+3UL) -= v1 * B(i1,j+3UL);
1386  }
1387  }
1388  }
1389 
1390  for( ; (j+2UL) <= N; j+=2UL ) {
1391  for( size_t i=( LOW ? j : 0UL ); i<( UPP ? j+2UL : M ); ++i )
1392  {
1394  ?( IsStrictlyUpper<MT5>::value ? A.lowerBound(i,j+2UL) : A.upperBound(i,j+2UL) )
1395  :( A.end(i) ) );
1396  ConstIterator element( ( IsLower<MT5>::value )
1397  ?( IsStrictlyLower<MT5>::value ? A.upperBound(i,j) : A.lowerBound(i,j) )
1398  :( A.begin(i) ) );
1399 
1400  const size_t nonzeros( end - element );
1401  const size_t kpos( nonzeros & size_t(-4) );
1402  BLAZE_INTERNAL_ASSERT( ( nonzeros - ( nonzeros % 4UL ) ) == kpos, "Invalid end calculation" );
1403 
1404  for( size_t k=0UL; k<kpos; k+=4UL )
1405  {
1406  const size_t i1( element->index() );
1407  const ET1 v1( element->value() );
1408  ++element;
1409  const size_t i2( element->index() );
1410  const ET1 v2( element->value() );
1411  ++element;
1412  const size_t i3( element->index() );
1413  const ET1 v3( element->value() );
1414  ++element;
1415  const size_t i4( element->index() );
1416  const ET1 v4( element->value() );
1417  ++element;
1418 
1419  BLAZE_INTERNAL_ASSERT( i1 < i2 && i2 < i3 && i3 < i4, "Invalid sparse matrix index detected" );
1420 
1421  C(i,j ) -= v1 * B(i1,j ) + v2 * B(i2,j ) + v3 * B(i3,j ) + v4 * B(i4,j );
1422  C(i,j+1UL) -= v1 * B(i1,j+1UL) + v2 * B(i2,j+1UL) + v3 * B(i3,j+1UL) + v4 * B(i4,j+1UL);
1423  }
1424 
1425  for( ; element!=end; ++element )
1426  {
1427  const size_t i1( element->index() );
1428  const ET1 v1( element->value() );
1429 
1430  C(i,j ) -= v1 * B(i1,j );
1431  C(i,j+1UL) -= v1 * B(i1,j+1UL);
1432  }
1433  }
1434  }
1435 
1436  for( ; j<N; ++j ) {
1437  for( size_t i=( LOW ? j : 0UL ); i<( UPP ? j+1UL : M ); ++i )
1438  {
1440  ?( IsStrictlyUpper<MT5>::value ? A.lowerBound(i,j) : A.upperBound(i,j) )
1441  :( A.end(i) ) );
1442  ConstIterator element( ( IsLower<MT5>::value )
1443  ?( IsStrictlyLower<MT5>::value ? A.upperBound(i,j) : A.lowerBound(i,j) )
1444  :( A.begin(i) ) );
1445 
1446  const size_t nonzeros( end - element );
1447  const size_t kpos( nonzeros & size_t(-4) );
1448  BLAZE_INTERNAL_ASSERT( ( nonzeros - ( nonzeros % 4UL ) ) == kpos, "Invalid end calculation" );
1449 
1450  for( size_t k=0UL; k<kpos; k+=4UL )
1451  {
1452  const size_t i1( element->index() );
1453  const ET1 v1( element->value() );
1454  ++element;
1455  const size_t i2( element->index() );
1456  const ET1 v2( element->value() );
1457  ++element;
1458  const size_t i3( element->index() );
1459  const ET1 v3( element->value() );
1460  ++element;
1461  const size_t i4( element->index() );
1462  const ET1 v4( element->value() );
1463  ++element;
1464 
1465  BLAZE_INTERNAL_ASSERT( i1 < i2 && i2 < i3 && i3 < i4, "Invalid sparse matrix index detected" );
1466 
1467  C(i,j) -= v1 * B(i1,j) + v2 * B(i2,j) + v3 * B(i3,j) + v4 * B(i4,j);
1468  }
1469 
1470  for( ; element!=end; ++element )
1471  {
1472  const size_t i1( element->index() );
1473  const ET1 v1( element->value() );
1474 
1475  C(i,j) -= v1 * B(i1,j);
1476  }
1477  }
1478  }
1479  }
1480  }
1482  //**********************************************************************************************
1483 
1484  //**Restructuring subtraction assignment********************************************************
1499  template< typename MT // Type of the target matrix
1500  , bool SO > // Storage order of the target matrix
1502  subAssign( Matrix<MT,SO>& lhs, const SMatTDMatMultExpr& rhs )
1503  {
1505 
1506  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
1507  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
1508 
1509  const ForwardFunctor fwd;
1510 
1511  subAssign( ~lhs, fwd( rhs.lhs_ * trans( rhs.rhs_ ) ) );
1512  }
1514  //**********************************************************************************************
1515 
1516  //**Subtraction assignment to sparse matrices***************************************************
1517  // No special implementation for the subtraction assignment to sparse matrices.
1518  //**********************************************************************************************
1519 
1520  //**Schur product assignment to dense matrices**************************************************
1533  template< typename MT // Type of the target dense matrix
1534  , bool SO > // Storage order of the target dense matrix
1535  friend inline void schurAssign( DenseMatrix<MT,SO>& lhs, const SMatTDMatMultExpr& rhs )
1536  {
1538 
1542 
1543  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
1544  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
1545 
1546  const ResultType tmp( serial( rhs ) );
1547  schurAssign( ~lhs, tmp );
1548  }
1550  //**********************************************************************************************
1551 
1552  //**Schur product assignment to sparse matrices*************************************************
1553  // No special implementation for the Schur product assignment to sparse matrices.
1554  //**********************************************************************************************
1555 
1556  //**Multiplication assignment to dense matrices*************************************************
1557  // No special implementation for the multiplication assignment to dense matrices.
1558  //**********************************************************************************************
1559 
1560  //**Multiplication assignment to sparse matrices************************************************
1561  // No special implementation for the multiplication assignment to sparse matrices.
1562  //**********************************************************************************************
1563 
1564  //**SMP assignment to dense matrices************************************************************
1579  template< typename MT // Type of the target dense matrix
1580  , bool SO > // Storage order of the target dense matrix
1582  smpAssign( DenseMatrix<MT,SO>& lhs, const SMatTDMatMultExpr& rhs )
1583  {
1585 
1586  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
1587  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
1588 
1589  LT A( rhs.lhs_ ); // Evaluation of the left-hand side sparse matrix operand
1590  RT B( rhs.rhs_ ); // Evaluation of the right-hand side dense matrix operand
1591 
1592  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
1593  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
1594  BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
1595  BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
1596  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
1597  BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
1598 
1599  smpAssign( ~lhs, A * B );
1600  }
1602  //**********************************************************************************************
1603 
1604  //**SMP assignment to sparse matrices***********************************************************
1619  template< typename MT // Type of the target sparse matrix
1620  , bool SO > // Storage order of the target sparse matrix
1622  smpAssign( SparseMatrix<MT,SO>& lhs, const SMatTDMatMultExpr& rhs )
1623  {
1625 
1627 
1634 
1635  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
1636  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
1637 
1638  const ForwardFunctor fwd;
1639 
1640  const TmpType tmp( rhs );
1641  smpAssign( ~lhs, fwd( tmp ) );
1642  }
1644  //**********************************************************************************************
1645 
1646  //**Restructuring SMP assignment****************************************************************
1661  template< typename MT // Type of the target matrix
1662  , bool SO > // Storage order of the target matrix
1664  smpAssign( Matrix<MT,SO>& lhs, const SMatTDMatMultExpr& rhs )
1665  {
1667 
1668  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
1669  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
1670 
1671  const ForwardFunctor fwd;
1672 
1673  smpAssign( ~lhs, fwd( rhs.lhs_ * trans( rhs.rhs_ ) ) );
1674  }
1676  //**********************************************************************************************
1677 
1678  //**SMP addition assignment to dense matrices***************************************************
1694  template< typename MT // Type of the target dense matrix
1695  , bool SO > // Storage order of the target dense matrix
1698  {
1700 
1701  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
1702  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
1703 
1704  LT A( rhs.lhs_ ); // Evaluation of the left-hand side sparse matrix operand
1705  RT B( rhs.rhs_ ); // Evaluation of the right-hand side dense matrix operand
1706 
1707  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
1708  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
1709  BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
1710  BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
1711  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
1712  BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
1713 
1714  smpAddAssign( ~lhs, A * B );
1715  }
1717  //**********************************************************************************************
1718 
1719  //**Restructuring SMP addition assignment*******************************************************
1734  template< typename MT // Type of the target matrix
1735  , bool SO > // Storage order of the target matrix
1737  smpAddAssign( Matrix<MT,SO>& lhs, const SMatTDMatMultExpr& rhs )
1738  {
1740 
1741  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
1742  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
1743 
1744  const ForwardFunctor fwd;
1745 
1746  smpAddAssign( ~lhs, fwd( rhs.lhs_ * trans( rhs.rhs_ ) ) );
1747  }
1749  //**********************************************************************************************
1750 
1751  //**SMP addition assignment to sparse matrices**************************************************
1752  // No special implementation for the SMP addition assignment to sparse matrices.
1753  //**********************************************************************************************
1754 
1755  //**SMP subtraction assignment to dense matrices************************************************
1771  template< typename MT // Type of the target dense matrix
1772  , bool SO > // Storage order of the target dense matrix
1775  {
1777 
1778  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
1779  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
1780 
1781  LT A( rhs.lhs_ ); // Evaluation of the left-hand side sparse matrix operand
1782  RT B( rhs.rhs_ ); // Evaluation of the right-hand side dense matrix operand
1783 
1784  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
1785  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
1786  BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
1787  BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
1788  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
1789  BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
1790 
1791  smpSubAssign( ~lhs, A * B );
1792  }
1794  //**********************************************************************************************
1795 
1796  //**Restructuring SMP subtraction assignment****************************************************
1811  template< typename MT // Type of the target matrix
1812  , bool SO > // Storage order of the target matrix
1814  smpSubAssign( Matrix<MT,SO>& lhs, const SMatTDMatMultExpr& rhs )
1815  {
1817 
1818  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
1819  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
1820 
1821  const ForwardFunctor fwd;
1822 
1823  smpSubAssign( ~lhs, fwd( rhs.lhs_ * trans( rhs.rhs_ ) ) );
1824  }
1826  //**********************************************************************************************
1827 
1828  //**SMP subtraction assignment to sparse matrices***********************************************
1829  // No special implementation for the SMP subtraction assignment to sparse matrices.
1830  //**********************************************************************************************
1831 
1832  //**SMP Schur product assignment to dense matrices**********************************************
1845  template< typename MT // Type of the target dense matrix
1846  , bool SO > // Storage order of the target dense matrix
1847  friend inline void smpSchurAssign( DenseMatrix<MT,SO>& lhs, const SMatTDMatMultExpr& rhs )
1848  {
1850 
1854 
1855  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
1856  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
1857 
1858  const ResultType tmp( rhs );
1859  smpSchurAssign( ~lhs, tmp );
1860  }
1862  //**********************************************************************************************
1863 
1864  //**SMP Schur product assignment to sparse matrices*********************************************
1865  // No special implementation for the SMP Schur product assignment to sparse matrices.
1866  //**********************************************************************************************
1867 
1868  //**SMP multiplication assignment to dense matrices*********************************************
1869  // No special implementation for the SMP multiplication assignment to dense matrices.
1870  //**********************************************************************************************
1871 
1872  //**SMP multiplication assignment to sparse matrices********************************************
1873  // No special implementation for the SMP multiplication assignment to sparse matrices.
1874  //**********************************************************************************************
1875 
1876  //**Compile time checks*************************************************************************
1884  //**********************************************************************************************
1885 };
1886 //*************************************************************************************************
1887 
1888 
1889 
1890 
1891 //=================================================================================================
1892 //
1893 // GLOBAL BINARY ARITHMETIC OPERATORS
1894 //
1895 //=================================================================================================
1896 
1897 //*************************************************************************************************
1928 template< typename MT1 // Type of the left-hand side sparse matrix
1929  , typename MT2 > // Type of the right-hand side dense matrix
1930 inline decltype(auto)
1931  operator*( const SparseMatrix<MT1,false>& lhs, const DenseMatrix<MT2,true>& rhs )
1932 {
1934 
1935  if( (~lhs).columns() != (~rhs).rows() ) {
1936  BLAZE_THROW_INVALID_ARGUMENT( "Matrix sizes do not match" );
1937  }
1938 
1940  return ReturnType( ~lhs, ~rhs );
1941 }
1942 //*************************************************************************************************
1943 
1944 
1945 
1946 
1947 //=================================================================================================
1948 //
1949 // GLOBAL FUNCTIONS
1950 //
1951 //=================================================================================================
1952 
1953 //*************************************************************************************************
1979 template< typename MT1 // Type of the left-hand side dense matrix
1980  , typename MT2 // Type of the right-hand side dense matrix
1981  , bool SF // Symmetry flag
1982  , bool HF // Hermitian flag
1983  , bool LF // Lower flag
1984  , bool UF > // Upper flag
1985 inline decltype(auto) declsym( const SMatTDMatMultExpr<MT1,MT2,SF,HF,LF,UF>& dm )
1986 {
1988 
1989  if( !isSquare( dm ) ) {
1990  BLAZE_THROW_INVALID_ARGUMENT( "Invalid symmetric matrix specification" );
1991  }
1992 
1994  return ReturnType( dm.leftOperand(), dm.rightOperand() );
1995 }
1997 //*************************************************************************************************
1998 
1999 
2000 //*************************************************************************************************
2026 template< typename MT1 // Type of the left-hand side dense matrix
2027  , typename MT2 // Type of the right-hand side dense matrix
2028  , bool SF // Symmetry flag
2029  , bool HF // Hermitian flag
2030  , bool LF // Lower flag
2031  , bool UF > // Upper flag
2032 inline decltype(auto) declherm( const SMatTDMatMultExpr<MT1,MT2,SF,HF,LF,UF>& dm )
2033 {
2035 
2036  if( !isSquare( dm ) ) {
2037  BLAZE_THROW_INVALID_ARGUMENT( "Invalid Hermitian matrix specification" );
2038  }
2039 
2041  return ReturnType( dm.leftOperand(), dm.rightOperand() );
2042 }
2044 //*************************************************************************************************
2045 
2046 
2047 //*************************************************************************************************
2073 template< typename MT1 // Type of the left-hand side dense matrix
2074  , typename MT2 // Type of the right-hand side dense matrix
2075  , bool SF // Symmetry flag
2076  , bool HF // Hermitian flag
2077  , bool LF // Lower flag
2078  , bool UF > // Upper flag
2079 inline decltype(auto) decllow( const SMatTDMatMultExpr<MT1,MT2,SF,HF,LF,UF>& dm )
2080 {
2082 
2083  if( !isSquare( dm ) ) {
2084  BLAZE_THROW_INVALID_ARGUMENT( "Invalid lower matrix specification" );
2085  }
2086 
2088  return ReturnType( dm.leftOperand(), dm.rightOperand() );
2089 }
2091 //*************************************************************************************************
2092 
2093 
2094 //*************************************************************************************************
2120 template< typename MT1 // Type of the left-hand side dense matrix
2121  , typename MT2 // Type of the right-hand side dense matrix
2122  , bool SF // Symmetry flag
2123  , bool HF // Hermitian flag
2124  , bool LF // Lower flag
2125  , bool UF > // Upper flag
2126 inline decltype(auto) declupp( const SMatTDMatMultExpr<MT1,MT2,SF,HF,LF,UF>& dm )
2127 {
2129 
2130  if( !isSquare( dm ) ) {
2131  BLAZE_THROW_INVALID_ARGUMENT( "Invalid upper matrix specification" );
2132  }
2133 
2135  return ReturnType( dm.leftOperand(), dm.rightOperand() );
2136 }
2138 //*************************************************************************************************
2139 
2140 
2141 //*************************************************************************************************
2167 template< typename MT1 // Type of the left-hand side dense matrix
2168  , typename MT2 // Type of the right-hand side dense matrix
2169  , bool SF // Symmetry flag
2170  , bool HF // Hermitian flag
2171  , bool LF // Lower flag
2172  , bool UF > // Upper flag
2173 inline decltype(auto) decldiag( const SMatTDMatMultExpr<MT1,MT2,SF,HF,LF,UF>& dm )
2174 {
2176 
2177  if( !isSquare( dm ) ) {
2178  BLAZE_THROW_INVALID_ARGUMENT( "Invalid diagonal matrix specification" );
2179  }
2180 
2182  return ReturnType( dm.leftOperand(), dm.rightOperand() );
2183 }
2185 //*************************************************************************************************
2186 
2187 
2188 
2189 
2190 //=================================================================================================
2191 //
2192 // ROWS SPECIALIZATIONS
2193 //
2194 //=================================================================================================
2195 
2196 //*************************************************************************************************
2198 template< typename MT1, typename MT2, bool SF, bool HF, bool LF, bool UF >
2199 struct Rows< SMatTDMatMultExpr<MT1,MT2,SF,HF,LF,UF> >
2200  : public Rows<MT1>
2201 {};
2203 //*************************************************************************************************
2204 
2205 
2206 
2207 
2208 //=================================================================================================
2209 //
2210 // COLUMNS SPECIALIZATIONS
2211 //
2212 //=================================================================================================
2213 
2214 //*************************************************************************************************
2216 template< typename MT1, typename MT2, bool SF, bool HF, bool LF, bool UF >
2217 struct Columns< SMatTDMatMultExpr<MT1,MT2,SF,HF,LF,UF> >
2218  : public Columns<MT2>
2219 {};
2221 //*************************************************************************************************
2222 
2223 
2224 
2225 
2226 //=================================================================================================
2227 //
2228 // ISALIGNED SPECIALIZATIONS
2229 //
2230 //=================================================================================================
2231 
2232 //*************************************************************************************************
2234 template< typename MT1, typename MT2, bool SF, bool HF, bool LF, bool UF >
2235 struct IsAligned< SMatTDMatMultExpr<MT1,MT2,SF,HF,LF,UF> >
2236  : public BoolConstant< IsAligned<MT2>::value >
2237 {};
2239 //*************************************************************************************************
2240 
2241 
2242 
2243 
2244 //=================================================================================================
2245 //
2246 // ISSYMMETRIC SPECIALIZATIONS
2247 //
2248 //=================================================================================================
2249 
2250 //*************************************************************************************************
2252 template< typename MT1, typename MT2, bool SF, bool HF, bool LF, bool UF >
2253 struct IsSymmetric< SMatTDMatMultExpr<MT1,MT2,SF,HF,LF,UF> >
2254  : public BoolConstant< Or< Bool<SF>
2255  , And< Bool<HF>
2256  , IsBuiltin< ElementType_< SMatTDMatMultExpr<MT1,MT2,false,true,false,false> > > >
2257  , And< Bool<LF>, Bool<UF> > >::value >
2258 {};
2260 //*************************************************************************************************
2261 
2262 
2263 
2264 
2265 //=================================================================================================
2266 //
2267 // ISHERMITIAN SPECIALIZATIONS
2268 //
2269 //=================================================================================================
2270 
2271 //*************************************************************************************************
2273 template< typename MT1, typename MT2, bool SF, bool LF, bool UF >
2274 struct IsHermitian< SMatTDMatMultExpr<MT1,MT2,SF,true,LF,UF> >
2275  : public TrueType
2276 {};
2278 //*************************************************************************************************
2279 
2280 
2281 
2282 
2283 //=================================================================================================
2284 //
2285 // ISLOWER SPECIALIZATIONS
2286 //
2287 //=================================================================================================
2288 
2289 //*************************************************************************************************
2291 template< typename MT1, typename MT2, bool SF, bool HF, bool LF, bool UF >
2292 struct IsLower< SMatTDMatMultExpr<MT1,MT2,SF,HF,LF,UF> >
2293  : public BoolConstant< Or< Bool<LF>
2294  , And< IsLower<MT1>, IsLower<MT2> >
2295  , And< Or< Bool<SF>, Bool<HF> >
2296  , IsUpper<MT1>, IsUpper<MT2> > >::value >
2297 {};
2299 //*************************************************************************************************
2300 
2301 
2302 
2303 
2304 //=================================================================================================
2305 //
2306 // ISUNILOWER SPECIALIZATIONS
2307 //
2308 //=================================================================================================
2309 
2310 //*************************************************************************************************
2312 template< typename MT1, typename MT2, bool SF, bool HF, bool LF, bool UF >
2313 struct IsUniLower< SMatTDMatMultExpr<MT1,MT2,SF,HF,LF,UF> >
2314  : public BoolConstant< Or< And< IsUniLower<MT1>, IsUniLower<MT2> >
2315  , And< Or< Bool<SF>, Bool<HF> >
2316  , IsUniUpper<MT1>, IsUniUpper<MT2> > >::value >
2317 {};
2319 //*************************************************************************************************
2320 
2321 
2322 
2323 
2324 //=================================================================================================
2325 //
2326 // ISSTRICTLYLOWER SPECIALIZATIONS
2327 //
2328 //=================================================================================================
2329 
2330 //*************************************************************************************************
2332 template< typename MT1, typename MT2, bool SF, bool HF, bool LF, bool UF >
2333 struct IsStrictlyLower< SMatTDMatMultExpr<MT1,MT2,SF,HF,LF,UF> >
2334  : public BoolConstant< Or< And< IsStrictlyLower<MT1>, IsLower<MT2> >
2335  , And< IsStrictlyLower<MT2>, IsLower<MT1> >
2336  , And< Or< Bool<SF>, Bool<HF> >
2337  , Or< And< IsStrictlyUpper<MT1>, IsUpper<MT2> >
2338  , And< IsStrictlyUpper<MT2>, IsUpper<MT1> > > > >::value >
2339 {};
2341 //*************************************************************************************************
2342 
2343 
2344 
2345 
2346 //=================================================================================================
2347 //
2348 // ISUPPER SPECIALIZATIONS
2349 //
2350 //=================================================================================================
2351 
2352 //*************************************************************************************************
2354 template< typename MT1, typename MT2, bool SF, bool HF, bool LF, bool UF >
2355 struct IsUpper< SMatTDMatMultExpr<MT1,MT2,SF,HF,LF,UF> >
2356  : public BoolConstant< Or< Bool<UF>
2357  , And< IsUpper<MT1>, IsUpper<MT2> >
2358  , And< Or< Bool<SF>, Bool<HF> >
2359  , IsLower<MT1>, IsLower<MT2> > >::value >
2360 {};
2362 //*************************************************************************************************
2363 
2364 
2365 
2366 
2367 //=================================================================================================
2368 //
2369 // ISUNIUPPER SPECIALIZATIONS
2370 //
2371 //=================================================================================================
2372 
2373 //*************************************************************************************************
2375 template< typename MT1, typename MT2, bool SF, bool HF, bool LF, bool UF >
2376 struct IsUniUpper< SMatTDMatMultExpr<MT1,MT2,SF,HF,LF,UF> >
2377  : public BoolConstant< Or< And< IsUniUpper<MT1>, IsUniUpper<MT2> >
2378  , And< Or< Bool<SF>, Bool<HF> >
2379  , IsUniLower<MT1>, IsUniLower<MT2> > >::value >
2380 {};
2382 //*************************************************************************************************
2383 
2384 
2385 
2386 
2387 //=================================================================================================
2388 //
2389 // ISSTRICTLYUPPER SPECIALIZATIONS
2390 //
2391 //=================================================================================================
2392 
2393 //*************************************************************************************************
2395 template< typename MT1, typename MT2, bool SF, bool HF, bool LF, bool UF >
2396 struct IsStrictlyUpper< SMatTDMatMultExpr<MT1,MT2,SF,HF,LF,UF> >
2397  : public BoolConstant< Or< And< IsStrictlyUpper<MT1>, IsUpper<MT2> >
2398  , And< IsStrictlyUpper<MT2>, IsUpper<MT1> >
2399  , And< Or< Bool<SF>, Bool<HF> >
2400  , Or< And< IsStrictlyLower<MT1>, IsLower<MT2> >
2401  , And< IsStrictlyLower<MT2>, IsLower<MT1> > > > >::value >
2402 {};
2404 //*************************************************************************************************
2405 
2406 } // namespace blaze
2407 
2408 #endif
#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
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
IfTrue_< evaluateLeft, const RT1, CT1 > LT
Type for the assignment of the left-hand side sparse matrix operand.
Definition: SMatTDMatMultExpr.h:236
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.
ResultType_< MT2 > RT2
Result type of the right-hand side dense matrix expression.
Definition: SMatTDMatMultExpr.h:128
const ElementType ReturnType
Return type for expression template evaluations.
Definition: SMatTDMatMultExpr.h:226
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
RightOperand rightOperand() const noexcept
Returns the right-hand side transpose dense matrix operand.
Definition: SMatTDMatMultExpr.h:366
ResultType_< MT1 > RT1
Result type of the left-hand side sparse matrix expression.
Definition: SMatTDMatMultExpr.h:127
Flag for lower matrices.
Definition: SMatTDMatMultExpr.h:150
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
Header file for the serial shim.
ElementType_< ResultType > ElementType
Resulting element type.
Definition: SMatTDMatMultExpr.h:225
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
size_t columns() const noexcept
Returns the current number of columns of the matrix.
Definition: SMatTDMatMultExpr.h:346
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
decltype(auto) declupp(const DenseMatrix< MT, SO > &dm)
Declares the given dense matrix expression dm as upper.
Definition: DMatDeclUppExpr.h:1027
bool isAliased(const T *alias) const noexcept
Returns whether the expression is aliased with the given address alias.
Definition: SMatTDMatMultExpr.h:390
TransposeType_< ResultType > TransposeType
Transpose type for expression template evaluations.
Definition: SMatTDMatMultExpr.h:224
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.
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.
System settings for performance optimizations.
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
CompositeType_< MT1 > CT1
Composite type of the left-hand side sparse matrix expression.
Definition: SMatTDMatMultExpr.h:131
size_t rows() const noexcept
Returns the current number of rows of the matrix.
Definition: SMatTDMatMultExpr.h:336
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
CompositeType_< MT2 > CT2
Composite type of the right-hand side dense matrix expression.
Definition: SMatTDMatMultExpr.h:132
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
Flag for Hermitian matrices.
Definition: SMatTDMatMultExpr.h:149
typename T::CompositeType CompositeType_
Alias declaration for nested CompositeType type definitions.The CompositeType_ alias declaration prov...
Definition: Aliases.h:83
bool canAlias(const T *alias) const noexcept
Returns whether the expression can alias with the given address alias.
Definition: SMatTDMatMultExpr.h:378
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.
Header file for the If class template.
#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
bool canSMPAssign() const noexcept
Returns whether the expression can be used in SMP assignments.
Definition: SMatTDMatMultExpr.h:410
OppositeType_< ResultType > OppositeType
Result type with opposite storage order for expression template evaluations.
Definition: SMatTDMatMultExpr.h:223
bool isAligned() const noexcept
Returns whether the operands of the expression are properly aligned in memory.
Definition: SMatTDMatMultExpr.h:400
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
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.
LeftOperand lhs_
Left-hand side sparse matrix of the multiplication expression.
Definition: SMatTDMatMultExpr.h:417
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
If_< IsExpression< MT2 >, const MT2, const MT2 &> RightOperand
Composite type of the right-hand side dense matrix expression.
Definition: SMatTDMatMultExpr.h:233
Expression object for sparse matrix-transpose dense matrix multiplications.The SMatTDMatMultExpr clas...
Definition: Forward.h:121
const ResultType CompositeType
Data type for composite expression templates.
Definition: SMatTDMatMultExpr.h:227
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
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.
ElementType_< RT2 > ET2
Element type of the right-hand side sparse matrix expression.
Definition: SMatTDMatMultExpr.h:130
Constraint on the data type.
Header file for all forward declarations for expression class templates.
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
#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.
ElementType_< RT1 > ET1
Element type of the left-hand side dense matrix expression.
Definition: SMatTDMatMultExpr.h:129
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
Header file for the reset shim.
#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:1029
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
Flag for symmetric matrices.
Definition: SMatTDMatMultExpr.h:148
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
SMatTDMatMultExpr(const MT1 &lhs, const MT2 &rhs) noexcept
Constructor for the SMatTDMatMultExpr class.
Definition: SMatTDMatMultExpr.h:257
Header file for the Noop functor.
#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
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
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
LeftOperand leftOperand() const noexcept
Returns the left-hand side sparse matrix operand.
Definition: SMatTDMatMultExpr.h:356
decltype(auto) declherm(const DenseMatrix< MT, SO > &dm)
Declares the given dense matrix expression dm as Hermitian.
Definition: DMatDeclHermExpr.h:1029
Header file for the IsComputation type trait class.
RightOperand rhs_
Right-hand side dense matrix of the multiplication expression.
Definition: SMatTDMatMultExpr.h:418
Header file for the IsBuiltin type trait.
ReturnType operator()(size_t i, size_t j) const
2D-access to the matrix elements.
Definition: SMatTDMatMultExpr.h:272
If_< IsExpression< MT1 >, const MT1, const MT1 &> LeftOperand
Composite type of the left-hand side sparse matrix expression.
Definition: SMatTDMatMultExpr.h:230
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.
IfTrue_< evaluateRight, const RT2, CT2 > RT
Type for the assignment of the right-hand side dense matrix operand.
Definition: SMatTDMatMultExpr.h:239
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
Flag for upper matrices.
Definition: SMatTDMatMultExpr.h:151
Constraint on the data type.
Generic wrapper for the declsym() function.
Definition: DeclSym.h:58
BLAZE_ALWAYS_INLINE bool isSquare(const Matrix< MT, SO > &matrix) noexcept
Checks if the given matrix is a square matrix.
Definition: Matrix.h:742
MultTrait_< RT1, RT2 > ResultType
Result type for expression template evaluations.
Definition: SMatTDMatMultExpr.h:222
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
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.
ReturnType at(size_t i, size_t j) const
Checked access to the matrix elements.
Definition: SMatTDMatMultExpr.h:320