All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
DMatDVecMultExpr.h
Go to the documentation of this file.
1 //=================================================================================================
33 //=================================================================================================
34 
35 #ifndef _BLAZE_MATH_EXPRESSIONS_DMATDVECMULTEXPR_H_
36 #define _BLAZE_MATH_EXPRESSIONS_DMATDVECMULTEXPR_H_
37 
38 
39 //*************************************************************************************************
40 // Includes
41 //*************************************************************************************************
42 
43 #include <stdexcept>
44 #include <boost/cast.hpp>
56 #include <blaze/math/Intrinsics.h>
57 #include <blaze/math/shims/Reset.h>
70 #include <blaze/system/BLAS.h>
72 #include <blaze/util/Assert.h>
73 #include <blaze/util/Complex.h>
79 #include <blaze/util/DisableIf.h>
80 #include <blaze/util/EnableIf.h>
82 #include <blaze/util/SelectType.h>
83 #include <blaze/util/Types.h>
89 
90 
91 namespace blaze {
92 
93 //=================================================================================================
94 //
95 // CLASS DMATDVECMULTEXPR
96 //
97 //=================================================================================================
98 
99 //*************************************************************************************************
106 template< typename MT // Type of the left-hand side dense matrix
107  , typename VT > // Type of the right-hand side dense vector
108 class DMatDVecMultExpr : public DenseVector< DMatDVecMultExpr<MT,VT>, false >
109  , private MatVecMultExpr
110  , private Computation
111 {
112  private:
113  //**Type definitions****************************************************************************
114  typedef typename MT::ResultType MRT;
115  typedef typename VT::ResultType VRT;
116  typedef typename MRT::ElementType MET;
117  typedef typename VRT::ElementType VET;
118  typedef typename MT::CompositeType MCT;
119  typedef typename VT::CompositeType VCT;
120  //**********************************************************************************************
121 
122  //**********************************************************************************************
124  enum { evaluateMatrix = ( IsComputation<MT>::value && IsSame<MET,VET>::value &&
126  //**********************************************************************************************
127 
128  //**********************************************************************************************
130  enum { evaluateVector = IsComputation<VT>::value || RequiresEvaluation<VT>::value };
131  //**********************************************************************************************
132 
133  //**********************************************************************************************
135 
139  template< typename T1 >
140  struct UseSMPAssign {
141  enum { value = ( evaluateMatrix || evaluateVector ) };
142  };
144  //**********************************************************************************************
145 
146  //**********************************************************************************************
148 
152  template< typename T1, typename T2, typename T3 >
153  struct UseSinglePrecisionKernel {
154  enum { value = BLAZE_BLAS_MODE &&
155  T1::vectorizable && T2::vectorizable && T3::vectorizable &&
159  };
161  //**********************************************************************************************
162 
163  //**********************************************************************************************
165 
169  template< typename T1, typename T2, typename T3 >
170  struct UseDoublePrecisionKernel {
171  enum { value = BLAZE_BLAS_MODE &&
172  T1::vectorizable && T2::vectorizable && T3::vectorizable &&
176  };
178  //**********************************************************************************************
179 
180  //**********************************************************************************************
182 
186  template< typename T1, typename T2, typename T3 >
187  struct UseSinglePrecisionComplexKernel {
188  typedef complex<float> Type;
189  enum { value = BLAZE_BLAS_MODE &&
190  T1::vectorizable && T2::vectorizable && T3::vectorizable &&
194  };
196  //**********************************************************************************************
197 
198  //**********************************************************************************************
200 
204  template< typename T1, typename T2, typename T3 >
205  struct UseDoublePrecisionComplexKernel {
206  typedef complex<double> Type;
207  enum { value = BLAZE_BLAS_MODE &&
208  T1::vectorizable && T2::vectorizable && T3::vectorizable &&
212  };
214  //**********************************************************************************************
215 
216  //**********************************************************************************************
218 
221  template< typename T1, typename T2, typename T3 >
222  struct UseDefaultKernel {
223  enum { value = !BLAZE_BLAS_MODE || ( !UseSinglePrecisionKernel<T1,T2,T3>::value &&
224  !UseDoublePrecisionKernel<T1,T2,T3>::value &&
225  !UseSinglePrecisionComplexKernel<T1,T2,T3>::value &&
226  !UseDoublePrecisionComplexKernel<T1,T2,T3>::value ) };
227  };
229  //**********************************************************************************************
230 
231  //**********************************************************************************************
233 
237  template< typename T1, typename T2, typename T3 >
238  struct UseVectorizedDefaultKernel {
239  enum { value = T1::vectorizable && T2::vectorizable && T3::vectorizable &&
244  };
246  //**********************************************************************************************
247 
248  public:
249  //**Type definitions****************************************************************************
255  typedef const ElementType ReturnType;
256  typedef const ResultType CompositeType;
257 
259  typedef typename SelectType< IsExpression<MT>::value, const MT, const MT& >::Type LeftOperand;
260 
262  typedef typename SelectType< IsExpression<VT>::value, const VT, const VT& >::Type RightOperand;
263 
266 
269  //**********************************************************************************************
270 
271  //**Compilation flags***************************************************************************
273  enum { vectorizable = MT::vectorizable && VT::vectorizable &&
277 
279  enum { smpAssignable = !evaluateMatrix && MT::smpAssignable &&
280  !evaluateVector && VT::smpAssignable };
281  //**********************************************************************************************
282 
283  //**Constructor*********************************************************************************
289  explicit inline DMatDVecMultExpr( const MT& mat, const VT& vec )
290  : mat_( mat ) // Left-hand side dense matrix of the multiplication expression
291  , vec_( vec ) // Right-hand side dense vector of the multiplication expression
292  , end_( ( (mat.columns()-1UL) & size_t(-2) ) + 1UL ) // End of the unrolled calculation loop
293  {
294  BLAZE_INTERNAL_ASSERT( mat_.columns() == vec_.size(), "Invalid matrix and vector sizes" );
295  }
296  //**********************************************************************************************
297 
298  //**Subscript operator**************************************************************************
304  inline ReturnType operator[]( size_t index ) const {
305  BLAZE_INTERNAL_ASSERT( index < mat_.rows(), "Invalid vector access index" );
306 
307  ElementType res;
308 
309  if( mat_.columns() != 0UL ) {
310  res = mat_(index,0UL) * vec_[0UL];
311  for( size_t j=1UL; j<end_; j+=2UL ) {
312  res += mat_(index,j) * vec_[j] + mat_(index,j+1UL) * vec_[j+1UL];
313  }
314  if( end_ < mat_.columns() ) {
315  res += mat_(index,end_) * vec_[end_];
316  }
317  }
318  else {
319  reset( res );
320  }
321 
322  return res;
323  }
324  //**********************************************************************************************
325 
326  //**Size function*******************************************************************************
331  inline size_t size() const {
332  return mat_.rows();
333  }
334  //**********************************************************************************************
335 
336  //**Left operand access*************************************************************************
341  inline LeftOperand leftOperand() const {
342  return mat_;
343  }
344  //**********************************************************************************************
345 
346  //**Right operand access************************************************************************
351  inline RightOperand rightOperand() const {
352  return vec_;
353  }
354  //**********************************************************************************************
355 
356  //**********************************************************************************************
362  template< typename T >
363  inline bool canAlias( const T* alias ) const {
364  return ( mat_.isAliased( alias ) || vec_.isAliased( alias ) );
365  }
366  //**********************************************************************************************
367 
368  //**********************************************************************************************
374  template< typename T >
375  inline bool isAliased( const T* alias ) const {
376  return ( mat_.isAliased( alias ) || vec_.isAliased( alias ) );
377  }
378  //**********************************************************************************************
379 
380  //**********************************************************************************************
385  inline bool isAligned() const {
386  return mat_.isAligned() && vec_.isAligned();
387  }
388  //**********************************************************************************************
389 
390  //**********************************************************************************************
395  inline bool canSMPAssign() const {
396  return ( !BLAZE_BLAS_IS_PARALLEL ||
397  ( IsComputation<MT>::value && !evaluateMatrix ) ||
398  ( mat_.rows() * mat_.columns() < DMATDVECMULT_THRESHOLD ) ) &&
400  }
401  //**********************************************************************************************
402 
403  private:
404  //**Member variables****************************************************************************
407  const size_t end_;
408  //**********************************************************************************************
409 
410  //**BLAS kernel (single precision)**************************************************************
411 #if BLAZE_BLAS_MODE
412 
427  template< typename VT1 // Type of the left-hand side target vector
428  , typename MT1 // Type of the left-hand side matrix operand
429  , typename VT2 > // Type of the right-hand side vector operand
430  static inline void sgemv( VT1& y, const MT1& A, const VT2& x, float alpha, float beta )
431  {
432  using boost::numeric_cast;
433 
437 
438  const int M ( numeric_cast<int>( A.rows() ) );
439  const int N ( numeric_cast<int>( A.columns() ) );
440  const int lda( numeric_cast<int>( A.spacing() ) );
441 
442  cblas_sgemv( CblasRowMajor, CblasNoTrans, M, N, alpha,
443  A.data(), lda, x.data(), 1, beta, y.data(), 1 );
444  }
446 #endif
447  //**********************************************************************************************
448 
449  //**BLAS kernel (double precision)**************************************************************
450 #if BLAZE_BLAS_MODE
451 
466  template< typename VT1 // Type of the left-hand side target vector
467  , typename MT1 // Type of the left-hand side matrix operand
468  , typename VT2 > // Type of the right-hand side vector operand
469  static inline void dgemv( VT1& y, const MT1& A, const VT2& x, double alpha, double beta )
470  {
471  using boost::numeric_cast;
472 
476 
477  const int M ( numeric_cast<int>( A.rows() ) );
478  const int N ( numeric_cast<int>( A.columns() ) );
479  const int lda( numeric_cast<int>( A.spacing() ) );
480 
481  cblas_dgemv( CblasRowMajor, CblasNoTrans, M, N, alpha,
482  A.data(), lda, x.data(), 1, beta, y.data(), 1 );
483  }
485 #endif
486  //**********************************************************************************************
487 
488  //**BLAS kernel (single precision complex)******************************************************
489 #if BLAZE_BLAS_MODE
490 
505  template< typename VT1 // Type of the left-hand side target vector
506  , typename MT1 // Type of the left-hand side matrix operand
507  , typename VT2 > // Type of the right-hand side vector operand
508  static inline void cgemv( VT1& y, const MT1& A, const VT2& x,
509  complex<float> alpha, complex<float> beta )
510  {
511  using boost::numeric_cast;
512 
516  BLAZE_CONSTRAINT_MUST_BE_FLOAT_TYPE ( typename VT1::ElementType::value_type );
517  BLAZE_CONSTRAINT_MUST_BE_FLOAT_TYPE ( typename MT1::ElementType::value_type );
518  BLAZE_CONSTRAINT_MUST_BE_FLOAT_TYPE ( typename VT2::ElementType::value_type );
519 
520  const int M ( numeric_cast<int>( A.rows() ) );
521  const int N ( numeric_cast<int>( A.columns() ) );
522  const int lda( numeric_cast<int>( A.spacing() ) );
523 
524  cblas_cgemv( CblasRowMajor, CblasNoTrans, M, N, &alpha,
525  A.data(), lda, x.data(), 1, &beta, y.data(), 1 );
526  }
528 #endif
529  //**********************************************************************************************
530 
531  //**BLAS kernel (double precision complex)******************************************************
532 #if BLAZE_BLAS_MODE
533 
548  template< typename VT1 // Type of the left-hand side target vector
549  , typename MT1 // Type of the left-hand side matrix operand
550  , typename VT2 > // Type of the right-hand side vector operand
551  static inline void zgemv( VT1& y, const MT1& A, const VT2& x,
552  complex<double> alpha, complex<double> beta )
553  {
554  using boost::numeric_cast;
555 
559  BLAZE_CONSTRAINT_MUST_BE_DOUBLE_TYPE ( typename VT1::ElementType::value_type );
560  BLAZE_CONSTRAINT_MUST_BE_DOUBLE_TYPE ( typename MT1::ElementType::value_type );
561  BLAZE_CONSTRAINT_MUST_BE_DOUBLE_TYPE ( typename VT2::ElementType::value_type );
562 
563  const int M ( numeric_cast<int>( A.rows() ) );
564  const int N ( numeric_cast<int>( A.columns() ) );
565  const int lda( numeric_cast<int>( A.spacing() ) );
566 
567  cblas_zgemv( CblasRowMajor, CblasNoTrans, M, N, &alpha,
568  A.data(), lda, x.data(), 1, &beta, y.data(), 1 );
569  }
571 #endif
572  //**********************************************************************************************
573 
574  //**Assignment to dense vectors*****************************************************************
587  template< typename VT1 > // Type of the target dense vector
588  friend inline void assign( DenseVector<VT1,false>& lhs, const DMatDVecMultExpr& rhs )
589  {
591 
592  BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
593 
594  if( rhs.mat_.rows() == 0UL ) {
595  return;
596  }
597  else if( rhs.mat_.columns() == 0UL ) {
598  reset( ~lhs );
599  return;
600  }
601 
602  LT A( serial( rhs.mat_ ) ); // Evaluation of the left-hand side dense matrix operand
603  RT x( serial( rhs.vec_ ) ); // Evaluation of the right-hand side dense vector operand
604 
605  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.mat_.rows() , "Invalid number of rows" );
606  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.mat_.columns(), "Invalid number of columns" );
607  BLAZE_INTERNAL_ASSERT( x.size() == rhs.vec_.size() , "Invalid vector size" );
608  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).size() , "Invalid vector size" );
609 
610  DMatDVecMultExpr::selectAssignKernel( ~lhs, A, x );
611  }
613  //**********************************************************************************************
614 
615  //**Assignment to dense vectors (kernel selection)**********************************************
626  template< typename VT1 // Type of the left-hand side target vector
627  , typename MT1 // Type of the left-hand side matrix operand
628  , typename VT2 > // Type of the right-hand side vector operand
629  static inline void selectAssignKernel( VT1& y, const MT1& A, const VT2& x )
630  {
631  if( ( IsComputation<MT>::value && !evaluateMatrix ) ||
632  ( A.rows() * A.columns() < DMATDVECMULT_THRESHOLD ) )
633  DMatDVecMultExpr::selectDefaultAssignKernel( y, A, x );
634  else
635  DMatDVecMultExpr::selectBlasAssignKernel( y, A, x );
636  }
638  //**********************************************************************************************
639 
640  //**Default assignment to dense vectors*********************************************************
654  template< typename VT1 // Type of the left-hand side target vector
655  , typename MT1 // Type of the left-hand side matrix operand
656  , typename VT2 > // Type of the right-hand side vector operand
657  static inline typename DisableIf< UseVectorizedDefaultKernel<VT1,MT1,VT2> >::Type
658  selectDefaultAssignKernel( VT1& y, const MT1& A, const VT2& x )
659  {
660  y.assign( A * x );
661  }
663  //**********************************************************************************************
664 
665  //**Vectorized default assignment to dense vectors**********************************************
679  template< typename VT1 // Type of the left-hand side target vector
680  , typename MT1 // Type of the left-hand side matrix operand
681  , typename VT2 > // Type of the right-hand side vector operand
682  static inline typename EnableIf< UseVectorizedDefaultKernel<VT1,MT1,VT2> >::Type
683  selectDefaultAssignKernel( VT1& y, const MT1& A, const VT2& x )
684  {
685  typedef IntrinsicTrait<ElementType> IT;
686 
687  const size_t M( A.rows() );
688  const size_t N( A.columns() );
689 
690  size_t i( 0UL );
691 
692  for( ; (i+8UL) <= M; i+=8UL ) {
693  IntrinsicType xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7, xmm8;
694  for( size_t j=0UL; j<N; j+=IT::size ) {
695  const IntrinsicType x1( x.load(j) );
696  xmm1 = xmm1 + A.load(i ,j) * x1;
697  xmm2 = xmm2 + A.load(i+1UL,j) * x1;
698  xmm3 = xmm3 + A.load(i+2UL,j) * x1;
699  xmm4 = xmm4 + A.load(i+3UL,j) * x1;
700  xmm5 = xmm5 + A.load(i+4UL,j) * x1;
701  xmm6 = xmm6 + A.load(i+5UL,j) * x1;
702  xmm7 = xmm7 + A.load(i+6UL,j) * x1;
703  xmm8 = xmm8 + A.load(i+7UL,j) * x1;
704  }
705  y[i ] = sum( xmm1 );
706  y[i+1UL] = sum( xmm2 );
707  y[i+2UL] = sum( xmm3 );
708  y[i+3UL] = sum( xmm4 );
709  y[i+4UL] = sum( xmm5 );
710  y[i+5UL] = sum( xmm6 );
711  y[i+6UL] = sum( xmm7 );
712  y[i+7UL] = sum( xmm8 );
713  }
714  for( ; (i+4UL) <= M; i+=4UL ) {
715  IntrinsicType xmm1, xmm2, xmm3, xmm4;
716  for( size_t j=0UL; j<N; j+=IT::size ) {
717  const IntrinsicType x1( x.load(j) );
718  xmm1 = xmm1 + A.load(i ,j) * x1;
719  xmm2 = xmm2 + A.load(i+1UL,j) * x1;
720  xmm3 = xmm3 + A.load(i+2UL,j) * x1;
721  xmm4 = xmm4 + A.load(i+3UL,j) * x1;
722  }
723  y[i ] = sum( xmm1 );
724  y[i+1UL] = sum( xmm2 );
725  y[i+2UL] = sum( xmm3 );
726  y[i+3UL] = sum( xmm4 );
727  }
728  for( ; (i+3UL) <= M; i+=3UL ) {
729  IntrinsicType xmm1, xmm2, xmm3;
730  for( size_t j=0UL; j<N; j+=IT::size ) {
731  const IntrinsicType x1( x.load(j) );
732  xmm1 = xmm1 + A.load(i ,j) * x1;
733  xmm2 = xmm2 + A.load(i+1UL,j) * x1;
734  xmm3 = xmm3 + A.load(i+2UL,j) * x1;
735  }
736  y[i ] = sum( xmm1 );
737  y[i+1UL] = sum( xmm2 );
738  y[i+2UL] = sum( xmm3 );
739  }
740  for( ; (i+2UL) <= M; i+=2UL ) {
741  IntrinsicType xmm1, xmm2;
742  for( size_t j=0UL; j<N; j+=IT::size ) {
743  const IntrinsicType x1( x.load(j) );
744  xmm1 = xmm1 + A.load(i ,j) * x1;
745  xmm2 = xmm2 + A.load(i+1UL,j) * x1;
746  }
747  y[i ] = sum( xmm1 );
748  y[i+1UL] = sum( xmm2 );
749  }
750  if( i < M ) {
751  IntrinsicType xmm1;
752  for( size_t j=0UL; j<N; j+=IT::size ) {
753  xmm1 = xmm1 + A.load(i,j) * x.load(j);
754  }
755  y[i] = sum( xmm1 );
756  }
757  }
759  //**********************************************************************************************
760 
761  //**BLAS-based assignment to dense vectors (default)********************************************
775  template< typename VT1 // Type of the left-hand side target vector
776  , typename MT1 // Type of the left-hand side matrix operand
777  , typename VT2 > // Type of the right-hand side vector operand
778  static inline typename EnableIf< UseDefaultKernel<VT1,MT1,VT2> >::Type
779  selectBlasAssignKernel( VT1& y, const MT1& A, const VT2& x )
780  {
781  selectDefaultAssignKernel( y, A, x );
782  }
784  //**********************************************************************************************
785 
786  //**BLAS-based assignment to dense vectors (single precision)***********************************
787 #if BLAZE_BLAS_MODE
788 
801  template< typename VT1 // Type of the left-hand side target vector
802  , typename MT1 // Type of the left-hand side matrix operand
803  , typename VT2 > // Type of the right-hand side vector operand
804  static inline typename EnableIf< UseSinglePrecisionKernel<VT1,MT1,VT2> >::Type
805  selectBlasAssignKernel( VT1& y, const MT1& A, const VT2& x )
806  {
807  sgemv( y, A, x, 1.0F, 0.0F );
808  }
810 #endif
811  //**********************************************************************************************
812 
813  //**BLAS-based assignment to dense vectors (double precision)***********************************
814 #if BLAZE_BLAS_MODE
815 
828  template< typename VT1 // Type of the left-hand side target vector
829  , typename MT1 // Type of the left-hand side matrix operand
830  , typename VT2 > // Type of the right-hand side vector operand
831  static inline typename EnableIf< UseDoublePrecisionKernel<VT1,MT1,VT2> >::Type
832  selectBlasAssignKernel( VT1& y, const MT1& A, const VT2& x )
833  {
834  dgemv( y, A, x, 1.0, 0.0 );
835  }
837 #endif
838  //**********************************************************************************************
839 
840  //**BLAS-based assignment to dense vectors (single precision complex)***************************
841 #if BLAZE_BLAS_MODE
842 
855  template< typename VT1 // Type of the left-hand side target vector
856  , typename MT1 // Type of the left-hand side matrix operand
857  , typename VT2 > // Type of the right-hand side vector operand
858  static inline typename EnableIf< UseSinglePrecisionComplexKernel<VT1,MT1,VT2> >::Type
859  selectBlasAssignKernel( VT1& y, const MT1& A, const VT2& x )
860  {
861  cgemv( y, A, x, complex<float>( 1.0F, 0.0F ), complex<float>( 0.0F, 0.0F ) );
862  }
864 #endif
865  //**********************************************************************************************
866 
867  //**BLAS-based assignment to dense vectors (double precision complex)***************************
868 #if BLAZE_BLAS_MODE
869 
882  template< typename VT1 // Type of the left-hand side target vector
883  , typename MT1 // Type of the left-hand side matrix operand
884  , typename VT2 > // Type of the right-hand side vector operand
885  static inline typename EnableIf< UseDoublePrecisionComplexKernel<VT1,MT1,VT2> >::Type
886  selectBlasAssignKernel( VT1& y, const MT1& A, const VT2& x )
887  {
888  zgemv( y, A, x, complex<double>( 1.0, 0.0 ), complex<double>( 0.0, 0.0 ) );
889  }
891 #endif
892  //**********************************************************************************************
893 
894  //**Assignment to sparse vectors****************************************************************
907  template< typename VT1 > // Type of the target sparse vector
908  friend inline void assign( SparseVector<VT1,false>& lhs, const DMatDVecMultExpr& rhs )
909  {
911 
915 
916  BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
917 
918  const ResultType tmp( serial( rhs ) );
919  assign( ~lhs, tmp );
920  }
922  //**********************************************************************************************
923 
924  //**Addition assignment to dense vectors********************************************************
937  template< typename VT1 > // Type of the target dense vector
938  friend inline void addAssign( DenseVector<VT1,false>& lhs, const DMatDVecMultExpr& rhs )
939  {
941 
942  BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
943 
944  if( rhs.mat_.rows() == 0UL || rhs.mat_.columns() == 0UL ) {
945  return;
946  }
947 
948  LT A( serial( rhs.mat_ ) ); // Evaluation of the left-hand side dense matrix operand
949  RT x( serial( rhs.vec_ ) ); // Evaluation of the right-hand side dense vector operand
950 
951  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.mat_.rows() , "Invalid number of rows" );
952  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.mat_.columns(), "Invalid number of columns" );
953  BLAZE_INTERNAL_ASSERT( x.size() == rhs.vec_.size() , "Invalid vector size" );
954  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).size() , "Invalid vector size" );
955 
956  DMatDVecMultExpr::selectAddAssignKernel( ~lhs, A, x );
957  }
959  //**********************************************************************************************
960 
961  //**Addition assignment to dense vectors (kernel selection)*************************************
972  template< typename VT1 // Type of the left-hand side target vector
973  , typename MT1 // Type of the left-hand side matrix operand
974  , typename VT2 > // Type of the right-hand side vector operand
975  static inline void selectAddAssignKernel( VT1& y, const MT1& A, const VT2& x )
976  {
977  if( ( IsComputation<MT>::value && !evaluateMatrix ) ||
978  ( A.rows() * A.columns() < DMATDVECMULT_THRESHOLD ) )
979  DMatDVecMultExpr::selectDefaultAddAssignKernel( y, A, x );
980  else
981  DMatDVecMultExpr::selectBlasAddAssignKernel( y, A, x );
982  }
984  //**********************************************************************************************
985 
986  //**Default addition assignment to dense vectors************************************************
1000  template< typename VT1 // Type of the left-hand side target vector
1001  , typename MT1 // Type of the left-hand side matrix operand
1002  , typename VT2 > // Type of the right-hand side vector operand
1003  static inline typename DisableIf< UseVectorizedDefaultKernel<VT1,MT1,VT2> >::Type
1004  selectDefaultAddAssignKernel( VT1& y, const MT1& A, const VT2& x )
1005  {
1006  y.addAssign( A * x );
1007  }
1009  //**********************************************************************************************
1010 
1011  //**Vectorized default addition assignment to dense vectors*************************************
1025  template< typename VT1 // Type of the left-hand side target vector
1026  , typename MT1 // Type of the left-hand side matrix operand
1027  , typename VT2 > // Type of the right-hand side vector operand
1028  static inline typename EnableIf< UseVectorizedDefaultKernel<VT1,MT1,VT2> >::Type
1029  selectDefaultAddAssignKernel( VT1& y, const MT1& A, const VT2& x )
1030  {
1031  typedef IntrinsicTrait<ElementType> IT;
1032 
1033  const size_t M( A.rows() );
1034  const size_t N( A.columns() );
1035 
1036  size_t i( 0UL );
1037 
1038  for( ; (i+8UL) <= M; i+=8UL ) {
1039  IntrinsicType xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7, xmm8;
1040  for( size_t j=0UL; j<N; j+=IT::size ) {
1041  const IntrinsicType x1( x.load(j) );
1042  xmm1 = xmm1 + A.load(i ,j) * x1;
1043  xmm2 = xmm2 + A.load(i+1UL,j) * x1;
1044  xmm3 = xmm3 + A.load(i+2UL,j) * x1;
1045  xmm4 = xmm4 + A.load(i+3UL,j) * x1;
1046  xmm5 = xmm5 + A.load(i+4UL,j) * x1;
1047  xmm6 = xmm6 + A.load(i+5UL,j) * x1;
1048  xmm7 = xmm7 + A.load(i+6UL,j) * x1;
1049  xmm8 = xmm8 + A.load(i+7UL,j) * x1;
1050  }
1051  y[i ] += sum( xmm1 );
1052  y[i+1UL] += sum( xmm2 );
1053  y[i+2UL] += sum( xmm3 );
1054  y[i+3UL] += sum( xmm4 );
1055  y[i+4UL] += sum( xmm5 );
1056  y[i+5UL] += sum( xmm6 );
1057  y[i+6UL] += sum( xmm7 );
1058  y[i+7UL] += sum( xmm8 );
1059  }
1060  for( ; (i+4UL) <= M; i+=4UL ) {
1061  IntrinsicType xmm1, xmm2, xmm3, xmm4;
1062  for( size_t j=0UL; j<N; j+=IT::size ) {
1063  const IntrinsicType x1( x.load(j) );
1064  xmm1 = xmm1 + A.load(i ,j) * x1;
1065  xmm2 = xmm2 + A.load(i+1UL,j) * x1;
1066  xmm3 = xmm3 + A.load(i+2UL,j) * x1;
1067  xmm4 = xmm4 + A.load(i+3UL,j) * x1;
1068  }
1069  y[i ] += sum( xmm1 );
1070  y[i+1UL] += sum( xmm2 );
1071  y[i+2UL] += sum( xmm3 );
1072  y[i+3UL] += sum( xmm4 );
1073  }
1074  for( ; (i+3UL) <= M; i+=3UL ) {
1075  IntrinsicType xmm1, xmm2, xmm3;
1076  for( size_t j=0UL; j<N; j+=IT::size ) {
1077  const IntrinsicType x1( x.load(j) );
1078  xmm1 = xmm1 + A.load(i ,j) * x1;
1079  xmm2 = xmm2 + A.load(i+1UL,j) * x1;
1080  xmm3 = xmm3 + A.load(i+2UL,j) * x1;
1081  }
1082  y[i ] += sum( xmm1 );
1083  y[i+1UL] += sum( xmm2 );
1084  y[i+2UL] += sum( xmm3 );
1085  }
1086  for( ; (i+2UL) <= M; i+=2UL ) {
1087  IntrinsicType xmm1, xmm2;
1088  for( size_t j=0UL; j<N; j+=IT::size ) {
1089  const IntrinsicType x1( x.load(j) );
1090  xmm1 = xmm1 + A.load(i ,j) * x1;
1091  xmm2 = xmm2 + A.load(i+1UL,j) * x1;
1092  }
1093  y[i ] += sum( xmm1 );
1094  y[i+1UL] += sum( xmm2 );
1095  }
1096  if( i < M ) {
1097  IntrinsicType xmm1;
1098  for( size_t j=0UL; j<N; j+=IT::size ) {
1099  xmm1 = xmm1 + A.load(i,j) * x.load(j);
1100  }
1101  y[i] += sum( xmm1 );
1102  }
1103  }
1105  //**********************************************************************************************
1106 
1107  //**BLAS-based addition assignment to dense vectors (default)***********************************
1121  template< typename VT1 // Type of the left-hand side target vector
1122  , typename MT1 // Type of the left-hand side matrix operand
1123  , typename VT2 > // Type of the right-hand side vector operand
1124  static inline typename EnableIf< UseDefaultKernel<VT1,MT1,VT2> >::Type
1125  selectBlasAddAssignKernel( VT1& y, const MT1& A, const VT2& x )
1126  {
1127  selectDefaultAddAssignKernel( y, A, x );
1128  }
1130  //**********************************************************************************************
1131 
1132  //**BLAS-based addition assignment to dense vectors (single precision)**************************
1133 #if BLAZE_BLAS_MODE
1134 
1147  template< typename VT1 // Type of the left-hand side target vector
1148  , typename MT1 // Type of the left-hand side matrix operand
1149  , typename VT2 > // Type of the right-hand side vector operand
1150  static inline typename EnableIf< UseSinglePrecisionKernel<VT1,MT1,VT2> >::Type
1151  selectBlasAddAssignKernel( VT1& y, const MT1& A, const VT2& x )
1152  {
1153  sgemv( y, A, x, 1.0F, 1.0F );
1154  }
1156 #endif
1157  //**********************************************************************************************
1158 
1159  //**BLAS-based addition assignment to dense vectors (double precision)**************************
1160 #if BLAZE_BLAS_MODE
1161 
1174  template< typename VT1 // Type of the left-hand side target vector
1175  , typename MT1 // Type of the left-hand side matrix operand
1176  , typename VT2 > // Type of the right-hand side vector operand
1177  static inline typename EnableIf< UseDoublePrecisionKernel<VT1,MT1,VT2> >::Type
1178  selectBlasAddAssignKernel( VT1& y, const MT1& A, const VT2& x )
1179  {
1180  dgemv( y, A, x, 1.0, 1.0 );
1181  }
1183 #endif
1184  //**********************************************************************************************
1185 
1186  //**BLAS-based addition assignment to dense vectors (single precision complex)******************
1187 #if BLAZE_BLAS_MODE
1188 
1201  template< typename VT1 // Type of the left-hand side target vector
1202  , typename MT1 // Type of the left-hand side matrix operand
1203  , typename VT2 > // Type of the right-hand side vector operand
1204  static inline typename EnableIf< UseSinglePrecisionComplexKernel<VT1,MT1,VT2> >::Type
1205  selectBlasAddAssignKernel( VT1& y, const MT1& A, const VT2& x )
1206  {
1207  cgemv( y, A, x, complex<float>( 1.0F, 0.0F ), complex<float>( 1.0F, 0.0F ) );
1208  }
1210 #endif
1211  //**********************************************************************************************
1212 
1213  //**BLAS-based addition assignment to dense vectors (double precision complex)******************
1214 #if BLAZE_BLAS_MODE
1215 
1228  template< typename VT1 // Type of the left-hand side target vector
1229  , typename MT1 // Type of the left-hand side matrix operand
1230  , typename VT2 > // Type of the right-hand side vector operand
1231  static inline typename EnableIf< UseDoublePrecisionComplexKernel<VT1,MT1,VT2> >::Type
1232  selectBlasAddAssignKernel( VT1& y, const MT1& A, const VT2& x )
1233  {
1234  zgemv( y, A, x, complex<double>( 1.0, 0.0 ), complex<double>( 1.0, 0.0 ) );
1235  }
1237 #endif
1238  //**********************************************************************************************
1239 
1240  //**Addition assignment to sparse vectors*******************************************************
1241  // No special implementation for the addition assignment to sparse vectors.
1242  //**********************************************************************************************
1243 
1244  //**Subtraction assignment to dense vectors*****************************************************
1257  template< typename VT1 > // Type of the target dense vector
1258  friend inline void subAssign( DenseVector<VT1,false>& lhs, const DMatDVecMultExpr& rhs )
1259  {
1261 
1262  BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
1263 
1264  if( rhs.mat_.rows() == 0UL || rhs.mat_.columns() == 0UL ) {
1265  return;
1266  }
1267 
1268  LT A( serial( rhs.mat_ ) ); // Evaluation of the left-hand side dense matrix operand
1269  RT x( serial( rhs.vec_ ) ); // Evaluation of the right-hand side dense vector operand
1270 
1271  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.mat_.rows() , "Invalid number of rows" );
1272  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.mat_.columns(), "Invalid number of columns" );
1273  BLAZE_INTERNAL_ASSERT( x.size() == rhs.vec_.size() , "Invalid vector size" );
1274  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).size() , "Invalid vector size" );
1275 
1276  DMatDVecMultExpr::selectSubAssignKernel( ~lhs, A, x );
1277  }
1279  //**********************************************************************************************
1280 
1281  //**Subtraction assignment to dense vectors (kernel selection)**********************************
1292  template< typename VT1 // Type of the left-hand side target vector
1293  , typename MT1 // Type of the left-hand side matrix operand
1294  , typename VT2 > // Type of the right-hand side vector operand
1295  static inline void selectSubAssignKernel( VT1& y, const MT1& A, const VT2& x )
1296  {
1297  if( ( IsComputation<MT>::value && !evaluateMatrix ) ||
1298  ( A.rows() * A.columns() < DMATDVECMULT_THRESHOLD ) )
1299  DMatDVecMultExpr::selectDefaultSubAssignKernel( y, A, x );
1300  else
1301  DMatDVecMultExpr::selectBlasSubAssignKernel( y, A, x );
1302  }
1304  //**********************************************************************************************
1305 
1306  //**Default subtraction assignment to dense vectors*********************************************
1320  template< typename VT1 // Type of the left-hand side target vector
1321  , typename MT1 // Type of the left-hand side matrix operand
1322  , typename VT2 > // Type of the right-hand side vector operand
1323  static inline typename DisableIf< UseVectorizedDefaultKernel<VT1,MT1,VT2> >::Type
1324  selectDefaultSubAssignKernel( VT1& y, const MT1& A, const VT2& x )
1325  {
1326  y.subAssign( A * x );
1327  }
1329  //**********************************************************************************************
1330 
1331  //**Vectorized default subtraction assignment to dense vectors**********************************
1345  template< typename VT1 // Type of the left-hand side target vector
1346  , typename MT1 // Type of the left-hand side matrix operand
1347  , typename VT2 > // Type of the right-hand side vector operand
1348  static inline typename EnableIf< UseVectorizedDefaultKernel<VT1,MT1,VT2> >::Type
1349  selectDefaultSubAssignKernel( VT1& y, const MT1& A, const VT2& x )
1350  {
1351  typedef IntrinsicTrait<ElementType> IT;
1352 
1353  const size_t M( A.rows() );
1354  const size_t N( A.columns() );
1355 
1356  size_t i( 0UL );
1357 
1358  for( ; (i+8UL) <= M; i+=8UL ) {
1359  IntrinsicType xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7, xmm8;
1360  for( size_t j=0UL; j<N; j+=IT::size ) {
1361  const IntrinsicType x1( x.load(j) );
1362  xmm1 = xmm1 + A.load(i ,j) * x1;
1363  xmm2 = xmm2 + A.load(i+1UL,j) * x1;
1364  xmm3 = xmm3 + A.load(i+2UL,j) * x1;
1365  xmm4 = xmm4 + A.load(i+3UL,j) * x1;
1366  xmm5 = xmm5 + A.load(i+4UL,j) * x1;
1367  xmm6 = xmm6 + A.load(i+5UL,j) * x1;
1368  xmm7 = xmm7 + A.load(i+6UL,j) * x1;
1369  xmm8 = xmm8 + A.load(i+7UL,j) * x1;
1370  }
1371  y[i ] -= sum( xmm1 );
1372  y[i+1UL] -= sum( xmm2 );
1373  y[i+2UL] -= sum( xmm3 );
1374  y[i+3UL] -= sum( xmm4 );
1375  y[i+4UL] -= sum( xmm5 );
1376  y[i+5UL] -= sum( xmm6 );
1377  y[i+6UL] -= sum( xmm7 );
1378  y[i+7UL] -= sum( xmm8 );
1379  }
1380  for( ; (i+4UL) <= M; i+=4UL ) {
1381  IntrinsicType xmm1, xmm2, xmm3, xmm4;
1382  for( size_t j=0UL; j<N; j+=IT::size ) {
1383  const IntrinsicType x1( x.load(j) );
1384  xmm1 = xmm1 + A.load(i ,j) * x1;
1385  xmm2 = xmm2 + A.load(i+1UL,j) * x1;
1386  xmm3 = xmm3 + A.load(i+2UL,j) * x1;
1387  xmm4 = xmm4 + A.load(i+3UL,j) * x1;
1388  }
1389  y[i ] -= sum( xmm1 );
1390  y[i+1UL] -= sum( xmm2 );
1391  y[i+2UL] -= sum( xmm3 );
1392  y[i+3UL] -= sum( xmm4 );
1393  }
1394  for( ; (i+3UL) <= M; i+=3UL ) {
1395  IntrinsicType xmm1, xmm2, xmm3;
1396  for( size_t j=0UL; j<N; j+=IT::size ) {
1397  const IntrinsicType x1( x.load(j) );
1398  xmm1 = xmm1 + A.load(i ,j) * x1;
1399  xmm2 = xmm2 + A.load(i+1UL,j) * x1;
1400  xmm3 = xmm3 + A.load(i+2UL,j) * x1;
1401  }
1402  y[i ] -= sum( xmm1 );
1403  y[i+1UL] -= sum( xmm2 );
1404  y[i+2UL] -= sum( xmm3 );
1405  }
1406  for( ; (i+2UL) <= M; i+=2UL ) {
1407  IntrinsicType xmm1, xmm2;
1408  for( size_t j=0UL; j<N; j+=IT::size ) {
1409  const IntrinsicType x1( x.load(j) );
1410  xmm1 = xmm1 + A.load(i ,j) * x1;
1411  xmm2 = xmm2 + A.load(i+1UL,j) * x1;
1412  }
1413  y[i ] -= sum( xmm1 );
1414  y[i+1UL] -= sum( xmm2 );
1415  }
1416  if( i < M ) {
1417  IntrinsicType xmm1;
1418  for( size_t j=0UL; j<N; j+=IT::size ) {
1419  xmm1 = xmm1 + A.load(i,j) * x.load(j);
1420  }
1421  y[i] -= sum( xmm1 );
1422  }
1423  }
1425  //**********************************************************************************************
1426 
1427  //**BLAS-based subtraction assignment to dense vectors (default)********************************
1441  template< typename VT1 // Type of the left-hand side target vector
1442  , typename MT1 // Type of the left-hand side matrix operand
1443  , typename VT2 > // Type of the right-hand side vector operand
1444  static inline typename EnableIf< UseDefaultKernel<VT1,MT1,VT2> >::Type
1445  selectBlasSubAssignKernel( VT1& y, const MT1& A, const VT2& x )
1446  {
1447  selectDefaultSubAssignKernel( y, A, x );
1448  }
1450  //**********************************************************************************************
1451 
1452  //**BLAS-based subtraction assignment to dense vectors (single precision)***********************
1453 #if BLAZE_BLAS_MODE
1454 
1467  template< typename VT1 // Type of the left-hand side target vector
1468  , typename MT1 // Type of the left-hand side matrix operand
1469  , typename VT2 > // Type of the right-hand side vector operand
1470  static inline typename EnableIf< UseSinglePrecisionKernel<VT1,MT1,VT2> >::Type
1471  selectBlasSubAssignKernel( VT1& y, const MT1& A, const VT2& x )
1472  {
1473  sgemv( y, A, x, -1.0F, 1.0F );
1474  }
1476 #endif
1477  //**********************************************************************************************
1478 
1479  //**BLAS-based subtraction assignment to dense vectors (double precision)***********************
1480 #if BLAZE_BLAS_MODE
1481 
1494  template< typename VT1 // Type of the left-hand side target vector
1495  , typename MT1 // Type of the left-hand side matrix operand
1496  , typename VT2 > // Type of the right-hand side vector operand
1497  static inline typename EnableIf< UseDoublePrecisionKernel<VT1,MT1,VT2> >::Type
1498  selectBlasSubAssignKernel( VT1& y, const MT1& A, const VT2& x )
1499  {
1500  dgemv( y, A, x, -1.0, 1.0 );
1501  }
1503 #endif
1504  //**********************************************************************************************
1505 
1506  //**BLAS-based subtraction assignment to dense vectors (single precision complex)***************
1507 #if BLAZE_BLAS_MODE
1508 
1521  template< typename VT1 // Type of the left-hand side target vector
1522  , typename MT1 // Type of the left-hand side matrix operand
1523  , typename VT2 > // Type of the right-hand side vector operand
1524  static inline typename EnableIf< UseSinglePrecisionComplexKernel<VT1,MT1,VT2> >::Type
1525  selectBlasSubAssignKernel( VT1& y, const MT1& A, const VT2& x )
1526  {
1527  cgemv( y, A, x, complex<float>( -1.0F, 0.0F ), complex<float>( 1.0F, 0.0F ) );
1528  }
1530 #endif
1531  //**********************************************************************************************
1532 
1533  //**BLAS-based subtraction assignment to dense vectors (double precision complex)***************
1534 #if BLAZE_BLAS_MODE
1535 
1548  template< typename VT1 // Type of the left-hand side target vector
1549  , typename MT1 // Type of the left-hand side matrix operand
1550  , typename VT2 > // Type of the right-hand side vector operand
1551  static inline typename EnableIf< UseDoublePrecisionComplexKernel<VT1,MT1,VT2> >::Type
1552  selectBlasSubAssignKernel( VT1& y, const MT1& A, const VT2& x )
1553  {
1554  zgemv( y, A, x, complex<double>( -1.0, 0.0 ), complex<double>( 1.0, 0.0 ) );
1555  }
1557 #endif
1558  //**********************************************************************************************
1559 
1560  //**Subtraction assignment to sparse vectors****************************************************
1561  // No special implementation for the subtraction assignment to sparse vectors.
1562  //**********************************************************************************************
1563 
1564  //**Multiplication assignment to dense vectors**************************************************
1577  template< typename VT1 > // Type of the target dense vector
1578  friend inline void multAssign( DenseVector<VT1,false>& lhs, const DMatDVecMultExpr& rhs )
1579  {
1581 
1585 
1586  BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
1587 
1588  const ResultType tmp( serial( rhs ) );
1589  multAssign( ~lhs, tmp );
1590  }
1592  //**********************************************************************************************
1593 
1594  //**Multiplication assignment to sparse vectors*************************************************
1595  // No special implementation for the multiplication assignment to sparse vectors.
1596  //**********************************************************************************************
1597 
1598  //**SMP assignment to dense vectors*************************************************************
1613  template< typename VT1 > // Type of the target dense vector
1614  friend inline typename EnableIf< UseSMPAssign<VT1> >::Type
1615  smpAssign( DenseVector<VT1,false>& lhs, const DMatDVecMultExpr& rhs )
1616  {
1618 
1619  BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
1620 
1621  if( rhs.mat_.rows() == 0UL ) {
1622  return;
1623  }
1624  else if( rhs.mat_.columns() == 0UL ) {
1625  reset( ~lhs );
1626  return;
1627  }
1628 
1629  LT A( rhs.mat_ ); // Evaluation of the left-hand side dense matrix operand
1630  RT x( rhs.vec_ ); // Evaluation of the right-hand side dense vector operand
1631 
1632  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.mat_.rows() , "Invalid number of rows" );
1633  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.mat_.columns(), "Invalid number of columns" );
1634  BLAZE_INTERNAL_ASSERT( x.size() == rhs.vec_.size() , "Invalid vector size" );
1635  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).size() , "Invalid vector size" );
1636 
1637  smpAssign( ~lhs, A * x );
1638  }
1640  //**********************************************************************************************
1641 
1642  //**SMP assignment to sparse vectors************************************************************
1657  template< typename VT1 > // Type of the target sparse vector
1658  friend inline typename EnableIf< UseSMPAssign<VT1> >::Type
1659  smpAssign( SparseVector<VT1,false>& lhs, const DMatDVecMultExpr& rhs )
1660  {
1662 
1666 
1667  BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
1668 
1669  const ResultType tmp( rhs );
1670  smpAssign( ~lhs, tmp );
1671  }
1673  //**********************************************************************************************
1674 
1675  //**SMP addition assignment to dense vectors****************************************************
1690  template< typename VT1 > // Type of the target dense vector
1691  friend inline typename EnableIf< UseSMPAssign<VT1> >::Type
1692  smpAddAssign( DenseVector<VT1,false>& lhs, const DMatDVecMultExpr& rhs )
1693  {
1695 
1696  BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
1697 
1698  if( rhs.mat_.rows() == 0UL || rhs.mat_.columns() == 0UL ) {
1699  return;
1700  }
1701 
1702  LT A( rhs.mat_ ); // Evaluation of the left-hand side dense matrix operand
1703  RT x( rhs.vec_ ); // Evaluation of the right-hand side dense vector operand
1704 
1705  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.mat_.rows() , "Invalid number of rows" );
1706  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.mat_.columns(), "Invalid number of columns" );
1707  BLAZE_INTERNAL_ASSERT( x.size() == rhs.vec_.size() , "Invalid vector size" );
1708  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).size() , "Invalid vector size" );
1709 
1710  smpAddAssign( ~lhs, A * x );
1711  }
1713  //**********************************************************************************************
1714 
1715  //**SMP addition assignment to sparse vectors***************************************************
1716  // No special implementation for the SMP addition assignment to sparse vectors.
1717  //**********************************************************************************************
1718 
1719  //**SMP subtraction assignment to dense vectors*************************************************
1734  template< typename VT1 > // Type of the target dense vector
1735  friend inline typename EnableIf< UseSMPAssign<VT1> >::Type
1736  smpSubAssign( DenseVector<VT1,false>& lhs, const DMatDVecMultExpr& rhs )
1737  {
1739 
1740  BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
1741 
1742  if( rhs.mat_.rows() == 0UL || rhs.mat_.columns() == 0UL ) {
1743  return;
1744  }
1745 
1746  LT A( rhs.mat_ ); // Evaluation of the left-hand side dense matrix operand
1747  RT x( rhs.vec_ ); // Evaluation of the right-hand side dense vector operand
1748 
1749  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.mat_.rows() , "Invalid number of rows" );
1750  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.mat_.columns(), "Invalid number of columns" );
1751  BLAZE_INTERNAL_ASSERT( x.size() == rhs.vec_.size() , "Invalid vector size" );
1752  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).size() , "Invalid vector size" );
1753 
1754  smpSubAssign( ~lhs, A * x );
1755  }
1757  //**********************************************************************************************
1758 
1759  //**SMP subtraction assignment to sparse vectors************************************************
1760  // No special implementation for the SMP subtraction assignment to sparse vectors.
1761  //**********************************************************************************************
1762 
1763  //**SMP multiplication assignment to dense vectors**********************************************
1778  template< typename VT1 > // Type of the target dense vector
1779  friend inline typename EnableIf< UseSMPAssign<VT1> >::Type
1780  smpMultAssign( DenseVector<VT1,false>& lhs, const DMatDVecMultExpr& rhs )
1781  {
1783 
1787 
1788  BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
1789 
1790  const ResultType tmp( rhs );
1791  smpMultAssign( ~lhs, tmp );
1792  }
1794  //**********************************************************************************************
1795 
1796  //**SMP multiplication assignment to sparse vectors*********************************************
1797  // No special implementation for the SMP multiplication assignment to sparse vectors.
1798  //**********************************************************************************************
1799 
1800  //**Compile time checks*************************************************************************
1808  //**********************************************************************************************
1809 };
1810 //*************************************************************************************************
1811 
1812 
1813 
1814 
1815 //=================================================================================================
1816 //
1817 // DVECSCALARMULTEXPR SPECIALIZATION
1818 //
1819 //=================================================================================================
1820 
1821 //*************************************************************************************************
1829 template< typename MT // Type of the left-hand side dense matrix
1830  , typename VT // Type of the right-hand side dense vector
1831  , typename ST > // Type of the scalar value
1832 class DVecScalarMultExpr< DMatDVecMultExpr<MT,VT>, ST, false >
1833  : public DenseVector< DVecScalarMultExpr< DMatDVecMultExpr<MT,VT>, ST, false >, false >
1834  , private VecScalarMultExpr
1835  , private Computation
1836 {
1837  private:
1838  //**Type definitions****************************************************************************
1839  typedef DMatDVecMultExpr<MT,VT> MVM;
1840  typedef typename MVM::ResultType RES;
1841  typedef typename MT::ResultType MRT;
1842  typedef typename VT::ResultType VRT;
1843  typedef typename MRT::ElementType MET;
1844  typedef typename VRT::ElementType VET;
1845  typedef typename MT::CompositeType MCT;
1846  typedef typename VT::CompositeType VCT;
1847  //**********************************************************************************************
1848 
1849  //**********************************************************************************************
1851  enum { evaluateMatrix = ( IsComputation<MT>::value && IsSame<MET,VET>::value &&
1852  IsBlasCompatible<MET>::value ) || RequiresEvaluation<MT>::value };
1853  //**********************************************************************************************
1854 
1855  //**********************************************************************************************
1857  enum { evaluateVector = IsComputation<VT>::value || RequiresEvaluation<MT>::value };
1858  //**********************************************************************************************
1859 
1860  //**********************************************************************************************
1862 
1865  template< typename T1 >
1866  struct UseSMPAssign {
1867  enum { value = ( evaluateMatrix || evaluateVector ) };
1868  };
1869  //**********************************************************************************************
1870 
1871  //**********************************************************************************************
1873 
1876  template< typename T1, typename T2, typename T3, typename T4 >
1877  struct UseSinglePrecisionKernel {
1878  enum { value = BLAZE_BLAS_MODE &&
1879  T1::vectorizable && T2::vectorizable && T3::vectorizable &&
1880  IsFloat<typename T1::ElementType>::value &&
1881  IsFloat<typename T2::ElementType>::value &&
1882  IsFloat<typename T3::ElementType>::value &&
1883  !IsComplex<T4>::value };
1884  };
1885  //**********************************************************************************************
1886 
1887  //**********************************************************************************************
1889 
1892  template< typename T1, typename T2, typename T3, typename T4 >
1893  struct UseDoublePrecisionKernel {
1894  enum { value = BLAZE_BLAS_MODE &&
1895  T1::vectorizable && T2::vectorizable && T3::vectorizable &&
1896  IsDouble<typename T1::ElementType>::value &&
1897  IsDouble<typename T2::ElementType>::value &&
1898  IsDouble<typename T3::ElementType>::value &&
1899  !IsComplex<T4>::value };
1900  };
1901  //**********************************************************************************************
1902 
1903  //**********************************************************************************************
1905 
1908  template< typename T1, typename T2, typename T3 >
1909  struct UseSinglePrecisionComplexKernel {
1910  typedef complex<float> Type;
1911  enum { value = BLAZE_BLAS_MODE &&
1912  T1::vectorizable && T2::vectorizable && T3::vectorizable &&
1913  IsSame<typename T1::ElementType,Type>::value &&
1914  IsSame<typename T2::ElementType,Type>::value &&
1915  IsSame<typename T3::ElementType,Type>::value };
1916  };
1917  //**********************************************************************************************
1918 
1919  //**********************************************************************************************
1921 
1924  template< typename T1, typename T2, typename T3 >
1925  struct UseDoublePrecisionComplexKernel {
1926  typedef complex<double> Type;
1927  enum { value = BLAZE_BLAS_MODE &&
1928  T1::vectorizable && T2::vectorizable && T3::vectorizable &&
1929  IsSame<typename T1::ElementType,Type>::value &&
1930  IsSame<typename T2::ElementType,Type>::value &&
1931  IsSame<typename T3::ElementType,Type>::value };
1932  };
1933  //**********************************************************************************************
1934 
1935  //**********************************************************************************************
1937 
1939  template< typename T1, typename T2, typename T3, typename T4 >
1940  struct UseDefaultKernel {
1941  enum { value = !BLAZE_BLAS_MODE || ( !UseSinglePrecisionKernel<T1,T2,T3,T4>::value &&
1942  !UseDoublePrecisionKernel<T1,T2,T3,T4>::value &&
1943  !UseSinglePrecisionComplexKernel<T1,T2,T3>::value &&
1944  !UseDoublePrecisionComplexKernel<T1,T2,T3>::value ) };
1945  };
1946  //**********************************************************************************************
1947 
1948  //**********************************************************************************************
1950 
1953  template< typename T1, typename T2, typename T3, typename T4 >
1954  struct UseVectorizedDefaultKernel {
1955  enum { value = T1::vectorizable && T2::vectorizable && T3::vectorizable &&
1956  IsSame<typename T1::ElementType,typename T2::ElementType>::value &&
1957  IsSame<typename T1::ElementType,typename T3::ElementType>::value &&
1958  IsSame<typename T1::ElementType,T4>::value &&
1959  IntrinsicTrait<typename T1::ElementType>::addition &&
1960  IntrinsicTrait<typename T1::ElementType>::multiplication };
1961  };
1962  //**********************************************************************************************
1963 
1964  public:
1965  //**Type definitions****************************************************************************
1966  typedef DVecScalarMultExpr<MVM,ST,false> This;
1967  typedef typename MultTrait<RES,ST>::Type ResultType;
1968  typedef typename ResultType::TransposeType TransposeType;
1969  typedef typename ResultType::ElementType ElementType;
1970  typedef typename IntrinsicTrait<ElementType>::Type IntrinsicType;
1971  typedef const ElementType ReturnType;
1972  typedef const ResultType CompositeType;
1973 
1975  typedef const DMatDVecMultExpr<MT,VT> LeftOperand;
1976 
1978  typedef ST RightOperand;
1979 
1981  typedef typename SelectType< evaluateMatrix, const MRT, MCT >::Type LT;
1982 
1984  typedef typename SelectType< evaluateVector, const VRT, VCT >::Type RT;
1985  //**********************************************************************************************
1986 
1987  //**Compilation flags***************************************************************************
1989  enum { vectorizable = MT::vectorizable && VT::vectorizable &&
1990  IsSame<MET,VET>::value &&
1991  IsSame<MET,ST>::value &&
1992  IntrinsicTrait<MET>::addition &&
1993  IntrinsicTrait<MET>::multiplication };
1994 
1996  enum { smpAssignable = !evaluateMatrix && MT::smpAssignable &&
1997  !evaluateVector && VT::smpAssignable };
1998  //**********************************************************************************************
1999 
2000  //**Constructor*********************************************************************************
2006  explicit inline DVecScalarMultExpr( const MVM& vector, ST scalar )
2007  : vector_( vector ) // Left-hand side dense vector of the multiplication expression
2008  , scalar_( scalar ) // Right-hand side scalar of the multiplication expression
2009  {}
2010  //**********************************************************************************************
2011 
2012  //**Subscript operator**************************************************************************
2018  inline ReturnType operator[]( size_t index ) const {
2019  BLAZE_INTERNAL_ASSERT( index < vector_.size(), "Invalid vector access index" );
2020  return vector_[index] * scalar_;
2021  }
2022  //**********************************************************************************************
2023 
2024  //**Size function*******************************************************************************
2029  inline size_t size() const {
2030  return vector_.size();
2031  }
2032  //**********************************************************************************************
2033 
2034  //**Left operand access*************************************************************************
2039  inline LeftOperand leftOperand() const {
2040  return vector_;
2041  }
2042  //**********************************************************************************************
2043 
2044  //**Right operand access************************************************************************
2049  inline RightOperand rightOperand() const {
2050  return scalar_;
2051  }
2052  //**********************************************************************************************
2053 
2054  //**********************************************************************************************
2060  template< typename T >
2061  inline bool canAlias( const T* alias ) const {
2062  return vector_.canAlias( alias );
2063  }
2064  //**********************************************************************************************
2065 
2066  //**********************************************************************************************
2072  template< typename T >
2073  inline bool isAliased( const T* alias ) const {
2074  return vector_.isAliased( alias );
2075  }
2076  //**********************************************************************************************
2077 
2078  //**********************************************************************************************
2083  inline bool isAligned() const {
2084  return vector_.isAligned();
2085  }
2086  //**********************************************************************************************
2087 
2088  //**********************************************************************************************
2093  inline bool canSMPAssign() const {
2094  typename MVM::LeftOperand A( vector_.leftOperand() );
2095  return ( !BLAZE_BLAS_IS_PARALLEL ||
2096  ( IsComputation<MT>::value && !evaluateMatrix ) ||
2097  ( A.rows() * A.columns() < DMATDVECMULT_THRESHOLD ) ) &&
2099  }
2100  //**********************************************************************************************
2101 
2102  private:
2103  //**Member variables****************************************************************************
2104  LeftOperand vector_;
2105  RightOperand scalar_;
2106  //**********************************************************************************************
2107 
2108  //**BLAS kernel (single precision)**************************************************************
2109 #if BLAZE_BLAS_MODE
2110 
2124  template< typename VT1 // Type of the left-hand side target vector
2125  , typename MT1 // Type of the left-hand side matrix operand
2126  , typename VT2 > // Type of the right-hand side vector operand
2127  static inline void sgemv( VT1& y, const MT1& A, const VT2& x, float alpha, float beta )
2128  {
2129  using boost::numeric_cast;
2130 
2134 
2135  const int M ( numeric_cast<int>( A.rows() ) );
2136  const int N ( numeric_cast<int>( A.columns() ) );
2137  const int lda( numeric_cast<int>( A.spacing() ) );
2138 
2139  cblas_sgemv( CblasRowMajor, CblasNoTrans, M, N, alpha,
2140  A.data(), lda, x.data(), 1, beta, y.data(), 1 );
2141  }
2142 #endif
2143  //**********************************************************************************************
2144 
2145  //**BLAS kernel (double precision)**************************************************************
2146 #if BLAZE_BLAS_MODE
2147 
2161  template< typename VT1 // Type of the left-hand side target vector
2162  , typename MT1 // Type of the left-hand side matrix operand
2163  , typename VT2 > // Type of the right-hand side vector operand
2164  static inline void dgemv( VT1& y, const MT1& A, const VT2& x, double alpha, double beta )
2165  {
2166  using boost::numeric_cast;
2167 
2171 
2172  const int M ( numeric_cast<int>( A.rows() ) );
2173  const int N ( numeric_cast<int>( A.columns() ) );
2174  const int lda( numeric_cast<int>( A.spacing() ) );
2175 
2176  cblas_dgemv( CblasRowMajor, CblasNoTrans, M, N, alpha,
2177  A.data(), lda, x.data(), 1, beta, y.data(), 1 );
2178  }
2179 #endif
2180  //**********************************************************************************************
2181 
2182  //**BLAS kernel (single precision complex)******************************************************
2183 #if BLAZE_BLAS_MODE
2184 
2198  template< typename VT1 // Type of the left-hand side target vector
2199  , typename MT1 // Type of the left-hand side matrix operand
2200  , typename VT2 > // Type of the right-hand side vector operand
2201  static inline void cgemv( VT1& y, const MT1& A, const VT2& x,
2202  complex<float> alpha, complex<float> beta )
2203  {
2204  using boost::numeric_cast;
2205 
2209  BLAZE_CONSTRAINT_MUST_BE_FLOAT_TYPE ( typename VT1::ElementType::value_type );
2210  BLAZE_CONSTRAINT_MUST_BE_FLOAT_TYPE ( typename MT1::ElementType::value_type );
2211  BLAZE_CONSTRAINT_MUST_BE_FLOAT_TYPE ( typename VT2::ElementType::value_type );
2212 
2213  const int M ( numeric_cast<int>( A.rows() ) );
2214  const int N ( numeric_cast<int>( A.columns() ) );
2215  const int lda( numeric_cast<int>( A.spacing() ) );
2216 
2217  cblas_cgemv( CblasRowMajor, CblasNoTrans, M, N, &alpha,
2218  A.data(), lda, x.data(), 1, &beta, y.data(), 1 );
2219  }
2220 #endif
2221  //**********************************************************************************************
2222 
2223  //**BLAS kernel (double precision complex)******************************************************
2224 #if BLAZE_BLAS_MODE
2225 
2239  template< typename VT1 // Type of the left-hand side target vector
2240  , typename MT1 // Type of the left-hand side matrix operand
2241  , typename VT2 > // Type of the right-hand side vector operand
2242  static inline void zgemv( VT1& y, const MT1& A, const VT2& x,
2243  complex<double> alpha, complex<double> beta )
2244  {
2245  using boost::numeric_cast;
2246 
2250  BLAZE_CONSTRAINT_MUST_BE_DOUBLE_TYPE ( typename VT1::ElementType::value_type );
2251  BLAZE_CONSTRAINT_MUST_BE_DOUBLE_TYPE ( typename MT1::ElementType::value_type );
2252  BLAZE_CONSTRAINT_MUST_BE_DOUBLE_TYPE ( typename VT2::ElementType::value_type );
2253 
2254  const int M ( numeric_cast<int>( A.rows() ) );
2255  const int N ( numeric_cast<int>( A.columns() ) );
2256  const int lda( numeric_cast<int>( A.spacing() ) );
2257 
2258  cblas_zgemv( CblasRowMajor, CblasNoTrans, M, N, &alpha,
2259  A.data(), lda, x.data(), 1, &beta, y.data(), 1 );
2260  }
2261 #endif
2262  //**********************************************************************************************
2263 
2264  //**Assignment to dense vectors*****************************************************************
2276  template< typename VT1 > // Type of the target dense vector
2277  friend inline void assign( DenseVector<VT1,false>& lhs, const DVecScalarMultExpr& rhs )
2278  {
2280 
2281  BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
2282 
2283  typename MVM::LeftOperand left ( rhs.vector_.leftOperand() );
2284  typename MVM::RightOperand right( rhs.vector_.rightOperand() );
2285 
2286  if( left.rows() == 0UL ) {
2287  return;
2288  }
2289  else if( left.columns() == 0UL ) {
2290  reset( ~lhs );
2291  return;
2292  }
2293 
2294  LT A( serial( left ) ); // Evaluation of the left-hand side dense matrix operand
2295  RT x( serial( right ) ); // Evaluation of the right-hand side dense vector operand
2296 
2297  BLAZE_INTERNAL_ASSERT( A.rows() == left.rows() , "Invalid number of rows" );
2298  BLAZE_INTERNAL_ASSERT( A.columns() == left.columns(), "Invalid number of columns" );
2299  BLAZE_INTERNAL_ASSERT( x.size() == right.size() , "Invalid vector size" );
2300  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).size() , "Invalid vector size" );
2301 
2302  DVecScalarMultExpr::selectAssignKernel( ~lhs, A, x, rhs.scalar_ );
2303  }
2304  //**********************************************************************************************
2305 
2306  //**Assignment to dense vectors (kernel selection)**********************************************
2317  template< typename VT1 // Type of the left-hand side target vector
2318  , typename MT1 // Type of the left-hand side matrix operand
2319  , typename VT2 // Type of the right-hand side vector operand
2320  , typename ST2 > // Type of the scalar value
2321  static inline void selectAssignKernel( VT1& y, const MT1& A, const VT2& x, ST2 scalar )
2322  {
2323  if( ( IsComputation<MT>::value && !evaluateMatrix ) ||
2324  ( A.rows() * A.columns() < DMATDVECMULT_THRESHOLD ) )
2325  DVecScalarMultExpr::selectDefaultAssignKernel( y, A, x, scalar );
2326  else
2327  DVecScalarMultExpr::selectBlasAssignKernel( y, A, x, scalar );
2328  }
2329  //**********************************************************************************************
2330 
2331  //**Default assignment to dense vectors*********************************************************
2345  template< typename VT1 // Type of the left-hand side target vector
2346  , typename MT1 // Type of the left-hand side matrix operand
2347  , typename VT2 // Type of the right-hand side vector operand
2348  , typename ST2 > // Type of the scalar value
2349  static inline typename DisableIf< UseVectorizedDefaultKernel<VT1,MT1,VT2,ST2> >::Type
2350  selectDefaultAssignKernel( VT1& y, const MT1& A, const VT2& x, ST2 scalar )
2351  {
2352  y.assign( A * x * scalar );
2353  }
2354  //**********************************************************************************************
2355 
2356  //**Vectorized default assignment to dense vectors**********************************************
2370  template< typename VT1 // Type of the left-hand side target vector
2371  , typename MT1 // Type of the left-hand side matrix operand
2372  , typename VT2 // Type of the right-hand side vector operand
2373  , typename ST2 > // Type of the scalar value
2374  static inline typename EnableIf< UseVectorizedDefaultKernel<VT1,MT1,VT2,ST2> >::Type
2375  selectDefaultAssignKernel( VT1& y, const MT1& A, const VT2& x, ST2 scalar )
2376  {
2377  typedef IntrinsicTrait<ElementType> IT;
2378 
2379  const size_t M( A.rows() );
2380  const size_t N( A.columns() );
2381 
2382  size_t i( 0UL );
2383 
2384  for( ; (i+8UL) <= M; i+=8UL ) {
2385  IntrinsicType xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7, xmm8;
2386  for( size_t j=0UL; j<N; j+=IT::size ) {
2387  const IntrinsicType x1( x.load(j) );
2388  xmm1 = xmm1 + A.load(i ,j) * x1;
2389  xmm2 = xmm2 + A.load(i+1UL,j) * x1;
2390  xmm3 = xmm3 + A.load(i+2UL,j) * x1;
2391  xmm4 = xmm4 + A.load(i+3UL,j) * x1;
2392  xmm5 = xmm5 + A.load(i+4UL,j) * x1;
2393  xmm6 = xmm6 + A.load(i+5UL,j) * x1;
2394  xmm7 = xmm7 + A.load(i+6UL,j) * x1;
2395  xmm8 = xmm8 + A.load(i+7UL,j) * x1;
2396  }
2397  y[i ] = sum( xmm1 ) * scalar;
2398  y[i+1UL] = sum( xmm2 ) * scalar;
2399  y[i+2UL] = sum( xmm3 ) * scalar;
2400  y[i+3UL] = sum( xmm4 ) * scalar;
2401  y[i+4UL] = sum( xmm5 ) * scalar;
2402  y[i+5UL] = sum( xmm6 ) * scalar;
2403  y[i+6UL] = sum( xmm7 ) * scalar;
2404  y[i+7UL] = sum( xmm8 ) * scalar;
2405  }
2406  for( ; (i+4UL) <= M; i+=4UL ) {
2407  IntrinsicType xmm1, xmm2, xmm3, xmm4;
2408  for( size_t j=0UL; j<N; j+=IT::size ) {
2409  const IntrinsicType x1( x.load(j) );
2410  xmm1 = xmm1 + A.load(i ,j) * x1;
2411  xmm2 = xmm2 + A.load(i+1UL,j) * x1;
2412  xmm3 = xmm3 + A.load(i+2UL,j) * x1;
2413  xmm4 = xmm4 + A.load(i+3UL,j) * x1;
2414  }
2415  y[i ] = sum( xmm1 ) * scalar;
2416  y[i+1UL] = sum( xmm2 ) * scalar;
2417  y[i+2UL] = sum( xmm3 ) * scalar;
2418  y[i+3UL] = sum( xmm4 ) * scalar;
2419  }
2420  for( ; (i+3UL) <= M; i+=3UL ) {
2421  IntrinsicType xmm1, xmm2, xmm3;
2422  for( size_t j=0UL; j<N; j+=IT::size ) {
2423  const IntrinsicType x1( x.load(j) );
2424  xmm1 = xmm1 + A.load(i ,j) * x1;
2425  xmm2 = xmm2 + A.load(i+1UL,j) * x1;
2426  xmm3 = xmm3 + A.load(i+2UL,j) * x1;
2427  }
2428  y[i ] = sum( xmm1 ) * scalar;
2429  y[i+1UL] = sum( xmm2 ) * scalar;
2430  y[i+2UL] = sum( xmm3 ) * scalar;
2431  }
2432  for( ; (i+2UL) <= M; i+=2UL ) {
2433  IntrinsicType xmm1, xmm2;
2434  for( size_t j=0UL; j<N; j+=IT::size ) {
2435  const IntrinsicType x1( x.load(j) );
2436  xmm1 = xmm1 + A.load(i ,j) * x1;
2437  xmm2 = xmm2 + A.load(i+1UL,j) * x1;
2438  }
2439  y[i ] = sum( xmm1 ) * scalar;
2440  y[i+1UL] = sum( xmm2 ) * scalar;
2441  }
2442  if( i < M ) {
2443  IntrinsicType xmm1;
2444  for( size_t j=0UL; j<N; j+=IT::size ) {
2445  xmm1 = xmm1 + A.load(i,j) * x.load(j);
2446  }
2447  y[i] = sum( xmm1 ) * scalar;
2448  }
2449  }
2450  //**********************************************************************************************
2451 
2452  //**BLAS-based assignment to dense vectors (default)********************************************
2466  template< typename VT1 // Type of the left-hand side target vector
2467  , typename MT1 // Type of the left-hand side matrix operand
2468  , typename VT2 // Type of the right-hand side vector operand
2469  , typename ST2 > // Type of the scalar value
2470  static inline typename EnableIf< UseDefaultKernel<VT1,MT1,VT2,ST2> >::Type
2471  selectBlasAssignKernel( VT1& y, const MT1& A, const VT2& x, ST2 scalar )
2472  {
2473  selectDefaultAssignKernel( y, A, x, scalar );
2474  }
2475  //**********************************************************************************************
2476 
2477  //**BLAS-based assignment to dense vectors (single precision)***********************************
2478 #if BLAZE_BLAS_MODE
2479 
2492  template< typename VT1 // Type of the left-hand side target vector
2493  , typename MT1 // Type of the left-hand side matrix operand
2494  , typename VT2 // Type of the right-hand side vector operand
2495  , typename ST2 > // Type of the scalar value
2496  static inline typename EnableIf< UseSinglePrecisionKernel<VT1,MT1,VT2,ST2> >::Type
2497  selectBlasAssignKernel( VT1& y, const MT1& A, const VT2& x, ST2 scalar )
2498  {
2499  sgemv( y, A, x, scalar, 0.0F );
2500  }
2501 #endif
2502  //**********************************************************************************************
2503 
2504  //**BLAS-based assignment to dense vectors (double precision)***********************************
2505 #if BLAZE_BLAS_MODE
2506 
2519  template< typename VT1 // Type of the left-hand side target vector
2520  , typename MT1 // Type of the left-hand side matrix operand
2521  , typename VT2 // Type of the right-hand side vector operand
2522  , typename ST2 > // Type of the scalar value
2523  static inline typename EnableIf< UseDoublePrecisionKernel<VT1,MT1,VT2,ST2> >::Type
2524  selectBlasAssignKernel( VT1& y, const MT1& A, const VT2& x, ST2 scalar )
2525  {
2526  dgemv( y, A, x, scalar, 0.0 );
2527  }
2528 #endif
2529  //**********************************************************************************************
2530 
2531  //**BLAS-based assignment to dense vectors (single precision complex)***************************
2532 #if BLAZE_BLAS_MODE
2533 
2546  template< typename VT1 // Type of the left-hand side target vector
2547  , typename MT1 // Type of the left-hand side matrix operand
2548  , typename VT2 // Type of the right-hand side vector operand
2549  , typename ST2 > // Type of the scalar value
2550  static inline typename EnableIf< UseSinglePrecisionComplexKernel<VT1,MT1,VT2> >::Type
2551  selectBlasAssignKernel( VT1& y, const MT1& A, const VT2& x, ST2 scalar )
2552  {
2553  cgemv( y, A, x, complex<float>( scalar, 0.0F ), complex<float>( 0.0F, 0.0F ) );
2554  }
2555 #endif
2556  //**********************************************************************************************
2557 
2558  //**BLAS-based assignment to dense vectors (double precision complex)***************************
2559 #if BLAZE_BLAS_MODE
2560 
2573  template< typename VT1 // Type of the left-hand side target vector
2574  , typename MT1 // Type of the left-hand side matrix operand
2575  , typename VT2 // Type of the right-hand side vector operand
2576  , typename ST2 > // Type of the scalar value
2577  static inline typename EnableIf< UseDoublePrecisionComplexKernel<VT1,MT1,VT2> >::Type
2578  selectBlasAssignKernel( VT1& y, const MT1& A, const VT2& x, ST2 scalar )
2579  {
2580  zgemv( y, A, x, complex<double>( scalar, 0.0 ), complex<double>( 0.0, 0.0 ) );
2581  }
2582 #endif
2583  //**********************************************************************************************
2584 
2585  //**Assignment to sparse vectors****************************************************************
2597  template< typename VT1 > // Type of the target sparse vector
2598  friend inline void assign( SparseVector<VT1,false>& lhs, const DVecScalarMultExpr& rhs )
2599  {
2601 
2605 
2606  BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
2607 
2608  const ResultType tmp( serial( rhs ) );
2609  assign( ~lhs, tmp );
2610  }
2611  //**********************************************************************************************
2612 
2613  //**Addition assignment to dense vectors********************************************************
2625  template< typename VT1 > // Type of the target dense vector
2626  friend inline void addAssign( DenseVector<VT1,false>& lhs, const DVecScalarMultExpr& rhs )
2627  {
2629 
2630  BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
2631 
2632  typename MVM::LeftOperand left ( rhs.vector_.leftOperand() );
2633  typename MVM::RightOperand right( rhs.vector_.rightOperand() );
2634 
2635  if( left.rows() == 0UL || left.columns() == 0UL ) {
2636  return;
2637  }
2638 
2639  LT A( serial( left ) ); // Evaluation of the left-hand side dense matrix operand
2640  RT x( serial( right ) ); // Evaluation of the right-hand side dense vector operand
2641 
2642  BLAZE_INTERNAL_ASSERT( A.rows() == left.rows() , "Invalid number of rows" );
2643  BLAZE_INTERNAL_ASSERT( A.columns() == left.columns(), "Invalid number of columns" );
2644  BLAZE_INTERNAL_ASSERT( x.size() == right.size() , "Invalid vector size" );
2645  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).size() , "Invalid vector size" );
2646 
2647  DVecScalarMultExpr::selectAddAssignKernel( ~lhs, A, x, rhs.scalar_ );
2648  }
2649  //**********************************************************************************************
2650 
2651  //**Addition assignment to dense vectors (kernel selection)*************************************
2662  template< typename VT1 // Type of the left-hand side target vector
2663  , typename MT1 // Type of the left-hand side matrix operand
2664  , typename VT2 // Type of the right-hand side vector operand
2665  , typename ST2 > // Type of the scalar value
2666  static inline void selectAddAssignKernel( VT1& y, const MT1& A, const VT2& x, ST2 scalar )
2667  {
2668  if( ( IsComputation<MT>::value && !evaluateMatrix ) ||
2669  ( A.rows() * A.columns() < DMATDVECMULT_THRESHOLD ) )
2670  DVecScalarMultExpr::selectDefaultAddAssignKernel( y, A, x, scalar );
2671  else
2672  DVecScalarMultExpr::selectBlasAddAssignKernel( y, A, x, scalar );
2673  }
2674  //**********************************************************************************************
2675 
2676  //**Default addition assignment to dense vectors************************************************
2690  template< typename VT1 // Type of the left-hand side target vector
2691  , typename MT1 // Type of the left-hand side matrix operand
2692  , typename VT2 // Type of the right-hand side vector operand
2693  , typename ST2 > // Type of the scalar value
2694  static inline typename DisableIf< UseVectorizedDefaultKernel<VT1,MT1,VT2,ST2> >::Type
2695  selectDefaultAddAssignKernel( VT1& y, const MT1& A, const VT2& x, ST2 scalar )
2696  {
2697  y.addAssign( A * x * scalar );
2698  }
2699  //**********************************************************************************************
2700 
2701  //**Vectorized default addition assignment to dense vectors*************************************
2715  template< typename VT1 // Type of the left-hand side target vector
2716  , typename MT1 // Type of the left-hand side matrix operand
2717  , typename VT2 // Type of the right-hand side vector operand
2718  , typename ST2 > // Type of the scalar value
2719  static inline typename EnableIf< UseVectorizedDefaultKernel<VT1,MT1,VT2,ST2> >::Type
2720  selectDefaultAddAssignKernel( VT1& y, const MT1& A, const VT2& x, ST2 scalar )
2721  {
2722  typedef IntrinsicTrait<ElementType> IT;
2723 
2724  const size_t M( A.rows() );
2725  const size_t N( A.columns() );
2726 
2727  size_t i( 0UL );
2728 
2729  for( ; (i+8UL) <= M; i+=8UL ) {
2730  IntrinsicType xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7, xmm8;
2731  for( size_t j=0UL; j<N; j+=IT::size ) {
2732  const IntrinsicType x1( x.load(j) );
2733  xmm1 = xmm1 + A.load(i ,j) * x1;
2734  xmm2 = xmm2 + A.load(i+1UL,j) * x1;
2735  xmm3 = xmm3 + A.load(i+2UL,j) * x1;
2736  xmm4 = xmm4 + A.load(i+3UL,j) * x1;
2737  xmm5 = xmm5 + A.load(i+4UL,j) * x1;
2738  xmm6 = xmm6 + A.load(i+5UL,j) * x1;
2739  xmm7 = xmm7 + A.load(i+6UL,j) * x1;
2740  xmm8 = xmm8 + A.load(i+7UL,j) * x1;
2741  }
2742  y[i ] += sum( xmm1 ) * scalar;
2743  y[i+1UL] += sum( xmm2 ) * scalar;
2744  y[i+2UL] += sum( xmm3 ) * scalar;
2745  y[i+3UL] += sum( xmm4 ) * scalar;
2746  y[i+4UL] += sum( xmm5 ) * scalar;
2747  y[i+5UL] += sum( xmm6 ) * scalar;
2748  y[i+6UL] += sum( xmm7 ) * scalar;
2749  y[i+7UL] += sum( xmm8 ) * scalar;
2750  }
2751  for( ; (i+4UL) <= M; i+=4UL ) {
2752  IntrinsicType xmm1, xmm2, xmm3, xmm4;
2753  for( size_t j=0UL; j<N; j+=IT::size ) {
2754  const IntrinsicType x1( x.load(j) );
2755  xmm1 = xmm1 + A.load(i ,j) * x1;
2756  xmm2 = xmm2 + A.load(i+1UL,j) * x1;
2757  xmm3 = xmm3 + A.load(i+2UL,j) * x1;
2758  xmm4 = xmm4 + A.load(i+3UL,j) * x1;
2759  }
2760  y[i ] += sum( xmm1 ) * scalar;
2761  y[i+1UL] += sum( xmm2 ) * scalar;
2762  y[i+2UL] += sum( xmm3 ) * scalar;
2763  y[i+3UL] += sum( xmm4 ) * scalar;
2764  }
2765  for( ; (i+3UL) <= M; i+=3UL ) {
2766  IntrinsicType xmm1, xmm2, xmm3;
2767  for( size_t j=0UL; j<N; j+=IT::size ) {
2768  const IntrinsicType x1( x.load(j) );
2769  xmm1 = xmm1 + A.load(i ,j) * x1;
2770  xmm2 = xmm2 + A.load(i+1UL,j) * x1;
2771  xmm3 = xmm3 + A.load(i+2UL,j) * x1;
2772  }
2773  y[i ] += sum( xmm1 ) * scalar;
2774  y[i+1UL] += sum( xmm2 ) * scalar;
2775  y[i+2UL] += sum( xmm3 ) * scalar;
2776  }
2777  for( ; (i+2UL) <= M; i+=2UL ) {
2778  IntrinsicType xmm1, xmm2;
2779  for( size_t j=0UL; j<N; j+=IT::size ) {
2780  const IntrinsicType x1( x.load(j) );
2781  xmm1 = xmm1 + A.load(i ,j) * x1;
2782  xmm2 = xmm2 + A.load(i+1UL,j) * x1;
2783  }
2784  y[i ] += sum( xmm1 ) * scalar;
2785  y[i+1UL] += sum( xmm2 ) * scalar;
2786  }
2787  if( i < M ) {
2788  IntrinsicType xmm1;
2789  for( size_t j=0UL; j<N; j+=IT::size ) {
2790  xmm1 = xmm1 + A.load(i,j) * x.load(j);
2791  }
2792  y[i] += sum( xmm1 ) * scalar;
2793  }
2794  }
2795  //**********************************************************************************************
2796 
2797  //**BLAS-based addition assignment to dense vectors (default)***********************************
2811  template< typename VT1 // Type of the left-hand side target vector
2812  , typename MT1 // Type of the left-hand side matrix operand
2813  , typename VT2 // Type of the right-hand side vector operand
2814  , typename ST2 > // Type of the scalar value
2815  static inline typename EnableIf< UseDefaultKernel<VT1,MT1,VT2,ST2> >::Type
2816  selectBlasAddAssignKernel( VT1& y, const MT1& A, const VT2& x, ST2 scalar )
2817  {
2818  selectDefaultAddAssignKernel( y, A, x, scalar );
2819  }
2820  //**********************************************************************************************
2821 
2822  //**BLAS-based addition assignment to dense vectors (single precision)**************************
2823 #if BLAZE_BLAS_MODE
2824 
2837  template< typename VT1 // Type of the left-hand side target vector
2838  , typename MT1 // Type of the left-hand side matrix operand
2839  , typename VT2 // Type of the right-hand side vector operand
2840  , typename ST2 > // Type of the scalar value
2841  static inline typename EnableIf< UseSinglePrecisionKernel<VT1,MT1,VT2,ST2> >::Type
2842  selectBlasAddAssignKernel( VT1& y, const MT1& A, const VT2& x, ST2 scalar )
2843  {
2844  sgemv( y, A, x, scalar, 1.0F );
2845  }
2846 #endif
2847  //**********************************************************************************************
2848 
2849  //**BLAS-based addition assignment to dense vectors (double precision)**************************
2850 #if BLAZE_BLAS_MODE
2851 
2864  template< typename VT1 // Type of the left-hand side target vector
2865  , typename MT1 // Type of the left-hand side matrix operand
2866  , typename VT2 // Type of the right-hand side vector operand
2867  , typename ST2 > // Type of the scalar value
2868  static inline typename EnableIf< UseDoublePrecisionKernel<VT1,MT1,VT2,ST2> >::Type
2869  selectBlasAddAssignKernel( VT1& y, const MT1& A, const VT2& x, ST2 scalar )
2870  {
2871  dgemv( y, A, x, scalar, 1.0 );
2872  }
2873 #endif
2874  //**********************************************************************************************
2875 
2876  //**BLAS-based addition assignment to dense vectors (single precision complex)******************
2877 #if BLAZE_BLAS_MODE
2878 
2891  template< typename VT1 // Type of the left-hand side target vector
2892  , typename MT1 // Type of the left-hand side matrix operand
2893  , typename VT2 // Type of the right-hand side vector operand
2894  , typename ST2 > // Type of the scalar value
2895  static inline typename EnableIf< UseSinglePrecisionComplexKernel<VT1,MT1,VT2> >::Type
2896  selectBlasAddAssignKernel( VT1& y, const MT1& A, const VT2& x, ST2 scalar )
2897  {
2898  cgemv( y, A, x, complex<float>( scalar, 0.0F ), complex<float>( 1.0F, 0.0F ) );
2899  }
2900 #endif
2901  //**********************************************************************************************
2902 
2903  //**BLAS-based addition assignment to dense vectors (double precision complex)******************
2904 #if BLAZE_BLAS_MODE
2905 
2918  template< typename VT1 // Type of the left-hand side target vector
2919  , typename MT1 // Type of the left-hand side matrix operand
2920  , typename VT2 // Type of the right-hand side vector operand
2921  , typename ST2 > // Type of the scalar value
2922  static inline typename EnableIf< UseDoublePrecisionComplexKernel<VT1,MT1,VT2> >::Type
2923  selectBlasAddAssignKernel( VT1& y, const MT1& A, const VT2& x, ST2 scalar )
2924  {
2925  zgemv( y, A, x, complex<double>( scalar, 0.0 ), complex<double>( 1.0, 0.0 ) );
2926  }
2927 #endif
2928  //**********************************************************************************************
2929 
2930  //**Addition assignment to sparse vectors*******************************************************
2931  // No special implementation for the addition assignment to sparse vectors.
2932  //**********************************************************************************************
2933 
2934  //**Subtraction assignment to dense vectors*****************************************************
2946  template< typename VT1 > // Type of the target dense vector
2947  friend inline void subAssign( DenseVector<VT1,false>& lhs, const DVecScalarMultExpr& rhs )
2948  {
2950 
2951  BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
2952 
2953  typename MVM::LeftOperand left ( rhs.vector_.leftOperand() );
2954  typename MVM::RightOperand right( rhs.vector_.rightOperand() );
2955 
2956  if( left.rows() == 0UL || left.columns() == 0UL ) {
2957  return;
2958  }
2959 
2960  LT A( serial( left ) ); // Evaluation of the left-hand side dense matrix operand
2961  RT x( serial( right ) ); // Evaluation of the right-hand side dense vector operand
2962 
2963  BLAZE_INTERNAL_ASSERT( A.rows() == left.rows() , "Invalid number of rows" );
2964  BLAZE_INTERNAL_ASSERT( A.columns() == left.columns(), "Invalid number of columns" );
2965  BLAZE_INTERNAL_ASSERT( x.size() == right.size() , "Invalid vector size" );
2966  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).size() , "Invalid vector size" );
2967 
2968  DVecScalarMultExpr::selectSubAssignKernel( ~lhs, A, x, rhs.scalar_ );
2969  }
2970  //**********************************************************************************************
2971 
2972  //**Subtraction assignment to dense vectors (kernel selection)**********************************
2983  template< typename VT1 // Type of the left-hand side target vector
2984  , typename MT1 // Type of the left-hand side matrix operand
2985  , typename VT2 // Type of the right-hand side vector operand
2986  , typename ST2 > // Type of the scalar value
2987  static inline void selectSubAssignKernel( VT1& y, const MT1& A, const VT2& x, ST2 scalar )
2988  {
2989  if( ( IsComputation<MT>::value && !evaluateMatrix ) ||
2990  ( A.rows() * A.columns() < DMATDVECMULT_THRESHOLD ) )
2991  DVecScalarMultExpr::selectDefaultSubAssignKernel( y, A, x, scalar );
2992  else
2993  DVecScalarMultExpr::selectBlasSubAssignKernel( y, A, x, scalar );
2994  }
2995  //**********************************************************************************************
2996 
2997  //**Default subtraction assignment to dense vectors*********************************************
3011  template< typename VT1 // Type of the left-hand side target vector
3012  , typename MT1 // Type of the left-hand side matrix operand
3013  , typename VT2 // Type of the right-hand side vector operand
3014  , typename ST2 > // Type of the scalar value
3015  static inline typename DisableIf< UseVectorizedDefaultKernel<VT1,MT1,VT2,ST2> >::Type
3016  selectDefaultSubAssignKernel( VT1& y, const MT1& A, const VT2& x, ST2 scalar )
3017  {
3018  y.subAssign( A * x * scalar );
3019  }
3020  //**********************************************************************************************
3021 
3022  //**Vectorized default subtraction assignment to dense vectors**********************************
3036  template< typename VT1 // Type of the left-hand side target vector
3037  , typename MT1 // Type of the left-hand side matrix operand
3038  , typename VT2 // Type of the right-hand side vector operand
3039  , typename ST2 > // Type of the scalar value
3040  static inline typename EnableIf< UseVectorizedDefaultKernel<VT1,MT1,VT2,ST2> >::Type
3041  selectDefaultSubAssignKernel( VT1& y, const MT1& A, const VT2& x, ST2 scalar )
3042  {
3043  typedef IntrinsicTrait<ElementType> IT;
3044 
3045  const size_t M( A.rows() );
3046  const size_t N( A.columns() );
3047 
3048  size_t i( 0UL );
3049 
3050  for( ; (i+8UL) <= M; i+=8UL ) {
3051  IntrinsicType xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7, xmm8;
3052  for( size_t j=0UL; j<N; j+=IT::size ) {
3053  const IntrinsicType x1( x.load(j) );
3054  xmm1 = xmm1 + A.load(i ,j) * x1;
3055  xmm2 = xmm2 + A.load(i+1UL,j) * x1;
3056  xmm3 = xmm3 + A.load(i+2UL,j) * x1;
3057  xmm4 = xmm4 + A.load(i+3UL,j) * x1;
3058  xmm5 = xmm5 + A.load(i+4UL,j) * x1;
3059  xmm6 = xmm6 + A.load(i+5UL,j) * x1;
3060  xmm7 = xmm7 + A.load(i+6UL,j) * x1;
3061  xmm8 = xmm8 + A.load(i+7UL,j) * x1;
3062  }
3063  y[i ] -= sum( xmm1 ) * scalar;
3064  y[i+1UL] -= sum( xmm2 ) * scalar;
3065  y[i+2UL] -= sum( xmm3 ) * scalar;
3066  y[i+3UL] -= sum( xmm4 ) * scalar;
3067  y[i+4UL] -= sum( xmm5 ) * scalar;
3068  y[i+5UL] -= sum( xmm6 ) * scalar;
3069  y[i+6UL] -= sum( xmm7 ) * scalar;
3070  y[i+7UL] -= sum( xmm8 ) * scalar;
3071  }
3072  for( ; (i+4UL) <= M; i+=4UL ) {
3073  IntrinsicType xmm1, xmm2, xmm3, xmm4;
3074  for( size_t j=0UL; j<N; j+=IT::size ) {
3075  const IntrinsicType x1( x.load(j) );
3076  xmm1 = xmm1 + A.load(i ,j) * x1;
3077  xmm2 = xmm2 + A.load(i+1UL,j) * x1;
3078  xmm3 = xmm3 + A.load(i+2UL,j) * x1;
3079  xmm4 = xmm4 + A.load(i+3UL,j) * x1;
3080  }
3081  y[i ] -= sum( xmm1 ) * scalar;
3082  y[i+1UL] -= sum( xmm2 ) * scalar;
3083  y[i+2UL] -= sum( xmm3 ) * scalar;
3084  y[i+3UL] -= sum( xmm4 ) * scalar;
3085  }
3086  for( ; (i+3UL) <= M; i+=3UL ) {
3087  IntrinsicType xmm1, xmm2, xmm3;
3088  for( size_t j=0UL; j<N; j+=IT::size ) {
3089  const IntrinsicType x1( x.load(j) );
3090  xmm1 = xmm1 + A.load(i ,j) * x1;
3091  xmm2 = xmm2 + A.load(i+1UL,j) * x1;
3092  xmm3 = xmm3 + A.load(i+2UL,j) * x1;
3093  }
3094  y[i ] -= sum( xmm1 ) * scalar;
3095  y[i+1UL] -= sum( xmm2 ) * scalar;
3096  y[i+2UL] -= sum( xmm3 ) * scalar;
3097  }
3098  for( ; (i+2UL) <= M; i+=2UL ) {
3099  IntrinsicType xmm1, xmm2;
3100  for( size_t j=0UL; j<N; j+=IT::size ) {
3101  const IntrinsicType x1( x.load(j) );
3102  xmm1 = xmm1 + A.load(i ,j) * x1;
3103  xmm2 = xmm2 + A.load(i+1UL,j) * x1;
3104  }
3105  y[i ] -= sum( xmm1 ) * scalar;
3106  y[i+1UL] -= sum( xmm2 ) * scalar;
3107  }
3108  if( i < M ) {
3109  IntrinsicType xmm1;
3110  for( size_t j=0UL; j<N; j+=IT::size ) {
3111  xmm1 = xmm1 + A.load(i,j) * x.load(j);
3112  }
3113  y[i] -= sum( xmm1 ) * scalar;
3114  }
3115  }
3116  //**********************************************************************************************
3117 
3118  //**BLAS-based subtraction assignment to dense vectors (default)********************************
3132  template< typename VT1 // Type of the left-hand side target vector
3133  , typename MT1 // Type of the left-hand side matrix operand
3134  , typename VT2 // Type of the right-hand side vector operand
3135  , typename ST2 > // Type of the scalar value
3136  static inline typename EnableIf< UseDefaultKernel<VT1,MT1,VT2,ST2> >::Type
3137  selectBlasSubAssignKernel( VT1& y, const MT1& A, const VT2& x, ST2 scalar )
3138  {
3139  selectDefaultSubAssignKernel( y, A, x, scalar );
3140  }
3141  //**********************************************************************************************
3142 
3143  //**BLAS-based subtraction assignment to dense vectors (single precision)***********************
3144 #if BLAZE_BLAS_MODE
3145 
3158  template< typename VT1 // Type of the left-hand side target vector
3159  , typename MT1 // Type of the left-hand side matrix operand
3160  , typename VT2 // Type of the right-hand side vector operand
3161  , typename ST2 > // Type of the scalar value
3162  static inline typename EnableIf< UseSinglePrecisionKernel<VT1,MT1,VT2,ST2> >::Type
3163  selectBlasSubAssignKernel( VT1& y, const MT1& A, const VT2& x, ST2 scalar )
3164  {
3165  sgemv( y, A, x, -scalar, 1.0F );
3166  }
3167 #endif
3168  //**********************************************************************************************
3169 
3170  //**BLAS-based subtraction assignment to dense vectors (double precision)***********************
3171 #if BLAZE_BLAS_MODE
3172 
3185  template< typename VT1 // Type of the left-hand side target vector
3186  , typename MT1 // Type of the left-hand side matrix operand
3187  , typename VT2 // Type of the right-hand side vector operand
3188  , typename ST2 > // Type of the scalar value
3189  static inline typename EnableIf< UseDoublePrecisionKernel<VT1,MT1,VT2,ST2> >::Type
3190  selectBlasSubAssignKernel( VT1& y, const MT1& A, const VT2& x, ST2 scalar )
3191  {
3192  dgemv( y, A, x, -scalar, 1.0 );
3193  }
3194 #endif
3195  //**********************************************************************************************
3196 
3197  //**BLAS-based subtraction assignment to dense vectors (single precision complex)***************
3198 #if BLAZE_BLAS_MODE
3199 
3212  template< typename VT1 // Type of the left-hand side target vector
3213  , typename MT1 // Type of the left-hand side matrix operand
3214  , typename VT2 // Type of the right-hand side vector operand
3215  , typename ST2 > // Type of the scalar value
3216  static inline typename EnableIf< UseSinglePrecisionComplexKernel<VT1,MT1,VT2> >::Type
3217  selectBlasSubAssignKernel( VT1& y, const MT1& A, const VT2& x, ST2 scalar )
3218  {
3219  cgemv( y, A, x, complex<float>( -scalar, 0.0F ), complex<float>( 1.0F, 0.0F ) );
3220  }
3221 #endif
3222  //**********************************************************************************************
3223 
3224  //**BLAS-based subtraction assignment to dense vectors (double precision complex)***************
3225 #if BLAZE_BLAS_MODE
3226 
3239  template< typename VT1 // Type of the left-hand side target vector
3240  , typename MT1 // Type of the left-hand side matrix operand
3241  , typename VT2 // Type of the right-hand side vector operand
3242  , typename ST2 > // Type of the scalar value
3243  static inline typename EnableIf< UseDoublePrecisionComplexKernel<VT1,MT1,VT2> >::Type
3244  selectBlasSubAssignKernel( VT1& y, const MT1& A, const VT2& x, ST2 scalar )
3245  {
3246  zgemv( y, A, x, complex<double>( -scalar, 0.0 ), complex<double>( 1.0, 0.0 ) );
3247  }
3248 #endif
3249  //**********************************************************************************************
3250 
3251  //**Subtraction assignment to sparse vectors****************************************************
3252  // No special implementation for the subtraction assignment to sparse vectors.
3253  //**********************************************************************************************
3254 
3255  //**Multiplication assignment to dense vectors**************************************************
3267  template< typename VT1 > // Type of the target dense vector
3268  friend inline void multAssign( DenseVector<VT1,false>& lhs, const DVecScalarMultExpr& rhs )
3269  {
3271 
3275 
3276  BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
3277 
3278  const ResultType tmp( serial( rhs ) );
3279  multAssign( ~lhs, tmp );
3280  }
3281  //**********************************************************************************************
3282 
3283  //**Multiplication assignment to sparse vectors*************************************************
3284  // No special implementation for the multiplication assignment to sparse vectors.
3285  //**********************************************************************************************
3286 
3287  //**SMP assignment to dense vectors*************************************************************
3301  template< typename VT1 > // Type of the target dense vector
3302  friend inline typename EnableIf< UseSMPAssign<VT1> >::Type
3303  smpAssign( DenseVector<VT1,false>& lhs, const DVecScalarMultExpr& rhs )
3304  {
3306 
3307  BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
3308 
3309  typename MVM::LeftOperand left ( rhs.vector_.leftOperand() );
3310  typename MVM::RightOperand right( rhs.vector_.rightOperand() );
3311 
3312  if( left.rows() == 0UL ) {
3313  return;
3314  }
3315  else if( left.columns() == 0UL ) {
3316  reset( ~lhs );
3317  return;
3318  }
3319 
3320  LT A( left ); // Evaluation of the left-hand side dense matrix operand
3321  RT x( right ); // Evaluation of the right-hand side dense vector operand
3322 
3323  BLAZE_INTERNAL_ASSERT( A.rows() == left.rows() , "Invalid number of rows" );
3324  BLAZE_INTERNAL_ASSERT( A.columns() == left.columns(), "Invalid number of columns" );
3325  BLAZE_INTERNAL_ASSERT( x.size() == right.size() , "Invalid vector size" );
3326  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).size() , "Invalid vector size" );
3327 
3328  smpAssign( ~lhs, A * x * rhs.scalar_ );
3329  }
3330  //**********************************************************************************************
3331 
3332  //**SMP assignment to sparse vectors************************************************************
3346  template< typename VT1 > // Type of the target sparse vector
3347  friend inline typename EnableIf< UseSMPAssign<VT1> >::Type
3348  smpAssign( SparseVector<VT1,false>& lhs, const DVecScalarMultExpr& rhs )
3349  {
3351 
3355 
3356  BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
3357 
3358  const ResultType tmp( rhs );
3359  smpAssign( ~lhs, tmp );
3360  }
3361  //**********************************************************************************************
3362 
3363  //**SMP addition assignment to dense vectors****************************************************
3377  template< typename VT1 > // Type of the target dense vector
3378  friend inline typename EnableIf< UseSMPAssign<VT1> >::Type
3379  smpAddAssign( DenseVector<VT1,false>& lhs, const DVecScalarMultExpr& rhs )
3380  {
3382 
3383  BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
3384 
3385  typename MVM::LeftOperand left ( rhs.vector_.leftOperand() );
3386  typename MVM::RightOperand right( rhs.vector_.rightOperand() );
3387 
3388  if( left.rows() == 0UL || left.columns() == 0UL ) {
3389  return;
3390  }
3391 
3392  LT A( left ); // Evaluation of the left-hand side dense matrix operand
3393  RT x( right ); // Evaluation of the right-hand side dense vector operand
3394 
3395  BLAZE_INTERNAL_ASSERT( A.rows() == left.rows() , "Invalid number of rows" );
3396  BLAZE_INTERNAL_ASSERT( A.columns() == left.columns(), "Invalid number of columns" );
3397  BLAZE_INTERNAL_ASSERT( x.size() == right.size() , "Invalid vector size" );
3398  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).size() , "Invalid vector size" );
3399 
3400  smpAddAssign( ~lhs, A * x * rhs.scalar_ );
3401  }
3402  //**********************************************************************************************
3403 
3404  //**SMP addition assignment to sparse vectors***************************************************
3405  // No special implementation for the SMP addition assignment to sparse vectors.
3406  //**********************************************************************************************
3407 
3408  //**SMP subtraction assignment to dense vectors*************************************************
3422  template< typename VT1 > // Type of the target dense vector
3423  friend inline typename EnableIf< UseSMPAssign<VT1> >::Type
3424  smpSubAssign( DenseVector<VT1,false>& lhs, const DVecScalarMultExpr& rhs )
3425  {
3427 
3428  BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
3429 
3430  typename MVM::LeftOperand left ( rhs.vector_.leftOperand() );
3431  typename MVM::RightOperand right( rhs.vector_.rightOperand() );
3432 
3433  if( left.rows() == 0UL || left.columns() == 0UL ) {
3434  return;
3435  }
3436 
3437  LT A( left ); // Evaluation of the left-hand side dense matrix operand
3438  RT x( right ); // Evaluation of the right-hand side dense vector operand
3439 
3440  BLAZE_INTERNAL_ASSERT( A.rows() == left.rows() , "Invalid number of rows" );
3441  BLAZE_INTERNAL_ASSERT( A.columns() == left.columns(), "Invalid number of columns" );
3442  BLAZE_INTERNAL_ASSERT( x.size() == right.size() , "Invalid vector size" );
3443  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).size() , "Invalid vector size" );
3444 
3445  smpSubAssign( ~lhs, A * x * rhs.scalar_ );
3446  }
3447  //**********************************************************************************************
3448 
3449  //**SMP subtraction assignment to sparse vectors************************************************
3450  // No special implementation for the SMP subtraction assignment to sparse vectors.
3451  //**********************************************************************************************
3452 
3453  //**SMP multiplication assignment to dense vectors**********************************************
3467  template< typename VT1 > // Type of the target dense vector
3468  friend inline typename EnableIf< UseSMPAssign<VT1> >::Type
3469  smpMultAssign( DenseVector<VT1,false>& lhs, const DVecScalarMultExpr& rhs )
3470  {
3472 
3476 
3477  BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
3478 
3479  const ResultType tmp( rhs );
3480  smpMultAssign( ~lhs, tmp );
3481  }
3482  //**********************************************************************************************
3483 
3484  //**SMP multiplication assignment to sparse vectors*********************************************
3485  // No special implementation for the SMP multiplication assignment to sparse vectors.
3486  //**********************************************************************************************
3487 
3488  //**Compile time checks*************************************************************************
3497  //**********************************************************************************************
3498 };
3500 //*************************************************************************************************
3501 
3502 
3503 
3504 
3505 //=================================================================================================
3506 //
3507 // GLOBAL BINARY ARITHMETIC OPERATORS
3508 //
3509 //=================================================================================================
3510 
3511 //*************************************************************************************************
3541 template< typename T1 // Type of the left-hand side dense matrix
3542  , typename T2 > // Type of the right-hand side dense vector
3543 inline const typename DisableIf< IsMatMatMultExpr<T1>, DMatDVecMultExpr<T1,T2> >::Type
3545 {
3547 
3548  if( (~mat).columns() != (~vec).size() )
3549  throw std::invalid_argument( "Matrix and vector sizes do not match" );
3550 
3551  return DMatDVecMultExpr<T1,T2>( ~mat, ~vec );
3552 }
3553 //*************************************************************************************************
3554 
3555 
3556 
3557 
3558 //=================================================================================================
3559 //
3560 // GLOBAL RESTRUCTURING BINARY ARITHMETIC OPERATORS
3561 //
3562 //=================================================================================================
3563 
3564 //*************************************************************************************************
3577 template< typename T1 // Type of the left-hand side dense matrix
3578  , bool SO // Storage order of the left-hand side dense matrix
3579  , typename T2 > // Type of the right-hand side dense vector
3580 inline const typename EnableIf< IsMatMatMultExpr<T1>, typename MultExprTrait<T1,T2>::Type >::Type
3582 {
3584 
3586 
3587  return (~mat).leftOperand() * ( (~mat).rightOperand() * vec );
3588 }
3589 //*************************************************************************************************
3590 
3591 
3592 
3593 
3594 //=================================================================================================
3595 //
3596 // SIZE SPECIALIZATIONS
3597 //
3598 //=================================================================================================
3599 
3600 //*************************************************************************************************
3602 template< typename MT, typename VT >
3603 struct Size< DMatDVecMultExpr<MT,VT> >
3604  : public Rows<MT>
3605 {};
3607 //*************************************************************************************************
3608 
3609 
3610 
3611 
3612 //=================================================================================================
3613 //
3614 // EXPRESSION TRAIT SPECIALIZATIONS
3615 //
3616 //=================================================================================================
3617 
3618 //*************************************************************************************************
3620 template< typename MT, typename VT, bool AF >
3621 struct SubvectorExprTrait< DMatDVecMultExpr<MT,VT>, AF >
3622 {
3623  public:
3624  //**********************************************************************************************
3625  typedef typename MultExprTrait< typename SubmatrixExprTrait<const MT,AF>::Type, VT >::Type Type;
3626  //**********************************************************************************************
3627 };
3629 //*************************************************************************************************
3630 
3631 } // namespace blaze
3632 
3633 #endif
BLAZE_ALWAYS_INLINE int16_t sum(const sse_int16_t &a)
Returns the sum of all elements in the 16-bit integral intrinsic vector.
Definition: Reduction.h:63
Data type constraint.
Compile time check whether the given type is a computational expression template.This type trait clas...
Definition: IsComputation.h:89
BLAZE_ALWAYS_INLINE void multAssign(Matrix< MT1, SO1 > &lhs, const Matrix< MT2, SO2 > &rhs)
Default implementation of the multiplication assignment of a matrix to a matrix.
Definition: Matrix.h:879
SelectType< IsExpression< VT >::value, const VT, const VT & >::Type RightOperand
Composite type of the right-hand side dense vector expression.
Definition: DMatDVecMultExpr.h:262
Header file for the Rows type trait.
#define BLAZE_BLAS_IS_PARALLEL
Compilation switch for the parallel BLAS mode.This compilation switch specifies whether the used BLAS...
Definition: BLAS.h:86
RightOperand rightOperand() const
Returns the right-hand side dense vector operand.
Definition: DMatDVecMultExpr.h:351
const DMatDMatMultExpr< T1, T2 > operator*(const DenseMatrix< T1, false > &lhs, const DenseMatrix< T2, false > &rhs)
Multiplication operator for the multiplication of two row-major dense matrices ( ).
Definition: DMatDMatMultExpr.h:4838
DMatDVecMultExpr(const MT &mat, const VT &vec)
Constructor for the DMatDVecMultExpr class.
Definition: DMatDVecMultExpr.h:289
BLAZE_ALWAYS_INLINE size_t size(const Vector< VT, TF > &vector)
Returns the current size/dimension of the vector.
Definition: Vector.h:258
#define BLAZE_CONSTRAINT_MUST_BE_COLUMN_VECTOR_TYPE(T)
Constraint on the data type.In case the given data type T is not a column dense or sparse vector type...
Definition: TransposeFlag.h:159
Efficient implementation of a compressed matrix.The CompressedMatrix class template is the represent...
Definition: CompressedMatrix.h:205
Expression object for dense matrix-dense vector multiplications.The DMatDVecMultExpr class represents...
Definition: DMatDVecMultExpr.h:108
#define BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE(T)
Constraint on the data type.In case the given data type T is not a dense, N-dimensional matrix type...
Definition: DenseMatrix.h:79
MT::ResultType MRT
Result type of the left-hand side dense matrix expression.
Definition: DMatDVecMultExpr.h:114
Header file for the IsSame and IsStrictlySame type traits.
Constraint on the data type.
bool isAligned() const
Returns whether the operands of the expression are properly aligned in memory.
Definition: DMatDVecMultExpr.h:385
MultTrait< MRT, VRT >::Type ResultType
Result type for expression template evaluations.
Definition: DMatDVecMultExpr.h:251
const This & CompositeType
Data type for composite expression templates.
Definition: CompressedMatrix.h:2478
Type ElementType
Type of the sparse matrix elements.
Definition: CompressedMatrix.h:257
Header file for the DenseVector base class.
const size_t SMP_DMATDVECMULT_THRESHOLD
SMP row-major dense matrix/dense vector multiplication threshold.This threshold specifies when a row-...
Definition: Thresholds.h:322
Compile time check for double precision floating point types.This type trait tests whether or not the...
Definition: IsDouble.h:75
const DMatSerialExpr< MT, SO > serial(const DenseMatrix< MT, SO > &dm)
Forces the serial evaluation of the given dense matrix expression dm.
Definition: DMatSerialExpr.h:695
Header file for the Computation base class.
Type relationship analysis.This class tests if the two data types A and B are equal. For this type comparison, the cv-qualifiers of both data types are ignored. If A and B are the same data type (ignoring the cv-qualifiers), then the value member enumeration is set to 1, the nested type definition Type is TrueType, and the class derives from TrueType. Otherwise value is set to 0, Type is FalseType, and the class derives from FalseType.
Definition: IsSame.h:158
Header file for the RequiresEvaluation type trait.
DMatDVecMultExpr< MT, VT > This
Type of this DMatDVecMultExpr instance.
Definition: DMatDVecMultExpr.h:250
Header file for the VecScalarMultExpr base class.
Header file for the IsFloat type trait.
Base class for dense matrices.The DenseMatrix class is a base class for all dense matrix classes...
Definition: DenseMatrix.h:70
Constraint on the data type.
#define BLAZE_CONSTRAINT_MUST_BE_FLOAT_TYPE(T)
Constraint on the data type.This compile time constraint checks that the given data type T is of type...
Definition: Float.h:80
size_t size() const
Returns the current size/dimension of the vector.
Definition: DMatDVecMultExpr.h:331
const size_t end_
End of the unrolled calculation loop.
Definition: DMatDVecMultExpr.h:407
Constraint on the data type.
VT::CompositeType VCT
Composite type of the right-hand side dense vector expression.
Definition: DMatDVecMultExpr.h:119
Constraint on the data type.
Header file for the MultExprTrait class template.
Compile time check to query the requirement to evaluate an expression.Via this type trait it is possi...
Definition: RequiresEvaluation.h:90
MRT::ElementType MET
Element type of the left-hand side dense matrix expression.
Definition: DMatDVecMultExpr.h:116
const This & CompositeType
Data type for composite expression templates.
Definition: CompressedMatrix.h:259
SelectType< evaluateVector, const VRT, VCT >::Type RT
Type for the assignment of the right-hand side dense vector operand.
Definition: DMatDVecMultExpr.h:268
Compile time type selection.The SelectType class template selects one of the two given types T1 and T...
Definition: SelectType.h:59
Header file for the DisableIf class template.
Header file for the multiplication trait.
Header file for the IsDouble type trait.
#define BLAZE_CONSTRAINT_MUST_BE_DOUBLE_TYPE(T)
Constraint on the data type.This compile time constraint checks that the given data type T is of type...
Definition: Double.h:80
Header file for the IsMatMatMultExpr type trait class.
BLAZE_ALWAYS_INLINE void assign(Matrix< MT1, SO1 > &lhs, const Matrix< MT2, SO2 > &rhs)
Default implementation of the assignment of a matrix to a matrix.
Definition: Matrix.h:635
Header file for the IsBlasCompatible type trait.
Base class for N-dimensional dense vectors.The DenseVector class is a base class for all arbitrarily ...
Definition: DenseVector.h:70
#define BLAZE_CONSTRAINT_MUST_BE_SAME_TYPE(A, B)
Data type constraint.In case the two types A and B are not the same (ignoring all cv-qualifiers of bo...
Definition: SameType.h:89
MT::CompositeType MCT
Composite type of the left-hand side dense matrix expression.
Definition: DMatDVecMultExpr.h:118
LeftOperand leftOperand() const
Returns the left-hand side dense matrix operand.
Definition: DMatDVecMultExpr.h:341
#define BLAZE_BLAS_MODE
Compilation switch for the BLAS mode.This compilation switch enables/disables the BLAS mode...
Definition: BLAS.h:65
bool canSMPAssign() const
Returns whether the expression can be used in SMP assignments.
Definition: DMatDVecMultExpr.h:395
Constraint on the data type.
Base class for all matrix/vector multiplication expression templates.The MatVecMultExpr class serves ...
Definition: MatVecMultExpr.h:66
#define BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE(T)
Constraint on the data type.In case the given data type T is not a reference type, a compilation error is created.
Definition: Reference.h:78
#define BLAZE_CONSTRAINT_MUST_FORM_VALID_MATVECMULTEXPR(T1, T2)
Constraint on the data type.In case the given data types T1 and T2 do not form a valid matrix/vector ...
Definition: MatVecMultExpr.h:166
SelectType< evaluateMatrix, const MRT, MCT >::Type LT
Type for the assignment of the left-hand side dense matrix operand.
Definition: DMatDVecMultExpr.h:265
Constraints on the storage order of matrix types.
Constraint on the data type.
ResultType::ElementType ElementType
Resulting element type.
Definition: DMatDVecMultExpr.h:253
Type ElementType
Type of the sparse matrix elements.
Definition: CompressedMatrix.h:2476
Header file for the SelectType class template.
Header file for all forward declarations for expression class templates.
LeftOperand mat_
Left-hand side dense matrix of the multiplication expression.
Definition: DMatDVecMultExpr.h:405
Header file for the EnableIf class template.
Header file for the serial shim.
Header file for the IsNumeric type trait.
EnableIf< IsDenseMatrix< MT1 > >::Type smpSubAssign(Matrix< MT1, SO1 > &lhs, const Matrix< MT2, SO2 > &rhs)
Default implementation of the SMP subtraction assignment of a matrix to dense matrix.
Definition: DenseMatrix.h:160
#define BLAZE_CONSTRAINT_MUST_NOT_BE_SYMMETRIC_MATRIX_TYPE(T)
Constraint on the data type.In case the given data type T is a symmetric matrix type, a compilation error is created.
Definition: Symmetric.h:116
Header file for the SubmatrixExprTrait class template.
#define BLAZE_CONSTRAINT_MUST_BE_ROW_MAJOR_MATRIX_TYPE(T)
Constraint on the data type.In case the given data type T is not a row-major dense or sparse matrix t...
Definition: StorageOrder.h:81
System settings for the BLAS mode.
Intrinsic characteristics of data types.The IntrinsicTrait class template provides the intrinsic char...
Definition: IntrinsicTrait.h:749
Header file for run time assertion macros.
EnableIf< IsDenseMatrix< MT1 > >::Type smpAssign(Matrix< MT1, SO1 > &lhs, const Matrix< MT2, SO2 > &rhs)
Default implementation of the SMP assignment of a matrix to a dense matrix.
Definition: DenseMatrix.h:98
Base template for the MultTrait class.
Definition: MultTrait.h:142
BLAZE_ALWAYS_INLINE void addAssign(Matrix< MT1, SO1 > &lhs, const Matrix< MT2, SO2 > &rhs)
Default implementation of the addition assignment of a matrix to a matrix.
Definition: Matrix.h:742
RightOperand vec_
Right-hand side dense vector of the multiplication expression.
Definition: DMatDVecMultExpr.h:406
bool canAlias(const T *alias) const
Returns whether the expression can alias with the given address alias.
Definition: DMatDVecMultExpr.h:363
VT::ResultType VRT
Result type of the right-hand side dense vector expression.
Definition: DMatDVecMultExpr.h:115
#define BLAZE_CONSTRAINT_MUST_BE_NUMERIC_TYPE(T)
Constraint on the data type.In case the given data type T is not a numeric (integral or floating poin...
Definition: Numeric.h:79
Header file for the reset shim.
const ResultType CompositeType
Data type for composite expression templates.
Definition: DMatDVecMultExpr.h:256
Compile time check for data types.This type trait tests whether or not the given template parameter i...
Definition: IsBlasCompatible.h:99
SelectType< IsExpression< MT >::value, const MT, const MT & >::Type LeftOperand
Composite type of the left-hand side dense matrix expression.
Definition: DMatDVecMultExpr.h:259
Constraint on the data type.
bool isAliased(const T *alias) const
Returns whether the expression is aliased with the given address alias.
Definition: DMatDVecMultExpr.h:375
BLAZE_ALWAYS_INLINE void reset(const NonNumericProxy< MT > &proxy)
Resetting the represented element to the default initial values.
Definition: NonNumericProxy.h:833
ResultType::TransposeType TransposeType
Transpose type for expression template evaluations.
Definition: DMatDVecMultExpr.h:252
Header file for all intrinsic functionality.
#define BLAZE_CONSTRAINT_MUST_BE_DENSE_VECTOR_TYPE(T)
Constraint on the data type.In case the given data type T is not a dense, N-dimensional vector type...
Definition: DenseVector.h:79
#define BLAZE_CONSTRAINT_MUST_BE_COMPLEX_TYPE(T)
Constraint on the data type.This compile time constraint checks that the given data type T is a compl...
Definition: Complex.h:80
Header file for the IsComputation type trait class.
CompressedMatrix< Type,!SO > TransposeType
Transpose type for expression template evaluations.
Definition: CompressedMatrix.h:256
Base class for all compute expression templates.The Computation class serves as a tag for all computa...
Definition: Computation.h:59
EnableIf< IsDenseMatrix< MT1 > >::Type smpAddAssign(Matrix< MT1, SO1 > &lhs, const Matrix< MT2, SO2 > &rhs)
Default implementation of the SMP addition assignment of a matrix to a dense matrix.
Definition: DenseMatrix.h:129
IntrinsicTrait< ElementType >::Type IntrinsicType
Resulting intrinsic element type.
Definition: DMatDVecMultExpr.h:254
#define BLAZE_FUNCTION_TRACE
Function trace macro.This macro can be used to reliably trace function calls. In case function tracin...
Definition: FunctionTrace.h:157
This ResultType
Result type for expression template evaluations.
Definition: CompressedMatrix.h:2473
BLAZE_ALWAYS_INLINE size_t columns(const Matrix< MT, SO > &matrix)
Returns the current number of columns of the matrix.
Definition: Matrix.h:332
const ElementType ReturnType
Return type for expression template evaluations.
Definition: DMatDVecMultExpr.h:255
Header file for basic type definitions.
Header file for the IsComplex type trait.
Header file for the SubvectorExprTrait class template.
Constraint on the data type.
Header file for the complex data type.
ReturnType operator[](size_t index) const
Subscript operator for the direct access to the vector elements.
Definition: DMatDVecMultExpr.h:304
Header file for the MatVecMultExpr base class.
Compile time check for single precision floating point types.This type trait tests whether or not the...
Definition: IsFloat.h:75
const size_t DMATDVECMULT_THRESHOLD
Row-major dense matrix/dense vector multiplication threshold.This setting specifies the threshold bet...
Definition: Thresholds.h:57
VRT::ElementType VET
Element type of the right-hand side dense vector expression.
Definition: DMatDVecMultExpr.h:117
Constraint on the data type.
EnableIf< IsDenseVector< VT1 > >::Type smpMultAssign(Vector< VT1, TF1 > &lhs, const Vector< VT2, TF2 > &rhs)
Default implementation of the SMP multiplication assignment of a vector to a dense vector...
Definition: DenseVector.h:189
Header file for the Size type trait.
Size type of the Blaze library.
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 IsExpression type trait class.
Header file for the FunctionTrace class.
BLAZE_ALWAYS_INLINE void subAssign(Matrix< MT1, SO1 > &lhs, const Matrix< MT2, SO2 > &rhs)
Default implementation of the subtraction assignment of a matrix to matrix.
Definition: Matrix.h:849