DMatSMatMultExpr.h
Go to the documentation of this file.
1 //=================================================================================================
33 //=================================================================================================
34 
35 #ifndef _BLAZE_MATH_EXPRESSIONS_DMATSMATMULTEXPR_H_
36 #define _BLAZE_MATH_EXPRESSIONS_DMATSMATMULTEXPR_H_
37 
38 
39 //*************************************************************************************************
40 // Includes
41 //*************************************************************************************************
42 
43 #include <blaze/math/Aliases.h>
53 #include <blaze/math/Exception.h>
66 #include <blaze/math/shims/Reset.h>
89 #include <blaze/math/views/Check.h>
94 #include <blaze/util/Assert.h>
95 #include <blaze/util/DisableIf.h>
96 #include <blaze/util/EnableIf.h>
99 #include <blaze/util/mpl/If.h>
100 #include <blaze/util/Types.h>
103 #include <blaze/util/Unused.h>
104 
105 
106 namespace blaze {
107 
108 //=================================================================================================
109 //
110 // CLASS DMATSMATMULTEXPR
111 //
112 //=================================================================================================
113 
114 //*************************************************************************************************
121 template< typename MT1 // Type of the left-hand side dense matrix
122  , typename MT2 // Type of the right-hand side sparse matrix
123  , bool SF // Symmetry flag
124  , bool HF // Hermitian flag
125  , bool LF // Lower flag
126  , bool UF > // Upper flag
128  : public MatMatMultExpr< DenseMatrix< DMatSMatMultExpr<MT1,MT2,SF,HF,LF,UF>, false > >
129  , private Computation
130 {
131  private:
132  //**Type definitions****************************************************************************
139  //**********************************************************************************************
140 
141  //**********************************************************************************************
143  static constexpr bool evaluateLeft = ( IsComputation_v<MT1> || RequiresEvaluation_v<MT1> );
144  //**********************************************************************************************
145 
146  //**********************************************************************************************
148  static constexpr bool evaluateRight = ( IsComputation_v<MT2> || RequiresEvaluation_v<MT2> );
149  //**********************************************************************************************
150 
151  //**********************************************************************************************
152  static constexpr bool SYM = ( SF && !( HF || LF || UF ) );
153  static constexpr bool HERM = ( HF && !( LF || UF ) );
154  static constexpr bool LOW = ( LF || ( ( SF || HF ) && UF ) );
155  static constexpr bool UPP = ( UF || ( ( SF || HF ) && LF ) );
156  //**********************************************************************************************
157 
158  //**********************************************************************************************
160 
165  template< typename T1, typename T2, typename T3 >
166  static constexpr bool CanExploitSymmetry_v = ( IsSymmetric_v<T2> || IsSymmetric_v<T3> );
168  //**********************************************************************************************
169 
170  //**********************************************************************************************
172 
176  template< typename T1, typename T2, typename T3 >
177  static constexpr bool IsEvaluationRequired_v =
178  ( evaluateLeft || evaluateRight ) && !CanExploitSymmetry_v<T1,T2,T3>;
180  //**********************************************************************************************
181 
182  //**********************************************************************************************
184 
187  template< typename T1, typename T2, typename T3 >
188  static constexpr bool UseOptimizedKernel_v =
189  useOptimizedKernels && !IsDiagonal_v<T2> && !IsResizable_v< ElementType_t<T1> >;
191  //**********************************************************************************************
192 
193  //**********************************************************************************************
195 
198  template< typename T1, typename T2, typename T3 >
199  static constexpr bool UseDefaultKernel_v = !UseOptimizedKernel_v<T1,T2,T3>;
201  //**********************************************************************************************
202 
203  //**********************************************************************************************
205 
208  using ForwardFunctor = If_t< HERM
209  , DeclHerm
210  , If_t< SYM
211  , DeclSym
212  , If_t< LOW
213  , If_t< UPP
214  , DeclDiag
215  , DeclLow >
216  , If_t< UPP
217  , DeclUpp
218  , Noop > > > >;
220  //**********************************************************************************************
221 
222  public:
223  //**Type definitions****************************************************************************
226 
229 
231  using ResultType = typename If_t< HERM
233  , If_t< SYM
235  , If_t< LOW
236  , If_t< UPP
239  , If_t< UPP
241  , MultTrait<RT1,RT2> > > > >::Type;
242 
246  using ReturnType = const ElementType;
247  using CompositeType = const ResultType;
248 
250  using LeftOperand = If_t< IsExpression_v<MT1>, const MT1, const MT1& >;
251 
253  using RightOperand = If_t< IsExpression_v<MT2>, const MT2, const MT2& >;
254 
257 
260  //**********************************************************************************************
261 
262  //**Compilation flags***************************************************************************
264  static constexpr bool simdEnabled = false;
265 
267  static constexpr bool smpAssignable =
269  //**********************************************************************************************
270 
271  //**Constructor*********************************************************************************
277  explicit inline DMatSMatMultExpr( const MT1& lhs, const MT2& rhs ) noexcept
278  : lhs_( lhs ) // Left-hand side dense matrix of the multiplication expression
279  , rhs_( rhs ) // Right-hand side sparse matrix of the multiplication expression
280  {
281  BLAZE_INTERNAL_ASSERT( lhs.columns() == rhs.rows(), "Invalid matrix sizes" );
282  }
283  //**********************************************************************************************
284 
285  //**Access operator*****************************************************************************
292  inline ReturnType operator()( size_t i, size_t j ) const {
293  BLAZE_INTERNAL_ASSERT( i < lhs_.rows() , "Invalid row access index" );
294  BLAZE_INTERNAL_ASSERT( j < rhs_.columns(), "Invalid column access index" );
295 
296  if( IsDiagonal_v<MT1> ) {
297  return lhs_(i,i) * rhs_(i,j);
298  }
299  else if( IsDiagonal_v<MT2> ) {
300  return lhs_(i,j) * rhs_(j,j);
301  }
302  else if( IsTriangular_v<MT1> || IsTriangular_v<MT2> ) {
303  const size_t begin( ( IsUpper_v<MT1> )
304  ?( ( IsLower_v<MT2> )
305  ?( max( ( IsStrictlyUpper_v<MT1> ? i+1UL : i )
306  , ( IsStrictlyLower_v<MT2> ? j+1UL : j ) ) )
307  :( IsStrictlyUpper_v<MT1> ? i+1UL : i ) )
308  :( ( IsLower_v<MT2> )
309  ?( IsStrictlyLower_v<MT2> ? j+1UL : j )
310  :( 0UL ) ) );
311  const size_t end( ( IsLower_v<MT1> )
312  ?( ( IsUpper_v<MT2> )
313  ?( min( ( IsStrictlyLower_v<MT1> ? i : i+1UL )
314  , ( IsStrictlyUpper_v<MT2> ? j : j+1UL ) ) )
315  :( IsStrictlyLower_v<MT1> ? i : i+1UL ) )
316  :( ( IsUpper_v<MT2> )
317  ?( IsStrictlyUpper_v<MT2> ? j : j+1UL )
318  :( lhs_.columns() ) ) );
319 
320  if( begin >= end ) return ElementType();
321 
322  const size_t n( end - begin );
323 
324  return subvector( row( lhs_, i, unchecked ), begin, n, unchecked ) *
325  subvector( column( rhs_, j, unchecked ), begin, n, unchecked );
326  }
327  else {
328  return row( lhs_, i, unchecked ) * column( rhs_, j, unchecked );
329  }
330  }
331  //**********************************************************************************************
332 
333  //**At function*********************************************************************************
341  inline ReturnType at( size_t i, size_t j ) const {
342  if( i >= lhs_.rows() ) {
343  BLAZE_THROW_OUT_OF_RANGE( "Invalid row access index" );
344  }
345  if( j >= rhs_.columns() ) {
346  BLAZE_THROW_OUT_OF_RANGE( "Invalid column access index" );
347  }
348  return (*this)(i,j);
349  }
350  //**********************************************************************************************
351 
352  //**Rows function*******************************************************************************
357  inline size_t rows() const noexcept {
358  return lhs_.rows();
359  }
360  //**********************************************************************************************
361 
362  //**Columns function****************************************************************************
367  inline size_t columns() const noexcept {
368  return rhs_.columns();
369  }
370  //**********************************************************************************************
371 
372  //**Left operand access*************************************************************************
377  inline LeftOperand leftOperand() const noexcept {
378  return lhs_;
379  }
380  //**********************************************************************************************
381 
382  //**Right operand access************************************************************************
387  inline RightOperand rightOperand() const noexcept {
388  return rhs_;
389  }
390  //**********************************************************************************************
391 
392  //**********************************************************************************************
398  template< typename T >
399  inline bool canAlias( const T* alias ) const noexcept {
400  return ( lhs_.isAliased( alias ) || rhs_.isAliased( alias ) );
401  }
402  //**********************************************************************************************
403 
404  //**********************************************************************************************
410  template< typename T >
411  inline bool isAliased( const T* alias ) const noexcept {
412  return ( lhs_.isAliased( alias ) || rhs_.isAliased( alias ) );
413  }
414  //**********************************************************************************************
415 
416  //**********************************************************************************************
421  inline bool isAligned() const noexcept {
422  return lhs_.isAligned();
423  }
424  //**********************************************************************************************
425 
426  //**********************************************************************************************
431  inline bool canSMPAssign() const noexcept {
432  return ( rows() * columns() >= SMP_DMATSMATMULT_THRESHOLD ) && !IsDiagonal_v<MT1>;
433  }
434  //**********************************************************************************************
435 
436  private:
437  //**Member variables****************************************************************************
440  //**********************************************************************************************
441 
442  //**Assignment to dense matrices****************************************************************
455  template< typename MT // Type of the target dense matrix
456  , bool SO > // Storage order of the target dense matrix
457  friend inline auto assign( DenseMatrix<MT,SO>& lhs, const DMatSMatMultExpr& rhs )
459  {
461 
462  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
463  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
464 
465  LT A( serial( rhs.lhs_ ) ); // Evaluation of the left-hand side dense matrix operand
466  RT B( serial( rhs.rhs_ ) ); // Evaluation of the right-hand side sparse matrix operand
467 
468  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
469  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
470  BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
471  BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
472  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
473  BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
474 
475  DMatSMatMultExpr::selectAssignKernel( ~lhs, A, B );
476  }
478  //**********************************************************************************************
479 
480  //**Assignment to dense matrices (kernel selection)*********************************************
491  template< typename MT3 // Type of the left-hand side target matrix
492  , typename MT4 // Type of the left-hand side matrix operand
493  , typename MT5 > // Type of the right-hand side matrix operand
494  static inline void selectAssignKernel( MT3& C, const MT4& A, const MT5& B )
495  {
496  if( C.rows() * C.columns() < DMATSMATMULT_THRESHOLD )
497  selectSmallAssignKernel( C, A, B );
498  else
499  selectLargeAssignKernel( C, A, B );
500  }
502  //**********************************************************************************************
503 
504  //**Default assignment to dense matrices********************************************************
518  template< typename MT3 // Type of the left-hand side target matrix
519  , typename MT4 // Type of the left-hand side matrix operand
520  , typename MT5 > // Type of the right-hand side matrix operand
521  static inline void selectDefaultAssignKernel( MT3& C, const MT4& A, const MT5& B )
522  {
523  reset( C );
524 
525  for( size_t k=0UL; k<B.rows(); ++k )
526  {
527  if( IsDiagonal_v<MT4> )
528  {
529  auto element( B.begin(k) );
530  const auto end( B.end(k) );
531 
532  for( ; element!=end; ++element ) {
533  C(k,element->index()) = A(k,k) * element->value();
534  }
535  }
536  else
537  {
538  const size_t iibegin( ( IsLower_v<MT4> )
539  ?( IsStrictlyLower_v<MT4> ? k+1UL : k )
540  :( 0UL ) );
541  const size_t iiend( ( IsUpper_v<MT4> )
542  ?( IsStrictlyUpper_v<MT4> ? k : k+1UL )
543  :( A.rows() ) );
544  BLAZE_INTERNAL_ASSERT( iibegin <= iiend, "Invalid loop indices detected" );
545 
546  for( size_t ii=iibegin; ii<iiend; ii+=8UL )
547  {
548  auto element( B.begin(k) );
549  const auto end( B.end(k) );
550  const size_t itmp( ( ii+8UL > iiend )?( iiend ):( ii+8UL ) );
551 
552  for( ; element!=end; ++element )
553  {
554  const size_t j1( element->index() );
555  const size_t ibegin( SYM || HERM || LOW ? max(j1,ii) : ii );
556  const size_t iend( UPP ? min(j1+1UL,itmp) : itmp );
557 
558  for( size_t i=ibegin; i<iend; ++i ) {
559  if( isDefault( C(i,element->index()) ) )
560  C(i,j1) = A(i,k) * element->value();
561  else
562  C(i,j1) += A(i,k) * element->value();
563  }
564  }
565  }
566  }
567  }
568 
569  if( SYM || HERM ) {
570  for( size_t i=0UL; i<A.rows(); ++i ) {
571  for( size_t j=i+1UL; j<B.columns(); ++j ) {
572  C(i,j) = HERM ? conj( C(j,i) ) : C(j,i);
573  }
574  }
575  }
576  }
578  //**********************************************************************************************
579 
580  //**Default assignment to dense matrices (small matrices)***************************************
593  template< typename MT3 // Type of the left-hand side target matrix
594  , typename MT4 // Type of the left-hand side matrix operand
595  , typename MT5 > // Type of the right-hand side matrix operand
596  static inline auto selectSmallAssignKernel( MT3& C, const MT4& A, const MT5& B )
597  -> EnableIf_t< UseDefaultKernel_v<MT3,MT4,MT5> >
598  {
599  selectDefaultAssignKernel( C, A, B );
600  }
602  //**********************************************************************************************
603 
604  //**Optimized assignment to dense matrices (small matrices)*************************************
619  template< typename MT3 // Type of the left-hand side target matrix
620  , typename MT4 // Type of the left-hand side matrix operand
621  , typename MT5 > // Type of the right-hand side matrix operand
622  static inline auto selectSmallAssignKernel( MT3& C, const MT4& A, const MT5& B )
623  -> EnableIf_t< UseOptimizedKernel_v<MT3,MT4,MT5> >
624  {
625  reset( C );
626 
627  for( size_t j=0UL; j<B.rows(); ++j )
628  {
629  const size_t iibegin( ( IsLower_v<MT4> )
630  ?( IsStrictlyLower_v<MT4> ? j+1UL : j )
631  :( 0UL ) );
632  const size_t iiend( ( IsUpper_v<MT4> )
633  ?( IsStrictlyUpper_v<MT4> ? j : j+1UL )
634  :( A.rows() ) );
635  BLAZE_INTERNAL_ASSERT( iibegin <= iiend, "Invalid loop indices detected" );
636 
637  for( size_t ii=iibegin; ii<iiend; ii+=8UL )
638  {
639  auto element( B.begin(j) );
640  const auto end( B.end(j) );
641  const size_t itmp( ( ii+8UL > iiend )?( iiend ):( ii+8UL ) );
642 
643  for( ; element!=end; ++element )
644  {
645  const size_t j1( element->index() );
646  const size_t ibegin( SYM || HERM || LOW ? max(j1,ii) : ii );
647  const size_t iend( UPP ? min(j1+1UL,itmp) : itmp );
648 
649  for( size_t i=ibegin; i<iend; ++i ) {
650  C(i,j1) += A(i,j) * element->value();
651  }
652  }
653  }
654  }
655 
656  if( SYM || HERM ) {
657  for( size_t i=0UL; i<A.rows(); ++i ) {
658  for( size_t j=i+1UL; j<B.columns(); ++j ) {
659  C(i,j) = HERM ? conj( C(j,i) ) : C(j,i);
660  }
661  }
662  }
663  }
665  //**********************************************************************************************
666 
667  //**Default assignment to dense matrices (large matrices)***************************************
680  template< typename MT3 // Type of the left-hand side target matrix
681  , typename MT4 // Type of the left-hand side matrix operand
682  , typename MT5 > // Type of the right-hand side matrix operand
683  static inline auto selectLargeAssignKernel( MT3& C, const MT4& A, const MT5& B )
684  -> EnableIf_t< UseDefaultKernel_v<MT3,MT4,MT5> >
685  {
686  selectDefaultAssignKernel( C, A, B );
687  }
689  //**********************************************************************************************
690 
691  //**Optimized assignment to dense matrices (large matrices)*************************************
706  template< typename MT3 // Type of the left-hand side target matrix
707  , typename MT4 // Type of the left-hand side matrix operand
708  , typename MT5 > // Type of the right-hand side matrix operand
709  static inline auto selectLargeAssignKernel( MT3& C, const MT4& A, const MT5& B )
710  -> EnableIf_t< UseOptimizedKernel_v<MT3,MT4,MT5> >
711  {
713 
714  const ForwardFunctor fwd;
715 
716  const OppositeType_t<MT5> tmp( serial( B ) );
717  assign( C, fwd( A * tmp ) );
718  }
720  //**********************************************************************************************
721 
722  //**Assignment to sparse matrices***************************************************************
735  template< typename MT // Type of the target sparse matrix
736  , bool SO > // Storage order of the target sparse matrix
737  friend inline auto assign( SparseMatrix<MT,SO>& lhs, const DMatSMatMultExpr& rhs )
738  -> DisableIf_t< CanExploitSymmetry_v<MT,MT1,MT2> >
739  {
741 
742  using TmpType = If_t< SO, OppositeType, ResultType >;
743 
750 
751  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
752  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
753 
754  const ForwardFunctor fwd;
755 
756  const TmpType tmp( serial( rhs ) );
757  assign( ~lhs, fwd( tmp ) );
758  }
760  //**********************************************************************************************
761 
762  //**Restructuring assignment********************************************************************
777  template< typename MT // Type of the target matrix
778  , bool SO > // Storage order of the target matrix
779  friend inline auto assign( Matrix<MT,SO>& lhs, const DMatSMatMultExpr& rhs )
780  -> EnableIf_t< CanExploitSymmetry_v<MT,MT1,MT2> >
781  {
783 
785 
786  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
787  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
788 
789  const ForwardFunctor fwd;
790 
791  if( IsSymmetric_v<MT1> && IsSymmetric_v<MT2> )
792  assign( ~lhs, fwd( trans( rhs.lhs_ ) * trans( rhs.rhs_ ) ) );
793  else if( IsSymmetric_v<MT1> )
794  assign( ~lhs, fwd( trans( rhs.lhs_ ) * rhs.rhs_ ) );
795  else
796  assign( ~lhs, fwd( rhs.lhs_ * trans( rhs.rhs_ ) ) );
797  }
799  //**********************************************************************************************
800 
801  //**Addition assignment to dense matrices*******************************************************
814  template< typename MT // Type of the target dense matrix
815  , bool SO > // Storage order of the target dense matrix
816  friend inline auto addAssign( DenseMatrix<MT,SO>& lhs, const DMatSMatMultExpr& rhs )
817  -> DisableIf_t< CanExploitSymmetry_v<MT,MT1,MT2> >
818  {
820 
821  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
822  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
823 
824  LT A( serial( rhs.lhs_ ) ); // Evaluation of the left-hand side dense matrix operand
825  RT B( serial( rhs.rhs_ ) ); // Evaluation of the right-hand side sparse matrix operand
826 
827  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
828  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
829  BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
830  BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
831  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
832  BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
833 
834  DMatSMatMultExpr::selectAddAssignKernel( ~lhs, A, B );
835  }
837  //**********************************************************************************************
838 
839  //**Addition assignment to dense matrices (kernel selection)************************************
850  template< typename MT3 // Type of the left-hand side target matrix
851  , typename MT4 // Type of the left-hand side matrix operand
852  , typename MT5 > // Type of the right-hand side matrix operand
853  static inline void selectAddAssignKernel( MT3& C, const MT4& A, const MT5& B )
854  {
855  if( C.rows() * C.columns() < DMATSMATMULT_THRESHOLD )
856  selectSmallAddAssignKernel( C, A, B );
857  else
858  selectLargeAddAssignKernel( C, A, B );
859  }
861  //**********************************************************************************************
862 
863  //**Optimized addition assignment to dense matrices (small matrices)****************************
877  template< typename MT3 // Type of the left-hand side target matrix
878  , typename MT4 // Type of the left-hand side matrix operand
879  , typename MT5 > // Type of the right-hand side matrix operand
880  static inline void selectSmallAddAssignKernel( MT3& C, const MT4& A, const MT5& B )
881  {
882  for( size_t j=0UL; j<B.rows(); ++j )
883  {
884  if( IsDiagonal_v<MT4> )
885  {
886  auto element( B.begin(j) );
887  const auto end( B.end(j) );
888 
889  for( ; element!=end; ++element ) {
890  C(j,element->index()) += A(j,j) * element->value();
891  }
892  }
893  else
894  {
895  const size_t iibegin( ( IsLower_v<MT4> )
896  ?( IsStrictlyLower_v<MT4> ? j+1UL : j )
897  :( 0UL ) );
898  const size_t iiend( ( IsUpper_v<MT4> )
899  ?( IsStrictlyUpper_v<MT4> ? j : j+1UL )
900  :( A.rows() ) );
901  BLAZE_INTERNAL_ASSERT( iibegin <= iiend, "Invalid loop indices detected" );
902 
903  for( size_t ii=iibegin; ii<iiend; ii+=8UL )
904  {
905  auto element( B.begin(j) );
906  const auto end( B.end(j) );
907  const size_t itmp( ( ii+8UL > iiend )?( iiend ):( ii+8UL ) );
908 
909  for( ; element!=end; ++element )
910  {
911  const size_t j1( element->index() );
912  const size_t ibegin( LOW ? max(j1,ii) : ii );
913  const size_t iend( UPP ? min(j1+1UL,itmp) : itmp );
914 
915  for( size_t i=ibegin; i<iend; ++i ) {
916  C(i,j1) += A(i,j) * element->value();
917  }
918  }
919  }
920  }
921  }
922  }
924  //**********************************************************************************************
925 
926  //**Optimized addition assignment to dense matrices (large matrices)****************************
940  template< typename MT3 // Type of the left-hand side target matrix
941  , typename MT4 // Type of the left-hand side matrix operand
942  , typename MT5 > // Type of the right-hand side matrix operand
943  static inline void selectLargeAddAssignKernel( MT3& C, const MT4& A, const MT5& B )
944  {
946 
947  const ForwardFunctor fwd;
948 
949  const OppositeType_t<MT5> tmp( serial( B ) );
950  addAssign( C, fwd( A * tmp ) );
951  }
953  //**********************************************************************************************
954 
955  //**Restructuring addition assignment***********************************************************
970  template< typename MT // Type of the target matrix
971  , bool SO > // Storage order of the target matrix
972  friend inline auto addAssign( Matrix<MT,SO>& lhs, const DMatSMatMultExpr& rhs )
973  -> EnableIf_t< CanExploitSymmetry_v<MT,MT1,MT2> >
974  {
976 
978 
979  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
980  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
981 
982  const ForwardFunctor fwd;
983 
984  if( IsSymmetric_v<MT1> && IsSymmetric_v<MT2> )
985  addAssign( ~lhs, fwd( trans( rhs.lhs_ ) * trans( rhs.rhs_ ) ) );
986  else if( IsSymmetric_v<MT1> )
987  addAssign( ~lhs, fwd( trans( rhs.lhs_ ) * rhs.rhs_ ) );
988  else
989  addAssign( ~lhs, fwd( rhs.lhs_ * trans( rhs.rhs_ ) ) );
990  }
992  //**********************************************************************************************
993 
994  //**Addition assignment to sparse matrices******************************************************
995  // No special implementation for the addition assignment to sparse matrices.
996  //**********************************************************************************************
997 
998  //**Subtraction assignment to dense matrices****************************************************
1011  template< typename MT // Type of the target dense matrix
1012  , bool SO > // Storage order of the target dense matrix
1013  friend inline auto subAssign( DenseMatrix<MT,SO>& lhs, const DMatSMatMultExpr& rhs )
1014  -> DisableIf_t< CanExploitSymmetry_v<MT,MT1,MT2> >
1015  {
1017 
1018  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
1019  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
1020 
1021  LT A( serial( rhs.lhs_ ) ); // Evaluation of the left-hand side dense matrix operand
1022  RT B( serial( rhs.rhs_ ) ); // Evaluation of the right-hand side sparse matrix operand
1023 
1024  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
1025  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
1026  BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
1027  BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
1028  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
1029  BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
1030 
1031  DMatSMatMultExpr::selectSubAssignKernel( ~lhs, A, B );
1032  }
1034  //**********************************************************************************************
1035 
1036  //**Subtraction assignment to dense matrices (kernel selection)*********************************
1047  template< typename MT3 // Type of the left-hand side target matrix
1048  , typename MT4 // Type of the left-hand side matrix operand
1049  , typename MT5 > // Type of the right-hand side matrix operand
1050  static inline void selectSubAssignKernel( MT3& C, const MT4& A, const MT5& B )
1051  {
1052  if( C.rows() * C.columns() < DMATSMATMULT_THRESHOLD )
1053  selectSmallSubAssignKernel( C, A, B );
1054  else
1055  selectLargeSubAssignKernel( C, A, B );
1056  }
1058  //**********************************************************************************************
1059 
1060  //**Optimized subtraction assignment to dense matrices (small matrices)*************************
1074  template< typename MT3 // Type of the left-hand side target matrix
1075  , typename MT4 // Type of the left-hand side matrix operand
1076  , typename MT5 > // Type of the right-hand side matrix operand
1077  static inline void selectSmallSubAssignKernel( MT3& C, const MT4& A, const MT5& B )
1078  {
1079  for( size_t j=0UL; j<B.rows(); ++j )
1080  {
1081  if( IsDiagonal_v<MT4> )
1082  {
1083  auto element( B.begin(j) );
1084  const auto end( B.end(j) );
1085 
1086  for( ; element!=end; ++element ) {
1087  C(j,element->index()) -= A(j,j) * element->value();
1088  }
1089  }
1090  else
1091  {
1092  const size_t iibegin( ( IsLower_v<MT4> )
1093  ?( IsStrictlyLower_v<MT4> ? j+1UL : j )
1094  :( 0UL ) );
1095  const size_t iiend( ( IsUpper_v<MT4> )
1096  ?( IsStrictlyUpper_v<MT4> ? j : j+1UL )
1097  :( A.rows() ) );
1098  BLAZE_INTERNAL_ASSERT( iibegin <= iiend, "Invalid loop indices detected" );
1099 
1100  for( size_t ii=iibegin; ii<iiend; ii+=8UL )
1101  {
1102  auto element( B.begin(j) );
1103  const auto end( B.end(j) );
1104  const size_t itmp( ( ii+8UL > iiend )?( iiend ):( ii+8UL ) );
1105 
1106  for( ; element!=end; ++element )
1107  {
1108  const size_t j1( element->index() );
1109  const size_t ibegin( LOW ? max(j1,ii) : ii );
1110  const size_t iend( UPP ? min(j1+1UL,itmp) : itmp );
1111 
1112  for( size_t i=ibegin; i<iend; ++i ) {
1113  C(i,j1) -= A(i,j) * element->value();
1114  }
1115  }
1116  }
1117  }
1118  }
1119  }
1121  //**********************************************************************************************
1122 
1123  //**Optimized subtraction assignment to dense matrices (large matrices)*************************
1137  template< typename MT3 // Type of the left-hand side target matrix
1138  , typename MT4 // Type of the left-hand side matrix operand
1139  , typename MT5 > // Type of the right-hand side matrix operand
1140  static inline void selectLargeSubAssignKernel( MT3& C, const MT4& A, const MT5& B )
1141  {
1143 
1144  const ForwardFunctor fwd;
1145 
1146  const OppositeType_t<MT5> tmp( serial( B ) );
1147  subAssign( C, fwd( A * tmp ) );
1148  }
1150  //**********************************************************************************************
1151 
1152  //**Restructuring subtraction assignment********************************************************
1167  template< typename MT // Type of the target matrix
1168  , bool SO > // Storage order of the target matrix
1169  friend inline auto subAssign( Matrix<MT,SO>& lhs, const DMatSMatMultExpr& rhs )
1170  -> EnableIf_t< CanExploitSymmetry_v<MT,MT1,MT2> >
1171  {
1173 
1175 
1176  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
1177  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
1178 
1179  const ForwardFunctor fwd;
1180 
1181  if( IsSymmetric_v<MT1> && IsSymmetric_v<MT2> )
1182  subAssign( ~lhs, fwd( trans( rhs.lhs_ ) * trans( rhs.rhs_ ) ) );
1183  else if( IsSymmetric_v<MT1> )
1184  subAssign( ~lhs, fwd( trans( rhs.lhs_ ) * rhs.rhs_ ) );
1185  else
1186  subAssign( ~lhs, fwd( rhs.lhs_ * trans( rhs.rhs_ ) ) );
1187  }
1189  //**********************************************************************************************
1190 
1191  //**Subtraction assignment to sparse matrices***************************************************
1192  // No special implementation for the subtraction assignment to sparse matrices.
1193  //**********************************************************************************************
1194 
1195  //**Schur product assignment to dense matrices**************************************************
1208  template< typename MT // Type of the target dense matrix
1209  , bool SO > // Storage order of the target dense matrix
1210  friend inline void schurAssign( DenseMatrix<MT,SO>& lhs, const DMatSMatMultExpr& rhs )
1211  {
1213 
1217 
1218  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
1219  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
1220 
1221  const ResultType tmp( serial( rhs ) );
1222  schurAssign( ~lhs, tmp );
1223  }
1225  //**********************************************************************************************
1226 
1227  //**Schur product assignment to sparse matrices*************************************************
1228  // No special implementation for the Schur product assignment to sparse matrices.
1229  //**********************************************************************************************
1230 
1231  //**Multiplication assignment to dense matrices*************************************************
1232  // No special implementation for the multiplication assignment to dense matrices.
1233  //**********************************************************************************************
1234 
1235  //**Multiplication assignment to sparse matrices************************************************
1236  // No special implementation for the multiplication assignment to sparse matrices.
1237  //**********************************************************************************************
1238 
1239  //**SMP assignment to dense matrices************************************************************
1254  template< typename MT // Type of the target dense matrix
1255  , bool SO > // Storage order of the target dense matrix
1256  friend inline auto smpAssign( DenseMatrix<MT,SO>& lhs, const DMatSMatMultExpr& rhs )
1257  -> EnableIf_t< IsEvaluationRequired_v<MT,MT1,MT2> >
1258  {
1260 
1261  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
1262  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
1263 
1264  LT A( rhs.lhs_ ); // Evaluation of the left-hand side dense matrix operand
1265  RT B( rhs.rhs_ ); // Evaluation of the right-hand side sparse matrix operand
1266 
1267  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
1268  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
1269  BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
1270  BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
1271  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
1272  BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
1273 
1274  smpAssign( ~lhs, A * B );
1275  }
1277  //**********************************************************************************************
1278 
1279  //**SMP assignment to sparse matrices***********************************************************
1294  template< typename MT // Type of the target sparse matrix
1295  , bool SO > // Storage order of the target sparse matrix
1296  friend inline auto smpAssign( SparseMatrix<MT,SO>& lhs, const DMatSMatMultExpr& rhs )
1297  -> EnableIf_t< IsEvaluationRequired_v<MT,MT1,MT2> >
1298  {
1300 
1301  using TmpType = If_t< SO, OppositeType, ResultType >;
1302 
1309 
1310  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
1311  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
1312 
1313  const ForwardFunctor fwd;
1314 
1315  const TmpType tmp( rhs );
1316  smpAssign( ~lhs, fwd( tmp ) );
1317  }
1319  //**********************************************************************************************
1320 
1321  //**Restructuring SMP assignment****************************************************************
1336  template< typename MT // Type of the target matrix
1337  , bool SO > // Storage order of the target matrix
1338  friend inline auto smpAssign( Matrix<MT,SO>& lhs, const DMatSMatMultExpr& rhs )
1339  -> EnableIf_t< CanExploitSymmetry_v<MT,MT1,MT2> >
1340  {
1342 
1344 
1345  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
1346  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
1347 
1348  const ForwardFunctor fwd;
1349 
1350  if( IsSymmetric_v<MT1> && IsSymmetric_v<MT2> )
1351  smpAssign( ~lhs, fwd( trans( rhs.lhs_ ) * trans( rhs.rhs_ ) ) );
1352  else if( IsSymmetric_v<MT1> )
1353  smpAssign( ~lhs, fwd( trans( rhs.lhs_ ) * rhs.rhs_ ) );
1354  else
1355  smpAssign( ~lhs, fwd( rhs.lhs_ * trans( rhs.rhs_ ) ) );
1356  }
1358  //**********************************************************************************************
1359 
1360  //**SMP addition assignment to dense matrices***************************************************
1375  template< typename MT // Type of the target dense matrix
1376  , bool SO > // Storage order of the target sparse matrix
1377  friend inline auto smpAddAssign( DenseMatrix<MT,SO>& lhs, const DMatSMatMultExpr& rhs )
1378  -> EnableIf_t< IsEvaluationRequired_v<MT,MT1,MT2> >
1379  {
1381 
1382  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
1383  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
1384 
1385  LT A( rhs.lhs_ ); // Evaluation of the left-hand side dense matrix operand
1386  RT B( rhs.rhs_ ); // Evaluation of the right-hand side sparse matrix operand
1387 
1388  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
1389  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
1390  BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
1391  BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
1392  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
1393  BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
1394 
1395  smpAddAssign( ~lhs, A * B );
1396  }
1398  //**********************************************************************************************
1399 
1400  //**Restructuring SMP addition assignment*******************************************************
1415  template< typename MT // Type of the target matrix
1416  , bool SO > // Storage order of the target matrix
1417  friend inline auto smpAddAssign( Matrix<MT,SO>& lhs, const DMatSMatMultExpr& rhs )
1418  -> EnableIf_t< CanExploitSymmetry_v<MT,MT1,MT2> >
1419  {
1421 
1423 
1424  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
1425  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
1426 
1427  const ForwardFunctor fwd;
1428 
1429  if( IsSymmetric_v<MT1> && IsSymmetric_v<MT2> )
1430  smpAddAssign( ~lhs, fwd( trans( rhs.lhs_ ) * trans( rhs.rhs_ ) ) );
1431  else if( IsSymmetric_v<MT1> )
1432  smpAddAssign( ~lhs, fwd( trans( rhs.lhs_ ) * rhs.rhs_ ) );
1433  else
1434  smpAddAssign( ~lhs, fwd( rhs.lhs_ * trans( rhs.rhs_ ) ) );
1435  }
1437  //**********************************************************************************************
1438 
1439  //**SMP addition assignment to sparse matrices**************************************************
1440  // No special implementation for the SMP addition assignment to sparse matrices.
1441  //**********************************************************************************************
1442 
1443  //**SMP subtraction assignment to dense matrices************************************************
1459  template< typename MT // Type of the target dense matrix
1460  , bool SO > // Storage order of the target sparse matrix
1461  friend inline auto smpSubAssign( DenseMatrix<MT,SO>& lhs, const DMatSMatMultExpr& rhs )
1462  -> EnableIf_t< IsEvaluationRequired_v<MT,MT1,MT2> >
1463  {
1465 
1466  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
1467  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
1468 
1469  LT A( rhs.lhs_ ); // Evaluation of the left-hand side dense matrix operand
1470  RT B( rhs.rhs_ ); // Evaluation of the right-hand side sparse matrix operand
1471 
1472  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
1473  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
1474  BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
1475  BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
1476  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
1477  BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
1478 
1479  smpSubAssign( ~lhs, A * B );
1480  }
1482  //**********************************************************************************************
1483 
1484  //**Restructuring SMP subtraction assignment****************************************************
1499  template< typename MT // Type of the target matrix
1500  , bool SO > // Storage order of the target matrix
1501  friend inline auto smpSubAssign( Matrix<MT,SO>& lhs, const DMatSMatMultExpr& rhs )
1502  -> EnableIf_t< CanExploitSymmetry_v<MT,MT1,MT2> >
1503  {
1505 
1507 
1508  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
1509  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
1510 
1511  const ForwardFunctor fwd;
1512 
1513  if( IsSymmetric_v<MT1> && IsSymmetric_v<MT2> )
1514  smpSubAssign( ~lhs, fwd( trans( rhs.lhs_ ) * trans( rhs.rhs_ ) ) );
1515  else if( IsSymmetric_v<MT1> )
1516  smpSubAssign( ~lhs, fwd( trans( rhs.lhs_ ) * rhs.rhs_ ) );
1517  else
1518  smpSubAssign( ~lhs, fwd( rhs.lhs_ * trans( rhs.rhs_ ) ) );
1519  }
1521  //**********************************************************************************************
1522 
1523  //**SMP subtraction assignment to sparse matrices***********************************************
1524  // No special implementation for the SMP subtraction assignment to sparse matrices.
1525  //**********************************************************************************************
1526 
1527  //**SMP Schur product assignment to dense matrices**********************************************
1540  template< typename MT // Type of the target dense matrix
1541  , bool SO > // Storage order of the target sparse matrix
1542  friend inline void smpSchurAssign( DenseMatrix<MT,SO>& lhs, const DMatSMatMultExpr& rhs )
1543  {
1545 
1549 
1550  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
1551  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
1552 
1553  const ResultType tmp( rhs );
1554  smpSchurAssign( ~lhs, tmp );
1555  }
1557  //**********************************************************************************************
1558 
1559  //**SMP Schur product assignment to sparse matrices*********************************************
1560  // No special implementation for the SMP Schur product assignment to sparse matrices.
1561  //**********************************************************************************************
1562 
1563  //**SMP multiplication assignment to dense matrices*********************************************
1564  // No special implementation for the SMP multiplication assignment to dense matrices.
1565  //**********************************************************************************************
1566 
1567  //**SMP multiplication assignment to sparse matrices********************************************
1568  // No special implementation for the SMP multiplication assignment to sparse matrices.
1569  //**********************************************************************************************
1570 
1571  //**Compile time checks*************************************************************************
1580  //**********************************************************************************************
1581 };
1582 //*************************************************************************************************
1583 
1584 
1585 
1586 
1587 //=================================================================================================
1588 //
1589 // GLOBAL BINARY ARITHMETIC OPERATORS
1590 //
1591 //=================================================================================================
1592 
1593 //*************************************************************************************************
1606 template< typename MT1 // Type of the left-hand side dense matrix
1607  , typename MT2 // Type of the right-hand side sparse matrix
1608  , DisableIf_t< ( IsIdentity_v<MT2> &&
1609  IsSame_v< ElementType_t<MT1>, ElementType_t<MT2> > ) ||
1610  IsZero_v<MT2> >* = nullptr >
1611 inline const DMatSMatMultExpr<MT1,MT2,false,false,false,false>
1612  dmatsmatmult( const DenseMatrix<MT1,false>& lhs, const SparseMatrix<MT2,false>& rhs )
1613 {
1615 
1616  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == (~rhs).rows(), "Invalid matrix sizes" );
1617 
1618  return DMatSMatMultExpr<MT1,MT2,false,false,false,false>( ~lhs, ~rhs );
1619 }
1621 //*************************************************************************************************
1622 
1623 
1624 //*************************************************************************************************
1638 template< typename MT1 // Type of the left-hand side dense matrix
1639  , typename MT2 // Type of the right-hand side sparse matrix
1640  , EnableIf_t< IsIdentity_v<MT2> &&
1641  IsSame_v< ElementType_t<MT1>, ElementType_t<MT2> > >* = nullptr >
1642 inline const MT1&
1643  dmatsmatmult( const DenseMatrix<MT1,false>& lhs, const SparseMatrix<MT2,false>& rhs )
1644 {
1646 
1647  UNUSED_PARAMETER( rhs );
1648 
1649  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == (~rhs).rows(), "Invalid matrix sizes" );
1650 
1651  return (~lhs);
1652 }
1654 //*************************************************************************************************
1655 
1656 
1657 //*************************************************************************************************
1670 template< typename MT1 // Type of the left-hand side dense matrix
1671  , typename MT2 // Type of the right-hand side sparse matrix
1672  , EnableIf_t< IsZero_v<MT2> >* = nullptr >
1673 inline decltype(auto)
1674  dmatsmatmult( const DenseMatrix<MT1,false>& lhs, const SparseMatrix<MT2,false>& rhs )
1675 {
1677 
1678  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == (~rhs).rows(), "Invalid matrix sizes" );
1679 
1680  using ReturnType = const MultTrait_t< ResultType_t<MT1>, ResultType_t<MT2> >;
1681 
1684 
1685  return ReturnType( (~lhs).rows(), (~rhs).columns() );
1686 }
1688 //*************************************************************************************************
1689 
1690 
1691 //*************************************************************************************************
1720 template< typename MT1 // Type of the left-hand side dense matrix
1721  , typename MT2 > // Type of the right-hand side sparse matrix
1722 inline decltype(auto)
1723  operator*( const DenseMatrix<MT1,false>& lhs, const SparseMatrix<MT2,false>& rhs )
1724 {
1726 
1727  if( (~lhs).columns() != (~rhs).rows() ) {
1728  BLAZE_THROW_INVALID_ARGUMENT( "Matrix sizes do not match" );
1729  }
1730 
1731  return dmatsmatmult( ~lhs, ~rhs );
1732 }
1733 //*************************************************************************************************
1734 
1735 
1736 
1737 
1738 //=================================================================================================
1739 //
1740 // GLOBAL FUNCTIONS
1741 //
1742 //=================================================================================================
1743 
1744 //*************************************************************************************************
1768 template< typename MT1 // Type of the left-hand side dense matrix
1769  , typename MT2 // Type of the right-hand side sparse matrix
1770  , bool SF // Symmetry flag
1771  , bool HF // Hermitian flag
1772  , bool LF // Lower flag
1773  , bool UF > // Upper flag
1774 inline decltype(auto) declsym( const DMatSMatMultExpr<MT1,MT2,SF,HF,LF,UF>& dm )
1775 {
1777 
1778  if( !isSquare( dm ) ) {
1779  BLAZE_THROW_INVALID_ARGUMENT( "Invalid symmetric matrix specification" );
1780  }
1781 
1782  using ReturnType = const DMatSMatMultExpr<MT1,MT2,true,HF,LF,UF>;
1783  return ReturnType( dm.leftOperand(), dm.rightOperand() );
1784 }
1786 //*************************************************************************************************
1787 
1788 
1789 //*************************************************************************************************
1813 template< typename MT1 // Type of the left-hand side dense matrix
1814  , typename MT2 // Type of the right-hand side sparse matrix
1815  , bool SF // Symmetry flag
1816  , bool HF // Hermitian flag
1817  , bool LF // Lower flag
1818  , bool UF > // Upper flag
1819 inline decltype(auto) declherm( const DMatSMatMultExpr<MT1,MT2,SF,HF,LF,UF>& dm )
1820 {
1822 
1823  if( !isSquare( dm ) ) {
1824  BLAZE_THROW_INVALID_ARGUMENT( "Invalid Hermitian matrix specification" );
1825  }
1826 
1827  using ReturnType = const DMatSMatMultExpr<MT1,MT2,SF,true,LF,UF>;
1828  return ReturnType( dm.leftOperand(), dm.rightOperand() );
1829 }
1831 //*************************************************************************************************
1832 
1833 
1834 //*************************************************************************************************
1858 template< typename MT1 // Type of the left-hand side dense matrix
1859  , typename MT2 // Type of the right-hand side sparse matrix
1860  , bool SF // Symmetry flag
1861  , bool HF // Hermitian flag
1862  , bool LF // Lower flag
1863  , bool UF > // Upper flag
1864 inline decltype(auto) decllow( const DMatSMatMultExpr<MT1,MT2,SF,HF,LF,UF>& dm )
1865 {
1867 
1868  if( !isSquare( dm ) ) {
1869  BLAZE_THROW_INVALID_ARGUMENT( "Invalid lower matrix specification" );
1870  }
1871 
1872  using ReturnType = const DMatSMatMultExpr<MT1,MT2,SF,HF,true,UF>;
1873  return ReturnType( dm.leftOperand(), dm.rightOperand() );
1874 }
1876 //*************************************************************************************************
1877 
1878 
1879 //*************************************************************************************************
1903 template< typename MT1 // Type of the left-hand side dense matrix
1904  , typename MT2 // Type of the right-hand side sparse matrix
1905  , bool SF // Symmetry flag
1906  , bool HF // Hermitian flag
1907  , bool LF // Lower flag
1908  , bool UF > // Upper flag
1909 inline decltype(auto) declupp( const DMatSMatMultExpr<MT1,MT2,SF,HF,LF,UF>& dm )
1910 {
1912 
1913  if( !isSquare( dm ) ) {
1914  BLAZE_THROW_INVALID_ARGUMENT( "Invalid upper matrix specification" );
1915  }
1916 
1917  using ReturnType = const DMatSMatMultExpr<MT1,MT2,SF,HF,LF,true>;
1918  return ReturnType( dm.leftOperand(), dm.rightOperand() );
1919 }
1921 //*************************************************************************************************
1922 
1923 
1924 //*************************************************************************************************
1948 template< typename MT1 // Type of the left-hand side dense matrix
1949  , typename MT2 // Type of the right-hand side sparse matrix
1950  , bool SF // Symmetry flag
1951  , bool HF // Hermitian flag
1952  , bool LF // Lower flag
1953  , bool UF > // Upper flag
1954 inline decltype(auto) decldiag( const DMatSMatMultExpr<MT1,MT2,SF,HF,LF,UF>& dm )
1955 {
1957 
1958  if( !isSquare( dm ) ) {
1959  BLAZE_THROW_INVALID_ARGUMENT( "Invalid diagonal matrix specification" );
1960  }
1961 
1962  using ReturnType = const DMatSMatMultExpr<MT1,MT2,SF,HF,true,true>;
1963  return ReturnType( dm.leftOperand(), dm.rightOperand() );
1964 }
1966 //*************************************************************************************************
1967 
1968 
1969 
1970 
1971 //=================================================================================================
1972 //
1973 // SIZE SPECIALIZATIONS
1974 //
1975 //=================================================================================================
1976 
1977 //*************************************************************************************************
1979 template< typename MT1, typename MT2, bool SF, bool HF, bool LF, bool UF >
1980 struct Size< DMatSMatMultExpr<MT1,MT2,SF,HF,LF,UF>, 0UL >
1981  : public Size<MT1,0UL>
1982 {};
1983 
1984 template< typename MT1, typename MT2, bool SF, bool HF, bool LF, bool UF >
1985 struct Size< DMatSMatMultExpr<MT1,MT2,SF,HF,LF,UF>, 1UL >
1986  : public Size<MT2,1UL>
1987 {};
1989 //*************************************************************************************************
1990 
1991 
1992 
1993 
1994 //=================================================================================================
1995 //
1996 // ISALIGNED SPECIALIZATIONS
1997 //
1998 //=================================================================================================
1999 
2000 //*************************************************************************************************
2002 template< typename MT1, typename MT2, bool SF, bool HF, bool LF, bool UF >
2003 struct IsAligned< DMatSMatMultExpr<MT1,MT2,SF,HF,LF,UF> >
2004  : public IsAligned<MT1>
2005 {};
2007 //*************************************************************************************************
2008 
2009 } // namespace blaze
2010 
2011 #endif
decltype(auto) subvector(Vector< VT, TF > &, RSAs...)
Creating a view on a specific subvector of the given vector.
Definition: Subvector.h:329
ElementType_t< ResultType > ElementType
Resulting element type.
Definition: DMatSMatMultExpr.h:245
#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.
decltype(auto) column(Matrix< MT, SO > &matrix, RCAs... args)
Creating a view on a specific column of the given matrix.
Definition: Column.h:133
Headerfile for the generic min algorithm.
Header file for the blaze::checked and blaze::unchecked instances.
Header file for the decldiag trait.
static constexpr bool smpAssignable
Compilation switch for the expression template assignment strategy.
Definition: DMatSMatMultExpr.h:267
decltype(auto) decldiag(const DenseMatrix< MT, SO > &dm)
Declares the given dense matrix expression dm as diagonal.
Definition: DMatDeclDiagExpr.h:975
bool canAlias(const T *alias) const noexcept
Returns whether the expression can alias with the given address alias.
Definition: DMatSMatMultExpr.h:399
size_t rows() const noexcept
Returns the current number of rows of the matrix.
Definition: DMatSMatMultExpr.h:357
Header file for the UNUSED_PARAMETER function template.
Header file for basic type definitions.
If_t< evaluateRight, const RT2, CT2 > RT
Type for the assignment of the right-hand side sparse matrix operand.
Definition: DMatSMatMultExpr.h:259
bool isAligned() const noexcept
Returns whether the operands of the expression are properly aligned in memory.
Definition: DMatSMatMultExpr.h:421
const ResultType CompositeType
Data type for composite expression templates.
Definition: DMatSMatMultExpr.h:247
typename If< Condition, T1, T2 >::Type If_t
Auxiliary alias declaration for the If class template.The If_t alias declaration provides a convenien...
Definition: If.h:109
Header file for the declherm trait.
ResultType_t< MT2 > RT2
Result type of the right-hand side sparse matrix expression.
Definition: DMatSMatMultExpr.h:134
typename T::ResultType ResultType_t
Alias declaration for nested ResultType type definitions.The ResultType_t alias declaration provides ...
Definition: Aliases.h:390
Header file for the serial shim.
Header file for the IsDiagonal type trait.
Base template for the DeclUppTrait class.
Definition: DeclUppTrait.h:134
#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.
Header file for the IsSame and IsStrictlySame type traits.
MT::Iterator begin(Matrix< MT, SO > &matrix, size_t i)
Returns an iterator to the first element of row/column i.
Definition: Matrix.h:372
void reset(const DiagonalProxy< MT > &proxy)
Resetting the represented element to the default initial values.
Definition: DiagonalProxy.h:591
static constexpr bool smpAssignable
Compilation flag for SMP assignments.
Definition: CompressedMatrix.h:3113
constexpr Unchecked unchecked
Global Unchecked instance.The blaze::unchecked instance is an optional token for the creation of view...
Definition: Check.h:138
Constraint on the data type.
OppositeType_t< ResultType > OppositeType
Result type with opposite storage order for expression template evaluations.
Definition: DMatSMatMultExpr.h:243
Header file for the IsIdentity type trait.
decltype(auto) declupp(const DenseMatrix< MT, SO > &dm)
Declares the given dense matrix expression dm as upper.
Definition: DMatDeclUppExpr.h:1002
Header file for the Computation base class.
Header file for the MatMatMultExpr base class.
Header file for the reset shim.
Constraints on the storage order of matrix types.
DMatSMatMultExpr(const MT1 &lhs, const MT2 &rhs) noexcept
Constructor for the DMatSMatMultExpr class.
Definition: DMatSMatMultExpr.h:277
Header file for the RequiresEvaluation type trait.
System settings for performance optimizations.
If_t< evaluateLeft, const RT1, CT1 > LT
Type for the assignment of the left-hand side dense matrix operand.
Definition: DMatSMatMultExpr.h:256
constexpr void UNUSED_PARAMETER(const Args &...)
Suppression of unused parameter warnings.
Definition: Unused.h:81
RightOperand rightOperand() const noexcept
Returns the right-hand side sparse matrix operand.
Definition: DMatSMatMultExpr.h:387
ElementType_t< RT2 > ET2
Element type of the right-hand side sparse matrix expression.
Definition: DMatSMatMultExpr.h:136
CompositeType_t< MT1 > CT1
Composite type of the left-hand side dense matrix expression.
Definition: DMatSMatMultExpr.h:137
constexpr size_t columns(const Matrix< MT, SO > &matrix) noexcept
Returns the current number of columns of the matrix.
Definition: Matrix.h:514
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:137
typename T::ElementType ElementType_t
Alias declaration for nested ElementType type definitions.The ElementType_t alias declaration provide...
Definition: Aliases.h:170
ReturnType operator()(size_t i, size_t j) const
2D-access to the matrix elements.
Definition: DMatSMatMultExpr.h:292
bool canSMPAssign() const noexcept
Returns whether the expression can be used in SMP assignments.
Definition: DMatSMatMultExpr.h:431
Constraint on the data type.
Constraint on the data type.
const ElementType ReturnType
Return type for expression template evaluations.
Definition: DMatSMatMultExpr.h:246
Headerfile for the generic max algorithm.
size_t columns() const noexcept
Returns the current number of columns of the matrix.
Definition: DMatSMatMultExpr.h:367
ElementType_t< RT1 > ET1
Element type of the left-hand side dense matrix expression.
Definition: DMatSMatMultExpr.h:135
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.
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
#define BLAZE_CONSTRAINT_MUST_BE_ZERO_TYPE(T)
Constraint on the data type.In case the given data type T is not a zero vector or matrix type...
Definition: Zero.h:61
Generic wrapper for the decllow() function.
Definition: DeclLow.h:58
decltype(auto) min(const DenseMatrix< MT1, SO1 > &lhs, const DenseMatrix< MT2, SO2 > &rhs)
Computes the componentwise minimum of the dense matrices lhs and rhs.
Definition: DMatDMatMapExpr.h:1147
LeftOperand leftOperand() const noexcept
Returns the left-hand side dense matrix operand.
Definition: DMatSMatMultExpr.h:377
Header file for the decllow trait.
#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.
decltype(auto) decllow(const DenseMatrix< MT, SO > &dm)
Declares the given dense matrix expression dm as lower.
Definition: DMatDeclLowExpr.h:1002
Header file for the IsLower type trait.
Header file for the IsAligned type trait.
static constexpr bool HERM
Flag for Hermitian matrices.
Definition: DMatSMatMultExpr.h:153
Generic wrapper for the null function.
Definition: Noop.h:59
Header file for the IsTriangular type trait.
Base template for the DeclSymTrait class.
Definition: DeclSymTrait.h:134
Constraints on the storage order of matrix types.
Header file for the exception macros of the math module.
decltype(auto) max(const DenseMatrix< MT1, SO1 > &lhs, const DenseMatrix< MT2, SO2 > &rhs)
Computes the componentwise maximum of the dense matrices lhs and rhs.
Definition: DMatDMatMapExpr.h:1179
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:438
static constexpr bool evaluateRight
Compilation switch for the composite type of the right-hand side sparse matrix expression.
Definition: DMatSMatMultExpr.h:148
Header file for the DeclDiag functor.
Constraint on the data type.
Header file for all forward declarations for expression class templates.
ResultType_t< MT1 > RT1
Result type of the left-hand side dense matrix expression.
Definition: DMatSMatMultExpr.h:133
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:103
ReturnType at(size_t i, size_t j) const
Checked access to the matrix elements.
Definition: DMatSMatMultExpr.h:341
typename T::OppositeType OppositeType_t
Alias declaration for nested OppositeType type definitions.The OppositeType_t alias declaration provi...
Definition: Aliases.h:270
Header file for the conjugate shim.
Header file for the declupp trait.
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
typename T::TransposeType TransposeType_t
Alias declaration for nested TransposeType type definitions.The TransposeType_t alias declaration pro...
Definition: Aliases.h:470
Header file for run time assertion macros.
Base template for the DeclHermTrait class.
Definition: DeclHermTrait.h:134
typename T::CompositeType CompositeType_t
Alias declaration for nested CompositeType type definitions.The CompositeType_t alias declaration pro...
Definition: Aliases.h:90
Base template for the MultTrait class.
Definition: MultTrait.h:146
Expression object for dense matrix-sparse matrix multiplications.The DMatSMatMultExpr class represent...
Definition: DMatSMatMultExpr.h:127
auto smpAddAssign(Matrix< MT1, SO1 > &lhs, const Matrix< MT2, SO2 > &rhs) -> EnableIf_t< IsDenseMatrix_v< MT1 > >
Default implementation of the SMP addition assignment of a matrix to a dense matrix.
Definition: DenseMatrix.h:131
decltype(auto) row(Matrix< MT, SO > &, RRAs...)
Creating a view on a specific row of the given matrix.
Definition: Row.h:133
Header file for the IsZero type trait.
Header file for the declsym trait.
#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
If_t< IsExpression_v< MT1 >, const MT1, const MT1 &> LeftOperand
Composite type of the left-hand side dense matrix expression.
Definition: DMatSMatMultExpr.h:250
decltype(auto) declsym(const DenseMatrix< MT, SO > &dm)
Declares the given dense matrix expression dm as symmetric.
Definition: DMatDeclSymExpr.h:1002
Header file for the isDefault shim.
auto smpAssign(Matrix< MT1, SO1 > &lhs, const Matrix< MT2, SO2 > &rhs) -> EnableIf_t< IsDenseMatrix_v< MT1 > >
Default implementation of the SMP assignment of a matrix to a dense matrix.
Definition: DenseMatrix.h:100
Constraint on the data type.
CompositeType_t< MT2 > CT2
Composite type of the right-hand side sparse matrix expression.
Definition: DMatSMatMultExpr.h:138
static constexpr bool evaluateLeft
Compilation switch for the composite type of the left-hand side dense matrix expression.
Definition: DMatSMatMultExpr.h:143
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:808
If_t< IsExpression_v< MT2 >, const MT2, const MT2 &> RightOperand
Composite type of the right-hand side sparse matrix expression.
Definition: DMatSMatMultExpr.h:253
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
auto smpSchurAssign(Matrix< MT1, SO1 > &lhs, const Matrix< MT2, SO2 > &rhs) -> EnableIf_t< IsDenseMatrix_v< MT1 > >
Default implementation of the SMP Schur product assignment of a matrix to dense matrix.
Definition: DenseMatrix.h:194
constexpr size_t rows(const Matrix< MT, SO > &matrix) noexcept
Returns the current number of rows of the matrix.
Definition: Matrix.h:498
#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
const Type & ReturnType
Return type for expression template evaluations.
Definition: CompressedMatrix.h:3081
decltype(auto) trans(const DenseMatrix< MT, SO > &dm)
Calculation of the transpose of the given dense matrix.
Definition: DMatTransExpr.h:765
static constexpr bool SYM
Flag for symmetric matrices.
Definition: DMatSMatMultExpr.h:152
Base template for the DeclLowTrait class.
Definition: DeclLowTrait.h:134
decltype(auto) declherm(const DenseMatrix< MT, SO > &dm)
Declares the given dense matrix expression dm as Hermitian.
Definition: DMatDeclHermExpr.h:1002
typename If_t< HERM, DeclHermTrait< MultTrait_t< RT1, RT2 > >, If_t< SYM, DeclSymTrait< MultTrait_t< RT1, RT2 > >, If_t< LOW, If_t< UPP, DeclDiagTrait< MultTrait_t< RT1, RT2 > >, DeclLowTrait< MultTrait_t< RT1, RT2 > > >, If_t< UPP, DeclUppTrait< MultTrait_t< RT1, RT2 > >, MultTrait< RT1, RT2 > > > > >::Type ResultType
Result type for expression template evaluations.
Definition: DMatSMatMultExpr.h:241
Header file for the IsComputation type trait class.
Header file for the IsBuiltin type trait.
auto smpSubAssign(Matrix< MT1, SO1 > &lhs, const Matrix< MT2, SO2 > &rhs) -> EnableIf_t< IsDenseMatrix_v< MT1 > >
Default implementation of the SMP subtraction assignment of a matrix to dense matrix.
Definition: DenseMatrix.h:162
Base class for all compute expression templates.The Computation class serves as a tag for all computa...
Definition: Computation.h:66
Header file for the IntegralConstant class template.
Generic wrapper for the decldiag() function.
Definition: DeclDiag.h:58
TransposeType_t< ResultType > TransposeType
Transpose type for expression template evaluations.
Definition: DMatSMatMultExpr.h:244
RightOperand rhs_
Right-hand side sparse matrix of the multiplication expression.
Definition: DMatSMatMultExpr.h:439
Header file for the DeclHerm functor.
bool isDefault(const DiagonalProxy< MT > &proxy)
Returns whether the represented element is in default state.
Definition: DiagonalProxy.h:631
Header file for the IsUpper type trait.
typename DisableIf< Condition, T >::Type DisableIf_t
Auxiliary type for the DisableIf class template.The DisableIf_t alias declaration provides a convenie...
Definition: DisableIf.h:138
static constexpr bool simdEnabled
Compilation switch for the expression template evaluation strategy.
Definition: DMatSMatMultExpr.h:264
decltype(auto) conj(const DenseMatrix< MT, SO > &dm)
Returns a matrix containing the complex conjugate of each single element of dm.
Definition: DMatMapExpr.h:1326
Constraint on the data type.
Generic wrapper for the declsym() function.
Definition: DeclSym.h:58
Base template for the DeclDiagTrait class.
Definition: DeclDiagTrait.h:134
static constexpr bool UPP
Flag for upper matrices.
Definition: DMatSMatMultExpr.h:155
static constexpr bool LOW
Flag for lower matrices.
Definition: DMatSMatMultExpr.h:154
bool isSquare(const Matrix< MT, SO > &matrix) noexcept
Checks if the given matrix is a square matrix.
Definition: Matrix.h:951
Header file for the IsResizable type trait.
Header file for the Size type trait.
#define BLAZE_CONSTRAINT_MUST_NOT_BE_ZERO_TYPE(T)
Constraint on the data type.In case the given data type T is a zero vector or matrix type...
Definition: Zero.h:81
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 DeclSym functor.
bool isAliased(const T *alias) const noexcept
Returns whether the expression is aliased with the given address alias.
Definition: DMatSMatMultExpr.h:411
#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 IsExpression type trait class.
Header file for the function trace functionality.
LeftOperand lhs_
Left-hand side dense matrix of the multiplication expression.
Definition: DMatSMatMultExpr.h:438