All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
TDVecDMatMultExpr.h
Go to the documentation of this file.
1 //=================================================================================================
33 //=================================================================================================
34 
35 #ifndef _BLAZE_MATH_EXPRESSIONS_TDVECDMATMULTEXPR_H_
36 #define _BLAZE_MATH_EXPRESSIONS_TDVECDMATMULTEXPR_H_
37 
38 
39 //*************************************************************************************************
40 // Includes
41 //*************************************************************************************************
42 
43 #include <stdexcept>
44 #include <boost/cast.hpp>
56 #include <blaze/math/Intrinsics.h>
57 #include <blaze/math/shims/Reset.h>
70 #include <blaze/system/BLAS.h>
72 #include <blaze/util/Assert.h>
73 #include <blaze/util/Complex.h>
79 #include <blaze/util/DisableIf.h>
80 #include <blaze/util/EnableIf.h>
82 #include <blaze/util/SelectType.h>
83 #include <blaze/util/Types.h>
89 
90 
91 namespace blaze {
92 
93 //=================================================================================================
94 //
95 // CLASS TDVECDMATMULTEXPR
96 //
97 //=================================================================================================
98 
99 //*************************************************************************************************
106 template< typename VT // Type of the left-hand side dense vector
107  , typename MT > // Type of the right-hand side dense matrix
108 class TDVecDMatMultExpr : public DenseVector< TDVecDMatMultExpr<VT,MT>, true >
109  , private TVecMatMultExpr
110  , private Computation
111 {
112  private:
113  //**Type definitions****************************************************************************
114  typedef typename VT::ResultType VRT;
115  typedef typename MT::ResultType MRT;
116  typedef typename VRT::ElementType VET;
117  typedef typename MRT::ElementType MET;
118  typedef typename VT::CompositeType VCT;
119  typedef typename MT::CompositeType MCT;
120  //**********************************************************************************************
121 
122  //**********************************************************************************************
124  enum { evaluateVector = IsComputation<VT>::value || RequiresEvaluation<VT>::value };
125  //**********************************************************************************************
126 
127  //**********************************************************************************************
129  enum { evaluateMatrix = ( IsComputation<MT>::value && IsSame<MET,VET>::value &&
131  //**********************************************************************************************
132 
133  //**********************************************************************************************
135 
139  template< typename T1 >
140  struct UseSMPAssign {
141  enum { value = ( evaluateVector || evaluateMatrix ) };
142  };
144  //**********************************************************************************************
145 
146  //**********************************************************************************************
148 
152  template< typename T1, typename T2, typename T3 >
153  struct UseSinglePrecisionKernel {
154  enum { value = BLAZE_BLAS_MODE &&
155  T1::vectorizable && T2::vectorizable && T3::vectorizable &&
156  IsFloat<typename T1::ElementType>::value &&
157  IsFloat<typename T2::ElementType>::value &&
158  IsFloat<typename T3::ElementType>::value };
159  };
161  //**********************************************************************************************
162 
163  //**********************************************************************************************
165 
169  template< typename T1, typename T2, typename T3 >
170  struct UseDoublePrecisionKernel {
171  enum { value = BLAZE_BLAS_MODE &&
172  T1::vectorizable && T2::vectorizable && T3::vectorizable &&
173  IsDouble<typename T1::ElementType>::value &&
174  IsDouble<typename T2::ElementType>::value &&
175  IsDouble<typename T3::ElementType>::value };
176  };
178  //**********************************************************************************************
179 
180  //**********************************************************************************************
182 
186  template< typename T1, typename T2, typename T3 >
187  struct UseSinglePrecisionComplexKernel {
188  typedef complex<float> Type;
189  enum { value = BLAZE_BLAS_MODE &&
190  T1::vectorizable && T2::vectorizable && T3::vectorizable &&
191  IsSame<typename T1::ElementType,Type>::value &&
192  IsSame<typename T2::ElementType,Type>::value &&
193  IsSame<typename T3::ElementType,Type>::value };
194  };
196  //**********************************************************************************************
197 
198  //**********************************************************************************************
200 
204  template< typename T1, typename T2, typename T3 >
205  struct UseDoublePrecisionComplexKernel {
206  typedef complex<double> Type;
207  enum { value = BLAZE_BLAS_MODE &&
208  T1::vectorizable && T2::vectorizable && T3::vectorizable &&
209  IsSame<typename T1::ElementType,Type>::value &&
210  IsSame<typename T2::ElementType,Type>::value &&
211  IsSame<typename T3::ElementType,Type>::value };
212  };
214  //**********************************************************************************************
215 
216  //**********************************************************************************************
218 
221  template< typename T1, typename T2, typename T3 >
222  struct UseDefaultKernel {
223  enum { value = !BLAZE_BLAS_MODE || ( !UseSinglePrecisionKernel<T1,T2,T3>::value &&
224  !UseDoublePrecisionKernel<T1,T2,T3>::value &&
225  !UseSinglePrecisionComplexKernel<T1,T2,T3>::value &&
226  !UseDoublePrecisionComplexKernel<T1,T2,T3>::value ) };
227  };
229  //**********************************************************************************************
230 
231  //**********************************************************************************************
233 
237  template< typename T1, typename T2, typename T3 >
238  struct UseVectorizedDefaultKernel {
239  enum { value = T1::vectorizable && T2::vectorizable && T3::vectorizable &&
240  IsSame<typename T1::ElementType,typename T2::ElementType>::value &&
241  IsSame<typename T1::ElementType,typename T3::ElementType>::value &&
242  IntrinsicTrait<typename T1::ElementType>::addition &&
243  IntrinsicTrait<typename T1::ElementType>::multiplication };
244  };
246  //**********************************************************************************************
247 
248  public:
249  //**Type definitions****************************************************************************
255  typedef const ElementType ReturnType;
256  typedef const ResultType CompositeType;
257 
259  typedef typename SelectType< IsExpression<VT>::value, const VT, const VT& >::Type LeftOperand;
260 
262  typedef typename SelectType< IsExpression<MT>::value, const MT, const MT& >::Type RightOperand;
263 
266 
269  //**********************************************************************************************
270 
271  //**Compilation flags***************************************************************************
273  enum { vectorizable = VT::vectorizable && MT::vectorizable &&
277 
279  enum { smpAssignable = !evaluateVector && VT::smpAssignable &&
280  !evaluateMatrix && MT::smpAssignable };
281  //**********************************************************************************************
282 
283  //**Constructor*********************************************************************************
289  explicit inline TDVecDMatMultExpr( const VT& vec, const MT& mat )
290  : vec_( vec ) // Left-hand side dense vector of the multiplication expression
291  , mat_( mat ) // Right-hand side dense matrix of the multiplication expression
292  , end_( ( (mat.rows()-1UL) & size_t(-2) ) + 1UL ) // End of the unrolled calculation loop
293  {
294  BLAZE_INTERNAL_ASSERT( vec_.size() == mat_.rows(), "Invalid vector and matrix sizes" );
295  }
296  //**********************************************************************************************
297 
298  //**Subscript operator**************************************************************************
304  inline ReturnType operator[]( size_t index ) const {
305  BLAZE_INTERNAL_ASSERT( index < mat_.columns(), "Invalid vector access index" );
306 
307  ElementType res;
308 
309  if( mat_.rows() != 0UL ) {
310  res = vec_[0UL] * mat_(0UL,index);
311  for( size_t j=1UL; j<end_; j+=2UL ) {
312  res += vec_[j] * mat_(j,index) + vec_[j+1UL] * mat_(j+1UL,index);
313  }
314  if( end_ < mat_.rows() ) {
315  res += vec_[end_] * mat_(end_,index);
316  }
317  }
318  else {
319  reset( res );
320  }
321 
322  return res;
323  }
324  //**********************************************************************************************
325 
326  //**Size function*******************************************************************************
331  inline size_t size() const {
332  return mat_.columns();
333  }
334  //**********************************************************************************************
335 
336  //**Left operand access*************************************************************************
341  inline LeftOperand leftOperand() const {
342  return vec_;
343  }
344  //**********************************************************************************************
345 
346  //**Right operand access************************************************************************
351  inline RightOperand rightOperand() const {
352  return mat_;
353  }
354  //**********************************************************************************************
355 
356  //**********************************************************************************************
362  template< typename T >
363  inline bool canAlias( const T* alias ) const {
364  return ( vec_.isAliased( alias ) || mat_.isAliased( alias ) );
365  }
366  //**********************************************************************************************
367 
368  //**********************************************************************************************
374  template< typename T >
375  inline bool isAliased( const T* alias ) const {
376  return ( vec_.isAliased( alias ) || mat_.isAliased( alias ) );
377  }
378  //**********************************************************************************************
379 
380  //**********************************************************************************************
385  inline bool isAligned() const {
386  return vec_.isAligned() && mat_.isAligned();
387  }
388  //**********************************************************************************************
389 
390  //**********************************************************************************************
395  inline bool canSMPAssign() const {
396  return ( !BLAZE_BLAS_IS_PARALLEL ||
397  ( IsComputation<MT>::value && !evaluateMatrix ) ||
398  ( mat_.rows() * mat_.columns() < TDVECDMATMULT_THRESHOLD ) ) &&
400  }
401  //**********************************************************************************************
402 
403  private:
404  //**Member variables****************************************************************************
407  const size_t end_;
408  //**********************************************************************************************
409 
410  //**BLAS kernel (single precision)**************************************************************
411 #if BLAZE_BLAS_MODE
412 
427  template< typename VT1 // Type of the left-hand side target vector
428  , typename VT2 // Type of the left-hand side vector operand
429  , typename MT1 > // Type of the right-hand side matrix operand
430  static inline void sgemv( VT1& y, const VT2& x, const MT1& A, float alpha, float beta )
431  {
432  using boost::numeric_cast;
433 
437 
438  const int M ( numeric_cast<int>( A.rows() ) );
439  const int N ( numeric_cast<int>( A.columns() ) );
440  const int lda( numeric_cast<int>( A.spacing() ) );
441 
442  cblas_sgemv( CblasRowMajor, CblasTrans, M, N, alpha,
443  A.data(), lda, x.data(), 1, beta, y.data(), 1 );
444  }
446 #endif
447  //**********************************************************************************************
448 
449  //**BLAS kernel (double precision)**************************************************************
450 #if BLAZE_BLAS_MODE
451 
466  template< typename VT1 // Type of the left-hand side target vector
467  , typename VT2 // Type of the left-hand side vector operand
468  , typename MT1 > // Type of the right-hand side matrix operand
469  static inline void dgemv( VT1& y, const VT2& x, const MT1& A, double alpha, double beta )
470  {
471  using boost::numeric_cast;
472 
476 
477  const int M ( numeric_cast<int>( A.rows() ) );
478  const int N ( numeric_cast<int>( A.columns() ) );
479  const int lda( numeric_cast<int>( A.spacing() ) );
480 
481  cblas_dgemv( CblasRowMajor, CblasTrans, M, N, alpha,
482  A.data(), lda, x.data(), 1, beta, y.data(), 1 );
483  }
485 #endif
486  //**********************************************************************************************
487 
488  //**BLAS kernel (single precision complex)******************************************************
489 #if BLAZE_BLAS_MODE
490 
505  template< typename VT1 // Type of the left-hand side target vector
506  , typename VT2 // Type of the left-hand side vector operand
507  , typename MT1 > // Type of the right-hand side matrix operand
508  static inline void cgemv( VT1& y, const VT2& x, const MT1& A,
509  complex<float> alpha, complex<float> beta )
510  {
511  using boost::numeric_cast;
512 
516  BLAZE_CONSTRAINT_MUST_BE_FLOAT_TYPE ( typename VT1::ElementType::value_type );
517  BLAZE_CONSTRAINT_MUST_BE_FLOAT_TYPE ( typename VT2::ElementType::value_type );
518  BLAZE_CONSTRAINT_MUST_BE_FLOAT_TYPE ( typename MT1::ElementType::value_type );
519 
520  const int M ( numeric_cast<int>( A.rows() ) );
521  const int N ( numeric_cast<int>( A.columns() ) );
522  const int lda( numeric_cast<int>( A.spacing() ) );
523 
524  cblas_cgemv( CblasRowMajor, CblasTrans, M, N, &alpha,
525  A.data(), lda, x.data(), 1, &beta, y.data(), 1 );
526  }
528 #endif
529  //**********************************************************************************************
530 
531  //**BLAS kernel (double precision complex)******************************************************
532 #if BLAZE_BLAS_MODE
533 
548  template< typename VT1 // Type of the left-hand side target vector
549  , typename VT2 // Type of the left-hand side vector operand
550  , typename MT1 > // Type of the right-hand side matrix operand
551  static inline void zgemv( VT1& y, const VT2& x, const MT1& A,
552  complex<double> alpha, complex<float> beta )
553  {
554  using boost::numeric_cast;
555 
559  BLAZE_CONSTRAINT_MUST_BE_DOUBLE_TYPE ( typename VT1::ElementType::value_type );
560  BLAZE_CONSTRAINT_MUST_BE_DOUBLE_TYPE ( typename VT2::ElementType::value_type );
561  BLAZE_CONSTRAINT_MUST_BE_DOUBLE_TYPE ( typename MT1::ElementType::value_type );
562 
563  const int M ( numeric_cast<int>( A.rows() ) );
564  const int N ( numeric_cast<int>( A.columns() ) );
565  const int lda( numeric_cast<int>( A.spacing() ) );
566 
567  cblas_zgemv( CblasRowMajor, CblasTrans, M, N, &alpha,
568  A.data(), lda, x.data(), 1, &beta, y.data(), 1 );
569  }
571 #endif
572  //**********************************************************************************************
573 
574  //**Assignment to dense vectors*****************************************************************
587  template< typename VT1 > // Type of the target dense vector
588  friend inline void assign( DenseVector<VT1,true>& lhs, const TDVecDMatMultExpr& rhs )
589  {
591 
592  BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
593 
594  if( rhs.mat_.rows() == 0UL ) {
595  reset( ~lhs );
596  return;
597  }
598  else if( rhs.mat_.columns() == 0UL ) {
599  return;
600  }
601 
602  LT x( serial( rhs.vec_ ) ); // Evaluation of the left-hand side dense vector operand
603  RT A( serial( rhs.mat_ ) ); // Evaluation of the right-hand side dense matrix operand
604 
605  BLAZE_INTERNAL_ASSERT( x.size() == rhs.vec_.size() , "Invalid vector size" );
606  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.mat_.rows() , "Invalid number of rows" );
607  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.mat_.columns(), "Invalid number of columns" );
608  BLAZE_INTERNAL_ASSERT( A.columns() == (~lhs).size() , "Invalid vector size" );
609 
610  TDVecDMatMultExpr::selectAssignKernel( ~lhs, x, A );
611  }
613  //**********************************************************************************************
614 
615  //**Assignment to dense vectors (kernel selection)**********************************************
626  template< typename VT1 // Type of the left-hand side target vector
627  , typename VT2 // Type of the left-hand side vector operand
628  , typename MT1 > // Type of the right-hand side matrix operand
629  static inline void selectAssignKernel( VT1& y, const VT2& x, const MT1& A )
630  {
631  if( ( IsComputation<MT>::value && !evaluateMatrix ) ||
632  ( A.rows() * A.columns() < TDVECDMATMULT_THRESHOLD ) )
633  TDVecDMatMultExpr::selectDefaultAssignKernel( y, x, A );
634  else
635  TDVecDMatMultExpr::selectBlasAssignKernel( y, x, A );
636  }
638  //**********************************************************************************************
639 
640  //**Default assignment to dense vectors*********************************************************
654  template< typename VT1 // Type of the left-hand side target vector
655  , typename VT2 // Type of the left-hand side vector operand
656  , typename MT1 > // Type of the right-hand side matrix operand
657  static inline typename DisableIf< UseVectorizedDefaultKernel<VT1,VT2,MT1> >::Type
658  selectDefaultAssignKernel( VT1& y, const VT2& x, const MT1& A )
659  {
660  const size_t M( A.rows() );
661  const size_t N( A.columns() );
662 
663  BLAZE_INTERNAL_ASSERT( ( N - ( N % 2UL ) ) == ( N & size_t(-2) ), "Invalid end calculation" );
664  const size_t jend( N & size_t(-2) );
665 
666  for( size_t j=0UL; j<N; ++j ) {
667  y[j] = x[0UL] * A(0UL,j);
668  }
669  for( size_t i=1UL; i<M; ++i ) {
670  for( size_t j=0UL; j<jend; j+=2UL ) {
671  y[j ] += x[i] * A(i,j );
672  y[j+1UL] += x[i] * A(i,j+1UL);
673  }
674  if( jend < N ) {
675  y[jend] += x[i] * A(i,jend);
676  }
677  }
678  }
680  //**********************************************************************************************
681 
682  //**Vectorized default assignment to dense vectors**********************************************
696  template< typename VT1 // Type of the left-hand side target vector
697  , typename VT2 // Type of the left-hand side vector operand
698  , typename MT1 > // Type of the right-hand side matrix operand
699  static inline typename EnableIf< UseVectorizedDefaultKernel<VT1,VT2,MT1> >::Type
700  selectDefaultAssignKernel( VT1& y, const VT2& x, const MT1& A )
701  {
702  typedef IntrinsicTrait<ElementType> IT;
703 
704  const size_t M( A.rows() );
705  const size_t N( A.columns() );
706 
707  size_t j( 0UL );
708 
709  for( ; (j+IT::size*7UL) < N; j+=IT::size*8UL ) {
710  IntrinsicType xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7, xmm8;
711  for( size_t i=0UL; i<M; ++i ) {
712  const IntrinsicType x1( set( x[i] ) );
713  xmm1 = xmm1 + x1 * A.load(i,j );
714  xmm2 = xmm2 + x1 * A.load(i,j+IT::size );
715  xmm3 = xmm3 + x1 * A.load(i,j+IT::size*2UL);
716  xmm4 = xmm4 + x1 * A.load(i,j+IT::size*3UL);
717  xmm5 = xmm5 + x1 * A.load(i,j+IT::size*4UL);
718  xmm6 = xmm6 + x1 * A.load(i,j+IT::size*5UL);
719  xmm7 = xmm7 + x1 * A.load(i,j+IT::size*6UL);
720  xmm8 = xmm8 + x1 * A.load(i,j+IT::size*7UL);
721  }
722  y.store( j , xmm1 );
723  y.store( j+IT::size , xmm2 );
724  y.store( j+IT::size*2UL, xmm3 );
725  y.store( j+IT::size*3UL, xmm4 );
726  y.store( j+IT::size*4UL, xmm5 );
727  y.store( j+IT::size*5UL, xmm6 );
728  y.store( j+IT::size*6UL, xmm7 );
729  y.store( j+IT::size*7UL, xmm8 );
730  }
731  for( ; (j+IT::size*3UL) < N; j+=IT::size*4UL ) {
732  IntrinsicType xmm1, xmm2, xmm3, xmm4;
733  for( size_t i=0UL; i<M; ++i ) {
734  const IntrinsicType x1( set( x[i] ) );
735  xmm1 = xmm1 + x1 * A.load(i,j );
736  xmm2 = xmm2 + x1 * A.load(i,j+IT::size );
737  xmm3 = xmm3 + x1 * A.load(i,j+IT::size*2UL);
738  xmm4 = xmm4 + x1 * A.load(i,j+IT::size*3UL);
739  }
740  y.store( j , xmm1 );
741  y.store( j+IT::size , xmm2 );
742  y.store( j+IT::size*2UL, xmm3 );
743  y.store( j+IT::size*3UL, xmm4 );
744  }
745  for( ; (j+IT::size*2UL) < N; j+=IT::size*3UL ) {
746  IntrinsicType xmm1, xmm2, xmm3;
747  for( size_t i=0UL; i<M; ++i ) {
748  const IntrinsicType x1( set( x[i] ) );
749  xmm1 = xmm1 + x1 * A.load(i,j );
750  xmm2 = xmm2 + x1 * A.load(i,j+IT::size );
751  xmm3 = xmm3 + x1 * A.load(i,j+IT::size*2UL);
752  }
753  y.store( j , xmm1 );
754  y.store( j+IT::size , xmm2 );
755  y.store( j+IT::size*2UL, xmm3 );
756  }
757  for( ; (j+IT::size) < N; j+=IT::size*2UL ) {
758  IntrinsicType xmm1, xmm2;
759  for( size_t i=0UL; i<M; ++i ) {
760  const IntrinsicType x1( set( x[i] ) );
761  xmm1 = xmm1 + x1 * A.load(i,j );
762  xmm2 = xmm2 + x1 * A.load(i,j+IT::size);
763  }
764  y.store( j , xmm1 );
765  y.store( j+IT::size, xmm2 );
766  }
767  if( j < N ) {
768  IntrinsicType xmm1;
769  for( size_t i=0UL; i<M; ++i ) {
770  xmm1 = xmm1 + set( x[i] ) * A.load(i,j);
771  }
772  y.store( j, xmm1 );
773  }
774  }
776  //**********************************************************************************************
777 
778  //**BLAS-based assignment to dense vectors (default)********************************************
792  template< typename VT1 // Type of the left-hand side target vector
793  , typename VT2 // Type of the left-hand side vector operand
794  , typename MT1 > // Type of the right-hand side matrix operand
795  static inline typename EnableIf< UseDefaultKernel<VT1,VT2,MT1> >::Type
796  selectBlasAssignKernel( VT1& y, const VT2& x, const MT1& A )
797  {
798  selectDefaultAssignKernel( y, x, A );
799  }
801  //**********************************************************************************************
802 
803  //**BLAS-based assignment to dense vectors (single precision)***********************************
804 #if BLAZE_BLAS_MODE
805 
818  template< typename VT1 // Type of the left-hand side target vector
819  , typename VT2 // Type of the left-hand side vector operand
820  , typename MT1 > // Type of the right-hand side matrix operand
821  static inline typename EnableIf< UseSinglePrecisionKernel<VT1,VT2,MT1> >::Type
822  selectBlasAssignKernel( VT1& y, const VT2& x, const MT1& A )
823  {
824  sgemv( y, x, A, 1.0F, 0.0F );
825  }
827 #endif
828  //**********************************************************************************************
829 
830  //**BLAS-based assignment to dense vectors (double precision)***********************************
831 #if BLAZE_BLAS_MODE
832 
845  template< typename VT1 // Type of the left-hand side target vector
846  , typename VT2 // Type of the left-hand side vector operand
847  , typename MT1 > // Type of the right-hand side matrix operand
848  static inline typename EnableIf< UseDoublePrecisionKernel<VT1,VT2,MT1> >::Type
849  selectBlasAssignKernel( VT1& y, const VT2& x, const MT1& A )
850  {
851  dgemv( y, x, A, 1.0, 0.0 );
852  }
854 #endif
855  //**********************************************************************************************
856 
857  //**BLAS-based assignment to dense vectors (single precision complex)***************************
858 #if BLAZE_BLAS_MODE
859 
872  template< typename VT1 // Type of the left-hand side target vector
873  , typename VT2 // Type of the left-hand side vector operand
874  , typename MT1 > // Type of the right-hand side matrix operand
875  static inline typename EnableIf< UseSinglePrecisionComplexKernel<VT1,VT2,MT1> >::Type
876  selectBlasAssignKernel( VT1& y, const VT2& x, const MT1& A )
877  {
878  cgemv( y, x, A, complex<float>( 1.0F, 0.0F ), complex<float>( 0.0F, 0.0F ) );
879  }
881 #endif
882  //**********************************************************************************************
883 
884  //**BLAS-based assignment to dense vectors (double precision complex)***************************
885 #if BLAZE_BLAS_MODE
886 
899  template< typename VT1 // Type of the left-hand side target vector
900  , typename VT2 // Type of the left-hand side vector operand
901  , typename MT1 > // Type of the right-hand side matrix operand
902  static inline typename EnableIf< UseDoublePrecisionComplexKernel<VT1,VT2,MT1> >::Type
903  selectBlasAssignKernel( VT1& y, const VT2& x, const MT1& A )
904  {
905  zgemv( y, x, A, complex<double>( 1.0, 0.0 ), complex<double>( 0.0, 0.0 ) );
906  }
908 #endif
909  //**********************************************************************************************
910 
911  //**Assignment to sparse vectors****************************************************************
924  template< typename VT1 > // Type of the target sparse vector
925  friend inline void assign( SparseVector<VT1,true>& lhs, const TDVecDMatMultExpr& rhs )
926  {
928 
932 
933  BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
934 
935  const ResultType tmp( serial( rhs ) );
936  assign( ~lhs, tmp );
937  }
939  //**********************************************************************************************
940 
941  //**Addition assignment to dense vectors********************************************************
954  template< typename VT1 > // Type of the target dense vector
955  friend inline void addAssign( DenseVector<VT1,true>& lhs, const TDVecDMatMultExpr& rhs )
956  {
958 
959  BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
960 
961  if( rhs.mat_.rows() == 0UL || rhs.mat_.columns() == 0UL ) {
962  return;
963  }
964 
965  LT x( serial( rhs.vec_ ) ); // Evaluation of the left-hand side dense vector operand
966  RT A( serial( rhs.mat_ ) ); // Evaluation of the right-hand side dense matrix operand
967 
968  BLAZE_INTERNAL_ASSERT( x.size() == rhs.vec_.size() , "Invalid vector size" );
969  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.mat_.rows() , "Invalid number of rows" );
970  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.mat_.columns(), "Invalid number of columns" );
971  BLAZE_INTERNAL_ASSERT( A.columns() == (~lhs).size() , "Invalid vector size" );
972 
973  TDVecDMatMultExpr::selectAddAssignKernel( ~lhs, x, A );
974  }
976  //**********************************************************************************************
977 
978  //**Addition assignment to dense vectors (kernel selection)*************************************
989  template< typename VT1 // Type of the left-hand side target vector
990  , typename VT2 // Type of the left-hand side vector operand
991  , typename MT1 > // Type of the right-hand side matrix operand
992  static inline void selectAddAssignKernel( VT1& y, const VT2& x, const MT1& A )
993  {
994  if( ( IsComputation<MT>::value && !evaluateMatrix ) ||
995  ( A.rows() * A.columns() < TDVECDMATMULT_THRESHOLD ) )
996  TDVecDMatMultExpr::selectDefaultAddAssignKernel( y, x, A );
997  else
998  TDVecDMatMultExpr::selectBlasAddAssignKernel( y, x, A );
999  }
1001  //**********************************************************************************************
1002 
1003  //**Default addition assignment to dense vectors************************************************
1017  template< typename VT1 // Type of the left-hand side target vector
1018  , typename VT2 // Type of the left-hand side vector operand
1019  , typename MT1 > // Type of the right-hand side matrix operand
1020  static inline typename DisableIf< UseVectorizedDefaultKernel<VT1,VT2,MT1> >::Type
1021  selectDefaultAddAssignKernel( VT1& y, const VT2& x, const MT1& A )
1022  {
1023  const size_t M( A.rows() );
1024  const size_t N( A.columns() );
1025 
1026  BLAZE_INTERNAL_ASSERT( ( N - ( N % 2UL ) ) == ( N & size_t(-2) ), "Invalid end calculation" );
1027  const size_t jend( N & size_t(-2) );
1028 
1029  for( size_t i=0UL; i<M; ++i ) {
1030  for( size_t j=0UL; j<jend; j+=2UL ) {
1031  y[j ] += x[i] * A(i,j );
1032  y[j+1UL] += x[i] * A(i,j+1UL);
1033  }
1034  if( jend < N ) {
1035  y[jend] += x[i] * A(i,jend);
1036  }
1037  }
1038  }
1040  //**********************************************************************************************
1041 
1042  //**Vectorized default addition assignment to dense vectors*************************************
1056  template< typename VT1 // Type of the left-hand side target vector
1057  , typename VT2 // Type of the left-hand side vector operand
1058  , typename MT1 > // Type of the right-hand side matrix operand
1059  static inline typename EnableIf< UseVectorizedDefaultKernel<VT1,VT2,MT1> >::Type
1060  selectDefaultAddAssignKernel( VT1& y, const VT2& x, const MT1& A )
1061  {
1062  typedef IntrinsicTrait<ElementType> IT;
1063 
1064  const size_t M( A.rows() );
1065  const size_t N( A.columns() );
1066 
1067  size_t j( 0UL );
1068 
1069  for( ; (j+IT::size*7UL) < N; j+=IT::size*8UL ) {
1070  IntrinsicType xmm1( y.load(j ) );
1071  IntrinsicType xmm2( y.load(j+IT::size ) );
1072  IntrinsicType xmm3( y.load(j+IT::size*2UL) );
1073  IntrinsicType xmm4( y.load(j+IT::size*3UL) );
1074  IntrinsicType xmm5( y.load(j+IT::size*4UL) );
1075  IntrinsicType xmm6( y.load(j+IT::size*5UL) );
1076  IntrinsicType xmm7( y.load(j+IT::size*6UL) );
1077  IntrinsicType xmm8( y.load(j+IT::size*7UL) );
1078  for( size_t i=0UL; i<M; ++i ) {
1079  const IntrinsicType x1( set( x[i] ) );
1080  xmm1 = xmm1 + x1 * A.load(i,j );
1081  xmm2 = xmm2 + x1 * A.load(i,j+IT::size );
1082  xmm3 = xmm3 + x1 * A.load(i,j+IT::size*2UL);
1083  xmm4 = xmm4 + x1 * A.load(i,j+IT::size*3UL);
1084  xmm5 = xmm5 + x1 * A.load(i,j+IT::size*4UL);
1085  xmm6 = xmm6 + x1 * A.load(i,j+IT::size*5UL);
1086  xmm7 = xmm7 + x1 * A.load(i,j+IT::size*6UL);
1087  xmm8 = xmm8 + x1 * A.load(i,j+IT::size*7UL);
1088  }
1089  y.store( j , xmm1 );
1090  y.store( j+IT::size , xmm2 );
1091  y.store( j+IT::size*2UL, xmm3 );
1092  y.store( j+IT::size*3UL, xmm4 );
1093  y.store( j+IT::size*4UL, xmm5 );
1094  y.store( j+IT::size*5UL, xmm6 );
1095  y.store( j+IT::size*6UL, xmm7 );
1096  y.store( j+IT::size*7UL, xmm8 );
1097  }
1098  for( ; (j+IT::size*3UL) < N; j+=IT::size*4UL ) {
1099  IntrinsicType xmm1( y.load(j ) );
1100  IntrinsicType xmm2( y.load(j+IT::size ) );
1101  IntrinsicType xmm3( y.load(j+IT::size*2UL) );
1102  IntrinsicType xmm4( y.load(j+IT::size*3UL) );
1103  for( size_t i=0UL; i<M; ++i ) {
1104  const IntrinsicType x1( set( x[i] ) );
1105  xmm1 = xmm1 + x1 * A.load(i,j );
1106  xmm2 = xmm2 + x1 * A.load(i,j+IT::size );
1107  xmm3 = xmm3 + x1 * A.load(i,j+IT::size*2UL);
1108  xmm4 = xmm4 + x1 * A.load(i,j+IT::size*3UL);
1109  }
1110  y.store( j , xmm1 );
1111  y.store( j+IT::size , xmm2 );
1112  y.store( j+IT::size*2UL, xmm3 );
1113  y.store( j+IT::size*3UL, xmm4 );
1114  }
1115  for( ; (j+IT::size*2UL) < N; j+=IT::size*3UL ) {
1116  IntrinsicType xmm1( y.load(j ) );
1117  IntrinsicType xmm2( y.load(j+IT::size ) );
1118  IntrinsicType xmm3( y.load(j+IT::size*2UL) );
1119  for( size_t i=0UL; i<M; ++i ) {
1120  const IntrinsicType x1( set( x[i] ) );
1121  xmm1 = xmm1 + x1 * A.load(i,j );
1122  xmm2 = xmm2 + x1 * A.load(i,j+IT::size );
1123  xmm3 = xmm3 + x1 * A.load(i,j+IT::size*2UL);
1124  }
1125  y.store( j , xmm1 );
1126  y.store( j+IT::size , xmm2 );
1127  y.store( j+IT::size*2UL, xmm3 );
1128  }
1129  for( ; (j+IT::size) < N; j+=IT::size*2UL ) {
1130  IntrinsicType xmm1( y.load(j ) );
1131  IntrinsicType xmm2( y.load(j+IT::size) );
1132  for( size_t i=0UL; i<M; ++i ) {
1133  const IntrinsicType x1( set( x[i] ) );
1134  xmm1 = xmm1 + x1 * A.load(i,j );
1135  xmm2 = xmm2 + x1 * A.load(i,j+IT::size);
1136  }
1137  y.store( j , xmm1 );
1138  y.store( j+IT::size, xmm2 );
1139  }
1140  if( j < N ) {
1141  IntrinsicType xmm1( y.load(j) );
1142  for( size_t i=0UL; i<M; ++i ) {
1143  xmm1 = xmm1 + set( x[i] ) * A.load(i,j);
1144  }
1145  y.store( j, xmm1 );
1146  }
1147  }
1149  //**********************************************************************************************
1150 
1151  //**BLAS-based addition assignment to dense vectors (default)***********************************
1165  template< typename VT1 // Type of the left-hand side target vector
1166  , typename VT2 // Type of the left-hand side vector operand
1167  , typename MT1 > // Type of the right-hand side matrix operand
1168  static inline typename EnableIf< UseDefaultKernel<VT1,VT2,MT1> >::Type
1169  selectBlasAddAssignKernel( VT1& y, const VT2& x, const MT1& A )
1170  {
1171  selectDefaultAddAssignKernel( y, x, A );
1172  }
1174  //**********************************************************************************************
1175 
1176  //**BLAS-based addition assignment to dense vectors (single precision)**************************
1177 #if BLAZE_BLAS_MODE
1178 
1191  template< typename VT1 // Type of the left-hand side target vector
1192  , typename VT2 // Type of the left-hand side vector operand
1193  , typename MT1 > // Type of the right-hand side matrix operand
1194  static inline typename EnableIf< UseSinglePrecisionKernel<VT1,VT2,MT1> >::Type
1195  selectBlasAddAssignKernel( VT1& y, const VT2& x, const MT1& A )
1196  {
1197  sgemv( y, x, A, 1.0F, 1.0F );
1198  }
1200 #endif
1201  //**********************************************************************************************
1202 
1203  //**BLAS-based addition assignment to dense vectors (double precision)**************************
1204 #if BLAZE_BLAS_MODE
1205 
1218  template< typename VT1 // Type of the left-hand side target vector
1219  , typename VT2 // Type of the left-hand side vector operand
1220  , typename MT1 > // Type of the right-hand side matrix operand
1221  static inline typename EnableIf< UseDoublePrecisionKernel<VT1,VT2,MT1> >::Type
1222  selectBlasAddAssignKernel( VT1& y, const VT2& x, const MT1& A )
1223  {
1224  dgemv( y, x, A, 1.0, 1.0 );
1225  }
1227 #endif
1228  //**********************************************************************************************
1229 
1230  //**BLAS-based addition assignment to dense vectors (single precision complex)******************
1231 #if BLAZE_BLAS_MODE
1232 
1245  template< typename VT1 // Type of the left-hand side target vector
1246  , typename VT2 // Type of the left-hand side vector operand
1247  , typename MT1 > // Type of the right-hand side matrix operand
1248  static inline typename EnableIf< UseSinglePrecisionComplexKernel<VT1,VT2,MT1> >::Type
1249  selectBlasAddAssignKernel( VT1& y, const VT2& x, const MT1& A )
1250  {
1251  cgemv( y, x, A, complex<float>( 1.0F, 0.0F ), complex<float>( 1.0F, 0.0F ) );
1252  }
1254 #endif
1255  //**********************************************************************************************
1256 
1257  //**BLAS-based addition assignment to dense vectors (double precision complex)******************
1258 #if BLAZE_BLAS_MODE
1259 
1272  template< typename VT1 // Type of the left-hand side target vector
1273  , typename VT2 // Type of the left-hand side vector operand
1274  , typename MT1 > // Type of the right-hand side matrix operand
1275  static inline typename EnableIf< UseDoublePrecisionComplexKernel<VT1,VT2,MT1> >::Type
1276  selectBlasAddAssignKernel( VT1& y, const VT2& x, const MT1& A )
1277  {
1278  zgemv( y, x, A, complex<double>( 1.0, 0.0 ), complex<double>( 1.0, 0.0 ) );
1279  }
1281 #endif
1282  //**********************************************************************************************
1283 
1284  //**Addition assignment to sparse vectors*******************************************************
1285  // No special implementation for the addition assignment to sparse vectors.
1286  //**********************************************************************************************
1287 
1288  //**Subtraction assignment to dense vectors*****************************************************
1301  template< typename VT1 > // Type of the target dense vector
1302  friend inline void subAssign( DenseVector<VT1,true>& lhs, const TDVecDMatMultExpr& rhs )
1303  {
1305 
1306  BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
1307 
1308  if( rhs.mat_.rows() == 0UL || rhs.mat_.columns() == 0UL ) {
1309  return;
1310  }
1311 
1312  LT x( serial( rhs.vec_ ) ); // Evaluation of the left-hand side dense vector operand
1313  RT A( serial( rhs.mat_ ) ); // Evaluation of the right-hand side dense matrix operand
1314 
1315  BLAZE_INTERNAL_ASSERT( x.size() == rhs.vec_.size() , "Invalid vector size" );
1316  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.mat_.rows() , "Invalid number of rows" );
1317  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.mat_.columns(), "Invalid number of columns" );
1318  BLAZE_INTERNAL_ASSERT( A.columns() == (~lhs).size() , "Invalid vector size" );
1319 
1320  TDVecDMatMultExpr::selectSubAssignKernel( ~lhs, x, A );
1321  }
1323  //**********************************************************************************************
1324 
1325  //**Subtraction assignment to dense vectors (kernel selection)**********************************
1336  template< typename VT1 // Type of the left-hand side target vector
1337  , typename VT2 // Type of the left-hand side vector operand
1338  , typename MT1 > // Type of the right-hand side matrix operand
1339  static inline void selectSubAssignKernel( VT1& y, const VT2& x, const MT1& A )
1340  {
1341  if( ( IsComputation<MT>::value && !evaluateMatrix ) ||
1342  ( A.rows() * A.columns() < TDVECDMATMULT_THRESHOLD ) )
1343  TDVecDMatMultExpr::selectDefaultSubAssignKernel( y, x, A );
1344  else
1345  TDVecDMatMultExpr::selectBlasSubAssignKernel( y, x, A );
1346  }
1348  //**********************************************************************************************
1349 
1350  //**Default subtraction assignment to dense vectors*********************************************
1364  template< typename VT1 // Type of the left-hand side target vector
1365  , typename VT2 // Type of the left-hand side vector operand
1366  , typename MT1 > // Type of the right-hand side matrix operand
1367  static inline typename DisableIf< UseVectorizedDefaultKernel<VT1,VT2,MT1> >::Type
1368  selectDefaultSubAssignKernel( VT1& y, const VT2& x, const MT1& A )
1369  {
1370  const size_t M( A.rows() );
1371  const size_t N( A.columns() );
1372 
1373  BLAZE_INTERNAL_ASSERT( ( N - ( N % 2UL ) ) == ( N & size_t(-2) ), "Invalid end calculation" );
1374  const size_t jend( N & size_t(-2) );
1375 
1376  for( size_t i=0UL; i<M; ++i ) {
1377  for( size_t j=0UL; j<jend; j+=2UL ) {
1378  y[j ] -= x[i] * A(i,j );
1379  y[j+1UL] -= x[i] * A(i,j+1UL);
1380  }
1381  if( jend < N ) {
1382  y[jend] -= x[i] * A(i,jend);
1383  }
1384  }
1385  }
1387  //**********************************************************************************************
1388 
1389  //**Vectorized default subtraction assignment to dense vectors**********************************
1403  template< typename VT1 // Type of the left-hand side target vector
1404  , typename VT2 // Type of the left-hand side vector operand
1405  , typename MT1 > // Type of the right-hand side matrix operand
1406  static inline typename EnableIf< UseVectorizedDefaultKernel<VT1,VT2,MT1> >::Type
1407  selectDefaultSubAssignKernel( VT1& y, const VT2& x, const MT1& A )
1408  {
1409  typedef IntrinsicTrait<ElementType> IT;
1410 
1411  const size_t M( A.rows() );
1412  const size_t N( A.columns() );
1413 
1414  size_t j( 0UL );
1415 
1416  for( ; (j+IT::size*7UL) < N; j+=IT::size*8UL ) {
1417  IntrinsicType xmm1( y.load(j ) );
1418  IntrinsicType xmm2( y.load(j+IT::size ) );
1419  IntrinsicType xmm3( y.load(j+IT::size*2UL) );
1420  IntrinsicType xmm4( y.load(j+IT::size*3UL) );
1421  IntrinsicType xmm5( y.load(j+IT::size*4UL) );
1422  IntrinsicType xmm6( y.load(j+IT::size*5UL) );
1423  IntrinsicType xmm7( y.load(j+IT::size*6UL) );
1424  IntrinsicType xmm8( y.load(j+IT::size*7UL) );
1425  for( size_t i=0UL; i<M; ++i ) {
1426  const IntrinsicType x1( set( x[i] ) );
1427  xmm1 = xmm1 - x1 * A.load(i,j );
1428  xmm2 = xmm2 - x1 * A.load(i,j+IT::size );
1429  xmm3 = xmm3 - x1 * A.load(i,j+IT::size*2UL);
1430  xmm4 = xmm4 - x1 * A.load(i,j+IT::size*3UL);
1431  xmm5 = xmm5 - x1 * A.load(i,j+IT::size*4UL);
1432  xmm6 = xmm6 - x1 * A.load(i,j+IT::size*5UL);
1433  xmm7 = xmm7 - x1 * A.load(i,j+IT::size*6UL);
1434  xmm8 = xmm8 - x1 * A.load(i,j+IT::size*7UL);
1435  }
1436  y.store( j , xmm1 );
1437  y.store( j+IT::size , xmm2 );
1438  y.store( j+IT::size*2UL, xmm3 );
1439  y.store( j+IT::size*3UL, xmm4 );
1440  y.store( j+IT::size*4UL, xmm5 );
1441  y.store( j+IT::size*5UL, xmm6 );
1442  y.store( j+IT::size*6UL, xmm7 );
1443  y.store( j+IT::size*7UL, xmm8 );
1444  }
1445  for( ; (j+IT::size*3UL) < N; j+=IT::size*4UL ) {
1446  IntrinsicType xmm1( y.load(j ) );
1447  IntrinsicType xmm2( y.load(j+IT::size ) );
1448  IntrinsicType xmm3( y.load(j+IT::size*2UL) );
1449  IntrinsicType xmm4( y.load(j+IT::size*3UL) );
1450  for( size_t i=0UL; i<M; ++i ) {
1451  const IntrinsicType x1( set( x[i] ) );
1452  xmm1 = xmm1 - x1 * A.load(i,j );
1453  xmm2 = xmm2 - x1 * A.load(i,j+IT::size );
1454  xmm3 = xmm3 - x1 * A.load(i,j+IT::size*2UL);
1455  xmm4 = xmm4 - x1 * A.load(i,j+IT::size*3UL);
1456  }
1457  y.store( j , xmm1 );
1458  y.store( j+IT::size , xmm2 );
1459  y.store( j+IT::size*2UL, xmm3 );
1460  y.store( j+IT::size*3UL, xmm4 );
1461  }
1462  for( ; (j+IT::size*2UL) < N; j+=IT::size*3UL ) {
1463  IntrinsicType xmm1( y.load(j ) );
1464  IntrinsicType xmm2( y.load(j+IT::size ) );
1465  IntrinsicType xmm3( y.load(j+IT::size*2UL) );
1466  for( size_t i=0UL; i<M; ++i ) {
1467  const IntrinsicType x1( set( x[i] ) );
1468  xmm1 = xmm1 - x1 * A.load(i,j );
1469  xmm2 = xmm2 - x1 * A.load(i,j+IT::size );
1470  xmm3 = xmm3 - x1 * A.load(i,j+IT::size*2UL);
1471  }
1472  y.store( j , xmm1 );
1473  y.store( j+IT::size , xmm2 );
1474  y.store( j+IT::size*2UL, xmm3 );
1475  }
1476  for( ; (j+IT::size) < N; j+=IT::size*2UL ) {
1477  IntrinsicType xmm1( y.load(j ) );
1478  IntrinsicType xmm2( y.load(j+IT::size) );
1479  for( size_t i=0UL; i<M; ++i ) {
1480  const IntrinsicType x1( set( x[i] ) );
1481  xmm1 = xmm1 - x1 * A.load(i,j );
1482  xmm2 = xmm2 - x1 * A.load(i,j+IT::size);
1483  }
1484  y.store( j , xmm1 );
1485  y.store( j+IT::size, xmm2 );
1486  }
1487  if( j < N ) {
1488  IntrinsicType xmm1( y.load(j) );
1489  for( size_t i=0UL; i<M; ++i ) {
1490  xmm1 = xmm1 - set( x[i] ) * A.load(i,j);
1491  }
1492  y.store( j, xmm1 );
1493  }
1494  }
1496  //**********************************************************************************************
1497 
1498  //**BLAS-based subtraction assignment to dense vectors (default)********************************
1512  template< typename VT1 // Type of the left-hand side target vector
1513  , typename VT2 // Type of the left-hand side vector operand
1514  , typename MT1 > // Type of the right-hand side matrix operand
1515  static inline typename EnableIf< UseDefaultKernel<VT1,VT2,MT1> >::Type
1516  selectBlasSubAssignKernel( VT1& y, const VT2& x, const MT1& A )
1517  {
1518  selectDefaultSubAssignKernel( y, x, A );
1519  }
1521  //**********************************************************************************************
1522 
1523  //**BLAS-based subtraction assignment to dense vectors (single precision)***********************
1524 #if BLAZE_BLAS_MODE
1525 
1538  template< typename VT1 // Type of the left-hand side target vector
1539  , typename VT2 // Type of the left-hand side vector operand
1540  , typename MT1 > // Type of the right-hand side matrix operand
1541  static inline typename EnableIf< UseSinglePrecisionKernel<VT1,VT2,MT1> >::Type
1542  selectBlasSubAssignKernel( VT1& y, const VT2& x, const MT1& A )
1543  {
1544  sgemv( y, x, A, -1.0F, 1.0F );
1545  }
1547 #endif
1548  //**********************************************************************************************
1549 
1550  //**BLAS-based subtraction assignment to dense vectors (double precision)***********************
1551 #if BLAZE_BLAS_MODE
1552 
1565  template< typename VT1 // Type of the left-hand side target vector
1566  , typename VT2 // Type of the left-hand side vector operand
1567  , typename MT1 > // Type of the right-hand side matrix operand
1568  static inline typename EnableIf< UseDoublePrecisionKernel<VT1,VT2,MT1> >::Type
1569  selectBlasSubAssignKernel( VT1& y, const VT2& x, const MT1& A )
1570  {
1571  dgemv( y, x, A, -1.0, 1.0 );
1572  }
1574 #endif
1575  //**********************************************************************************************
1576 
1577  //**BLAS-based subtraction assignment to dense vectors (single precision complex)***************
1578 #if BLAZE_BLAS_MODE
1579 
1592  template< typename VT1 // Type of the left-hand side target vector
1593  , typename VT2 // Type of the left-hand side vector operand
1594  , typename MT1 > // Type of the right-hand side matrix operand
1595  static inline typename EnableIf< UseSinglePrecisionComplexKernel<VT1,VT2,MT1> >::Type
1596  selectBlasSubAssignKernel( VT1& y, const VT2& x, const MT1& A )
1597  {
1598  cgemv( y, x, A, complex<float>( -1.0F, 0.0F ), complex<float>( 1.0F, 0.0F ) );
1599  }
1601 #endif
1602  //**********************************************************************************************
1603 
1604  //**BLAS-based subtraction assignment to dense vectors (double precision complex)***************
1605 #if BLAZE_BLAS_MODE
1606 
1619  template< typename VT1 // Type of the left-hand side target vector
1620  , typename VT2 // Type of the left-hand side vector operand
1621  , typename MT1 > // Type of the right-hand side matrix operand
1622  static inline typename EnableIf< UseDoublePrecisionComplexKernel<VT1,VT2,MT1> >::Type
1623  selectBlasSubAssignKernel( VT1& y, const VT2& x, const MT1& A )
1624  {
1625  zgemv( y, x, A, complex<double>( -1.0, 0.0 ), complex<double>( 1.0, 0.0 ) );
1626  }
1628 #endif
1629  //**********************************************************************************************
1630 
1631  //**Subtraction assignment to sparse vectors****************************************************
1632  // No special implementation for the subtraction assignment to sparse vectors.
1633  //**********************************************************************************************
1634 
1635  //**Multiplication assignment to dense vectors**************************************************
1648  template< typename VT1 > // Type of the target dense vector
1649  friend inline void multAssign( DenseVector<VT1,true>& lhs, const TDVecDMatMultExpr& rhs )
1650  {
1652 
1656 
1657  BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
1658 
1659  const ResultType tmp( serial( rhs ) );
1660  multAssign( ~lhs, tmp );
1661  }
1663  //**********************************************************************************************
1664 
1665  //**Multiplication assignment to sparse vectors*************************************************
1666  // No special implementation for the multiplication assignment to sparse vectors.
1667  //**********************************************************************************************
1668 
1669  //**SMP assignment to dense vectors*************************************************************
1684  template< typename VT1 > // Type of the target dense vector
1685  friend inline typename EnableIf< UseSMPAssign<VT1> >::Type
1686  smpAssign( DenseVector<VT1,true>& lhs, const TDVecDMatMultExpr& rhs )
1687  {
1689 
1690  BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
1691 
1692  if( rhs.mat_.rows() == 0UL ) {
1693  reset( ~lhs );
1694  return;
1695  }
1696  else if( rhs.mat_.columns() == 0UL ) {
1697  return;
1698  }
1699 
1700  LT x( rhs.vec_ ); // Evaluation of the left-hand side dense vector operand
1701  RT A( rhs.mat_ ); // Evaluation of the right-hand side dense matrix operand
1702 
1703  BLAZE_INTERNAL_ASSERT( x.size() == rhs.vec_.size() , "Invalid vector size" );
1704  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.mat_.rows() , "Invalid number of rows" );
1705  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.mat_.columns(), "Invalid number of columns" );
1706  BLAZE_INTERNAL_ASSERT( A.columns() == (~lhs).size() , "Invalid vector size" );
1707 
1708  smpAssign( ~lhs, x * A );
1709  }
1711  //**********************************************************************************************
1712 
1713  //**SMP assignment to sparse vectors************************************************************
1728  template< typename VT1 > // Type of the target sparse vector
1729  friend inline typename EnableIf< UseSMPAssign<VT1> >::Type
1730  smpAssign( SparseVector<VT1,true>& lhs, const TDVecDMatMultExpr& rhs )
1731  {
1733 
1737 
1738  BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
1739 
1740  const ResultType tmp( rhs );
1741  smpAssign( ~lhs, tmp );
1742  }
1744  //**********************************************************************************************
1745 
1746  //**SMP addition assignment to dense vectors****************************************************
1761  template< typename VT1 > // Type of the target dense vector
1762  friend inline typename EnableIf< UseSMPAssign<VT1> >::Type
1763  smpAddAssign( DenseVector<VT1,true>& lhs, const TDVecDMatMultExpr& rhs )
1764  {
1766 
1767  BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
1768 
1769  if( rhs.mat_.rows() == 0UL || rhs.mat_.columns() == 0UL ) {
1770  return;
1771  }
1772 
1773  LT x( rhs.vec_ ); // Evaluation of the left-hand side dense vector operand
1774  RT A( rhs.mat_ ); // Evaluation of the right-hand side dense matrix operand
1775 
1776  BLAZE_INTERNAL_ASSERT( x.size() == rhs.vec_.size() , "Invalid vector size" );
1777  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.mat_.rows() , "Invalid number of rows" );
1778  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.mat_.columns(), "Invalid number of columns" );
1779  BLAZE_INTERNAL_ASSERT( A.columns() == (~lhs).size() , "Invalid vector size" );
1780 
1781  smpAddAssign( ~lhs, x * A );
1782  }
1784  //**********************************************************************************************
1785 
1786  //**SMP addition assignment to sparse vectors***************************************************
1787  // No special implementation for the SMP addition assignment to sparse vectors.
1788  //**********************************************************************************************
1789 
1790  //**SMP subtraction assignment to dense vectors*************************************************
1805  template< typename VT1 > // Type of the target dense vector
1806  friend inline typename EnableIf< UseSMPAssign<VT1> >::Type
1807  smpSubAssign( DenseVector<VT1,true>& lhs, const TDVecDMatMultExpr& rhs )
1808  {
1810 
1811  BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
1812 
1813  if( rhs.mat_.rows() == 0UL || rhs.mat_.columns() == 0UL ) {
1814  return;
1815  }
1816 
1817  LT x( rhs.vec_ ); // Evaluation of the left-hand side dense vector operand
1818  RT A( rhs.mat_ ); // Evaluation of the right-hand side dense matrix operand
1819 
1820  BLAZE_INTERNAL_ASSERT( x.size() == rhs.vec_.size() , "Invalid vector size" );
1821  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.mat_.rows() , "Invalid number of rows" );
1822  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.mat_.columns(), "Invalid number of columns" );
1823  BLAZE_INTERNAL_ASSERT( A.columns() == (~lhs).size() , "Invalid vector size" );
1824 
1825  smpSubAssign( ~lhs, x * A );
1826  }
1828  //**********************************************************************************************
1829 
1830  //**SMP subtraction assignment to sparse vectors************************************************
1831  // No special implementation for the SMP subtraction assignment to sparse vectors.
1832  //**********************************************************************************************
1833 
1834  //**SMP multiplication assignment to dense vectors**********************************************
1849  template< typename VT1 > // Type of the target dense vector
1850  friend inline typename EnableIf< UseSMPAssign<VT1> >::Type
1851  smpMultAssign( DenseVector<VT1,true>& lhs, const TDVecDMatMultExpr& rhs )
1852  {
1854 
1858 
1859  BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
1860 
1861  const ResultType tmp( rhs );
1862  smpMultAssign( ~lhs, tmp );
1863  }
1865  //**********************************************************************************************
1866 
1867  //**SMP multiplication assignment to sparse vectors*********************************************
1868  // No special implementation for the SMP multiplication assignment to sparse vectors.
1869  //**********************************************************************************************
1870 
1871  //**Compile time checks*************************************************************************
1879  //**********************************************************************************************
1880 };
1881 //*************************************************************************************************
1882 
1883 
1884 
1885 
1886 //=================================================================================================
1887 //
1888 // DVECSCALARMULTEXPR SPECIALIZATION
1889 //
1890 //=================================================================================================
1891 
1892 //*************************************************************************************************
1900 template< typename VT // Type of the left-hand side dense vector
1901  , typename MT // Type of the right-hand side dense matrix
1902  , typename ST > // Type of the side scalar value
1903 class DVecScalarMultExpr< TDVecDMatMultExpr<VT,MT>, ST, true >
1904  : public DenseVector< DVecScalarMultExpr< TDVecDMatMultExpr<VT,MT>, ST, true >, true >
1905  , private VecScalarMultExpr
1906  , private Computation
1907 {
1908  private:
1909  //**Type definitions****************************************************************************
1910  typedef TDVecDMatMultExpr<VT,MT> VMM;
1911  typedef typename VMM::ResultType RES;
1912  typedef typename VT::ResultType VRT;
1913  typedef typename MT::ResultType MRT;
1914  typedef typename VRT::ElementType VET;
1915  typedef typename MRT::ElementType MET;
1916  typedef typename VT::CompositeType VCT;
1917  typedef typename MT::CompositeType MCT;
1918  //**********************************************************************************************
1919 
1920  //**********************************************************************************************
1922  enum { evaluateVector = IsComputation<VT>::value || RequiresEvaluation<VT>::value };
1923  //**********************************************************************************************
1924 
1925  //**********************************************************************************************
1927  enum { evaluateMatrix = ( IsComputation<MT>::value && IsSame<MET,VET>::value &&
1928  IsBlasCompatible<MET>::value ) || RequiresEvaluation<MT>::value };
1929  //**********************************************************************************************
1930 
1931  //**********************************************************************************************
1933 
1936  template< typename T1 >
1937  struct UseSMPAssign {
1938  enum { value = ( evaluateVector || evaluateMatrix ) };
1939  };
1940  //**********************************************************************************************
1941 
1942  //**********************************************************************************************
1944 
1947  template< typename T1, typename T2, typename T3, typename T4 >
1948  struct UseSinglePrecisionKernel {
1949  enum { value = BLAZE_BLAS_MODE &&
1950  T1::vectorizable && T2::vectorizable && T3::vectorizable &&
1951  IsFloat<typename T1::ElementType>::value &&
1952  IsFloat<typename T2::ElementType>::value &&
1953  IsFloat<typename T3::ElementType>::value &&
1954  !IsComplex<T4>::value };
1955  };
1956  //**********************************************************************************************
1957 
1958  //**********************************************************************************************
1960 
1963  template< typename T1, typename T2, typename T3, typename T4 >
1964  struct UseDoublePrecisionKernel {
1965  enum { value = BLAZE_BLAS_MODE &&
1966  T1::vectorizable && T2::vectorizable && T3::vectorizable &&
1967  IsDouble<typename T1::ElementType>::value &&
1968  IsDouble<typename T2::ElementType>::value &&
1969  IsDouble<typename T3::ElementType>::value &&
1970  !IsComplex<T4>::value };
1971  };
1972  //**********************************************************************************************
1973 
1974  //**********************************************************************************************
1976 
1979  template< typename T1, typename T2, typename T3 >
1980  struct UseSinglePrecisionComplexKernel {
1981  typedef complex<float> Type;
1982  enum { value = BLAZE_BLAS_MODE &&
1983  T1::vectorizable && T2::vectorizable && T3::vectorizable &&
1984  IsSame<typename T1::ElementType,Type>::value &&
1985  IsSame<typename T2::ElementType,Type>::value &&
1986  IsSame<typename T3::ElementType,Type>::value };
1987  };
1988  //**********************************************************************************************
1989 
1990  //**********************************************************************************************
1992 
1995  template< typename T1, typename T2, typename T3 >
1996  struct UseDoublePrecisionComplexKernel {
1997  typedef complex<double> Type;
1998  enum { value = BLAZE_BLAS_MODE &&
1999  T1::vectorizable && T2::vectorizable && T3::vectorizable &&
2000  IsSame<typename T1::ElementType,Type>::value &&
2001  IsSame<typename T2::ElementType,Type>::value &&
2002  IsSame<typename T3::ElementType,Type>::value };
2003  };
2004  //**********************************************************************************************
2005 
2006  //**********************************************************************************************
2008 
2010  template< typename T1, typename T2, typename T3, typename T4 >
2011  struct UseDefaultKernel {
2012  enum { value = !BLAZE_BLAS_MODE || ( !UseSinglePrecisionKernel<T1,T2,T3,T4>::value &&
2013  !UseDoublePrecisionKernel<T1,T2,T3,T4>::value &&
2014  !UseSinglePrecisionComplexKernel<T1,T2,T3>::value &&
2015  !UseDoublePrecisionComplexKernel<T1,T2,T3>::value ) };
2016  };
2017  //**********************************************************************************************
2018 
2019  //**********************************************************************************************
2021 
2024  template< typename T1, typename T2, typename T3, typename T4 >
2025  struct UseVectorizedDefaultKernel {
2026  enum { value = T1::vectorizable && T2::vectorizable && T3::vectorizable &&
2027  IsSame<typename T1::ElementType,typename T2::ElementType>::value &&
2028  IsSame<typename T1::ElementType,typename T3::ElementType>::value &&
2029  IsSame<typename T1::ElementType,T4>::value &&
2030  IntrinsicTrait<typename T1::ElementType>::addition &&
2031  IntrinsicTrait<typename T1::ElementType>::multiplication };
2032  };
2033  //**********************************************************************************************
2034 
2035  public:
2036  //**Type definitions****************************************************************************
2037  typedef DVecScalarMultExpr<VMM,ST,true> This;
2038  typedef typename MultTrait<RES,ST>::Type ResultType;
2039  typedef typename ResultType::TransposeType TransposeType;
2040  typedef typename ResultType::ElementType ElementType;
2041  typedef typename IntrinsicTrait<ElementType>::Type IntrinsicType;
2042  typedef const ElementType ReturnType;
2043  typedef const ResultType CompositeType;
2044 
2046  typedef const TDVecDMatMultExpr<VT,MT> LeftOperand;
2047 
2049  typedef ST RightOperand;
2050 
2052  typedef typename SelectType< evaluateVector, const VRT, VCT >::Type LT;
2053 
2055  typedef typename SelectType< evaluateMatrix, const MRT, MCT >::Type RT;
2056  //**********************************************************************************************
2057 
2058  //**Compilation flags***************************************************************************
2060  enum { vectorizable = VT::vectorizable && MT::vectorizable &&
2061  IsSame<VET,MET>::value &&
2062  IsSame<VET,ST>::value &&
2063  IntrinsicTrait<VET>::addition &&
2064  IntrinsicTrait<VET>::multiplication };
2065 
2067  enum { smpAssignable = !evaluateVector && VT::smpAssignable &&
2068  !evaluateMatrix && MT::smpAssignable };
2069  //**********************************************************************************************
2070 
2071  //**Constructor*********************************************************************************
2077  explicit inline DVecScalarMultExpr( const VMM& vector, ST scalar )
2078  : vector_( vector ) // Left-hand side dense vector of the multiplication expression
2079  , scalar_( scalar ) // Right-hand side scalar of the multiplication expression
2080  {}
2081  //**********************************************************************************************
2082 
2083  //**Subscript operator**************************************************************************
2089  inline ReturnType operator[]( size_t index ) const {
2090  BLAZE_INTERNAL_ASSERT( index < vector_.size(), "Invalid vector access index" );
2091  return vector_[index] * scalar_;
2092  }
2093  //**********************************************************************************************
2094 
2095  //**Size function*******************************************************************************
2100  inline size_t size() const {
2101  return vector_.size();
2102  }
2103  //**********************************************************************************************
2104 
2105  //**Left operand access*************************************************************************
2110  inline LeftOperand leftOperand() const {
2111  return vector_;
2112  }
2113  //**********************************************************************************************
2114 
2115  //**Right operand access************************************************************************
2120  inline RightOperand rightOperand() const {
2121  return scalar_;
2122  }
2123  //**********************************************************************************************
2124 
2125  //**********************************************************************************************
2131  template< typename T >
2132  inline bool canAlias( const T* alias ) const {
2133  return vector_.canAlias( alias );
2134  }
2135  //**********************************************************************************************
2136 
2137  //**********************************************************************************************
2143  template< typename T >
2144  inline bool isAliased( const T* alias ) const {
2145  return vector_.isAliased( alias );
2146  }
2147  //**********************************************************************************************
2148 
2149  //**********************************************************************************************
2154  inline bool isAligned() const {
2155  return vector_.isAligned();
2156  }
2157  //**********************************************************************************************
2158 
2159  //**********************************************************************************************
2164  inline bool canSMPAssign() const {
2165  typename VMM::RightOperand A( vector_.rightOperand() );
2166  return ( !BLAZE_BLAS_IS_PARALLEL ||
2167  ( IsComputation<MT>::value && !evaluateMatrix ) ||
2168  ( A.rows() * A.columns() < TDVECDMATMULT_THRESHOLD ) ) &&
2170  }
2171  //**********************************************************************************************
2172 
2173  private:
2174  //**Member variables****************************************************************************
2175  LeftOperand vector_;
2176  RightOperand scalar_;
2177  //**********************************************************************************************
2178 
2179  //**BLAS kernel (single precision)**************************************************************
2180 #if BLAZE_BLAS_MODE
2181 
2195  template< typename VT1 // Type of the left-hand side target vector
2196  , typename VT2 // Type of the left-hand side vector operand
2197  , typename MT1 > // Type of the right-hand side matrix operand
2198  static inline void sgemv( VT1& y, const VT2& x, const MT1& A, float alpha, float beta )
2199  {
2200  using boost::numeric_cast;
2201 
2205 
2206  const int M ( numeric_cast<int>( A.rows() ) );
2207  const int N ( numeric_cast<int>( A.columns() ) );
2208  const int lda( numeric_cast<int>( A.spacing() ) );
2209 
2210  cblas_sgemv( CblasRowMajor, CblasTrans, M, N, alpha,
2211  A.data(), lda, x.data(), 1, beta, y.data(), 1 );
2212  }
2213 #endif
2214  //**********************************************************************************************
2215 
2216  //**BLAS kernel (double precision)**************************************************************
2217 #if BLAZE_BLAS_MODE
2218 
2232  template< typename VT1 // Type of the left-hand side target vector
2233  , typename VT2 // Type of the left-hand side vector operand
2234  , typename MT1 > // Type of the right-hand side matrix operand
2235  static inline void dgemv( VT1& y, const VT2& x, const MT1& A, double alpha, double beta )
2236  {
2237  using boost::numeric_cast;
2238 
2242 
2243  const int M ( numeric_cast<int>( A.rows() ) );
2244  const int N ( numeric_cast<int>( A.columns() ) );
2245  const int lda( numeric_cast<int>( A.spacing() ) );
2246 
2247  cblas_dgemv( CblasRowMajor, CblasTrans, M, N, alpha,
2248  A.data(), lda, x.data(), 1, beta, y.data(), 1 );
2249  }
2250 #endif
2251  //**********************************************************************************************
2252 
2253  //**BLAS kernel (single precision complex)******************************************************
2254 #if BLAZE_BLAS_MODE
2255 
2269  template< typename VT1 // Type of the left-hand side target vector
2270  , typename VT2 // Type of the left-hand side vector operand
2271  , typename MT1 > // Type of the right-hand side matrix operand
2272  static inline void cgemv( VT1& y, const VT2& x, const MT1& A,
2273  complex<float> alpha, complex<float> beta )
2274  {
2275  using boost::numeric_cast;
2276 
2280  BLAZE_CONSTRAINT_MUST_BE_FLOAT_TYPE ( typename VT1::ElementType::value_type );
2281  BLAZE_CONSTRAINT_MUST_BE_FLOAT_TYPE ( typename VT2::ElementType::value_type );
2282  BLAZE_CONSTRAINT_MUST_BE_FLOAT_TYPE ( typename MT1::ElementType::value_type );
2283 
2284  const int M ( numeric_cast<int>( A.rows() ) );
2285  const int N ( numeric_cast<int>( A.columns() ) );
2286  const int lda( numeric_cast<int>( A.spacing() ) );
2287 
2288  cblas_cgemv( CblasRowMajor, CblasTrans, M, N, &alpha,
2289  A.data(), lda, x.data(), 1, &beta, y.data(), 1 );
2290  }
2291 #endif
2292  //**********************************************************************************************
2293 
2294  //**BLAS kernel (double precision complex)******************************************************
2295 #if BLAZE_BLAS_MODE
2296 
2310  template< typename VT1 // Type of the left-hand side target vector
2311  , typename VT2 // Type of the left-hand side vector operand
2312  , typename MT1 > // Type of the right-hand side matrix operand
2313  static inline void zgemv( VT1& y, const VT2& x, const MT1& A,
2314  complex<double> alpha, complex<float> beta )
2315  {
2316  using boost::numeric_cast;
2317 
2321  BLAZE_CONSTRAINT_MUST_BE_DOUBLE_TYPE ( typename VT1::ElementType::value_type );
2322  BLAZE_CONSTRAINT_MUST_BE_DOUBLE_TYPE ( typename VT2::ElementType::value_type );
2323  BLAZE_CONSTRAINT_MUST_BE_DOUBLE_TYPE ( typename MT1::ElementType::value_type );
2324 
2325  const int M ( numeric_cast<int>( A.rows() ) );
2326  const int N ( numeric_cast<int>( A.columns() ) );
2327  const int lda( numeric_cast<int>( A.spacing() ) );
2328 
2329  cblas_zgemv( CblasRowMajor, CblasTrans, M, N, &alpha,
2330  A.data(), lda, x.data(), 1, &beta, y.data(), 1 );
2331  }
2332 #endif
2333  //**********************************************************************************************
2334 
2335  //**Assignment to dense vectors*****************************************************************
2347  template< typename VT1 > // Type of the target dense vector
2348  friend inline void assign( DenseVector<VT1,true>& lhs, const DVecScalarMultExpr& rhs )
2349  {
2351 
2352  BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
2353 
2354  typename VMM::LeftOperand left ( rhs.vector_.leftOperand() );
2355  typename VMM::RightOperand right( rhs.vector_.rightOperand() );
2356 
2357  if( right.rows() == 0UL ) {
2358  reset( ~lhs );
2359  return;
2360  }
2361  else if( right.columns() == 0UL ) {
2362  return;
2363  }
2364 
2365  LT x( serial( left ) ); // Evaluation of the left-hand side dense vector operand
2366  RT A( serial( right ) ); // Evaluation of the right-hand side dense matrix operand
2367 
2368  BLAZE_INTERNAL_ASSERT( x.size() == left.size() , "Invalid vector size" );
2369  BLAZE_INTERNAL_ASSERT( A.rows() == right.rows() , "Invalid number of rows" );
2370  BLAZE_INTERNAL_ASSERT( A.columns() == right.columns(), "Invalid number of columns" );
2371  BLAZE_INTERNAL_ASSERT( A.columns() == (~lhs).size() , "Invalid vector size" );
2372 
2373  DVecScalarMultExpr::selectAssignKernel( ~lhs, x, A, rhs.scalar_ );
2374  }
2375  //**********************************************************************************************
2376 
2377  //**Assignment to dense vectors (kernel selection)**********************************************
2388  template< typename VT1 // Type of the left-hand side target vector
2389  , typename VT2 // Type of the left-hand side vector operand
2390  , typename MT1 // Type of the right-hand side matrix operand
2391  , typename ST2 > // Type of the scalar value
2392  static inline void selectAssignKernel( VT1& y, const VT2& x, const MT1& A, ST2 scalar )
2393  {
2394  if( ( IsComputation<MT>::value && !evaluateMatrix ) ||
2395  ( A.rows() * A.columns() < TDVECDMATMULT_THRESHOLD ) )
2396  DVecScalarMultExpr::selectDefaultAssignKernel( y, x, A, scalar );
2397  else
2398  DVecScalarMultExpr::selectBlasAssignKernel( y, x, A, scalar );
2399  }
2400  //**********************************************************************************************
2401 
2402  //**Default assignment to dense vectors*********************************************************
2416  template< typename VT1 // Type of the left-hand side target vector
2417  , typename VT2 // Type of the left-hand side vector operand
2418  , typename MT1 // Type of the right-hand side matrix operand
2419  , typename ST2 > // Type of the scalar value
2420  static inline typename DisableIf< UseVectorizedDefaultKernel<VT1,VT2,MT1,ST2> >::Type
2421  selectDefaultAssignKernel( VT1& y, const VT2& x, const MT1& A, ST2 scalar )
2422  {
2423  const size_t M( A.rows() );
2424  const size_t N( A.columns() );
2425 
2426  BLAZE_INTERNAL_ASSERT( ( N - ( N % 2UL ) ) == ( N & size_t(-2) ), "Invalid end calculation" );
2427  const size_t jend( N & size_t(-2) );
2428 
2429  for( size_t j=0UL; j<N; ++j ) {
2430  y[j] = x[0UL] * A(0UL,j);
2431  }
2432  for( size_t i=1UL; i<M; ++i ) {
2433  for( size_t j=0UL; j<jend; j+=2UL ) {
2434  y[j ] += x[i] * A(i,j );
2435  y[j+1UL] += x[i] * A(i,j+1UL);
2436  }
2437  if( jend < N ) {
2438  y[jend] += x[i] * A(i,jend);
2439  }
2440  }
2441  for( size_t j=0UL; j<N; ++j ) {
2442  y[j] *= scalar;
2443  }
2444  }
2445  //**********************************************************************************************
2446 
2447  //**Default assignment to dense vectors*********************************************************
2461  template< typename VT1 // Type of the left-hand side target vector
2462  , typename VT2 // Type of the left-hand side vector operand
2463  , typename MT1 // Type of the right-hand side matrix operand
2464  , typename ST2 > // Type of the scalar value
2465  static inline typename EnableIf< UseVectorizedDefaultKernel<VT1,VT2,MT1,ST2> >::Type
2466  selectDefaultAssignKernel( VT1& y, const VT2& x, const MT1& A, ST2 scalar )
2467  {
2468  typedef IntrinsicTrait<ElementType> IT;
2469 
2470  const size_t M( A.rows() );
2471  const size_t N( A.columns() );
2472 
2473  const IntrinsicType factor( set( scalar ) );
2474 
2475  size_t j( 0UL );
2476 
2477  for( ; (j+IT::size*7UL) < N; j+=IT::size*8UL ) {
2478  IntrinsicType xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7, xmm8;
2479  for( size_t i=0UL; i<M; ++i ) {
2480  const IntrinsicType x1( set( x[i] ) );
2481  xmm1 = xmm1 + x1 * A.load(i,j );
2482  xmm2 = xmm2 + x1 * A.load(i,j+IT::size );
2483  xmm3 = xmm3 + x1 * A.load(i,j+IT::size*2UL);
2484  xmm4 = xmm4 + x1 * A.load(i,j+IT::size*3UL);
2485  xmm5 = xmm5 + x1 * A.load(i,j+IT::size*4UL);
2486  xmm6 = xmm6 + x1 * A.load(i,j+IT::size*5UL);
2487  xmm7 = xmm7 + x1 * A.load(i,j+IT::size*6UL);
2488  xmm8 = xmm8 + x1 * A.load(i,j+IT::size*7UL);
2489  }
2490  y.store( j , xmm1*factor );
2491  y.store( j+IT::size , xmm2*factor );
2492  y.store( j+IT::size*2UL, xmm3*factor );
2493  y.store( j+IT::size*3UL, xmm4*factor );
2494  y.store( j+IT::size*4UL, xmm5*factor );
2495  y.store( j+IT::size*5UL, xmm6*factor );
2496  y.store( j+IT::size*6UL, xmm7*factor );
2497  y.store( j+IT::size*7UL, xmm8*factor );
2498  }
2499  for( ; (j+IT::size*3UL) < N; j+=IT::size*4UL ) {
2500  IntrinsicType xmm1, xmm2, xmm3, xmm4;
2501  for( size_t i=0UL; i<M; ++i ) {
2502  const IntrinsicType x1( set( x[i] ) );
2503  xmm1 = xmm1 + x1 * A.load(i,j );
2504  xmm2 = xmm2 + x1 * A.load(i,j+IT::size );
2505  xmm3 = xmm3 + x1 * A.load(i,j+IT::size*2UL);
2506  xmm4 = xmm4 + x1 * A.load(i,j+IT::size*3UL);
2507  }
2508  y.store( j , xmm1*factor );
2509  y.store( j+IT::size , xmm2*factor );
2510  y.store( j+IT::size*2UL, xmm3*factor );
2511  y.store( j+IT::size*3UL, xmm4*factor );
2512  }
2513  for( ; (j+IT::size*2UL) < N; j+=IT::size*3UL ) {
2514  IntrinsicType xmm1, xmm2, xmm3;
2515  for( size_t i=0UL; i<M; ++i ) {
2516  const IntrinsicType x1( set( x[i] ) );
2517  xmm1 = xmm1 + x1 * A.load(i,j );
2518  xmm2 = xmm2 + x1 * A.load(i,j+IT::size );
2519  xmm3 = xmm3 + x1 * A.load(i,j+IT::size*2UL);
2520  }
2521  y.store( j , xmm1*factor );
2522  y.store( j+IT::size , xmm2*factor );
2523  y.store( j+IT::size*2UL, xmm3*factor );
2524  }
2525  for( ; (j+IT::size) < N; j+=IT::size*2UL ) {
2526  IntrinsicType xmm1, xmm2;
2527  for( size_t i=0UL; i<M; ++i ) {
2528  const IntrinsicType x1( set( x[i] ) );
2529  xmm1 = xmm1 + x1 * A.load(i,j );
2530  xmm2 = xmm2 + x1 * A.load(i,j+IT::size);
2531  }
2532  y.store( j , xmm1*factor );
2533  y.store( j+IT::size, xmm2*factor );
2534  }
2535  if( j < N ) {
2536  IntrinsicType xmm1;
2537  for( size_t i=0UL; i<M; ++i ) {
2538  xmm1 = xmm1 + set( x[i] ) * A.load(i,j);
2539  }
2540  y.store( j, xmm1*factor );
2541  }
2542  }
2543  //**********************************************************************************************
2544 
2545  //**BLAS-based assignment to dense vectors (default)********************************************
2558  template< typename VT1 // Type of the left-hand side target vector
2559  , typename VT2 // Type of the left-hand side vector operand
2560  , typename MT1 // Type of the right-hand side matrix operand
2561  , typename ST2 > // Type of the scalar value
2562  static inline typename EnableIf< UseDefaultKernel<VT1,VT2,MT1,ST2> >::Type
2563  selectBlasAssignKernel( VT1& y, const VT2& x, const MT1& A, ST2 scalar )
2564  {
2565  selectDefaultAssignKernel( y, x, A, scalar );
2566  }
2567  //**********************************************************************************************
2568 
2569  //**BLAS-based assignment to dense vectors (single precision)***********************************
2570 #if BLAZE_BLAS_MODE
2571 
2584  template< typename VT1 // Type of the left-hand side target vector
2585  , typename VT2 // Type of the left-hand side vector operand
2586  , typename MT1 // Type of the right-hand side matrix operand
2587  , typename ST2 > // Type of the scalar value
2588  static inline typename EnableIf< UseSinglePrecisionKernel<VT1,VT2,MT1,ST2> >::Type
2589  selectBlasAssignKernel( VT1& y, const VT2& x, const MT1& A, ST2 scalar )
2590  {
2591  sgemv( y, x, A, scalar, 0.0F );
2592  }
2593 #endif
2594  //**********************************************************************************************
2595 
2596  //**BLAS-based assignment to dense vectors (double precision)***********************************
2597 #if BLAZE_BLAS_MODE
2598 
2611  template< typename VT1 // Type of the left-hand side target vector
2612  , typename VT2 // Type of the left-hand side vector operand
2613  , typename MT1 // Type of the right-hand side matrix operand
2614  , typename ST2 > // Type of the scalar value
2615  static inline typename EnableIf< UseDoublePrecisionKernel<VT1,VT2,MT1,ST2> >::Type
2616  selectBlasAssignKernel( VT1& y, const VT2& x, const MT1& A, ST2 scalar )
2617  {
2618  dgemv( y, x, A, scalar, 0.0 );
2619  }
2620 #endif
2621  //**********************************************************************************************
2622 
2623  //**BLAS-based assignment to dense vectors (single precision complex)***************************
2624 #if BLAZE_BLAS_MODE
2625 
2638  template< typename VT1 // Type of the left-hand side target vector
2639  , typename VT2 // Type of the left-hand side vector operand
2640  , typename MT1 // Type of the right-hand side matrix operand
2641  , typename ST2 > // Type of the scalar value
2642  static inline typename EnableIf< UseSinglePrecisionComplexKernel<VT1,VT2,MT1> >::Type
2643  selectBlasAssignKernel( VT1& y, const VT2& x, const MT1& A, ST2 scalar )
2644  {
2645  cgemv( y, x, A, complex<float>( scalar, 0.0F ), complex<float>( 0.0F, 0.0F ) );
2646  }
2647 #endif
2648  //**********************************************************************************************
2649 
2650  //**BLAS-based assignment to dense vectors (double precision complex)***************************
2651 #if BLAZE_BLAS_MODE
2652 
2665  template< typename VT1 // Type of the left-hand side target vector
2666  , typename VT2 // Type of the left-hand side vector operand
2667  , typename MT1 // Type of the right-hand side matrix operand
2668  , typename ST2 > // Type of the scalar value
2669  static inline typename EnableIf< UseDoublePrecisionComplexKernel<VT1,VT2,MT1> >::Type
2670  selectBlasAssignKernel( VT1& y, const VT2& x, const MT1& A, ST2 scalar )
2671  {
2672  zgemv( y, x, A, complex<double>( scalar, 0.0 ), complex<double>( 0.0, 0.0 ) );
2673  }
2674 #endif
2675  //**********************************************************************************************
2676 
2677  //**Assignment to sparse vectors****************************************************************
2689  template< typename VT1 > // Type of the target sparse vector
2690  friend inline void assign( SparseVector<VT1,true>& lhs, const DVecScalarMultExpr& rhs )
2691  {
2693 
2697 
2698  BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
2699 
2700  const ResultType tmp( serial( rhs ) );
2701  assign( ~lhs, tmp );
2702  }
2703  //**********************************************************************************************
2704 
2705  //**Addition assignment to dense vectors********************************************************
2717  template< typename VT1 > // Type of the target dense vector
2718  friend inline void addAssign( DenseVector<VT1,true>& lhs, const DVecScalarMultExpr& rhs )
2719  {
2721 
2722  BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
2723 
2724  typename VMM::LeftOperand left ( rhs.vector_.leftOperand() );
2725  typename VMM::RightOperand right( rhs.vector_.rightOperand() );
2726 
2727  if( right.rows() == 0UL || right.columns() == 0UL ) {
2728  return;
2729  }
2730 
2731  LT x( serial( left ) ); // Evaluation of the left-hand side dense vector operand
2732  RT A( serial( right ) ); // Evaluation of the right-hand side dense matrix operand
2733 
2734  BLAZE_INTERNAL_ASSERT( x.size() == left.size() , "Invalid vector size" );
2735  BLAZE_INTERNAL_ASSERT( A.rows() == right.rows() , "Invalid number of rows" );
2736  BLAZE_INTERNAL_ASSERT( A.columns() == right.columns(), "Invalid number of columns" );
2737  BLAZE_INTERNAL_ASSERT( A.columns() == (~lhs).size() , "Invalid vector size" );
2738 
2739  DVecScalarMultExpr::selectAddAssignKernel( ~lhs, x, A, rhs.scalar_ );
2740  }
2741  //**********************************************************************************************
2742 
2743  //**Addition assignment to dense vectors (kernel selection)*************************************
2754  template< typename VT1 // Type of the left-hand side target vector
2755  , typename VT2 // Type of the left-hand side vector operand
2756  , typename MT1 // Type of the right-hand side matrix operand
2757  , typename ST2 > // Type of the scalar value
2758  static inline void selectAddAssignKernel( VT1& y, const VT2& x, const MT1& A, ST2 scalar )
2759  {
2760  if( ( IsComputation<MT>::value && !evaluateMatrix ) ||
2761  ( A.rows() * A.columns() < TDVECDMATMULT_THRESHOLD ) )
2762  DVecScalarMultExpr::selectDefaultAddAssignKernel( y, x, A, scalar );
2763  else
2764  DVecScalarMultExpr::selectBlasAddAssignKernel( y, x, A, scalar );
2765  }
2766  //**********************************************************************************************
2767 
2768  //**Default addition assignment to dense vectors************************************************
2782  template< typename VT1 // Type of the left-hand side target vector
2783  , typename VT2 // Type of the left-hand side vector operand
2784  , typename MT1 // Type of the right-hand side matrix operand
2785  , typename ST2 > // Type of the scalar value
2786  static inline typename DisableIf< UseVectorizedDefaultKernel<VT1,VT2,MT1,ST2> >::Type
2787  selectDefaultAddAssignKernel( VT1& y, const VT2& x, const MT1& A, ST2 scalar )
2788  {
2789  y.addAssign( x * A * scalar );
2790  }
2791  //**********************************************************************************************
2792 
2793  //**Vectorized default addition assignment to dense vectors*************************************
2807  template< typename VT1 // Type of the left-hand side target vector
2808  , typename VT2 // Type of the left-hand side vector operand
2809  , typename MT1 // Type of the right-hand side matrix operand
2810  , typename ST2 > // Type of the scalar value
2811  static inline typename EnableIf< UseVectorizedDefaultKernel<VT1,VT2,MT1,ST2> >::Type
2812  selectDefaultAddAssignKernel( VT1& y, const VT2& x, const MT1& A, ST2 scalar )
2813  {
2814  typedef IntrinsicTrait<ElementType> IT;
2815 
2816  const size_t M( A.rows() );
2817  const size_t N( A.columns() );
2818 
2819  const IntrinsicType factor( set( scalar ) );
2820 
2821  size_t j( 0UL );
2822 
2823  for( ; (j+IT::size*7UL) < N; j+=IT::size*8UL ) {
2824  IntrinsicType xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7, xmm8;
2825  for( size_t i=0UL; i<M; ++i ) {
2826  const IntrinsicType x1( set( x[i] ) );
2827  xmm1 = xmm1 + x1 * A.load(i,j );
2828  xmm2 = xmm2 + x1 * A.load(i,j+IT::size );
2829  xmm3 = xmm3 + x1 * A.load(i,j+IT::size*2UL);
2830  xmm4 = xmm4 + x1 * A.load(i,j+IT::size*3UL);
2831  xmm5 = xmm5 + x1 * A.load(i,j+IT::size*4UL);
2832  xmm6 = xmm6 + x1 * A.load(i,j+IT::size*5UL);
2833  xmm7 = xmm7 + x1 * A.load(i,j+IT::size*6UL);
2834  xmm8 = xmm8 + x1 * A.load(i,j+IT::size*7UL);
2835  }
2836  y.store( j , y.load(j ) + xmm1*factor );
2837  y.store( j+IT::size , y.load(j+IT::size ) + xmm2*factor );
2838  y.store( j+IT::size*2UL, y.load(j+IT::size*2UL) + xmm3*factor );
2839  y.store( j+IT::size*3UL, y.load(j+IT::size*3UL) + xmm4*factor );
2840  y.store( j+IT::size*4UL, y.load(j+IT::size*4UL) + xmm5*factor );
2841  y.store( j+IT::size*5UL, y.load(j+IT::size*5UL) + xmm6*factor );
2842  y.store( j+IT::size*6UL, y.load(j+IT::size*6UL) + xmm7*factor );
2843  y.store( j+IT::size*7UL, y.load(j+IT::size*7UL) + xmm8*factor );
2844  }
2845  for( ; (j+IT::size*3UL) < N; j+=IT::size*4UL ) {
2846  IntrinsicType xmm1, xmm2, xmm3, xmm4;
2847  for( size_t i=0UL; i<M; ++i ) {
2848  const IntrinsicType x1( set( x[i] ) );
2849  xmm1 = xmm1 + x1 * A.load(i,j );
2850  xmm2 = xmm2 + x1 * A.load(i,j+IT::size );
2851  xmm3 = xmm3 + x1 * A.load(i,j+IT::size*2UL);
2852  xmm4 = xmm4 + x1 * A.load(i,j+IT::size*3UL);
2853  }
2854  y.store( j , y.load(j ) + xmm1*factor );
2855  y.store( j+IT::size , y.load(j+IT::size ) + xmm2*factor );
2856  y.store( j+IT::size*2UL, y.load(j+IT::size*2UL) + xmm3*factor );
2857  y.store( j+IT::size*3UL, y.load(j+IT::size*3UL) + xmm4*factor );
2858  }
2859  for( ; (j+IT::size*2UL) < N; j+=IT::size*3UL ) {
2860  IntrinsicType xmm1, xmm2, xmm3;
2861  for( size_t i=0UL; i<M; ++i ) {
2862  const IntrinsicType x1( set( x[i] ) );
2863  xmm1 = xmm1 + x1 * A.load(i,j );
2864  xmm2 = xmm2 + x1 * A.load(i,j+IT::size );
2865  xmm3 = xmm3 + x1 * A.load(i,j+IT::size*2UL);
2866  }
2867  y.store( j , y.load(j ) + xmm1*factor );
2868  y.store( j+IT::size , y.load(j+IT::size ) + xmm2*factor );
2869  y.store( j+IT::size*2UL, y.load(j+IT::size*2UL) + xmm3*factor );
2870  }
2871  for( ; (j+IT::size) < N; j+=IT::size*2UL ) {
2872  IntrinsicType xmm1, xmm2;
2873  for( size_t i=0UL; i<M; ++i ) {
2874  const IntrinsicType x1( set( x[i] ) );
2875  xmm1 = xmm1 + x1 * A.load(i,j );
2876  xmm2 = xmm2 + x1 * A.load(i,j+IT::size);
2877  }
2878  y.store( j , y.load(j ) + xmm1*factor );
2879  y.store( j+IT::size, y.load(j+IT::size) + xmm2*factor );
2880  }
2881  if( j < N ) {
2882  IntrinsicType xmm1;
2883  for( size_t i=0UL; i<M; ++i ) {
2884  xmm1 = xmm1 + set( x[i] ) * A.load(i,j);
2885  }
2886  y.store( j, y.load(j) + xmm1*factor );
2887  }
2888  }
2889  //**********************************************************************************************
2890 
2891  //**BLAS-based addition assignment to dense vectors (default)***********************************
2905  template< typename VT1 // Type of the left-hand side target vector
2906  , typename VT2 // Type of the left-hand side vector operand
2907  , typename MT1 // Type of the right-hand side matrix operand
2908  , typename ST2 > // Type of the scalar value
2909  static inline typename EnableIf< UseDefaultKernel<VT1,VT2,MT1,ST2> >::Type
2910  selectBlasAddAssignKernel( VT1& y, const VT2& x, const MT1& A, ST2 scalar )
2911  {
2912  selectDefaultAddAssignKernel( y, x, A, scalar );
2913  }
2914  //**********************************************************************************************
2915 
2916  //**BLAS-based addition assignment to dense vectors (single precision)**************************
2917 #if BLAZE_BLAS_MODE
2918 
2931  template< typename VT1 // Type of the left-hand side target vector
2932  , typename VT2 // Type of the left-hand side vector operand
2933  , typename MT1 // Type of the right-hand side matrix operand
2934  , typename ST2 > // Type of the scalar value
2935  static inline typename EnableIf< UseSinglePrecisionKernel<VT1,VT2,MT1,ST2> >::Type
2936  selectBlasAddAssignKernel( VT1& y, const VT2& x, const MT1& A, ST2 scalar )
2937  {
2938  sgemv( y, x, A, scalar, 1.0F );
2939  }
2940 #endif
2941  //**********************************************************************************************
2942 
2943  //**BLAS-based addition assignment to dense vectors (double precision)**************************
2944 #if BLAZE_BLAS_MODE
2945 
2958  template< typename VT1 // Type of the left-hand side target vector
2959  , typename VT2 // Type of the left-hand side vector operand
2960  , typename MT1 // Type of the right-hand side matrix operand
2961  , typename ST2 > // Type of the scalar value
2962  static inline typename EnableIf< UseDoublePrecisionKernel<VT1,VT2,MT1,ST2> >::Type
2963  selectBlasAddAssignKernel( VT1& y, const VT2& x, const MT1& A, ST2 scalar )
2964  {
2965  dgemv( y, x, A, scalar, 1.0 );
2966  }
2967 #endif
2968  //**********************************************************************************************
2969 
2970  //**BLAS-based addition assignment to dense vectors (single precision complex)******************
2971 #if BLAZE_BLAS_MODE
2972 
2985  template< typename VT1 // Type of the left-hand side target vector
2986  , typename VT2 // Type of the left-hand side vector operand
2987  , typename MT1 // Type of the right-hand side matrix operand
2988  , typename ST2 > // Type of the scalar value
2989  static inline typename EnableIf< UseSinglePrecisionComplexKernel<VT1,VT2,MT1> >::Type
2990  selectBlasAddAssignKernel( VT1& y, const VT2& x, const MT1& A, ST2 scalar )
2991  {
2992  cgemv( y, x, A, complex<float>( scalar, 0.0F ), complex<float>( 1.0F, 0.0F ) );
2993  }
2994 #endif
2995  //**********************************************************************************************
2996 
2997  //**BLAS-based addition assignment to dense vectors (double precision complex)******************
2998 #if BLAZE_BLAS_MODE
2999 
3012  template< typename VT1 // Type of the left-hand side target vector
3013  , typename VT2 // Type of the left-hand side vector operand
3014  , typename MT1 // Type of the right-hand side matrix operand
3015  , typename ST2 > // Type of the scalar value
3016  static inline typename EnableIf< UseDoublePrecisionComplexKernel<VT1,VT2,MT1> >::Type
3017  selectBlasAddAssignKernel( VT1& y, const VT2& x, const MT1& A, ST2 scalar )
3018  {
3019  zgemv( y, x, A, complex<double>( scalar, 0.0 ), complex<double>( 1.0, 0.0 ) );
3020  }
3021 #endif
3022  //**********************************************************************************************
3023 
3024  //**Addition assignment to sparse vectors*******************************************************
3025  // No special implementation for the addition assignment to sparse vectors.
3026  //**********************************************************************************************
3027 
3028  //**Subtraction assignment to dense vectors*****************************************************
3040  template< typename VT1 > // Type of the target dense vector
3041  friend inline void subAssign( DenseVector<VT1,true>& lhs, const DVecScalarMultExpr& rhs )
3042  {
3044 
3045  BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
3046 
3047  typename VMM::LeftOperand left ( rhs.vector_.leftOperand() );
3048  typename VMM::RightOperand right( rhs.vector_.rightOperand() );
3049 
3050  if( right.rows() == 0UL || right.columns() == 0UL ) {
3051  return;
3052  }
3053 
3054  LT x( serial( left ) ); // Evaluation of the left-hand side dense vector operand
3055  RT A( serial( right ) ); // Evaluation of the right-hand side dense matrix operand
3056 
3057  BLAZE_INTERNAL_ASSERT( x.size() == left.size() , "Invalid vector size" );
3058  BLAZE_INTERNAL_ASSERT( A.rows() == right.rows() , "Invalid number of rows" );
3059  BLAZE_INTERNAL_ASSERT( A.columns() == right.columns(), "Invalid number of columns" );
3060  BLAZE_INTERNAL_ASSERT( A.columns() == (~lhs).size() , "Invalid vector size" );
3061 
3062  DVecScalarMultExpr::selectSubAssignKernel( ~lhs, x, A, rhs.scalar_ );
3063  }
3064  //**********************************************************************************************
3065 
3066  //**Subtraction assignment to dense vectors (kernel selection)**********************************
3077  template< typename VT1 // Type of the left-hand side target vector
3078  , typename VT2 // Type of the left-hand side vector operand
3079  , typename MT1 // Type of the right-hand side matrix operand
3080  , typename ST2 > // Type of the scalar value
3081  static inline void selectSubAssignKernel( VT1& y, const VT2& x, const MT1& A, ST2 scalar )
3082  {
3083  if( ( IsComputation<MT>::value && !evaluateMatrix ) ||
3084  ( A.rows() * A.columns() < TDVECDMATMULT_THRESHOLD ) )
3085  DVecScalarMultExpr::selectDefaultSubAssignKernel( y, x, A, scalar );
3086  else
3087  DVecScalarMultExpr::selectBlasSubAssignKernel( y, x, A, scalar );
3088  }
3089  //**********************************************************************************************
3090 
3091  //**Default subtraction assignment to dense vectors*********************************************
3105  template< typename VT1 // Type of the left-hand side target vector
3106  , typename VT2 // Type of the left-hand side vector operand
3107  , typename MT1 // Type of the right-hand side matrix operand
3108  , typename ST2 > // Type of the scalar value
3109  static inline typename DisableIf< UseVectorizedDefaultKernel<VT1,VT2,MT1,ST2> >::Type
3110  selectDefaultSubAssignKernel( VT1& y, const VT2& x, const MT1& A, ST2 scalar )
3111  {
3112  y.subAssign( x * A * scalar );
3113  }
3114  //**********************************************************************************************
3115 
3116  //**Vectorized default subtraction assignment to dense vectors**********************************
3130  template< typename VT1 // Type of the left-hand side target vector
3131  , typename VT2 // Type of the left-hand side vector operand
3132  , typename MT1 // Type of the right-hand side matrix operand
3133  , typename ST2 > // Type of the scalar value
3134  static inline typename EnableIf< UseVectorizedDefaultKernel<VT1,VT2,MT1,ST2> >::Type
3135  selectDefaultSubAssignKernel( VT1& y, const VT2& x, const MT1& A, ST2 scalar )
3136  {
3137  typedef IntrinsicTrait<ElementType> IT;
3138 
3139  const size_t M( A.rows() );
3140  const size_t N( A.columns() );
3141 
3142  const IntrinsicType factor( set( scalar ) );
3143 
3144  size_t j( 0UL );
3145 
3146  for( ; (j+IT::size*7UL) < N; j+=IT::size*8UL ) {
3147  IntrinsicType xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7, xmm8;
3148  for( size_t i=0UL; i<M; ++i ) {
3149  const IntrinsicType x1( set( x[i] ) );
3150  xmm1 = xmm1 + x1 * A.load(i,j );
3151  xmm2 = xmm2 + x1 * A.load(i,j+IT::size );
3152  xmm3 = xmm3 + x1 * A.load(i,j+IT::size*2UL);
3153  xmm4 = xmm4 + x1 * A.load(i,j+IT::size*3UL);
3154  xmm5 = xmm5 + x1 * A.load(i,j+IT::size*4UL);
3155  xmm6 = xmm6 + x1 * A.load(i,j+IT::size*5UL);
3156  xmm7 = xmm7 + x1 * A.load(i,j+IT::size*6UL);
3157  xmm8 = xmm8 + x1 * A.load(i,j+IT::size*7UL);
3158  }
3159  y.store( j , y.load(j ) - xmm1*factor );
3160  y.store( j+IT::size , y.load(j+IT::size ) - xmm2*factor );
3161  y.store( j+IT::size*2UL, y.load(j+IT::size*2UL) - xmm3*factor );
3162  y.store( j+IT::size*3UL, y.load(j+IT::size*3UL) - xmm4*factor );
3163  y.store( j+IT::size*4UL, y.load(j+IT::size*4UL) - xmm5*factor );
3164  y.store( j+IT::size*5UL, y.load(j+IT::size*5UL) - xmm6*factor );
3165  y.store( j+IT::size*6UL, y.load(j+IT::size*6UL) - xmm7*factor );
3166  y.store( j+IT::size*7UL, y.load(j+IT::size*7UL) - xmm8*factor );
3167  }
3168  for( ; (j+IT::size*3UL) < N; j+=IT::size*4UL ) {
3169  IntrinsicType xmm1, xmm2, xmm3, xmm4;
3170  for( size_t i=0UL; i<M; ++i ) {
3171  const IntrinsicType x1( set( x[i] ) );
3172  xmm1 = xmm1 + x1 * A.load(i,j );
3173  xmm2 = xmm2 + x1 * A.load(i,j+IT::size );
3174  xmm3 = xmm3 + x1 * A.load(i,j+IT::size*2UL);
3175  xmm4 = xmm4 + x1 * A.load(i,j+IT::size*3UL);
3176  }
3177  y.store( j , y.load(j ) - xmm1*factor );
3178  y.store( j+IT::size , y.load(j+IT::size ) - xmm2*factor );
3179  y.store( j+IT::size*2UL, y.load(j+IT::size*2UL) - xmm3*factor );
3180  y.store( j+IT::size*3UL, y.load(j+IT::size*3UL) - xmm4*factor );
3181  }
3182  for( ; (j+IT::size*2UL) < N; j+=IT::size*3UL ) {
3183  IntrinsicType xmm1, xmm2, xmm3;
3184  for( size_t i=0UL; i<M; ++i ) {
3185  const IntrinsicType x1( set( x[i] ) );
3186  xmm1 = xmm1 + x1 * A.load(i,j );
3187  xmm2 = xmm2 + x1 * A.load(i,j+IT::size );
3188  xmm3 = xmm3 + x1 * A.load(i,j+IT::size*2UL);
3189  }
3190  y.store( j , y.load(j ) - xmm1*factor );
3191  y.store( j+IT::size , y.load(j+IT::size ) - xmm2*factor );
3192  y.store( j+IT::size*2UL, y.load(j+IT::size*2UL) - xmm3*factor );
3193  }
3194  for( ; (j+IT::size) < N; j+=IT::size*2UL ) {
3195  IntrinsicType xmm1, xmm2;
3196  for( size_t i=0UL; i<M; ++i ) {
3197  const IntrinsicType x1( set( x[i] ) );
3198  xmm1 = xmm1 + x1 * A.load(i,j );
3199  xmm2 = xmm2 + x1 * A.load(i,j+IT::size);
3200  }
3201  y.store( j , y.load(j ) - xmm1*factor );
3202  y.store( j+IT::size, y.load(j+IT::size) - xmm2*factor );
3203  }
3204  if( j < N ) {
3205  IntrinsicType xmm1;
3206  for( size_t i=0UL; i<M; ++i ) {
3207  xmm1 = xmm1 + set( x[i] ) * A.load(i,j);
3208  }
3209  y.store( j, y.load(j) - xmm1*factor );
3210  }
3211  }
3212  //**********************************************************************************************
3213 
3214  //**BLAS-based subtraction assignment to dense vectors (default)********************************
3228  template< typename VT1 // Type of the left-hand side target vector
3229  , typename VT2 // Type of the left-hand side vector operand
3230  , typename MT1 // Type of the right-hand side matrix operand
3231  , typename ST2 > // Type of the scalar value
3232  static inline typename EnableIf< UseDefaultKernel<VT1,VT2,MT1,ST2> >::Type
3233  selectBlasSubAssignKernel( VT1& y, const VT2& x, const MT1& A, ST2 scalar )
3234  {
3235  selectDefaultSubAssignKernel( y, x, A, scalar );
3236  }
3237  //**********************************************************************************************
3238 
3239  //**BLAS-based subtraction assignment to dense vectors (single precision)***********************
3240 #if BLAZE_BLAS_MODE
3241 
3254  template< typename VT1 // Type of the left-hand side target vector
3255  , typename VT2 // Type of the left-hand side vector operand
3256  , typename MT1 // Type of the right-hand side matrix operand
3257  , typename ST2 > // Type of the scalar value
3258  static inline typename EnableIf< UseSinglePrecisionKernel<VT1,VT2,MT1,ST2> >::Type
3259  selectBlasSubAssignKernel( VT1& y, const VT2& x, const MT1& A, ST2 scalar )
3260  {
3261  sgemv( y, x, A, -scalar, 1.0F );
3262  }
3263 #endif
3264  //**********************************************************************************************
3265 
3266  //**BLAS-based subtraction assignment to dense vectors (double precision)***********************
3267 #if BLAZE_BLAS_MODE
3268 
3281  template< typename VT1 // Type of the left-hand side target vector
3282  , typename VT2 // Type of the left-hand side vector operand
3283  , typename MT1 // Type of the right-hand side matrix operand
3284  , typename ST2 > // Type of the scalar value
3285  static inline typename EnableIf< UseDoublePrecisionKernel<VT1,VT2,MT1,ST2> >::Type
3286  selectBlasSubAssignKernel( VT1& y, const VT2& x, const MT1& A, ST2 scalar )
3287  {
3288  dgemv( y, x, A, -scalar, 1.0 );
3289  }
3290 #endif
3291  //**********************************************************************************************
3292 
3293  //**BLAS-based subtraction assignment to dense vectors (single precision complex)***************
3294 #if BLAZE_BLAS_MODE
3295 
3308  template< typename VT1 // Type of the left-hand side target vector
3309  , typename VT2 // Type of the left-hand side vector operand
3310  , typename MT1 // Type of the right-hand side matrix operand
3311  , typename ST2 > // Type of the scalar value
3312  static inline typename EnableIf< UseSinglePrecisionComplexKernel<VT1,VT2,MT1> >::Type
3313  selectBlasSubAssignKernel( VT1& y, const VT2& x, const MT1& A, ST2 scalar )
3314  {
3315  cgemv( y, x, A, complex<float>( -scalar, 0.0F ), complex<float>( 1.0F, 0.0F ) );
3316  }
3317 #endif
3318  //**********************************************************************************************
3319 
3320  //**BLAS-based subtraction assignment to dense vectors (double precision complex)***************
3321 #if BLAZE_BLAS_MODE
3322 
3335  template< typename VT1 // Type of the left-hand side target vector
3336  , typename VT2 // Type of the left-hand side vector operand
3337  , typename MT1 // Type of the right-hand side matrix operand
3338  , typename ST2 > // Type of the scalar value
3339  static inline typename EnableIf< UseDoublePrecisionComplexKernel<VT1,VT2,MT1> >::Type
3340  selectBlasSubAssignKernel( VT1& y, const VT2& x, const MT1& A, ST2 scalar )
3341  {
3342  zgemv( y, x, A, complex<double>( -scalar, 0.0 ), complex<double>( 1.0, 0.0 ) );
3343  }
3344 #endif
3345  //**********************************************************************************************
3346 
3347  //**Subtraction assignment to sparse vectors****************************************************
3348  // No special implementation for the subtraction assignment to sparse vectors.
3349  //**********************************************************************************************
3350 
3351  //**Multiplication assignment to dense vectors**************************************************
3363  template< typename VT1 > // Type of the target dense vector
3364  friend inline void multAssign( DenseVector<VT1,true>& lhs, const DVecScalarMultExpr& rhs )
3365  {
3367 
3371 
3372  BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
3373 
3374  const ResultType tmp( serial( rhs ) );
3375  multAssign( ~lhs, tmp );
3376  }
3377  //**********************************************************************************************
3378 
3379  //**Multiplication assignment to sparse vectors*************************************************
3380  // No special implementation for the multiplication assignment to sparse vectors.
3381  //**********************************************************************************************
3382 
3383  //**SMP assignment to dense vectors*************************************************************
3397  template< typename VT1 > // Type of the target dense vector
3398  friend inline typename EnableIf< UseSMPAssign<VT1> >::Type
3399  smpAssign( DenseVector<VT1,true>& lhs, const DVecScalarMultExpr& rhs )
3400  {
3402 
3403  BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
3404 
3405  typename VMM::LeftOperand left ( rhs.vector_.leftOperand() );
3406  typename VMM::RightOperand right( rhs.vector_.rightOperand() );
3407 
3408  if( right.rows() == 0UL ) {
3409  reset( ~lhs );
3410  return;
3411  }
3412  else if( right.columns() == 0UL ) {
3413  return;
3414  }
3415 
3416  LT x( left ); // Evaluation of the left-hand side dense vector operand
3417  RT A( right ); // Evaluation of the right-hand side dense matrix operand
3418 
3419  BLAZE_INTERNAL_ASSERT( x.size() == left.size() , "Invalid vector size" );
3420  BLAZE_INTERNAL_ASSERT( A.rows() == right.rows() , "Invalid number of rows" );
3421  BLAZE_INTERNAL_ASSERT( A.columns() == right.columns(), "Invalid number of columns" );
3422  BLAZE_INTERNAL_ASSERT( A.columns() == (~lhs).size() , "Invalid vector size" );
3423 
3424  smpAssign( ~lhs, x * A * rhs.scalar_ );
3425  }
3426  //**********************************************************************************************
3427 
3428  //**SMP assignment to sparse vectors************************************************************
3442  template< typename VT1 > // Type of the target sparse vector
3443  friend inline typename EnableIf< UseSMPAssign<VT1> >::Type
3444  smpAssign( SparseVector<VT1,true>& lhs, const DVecScalarMultExpr& rhs )
3445  {
3447 
3451 
3452  BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
3453 
3454  const ResultType tmp( rhs );
3455  smpAssign( ~lhs, tmp );
3456  }
3457  //**********************************************************************************************
3458 
3459  //**SMP addition assignment to dense vectors****************************************************
3473  template< typename VT1 > // Type of the target dense vector
3474  friend inline typename EnableIf< UseSMPAssign<VT1> >::Type
3475  smpAddAssign( DenseVector<VT1,true>& lhs, const DVecScalarMultExpr& rhs )
3476  {
3478 
3479  BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
3480 
3481  typename VMM::LeftOperand left ( rhs.vector_.leftOperand() );
3482  typename VMM::RightOperand right( rhs.vector_.rightOperand() );
3483 
3484  if( right.rows() == 0UL || right.columns() == 0UL ) {
3485  return;
3486  }
3487 
3488  LT x( left ); // Evaluation of the left-hand side dense vector operand
3489  RT A( right ); // Evaluation of the right-hand side dense matrix operand
3490 
3491  BLAZE_INTERNAL_ASSERT( x.size() == left.size() , "Invalid vector size" );
3492  BLAZE_INTERNAL_ASSERT( A.rows() == right.rows() , "Invalid number of rows" );
3493  BLAZE_INTERNAL_ASSERT( A.columns() == right.columns(), "Invalid number of columns" );
3494  BLAZE_INTERNAL_ASSERT( A.columns() == (~lhs).size() , "Invalid vector size" );
3495 
3496  smpAddAssign( ~lhs, x * A * rhs.scalar_ );
3497  }
3498  //**********************************************************************************************
3499 
3500  //**SMP addition assignment to sparse vectors***************************************************
3501  // No special implementation for the SMP addition assignment to sparse vectors.
3502  //**********************************************************************************************
3503 
3504  //**SMP subtraction assignment to dense vectors*************************************************
3518  template< typename VT1 > // Type of the target dense vector
3519  friend inline typename EnableIf< UseSMPAssign<VT1> >::Type
3520  smpSubAssign( DenseVector<VT1,true>& lhs, const DVecScalarMultExpr& rhs )
3521  {
3523 
3524  BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
3525 
3526  typename VMM::LeftOperand left ( rhs.vector_.leftOperand() );
3527  typename VMM::RightOperand right( rhs.vector_.rightOperand() );
3528 
3529  if( right.rows() == 0UL || right.columns() == 0UL ) {
3530  return;
3531  }
3532 
3533  LT x( left ); // Evaluation of the left-hand side dense vector operand
3534  RT A( right ); // Evaluation of the right-hand side dense matrix operand
3535 
3536  BLAZE_INTERNAL_ASSERT( x.size() == left.size() , "Invalid vector size" );
3537  BLAZE_INTERNAL_ASSERT( A.rows() == right.rows() , "Invalid number of rows" );
3538  BLAZE_INTERNAL_ASSERT( A.columns() == right.columns(), "Invalid number of columns" );
3539  BLAZE_INTERNAL_ASSERT( A.columns() == (~lhs).size() , "Invalid vector size" );
3540 
3541  smpSubAssign( ~lhs, x * A * rhs.scalar_ );
3542  }
3543  //**********************************************************************************************
3544 
3545  //**SMP subtraction assignment to sparse vectors************************************************
3546  // No special implementation for the SMP subtraction assignment to sparse vectors.
3547  //**********************************************************************************************
3548 
3549  //**SMP multiplication assignment to dense vectors**********************************************
3564  template< typename VT1 > // Type of the target dense vector
3565  friend inline typename EnableIf< UseSMPAssign<VT1> >::Type
3566  smpMultAssign( DenseVector<VT1,true>& lhs, const DVecScalarMultExpr& rhs )
3567  {
3569 
3573 
3574  BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
3575 
3576  const ResultType tmp( rhs );
3577  smpMultAssign( ~lhs, tmp );
3578  }
3579  //**********************************************************************************************
3580 
3581  //**SMP multiplication assignment to sparse vectors*********************************************
3582  // No special implementation for the SMP multiplication assignment to sparse vectors.
3583  //**********************************************************************************************
3584 
3585  //**Compile time checks*************************************************************************
3594  //**********************************************************************************************
3595 };
3597 //*************************************************************************************************
3598 
3599 
3600 
3601 
3602 //=================================================================================================
3603 //
3604 // GLOBAL BINARY ARITHMETIC OPERATORS
3605 //
3606 //=================================================================================================
3607 
3608 //*************************************************************************************************
3639 template< typename T1 // Type of the left-hand side dense vector
3640  , typename T2 > // Type of the right-hand side dense matrix
3641 inline const typename DisableIf< IsMatMatMultExpr<T2>, TDVecDMatMultExpr<T1,T2> >::Type
3643 {
3645 
3646  if( (~vec).size() != (~mat).rows() )
3647  throw std::invalid_argument( "Vector and matrix sizes do not match" );
3648 
3649  return TDVecDMatMultExpr<T1,T2>( ~vec, ~mat );
3650 }
3651 //*************************************************************************************************
3652 
3653 
3654 
3655 
3656 //=================================================================================================
3657 //
3658 // GLOBAL RESTRUCTURING BINARY ARITHMETIC OPERATORS
3659 //
3660 //=================================================================================================
3661 
3662 //*************************************************************************************************
3675 template< typename T1 // Type of the left-hand side dense vector
3676  , typename T2 // Type of the right-hand side dense matrix
3677  , bool SO > // Storage order of the right-hand side dense matrix
3678 inline const typename EnableIf< IsMatMatMultExpr<T2>, typename MultExprTrait<T1,T2>::Type >::Type
3680 {
3682 
3684 
3685  return ( vec * (~mat).leftOperand() ) * (~mat).rightOperand();
3686 }
3687 //*************************************************************************************************
3688 
3689 
3690 
3691 
3692 //=================================================================================================
3693 //
3694 // SIZE SPECIALIZATIONS
3695 //
3696 //=================================================================================================
3697 
3698 //*************************************************************************************************
3700 template< typename MT, typename VT >
3701 struct Size< TDVecDMatMultExpr<MT,VT> >
3702  : public Columns<MT>
3703 {};
3705 //*************************************************************************************************
3706 
3707 
3708 
3709 
3710 //=================================================================================================
3711 //
3712 // EXPRESSION TRAIT SPECIALIZATIONS
3713 //
3714 //=================================================================================================
3715 
3716 //*************************************************************************************************
3718 template< typename VT, typename MT, bool AF >
3719 struct SubvectorExprTrait< TDVecDMatMultExpr<VT,MT>, AF >
3720 {
3721  public:
3722  //**********************************************************************************************
3723  typedef typename MultExprTrait< VT, typename SubmatrixExprTrait<const MT,AF>::Type >::Type Type;
3724  //**********************************************************************************************
3725 };
3727 //*************************************************************************************************
3728 
3729 } // namespace blaze
3730 
3731 #endif
bool isAligned() const
Returns whether the operands of the expression are properly aligned in memory.
Definition: TDVecDMatMultExpr.h:385
Data type constraint.
Compile time check whether the given type is a computational expression template.This type trait clas...
Definition: IsComputation.h:89
BLAZE_ALWAYS_INLINE void multAssign(Matrix< MT1, SO1 > &lhs, const Matrix< MT2, SO2 > &rhs)
Default implementation of the multiplication assignment of a matrix to a matrix.
Definition: Matrix.h:879
#define BLAZE_BLAS_IS_PARALLEL
Compilation switch for the parallel BLAS mode.This compilation switch specifies whether the used BLAS...
Definition: BLAS.h:86
MT::ResultType MRT
Result type of the right-hand side dense matrix expression.
Definition: TDVecDMatMultExpr.h:115
const DMatDMatMultExpr< T1, T2 > operator*(const DenseMatrix< T1, false > &lhs, const DenseMatrix< T2, false > &rhs)
Multiplication operator for the multiplication of two row-major dense matrices ( ).
Definition: DMatDMatMultExpr.h:4838
const ElementType ReturnType
Return type for expression template evaluations.
Definition: TDVecDMatMultExpr.h:255
MT::CompositeType MCT
Composite type of the right-hand side dense matrix expression.
Definition: TDVecDMatMultExpr.h:119
BLAZE_ALWAYS_INLINE size_t size(const Vector< VT, TF > &vector)
Returns the current size/dimension of the vector.
Definition: Vector.h:258
bool canSMPAssign() const
Returns whether the expression can be used in SMP assignments.
Definition: TDVecDMatMultExpr.h:395
Efficient implementation of a compressed matrix.The CompressedMatrix class template is the represent...
Definition: CompressedMatrix.h:205
#define BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE(T)
Constraint on the data type.In case the given data type T is not a dense, N-dimensional matrix type...
Definition: DenseMatrix.h:79
RightOperand rightOperand() const
Returns the right-hand side dense matrix operand.
Definition: TDVecDMatMultExpr.h:351
Header file for the IsSame and IsStrictlySame type traits.
Constraint on the data type.
const This & CompositeType
Data type for composite expression templates.
Definition: CompressedMatrix.h:2478
Type ElementType
Type of the sparse matrix elements.
Definition: CompressedMatrix.h:257
BLAZE_ALWAYS_INLINE size_t rows(const Matrix< MT, SO > &matrix)
Returns the current number of rows of the matrix.
Definition: Matrix.h:316
Header file for the DenseVector base class.
const DMatSerialExpr< MT, SO > serial(const DenseMatrix< MT, SO > &dm)
Forces the serial evaluation of the given dense matrix expression dm.
Definition: DMatSerialExpr.h:695
Header file for the Computation base class.
Type relationship analysis.This class tests if the two data types A and B are equal. For this type comparison, the cv-qualifiers of both data types are ignored. If A and B are the same data type (ignoring the cv-qualifiers), then the value member enumeration is set to 1, the nested type definition Type is TrueType, and the class derives from TrueType. Otherwise value is set to 0, Type is FalseType, and the class derives from FalseType.
Definition: IsSame.h:158
Header file for the RequiresEvaluation type trait.
ReturnType operator[](size_t index) const
Subscript operator for the direct access to the vector elements.
Definition: TDVecDMatMultExpr.h:304
Header file for the VecScalarMultExpr base class.
SelectType< evaluateVector, const VRT, VCT >::Type LT
Type for the assignment of the left-hand side dense matrix operand.
Definition: TDVecDMatMultExpr.h:265
Header file for the IsFloat type trait.
Base class for dense matrices.The DenseMatrix class is a base class for all dense matrix classes...
Definition: DenseMatrix.h:70
TDVecDMatMultExpr< VT, MT > This
Type of this TDVecDMatMultExpr instance.
Definition: TDVecDMatMultExpr.h:250
Constraint on the data type.
#define BLAZE_CONSTRAINT_MUST_BE_FLOAT_TYPE(T)
Constraint on the data type.This compile time constraint checks that the given data type T is of type...
Definition: Float.h:80
Constraint on the data type.
Constraint on the data type.
Header file for the MultExprTrait class template.
Compile time check to query the requirement to evaluate an expression.Via this type trait it is possi...
Definition: RequiresEvaluation.h:90
SelectType< IsExpression< VT >::value, const VT, const VT & >::Type LeftOperand
Composite type of the left-hand side dense vector expression.
Definition: TDVecDMatMultExpr.h:259
const This & CompositeType
Data type for composite expression templates.
Definition: CompressedMatrix.h:259
Compile time type selection.The SelectType class template selects one of the two given types T1 and T...
Definition: SelectType.h:59
Header file for the DisableIf class template.
ResultType::TransposeType TransposeType
Transpose type for expression template evaluations.
Definition: TDVecDMatMultExpr.h:252
Header file for the multiplication trait.
Header file for the IsDouble type trait.
IntrinsicTrait< ElementType >::Type IntrinsicType
Resulting intrinsic element type.
Definition: TDVecDMatMultExpr.h:254
#define BLAZE_CONSTRAINT_MUST_BE_DOUBLE_TYPE(T)
Constraint on the data type.This compile time constraint checks that the given data type T is of type...
Definition: Double.h:80
bool canAlias(const T *alias) const
Returns whether the expression can alias with the given address alias.
Definition: TDVecDMatMultExpr.h:363
TDVecDMatMultExpr(const VT &vec, const MT &mat)
Constructor for the TDVecDMatMultExpr class.
Definition: TDVecDMatMultExpr.h:289
Header file for the IsMatMatMultExpr type trait class.
BLAZE_ALWAYS_INLINE void assign(Matrix< MT1, SO1 > &lhs, const Matrix< MT2, SO2 > &rhs)
Default implementation of the assignment of a matrix to a matrix.
Definition: Matrix.h:635
Header file for the Columns type trait.
const size_t SMP_TDVECDMATMULT_THRESHOLD
SMP dense vector/row-major dense matrix multiplication threshold.This threshold specifies when a dens...
Definition: Thresholds.h:368
Header file for the IsBlasCompatible type trait.
Base class for N-dimensional dense vectors.The DenseVector class is a base class for all arbitrarily ...
Definition: DenseVector.h:70
#define BLAZE_CONSTRAINT_MUST_BE_SAME_TYPE(A, B)
Data type constraint.In case the two types A and B are not the same (ignoring all cv-qualifiers of bo...
Definition: SameType.h:89
#define BLAZE_BLAS_MODE
Compilation switch for the BLAS mode.This compilation switch enables/disables the BLAS mode...
Definition: BLAS.h:65
Constraint on the data type.
#define BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE(T)
Constraint on the data type.In case the given data type T is not a reference type, a compilation error is created.
Definition: Reference.h:78
Constraints on the storage order of matrix types.
Constraint on the data type.
Type ElementType
Type of the sparse matrix elements.
Definition: CompressedMatrix.h:2476
bool isAliased(const T *alias) const
Returns whether the expression is aliased with the given address alias.
Definition: TDVecDMatMultExpr.h:375
Header file for the SelectType class template.
Header file for all forward declarations for expression class templates.
Header file for the EnableIf class template.
Header file for the serial shim.
size_t size() const
Returns the current size/dimension of the vector.
Definition: TDVecDMatMultExpr.h:331
Header file for the IsNumeric type trait.
BLAZE_ALWAYS_INLINE EnableIf< IsIntegral< T >, Set< T, sizeof(T)> >::Type::Type set(T value)
Sets all values in the vector to the given integral value.
Definition: Set.h:211
VT::ResultType VRT
Result type of the left-hand side dense vector expression.
Definition: TDVecDMatMultExpr.h:114
EnableIf< IsDenseMatrix< MT1 > >::Type smpSubAssign(Matrix< MT1, SO1 > &lhs, const Matrix< MT2, SO2 > &rhs)
Default implementation of the SMP subtraction assignment of a matrix to dense matrix.
Definition: DenseMatrix.h:160
#define BLAZE_CONSTRAINT_MUST_NOT_BE_SYMMETRIC_MATRIX_TYPE(T)
Constraint on the data type.In case the given data type T is a symmetric matrix type, a compilation error is created.
Definition: Symmetric.h:116
Header file for the SubmatrixExprTrait class template.
#define BLAZE_CONSTRAINT_MUST_BE_ROW_MAJOR_MATRIX_TYPE(T)
Constraint on the data type.In case the given data type T is not a row-major dense or sparse matrix t...
Definition: StorageOrder.h:81
System settings for the BLAS mode.
Intrinsic characteristics of data types.The IntrinsicTrait class template provides the intrinsic char...
Definition: IntrinsicTrait.h:749
Header file for run time assertion macros.
EnableIf< IsDenseMatrix< MT1 > >::Type smpAssign(Matrix< MT1, SO1 > &lhs, const Matrix< MT2, SO2 > &rhs)
Default implementation of the SMP assignment of a matrix to a dense matrix.
Definition: DenseMatrix.h:98
Base template for the MultTrait class.
Definition: MultTrait.h:142
BLAZE_ALWAYS_INLINE void addAssign(Matrix< MT1, SO1 > &lhs, const Matrix< MT2, SO2 > &rhs)
Default implementation of the addition assignment of a matrix to a matrix.
Definition: Matrix.h:742
VRT::ElementType VET
Element type of the left-hand side dense vector epxression.
Definition: TDVecDMatMultExpr.h:116
SelectType< IsExpression< MT >::value, const MT, const MT & >::Type RightOperand
Composite type of the right-hand side dense matrix expression.
Definition: TDVecDMatMultExpr.h:262
#define BLAZE_CONSTRAINT_MUST_BE_NUMERIC_TYPE(T)
Constraint on the data type.In case the given data type T is not a numeric (integral or floating poin...
Definition: Numeric.h:79
Header file for the reset shim.
LeftOperand leftOperand() const
Returns the left-hand side dense vector operand.
Definition: TDVecDMatMultExpr.h:341
Constraint on the data type.
MRT::ElementType MET
Element type of the right-hand side dense matrix expression.
Definition: TDVecDMatMultExpr.h:117
Compile time check for data types.This type trait tests whether or not the given template parameter i...
Definition: IsBlasCompatible.h:99
Header file for the TVecMatMultExpr base class.
RightOperand mat_
Right-hand side dense matrix of the multiplication expression.
Definition: TDVecDMatMultExpr.h:406
Constraint on the data type.
Expression object for transpose dense vector-dense matrix multiplications.The TDVecDMatMultExpr class...
Definition: Forward.h:133
BLAZE_ALWAYS_INLINE void reset(const NonNumericProxy< MT > &proxy)
Resetting the represented element to the default initial values.
Definition: NonNumericProxy.h:833
ResultType::ElementType ElementType
Resulting element type.
Definition: TDVecDMatMultExpr.h:253
SelectType< evaluateMatrix, const MRT, MCT >::Type RT
Type for the assignment of the right-hand side dense vector operand.
Definition: TDVecDMatMultExpr.h:268
Header file for all intrinsic functionality.
const size_t end_
End of the unrolled calculation loop.
Definition: TDVecDMatMultExpr.h:407
#define BLAZE_CONSTRAINT_MUST_BE_DENSE_VECTOR_TYPE(T)
Constraint on the data type.In case the given data type T is not a dense, N-dimensional vector type...
Definition: DenseVector.h:79
#define BLAZE_CONSTRAINT_MUST_FORM_VALID_TVECMATMULTEXPR(T1, T2)
Constraint on the data type.In case the given data types T1 and T2 do not form a valid vector/matrix ...
Definition: TVecMatMultExpr.h:166
#define BLAZE_CONSTRAINT_MUST_BE_COMPLEX_TYPE(T)
Constraint on the data type.This compile time constraint checks that the given data type T is a compl...
Definition: Complex.h:80
Header file for the IsComputation type trait class.
CompressedMatrix< Type,!SO > TransposeType
Transpose type for expression template evaluations.
Definition: CompressedMatrix.h:256
EnableIf< IsDenseMatrix< MT1 > >::Type smpAddAssign(Matrix< MT1, SO1 > &lhs, const Matrix< MT2, SO2 > &rhs)
Default implementation of the SMP addition assignment of a matrix to a dense matrix.
Definition: DenseMatrix.h:129
const size_t TDVECDMATMULT_THRESHOLD
Dense Vector/row-major dense matrix multiplication threshold.This setting specifies the threshold bet...
Definition: Thresholds.h:91
#define BLAZE_FUNCTION_TRACE
Function trace macro.This macro can be used to reliably trace function calls. In case function tracin...
Definition: FunctionTrace.h:157
VT::CompositeType VCT
Composite type of the left-hand side dense vector expression.
Definition: TDVecDMatMultExpr.h:118
This ResultType
Result type for expression template evaluations.
Definition: CompressedMatrix.h:2473
Header file for basic type definitions.
#define BLAZE_CONSTRAINT_MUST_BE_ROW_VECTOR_TYPE(T)
Constraint on the data type.In case the given data type T is not a row dense or sparse vector type (i...
Definition: TransposeFlag.h:81
const ResultType CompositeType
Data type for composite expression templates.
Definition: TDVecDMatMultExpr.h:256
Header file for the IsComplex type trait.
Header file for the SubvectorExprTrait class template.
Header file for the complex data type.
LeftOperand vec_
Left-hand side dense vector of the multiplication expression.
Definition: TDVecDMatMultExpr.h:405
Constraint on the data type.
EnableIf< IsDenseVector< VT1 > >::Type smpMultAssign(Vector< VT1, TF1 > &lhs, const Vector< VT2, TF2 > &rhs)
Default implementation of the SMP multiplication assignment of a vector to a dense vector...
Definition: DenseVector.h:189
Header file for the Size type trait.
Size type of the Blaze library.
Header file for the thresholds for matrix/vector and matrix/matrix multiplications.
#define BLAZE_INTERNAL_ASSERT(expr, msg)
Run time assertion macro for internal checks.In case of an invalid run time expression, the program execution is terminated. The BLAZE_INTERNAL_ASSERT macro can be disabled by setting the BLAZE_USER_ASSERTION flag to zero or by defining NDEBUG during the compilation.
Definition: Assert.h:101
MultTrait< VRT, MRT >::Type ResultType
Result type for expression template evaluations.
Definition: TDVecDMatMultExpr.h:251
Header file for the IsExpression type trait class.
Header file for the FunctionTrace class.
BLAZE_ALWAYS_INLINE void subAssign(Matrix< MT1, SO1 > &lhs, const Matrix< MT2, SO2 > &rhs)
Default implementation of the subtraction assignment of a matrix to matrix.
Definition: Matrix.h:849