All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
DMatDVecMultExpr.h
Go to the documentation of this file.
1 //=================================================================================================
20 //=================================================================================================
21 
22 #ifndef _BLAZE_MATH_EXPRESSIONS_DMATDVECMULTEXPR_H_
23 #define _BLAZE_MATH_EXPRESSIONS_DMATDVECMULTEXPR_H_
24 
25 
26 //*************************************************************************************************
27 // Includes
28 //*************************************************************************************************
29 
30 #include <stdexcept>
31 #include <boost/cast.hpp>
40 #include <blaze/math/Intrinsics.h>
41 #include <blaze/math/shims/Reset.h>
50 #include <blaze/system/BLAS.h>
52 #include <blaze/util/Assert.h>
53 #include <blaze/util/Complex.h>
58 #include <blaze/util/DisableIf.h>
59 #include <blaze/util/EnableIf.h>
60 #include <blaze/util/SelectType.h>
61 #include <blaze/util/Types.h>
67 
68 
69 namespace blaze {
70 
71 //=================================================================================================
72 //
73 // CLASS DMATDVECMULTEXPR
74 //
75 //=================================================================================================
76 
77 //*************************************************************************************************
84 template< typename MT // Type of the left-hand side dense matrix
85  , typename VT > // Type of the right-hand side dense vector
86 class DMatDVecMultExpr : public DenseVector< DMatDVecMultExpr<MT,VT>, false >
87  , private Expression
88  , private Computation
89 {
90  private:
91  //**Type definitions****************************************************************************
92  typedef typename MT::ResultType MRT;
93  typedef typename VT::ResultType VRT;
94  typedef typename MRT::ElementType MET;
95  typedef typename VRT::ElementType VET;
96  typedef typename MT::CompositeType MCT;
97  typedef typename VT::CompositeType VCT;
98  //**********************************************************************************************
99 
100  //**********************************************************************************************
102  enum { evaluate = IsComputation<MT>::value && !MT::vectorizable &&
104  //**********************************************************************************************
105 
106  //**********************************************************************************************
108 
109 
112  template< typename T1, typename T2, typename T3 >
113  struct UseSinglePrecisionKernel {
117  };
119  //**********************************************************************************************
120 
121  //**********************************************************************************************
123 
124 
127  template< typename T1, typename T2, typename T3 >
128  struct UseDoublePrecisionKernel {
129  enum { value = IsDouble<typename T1::ElementType>::value &&
130  IsDouble<typename T2::ElementType>::value &&
131  IsDouble<typename T3::ElementType>::value };
132  };
134  //**********************************************************************************************
135 
136  //**********************************************************************************************
138 
139 
142  template< typename T1, typename T2, typename T3 >
143  struct UseSinglePrecisionComplexKernel {
144  typedef complex<float> Type;
145  enum { value = IsSame<typename T1::ElementType,Type>::value &&
146  IsSame<typename T2::ElementType,Type>::value &&
147  IsSame<typename T3::ElementType,Type>::value };
148  };
150  //**********************************************************************************************
151 
152  //**********************************************************************************************
154 
155 
158  template< typename T1, typename T2, typename T3 >
159  struct UseDoublePrecisionComplexKernel {
160  typedef complex<double> Type;
161  enum { value = IsSame<typename T1::ElementType,Type>::value &&
162  IsSame<typename T2::ElementType,Type>::value &&
163  IsSame<typename T3::ElementType,Type>::value };
164  };
166  //**********************************************************************************************
167 
168  //**********************************************************************************************
170 
171 
173  template< typename T1, typename T2, typename T3 >
174  struct UseDefaultKernel {
175  enum { value = !BLAZE_BLAS_MODE || ( !UseSinglePrecisionKernel<T1,T2,T3>::value &&
176  !UseDoublePrecisionKernel<T1,T2,T3>::value &&
177  !UseSinglePrecisionComplexKernel<T1,T2,T3>::value &&
178  !UseDoublePrecisionComplexKernel<T1,T2,T3>::value ) };
179  };
181  //**********************************************************************************************
182 
183  //**********************************************************************************************
185 
186 
189  template< typename T1, typename T2, typename T3 >
190  struct UseVectorizedDefaultKernel {
191  enum { value = T1::vectorizable && T2::vectorizable && T3::vectorizable &&
192  IsSame<typename T1::ElementType,typename T2::ElementType>::value &&
193  IsSame<typename T1::ElementType,typename T3::ElementType>::value &&
194  IntrinsicTrait<typename T1::ElementType>::addition &&
195  IntrinsicTrait<typename T1::ElementType>::multiplication };
196  };
198  //**********************************************************************************************
199 
200  public:
201  //**Type definitions****************************************************************************
204  typedef typename ResultType::TransposeType TransposeType;
205  typedef typename ResultType::ElementType ElementType;
207  typedef const ElementType ReturnType;
208  typedef const ResultType CompositeType;
209 
211  typedef typename SelectType< IsExpression<MT>::value, const MT, const MT& >::Type LeftOperand;
212 
214  typedef typename SelectType< IsExpression<VT>::value, const VT, const VT& >::Type RightOperand;
215 
218 
220  typedef typename SelectType< IsComputation<VT>::value, const VRT, VCT >::Type RT;
221  //**********************************************************************************************
222 
223  //**Compilation flags***************************************************************************
225  enum { vectorizable = 0 };
226 
228  enum { canAlias = ( !evaluate && IsComputation<MT>::value &&
231  //**********************************************************************************************
232 
233  //**Constructor*********************************************************************************
239  explicit inline DMatDVecMultExpr( const MT& mat, const VT& vec )
240  : mat_( mat ) // Left-hand side dense matrix of the multiplication expression
241  , vec_( vec ) // Right-hand side dense vector of the multiplication expression
242  , end_( ( (mat.columns()-1UL) & size_t(-2) ) + 1UL ) // End of the unrolled calculation loop
243  {
244  BLAZE_INTERNAL_ASSERT( mat_.columns() == vec_.size(), "Invalid matrix and vector sizes" );
245  }
246  //**********************************************************************************************
247 
248  //**Subscript operator**************************************************************************
254  inline ReturnType operator[]( size_t index ) const {
255  BLAZE_INTERNAL_ASSERT( index < mat_.rows(), "Invalid vector access index" );
256 
257  ElementType res;
258 
259  if( mat_.columns() != 0UL ) {
260  res = mat_(index,0UL) * vec_[0UL];
261  for( size_t j=1UL; j<end_; j+=2UL ) {
262  res += mat_(index,j) * vec_[j] + mat_(index,j+1UL) * vec_[j+1UL];
263  }
264  if( end_ < mat_.columns() ) {
265  res += mat_(index,end_) * vec_[end_];
266  }
267  }
268  else {
269  reset( res );
270  }
271 
272  return res;
273  }
274  //**********************************************************************************************
275 
276  //**Size function*******************************************************************************
281  inline size_t size() const {
282  return mat_.rows();
283  }
284  //**********************************************************************************************
285 
286  //**Left function*******************************************************************************
291  inline LeftOperand leftOperand() const {
292  return mat_;
293  }
294  //**********************************************************************************************
295 
296  //**Right function******************************************************************************
301  inline RightOperand rightOperand() const {
302  return vec_;
303  }
304  //**********************************************************************************************
305 
306  //**********************************************************************************************
312  template< typename T >
313  inline bool isAliased( const T* alias ) const {
314  return ( !evaluate && IsComputation<MT>::value && !RequiresEvaluation<MT>::value &&
315  CanAlias<MT>::value && mat_.isAliased( alias ) ) ||
316  ( !IsComputation<VT>::value && vec_.isAliased( alias ) );
317  }
318  //**********************************************************************************************
319 
320  private:
321  //**Member variables****************************************************************************
324  const size_t end_;
325  //**********************************************************************************************
326 
327  //**Assignment to dense vectors*****************************************************************
339  template< typename VT1 > // Type of the target dense vector
340  friend inline void assign( DenseVector<VT1,false>& lhs, const DMatDVecMultExpr& rhs )
341  {
342  BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
343 
344  if( rhs.mat_.rows() == 0UL ) {
345  return;
346  }
347  else if( rhs.mat_.columns() == 0UL ) {
348  reset( ~lhs );
349  return;
350  }
351 
352  LT A( rhs.mat_ ); // Evaluation of the left-hand side dense matrix operand
353  RT x( rhs.vec_ ); // Evaluation of the right-hand side dense vector operand
354 
355  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.mat_.rows() , "Invalid number of rows" );
356  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.mat_.columns(), "Invalid number of columns" );
357  BLAZE_INTERNAL_ASSERT( x.size() == rhs.vec_.size() , "Invalid vector size" );
358  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).size() , "Invalid vector size" );
359 
360  if( ( IsComputation<MT>::value && !evaluate ) ||
361  ( A.rows() * A.columns() < DMATDVECMULT_THRESHOLD ) )
362  DMatDVecMultExpr::selectDefaultAssignKernel( ~lhs, A, x );
363  else
364  DMatDVecMultExpr::selectBlasAssignKernel( ~lhs, A, x );
365  }
367  //**********************************************************************************************
368 
369  //**Default assignment to dense vectors*********************************************************
383  template< typename VT1 // Type of the left-hand side target vector
384  , typename MT1 // Type of the left-hand side matrix operand
385  , typename VT2 > // Type of the right-hand side vector operand
386  static inline typename DisableIf< UseVectorizedDefaultKernel<VT1,MT1,VT2> >::Type
387  selectDefaultAssignKernel( VT1& y, const MT1& A, const VT2& x )
388  {
389  y.assign( A * x );
390  }
392  //**********************************************************************************************
393 
394  //**Vectorized default assignment to dense vectors**********************************************
408  template< typename VT1 // Type of the left-hand side target vector
409  , typename MT1 // Type of the left-hand side matrix operand
410  , typename VT2 > // Type of the right-hand side vector operand
411  static inline typename EnableIf< UseVectorizedDefaultKernel<VT1,MT1,VT2> >::Type
412  selectDefaultAssignKernel( VT1& y, const MT1& A, const VT2& x )
413  {
414  typedef IntrinsicTrait<ElementType> IT;
415 
416  const size_t M( A.rows() );
417  const size_t N( A.columns() );
418 
419  size_t i( 0UL );
420 
421  for( ; (i+8UL) <= M; i+=8UL ) {
422  IntrinsicType xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7, xmm8;
423  for( size_t j=0UL; j<N; j+=IT::size ) {
424  const IntrinsicType x1( x.get(j) );
425  xmm1 = xmm1 + A.get(i ,j) * x1;
426  xmm2 = xmm2 + A.get(i+1UL,j) * x1;
427  xmm3 = xmm3 + A.get(i+2UL,j) * x1;
428  xmm4 = xmm4 + A.get(i+3UL,j) * x1;
429  xmm5 = xmm5 + A.get(i+4UL,j) * x1;
430  xmm6 = xmm6 + A.get(i+5UL,j) * x1;
431  xmm7 = xmm7 + A.get(i+6UL,j) * x1;
432  xmm8 = xmm8 + A.get(i+7UL,j) * x1;
433  }
434  y[i ] = sum( xmm1 );
435  y[i+1UL] = sum( xmm2 );
436  y[i+2UL] = sum( xmm3 );
437  y[i+3UL] = sum( xmm4 );
438  y[i+4UL] = sum( xmm5 );
439  y[i+5UL] = sum( xmm6 );
440  y[i+6UL] = sum( xmm7 );
441  y[i+7UL] = sum( xmm8 );
442  }
443  for( ; (i+4UL) <= M; i+=4UL ) {
444  IntrinsicType xmm1, xmm2, xmm3, xmm4;
445  for( size_t j=0UL; j<N; j+=IT::size ) {
446  const IntrinsicType x1( x.get(j) );
447  xmm1 = xmm1 + A.get(i ,j) * x1;
448  xmm2 = xmm2 + A.get(i+1UL,j) * x1;
449  xmm3 = xmm3 + A.get(i+2UL,j) * x1;
450  xmm4 = xmm4 + A.get(i+3UL,j) * x1;
451  }
452  y[i ] = sum( xmm1 );
453  y[i+1UL] = sum( xmm2 );
454  y[i+2UL] = sum( xmm3 );
455  y[i+3UL] = sum( xmm4 );
456  }
457  for( ; (i+3UL) <= M; i+=3UL ) {
458  IntrinsicType xmm1, xmm2, xmm3;
459  for( size_t j=0UL; j<N; j+=IT::size ) {
460  const IntrinsicType x1( x.get(j) );
461  xmm1 = xmm1 + A.get(i ,j) * x1;
462  xmm2 = xmm2 + A.get(i+1UL,j) * x1;
463  xmm3 = xmm3 + A.get(i+2UL,j) * x1;
464  }
465  y[i ] = sum( xmm1 );
466  y[i+1UL] = sum( xmm2 );
467  y[i+2UL] = sum( xmm3 );
468  }
469  for( ; (i+2UL) <= M; i+=2UL ) {
470  IntrinsicType xmm1, xmm2;
471  for( size_t j=0UL; j<N; j+=IT::size ) {
472  const IntrinsicType x1( x.get(j) );
473  xmm1 = xmm1 + A.get(i ,j) * x1;
474  xmm2 = xmm2 + A.get(i+1UL,j) * x1;
475  }
476  y[i ] = sum( xmm1 );
477  y[i+1UL] = sum( xmm2 );
478  }
479  if( i < M ) {
480  IntrinsicType xmm1;
481  for( size_t j=0UL; j<N; j+=IT::size ) {
482  xmm1 = xmm1 + A.get(i,j) * x.get(j);
483  }
484  y[i] = sum( xmm1 );
485  }
486  }
488  //**********************************************************************************************
489 
490  //**BLAS-based assignment to dense vectors (default)********************************************
504  template< typename VT1 // Type of the left-hand side target vector
505  , typename MT1 // Type of the left-hand side matrix operand
506  , typename VT2 > // Type of the right-hand side vector operand
507  static inline typename EnableIf< UseDefaultKernel<VT1,MT1,VT2> >::Type
508  selectBlasAssignKernel( VT1& y, const MT1& A, const VT2& x )
509  {
510  selectDefaultAssignKernel( y, A, x );
511  }
513  //**********************************************************************************************
514 
515  //**BLAS-based assignment to dense vectors (single precision)***********************************
516 #if BLAZE_BLAS_MODE
517 
530  template< typename VT1 // Type of the left-hand side target vector
531  , typename MT1 // Type of the left-hand side matrix operand
532  , typename VT2 > // Type of the right-hand side vector operand
533  static inline typename EnableIf< UseSinglePrecisionKernel<VT1,MT1,VT2> >::Type
534  selectBlasAssignKernel( VT1& y, const MT1& A, const VT2& x )
535  {
536  using boost::numeric_cast;
537 
538  BLAZE_CONSTRAINT_MUST_BE_FLOAT_TYPE( typename VT1::ElementType );
539  BLAZE_CONSTRAINT_MUST_BE_FLOAT_TYPE( typename MT1::ElementType );
540  BLAZE_CONSTRAINT_MUST_BE_FLOAT_TYPE( typename VT2::ElementType );
541 
542  const int M ( numeric_cast<int>( A.rows() ) );
543  const int N ( numeric_cast<int>( A.columns() ) );
544  const int lda( numeric_cast<int>( A.spacing() ) );
545 
546  cblas_sgemv( CblasRowMajor, CblasNoTrans, M, N, 1.0F,
547  A.data(), lda, x.data(), 1, 0.0F, y.data(), 1 );
548  }
550 #endif
551  //**********************************************************************************************
552 
553  //**BLAS-based assignment to dense vectors (double precision)***********************************
554 #if BLAZE_BLAS_MODE
555 
568  template< typename VT1 // Type of the left-hand side target vector
569  , typename MT1 // Type of the left-hand side matrix operand
570  , typename VT2 > // Type of the right-hand side vector operand
571  static inline typename EnableIf< UseDoublePrecisionKernel<VT1,MT1,VT2> >::Type
572  selectBlasAssignKernel( VT1& y, const MT1& A, const VT2& x )
573  {
574  using boost::numeric_cast;
575 
576  BLAZE_CONSTRAINT_MUST_BE_DOUBLE_TYPE( typename VT1::ElementType );
577  BLAZE_CONSTRAINT_MUST_BE_DOUBLE_TYPE( typename MT1::ElementType );
578  BLAZE_CONSTRAINT_MUST_BE_DOUBLE_TYPE( typename VT2::ElementType );
579 
580  const int M ( numeric_cast<int>( A.rows() ) );
581  const int N ( numeric_cast<int>( A.columns() ) );
582  const int lda( numeric_cast<int>( A.spacing() ) );
583 
584  cblas_dgemv( CblasRowMajor, CblasNoTrans, M, N, 1.0,
585  A.data(), lda, x.data(), 1, 0.0, y.data(), 1 );
586  }
588 #endif
589  //**********************************************************************************************
590 
591  //**BLAS-based assignment to dense vectors (single precision complex)***************************
592 #if BLAZE_BLAS_MODE
593 
606  template< typename VT1 // Type of the left-hand side target vector
607  , typename MT1 // Type of the left-hand side matrix operand
608  , typename VT2 > // Type of the right-hand side vector operand
609  static inline typename EnableIf< UseSinglePrecisionComplexKernel<VT1,MT1,VT2> >::Type
610  selectBlasAssignKernel( VT1& y, const MT1& A, const VT2& x )
611  {
612  using boost::numeric_cast;
613 
614  BLAZE_CONSTRAINT_MUST_BE_COMPLEX_TYPE( typename VT1::ElementType );
615  BLAZE_CONSTRAINT_MUST_BE_COMPLEX_TYPE( typename MT1::ElementType );
616  BLAZE_CONSTRAINT_MUST_BE_COMPLEX_TYPE( typename VT2::ElementType );
617  BLAZE_CONSTRAINT_MUST_BE_FLOAT_TYPE ( typename VT1::ElementType::value_type );
618  BLAZE_CONSTRAINT_MUST_BE_FLOAT_TYPE ( typename MT1::ElementType::value_type );
619  BLAZE_CONSTRAINT_MUST_BE_FLOAT_TYPE ( typename VT2::ElementType::value_type );
620 
621  const int M ( numeric_cast<int>( A.rows() ) );
622  const int N ( numeric_cast<int>( A.columns() ) );
623  const int lda( numeric_cast<int>( A.spacing() ) );
624  const complex<float> alpha( 1.0F, 0.0F );
625  const complex<float> beta ( 0.0F, 0.0F );
626 
627  cblas_cgemv( CblasRowMajor, CblasNoTrans, M, N, &alpha,
628  A.data(), lda, x.data(), 1, &beta, y.data(), 1 );
629  }
631 #endif
632  //**********************************************************************************************
633 
634  //**BLAS-based assignment to dense vectors (double precision complex)***************************
635 #if BLAZE_BLAS_MODE
636 
649  template< typename VT1 // Type of the left-hand side target vector
650  , typename MT1 // Type of the left-hand side matrix operand
651  , typename VT2 > // Type of the right-hand side vector operand
652  static inline typename EnableIf< UseDoublePrecisionComplexKernel<VT1,MT1,VT2> >::Type
653  selectBlasAssignKernel( VT1& y, const MT1& A, const VT2& x )
654  {
655  using boost::numeric_cast;
656 
657  BLAZE_CONSTRAINT_MUST_BE_COMPLEX_TYPE( typename VT1::ElementType );
658  BLAZE_CONSTRAINT_MUST_BE_COMPLEX_TYPE( typename MT1::ElementType );
659  BLAZE_CONSTRAINT_MUST_BE_COMPLEX_TYPE( typename VT2::ElementType );
660  BLAZE_CONSTRAINT_MUST_BE_DOUBLE_TYPE ( typename VT1::ElementType::value_type );
661  BLAZE_CONSTRAINT_MUST_BE_DOUBLE_TYPE ( typename MT1::ElementType::value_type );
662  BLAZE_CONSTRAINT_MUST_BE_DOUBLE_TYPE ( typename VT2::ElementType::value_type );
663 
664  const int M ( numeric_cast<int>( A.rows() ) );
665  const int N ( numeric_cast<int>( A.columns() ) );
666  const int lda( numeric_cast<int>( A.spacing() ) );
667  const complex<double> alpha( 1.0, 0.0 );
668  const complex<double> beta ( 0.0, 0.0 );
669 
670  cblas_zgemv( CblasRowMajor, CblasNoTrans, M, N, &alpha,
671  A.data(), lda, x.data(), 1, &beta, y.data(), 1 );
672  }
674 #endif
675  //**********************************************************************************************
676 
677  //**Assignment to sparse vectors****************************************************************
689  template< typename VT1 > // Type of the target sparse vector
690  friend inline void assign( SparseVector<VT1,false>& lhs, const DMatDVecMultExpr& rhs )
691  {
694  BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( typename ResultType::CompositeType );
695 
696  BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
697 
698  const ResultType tmp( rhs );
699  assign( ~lhs, tmp );
700  }
702  //**********************************************************************************************
703 
704  //**Addition assignment to dense vectors********************************************************
716  template< typename VT1 > // Type of the target dense vector
717  friend inline void addAssign( DenseVector<VT1,false>& lhs, const DMatDVecMultExpr& rhs )
718  {
719  BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
720 
721  if( rhs.mat_.rows() == 0UL || rhs.mat_.columns() == 0UL ) {
722  return;
723  }
724 
725  LT A( rhs.mat_ ); // Evaluation of the left-hand side dense matrix operand
726  RT x( rhs.vec_ ); // Evaluation of the right-hand side dense vector operand
727 
728  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.mat_.rows() , "Invalid number of rows" );
729  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.mat_.columns(), "Invalid number of columns" );
730  BLAZE_INTERNAL_ASSERT( x.size() == rhs.vec_.size() , "Invalid vector size" );
731  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).size() , "Invalid vector size" );
732 
733  if( ( IsComputation<MT>::value && !evaluate ) ||
734  ( A.rows() * A.columns() < DMATDVECMULT_THRESHOLD ) )
735  DMatDVecMultExpr::selectDefaultAddAssignKernel( ~lhs, A, x );
736  else
737  DMatDVecMultExpr::selectBlasAddAssignKernel( ~lhs, A, x );
738  }
740  //**********************************************************************************************
741 
742  //**Default addition assignment to dense vectors************************************************
756  template< typename VT1 // Type of the left-hand side target vector
757  , typename MT1 // Type of the left-hand side matrix operand
758  , typename VT2 > // Type of the right-hand side vector operand
759  static inline typename DisableIf< UseVectorizedDefaultKernel<VT1,MT1,VT2> >::Type
760  selectDefaultAddAssignKernel( VT1& y, const MT1& A, const VT2& x )
761  {
762  y.addAssign( A * x );
763  }
765  //**********************************************************************************************
766 
767  //**Vectorized default addition assignment to dense vectors*************************************
781  template< typename VT1 // Type of the left-hand side target vector
782  , typename MT1 // Type of the left-hand side matrix operand
783  , typename VT2 > // Type of the right-hand side vector operand
784  static inline typename EnableIf< UseVectorizedDefaultKernel<VT1,MT1,VT2> >::Type
785  selectDefaultAddAssignKernel( VT1& y, const MT1& A, const VT2& x )
786  {
787  typedef IntrinsicTrait<ElementType> IT;
788 
789  const size_t M( A.rows() );
790  const size_t N( A.columns() );
791 
792  size_t i( 0UL );
793 
794  for( ; (i+8UL) <= M; i+=8UL ) {
795  IntrinsicType xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7, xmm8;
796  for( size_t j=0UL; j<N; j+=IT::size ) {
797  const IntrinsicType x1( x.get(j) );
798  xmm1 = xmm1 + A.get(i ,j) * x1;
799  xmm2 = xmm2 + A.get(i+1UL,j) * x1;
800  xmm3 = xmm3 + A.get(i+2UL,j) * x1;
801  xmm4 = xmm4 + A.get(i+3UL,j) * x1;
802  xmm5 = xmm5 + A.get(i+4UL,j) * x1;
803  xmm6 = xmm6 + A.get(i+5UL,j) * x1;
804  xmm7 = xmm7 + A.get(i+6UL,j) * x1;
805  xmm8 = xmm8 + A.get(i+7UL,j) * x1;
806  }
807  y[i ] += sum( xmm1 );
808  y[i+1UL] += sum( xmm2 );
809  y[i+2UL] += sum( xmm3 );
810  y[i+3UL] += sum( xmm4 );
811  y[i+4UL] += sum( xmm5 );
812  y[i+5UL] += sum( xmm6 );
813  y[i+6UL] += sum( xmm7 );
814  y[i+7UL] += sum( xmm8 );
815  }
816  for( ; (i+4UL) <= M; i+=4UL ) {
817  IntrinsicType xmm1, xmm2, xmm3, xmm4;
818  for( size_t j=0UL; j<N; j+=IT::size ) {
819  const IntrinsicType x1( x.get(j) );
820  xmm1 = xmm1 + A.get(i ,j) * x1;
821  xmm2 = xmm2 + A.get(i+1UL,j) * x1;
822  xmm3 = xmm3 + A.get(i+2UL,j) * x1;
823  xmm4 = xmm4 + A.get(i+3UL,j) * x1;
824  }
825  y[i ] += sum( xmm1 );
826  y[i+1UL] += sum( xmm2 );
827  y[i+2UL] += sum( xmm3 );
828  y[i+3UL] += sum( xmm4 );
829  }
830  for( ; (i+3UL) <= M; i+=3UL ) {
831  IntrinsicType xmm1, xmm2, xmm3;
832  for( size_t j=0UL; j<N; j+=IT::size ) {
833  const IntrinsicType x1( x.get(j) );
834  xmm1 = xmm1 + A.get(i ,j) * x1;
835  xmm2 = xmm2 + A.get(i+1UL,j) * x1;
836  xmm3 = xmm3 + A.get(i+2UL,j) * x1;
837  }
838  y[i ] += sum( xmm1 );
839  y[i+1UL] += sum( xmm2 );
840  y[i+2UL] += sum( xmm3 );
841  }
842  for( ; (i+2UL) <= M; i+=2UL ) {
843  IntrinsicType xmm1, xmm2;
844  for( size_t j=0UL; j<N; j+=IT::size ) {
845  const IntrinsicType x1( x.get(j) );
846  xmm1 = xmm1 + A.get(i ,j) * x1;
847  xmm2 = xmm2 + A.get(i+1UL,j) * x1;
848  }
849  y[i ] += sum( xmm1 );
850  y[i+1UL] += sum( xmm2 );
851  }
852  if( i < M ) {
853  IntrinsicType xmm1;
854  for( size_t j=0UL; j<N; j+=IT::size ) {
855  xmm1 = xmm1 + A.get(i,j) * x.get(j);
856  }
857  y[i] += sum( xmm1 );
858  }
859  }
861  //**********************************************************************************************
862 
863  //**BLAS-based addition assignment to dense vectors (default)***********************************
877  template< typename VT1 // Type of the left-hand side target vector
878  , typename MT1 // Type of the left-hand side matrix operand
879  , typename VT2 > // Type of the right-hand side vector operand
880  static inline typename EnableIf< UseDefaultKernel<VT1,MT1,VT2> >::Type
881  selectBlasAddAssignKernel( VT1& y, const MT1& A, const VT2& x )
882  {
883  selectDefaultAddAssignKernel( y, A, x );
884  }
886  //**********************************************************************************************
887 
888  //**BLAS-based addition assignment to dense vectors (single precision)**************************
889 #if BLAZE_BLAS_MODE
890 
903  template< typename VT1 // Type of the left-hand side target vector
904  , typename MT1 // Type of the left-hand side matrix operand
905  , typename VT2 > // Type of the right-hand side vector operand
906  static inline typename EnableIf< UseSinglePrecisionKernel<VT1,MT1,VT2> >::Type
907  selectBlasAddAssignKernel( VT1& y, const MT1& A, const VT2& x )
908  {
909  using boost::numeric_cast;
910 
911  BLAZE_CONSTRAINT_MUST_BE_FLOAT_TYPE( typename VT1::ElementType );
912  BLAZE_CONSTRAINT_MUST_BE_FLOAT_TYPE( typename MT1::ElementType );
913  BLAZE_CONSTRAINT_MUST_BE_FLOAT_TYPE( typename VT2::ElementType );
914 
915  const int M ( numeric_cast<int>( A.rows() ) );
916  const int N ( numeric_cast<int>( A.columns() ) );
917  const int lda( numeric_cast<int>( A.spacing() ) );
918 
919  cblas_sgemv( CblasRowMajor, CblasNoTrans, M, N, 1.0F,
920  A.data(), lda, x.data(), 1, 1.0F, y.data(), 1 );
921  }
923 #endif
924  //**********************************************************************************************
925 
926  //**BLAS-based addition assignment to dense vectors (double precision)**************************
927 #if BLAZE_BLAS_MODE
928 
941  template< typename VT1 // Type of the left-hand side target vector
942  , typename MT1 // Type of the left-hand side matrix operand
943  , typename VT2 > // Type of the right-hand side vector operand
944  static inline typename EnableIf< UseDoublePrecisionKernel<VT1,MT1,VT2> >::Type
945  selectBlasAddAssignKernel( VT1& y, const MT1& A, const VT2& x )
946  {
947  using boost::numeric_cast;
948 
949  BLAZE_CONSTRAINT_MUST_BE_DOUBLE_TYPE( typename VT1::ElementType );
950  BLAZE_CONSTRAINT_MUST_BE_DOUBLE_TYPE( typename MT1::ElementType );
951  BLAZE_CONSTRAINT_MUST_BE_DOUBLE_TYPE( typename VT2::ElementType );
952 
953  const int M ( numeric_cast<int>( A.rows() ) );
954  const int N ( numeric_cast<int>( A.columns() ) );
955  const int lda( numeric_cast<int>( A.spacing() ) );
956 
957  cblas_dgemv( CblasRowMajor, CblasNoTrans, M, N, 1.0,
958  A.data(), lda, x.data(), 1, 1.0, y.data(), 1 );
959  }
961 #endif
962  //**********************************************************************************************
963 
964  //**BLAS-based addition assignment to dense vectors (single precision complex)******************
965 #if BLAZE_BLAS_MODE
966 
979  template< typename VT1 // Type of the left-hand side target vector
980  , typename MT1 // Type of the left-hand side matrix operand
981  , typename VT2 > // Type of the right-hand side vector operand
982  static inline typename EnableIf< UseSinglePrecisionComplexKernel<VT1,MT1,VT2> >::Type
983  selectBlasAddAssignKernel( VT1& y, const MT1& A, const VT2& x )
984  {
985  using boost::numeric_cast;
986 
987  BLAZE_CONSTRAINT_MUST_BE_COMPLEX_TYPE( typename VT1::ElementType );
988  BLAZE_CONSTRAINT_MUST_BE_COMPLEX_TYPE( typename MT1::ElementType );
989  BLAZE_CONSTRAINT_MUST_BE_COMPLEX_TYPE( typename VT2::ElementType );
990  BLAZE_CONSTRAINT_MUST_BE_FLOAT_TYPE ( typename VT1::ElementType::value_type );
991  BLAZE_CONSTRAINT_MUST_BE_FLOAT_TYPE ( typename MT1::ElementType::value_type );
992  BLAZE_CONSTRAINT_MUST_BE_FLOAT_TYPE ( typename VT2::ElementType::value_type );
993 
994  const int M ( numeric_cast<int>( A.rows() ) );
995  const int N ( numeric_cast<int>( A.columns() ) );
996  const int lda( numeric_cast<int>( A.spacing() ) );
997  const complex<float> alpha( 1.0F, 0.0F );
998  const complex<float> beta ( 1.0F, 0.0F );
999 
1000  cblas_cgemv( CblasRowMajor, CblasNoTrans, M, N, &alpha,
1001  A.data(), lda, x.data(), 1, &beta, y.data(), 1 );
1002  }
1004 #endif
1005  //**********************************************************************************************
1006 
1007  //**BLAS-based addition assignment to dense vectors (double precision complex)******************
1008 #if BLAZE_BLAS_MODE
1009 
1022  template< typename VT1 // Type of the left-hand side target vector
1023  , typename MT1 // Type of the left-hand side matrix operand
1024  , typename VT2 > // Type of the right-hand side vector operand
1025  static inline typename EnableIf< UseDoublePrecisionComplexKernel<VT1,MT1,VT2> >::Type
1026  selectBlasAddAssignKernel( VT1& y, const MT1& A, const VT2& x )
1027  {
1028  using boost::numeric_cast;
1029 
1030  BLAZE_CONSTRAINT_MUST_BE_COMPLEX_TYPE( typename VT1::ElementType );
1031  BLAZE_CONSTRAINT_MUST_BE_COMPLEX_TYPE( typename MT1::ElementType );
1032  BLAZE_CONSTRAINT_MUST_BE_COMPLEX_TYPE( typename VT2::ElementType );
1033  BLAZE_CONSTRAINT_MUST_BE_DOUBLE_TYPE ( typename VT1::ElementType::value_type );
1034  BLAZE_CONSTRAINT_MUST_BE_DOUBLE_TYPE ( typename MT1::ElementType::value_type );
1035  BLAZE_CONSTRAINT_MUST_BE_DOUBLE_TYPE ( typename VT2::ElementType::value_type );
1036 
1037  const int M ( numeric_cast<int>( A.rows() ) );
1038  const int N ( numeric_cast<int>( A.columns() ) );
1039  const int lda( numeric_cast<int>( A.spacing() ) );
1040  const complex<double> alpha( 1.0, 0.0 );
1041  const complex<double> beta ( 1.0, 0.0 );
1042 
1043  cblas_zgemv( CblasRowMajor, CblasNoTrans, M, N, &alpha,
1044  A.data(), lda, x.data(), 1, &beta, y.data(), 1 );
1045  }
1047 #endif
1048  //**********************************************************************************************
1049 
1050  //**Addition assignment to sparse vectors*******************************************************
1051  // No special implementation for the addition assignment to sparse vectors.
1052  //**********************************************************************************************
1053 
1054  //**Subtraction assignment to dense vectors*****************************************************
1066  template< typename VT1 > // Type of the target dense vector
1067  friend inline void subAssign( DenseVector<VT1,false>& lhs, const DMatDVecMultExpr& rhs )
1068  {
1069  BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
1070 
1071  if( rhs.mat_.rows() == 0UL || rhs.mat_.columns() == 0UL ) {
1072  return;
1073  }
1074 
1075  LT A( rhs.mat_ ); // Evaluation of the left-hand side dense matrix operand
1076  RT x( rhs.vec_ ); // Evaluation of the right-hand side dense vector operand
1077 
1078  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.mat_.rows() , "Invalid number of rows" );
1079  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.mat_.columns(), "Invalid number of columns" );
1080  BLAZE_INTERNAL_ASSERT( x.size() == rhs.vec_.size() , "Invalid vector size" );
1081  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).size() , "Invalid vector size" );
1082 
1083  if( ( IsComputation<MT>::value && !evaluate ) ||
1084  ( A.rows() * A.columns() < DMATDVECMULT_THRESHOLD ) )
1085  DMatDVecMultExpr::selectDefaultSubAssignKernel( ~lhs, A, x );
1086  else
1087  DMatDVecMultExpr::selectBlasSubAssignKernel( ~lhs, A, x );
1088  }
1090  //**********************************************************************************************
1091 
1092  //**Default subtraction assignment to dense vectors*********************************************
1106  template< typename VT1 // Type of the left-hand side target vector
1107  , typename MT1 // Type of the left-hand side matrix operand
1108  , typename VT2 > // Type of the right-hand side vector operand
1109  static inline typename DisableIf< UseVectorizedDefaultKernel<VT1,MT1,VT2> >::Type
1110  selectDefaultSubAssignKernel( VT1& y, const MT1& A, const VT2& x )
1111  {
1112  y.subAssign( A * x );
1113  }
1115  //**********************************************************************************************
1116 
1117  //**Vectorized default subtraction assignment to dense vectors**********************************
1131  template< typename VT1 // Type of the left-hand side target vector
1132  , typename MT1 // Type of the left-hand side matrix operand
1133  , typename VT2 > // Type of the right-hand side vector operand
1134  static inline typename EnableIf< UseVectorizedDefaultKernel<VT1,MT1,VT2> >::Type
1135  selectDefaultSubAssignKernel( VT1& y, const MT1& A, const VT2& x )
1136  {
1137  typedef IntrinsicTrait<ElementType> IT;
1138 
1139  const size_t M( A.rows() );
1140  const size_t N( A.columns() );
1141 
1142  size_t i( 0UL );
1143 
1144  for( ; (i+8UL) <= M; i+=8UL ) {
1145  IntrinsicType xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7, xmm8;
1146  for( size_t j=0UL; j<N; j+=IT::size ) {
1147  const IntrinsicType x1( x.get(j) );
1148  xmm1 = xmm1 + A.get(i ,j) * x1;
1149  xmm2 = xmm2 + A.get(i+1UL,j) * x1;
1150  xmm3 = xmm3 + A.get(i+2UL,j) * x1;
1151  xmm4 = xmm4 + A.get(i+3UL,j) * x1;
1152  xmm5 = xmm5 + A.get(i+4UL,j) * x1;
1153  xmm6 = xmm6 + A.get(i+5UL,j) * x1;
1154  xmm7 = xmm7 + A.get(i+6UL,j) * x1;
1155  xmm8 = xmm8 + A.get(i+7UL,j) * x1;
1156  }
1157  y[i ] -= sum( xmm1 );
1158  y[i+1UL] -= sum( xmm2 );
1159  y[i+2UL] -= sum( xmm3 );
1160  y[i+3UL] -= sum( xmm4 );
1161  y[i+4UL] -= sum( xmm5 );
1162  y[i+5UL] -= sum( xmm6 );
1163  y[i+6UL] -= sum( xmm7 );
1164  y[i+7UL] -= sum( xmm8 );
1165  }
1166  for( ; (i+4UL) <= M; i+=4UL ) {
1167  IntrinsicType xmm1, xmm2, xmm3, xmm4;
1168  for( size_t j=0UL; j<N; j+=IT::size ) {
1169  const IntrinsicType x1( x.get(j) );
1170  xmm1 = xmm1 + A.get(i ,j) * x1;
1171  xmm2 = xmm2 + A.get(i+1UL,j) * x1;
1172  xmm3 = xmm3 + A.get(i+2UL,j) * x1;
1173  xmm4 = xmm4 + A.get(i+3UL,j) * x1;
1174  }
1175  y[i ] -= sum( xmm1 );
1176  y[i+1UL] -= sum( xmm2 );
1177  y[i+2UL] -= sum( xmm3 );
1178  y[i+3UL] -= sum( xmm4 );
1179  }
1180  for( ; (i+3UL) <= M; i+=3UL ) {
1181  IntrinsicType xmm1, xmm2, xmm3;
1182  for( size_t j=0UL; j<N; j+=IT::size ) {
1183  const IntrinsicType x1( x.get(j) );
1184  xmm1 = xmm1 + A.get(i ,j) * x1;
1185  xmm2 = xmm2 + A.get(i+1UL,j) * x1;
1186  xmm3 = xmm3 + A.get(i+2UL,j) * x1;
1187  }
1188  y[i ] -= sum( xmm1 );
1189  y[i+1UL] -= sum( xmm2 );
1190  y[i+2UL] -= sum( xmm3 );
1191  }
1192  for( ; (i+2UL) <= M; i+=2UL ) {
1193  IntrinsicType xmm1, xmm2;
1194  for( size_t j=0UL; j<N; j+=IT::size ) {
1195  const IntrinsicType x1( x.get(j) );
1196  xmm1 = xmm1 + A.get(i ,j) * x1;
1197  xmm2 = xmm2 + A.get(i+1UL,j) * x1;
1198  }
1199  y[i ] -= sum( xmm1 );
1200  y[i+1UL] -= sum( xmm2 );
1201  }
1202  if( i < M ) {
1203  IntrinsicType xmm1;
1204  for( size_t j=0UL; j<N; j+=IT::size ) {
1205  xmm1 = xmm1 + A.get(i,j) * x.get(j);
1206  }
1207  y[i] -= sum( xmm1 );
1208  }
1209  }
1211  //**********************************************************************************************
1212 
1213  //**BLAS-based subtraction assignment to dense vectors (default)********************************
1227  template< typename VT1 // Type of the left-hand side target vector
1228  , typename MT1 // Type of the left-hand side matrix operand
1229  , typename VT2 > // Type of the right-hand side vector operand
1230  static inline typename EnableIf< UseDefaultKernel<VT1,MT1,VT2> >::Type
1231  selectBlasSubAssignKernel( VT1& y, const MT1& A, const VT2& x )
1232  {
1233  selectDefaultSubAssignKernel( y, A, x );
1234  }
1236  //**********************************************************************************************
1237 
1238  //**BLAS-based subtraction assignment to dense vectors (single precision)***********************
1239 #if BLAZE_BLAS_MODE
1240 
1253  template< typename VT1 // Type of the left-hand side target vector
1254  , typename MT1 // Type of the left-hand side matrix operand
1255  , typename VT2 > // Type of the right-hand side vector operand
1256  static inline typename EnableIf< UseSinglePrecisionKernel<VT1,MT1,VT2> >::Type
1257  selectBlasSubAssignKernel( VT1& y, const MT1& A, const VT2& x )
1258  {
1259  using boost::numeric_cast;
1260 
1261  BLAZE_CONSTRAINT_MUST_BE_FLOAT_TYPE( typename VT1::ElementType );
1262  BLAZE_CONSTRAINT_MUST_BE_FLOAT_TYPE( typename MT1::ElementType );
1263  BLAZE_CONSTRAINT_MUST_BE_FLOAT_TYPE( typename VT2::ElementType );
1264 
1265  const int M ( numeric_cast<int>( A.rows() ) );
1266  const int N ( numeric_cast<int>( A.columns() ) );
1267  const int lda( numeric_cast<int>( A.spacing() ) );
1268 
1269  cblas_sgemv( CblasRowMajor, CblasNoTrans, M, N, -1.0F,
1270  A.data(), lda, x.data(), 1, 1.0F, y.data(), 1 );
1271  }
1273 #endif
1274  //**********************************************************************************************
1275 
1276  //**BLAS-based subtraction assignment to dense vectors (double precision)***********************
1277 #if BLAZE_BLAS_MODE
1278 
1291  template< typename VT1 // Type of the left-hand side target vector
1292  , typename MT1 // Type of the left-hand side matrix operand
1293  , typename VT2 > // Type of the right-hand side vector operand
1294  static inline typename EnableIf< UseDoublePrecisionKernel<VT1,MT1,VT2> >::Type
1295  selectBlasSubAssignKernel( VT1& y, const MT1& A, const VT2& x )
1296  {
1297  using boost::numeric_cast;
1298 
1299  BLAZE_CONSTRAINT_MUST_BE_DOUBLE_TYPE( typename VT1::ElementType );
1300  BLAZE_CONSTRAINT_MUST_BE_DOUBLE_TYPE( typename MT1::ElementType );
1301  BLAZE_CONSTRAINT_MUST_BE_DOUBLE_TYPE( typename VT2::ElementType );
1302 
1303  const int M ( numeric_cast<int>( A.rows() ) );
1304  const int N ( numeric_cast<int>( A.columns() ) );
1305  const int lda( numeric_cast<int>( A.spacing() ) );
1306 
1307  cblas_dgemv( CblasRowMajor, CblasNoTrans, M, N, -1.0,
1308  A.data(), lda, x.data(), 1, 1.0, y.data(), 1 );
1309  }
1311 #endif
1312  //**********************************************************************************************
1313 
1314  //**BLAS-based subtraction assignment to dense vectors (single precision complex)***************
1315 #if BLAZE_BLAS_MODE
1316 
1329  template< typename VT1 // Type of the left-hand side target vector
1330  , typename MT1 // Type of the left-hand side matrix operand
1331  , typename VT2 > // Type of the right-hand side vector operand
1332  static inline typename EnableIf< UseSinglePrecisionComplexKernel<VT1,MT1,VT2> >::Type
1333  selectBlasSubAssignKernel( VT1& y, const MT1& A, const VT2& x )
1334  {
1335  using boost::numeric_cast;
1336 
1337  BLAZE_CONSTRAINT_MUST_BE_COMPLEX_TYPE( typename VT1::ElementType );
1338  BLAZE_CONSTRAINT_MUST_BE_COMPLEX_TYPE( typename MT1::ElementType );
1339  BLAZE_CONSTRAINT_MUST_BE_COMPLEX_TYPE( typename VT2::ElementType );
1340  BLAZE_CONSTRAINT_MUST_BE_FLOAT_TYPE ( typename VT1::ElementType::value_type );
1341  BLAZE_CONSTRAINT_MUST_BE_FLOAT_TYPE ( typename MT1::ElementType::value_type );
1342  BLAZE_CONSTRAINT_MUST_BE_FLOAT_TYPE ( typename VT2::ElementType::value_type );
1343 
1344  const int M ( numeric_cast<int>( A.rows() ) );
1345  const int N ( numeric_cast<int>( A.columns() ) );
1346  const int lda( numeric_cast<int>( A.spacing() ) );
1347  const complex<float> alpha( -1.0F, 0.0F );
1348  const complex<float> beta ( 1.0F, 0.0F );
1349 
1350  cblas_cgemv( CblasRowMajor, CblasNoTrans, M, N, &alpha,
1351  A.data(), lda, x.data(), 1, &beta, y.data(), 1 );
1352  }
1354 #endif
1355  //**********************************************************************************************
1356 
1357  //**BLAS-based subtraction assignment to dense vectors (double precision complex)***************
1358 #if BLAZE_BLAS_MODE
1359 
1372  template< typename VT1 // Type of the left-hand side target vector
1373  , typename MT1 // Type of the left-hand side matrix operand
1374  , typename VT2 > // Type of the right-hand side vector operand
1375  static inline typename EnableIf< UseDoublePrecisionComplexKernel<VT1,MT1,VT2> >::Type
1376  selectBlasSubAssignKernel( VT1& y, const MT1& A, const VT2& x )
1377  {
1378  using boost::numeric_cast;
1379 
1380  BLAZE_CONSTRAINT_MUST_BE_COMPLEX_TYPE( typename VT1::ElementType );
1381  BLAZE_CONSTRAINT_MUST_BE_COMPLEX_TYPE( typename MT1::ElementType );
1382  BLAZE_CONSTRAINT_MUST_BE_COMPLEX_TYPE( typename VT2::ElementType );
1383  BLAZE_CONSTRAINT_MUST_BE_DOUBLE_TYPE ( typename VT1::ElementType::value_type );
1384  BLAZE_CONSTRAINT_MUST_BE_DOUBLE_TYPE ( typename MT1::ElementType::value_type );
1385  BLAZE_CONSTRAINT_MUST_BE_DOUBLE_TYPE ( typename VT2::ElementType::value_type );
1386 
1387  const int M ( numeric_cast<int>( A.rows() ) );
1388  const int N ( numeric_cast<int>( A.columns() ) );
1389  const int lda( numeric_cast<int>( A.spacing() ) );
1390  const complex<double> alpha( -1.0, 0.0 );
1391  const complex<double> beta ( 1.0, 0.0 );
1392 
1393  cblas_zgemv( CblasRowMajor, CblasNoTrans, M, N, &alpha,
1394  A.data(), lda, x.data(), 1, &beta, y.data(), 1 );
1395  }
1397 #endif
1398  //**********************************************************************************************
1399 
1400  //**Subtraction assignment to sparse vectors****************************************************
1401  // No special implementation for the subtraction assignment to sparse vectors.
1402  //**********************************************************************************************
1403 
1404  //**Multiplication assignment to dense vectors**************************************************
1416  template< typename VT1 > // Type of the target dense vector
1417  friend inline void multAssign( DenseVector<VT1,false>& lhs, const DMatDVecMultExpr& rhs )
1418  {
1421  BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( typename ResultType::CompositeType );
1422 
1423  BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
1424 
1425  const ResultType tmp( rhs );
1426  multAssign( ~lhs, tmp );
1427  }
1429  //**********************************************************************************************
1430 
1431  //**Multiplication assignment to sparse vectors*************************************************
1432  // No special implementation for the multiplication assignment to sparse vectors.
1433  //**********************************************************************************************
1434 
1435  //**Compile time checks*************************************************************************
1442  //**********************************************************************************************
1443 };
1444 //*************************************************************************************************
1445 
1446 
1447 
1448 
1449 //=================================================================================================
1450 //
1451 // DVECSCALARMULTEXPR SPECIALIZATION
1452 //
1453 //=================================================================================================
1454 
1455 //*************************************************************************************************
1463 template< typename MT // Type of the left-hand side dense matrix
1464  , typename VT // Type of the right-hand side dense vector
1465  , typename ST > // Type of the side scalar value
1466 class DVecScalarMultExpr< DMatDVecMultExpr<MT,VT>, ST, false >
1467  : public DenseVector< DVecScalarMultExpr< DMatDVecMultExpr<MT,VT>, ST, false >, false >
1468  , private Expression
1469  , private Computation
1470 {
1471  private:
1472  //**Type definitions****************************************************************************
1473  typedef DMatDVecMultExpr<MT,VT> MVM;
1474  typedef typename MVM::ResultType RES;
1475  typedef typename MT::ResultType MRT;
1476  typedef typename VT::ResultType VRT;
1477  typedef typename MRT::ElementType MET;
1478  typedef typename VRT::ElementType VET;
1479  typedef typename MT::CompositeType MCT;
1480  typedef typename VT::CompositeType VCT;
1481  //**********************************************************************************************
1482 
1483  //**********************************************************************************************
1485  enum { evaluate = IsComputation<MT>::value && !MT::vectorizable &&
1486  IsSame<VET,MET>::value && IsBlasCompatible<VET>::value };
1487  //**********************************************************************************************
1488 
1489  //**********************************************************************************************
1491 
1494  template< typename T1, typename T2, typename T3, typename T4 >
1495  struct UseSinglePrecisionKernel {
1496  enum { value = IsFloat<typename T1::ElementType>::value &&
1497  IsFloat<typename T2::ElementType>::value &&
1498  IsFloat<typename T3::ElementType>::value &&
1499  !IsComplex<T4>::value };
1500  };
1501  //**********************************************************************************************
1502 
1503  //**********************************************************************************************
1505 
1508  template< typename T1, typename T2, typename T3, typename T4 >
1509  struct UseDoublePrecisionKernel {
1510  enum { value = IsDouble<typename T1::ElementType>::value &&
1511  IsDouble<typename T2::ElementType>::value &&
1512  IsDouble<typename T3::ElementType>::value &&
1513  !IsComplex<T4>::value };
1514  };
1515  //**********************************************************************************************
1516 
1517  //**********************************************************************************************
1519 
1522  template< typename T1, typename T2, typename T3 >
1523  struct UseSinglePrecisionComplexKernel {
1524  typedef complex<float> Type;
1525  enum { value = IsSame<typename T1::ElementType,Type>::value &&
1526  IsSame<typename T2::ElementType,Type>::value &&
1527  IsSame<typename T3::ElementType,Type>::value };
1528  };
1529  //**********************************************************************************************
1530 
1531  //**********************************************************************************************
1533 
1536  template< typename T1, typename T2, typename T3 >
1537  struct UseDoublePrecisionComplexKernel {
1538  typedef complex<double> Type;
1539  enum { value = IsSame<typename T1::ElementType,Type>::value &&
1540  IsSame<typename T2::ElementType,Type>::value &&
1541  IsSame<typename T3::ElementType,Type>::value };
1542  };
1543  //**********************************************************************************************
1544 
1545  //**********************************************************************************************
1547 
1549  template< typename T1, typename T2, typename T3, typename T4 >
1550  struct UseDefaultKernel {
1551  enum { value = !BLAZE_BLAS_MODE || ( !UseSinglePrecisionKernel<T1,T2,T3,T4>::value &&
1552  !UseDoublePrecisionKernel<T1,T2,T3,T4>::value &&
1553  !UseSinglePrecisionComplexKernel<T1,T2,T3>::value &&
1554  !UseDoublePrecisionComplexKernel<T1,T2,T3>::value ) };
1555  };
1556  //**********************************************************************************************
1557 
1558  //**********************************************************************************************
1560 
1563  template< typename T1, typename T2, typename T3, typename T4 >
1564  struct UseVectorizedDefaultKernel {
1565  enum { value = T1::vectorizable && T2::vectorizable && T3::vectorizable &&
1566  IsSame<typename T1::ElementType,typename T2::ElementType>::value &&
1567  IsSame<typename T1::ElementType,typename T3::ElementType>::value &&
1568  IsSame<typename T1::ElementType,T4>::value &&
1569  IntrinsicTrait<typename T1::ElementType>::addition &&
1570  IntrinsicTrait<typename T1::ElementType>::multiplication };
1571  };
1572  //**********************************************************************************************
1573 
1574  public:
1575  //**Type definitions****************************************************************************
1576  typedef DVecScalarMultExpr<MVM,ST,false> This;
1577  typedef typename MultTrait<RES,ST>::Type ResultType;
1578  typedef typename ResultType::TransposeType TransposeType;
1579  typedef typename ResultType::ElementType ElementType;
1580  typedef typename IntrinsicTrait<ElementType>::Type IntrinsicType;
1581  typedef const ElementType ReturnType;
1582  typedef const ResultType CompositeType;
1583 
1585  typedef const DMatDVecMultExpr<MT,VT> LeftOperand;
1586 
1588  typedef typename SelectType< IsNumeric<ElementType>::value, ElementType, ST >::Type RightOperand;
1589 
1591  typedef typename SelectType< evaluate, const MRT, MCT >::Type LT;
1592 
1594  typedef typename SelectType< IsComputation<VT>::value, const VRT, VCT >::Type RT;
1595  //**********************************************************************************************
1596 
1597  //**Compilation flags***************************************************************************
1599  enum { vectorizable = 0 };
1600 
1602  enum { canAlias = CanAlias<MVM>::value };
1603  //**********************************************************************************************
1604 
1605  //**Constructor*********************************************************************************
1611  explicit inline DVecScalarMultExpr( const MVM& vector, ST scalar )
1612  : vector_( vector ) // Left-hand side dense vector of the multiplication expression
1613  , scalar_( scalar ) // Right-hand side scalar of the multiplication expression
1614  {}
1615  //**********************************************************************************************
1616 
1617  //**Subscript operator**************************************************************************
1623  inline ReturnType operator[]( size_t index ) const {
1624  BLAZE_INTERNAL_ASSERT( index < vector_.size(), "Invalid vector access index" );
1625  return vector_[index] * scalar_;
1626  }
1627  //**********************************************************************************************
1628 
1629  //**Size function*******************************************************************************
1634  inline size_t size() const {
1635  return vector_.size();
1636  }
1637  //**********************************************************************************************
1638 
1639  //**Left operand access*************************************************************************
1644  inline LeftOperand leftOperand() const {
1645  return vector_;
1646  }
1647  //**********************************************************************************************
1648 
1649  //**Right operand access************************************************************************
1654  inline RightOperand rightOperand() const {
1655  return scalar_;
1656  }
1657  //**********************************************************************************************
1658 
1659  //**********************************************************************************************
1665  template< typename T >
1666  inline bool isAliased( const T* alias ) const {
1667  return CanAlias<MVM>::value && vector_.isAliased( alias );
1668  }
1669  //**********************************************************************************************
1670 
1671  private:
1672  //**Member variables****************************************************************************
1673  LeftOperand vector_;
1674  RightOperand scalar_;
1675  //**********************************************************************************************
1676 
1677  //**Assignment to dense vectors*****************************************************************
1689  template< typename VT1 > // Type of the target dense vector
1690  friend inline void assign( DenseVector<VT1,false>& lhs, const DVecScalarMultExpr& rhs )
1691  {
1692  BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
1693 
1694  typename MVM::LeftOperand left ( rhs.vector_.leftOperand() );
1695  typename MVM::RightOperand right( rhs.vector_.rightOperand() );
1696 
1697  if( left.rows() == 0UL ) {
1698  return;
1699  }
1700  else if( left.columns() == 0UL ) {
1701  reset( ~lhs );
1702  return;
1703  }
1704 
1705  LT A( left ); // Evaluation of the left-hand side dense matrix operand
1706  RT x( right ); // Evaluation of the right-hand side dense vector operand
1707 
1708  BLAZE_INTERNAL_ASSERT( A.rows() == left.rows() , "Invalid number of rows" );
1709  BLAZE_INTERNAL_ASSERT( A.columns() == left.columns(), "Invalid number of columns" );
1710  BLAZE_INTERNAL_ASSERT( x.size() == right.size() , "Invalid vector size" );
1711  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).size() , "Invalid vector size" );
1712 
1713  if( ( IsComputation<MT>::value && !evaluate ) ||
1714  ( A.rows() * A.columns() < DMATDVECMULT_THRESHOLD ) )
1715  DVecScalarMultExpr::selectDefaultAssignKernel( ~lhs, A, x, rhs.scalar_ );
1716  else
1717  DVecScalarMultExpr::selectBlasAssignKernel( ~lhs, A, x, rhs.scalar_ );
1718  }
1719  //**********************************************************************************************
1720 
1721  //**Default assignment to dense vectors*********************************************************
1735  template< typename VT1 // Type of the left-hand side target vector
1736  , typename MT1 // Type of the left-hand side matrix operand
1737  , typename VT2 // Type of the right-hand side vector operand
1738  , typename ST2 > // Type of the scalar value
1739  static inline typename DisableIf< UseVectorizedDefaultKernel<VT1,MT1,VT2,ST2> >::Type
1740  selectDefaultAssignKernel( VT1& y, const MT1& A, const VT2& x, ST2 scalar )
1741  {
1742  y.assign( A * x * scalar );
1743  }
1744  //**********************************************************************************************
1745 
1746  //**Vectorized default assignment to dense vectors**********************************************
1760  template< typename VT1 // Type of the left-hand side target vector
1761  , typename MT1 // Type of the left-hand side matrix operand
1762  , typename VT2 // Type of the right-hand side vector operand
1763  , typename ST2 > // Type of the scalar value
1764  static inline typename EnableIf< UseVectorizedDefaultKernel<VT1,MT1,VT2,ST2> >::Type
1765  selectDefaultAssignKernel( VT1& y, const MT1& A, const VT2& x, ST2 scalar )
1766  {
1767  typedef IntrinsicTrait<ElementType> IT;
1768 
1769  const size_t M( A.rows() );
1770  const size_t N( A.columns() );
1771 
1772  size_t i( 0UL );
1773 
1774  for( ; (i+8UL) <= M; i+=8UL ) {
1775  IntrinsicType xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7, xmm8;
1776  for( size_t j=0UL; j<N; j+=IT::size ) {
1777  const IntrinsicType x1( x.get(j) );
1778  xmm1 = xmm1 + A.get(i ,j) * x1;
1779  xmm2 = xmm2 + A.get(i+1UL,j) * x1;
1780  xmm3 = xmm3 + A.get(i+2UL,j) * x1;
1781  xmm4 = xmm4 + A.get(i+3UL,j) * x1;
1782  xmm5 = xmm5 + A.get(i+4UL,j) * x1;
1783  xmm6 = xmm6 + A.get(i+5UL,j) * x1;
1784  xmm7 = xmm7 + A.get(i+6UL,j) * x1;
1785  xmm8 = xmm8 + A.get(i+7UL,j) * x1;
1786  }
1787  y[i ] = sum( xmm1 ) * scalar;
1788  y[i+1UL] = sum( xmm2 ) * scalar;
1789  y[i+2UL] = sum( xmm3 ) * scalar;
1790  y[i+3UL] = sum( xmm4 ) * scalar;
1791  y[i+4UL] = sum( xmm5 ) * scalar;
1792  y[i+5UL] = sum( xmm6 ) * scalar;
1793  y[i+6UL] = sum( xmm7 ) * scalar;
1794  y[i+7UL] = sum( xmm8 ) * scalar;
1795  }
1796  for( ; (i+4UL) <= M; i+=4UL ) {
1797  IntrinsicType xmm1, xmm2, xmm3, xmm4;
1798  for( size_t j=0UL; j<N; j+=IT::size ) {
1799  const IntrinsicType x1( x.get(j) );
1800  xmm1 = xmm1 + A.get(i ,j) * x1;
1801  xmm2 = xmm2 + A.get(i+1UL,j) * x1;
1802  xmm3 = xmm3 + A.get(i+2UL,j) * x1;
1803  xmm4 = xmm4 + A.get(i+3UL,j) * x1;
1804  }
1805  y[i ] = sum( xmm1 ) * scalar;
1806  y[i+1UL] = sum( xmm2 ) * scalar;
1807  y[i+2UL] = sum( xmm3 ) * scalar;
1808  y[i+3UL] = sum( xmm4 ) * scalar;
1809  }
1810  for( ; (i+3UL) <= M; i+=3UL ) {
1811  IntrinsicType xmm1, xmm2, xmm3;
1812  for( size_t j=0UL; j<N; j+=IT::size ) {
1813  const IntrinsicType x1( x.get(j) );
1814  xmm1 = xmm1 + A.get(i ,j) * x1;
1815  xmm2 = xmm2 + A.get(i+1UL,j) * x1;
1816  xmm3 = xmm3 + A.get(i+2UL,j) * x1;
1817  }
1818  y[i ] = sum( xmm1 ) * scalar;
1819  y[i+1UL] = sum( xmm2 ) * scalar;
1820  y[i+2UL] = sum( xmm3 ) * scalar;
1821  }
1822  for( ; (i+2UL) <= M; i+=2UL ) {
1823  IntrinsicType xmm1, xmm2;
1824  for( size_t j=0UL; j<N; j+=IT::size ) {
1825  const IntrinsicType x1( x.get(j) );
1826  xmm1 = xmm1 + A.get(i ,j) * x1;
1827  xmm2 = xmm2 + A.get(i+1UL,j) * x1;
1828  }
1829  y[i ] = sum( xmm1 ) * scalar;
1830  y[i+1UL] = sum( xmm2 ) * scalar;
1831  }
1832  if( i < M ) {
1833  IntrinsicType xmm1;
1834  for( size_t j=0UL; j<N; j+=IT::size ) {
1835  xmm1 = xmm1 + A.get(i,j) * x.get(j);
1836  }
1837  y[i] = sum( xmm1 ) * scalar;
1838  }
1839  }
1840  //**********************************************************************************************
1841 
1842  //**BLAS-based assignment to dense vectors (default)********************************************
1856  template< typename VT1 // Type of the left-hand side target vector
1857  , typename MT1 // Type of the left-hand side matrix operand
1858  , typename VT2 // Type of the right-hand side vector operand
1859  , typename ST2 > // Type of the scalar value
1860  static inline typename EnableIf< UseDefaultKernel<VT1,MT1,VT2,ST2> >::Type
1861  selectBlasAssignKernel( VT1& y, const MT1& A, const VT2& x, ST2 scalar )
1862  {
1863  selectDefaultAssignKernel( y, A, x, scalar );
1864  }
1865  //**********************************************************************************************
1866 
1867  //**BLAS-based assignment to dense vectors (single precision)***********************************
1868 #if BLAZE_BLAS_MODE
1869 
1882  template< typename VT1 // Type of the left-hand side target vector
1883  , typename MT1 // Type of the left-hand side matrix operand
1884  , typename VT2 // Type of the right-hand side vector operand
1885  , typename ST2 > // Type of the scalar value
1886  static inline typename EnableIf< UseSinglePrecisionKernel<VT1,MT1,VT2,ST2> >::Type
1887  selectBlasAssignKernel( VT1& y, const MT1& A, const VT2& x, ST2 scalar )
1888  {
1889  using boost::numeric_cast;
1890 
1891  BLAZE_CONSTRAINT_MUST_BE_FLOAT_TYPE( typename VT1::ElementType );
1892  BLAZE_CONSTRAINT_MUST_BE_FLOAT_TYPE( typename MT1::ElementType );
1893  BLAZE_CONSTRAINT_MUST_BE_FLOAT_TYPE( typename VT2::ElementType );
1894 
1895  const int M ( numeric_cast<int>( A.rows() ) );
1896  const int N ( numeric_cast<int>( A.columns() ) );
1897  const int lda( numeric_cast<int>( A.spacing() ) );
1898 
1899  cblas_sgemv( CblasRowMajor, CblasNoTrans, M, N, scalar,
1900  A.data(), lda, x.data(), 1, 0.0F, y.data(), 1 );
1901  }
1902 #endif
1903  //**********************************************************************************************
1904 
1905  //**BLAS-based assignment to dense vectors (double precision)***********************************
1906 #if BLAZE_BLAS_MODE
1907 
1920  template< typename VT1 // Type of the left-hand side target vector
1921  , typename MT1 // Type of the left-hand side matrix operand
1922  , typename VT2 // Type of the right-hand side vector operand
1923  , typename ST2 > // Type of the scalar value
1924  static inline typename EnableIf< UseDoublePrecisionKernel<VT1,MT1,VT2,ST2> >::Type
1925  selectBlasAssignKernel( VT1& y, const MT1& A, const VT2& x, ST2 scalar )
1926  {
1927  using boost::numeric_cast;
1928 
1929  BLAZE_CONSTRAINT_MUST_BE_DOUBLE_TYPE( typename VT1::ElementType );
1930  BLAZE_CONSTRAINT_MUST_BE_DOUBLE_TYPE( typename MT1::ElementType );
1931  BLAZE_CONSTRAINT_MUST_BE_DOUBLE_TYPE( typename VT2::ElementType );
1932 
1933  const int M ( numeric_cast<int>( A.rows() ) );
1934  const int N ( numeric_cast<int>( A.columns() ) );
1935  const int lda( numeric_cast<int>( A.spacing() ) );
1936 
1937  cblas_dgemv( CblasRowMajor, CblasNoTrans, M, N, scalar,
1938  A.data(), lda, x.data(), 1, 0.0, y.data(), 1 );
1939  }
1940 #endif
1941  //**********************************************************************************************
1942 
1943  //**BLAS-based assignment to dense vectors (single precision complex)***************************
1944 #if BLAZE_BLAS_MODE
1945 
1958  template< typename VT1 // Type of the left-hand side target vector
1959  , typename MT1 // Type of the left-hand side matrix operand
1960  , typename VT2 // Type of the right-hand side vector operand
1961  , typename ST2 > // Type of the scalar value
1962  static inline typename EnableIf< UseSinglePrecisionComplexKernel<VT1,MT1,VT2> >::Type
1963  selectBlasAssignKernel( VT1& y, const MT1& A, const VT2& x, ST2 scalar )
1964  {
1965  using boost::numeric_cast;
1966 
1967  BLAZE_CONSTRAINT_MUST_BE_COMPLEX_TYPE( typename VT1::ElementType );
1968  BLAZE_CONSTRAINT_MUST_BE_COMPLEX_TYPE( typename MT1::ElementType );
1969  BLAZE_CONSTRAINT_MUST_BE_COMPLEX_TYPE( typename VT2::ElementType );
1971  BLAZE_CONSTRAINT_MUST_BE_FLOAT_TYPE ( typename VT1::ElementType::value_type );
1972  BLAZE_CONSTRAINT_MUST_BE_FLOAT_TYPE ( typename MT1::ElementType::value_type );
1973  BLAZE_CONSTRAINT_MUST_BE_FLOAT_TYPE ( typename VT2::ElementType::value_type );
1974 
1975  const int M ( numeric_cast<int>( A.rows() ) );
1976  const int N ( numeric_cast<int>( A.columns() ) );
1977  const int lda( numeric_cast<int>( A.spacing() ) );
1978  const complex<float> alpha( scalar );
1979  const complex<float> beta ( 0.0F, 0.0F );
1980 
1981  cblas_cgemv( CblasRowMajor, CblasNoTrans, M, N, &alpha,
1982  A.data(), lda, x.data(), 1, &beta, y.data(), 1 );
1983  }
1984 #endif
1985  //**********************************************************************************************
1986 
1987  //**BLAS-based assignment to dense vectors (double precision complex)***************************
1988 #if BLAZE_BLAS_MODE
1989 
2002  template< typename VT1 // Type of the left-hand side target vector
2003  , typename MT1 // Type of the left-hand side matrix operand
2004  , typename VT2 // Type of the right-hand side vector operand
2005  , typename ST2 > // Type of the scalar value
2006  static inline typename EnableIf< UseDoublePrecisionComplexKernel<VT1,MT1,VT2> >::Type
2007  selectBlasAssignKernel( VT1& y, const MT1& A, const VT2& x, ST2 scalar )
2008  {
2009  using boost::numeric_cast;
2010 
2011  BLAZE_CONSTRAINT_MUST_BE_COMPLEX_TYPE( typename VT1::ElementType );
2012  BLAZE_CONSTRAINT_MUST_BE_COMPLEX_TYPE( typename MT1::ElementType );
2013  BLAZE_CONSTRAINT_MUST_BE_COMPLEX_TYPE( typename VT2::ElementType );
2015  BLAZE_CONSTRAINT_MUST_BE_DOUBLE_TYPE ( typename VT1::ElementType::value_type );
2016  BLAZE_CONSTRAINT_MUST_BE_DOUBLE_TYPE ( typename MT1::ElementType::value_type );
2017  BLAZE_CONSTRAINT_MUST_BE_DOUBLE_TYPE ( typename VT2::ElementType::value_type );
2018 
2019  const int M ( numeric_cast<int>( A.rows() ) );
2020  const int N ( numeric_cast<int>( A.columns() ) );
2021  const int lda( numeric_cast<int>( A.spacing() ) );
2022  const complex<double> alpha( scalar );
2023  const complex<double> beta ( 0.0, 0.0 );
2024 
2025  cblas_zgemv( CblasRowMajor, CblasNoTrans, M, N, &alpha,
2026  A.data(), lda, x.data(), 1, &beta, y.data(), 1 );
2027  }
2028 #endif
2029  //**********************************************************************************************
2030 
2031  //**Assignment to sparse vectors****************************************************************
2042  template< typename VT1 > // Type of the target sparse vector
2043  friend inline void assign( SparseVector<VT1,false>& lhs, const DVecScalarMultExpr& rhs )
2044  {
2047  BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( typename ResultType::CompositeType );
2048 
2049  BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
2050 
2051  const ResultType tmp( rhs );
2052  assign( ~lhs, tmp );
2053  }
2054  //**********************************************************************************************
2055 
2056  //**Addition assignment to dense vectors********************************************************
2068  template< typename VT1 > // Type of the target dense vector
2069  friend inline void addAssign( DenseVector<VT1,false>& lhs, const DVecScalarMultExpr& rhs )
2070  {
2071  BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
2072 
2073  typename MVM::LeftOperand left ( rhs.vector_.leftOperand() );
2074  typename MVM::RightOperand right( rhs.vector_.rightOperand() );
2075 
2076  if( left.rows() == 0UL || left.columns() == 0UL ) {
2077  return;
2078  }
2079 
2080  LT A( left ); // Evaluation of the left-hand side dense matrix operand
2081  RT x( right ); // Evaluation of the right-hand side dense vector operand
2082 
2083  BLAZE_INTERNAL_ASSERT( A.rows() == left.rows() , "Invalid number of rows" );
2084  BLAZE_INTERNAL_ASSERT( A.columns() == left.columns(), "Invalid number of columns" );
2085  BLAZE_INTERNAL_ASSERT( x.size() == right.size() , "Invalid vector size" );
2086  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).size() , "Invalid vector size" );
2087 
2088  if( ( IsComputation<MT>::value && !evaluate ) ||
2089  ( A.rows() * A.columns() < DMATDVECMULT_THRESHOLD ) )
2090  DVecScalarMultExpr::selectDefaultAddAssignKernel( ~lhs, A, x, rhs.scalar_ );
2091  else
2092  DVecScalarMultExpr::selectBlasAddAssignKernel( ~lhs, A, x, rhs.scalar_ );
2093  }
2094  //**********************************************************************************************
2095 
2096  //**Default addition assignment to dense vectors************************************************
2110  template< typename VT1 // Type of the left-hand side target vector
2111  , typename MT1 // Type of the left-hand side matrix operand
2112  , typename VT2 // Type of the right-hand side vector operand
2113  , typename ST2 > // Type of the scalar value
2114  static inline typename DisableIf< UseVectorizedDefaultKernel<VT1,MT1,VT2,ST2> >::Type
2115  selectDefaultAddAssignKernel( VT1& y, const MT1& A, const VT2& x, ST2 scalar )
2116  {
2117  y.addAssign( A * x * scalar );
2118  }
2119  //**********************************************************************************************
2120 
2121  //**Vectorized default addition assignment to dense vectors*************************************
2135  template< typename VT1 // Type of the left-hand side target vector
2136  , typename MT1 // Type of the left-hand side matrix operand
2137  , typename VT2 // Type of the right-hand side vector operand
2138  , typename ST2 > // Type of the scalar value
2139  static inline typename EnableIf< UseVectorizedDefaultKernel<VT1,MT1,VT2,ST2> >::Type
2140  selectDefaultAddAssignKernel( VT1& y, const MT1& A, const VT2& x, ST2 scalar )
2141  {
2142  typedef IntrinsicTrait<ElementType> IT;
2143 
2144  const size_t M( A.rows() );
2145  const size_t N( A.columns() );
2146 
2147  size_t i( 0UL );
2148 
2149  for( ; (i+8UL) <= M; i+=8UL ) {
2150  IntrinsicType xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7, xmm8;
2151  for( size_t j=0UL; j<N; j+=IT::size ) {
2152  const IntrinsicType x1( x.get(j) );
2153  xmm1 = xmm1 + A.get(i ,j) * x1;
2154  xmm2 = xmm2 + A.get(i+1UL,j) * x1;
2155  xmm3 = xmm3 + A.get(i+2UL,j) * x1;
2156  xmm4 = xmm4 + A.get(i+3UL,j) * x1;
2157  xmm5 = xmm5 + A.get(i+4UL,j) * x1;
2158  xmm6 = xmm6 + A.get(i+5UL,j) * x1;
2159  xmm7 = xmm7 + A.get(i+6UL,j) * x1;
2160  xmm8 = xmm8 + A.get(i+7UL,j) * x1;
2161  }
2162  y[i ] += sum( xmm1 ) * scalar;
2163  y[i+1UL] += sum( xmm2 ) * scalar;
2164  y[i+2UL] += sum( xmm3 ) * scalar;
2165  y[i+3UL] += sum( xmm4 ) * scalar;
2166  y[i+4UL] += sum( xmm5 ) * scalar;
2167  y[i+5UL] += sum( xmm6 ) * scalar;
2168  y[i+6UL] += sum( xmm7 ) * scalar;
2169  y[i+7UL] += sum( xmm8 ) * scalar;
2170  }
2171  for( ; (i+4UL) <= M; i+=4UL ) {
2172  IntrinsicType xmm1, xmm2, xmm3, xmm4;
2173  for( size_t j=0UL; j<N; j+=IT::size ) {
2174  const IntrinsicType x1( x.get(j) );
2175  xmm1 = xmm1 + A.get(i ,j) * x1;
2176  xmm2 = xmm2 + A.get(i+1UL,j) * x1;
2177  xmm3 = xmm3 + A.get(i+2UL,j) * x1;
2178  xmm4 = xmm4 + A.get(i+3UL,j) * x1;
2179  }
2180  y[i ] += sum( xmm1 ) * scalar;
2181  y[i+1UL] += sum( xmm2 ) * scalar;
2182  y[i+2UL] += sum( xmm3 ) * scalar;
2183  y[i+3UL] += sum( xmm4 ) * scalar;
2184  }
2185  for( ; (i+3UL) <= M; i+=3UL ) {
2186  IntrinsicType xmm1, xmm2, xmm3;
2187  for( size_t j=0UL; j<N; j+=IT::size ) {
2188  const IntrinsicType x1( x.get(j) );
2189  xmm1 = xmm1 + A.get(i ,j) * x1;
2190  xmm2 = xmm2 + A.get(i+1UL,j) * x1;
2191  xmm3 = xmm3 + A.get(i+2UL,j) * x1;
2192  }
2193  y[i ] += sum( xmm1 ) * scalar;
2194  y[i+1UL] += sum( xmm2 ) * scalar;
2195  y[i+2UL] += sum( xmm3 ) * scalar;
2196  }
2197  for( ; (i+2UL) <= M; i+=2UL ) {
2198  IntrinsicType xmm1, xmm2;
2199  for( size_t j=0UL; j<N; j+=IT::size ) {
2200  const IntrinsicType x1( x.get(j) );
2201  xmm1 = xmm1 + A.get(i ,j) * x1;
2202  xmm2 = xmm2 + A.get(i+1UL,j) * x1;
2203  }
2204  y[i ] += sum( xmm1 ) * scalar;
2205  y[i+1UL] += sum( xmm2 ) * scalar;
2206  }
2207  if( i < M ) {
2208  IntrinsicType xmm1;
2209  for( size_t j=0UL; j<N; j+=IT::size ) {
2210  xmm1 = xmm1 + A.get(i,j) * x.get(j);
2211  }
2212  y[i] += sum( xmm1 ) * scalar;
2213  }
2214  }
2215  //**********************************************************************************************
2216 
2217  //**BLAS-based addition assignment to dense vectors (default)***********************************
2231  template< typename VT1 // Type of the left-hand side target vector
2232  , typename MT1 // Type of the left-hand side matrix operand
2233  , typename VT2 // Type of the right-hand side vector operand
2234  , typename ST2 > // Type of the scalar value
2235  static inline typename EnableIf< UseDefaultKernel<VT1,MT1,VT2,ST2> >::Type
2236  selectBlasAddAssignKernel( VT1& y, const MT1& A, const VT2& x, ST2 scalar )
2237  {
2238  selectDefaultAddAssignKernel( y, A, x, scalar );
2239  }
2240  //**********************************************************************************************
2241 
2242  //**BLAS-based addition assignment to dense vectors (single precision)**************************
2243 #if BLAZE_BLAS_MODE
2244 
2257  template< typename VT1 // Type of the left-hand side target vector
2258  , typename MT1 // Type of the left-hand side matrix operand
2259  , typename VT2 // Type of the right-hand side vector operand
2260  , typename ST2 > // Type of the scalar value
2261  static inline typename EnableIf< UseSinglePrecisionKernel<VT1,MT1,VT2,ST2> >::Type
2262  selectBlasAddAssignKernel( VT1& y, const MT1& A, const VT2& x, ST2 scalar )
2263  {
2264  using boost::numeric_cast;
2265 
2266  BLAZE_CONSTRAINT_MUST_BE_FLOAT_TYPE( typename VT1::ElementType );
2267  BLAZE_CONSTRAINT_MUST_BE_FLOAT_TYPE( typename MT1::ElementType );
2268  BLAZE_CONSTRAINT_MUST_BE_FLOAT_TYPE( typename VT2::ElementType );
2269 
2270  const int M ( numeric_cast<int>( A.rows() ) );
2271  const int N ( numeric_cast<int>( A.columns() ) );
2272  const int lda( numeric_cast<int>( A.spacing() ) );
2273 
2274  cblas_sgemv( CblasRowMajor, CblasNoTrans, M, N, scalar,
2275  A.data(), lda, x.data(), 1, 1.0F, y.data(), 1 );
2276  }
2277 #endif
2278  //**********************************************************************************************
2279 
2280  //**BLAS-based addition assignment to dense vectors (double precision)**************************
2281 #if BLAZE_BLAS_MODE
2282 
2295  template< typename VT1 // Type of the left-hand side target vector
2296  , typename MT1 // Type of the left-hand side matrix operand
2297  , typename VT2 // Type of the right-hand side vector operand
2298  , typename ST2 > // Type of the scalar value
2299  static inline typename EnableIf< UseDoublePrecisionKernel<VT1,MT1,VT2,ST2> >::Type
2300  selectBlasAddAssignKernel( VT1& y, const MT1& A, const VT2& x, ST2 scalar )
2301  {
2302  using boost::numeric_cast;
2303 
2304  BLAZE_CONSTRAINT_MUST_BE_DOUBLE_TYPE( typename VT1::ElementType );
2305  BLAZE_CONSTRAINT_MUST_BE_DOUBLE_TYPE( typename MT1::ElementType );
2306  BLAZE_CONSTRAINT_MUST_BE_DOUBLE_TYPE( typename VT2::ElementType );
2307 
2308  const int M ( numeric_cast<int>( A.rows() ) );
2309  const int N ( numeric_cast<int>( A.columns() ) );
2310  const int lda( numeric_cast<int>( A.spacing() ) );
2311 
2312  cblas_dgemv( CblasRowMajor, CblasNoTrans, M, N, scalar,
2313  A.data(), lda, x.data(), 1, 1.0, y.data(), 1 );
2314  }
2315 #endif
2316  //**********************************************************************************************
2317 
2318  //**BLAS-based addition assignment to dense vectors (single precision complex)******************
2319 #if BLAZE_BLAS_MODE
2320 
2333  template< typename VT1 // Type of the left-hand side target vector
2334  , typename MT1 // Type of the left-hand side matrix operand
2335  , typename VT2 // Type of the right-hand side vector operand
2336  , typename ST2 > // Type of the scalar value
2337  static inline typename EnableIf< UseSinglePrecisionComplexKernel<VT1,MT1,VT2> >::Type
2338  selectBlasAddAssignKernel( VT1& y, const MT1& A, const VT2& x, ST2 scalar )
2339  {
2340  using boost::numeric_cast;
2341 
2342  BLAZE_CONSTRAINT_MUST_BE_COMPLEX_TYPE( typename VT1::ElementType );
2343  BLAZE_CONSTRAINT_MUST_BE_COMPLEX_TYPE( typename MT1::ElementType );
2344  BLAZE_CONSTRAINT_MUST_BE_COMPLEX_TYPE( typename VT2::ElementType );
2346  BLAZE_CONSTRAINT_MUST_BE_FLOAT_TYPE ( typename VT1::ElementType::value_type );
2347  BLAZE_CONSTRAINT_MUST_BE_FLOAT_TYPE ( typename MT1::ElementType::value_type );
2348  BLAZE_CONSTRAINT_MUST_BE_FLOAT_TYPE ( typename VT2::ElementType::value_type );
2349 
2350  const int M ( numeric_cast<int>( A.rows() ) );
2351  const int N ( numeric_cast<int>( A.columns() ) );
2352  const int lda( numeric_cast<int>( A.spacing() ) );
2353  const complex<float> alpha( scalar );
2354  const complex<float> beta ( 1.0F, 0.0F );
2355 
2356  cblas_cgemv( CblasRowMajor, CblasNoTrans, M, N, &alpha,
2357  A.data(), lda, x.data(), 1, &beta, y.data(), 1 );
2358  }
2359 #endif
2360  //**********************************************************************************************
2361 
2362  //**BLAS-based addition assignment to dense vectors (double precision complex)******************
2363 #if BLAZE_BLAS_MODE
2364 
2377  template< typename VT1 // Type of the left-hand side target vector
2378  , typename MT1 // Type of the left-hand side matrix operand
2379  , typename VT2 // Type of the right-hand side vector operand
2380  , typename ST2 > // Type of the scalar value
2381  static inline typename EnableIf< UseDoublePrecisionComplexKernel<VT1,MT1,VT2> >::Type
2382  selectBlasAddAssignKernel( VT1& y, const MT1& A, const VT2& x, ST2 scalar )
2383  {
2384  using boost::numeric_cast;
2385 
2386  BLAZE_CONSTRAINT_MUST_BE_COMPLEX_TYPE( typename VT1::ElementType );
2387  BLAZE_CONSTRAINT_MUST_BE_COMPLEX_TYPE( typename MT1::ElementType );
2388  BLAZE_CONSTRAINT_MUST_BE_COMPLEX_TYPE( typename VT2::ElementType );
2390  BLAZE_CONSTRAINT_MUST_BE_DOUBLE_TYPE ( typename VT1::ElementType::value_type );
2391  BLAZE_CONSTRAINT_MUST_BE_DOUBLE_TYPE ( typename MT1::ElementType::value_type );
2392  BLAZE_CONSTRAINT_MUST_BE_DOUBLE_TYPE ( typename VT2::ElementType::value_type );
2393 
2394  const int M ( numeric_cast<int>( A.rows() ) );
2395  const int N ( numeric_cast<int>( A.columns() ) );
2396  const int lda( numeric_cast<int>( A.spacing() ) );
2397  const complex<double> alpha( scalar );
2398  const complex<double> beta ( 1.0, 0.0 );
2399 
2400  cblas_zgemv( CblasRowMajor, CblasNoTrans, M, N, &alpha,
2401  A.data(), lda, x.data(), 1, &beta, y.data(), 1 );
2402  }
2403 #endif
2404  //**********************************************************************************************
2405 
2406  //**Addition assignment to sparse vectors*******************************************************
2407  // No special implementation for the addition assignment to sparse vectors.
2408  //**********************************************************************************************
2409 
2410  //**Subtraction assignment to dense vectors*****************************************************
2422  template< typename VT1 > // Type of the target dense vector
2423  friend inline void subAssign( DenseVector<VT1,false>& lhs, const DVecScalarMultExpr& rhs )
2424  {
2425  BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
2426 
2427  typename MVM::LeftOperand left ( rhs.vector_.leftOperand() );
2428  typename MVM::RightOperand right( rhs.vector_.rightOperand() );
2429 
2430  if( left.rows() == 0UL || left.columns() == 0UL ) {
2431  return;
2432  }
2433 
2434  LT A( left ); // Evaluation of the left-hand side dense matrix operand
2435  RT x( right ); // Evaluation of the right-hand side dense vector operand
2436 
2437  BLAZE_INTERNAL_ASSERT( A.rows() == left.rows() , "Invalid number of rows" );
2438  BLAZE_INTERNAL_ASSERT( A.columns() == left.columns(), "Invalid number of columns" );
2439  BLAZE_INTERNAL_ASSERT( x.size() == right.size() , "Invalid vector size" );
2440  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).size() , "Invalid vector size" );
2441 
2442  if( ( IsComputation<MT>::value && !evaluate ) ||
2443  ( A.rows() * A.columns() < DMATDVECMULT_THRESHOLD ) )
2444  DVecScalarMultExpr::selectDefaultSubAssignKernel( ~lhs, A, x, rhs.scalar_ );
2445  else
2446  DVecScalarMultExpr::selectBlasSubAssignKernel( ~lhs, A, x, rhs.scalar_ );
2447  }
2448  //**********************************************************************************************
2449 
2450  //**Default subtraction assignment to dense vectors*********************************************
2464  template< typename VT1 // Type of the left-hand side target vector
2465  , typename MT1 // Type of the left-hand side matrix operand
2466  , typename VT2 // Type of the right-hand side vector operand
2467  , typename ST2 > // Type of the scalar value
2468  static inline typename DisableIf< UseVectorizedDefaultKernel<VT1,MT1,VT2,ST2> >::Type
2469  selectDefaultSubAssignKernel( VT1& y, const MT1& A, const VT2& x, ST2 scalar )
2470  {
2471  y.subAssign( A * x * scalar );
2472  }
2473  //**********************************************************************************************
2474 
2475  //**Vectorized default subtraction assignment to dense vectors**********************************
2489  template< typename VT1 // Type of the left-hand side target vector
2490  , typename MT1 // Type of the left-hand side matrix operand
2491  , typename VT2 // Type of the right-hand side vector operand
2492  , typename ST2 > // Type of the scalar value
2493  static inline typename EnableIf< UseVectorizedDefaultKernel<VT1,MT1,VT2,ST2> >::Type
2494  selectDefaultSubAssignKernel( VT1& y, const MT1& A, const VT2& x, ST2 scalar )
2495  {
2496  typedef IntrinsicTrait<ElementType> IT;
2497 
2498  const size_t M( A.rows() );
2499  const size_t N( A.columns() );
2500 
2501  size_t i( 0UL );
2502 
2503  for( ; (i+8UL) <= M; i+=8UL ) {
2504  IntrinsicType xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7, xmm8;
2505  for( size_t j=0UL; j<N; j+=IT::size ) {
2506  const IntrinsicType x1( x.get(j) );
2507  xmm1 = xmm1 + A.get(i ,j) * x1;
2508  xmm2 = xmm2 + A.get(i+1UL,j) * x1;
2509  xmm3 = xmm3 + A.get(i+2UL,j) * x1;
2510  xmm4 = xmm4 + A.get(i+3UL,j) * x1;
2511  xmm5 = xmm5 + A.get(i+4UL,j) * x1;
2512  xmm6 = xmm6 + A.get(i+5UL,j) * x1;
2513  xmm7 = xmm7 + A.get(i+6UL,j) * x1;
2514  xmm8 = xmm8 + A.get(i+7UL,j) * x1;
2515  }
2516  y[i ] -= sum( xmm1 ) * scalar;
2517  y[i+1UL] -= sum( xmm2 ) * scalar;
2518  y[i+2UL] -= sum( xmm3 ) * scalar;
2519  y[i+3UL] -= sum( xmm4 ) * scalar;
2520  y[i+4UL] -= sum( xmm5 ) * scalar;
2521  y[i+5UL] -= sum( xmm6 ) * scalar;
2522  y[i+6UL] -= sum( xmm7 ) * scalar;
2523  y[i+7UL] -= sum( xmm8 ) * scalar;
2524  }
2525  for( ; (i+4UL) <= M; i+=4UL ) {
2526  IntrinsicType xmm1, xmm2, xmm3, xmm4;
2527  for( size_t j=0UL; j<N; j+=IT::size ) {
2528  const IntrinsicType x1( x.get(j) );
2529  xmm1 = xmm1 + A.get(i ,j) * x1;
2530  xmm2 = xmm2 + A.get(i+1UL,j) * x1;
2531  xmm3 = xmm3 + A.get(i+2UL,j) * x1;
2532  xmm4 = xmm4 + A.get(i+3UL,j) * x1;
2533  }
2534  y[i ] -= sum( xmm1 ) * scalar;
2535  y[i+1UL] -= sum( xmm2 ) * scalar;
2536  y[i+2UL] -= sum( xmm3 ) * scalar;
2537  y[i+3UL] -= sum( xmm4 ) * scalar;
2538  }
2539  for( ; (i+3UL) <= M; i+=3UL ) {
2540  IntrinsicType xmm1, xmm2, xmm3;
2541  for( size_t j=0UL; j<N; j+=IT::size ) {
2542  const IntrinsicType x1( x.get(j) );
2543  xmm1 = xmm1 + A.get(i ,j) * x1;
2544  xmm2 = xmm2 + A.get(i+1UL,j) * x1;
2545  xmm3 = xmm3 + A.get(i+2UL,j) * x1;
2546  }
2547  y[i ] -= sum( xmm1 ) * scalar;
2548  y[i+1UL] -= sum( xmm2 ) * scalar;
2549  y[i+2UL] -= sum( xmm3 ) * scalar;
2550  }
2551  for( ; (i+2UL) <= M; i+=2UL ) {
2552  IntrinsicType xmm1, xmm2;
2553  for( size_t j=0UL; j<N; j+=IT::size ) {
2554  const IntrinsicType x1( x.get(j) );
2555  xmm1 = xmm1 + A.get(i ,j) * x1;
2556  xmm2 = xmm2 + A.get(i+1UL,j) * x1;
2557  }
2558  y[i ] -= sum( xmm1 ) * scalar;
2559  y[i+1UL] -= sum( xmm2 ) * scalar;
2560  }
2561  if( i < M ) {
2562  IntrinsicType xmm1;
2563  for( size_t j=0UL; j<N; j+=IT::size ) {
2564  xmm1 = xmm1 + A.get(i,j) * x.get(j);
2565  }
2566  y[i] -= sum( xmm1 ) * scalar;
2567  }
2568  }
2569  //**********************************************************************************************
2570 
2571  //**BLAS-based subtraction assignment to dense vectors (default)********************************
2585  template< typename VT1 // Type of the left-hand side target vector
2586  , typename MT1 // Type of the left-hand side matrix operand
2587  , typename VT2 // Type of the right-hand side vector operand
2588  , typename ST2 > // Type of the scalar value
2589  static inline typename EnableIf< UseDefaultKernel<VT1,MT1,VT2,ST2> >::Type
2590  selectBlasSubAssignKernel( VT1& y, const MT1& A, const VT2& x, ST2 scalar )
2591  {
2592  selectDefaultSubAssignKernel( y, A, x, scalar );
2593  }
2594  //**********************************************************************************************
2595 
2596  //**BLAS-based subtraction assignment to dense vectors (single precision)***********************
2597 #if BLAZE_BLAS_MODE
2598 
2611  template< typename VT1 // Type of the left-hand side target vector
2612  , typename MT1 // Type of the left-hand side matrix operand
2613  , typename VT2 // Type of the right-hand side vector operand
2614  , typename ST2 > // Type of the scalar value
2615  static inline typename EnableIf< UseSinglePrecisionKernel<VT1,MT1,VT2,ST2> >::Type
2616  selectBlasSubAssignKernel( VT1& y, const MT1& A, const VT2& x, ST2 scalar )
2617  {
2618  using boost::numeric_cast;
2619 
2620  BLAZE_CONSTRAINT_MUST_BE_FLOAT_TYPE( typename VT1::ElementType );
2621  BLAZE_CONSTRAINT_MUST_BE_FLOAT_TYPE( typename MT1::ElementType );
2622  BLAZE_CONSTRAINT_MUST_BE_FLOAT_TYPE( typename VT2::ElementType );
2623 
2624  const int M ( numeric_cast<int>( A.rows() ) );
2625  const int N ( numeric_cast<int>( A.columns() ) );
2626  const int lda( numeric_cast<int>( A.spacing() ) );
2627 
2628  cblas_sgemv( CblasRowMajor, CblasNoTrans, M, N, -scalar,
2629  A.data(), lda, x.data(), 1, 1.0F, y.data(), 1 );
2630  }
2631 #endif
2632  //**********************************************************************************************
2633 
2634  //**BLAS-based subtraction assignment to dense vectors (double precision)***********************
2635 #if BLAZE_BLAS_MODE
2636 
2649  template< typename VT1 // Type of the left-hand side target vector
2650  , typename MT1 // Type of the left-hand side matrix operand
2651  , typename VT2 // Type of the right-hand side vector operand
2652  , typename ST2 > // Type of the scalar value
2653  static inline typename EnableIf< UseDoublePrecisionKernel<VT1,MT1,VT2,ST2> >::Type
2654  selectBlasSubAssignKernel( VT1& y, const MT1& A, const VT2& x, ST2 scalar )
2655  {
2656  using boost::numeric_cast;
2657 
2658  BLAZE_CONSTRAINT_MUST_BE_DOUBLE_TYPE( typename VT1::ElementType );
2659  BLAZE_CONSTRAINT_MUST_BE_DOUBLE_TYPE( typename MT1::ElementType );
2660  BLAZE_CONSTRAINT_MUST_BE_DOUBLE_TYPE( typename VT2::ElementType );
2661 
2662  const int M ( numeric_cast<int>( A.rows() ) );
2663  const int N ( numeric_cast<int>( A.columns() ) );
2664  const int lda( numeric_cast<int>( A.spacing() ) );
2665 
2666  cblas_dgemv( CblasRowMajor, CblasNoTrans, M, N, -scalar,
2667  A.data(), lda, x.data(), 1, 1.0, y.data(), 1 );
2668  }
2669 #endif
2670  //**********************************************************************************************
2671 
2672  //**BLAS-based subtraction assignment to dense vectors (single precision complex)***************
2673 #if BLAZE_BLAS_MODE
2674 
2687  template< typename VT1 // Type of the left-hand side target vector
2688  , typename MT1 // Type of the left-hand side matrix operand
2689  , typename VT2 // Type of the right-hand side vector operand
2690  , typename ST2 > // Type of the scalar value
2691  static inline typename EnableIf< UseSinglePrecisionComplexKernel<VT1,MT1,VT2> >::Type
2692  selectBlasSubAssignKernel( VT1& y, const MT1& A, const VT2& x, ST2 scalar )
2693  {
2694  using boost::numeric_cast;
2695 
2696  BLAZE_CONSTRAINT_MUST_BE_COMPLEX_TYPE( typename VT1::ElementType );
2697  BLAZE_CONSTRAINT_MUST_BE_COMPLEX_TYPE( typename MT1::ElementType );
2698  BLAZE_CONSTRAINT_MUST_BE_COMPLEX_TYPE( typename VT2::ElementType );
2700  BLAZE_CONSTRAINT_MUST_BE_FLOAT_TYPE ( typename VT1::ElementType::value_type );
2701  BLAZE_CONSTRAINT_MUST_BE_FLOAT_TYPE ( typename MT1::ElementType::value_type );
2702  BLAZE_CONSTRAINT_MUST_BE_FLOAT_TYPE ( typename VT2::ElementType::value_type );
2703 
2704  const int M ( numeric_cast<int>( A.rows() ) );
2705  const int N ( numeric_cast<int>( A.columns() ) );
2706  const int lda( numeric_cast<int>( A.spacing() ) );
2707  const complex<float> alpha( -scalar );
2708  const complex<float> beta ( 1.0F, 0.0F );
2709 
2710  cblas_cgemv( CblasRowMajor, CblasNoTrans, M, N, &alpha,
2711  A.data(), lda, x.data(), 1, &beta, y.data(), 1 );
2712  }
2713 #endif
2714  //**********************************************************************************************
2715 
2716  //**BLAS-based subtraction assignment to dense vectors (double precision complex)***************
2717 #if BLAZE_BLAS_MODE
2718 
2731  template< typename VT1 // Type of the left-hand side target vector
2732  , typename MT1 // Type of the left-hand side matrix operand
2733  , typename VT2 // Type of the right-hand side vector operand
2734  , typename ST2 > // Type of the scalar value
2735  static inline typename EnableIf< UseDoublePrecisionComplexKernel<VT1,MT1,VT2> >::Type
2736  selectBlasSubAssignKernel( VT1& y, const MT1& A, const VT2& x, ST2 scalar )
2737  {
2738  using boost::numeric_cast;
2739 
2740  BLAZE_CONSTRAINT_MUST_BE_COMPLEX_TYPE( typename VT1::ElementType );
2741  BLAZE_CONSTRAINT_MUST_BE_COMPLEX_TYPE( typename MT1::ElementType );
2742  BLAZE_CONSTRAINT_MUST_BE_COMPLEX_TYPE( typename VT2::ElementType );
2744  BLAZE_CONSTRAINT_MUST_BE_DOUBLE_TYPE ( typename VT1::ElementType::value_type );
2745  BLAZE_CONSTRAINT_MUST_BE_DOUBLE_TYPE ( typename MT1::ElementType::value_type );
2746  BLAZE_CONSTRAINT_MUST_BE_DOUBLE_TYPE ( typename VT2::ElementType::value_type );
2747 
2748  const int M ( numeric_cast<int>( A.rows() ) );
2749  const int N ( numeric_cast<int>( A.columns() ) );
2750  const int lda( numeric_cast<int>( A.spacing() ) );
2751  const complex<double> alpha( -scalar );
2752  const complex<double> beta ( 1.0, 0.0 );
2753 
2754  cblas_zgemv( CblasRowMajor, CblasNoTrans, M, N, &alpha,
2755  A.data(), lda, x.data(), 1, &beta, y.data(), 1 );
2756  }
2757 #endif
2758  //**********************************************************************************************
2759 
2760  //**Subtraction assignment to sparse vectors****************************************************
2761  // No special implementation for the subtraction assignment to sparse vectors.
2762  //**********************************************************************************************
2763 
2764  //**Multiplication assignment to dense vectors**************************************************
2776  template< typename VT1 > // Type of the target dense vector
2777  friend inline void multAssign( DenseVector<VT1,false>& lhs, const DVecScalarMultExpr& rhs )
2778  {
2781  BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( typename ResultType::CompositeType );
2782 
2783  BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
2784 
2785  const ResultType tmp( rhs );
2786  multAssign( ~lhs, tmp );
2787  }
2788  //**********************************************************************************************
2789 
2790  //**Multiplication assignment to sparse vectors*************************************************
2791  // No special implementation for the multiplication assignment to sparse vectors.
2792  //**********************************************************************************************
2793 
2794  //**Compile time checks*************************************************************************
2802  //**********************************************************************************************
2803 };
2805 //*************************************************************************************************
2806 
2807 
2808 
2809 
2810 //=================================================================================================
2811 //
2812 // GLOBAL BINARY ARITHMETIC OPERATORS
2813 //
2814 //=================================================================================================
2815 
2816 //*************************************************************************************************
2846 template< typename T1 // Type of the left-hand side dense matrix
2847  , typename T2 > // Type of the right-hand side dense vector
2848 inline const typename DisableIf< IsMatMatMultExpr<T1>, DMatDVecMultExpr<T1,T2> >::Type
2850 {
2851  if( (~mat).columns() != (~vec).size() )
2852  throw std::invalid_argument( "Matrix and vector sizes do not match" );
2853 
2854  return DMatDVecMultExpr<T1,T2>( ~mat, ~vec );
2855 }
2856 //*************************************************************************************************
2857 
2858 
2859 
2860 
2861 //=================================================================================================
2862 //
2863 // GLOBAL RESTRUCTURING BINARY ARITHMETIC OPERATORS
2864 //
2865 //=================================================================================================
2866 
2867 //*************************************************************************************************
2880 template< typename T1 // Type of the left-hand side dense matrix
2881  , bool SO // Storage order of the left-hand side dense matrix
2882  , typename T2 > // Type of the right-hand side dense vector
2883 inline const typename EnableIf< IsMatMatMultExpr<T1>, MultExprTrait<T1,T2> >::Type::Type
2885 {
2886  return (~mat).leftOperand() * ( (~mat).rightOperand() * vec );
2887 }
2888 //*************************************************************************************************
2889 
2890 } // namespace blaze
2891 
2892 #endif