All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
TDVecTDMatMultExpr.h
Go to the documentation of this file.
1 //=================================================================================================
33 //=================================================================================================
34 
35 #ifndef _BLAZE_MATH_EXPRESSIONS_TDVECTDMATMULTEXPR_H_
36 #define _BLAZE_MATH_EXPRESSIONS_TDVECTDMATMULTEXPR_H_
37 
38 
39 //*************************************************************************************************
40 // Includes
41 //*************************************************************************************************
42 
43 #include <stdexcept>
44 #include <boost/cast.hpp>
55 #include <blaze/math/Intrinsics.h>
56 #include <blaze/math/shims/Reset.h>
69 #include <blaze/system/BLAS.h>
71 #include <blaze/util/Assert.h>
72 #include <blaze/util/Complex.h>
78 #include <blaze/util/DisableIf.h>
79 #include <blaze/util/EnableIf.h>
81 #include <blaze/util/SelectType.h>
82 #include <blaze/util/Types.h>
88 
89 
90 namespace blaze {
91 
92 //=================================================================================================
93 //
94 // CLASS TDVECTDMATMULTEXPR
95 //
96 //=================================================================================================
97 
98 //*************************************************************************************************
105 template< typename VT // Type of the left-hand side dense vector
106  , typename MT > // Type of the right-hand side dense matrix
107 class TDVecTDMatMultExpr : public DenseVector< TDVecTDMatMultExpr<VT,MT>, true >
108  , private TVecMatMultExpr
109  , private Computation
110 {
111  private:
112  //**Type definitions****************************************************************************
113  typedef typename VT::ResultType VRT;
114  typedef typename MT::ResultType MRT;
115  typedef typename VRT::ElementType VET;
116  typedef typename MRT::ElementType MET;
117  typedef typename VT::CompositeType VCT;
118  typedef typename MT::CompositeType MCT;
119  //**********************************************************************************************
120 
121  //**********************************************************************************************
123  enum { evaluateVector = IsComputation<VT>::value || RequiresEvaluation<VT>::value };
124  //**********************************************************************************************
125 
126  //**********************************************************************************************
128  enum { evaluateMatrix = ( IsComputation<MT>::value && IsSame<MET,VET>::value &&
130  //**********************************************************************************************
131 
132  //**********************************************************************************************
134 
138  template< typename T1 >
139  struct UseSMPAssign {
140  enum { value = ( evaluateVector || evaluateMatrix ) };
141  };
143  //**********************************************************************************************
144 
145  //**********************************************************************************************
147 
151  template< typename T1, typename T2, typename T3 >
152  struct UseSinglePrecisionKernel {
153  enum { value = T1::vectorizable && T2::vectorizable && T3::vectorizable &&
154  IsFloat<typename T1::ElementType>::value &&
155  IsFloat<typename T2::ElementType>::value &&
156  IsFloat<typename T3::ElementType>::value };
157  };
159  //**********************************************************************************************
160 
161  //**********************************************************************************************
163 
167  template< typename T1, typename T2, typename T3 >
168  struct UseDoublePrecisionKernel {
169  enum { value = T1::vectorizable && T2::vectorizable && T3::vectorizable &&
170  IsDouble<typename T1::ElementType>::value &&
171  IsDouble<typename T2::ElementType>::value &&
172  IsDouble<typename T3::ElementType>::value };
173  };
175  //**********************************************************************************************
176 
177  //**********************************************************************************************
179 
183  template< typename T1, typename T2, typename T3 >
184  struct UseSinglePrecisionComplexKernel {
185  typedef complex<float> Type;
186  enum { value = T1::vectorizable && T2::vectorizable && T3::vectorizable &&
187  IsSame<typename T1::ElementType,Type>::value &&
188  IsSame<typename T2::ElementType,Type>::value &&
189  IsSame<typename T3::ElementType,Type>::value };
190  };
192  //**********************************************************************************************
193 
194  //**********************************************************************************************
196 
200  template< typename T1, typename T2, typename T3 >
201  struct UseDoublePrecisionComplexKernel {
202  typedef complex<double> Type;
203  enum { value = T1::vectorizable && T2::vectorizable && T3::vectorizable &&
204  IsSame<typename T1::ElementType,Type>::value &&
205  IsSame<typename T2::ElementType,Type>::value &&
206  IsSame<typename T3::ElementType,Type>::value };
207  };
209  //**********************************************************************************************
210 
211  //**********************************************************************************************
213 
216  template< typename T1, typename T2, typename T3 >
217  struct UseDefaultKernel {
218  enum { value = !BLAZE_BLAS_MODE || ( !UseSinglePrecisionKernel<T1,T2,T3>::value &&
219  !UseDoublePrecisionKernel<T1,T2,T3>::value &&
220  !UseSinglePrecisionComplexKernel<T1,T2,T3>::value &&
221  !UseDoublePrecisionComplexKernel<T1,T2,T3>::value ) };
222  };
224  //**********************************************************************************************
225 
226  //**********************************************************************************************
228 
232  template< typename T1, typename T2, typename T3 >
233  struct UseVectorizedDefaultKernel {
234  enum { value = T1::vectorizable && T2::vectorizable && T3::vectorizable &&
235  IsSame<typename T1::ElementType,typename T2::ElementType>::value &&
236  IsSame<typename T1::ElementType,typename T3::ElementType>::value &&
237  IntrinsicTrait<typename T1::ElementType>::addition &&
238  IntrinsicTrait<typename T1::ElementType>::multiplication };
239  };
241  //**********************************************************************************************
242 
243  public:
244  //**Type definitions****************************************************************************
250  typedef const ElementType ReturnType;
251  typedef const ResultType CompositeType;
252 
254  typedef typename SelectType< IsExpression<VT>::value, const VT, const VT& >::Type LeftOperand;
255 
257  typedef typename SelectType< IsExpression<MT>::value, const MT, const MT& >::Type RightOperand;
258 
261 
264  //**********************************************************************************************
265 
266  //**Compilation flags***************************************************************************
268  enum { vectorizable = VT::vectorizable && MT::vectorizable &&
272 
274  enum { smpAssignable = !evaluateVector && VT::smpAssignable &&
275  !evaluateMatrix && MT::smpAssignable };
276  //**********************************************************************************************
277 
278  //**Constructor*********************************************************************************
284  explicit inline TDVecTDMatMultExpr( const VT& vec, const MT& mat )
285  : vec_( vec ) // Left-hand side dense vector of the multiplication expression
286  , mat_( mat ) // Right-hand side dense matrix of the multiplication expression
287  , end_( ( (mat.rows()-1UL) & size_t(-2) ) + 1UL ) // End of the unrolled calculation loop
288  {
289  BLAZE_INTERNAL_ASSERT( vec_.size() == mat_.rows(), "Invalid vector and matrix sizes" );
290  }
291  //**********************************************************************************************
292 
293  //**Subscript operator**************************************************************************
299  inline ReturnType operator[]( size_t index ) const {
300  BLAZE_INTERNAL_ASSERT( index < mat_.columns(), "Invalid vector access index" );
301 
302  ElementType res;
303 
304  if( mat_.rows() != 0UL ) {
305  res = vec_[0UL] * mat_(0UL,index);
306  for( size_t j=1UL; j<end_; j+=2UL ) {
307  res += vec_[j] * mat_(j,index) + vec_[j+1UL] * mat_(j+1UL,index);
308  }
309  if( end_ < mat_.rows() ) {
310  res += vec_[end_] * mat_(end_,index);
311  }
312  }
313  else {
314  reset( res );
315  }
316 
317  return res;
318  }
319  //**********************************************************************************************
320 
321  //**Size function*******************************************************************************
326  inline size_t size() const {
327  return mat_.columns();
328  }
329  //**********************************************************************************************
330 
331  //**Left operand access*************************************************************************
336  inline LeftOperand leftOperand() const {
337  return vec_;
338  }
339  //**********************************************************************************************
340 
341  //**Right operand access************************************************************************
346  inline RightOperand rightOperand() const {
347  return mat_;
348  }
349  //**********************************************************************************************
350 
351  //**********************************************************************************************
357  template< typename T >
358  inline bool canAlias( const T* alias ) const {
359  return ( vec_.isAliased( alias ) || mat_.isAliased( alias ) );
360  }
361  //**********************************************************************************************
362 
363  //**********************************************************************************************
369  template< typename T >
370  inline bool isAliased( const T* alias ) const {
371  return ( vec_.isAliased( alias ) || mat_.isAliased( alias ) );
372  }
373  //**********************************************************************************************
374 
375  //**********************************************************************************************
380  inline bool isAligned() const {
381  return vec_.isAligned() && mat_.isAligned();
382  }
383  //**********************************************************************************************
384 
385  //**********************************************************************************************
390  inline bool canSMPAssign() const {
391  return ( !BLAZE_BLAS_IS_PARALLEL ||
392  ( IsComputation<MT>::value && !evaluateMatrix ) ||
393  ( mat_.rows() * mat_.columns() < TDVECTDMATMULT_THRESHOLD ) ) &&
395  }
396  //**********************************************************************************************
397 
398  private:
399  //**Member variables****************************************************************************
402  const size_t end_;
403  //**********************************************************************************************
404 
405  //**BLAS kernel (single precision)*************************************************************
406 #if BLAZE_BLAS_MODE
407 
422  template< typename VT1 // Type of the left-hand side target vector
423  , typename VT2 // Type of the left-hand side vector operand
424  , typename MT1 > // Type of the right-hand side matrix operand
425  static inline void sgemv( VT1& y, const VT2& x, const MT1& A, float alpha, float beta )
426  {
427  using boost::numeric_cast;
428 
432 
433  const int M ( numeric_cast<int>( A.rows() ) );
434  const int N ( numeric_cast<int>( A.columns() ) );
435  const int lda( numeric_cast<int>( A.spacing() ) );
436 
437  cblas_sgemv( CblasColMajor, CblasTrans, M, N, alpha,
438  A.data(), lda, x.data(), 1, beta, y.data(), 1 );
439  }
441 #endif
442  //**********************************************************************************************
443 
444  //**BLAS kernel (double precision)**************************************************************
445 #if BLAZE_BLAS_MODE
446 
461  template< typename VT1 // Type of the left-hand side target vector
462  , typename VT2 // Type of the left-hand side vector operand
463  , typename MT1 > // Type of the right-hand side matrix operand
464  static inline void dgemv( VT1& y, const VT2& x, const MT1& A, double alpha, double beta )
465  {
466  using boost::numeric_cast;
467 
471 
472  const int M ( numeric_cast<int>( A.rows() ) );
473  const int N ( numeric_cast<int>( A.columns() ) );
474  const int lda( numeric_cast<int>( A.spacing() ) );
475 
476  cblas_dgemv( CblasColMajor, CblasTrans, M, N, alpha,
477  A.data(), lda, x.data(), 1, beta, y.data(), 1 );
478  }
480 #endif
481  //**********************************************************************************************
482 
483  //**BLAS kernel (single precision complex)******************************************************
484 #if BLAZE_BLAS_MODE
485 
500  template< typename VT1 // Type of the left-hand side target vector
501  , typename VT2 // Type of the left-hand side vector operand
502  , typename MT1 > // Type of the right-hand side matrix operand
503  static inline void cgemv( VT1& y, const VT2& x, const MT1& A,
504  complex<float> alpha, complex<float> beta )
505  {
506  using boost::numeric_cast;
507 
511  BLAZE_CONSTRAINT_MUST_BE_FLOAT_TYPE ( typename VT1::ElementType::value_type );
512  BLAZE_CONSTRAINT_MUST_BE_FLOAT_TYPE ( typename VT2::ElementType::value_type );
513  BLAZE_CONSTRAINT_MUST_BE_FLOAT_TYPE ( typename MT1::ElementType::value_type );
514 
515  const int M ( numeric_cast<int>( A.rows() ) );
516  const int N ( numeric_cast<int>( A.columns() ) );
517  const int lda( numeric_cast<int>( A.spacing() ) );
518 
519  cblas_cgemv( CblasColMajor, CblasTrans, M, N, &alpha,
520  A.data(), lda, x.data(), 1, &beta, y.data(), 1 );
521  }
523 #endif
524  //**********************************************************************************************
525 
526  //**BLAS kernel (double precision complex)******************************************************
527 #if BLAZE_BLAS_MODE
528 
543  template< typename VT1 // Type of the left-hand side target vector
544  , typename VT2 // Type of the left-hand side vector operand
545  , typename MT1 > // Type of the right-hand side matrix operand
546  static inline void zgemv( VT1& y, const VT2& x, const MT1& A,
547  complex<double> alpha, complex<double> beta )
548  {
549  using boost::numeric_cast;
550 
554  BLAZE_CONSTRAINT_MUST_BE_DOUBLE_TYPE ( typename VT1::ElementType::value_type );
555  BLAZE_CONSTRAINT_MUST_BE_DOUBLE_TYPE ( typename VT2::ElementType::value_type );
556  BLAZE_CONSTRAINT_MUST_BE_DOUBLE_TYPE ( typename MT1::ElementType::value_type );
557 
558  const int M ( numeric_cast<int>( A.rows() ) );
559  const int N ( numeric_cast<int>( A.columns() ) );
560  const int lda( numeric_cast<int>( A.spacing() ) );
561 
562  cblas_zgemv( CblasColMajor, CblasTrans, M, N, &alpha,
563  A.data(), lda, x.data(), 1, &beta, y.data(), 1 );
564  }
566 #endif
567  //**********************************************************************************************
568 
569  //**Assignment to dense vectors*****************************************************************
582  template< typename VT1 > // Type of the target dense vector
583  friend inline void assign( DenseVector<VT1,true>& lhs, const TDVecTDMatMultExpr& rhs )
584  {
586 
587  BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
588 
589  if( rhs.mat_.rows() == 0UL ) {
590  reset( ~lhs );
591  return;
592  }
593  else if( rhs.mat_.columns() == 0UL ) {
594  return;
595  }
596 
597  LT x( serial( rhs.vec_ ) ); // Evaluation of the left-hand side dense vector operand
598  RT A( serial( rhs.mat_ ) ); // Evaluation of the right-hand side dense matrix operand
599 
600  BLAZE_INTERNAL_ASSERT( x.size() == rhs.vec_.size() , "Invalid vector size" );
601  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.mat_.rows() , "Invalid number of rows" );
602  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.mat_.columns(), "Invalid number of columns" );
603  BLAZE_INTERNAL_ASSERT( A.columns() == (~lhs).size() , "Invalid vector size" );
604 
605  TDVecTDMatMultExpr::selectAssignKernel( ~lhs, x, A );
606  }
608  //**********************************************************************************************
609 
610  //**Assignment to dense vectors (kernel selection)**********************************************
621  template< typename VT1 // Type of the left-hand side target vector
622  , typename VT2 // Type of the left-hand side vector operand
623  , typename MT1 > // Type of the right-hand side matrix operand
624  static inline void selectAssignKernel( VT1& y, const VT2& x, const MT1& A )
625  {
626  if( ( IsComputation<MT>::value && !evaluateMatrix ) ||
627  ( A.rows() * A.columns() < TDVECTDMATMULT_THRESHOLD ) )
628  TDVecTDMatMultExpr::selectDefaultAssignKernel( y, x, A );
629  else
630  TDVecTDMatMultExpr::selectBlasAssignKernel( y, x, A );
631  }
633  //**********************************************************************************************
634 
635  //**Default assignment to dense vectors*********************************************************
649  template< typename VT1 // Type of the left-hand side target vector
650  , typename VT2 // Type of the left-hand side vector operand
651  , typename MT1 > // Type of the right-hand side matrix operand
652  static inline typename DisableIf< UseVectorizedDefaultKernel<VT1,VT2,MT1> >::Type
653  selectDefaultAssignKernel( VT1& y, const VT2& x, const MT1& A )
654  {
655  y.assign( x * A );
656  }
658  //**********************************************************************************************
659 
660  //**Vectorized default assignment to dense vectors**********************************************
674  template< typename VT1 // Type of the left-hand side target vector
675  , typename VT2 // Type of the left-hand side vector operand
676  , typename MT1 > // Type of the right-hand side matrix operand
677  static inline typename EnableIf< UseVectorizedDefaultKernel<VT1,VT2,MT1> >::Type
678  selectDefaultAssignKernel( VT1& y, const VT2& x, const MT1& A )
679  {
680  typedef IntrinsicTrait<ElementType> IT;
681 
682  const size_t M( A.rows() );
683  const size_t N( A.columns() );
684 
685  size_t j( 0UL );
686 
687  for( ; (j+8UL) <= N; j+=8UL ) {
688  IntrinsicType xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7, xmm8;
689  for( size_t i=0UL; i<M; i+=IT::size ) {
690  const IntrinsicType x1( x.load(i) );
691  xmm1 = xmm1 + x1 * A.load(i,j );
692  xmm2 = xmm2 + x1 * A.load(i,j+1UL);
693  xmm3 = xmm3 + x1 * A.load(i,j+2UL);
694  xmm4 = xmm4 + x1 * A.load(i,j+3UL);
695  xmm5 = xmm5 + x1 * A.load(i,j+4UL);
696  xmm6 = xmm6 + x1 * A.load(i,j+5UL);
697  xmm7 = xmm7 + x1 * A.load(i,j+6UL);
698  xmm8 = xmm8 + x1 * A.load(i,j+7UL);
699  }
700  y[j ] = sum( xmm1 );
701  y[j+1UL] = sum( xmm2 );
702  y[j+2UL] = sum( xmm3 );
703  y[j+3UL] = sum( xmm4 );
704  y[j+4UL] = sum( xmm5 );
705  y[j+5UL] = sum( xmm6 );
706  y[j+6UL] = sum( xmm7 );
707  y[j+7UL] = sum( xmm8 );
708  }
709  for( ; (j+4UL) <= N; j+=4UL ) {
710  IntrinsicType xmm1, xmm2, xmm3, xmm4;
711  for( size_t i=0UL; i<M; i+=IT::size ) {
712  const IntrinsicType x1( x.load(i) );
713  xmm1 = xmm1 + x1 * A.load(i,j );
714  xmm2 = xmm2 + x1 * A.load(i,j+1UL);
715  xmm3 = xmm3 + x1 * A.load(i,j+2UL);
716  xmm4 = xmm4 + x1 * A.load(i,j+3UL);
717  }
718  y[j ] = sum( xmm1 );
719  y[j+1UL] = sum( xmm2 );
720  y[j+2UL] = sum( xmm3 );
721  y[j+3UL] = sum( xmm4 );
722  }
723  for( ; (j+3UL) <= N; j+=3UL ) {
724  IntrinsicType xmm1, xmm2, xmm3;
725  for( size_t i=0UL; i<M; i+=IT::size ) {
726  const IntrinsicType x1( x.load(i) );
727  xmm1 = xmm1 + x1 * A.load(i,j );
728  xmm2 = xmm2 + x1 * A.load(i,j+1UL);
729  xmm3 = xmm3 + x1 * A.load(i,j+2UL);
730  }
731  y[j ] = sum( xmm1 );
732  y[j+1UL] = sum( xmm2 );
733  y[j+2UL] = sum( xmm3 );
734  }
735  for( ; (j+2UL) <= N; j+=2UL ) {
736  IntrinsicType xmm1, xmm2;
737  for( size_t i=0UL; i<M; i+=IT::size ) {
738  const IntrinsicType x1( x.load(i) );
739  xmm1 = xmm1 + x1 * A.load(i,j );
740  xmm2 = xmm2 + x1 * A.load(i,j+1UL);
741  }
742  y[j ] = sum( xmm1 );
743  y[j+1UL] = sum( xmm2 );
744  }
745  if( j < N ) {
746  IntrinsicType xmm1;
747  for( size_t i=0UL; i<M; i+=IT::size ) {
748  xmm1 = xmm1 + A.load(i,j) * x.load(i);
749  }
750  y[j] = sum( xmm1 );
751  }
752  }
754  //**********************************************************************************************
755 
756  //**BLAS-based assignment to dense vectors (default)********************************************
770  template< typename VT1 // Type of the left-hand side target vector
771  , typename VT2 // Type of the left-hand side vector operand
772  , typename MT1 > // Type of the right-hand side matrix operand
773  static inline typename EnableIf< UseDefaultKernel<VT1,VT2,MT1> >::Type
774  selectBlasAssignKernel( VT1& y, const VT2& x, const MT1& A )
775  {
776  selectDefaultAssignKernel( y, x, A );
777  }
779  //**********************************************************************************************
780 
781  //**BLAS-based assignment to dense vectors (single precision)***********************************
782 #if BLAZE_BLAS_MODE
783 
796  template< typename VT1 // Type of the left-hand side target vector
797  , typename VT2 // Type of the left-hand side vector operand
798  , typename MT1 > // Type of the right-hand side matrix operand
799  static inline typename EnableIf< UseSinglePrecisionKernel<VT1,VT2,MT1> >::Type
800  selectBlasAssignKernel( VT1& y, const VT2& x, const MT1& A )
801  {
802  sgemv( y, x, A, 1.0F, 0.0F );
803  }
805 #endif
806  //**********************************************************************************************
807 
808  //**BLAS-based assignment to dense vectors (double precision)***********************************
809 #if BLAZE_BLAS_MODE
810 
823  template< typename VT1 // Type of the left-hand side target vector
824  , typename VT2 // Type of the left-hand side vector operand
825  , typename MT1 > // Type of the right-hand side matrix operand
826  static inline typename EnableIf< UseDoublePrecisionKernel<VT1,VT2,MT1> >::Type
827  selectBlasAssignKernel( VT1& y, const VT2& x, const MT1& A )
828  {
829  dgemv( y, x, A, 1.0, 0.0 );
830  }
832 #endif
833  //**********************************************************************************************
834 
835  //**BLAS-based assignment to dense vectors (single precision complex)***************************
836 #if BLAZE_BLAS_MODE
837 
850  template< typename VT1 // Type of the left-hand side target vector
851  , typename VT2 // Type of the left-hand side vector operand
852  , typename MT1 > // Type of the right-hand side matrix operand
853  static inline typename EnableIf< UseSinglePrecisionComplexKernel<VT1,VT2,MT1> >::Type
854  selectBlasAssignKernel( VT1& y, const VT2& x, const MT1& A )
855  {
856  cgemv( y, x, A, complex<float>( 1.0F, 0.0F ), complex<float>( 0.0F, 0.0F ) );
857  }
859 #endif
860  //**********************************************************************************************
861 
862  //**BLAS-based assignment to dense vectors (double precision complex)***************************
863 #if BLAZE_BLAS_MODE
864 
877  template< typename VT1 // Type of the left-hand side target vector
878  , typename VT2 // Type of the left-hand side vector operand
879  , typename MT1 > // Type of the right-hand side matrix operand
880  static inline typename EnableIf< UseDoublePrecisionComplexKernel<VT1,VT2,MT1> >::Type
881  selectBlasAssignKernel( VT1& y, const VT2& x, const MT1& A )
882  {
883  zgemv( y, x, A, complex<double>( 1.0, 0.0 ), complex<double>( 0.0, 0.0 ) );
884  }
886 #endif
887  //**********************************************************************************************
888 
889  //**Assignment to sparse vectors****************************************************************
902  template< typename VT1 > // Type of the target sparse vector
903  friend inline void assign( SparseVector<VT1,true>& lhs, const TDVecTDMatMultExpr& rhs )
904  {
906 
910 
911  BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
912 
913  const ResultType tmp( serial( rhs ) );
914  assign( ~lhs, tmp );
915  }
917  //**********************************************************************************************
918 
919  //**Addition assignment to dense vectors********************************************************
932  template< typename VT1 > // Type of the target dense vector
933  friend inline void addAssign( DenseVector<VT1,true>& lhs, const TDVecTDMatMultExpr& rhs )
934  {
936 
937  BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
938 
939  if( rhs.mat_.rows() == 0UL || rhs.mat_.columns() == 0UL ) {
940  return;
941  }
942 
943  LT x( serial( rhs.vec_ ) ); // Evaluation of the left-hand side dense vector operand
944  RT A( serial( rhs.mat_ ) ); // Evaluation of the right-hand side dense matrix operand
945 
946  BLAZE_INTERNAL_ASSERT( x.size() == rhs.vec_.size() , "Invalid vector size" );
947  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.mat_.rows() , "Invalid number of rows" );
948  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.mat_.columns(), "Invalid number of columns" );
949  BLAZE_INTERNAL_ASSERT( A.columns() == (~lhs).size() , "Invalid vector size" );
950 
951  TDVecTDMatMultExpr::selectAddAssignKernel( ~lhs, x, A );
952  }
954  //**********************************************************************************************
955 
956  //**Addition assignment to dense vectors (kernel selection)*************************************
967  template< typename VT1 // Type of the left-hand side target vector
968  , typename VT2 // Type of the left-hand side vector operand
969  , typename MT1 > // Type of the right-hand side matrix operand
970  static inline void selectAddAssignKernel( VT1& y, const VT2& x, const MT1& A )
971  {
972  if( ( IsComputation<MT>::value && !evaluateMatrix ) ||
973  ( A.rows() * A.columns() < TDVECTDMATMULT_THRESHOLD ) )
974  TDVecTDMatMultExpr::selectDefaultAddAssignKernel( y, x, A );
975  else
976  TDVecTDMatMultExpr::selectBlasAddAssignKernel( y, x, A );
977  }
979  //**********************************************************************************************
980 
981  //**Default addition assignment to dense vectors************************************************
995  template< typename VT1 // Type of the left-hand side target vector
996  , typename VT2 // Type of the left-hand side vector operand
997  , typename MT1 > // Type of the right-hand side matrix operand
998  static inline typename DisableIf< UseVectorizedDefaultKernel<VT1,VT2,MT1> >::Type
999  selectDefaultAddAssignKernel( VT1& y, const VT2& x, const MT1& A )
1000  {
1001  y.addAssign( x * A );
1002  }
1004  //**********************************************************************************************
1005 
1006  //**Vectorized default addition assignment to dense vectors*************************************
1020  template< typename VT1 // Type of the left-hand side target vector
1021  , typename VT2 // Type of the left-hand side vector operand
1022  , typename MT1 > // Type of the right-hand side matrix operand
1023  static inline typename EnableIf< UseVectorizedDefaultKernel<VT1,VT2,MT1> >::Type
1024  selectDefaultAddAssignKernel( VT1& y, const VT2& x, const MT1& A )
1025  {
1026  typedef IntrinsicTrait<ElementType> IT;
1027 
1028  const size_t M( A.rows() );
1029  const size_t N( A.columns() );
1030 
1031  size_t j( 0UL );
1032 
1033  for( ; (j+8UL) <= N; j+=8UL ) {
1034  IntrinsicType xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7, xmm8;
1035  for( size_t i=0UL; i<M; i+=IT::size ) {
1036  const IntrinsicType x1( x.load(i) );
1037  xmm1 = xmm1 + x1 * A.load(i,j );
1038  xmm2 = xmm2 + x1 * A.load(i,j+1UL);
1039  xmm3 = xmm3 + x1 * A.load(i,j+2UL);
1040  xmm4 = xmm4 + x1 * A.load(i,j+3UL);
1041  xmm5 = xmm5 + x1 * A.load(i,j+4UL);
1042  xmm6 = xmm6 + x1 * A.load(i,j+5UL);
1043  xmm7 = xmm7 + x1 * A.load(i,j+6UL);
1044  xmm8 = xmm8 + x1 * A.load(i,j+7UL);
1045  }
1046  y[j ] += sum( xmm1 );
1047  y[j+1UL] += sum( xmm2 );
1048  y[j+2UL] += sum( xmm3 );
1049  y[j+3UL] += sum( xmm4 );
1050  y[j+4UL] += sum( xmm5 );
1051  y[j+5UL] += sum( xmm6 );
1052  y[j+6UL] += sum( xmm7 );
1053  y[j+7UL] += sum( xmm8 );
1054  }
1055  for( ; (j+4UL) <= N; j+=4UL ) {
1056  IntrinsicType xmm1, xmm2, xmm3, xmm4;
1057  for( size_t i=0UL; i<M; i+=IT::size ) {
1058  const IntrinsicType x1( x.load(i) );
1059  xmm1 = xmm1 + x1 * A.load(i,j );
1060  xmm2 = xmm2 + x1 * A.load(i,j+1UL);
1061  xmm3 = xmm3 + x1 * A.load(i,j+2UL);
1062  xmm4 = xmm4 + x1 * A.load(i,j+3UL);
1063  }
1064  y[j ] += sum( xmm1 );
1065  y[j+1UL] += sum( xmm2 );
1066  y[j+2UL] += sum( xmm3 );
1067  y[j+3UL] += sum( xmm4 );
1068  }
1069  for( ; (j+3UL) <= N; j+=3UL ) {
1070  IntrinsicType xmm1, xmm2, xmm3;
1071  for( size_t i=0UL; i<M; i+=IT::size ) {
1072  const IntrinsicType x1( x.load(i) );
1073  xmm1 = xmm1 + x1 * A.load(i,j );
1074  xmm2 = xmm2 + x1 * A.load(i,j+1UL);
1075  xmm3 = xmm3 + x1 * A.load(i,j+2UL);
1076  }
1077  y[j ] += sum( xmm1 );
1078  y[j+1UL] += sum( xmm2 );
1079  y[j+2UL] += sum( xmm3 );
1080  }
1081  for( ; (j+2UL) <= N; j+=2UL ) {
1082  IntrinsicType xmm1, xmm2;
1083  for( size_t i=0UL; i<M; i+=IT::size ) {
1084  const IntrinsicType x1( x.load(i) );
1085  xmm1 = xmm1 + x1 * A.load(i,j );
1086  xmm2 = xmm2 + x1 * A.load(i,j+1UL);
1087  }
1088  y[j ] += sum( xmm1 );
1089  y[j+1UL] += sum( xmm2 );
1090  }
1091  if( j < N ) {
1092  IntrinsicType xmm1;
1093  for( size_t i=0UL; i<M; i+=IT::size ) {
1094  xmm1 = xmm1 + A.load(i,j) * x.load(i);
1095  }
1096  y[j] += sum( xmm1 );
1097  }
1098  }
1100  //**********************************************************************************************
1101 
1102  //**BLAS-based addition assignment to dense vectors (default)***********************************
1116  template< typename VT1 // Type of the left-hand side target vector
1117  , typename VT2 // Type of the left-hand side vector operand
1118  , typename MT1 > // Type of the right-hand side matrix operand
1119  static inline typename EnableIf< UseDefaultKernel<VT1,VT2,MT1> >::Type
1120  selectBlasAddAssignKernel( VT1& y, const VT2& x, const MT1& A )
1121  {
1122  selectDefaultAddAssignKernel( y, x, A );
1123  }
1125  //**********************************************************************************************
1126 
1127  //**BLAS-based addition assignment to dense vectors (single precision)**************************
1128 #if BLAZE_BLAS_MODE
1129 
1142  template< typename VT1 // Type of the left-hand side target vector
1143  , typename VT2 // Type of the left-hand side vector operand
1144  , typename MT1 > // Type of the right-hand side matrix operand
1145  static inline typename EnableIf< UseSinglePrecisionKernel<VT1,VT2,MT1> >::Type
1146  selectBlasAddAssignKernel( VT1& y, const VT2& x, const MT1& A )
1147  {
1148  sgemv( y, x, A, 1.0F, 1.0F );
1149  }
1151 #endif
1152  //**********************************************************************************************
1153 
1154  //**BLAS-based addition assignment to dense vectors (double precision)**************************
1155 #if BLAZE_BLAS_MODE
1156 
1169  template< typename VT1 // Type of the left-hand side target vector
1170  , typename VT2 // Type of the left-hand side vector operand
1171  , typename MT1 > // Type of the right-hand side matrix operand
1172  static inline typename EnableIf< UseDoublePrecisionKernel<VT1,VT2,MT1> >::Type
1173  selectBlasAddAssignKernel( VT1& y, const VT2& x, const MT1& A )
1174  {
1175  dgemv( y, x, A, 1.0, 1.0 );
1176  }
1178 #endif
1179  //**********************************************************************************************
1180 
1181  //**BLAS-based addition assignment to dense vectors (single precision complex)******************
1182 #if BLAZE_BLAS_MODE
1183 
1196  template< typename VT1 // Type of the left-hand side target vector
1197  , typename VT2 // Type of the left-hand side vector operand
1198  , typename MT1 > // Type of the right-hand side matrix operand
1199  static inline typename EnableIf< UseSinglePrecisionComplexKernel<VT1,VT2,MT1> >::Type
1200  selectBlasAddAssignKernel( VT1& y, const VT2& x, const MT1& A )
1201  {
1202  cgemv( y, x, A, complex<float>( 1.0F, 0.0F ), complex<float>( 1.0F, 0.0F ) );
1203  }
1205 #endif
1206  //**********************************************************************************************
1207 
1208  //**BLAS-based addition assignment to dense vectors (double precision complex)******************
1209 #if BLAZE_BLAS_MODE
1210 
1223  template< typename VT1 // Type of the left-hand side target vector
1224  , typename VT2 // Type of the left-hand side vector operand
1225  , typename MT1 > // Type of the right-hand side matrix operand
1226  static inline typename EnableIf< UseDoublePrecisionComplexKernel<VT1,VT2,MT1> >::Type
1227  selectBlasAddAssignKernel( VT1& y, const VT2& x, const MT1& A )
1228  {
1229  zgemv( y, x, A, complex<double>( 1.0, 0.0 ), complex<double>( 1.0, 0.0 ) );
1230  }
1232 #endif
1233  //**********************************************************************************************
1234 
1235  //**Addition assignment to sparse vectors*******************************************************
1236  // No special implementation for the addition assignment to sparse vectors.
1237  //**********************************************************************************************
1238 
1239  //**Subtraction assignment to dense vectors*****************************************************
1252  template< typename VT1 > // Type of the target dense vector
1253  friend inline void subAssign( DenseVector<VT1,true>& lhs, const TDVecTDMatMultExpr& rhs )
1254  {
1256 
1257  BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
1258 
1259  if( rhs.mat_.rows() == 0UL || rhs.mat_.columns() == 0UL ) {
1260  return;
1261  }
1262 
1263  LT x( serial( rhs.vec_ ) ); // Evaluation of the left-hand side dense vector operand
1264  RT A( serial( rhs.mat_ ) ); // Evaluation of the right-hand side dense matrix operand
1265 
1266  BLAZE_INTERNAL_ASSERT( x.size() == rhs.vec_.size() , "Invalid vector size" );
1267  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.mat_.rows() , "Invalid number of rows" );
1268  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.mat_.columns(), "Invalid number of columns" );
1269  BLAZE_INTERNAL_ASSERT( A.columns() == (~lhs).size() , "Invalid vector size" );
1270 
1271  TDVecTDMatMultExpr::selectSubAssignKernel( ~lhs, x, A );
1272  }
1274  //**********************************************************************************************
1275 
1276  //**Subtraction assignment to dense vectors (kernel selection)**********************************
1287  template< typename VT1 // Type of the left-hand side target vector
1288  , typename VT2 // Type of the left-hand side vector operand
1289  , typename MT1 > // Type of the right-hand side matrix operand
1290  static inline void selectSubAssignKernel( VT1& y, const VT2& x, const MT1& A )
1291  {
1292  if( ( IsComputation<MT>::value && !evaluateMatrix ) ||
1293  ( A.rows() * A.columns() < TDVECTDMATMULT_THRESHOLD ) )
1294  TDVecTDMatMultExpr::selectDefaultSubAssignKernel( y, x, A );
1295  else
1296  TDVecTDMatMultExpr::selectBlasSubAssignKernel( y, x, A );
1297  }
1299  //**********************************************************************************************
1300 
1301  //**Default subtraction assignment to dense vectors*********************************************
1315  template< typename VT1 // Type of the left-hand side target vector
1316  , typename VT2 // Type of the left-hand side vector operand
1317  , typename MT1 > // Type of the right-hand side matrix operand
1318  static inline typename DisableIf< UseVectorizedDefaultKernel<VT1,VT2,MT1> >::Type
1319  selectDefaultSubAssignKernel( VT1& y, const VT2& x, const MT1& A )
1320  {
1321  y.subAssign( x * A );
1322  }
1324  //**********************************************************************************************
1325 
1326  //**Vectorized default subtraction assignment to dense vectors**********************************
1340  template< typename VT1 // Type of the left-hand side target vector
1341  , typename VT2 // Type of the left-hand side vector operand
1342  , typename MT1 > // Type of the right-hand side matrix operand
1343  static inline typename EnableIf< UseVectorizedDefaultKernel<VT1,VT2,MT1> >::Type
1344  selectDefaultSubAssignKernel( VT1& y, const VT2& x, const MT1& A )
1345  {
1346  typedef IntrinsicTrait<ElementType> IT;
1347 
1348  const size_t M( A.rows() );
1349  const size_t N( A.columns() );
1350 
1351  size_t j( 0UL );
1352 
1353  for( ; (j+8UL) <= N; j+=8UL ) {
1354  IntrinsicType xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7, xmm8;
1355  for( size_t i=0UL; i<M; i+=IT::size ) {
1356  const IntrinsicType x1( x.load(i) );
1357  xmm1 = xmm1 + x1 * A.load(i,j );
1358  xmm2 = xmm2 + x1 * A.load(i,j+1UL);
1359  xmm3 = xmm3 + x1 * A.load(i,j+2UL);
1360  xmm4 = xmm4 + x1 * A.load(i,j+3UL);
1361  xmm5 = xmm5 + x1 * A.load(i,j+4UL);
1362  xmm6 = xmm6 + x1 * A.load(i,j+5UL);
1363  xmm7 = xmm7 + x1 * A.load(i,j+6UL);
1364  xmm8 = xmm8 + x1 * A.load(i,j+7UL);
1365  }
1366  y[j ] -= sum( xmm1 );
1367  y[j+1UL] -= sum( xmm2 );
1368  y[j+2UL] -= sum( xmm3 );
1369  y[j+3UL] -= sum( xmm4 );
1370  y[j+4UL] -= sum( xmm5 );
1371  y[j+5UL] -= sum( xmm6 );
1372  y[j+6UL] -= sum( xmm7 );
1373  y[j+7UL] -= sum( xmm8 );
1374  }
1375  for( ; (j+4UL) <= N; j+=4UL ) {
1376  IntrinsicType xmm1, xmm2, xmm3, xmm4;
1377  for( size_t i=0UL; i<M; i+=IT::size ) {
1378  const IntrinsicType x1( x.load(i) );
1379  xmm1 = xmm1 + x1 * A.load(i,j );
1380  xmm2 = xmm2 + x1 * A.load(i,j+1UL);
1381  xmm3 = xmm3 + x1 * A.load(i,j+2UL);
1382  xmm4 = xmm4 + x1 * A.load(i,j+3UL);
1383  }
1384  y[j ] -= sum( xmm1 );
1385  y[j+1UL] -= sum( xmm2 );
1386  y[j+2UL] -= sum( xmm3 );
1387  y[j+3UL] -= sum( xmm4 );
1388  }
1389  for( ; (j+3UL) <= N; j+=3UL ) {
1390  IntrinsicType xmm1, xmm2, xmm3;
1391  for( size_t i=0UL; i<M; i+=IT::size ) {
1392  const IntrinsicType x1( x.load(i) );
1393  xmm1 = xmm1 + x1 * A.load(i,j );
1394  xmm2 = xmm2 + x1 * A.load(i,j+1UL);
1395  xmm3 = xmm3 + x1 * A.load(i,j+2UL);
1396  }
1397  y[j ] -= sum( xmm1 );
1398  y[j+1UL] -= sum( xmm2 );
1399  y[j+2UL] -= sum( xmm3 );
1400  }
1401  for( ; (j+2UL) <= N; j+=2UL ) {
1402  IntrinsicType xmm1, xmm2;
1403  for( size_t i=0UL; i<M; i+=IT::size ) {
1404  const IntrinsicType x1( x.load(i) );
1405  xmm1 = xmm1 + x1 * A.load(i,j );
1406  xmm2 = xmm2 + x1 * A.load(i,j+1UL);
1407  }
1408  y[j ] -= sum( xmm1 );
1409  y[j+1UL] -= sum( xmm2 );
1410  }
1411  if( j < N ) {
1412  IntrinsicType xmm1;
1413  for( size_t i=0UL; i<M; i+=IT::size ) {
1414  xmm1 = xmm1 + A.load(i,j) * x.load(i);
1415  }
1416  y[j] -= sum( xmm1 );
1417  }
1418  }
1420  //**********************************************************************************************
1421 
1422  //**BLAS-based subtraction assignment to dense vectors (default)********************************
1436  template< typename VT1 // Type of the left-hand side target vector
1437  , typename VT2 // Type of the left-hand side vector operand
1438  , typename MT1 > // Type of the right-hand side matrix operand
1439  static inline typename EnableIf< UseDefaultKernel<VT1,VT2,MT1> >::Type
1440  selectBlasSubAssignKernel( VT1& y, const VT2& x, const MT1& A )
1441  {
1442  selectDefaultSubAssignKernel( y, x, A );
1443  }
1445  //**********************************************************************************************
1446 
1447  //**BLAS-based subtraction assignment to dense vectors (single precision)***********************
1448 #if BLAZE_BLAS_MODE
1449 
1462  template< typename VT1 // Type of the left-hand side target vector
1463  , typename VT2 // Type of the left-hand side vector operand
1464  , typename MT1 > // Type of the right-hand side matrix operand
1465  static inline typename EnableIf< UseSinglePrecisionKernel<VT1,VT2,MT1> >::Type
1466  selectBlasSubAssignKernel( VT1& y, const VT2& x, const MT1& A )
1467  {
1468  sgemv( y, x, A, -1.0F, 1.0F );
1469  }
1471 #endif
1472  //**********************************************************************************************
1473 
1474  //**BLAS-based subtraction assignment to dense vectors (double precision)***********************
1475 #if BLAZE_BLAS_MODE
1476 
1489  template< typename VT1 // Type of the left-hand side target vector
1490  , typename VT2 // Type of the left-hand side vector operand
1491  , typename MT1 > // Type of the right-hand side matrix operand
1492  static inline typename EnableIf< UseDoublePrecisionKernel<VT1,VT2,MT1> >::Type
1493  selectBlasSubAssignKernel( VT1& y, const VT2& x, const MT1& A )
1494  {
1495  dgemv( y, x, A, -1.0, 1.0 );
1496  }
1498 #endif
1499  //**********************************************************************************************
1500 
1501  //**BLAS-based subtraction assignment to dense vectors (single precision complex)***************
1502 #if BLAZE_BLAS_MODE
1503 
1516  template< typename VT1 // Type of the left-hand side target vector
1517  , typename VT2 // Type of the left-hand side vector operand
1518  , typename MT1 > // Type of the right-hand side matrix operand
1519  static inline typename EnableIf< UseSinglePrecisionComplexKernel<VT1,VT2,MT1> >::Type
1520  selectBlasSubAssignKernel( VT1& y, const VT2& x, const MT1& A )
1521  {
1522  cgemv( y, x, A, complex<float>( -1.0F, 0.0F ), complex<float>( 1.0F, 0.0F ) );
1523  }
1525 #endif
1526  //**********************************************************************************************
1527 
1528  //**BLAS-based subtraction assignment to dense vectors (double precision complex)***************
1529 #if BLAZE_BLAS_MODE
1530 
1543  template< typename VT1 // Type of the left-hand side target vector
1544  , typename VT2 // Type of the left-hand side vector operand
1545  , typename MT1 > // Type of the right-hand side matrix operand
1546  static inline typename EnableIf< UseDoublePrecisionComplexKernel<VT1,VT2,MT1> >::Type
1547  selectBlasSubAssignKernel( VT1& y, const VT2& x, const MT1& A )
1548  {
1549  zgemv( y, x, A, complex<double>( -1.0, 0.0 ), complex<double>( 1.0, 0.0 ) );
1550  }
1552 #endif
1553  //**********************************************************************************************
1554 
1555  //**Subtraction assignment to sparse vectors****************************************************
1556  // No special implementation for the subtraction assignment to sparse vectors.
1557  //**********************************************************************************************
1558 
1559  //**Multiplication assignment to dense vectors**************************************************
1572  template< typename VT1 > // Type of the target dense vector
1573  friend inline void multAssign( DenseVector<VT1,true>& lhs, const TDVecTDMatMultExpr& rhs )
1574  {
1576 
1580 
1581  BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
1582 
1583  const ResultType tmp( serial( rhs ) );
1584  multAssign( ~lhs, tmp );
1585  }
1587  //**********************************************************************************************
1588 
1589  //**Multiplication assignment to sparse vectors*************************************************
1590  // No special implementation for the multiplication assignment to sparse vectors.
1591  //**********************************************************************************************
1592 
1593  //**SMP assignment to dense vectors*************************************************************
1608  template< typename VT1 > // Type of the target dense vector
1609  friend inline typename EnableIf< UseSMPAssign<VT1> >::Type
1610  smpAssign( DenseVector<VT1,true>& lhs, const TDVecTDMatMultExpr& rhs )
1611  {
1613 
1614  BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
1615 
1616  if( rhs.mat_.rows() == 0UL ) {
1617  reset( ~lhs );
1618  return;
1619  }
1620  else if( rhs.mat_.columns() == 0UL ) {
1621  return;
1622  }
1623 
1624  LT x( rhs.vec_ ); // Evaluation of the left-hand side dense vector operand
1625  RT A( rhs.mat_ ); // Evaluation of the right-hand side dense matrix operand
1626 
1627  BLAZE_INTERNAL_ASSERT( x.size() == rhs.vec_.size() , "Invalid vector size" );
1628  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.mat_.rows() , "Invalid number of rows" );
1629  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.mat_.columns(), "Invalid number of columns" );
1630  BLAZE_INTERNAL_ASSERT( A.columns() == (~lhs).size() , "Invalid vector size" );
1631 
1632  smpAssign( ~lhs, x * A );
1633  }
1635  //**********************************************************************************************
1636 
1637  //**SMP assignment to sparse vectors************************************************************
1652  template< typename VT1 > // Type of the target sparse vector
1653  friend inline typename EnableIf< UseSMPAssign<VT1> >::Type
1654  smpAssign( SparseVector<VT1,true>& lhs, const TDVecTDMatMultExpr& rhs )
1655  {
1657 
1661 
1662  BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
1663 
1664  const ResultType tmp( rhs );
1665  smpAssign( ~lhs, tmp );
1666  }
1668  //**********************************************************************************************
1669 
1670  //**SMP addition assignment to dense vectors****************************************************
1685  template< typename VT1 > // Type of the target dense vector
1686  friend inline typename EnableIf< UseSMPAssign<VT1> >::Type
1687  smpAddAssign( DenseVector<VT1,true>& lhs, const TDVecTDMatMultExpr& rhs )
1688  {
1690 
1691  BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
1692 
1693  if( rhs.mat_.rows() == 0UL || rhs.mat_.columns() == 0UL ) {
1694  return;
1695  }
1696 
1697  LT x( rhs.vec_ ); // Evaluation of the left-hand side dense vector operand
1698  RT A( rhs.mat_ ); // Evaluation of the right-hand side dense matrix operand
1699 
1700  BLAZE_INTERNAL_ASSERT( x.size() == rhs.vec_.size() , "Invalid vector size" );
1701  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.mat_.rows() , "Invalid number of rows" );
1702  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.mat_.columns(), "Invalid number of columns" );
1703  BLAZE_INTERNAL_ASSERT( A.columns() == (~lhs).size() , "Invalid vector size" );
1704 
1705  smpAddAssign( ~lhs, x * A );
1706  }
1708  //**********************************************************************************************
1709 
1710  //**SMP addition assignment to sparse vectors***************************************************
1711  // No special implementation for the SMP addition assignment to sparse vectors.
1712  //**********************************************************************************************
1713 
1714  //**SMP subtraction assignment to dense vectors*************************************************
1729  template< typename VT1 > // Type of the target dense vector
1730  friend inline typename EnableIf< UseSMPAssign<VT1> >::Type
1731  smpSubAssign( DenseVector<VT1,true>& lhs, const TDVecTDMatMultExpr& rhs )
1732  {
1734 
1735  BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
1736 
1737  if( rhs.mat_.rows() == 0UL || rhs.mat_.columns() == 0UL ) {
1738  return;
1739  }
1740 
1741  LT x( rhs.vec_ ); // Evaluation of the left-hand side dense vector operand
1742  RT A( rhs.mat_ ); // Evaluation of the right-hand side dense matrix operand
1743 
1744  BLAZE_INTERNAL_ASSERT( x.size() == rhs.vec_.size() , "Invalid vector size" );
1745  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.mat_.rows() , "Invalid number of rows" );
1746  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.mat_.columns(), "Invalid number of columns" );
1747  BLAZE_INTERNAL_ASSERT( A.columns() == (~lhs).size() , "Invalid vector size" );
1748 
1749  smpSubAssign( ~lhs, x * A );
1750  }
1752  //**********************************************************************************************
1753 
1754  //**SMP subtraction assignment to sparse vectors************************************************
1755  // No special implementation for the SMP subtraction assignment to sparse vectors.
1756  //**********************************************************************************************
1757 
1758  //**SMP multiplication assignment to dense vectors**********************************************
1773  template< typename VT1 > // Type of the target dense vector
1774  friend inline typename EnableIf< UseSMPAssign<VT1> >::Type
1775  smpMultAssign( DenseVector<VT1,true>& lhs, const TDVecTDMatMultExpr& rhs )
1776  {
1778 
1782 
1783  BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
1784 
1785  const ResultType tmp( rhs );
1786  smpMultAssign( ~lhs, tmp );
1787  }
1789  //**********************************************************************************************
1790 
1791  //**SMP multiplication assignment to sparse vectors*********************************************
1792  // No special implementation for the SMP multiplication assignment to sparse vectors.
1793  //**********************************************************************************************
1794 
1795  //**Compile time checks*************************************************************************
1803  //**********************************************************************************************
1804 };
1805 //*************************************************************************************************
1806 
1807 
1808 
1809 
1810 //=================================================================================================
1811 //
1812 // DVECSCALARMULTEXPR SPECIALIZATION
1813 //
1814 //=================================================================================================
1815 
1816 //*************************************************************************************************
1824 template< typename VT // Type of the left-hand side dense vector
1825  , typename MT // Type of the right-hand side dense matrix
1826  , typename ST > // Type of the side scalar value
1827 class DVecScalarMultExpr< TDVecTDMatMultExpr<VT,MT>, ST, true >
1828  : public DenseVector< DVecScalarMultExpr< TDVecTDMatMultExpr<VT,MT>, ST, true >, true >
1829  , private VecScalarMultExpr
1830  , private Computation
1831 {
1832  private:
1833  //**Type definitions****************************************************************************
1834  typedef TDVecTDMatMultExpr<VT,MT> VMM;
1835  typedef typename VMM::ResultType RES;
1836  typedef typename VT::ResultType VRT;
1837  typedef typename MT::ResultType MRT;
1838  typedef typename VRT::ElementType VET;
1839  typedef typename MRT::ElementType MET;
1840  typedef typename VT::CompositeType VCT;
1841  typedef typename MT::CompositeType MCT;
1842  //**********************************************************************************************
1843 
1844  //**********************************************************************************************
1846  enum { evaluateVector = IsComputation<VT>::value || RequiresEvaluation<VT>::value };
1847  //**********************************************************************************************
1848 
1849  //**********************************************************************************************
1851  enum { evaluateMatrix = ( IsComputation<MT>::value && IsSame<MET,VET>::value &&
1852  IsBlasCompatible<MET>::value ) || RequiresEvaluation<MT>::value };
1853  //**********************************************************************************************
1854 
1855  //**********************************************************************************************
1857 
1860  template< typename T1 >
1861  struct UseSMPAssign {
1862  enum { value = T1::smpAssignable && ( evaluateVector || evaluateMatrix ) };
1863  };
1864  //**********************************************************************************************
1865 
1866  //**********************************************************************************************
1868 
1871  template< typename T1, typename T2, typename T3, typename T4 >
1872  struct UseSinglePrecisionKernel {
1873  enum { value = T1::vectorizable && T2::vectorizable && T3::vectorizable &&
1874  IsFloat<typename T1::ElementType>::value &&
1875  IsFloat<typename T2::ElementType>::value &&
1876  IsFloat<typename T3::ElementType>::value &&
1877  !IsComplex<T4>::value };
1878  };
1879  //**********************************************************************************************
1880 
1881  //**********************************************************************************************
1883 
1886  template< typename T1, typename T2, typename T3, typename T4 >
1887  struct UseDoublePrecisionKernel {
1888  enum { value = T1::vectorizable && T2::vectorizable && T3::vectorizable &&
1889  IsDouble<typename T1::ElementType>::value &&
1890  IsDouble<typename T2::ElementType>::value &&
1891  IsDouble<typename T3::ElementType>::value &&
1892  !IsComplex<T4>::value };
1893  };
1894  //**********************************************************************************************
1895 
1896  //**********************************************************************************************
1898 
1901  template< typename T1, typename T2, typename T3 >
1902  struct UseSinglePrecisionComplexKernel {
1903  typedef complex<float> Type;
1904  enum { value = T1::vectorizable && T2::vectorizable && T3::vectorizable &&
1905  IsSame<typename T1::ElementType,Type>::value &&
1906  IsSame<typename T2::ElementType,Type>::value &&
1907  IsSame<typename T3::ElementType,Type>::value };
1908  };
1909  //**********************************************************************************************
1910 
1911  //**********************************************************************************************
1913 
1916  template< typename T1, typename T2, typename T3 >
1917  struct UseDoublePrecisionComplexKernel {
1918  typedef complex<double> Type;
1919  enum { value = T1::vectorizable && T2::vectorizable && T3::vectorizable &&
1920  IsSame<typename T1::ElementType,Type>::value &&
1921  IsSame<typename T2::ElementType,Type>::value &&
1922  IsSame<typename T3::ElementType,Type>::value };
1923  };
1924  //**********************************************************************************************
1925 
1926  //**********************************************************************************************
1928 
1930  template< typename T1, typename T2, typename T3, typename T4 >
1931  struct UseDefaultKernel {
1932  enum { value = !BLAZE_BLAS_MODE || ( !UseSinglePrecisionKernel<T1,T2,T3,T4>::value &&
1933  !UseDoublePrecisionKernel<T1,T2,T3,T4>::value &&
1934  !UseSinglePrecisionComplexKernel<T1,T2,T3>::value &&
1935  !UseDoublePrecisionComplexKernel<T1,T2,T3>::value ) };
1936  };
1937  //**********************************************************************************************
1938 
1939  //**********************************************************************************************
1941 
1944  template< typename T1, typename T2, typename T3, typename T4 >
1945  struct UseVectorizedDefaultKernel {
1946  enum { value = T1::vectorizable && T2::vectorizable && T3::vectorizable &&
1947  IsSame<typename T1::ElementType,typename T2::ElementType>::value &&
1948  IsSame<typename T1::ElementType,typename T3::ElementType>::value &&
1949  IsSame<typename T1::ElementType,T4>::value &&
1950  IntrinsicTrait<typename T1::ElementType>::addition &&
1951  IntrinsicTrait<typename T1::ElementType>::multiplication };
1952  };
1953  //**********************************************************************************************
1954 
1955  public:
1956  //**Type definitions****************************************************************************
1957  typedef DVecScalarMultExpr<VMM,ST,true> This;
1958  typedef typename MultTrait<RES,ST>::Type ResultType;
1959  typedef typename ResultType::TransposeType TransposeType;
1960  typedef typename ResultType::ElementType ElementType;
1961  typedef typename IntrinsicTrait<ElementType>::Type IntrinsicType;
1962  typedef const ElementType ReturnType;
1963  typedef const ResultType CompositeType;
1964 
1966  typedef const TDVecTDMatMultExpr<VT,MT> LeftOperand;
1967 
1969  typedef ST RightOperand;
1970 
1972  typedef typename SelectType< evaluateVector, const VRT, VCT >::Type LT;
1973 
1975  typedef typename SelectType< evaluateMatrix, const MRT, MCT >::Type RT;
1976  //**********************************************************************************************
1977 
1978  //**Compilation flags***************************************************************************
1980  enum { vectorizable = VT::vectorizable && MT::vectorizable &&
1981  IsSame<VET,MET>::value &&
1982  IsSame<VET,ST>::value &&
1983  IntrinsicTrait<VET>::addition &&
1984  IntrinsicTrait<VET>::multiplication };
1985 
1987  enum { smpAssignable = !evaluateVector && VT::smpAssignable &&
1988  !evaluateMatrix && MT::smpAssignable };
1989  //**********************************************************************************************
1990 
1991  //**Constructor*********************************************************************************
1997  explicit inline DVecScalarMultExpr( const VMM& vector, ST scalar )
1998  : vector_( vector ) // Left-hand side dense vector of the multiplication expression
1999  , scalar_( scalar ) // Right-hand side scalar of the multiplication expression
2000  {}
2001  //**********************************************************************************************
2002 
2003  //**Subscript operator**************************************************************************
2009  inline ReturnType operator[]( size_t index ) const {
2010  BLAZE_INTERNAL_ASSERT( index < vector_.size(), "Invalid vector access index" );
2011  return vector_[index] * scalar_;
2012  }
2013  //**********************************************************************************************
2014 
2015  //**Size function*******************************************************************************
2020  inline size_t size() const {
2021  return vector_.size();
2022  }
2023  //**********************************************************************************************
2024 
2025  //**Left operand access*************************************************************************
2030  inline LeftOperand leftOperand() const {
2031  return vector_;
2032  }
2033  //**********************************************************************************************
2034 
2035  //**Right operand access************************************************************************
2040  inline RightOperand rightOperand() const {
2041  return scalar_;
2042  }
2043  //**********************************************************************************************
2044 
2045  //**********************************************************************************************
2051  template< typename T >
2052  inline bool canAlias( const T* alias ) const {
2053  return vector_.canAlias( alias );
2054  }
2055  //**********************************************************************************************
2056 
2057  //**********************************************************************************************
2063  template< typename T >
2064  inline bool isAliased( const T* alias ) const {
2065  return vector_.isAliased( alias );
2066  }
2067  //**********************************************************************************************
2068 
2069  //**********************************************************************************************
2074  inline bool isAligned() const {
2075  return vector_.isAligned();
2076  }
2077  //**********************************************************************************************
2078 
2079  //**********************************************************************************************
2084  inline bool canSMPAssign() const {
2085  typename VMM::RightOperand A( vector_.rightOperand() );
2086  return ( !BLAZE_BLAS_IS_PARALLEL ||
2087  ( IsComputation<MT>::value && !evaluateMatrix ) ||
2088  ( A.rows() * A.columns() < TDVECTDMATMULT_THRESHOLD ) ) &&
2090  }
2091  //**********************************************************************************************
2092 
2093  private:
2094  //**Member variables****************************************************************************
2095  LeftOperand vector_;
2096  RightOperand scalar_;
2097  //**********************************************************************************************
2098 
2099  //**BLAS kernel (single precision)*************************************************************
2100 #if BLAZE_BLAS_MODE
2101 
2115  template< typename VT1 // Type of the left-hand side target vector
2116  , typename VT2 // Type of the left-hand side vector operand
2117  , typename MT1 > // Type of the right-hand side matrix operand
2118  static inline void sgemv( VT1& y, const VT2& x, const MT1& A, float alpha, float beta )
2119  {
2120  using boost::numeric_cast;
2121 
2125 
2126  const int M ( numeric_cast<int>( A.rows() ) );
2127  const int N ( numeric_cast<int>( A.columns() ) );
2128  const int lda( numeric_cast<int>( A.spacing() ) );
2129 
2130  cblas_sgemv( CblasColMajor, CblasTrans, M, N, alpha,
2131  A.data(), lda, x.data(), 1, beta, y.data(), 1 );
2132  }
2133 #endif
2134  //**********************************************************************************************
2135 
2136  //**BLAS kernel (double precision)**************************************************************
2137 #if BLAZE_BLAS_MODE
2138 
2152  template< typename VT1 // Type of the left-hand side target vector
2153  , typename VT2 // Type of the left-hand side vector operand
2154  , typename MT1 > // Type of the right-hand side matrix operand
2155  static inline void dgemv( VT1& y, const VT2& x, const MT1& A, double alpha, double beta )
2156  {
2157  using boost::numeric_cast;
2158 
2162 
2163  const int M ( numeric_cast<int>( A.rows() ) );
2164  const int N ( numeric_cast<int>( A.columns() ) );
2165  const int lda( numeric_cast<int>( A.spacing() ) );
2166 
2167  cblas_dgemv( CblasColMajor, CblasTrans, M, N, alpha,
2168  A.data(), lda, x.data(), 1, beta, y.data(), 1 );
2169  }
2170 #endif
2171  //**********************************************************************************************
2172 
2173  //**BLAS kernel (single precision complex)******************************************************
2174 #if BLAZE_BLAS_MODE
2175 
2189  template< typename VT1 // Type of the left-hand side target vector
2190  , typename VT2 // Type of the left-hand side vector operand
2191  , typename MT1 > // Type of the right-hand side matrix operand
2192  static inline void cgemv( VT1& y, const VT2& x, const MT1& A,
2193  complex<float> alpha, complex<float> beta )
2194  {
2195  using boost::numeric_cast;
2196 
2200  BLAZE_CONSTRAINT_MUST_BE_FLOAT_TYPE ( typename VT1::ElementType::value_type );
2201  BLAZE_CONSTRAINT_MUST_BE_FLOAT_TYPE ( typename VT2::ElementType::value_type );
2202  BLAZE_CONSTRAINT_MUST_BE_FLOAT_TYPE ( typename MT1::ElementType::value_type );
2203 
2204  const int M ( numeric_cast<int>( A.rows() ) );
2205  const int N ( numeric_cast<int>( A.columns() ) );
2206  const int lda( numeric_cast<int>( A.spacing() ) );
2207 
2208  cblas_cgemv( CblasColMajor, CblasTrans, M, N, &alpha,
2209  A.data(), lda, x.data(), 1, &beta, y.data(), 1 );
2210  }
2211 #endif
2212  //**********************************************************************************************
2213 
2214  //**BLAS kernel (double precision complex)******************************************************
2215 #if BLAZE_BLAS_MODE
2216 
2230  template< typename VT1 // Type of the left-hand side target vector
2231  , typename VT2 // Type of the left-hand side vector operand
2232  , typename MT1 > // Type of the right-hand side matrix operand
2233  static inline void zgemv( VT1& y, const VT2& x, const MT1& A,
2234  complex<double> alpha, complex<double> beta )
2235  {
2236  using boost::numeric_cast;
2237 
2241  BLAZE_CONSTRAINT_MUST_BE_DOUBLE_TYPE ( typename VT1::ElementType::value_type );
2242  BLAZE_CONSTRAINT_MUST_BE_DOUBLE_TYPE ( typename VT2::ElementType::value_type );
2243  BLAZE_CONSTRAINT_MUST_BE_DOUBLE_TYPE ( typename MT1::ElementType::value_type );
2244 
2245  const int M ( numeric_cast<int>( A.rows() ) );
2246  const int N ( numeric_cast<int>( A.columns() ) );
2247  const int lda( numeric_cast<int>( A.spacing() ) );
2248 
2249  cblas_zgemv( CblasColMajor, CblasTrans, M, N, &alpha,
2250  A.data(), lda, x.data(), 1, &beta, y.data(), 1 );
2251  }
2252 #endif
2253  //**********************************************************************************************
2254 
2255  //**Assignment to dense vectors*****************************************************************
2267  template< typename VT1 // Type of the target dense vector
2268  , bool TF > // Transpose flag of the target dense vector
2269  friend inline void assign( DenseVector<VT1,TF>& lhs, const DVecScalarMultExpr& rhs )
2270  {
2272 
2273  BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
2274 
2275  typename VMM::LeftOperand left ( rhs.vector_.leftOperand() );
2276  typename VMM::RightOperand right( rhs.vector_.rightOperand() );
2277 
2278  if( right.rows() == 0UL ) {
2279  reset( ~lhs );
2280  return;
2281  }
2282  else if( right.columns() == 0UL ) {
2283  return;
2284  }
2285 
2286  LT x( serial( left ) ); // Evaluation of the left-hand side dense vector operand
2287  RT A( serial( right ) ); // Evaluation of the right-hand side dense matrix operand
2288 
2289  BLAZE_INTERNAL_ASSERT( x.size() == left.size() , "Invalid vector size" );
2290  BLAZE_INTERNAL_ASSERT( A.rows() == right.rows() , "Invalid number of rows" );
2291  BLAZE_INTERNAL_ASSERT( A.columns() == right.columns(), "Invalid number of columns" );
2292  BLAZE_INTERNAL_ASSERT( A.columns() == (~lhs).size() , "Invalid vector size" );
2293 
2294  DVecScalarMultExpr::selectAssignKernel( ~lhs, x, A, rhs.scalar_ );
2295  }
2296  //**********************************************************************************************
2297 
2298  //**Assignment to dense vectors (kernel selection)**********************************************
2309  template< typename VT1 // Type of the left-hand side target vector
2310  , typename VT2 // Type of the left-hand side vector operand
2311  , typename MT1 // Type of the right-hand side matrix operand
2312  , typename ST2 > // Type of the scalar value
2313  static inline void selectAssignKernel( VT1& y, const VT2& x, const MT1& A, ST2 scalar )
2314  {
2315  if( ( IsComputation<MT>::value && !evaluateMatrix ) ||
2316  ( A.rows() * A.columns() < TDVECTDMATMULT_THRESHOLD ) )
2317  DVecScalarMultExpr::selectDefaultAssignKernel( y, x, A, scalar );
2318  else
2319  DVecScalarMultExpr::selectBlasAssignKernel( y, x, A, scalar );
2320  }
2321  //**********************************************************************************************
2322 
2323  //**Default assignment to dense vectors*********************************************************
2337  template< typename VT1 // Type of the left-hand side target vector
2338  , typename VT2 // Type of the left-hand side vector operand
2339  , typename MT1 // Type of the right-hand side matrix operand
2340  , typename ST2 > // Type of the scalar value
2341  static inline typename DisableIf< UseVectorizedDefaultKernel<VT1,VT2,MT1,ST2> >::Type
2342  selectDefaultAssignKernel( VT1& y, const VT2& x, const MT1& A, ST2 scalar )
2343  {
2344  y.assign( x * A * scalar );
2345  }
2346  //**********************************************************************************************
2347 
2348  //**Vectorized default assignment to dense vectors**********************************************
2362  template< typename VT1 // Type of the left-hand side target vector
2363  , typename VT2 // Type of the left-hand side vector operand
2364  , typename MT1 // Type of the right-hand side matrix operand
2365  , typename ST2 > // Type of the scalar value
2366  static inline typename EnableIf< UseVectorizedDefaultKernel<VT1,VT2,MT1,ST2> >::Type
2367  selectDefaultAssignKernel( VT1& y, const VT2& x, const MT1& A, ST2 scalar )
2368  {
2369  typedef IntrinsicTrait<ElementType> IT;
2370 
2371  const size_t M( A.rows() );
2372  const size_t N( A.columns() );
2373 
2374  size_t j( 0UL );
2375 
2376  for( ; (j+8UL) <= N; j+=8UL ) {
2377  IntrinsicType xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7, xmm8;
2378  for( size_t i=0UL; i<M; i+=IT::size ) {
2379  const IntrinsicType x1( x.load(i) );
2380  xmm1 = xmm1 + x1 * A.load(i,j );
2381  xmm2 = xmm2 + x1 * A.load(i,j+1UL);
2382  xmm3 = xmm3 + x1 * A.load(i,j+2UL);
2383  xmm4 = xmm4 + x1 * A.load(i,j+3UL);
2384  xmm5 = xmm5 + x1 * A.load(i,j+4UL);
2385  xmm6 = xmm6 + x1 * A.load(i,j+5UL);
2386  xmm7 = xmm7 + x1 * A.load(i,j+6UL);
2387  xmm8 = xmm8 + x1 * A.load(i,j+7UL);
2388  }
2389  y[j ] = sum( xmm1 ) * scalar;
2390  y[j+1UL] = sum( xmm2 ) * scalar;
2391  y[j+2UL] = sum( xmm3 ) * scalar;
2392  y[j+3UL] = sum( xmm4 ) * scalar;
2393  y[j+4UL] = sum( xmm5 ) * scalar;
2394  y[j+5UL] = sum( xmm6 ) * scalar;
2395  y[j+6UL] = sum( xmm7 ) * scalar;
2396  y[j+7UL] = sum( xmm8 ) * scalar;
2397  }
2398  for( ; (j+4UL) <= N; j+=4UL ) {
2399  IntrinsicType xmm1, xmm2, xmm3, xmm4;
2400  for( size_t i=0UL; i<M; i+=IT::size ) {
2401  const IntrinsicType x1( x.load(i) );
2402  xmm1 = xmm1 + x1 * A.load(i,j );
2403  xmm2 = xmm2 + x1 * A.load(i,j+1UL);
2404  xmm3 = xmm3 + x1 * A.load(i,j+2UL);
2405  xmm4 = xmm4 + x1 * A.load(i,j+3UL);
2406  }
2407  y[j ] = sum( xmm1 ) * scalar;
2408  y[j+1UL] = sum( xmm2 ) * scalar;
2409  y[j+2UL] = sum( xmm3 ) * scalar;
2410  y[j+3UL] = sum( xmm4 ) * scalar;
2411  }
2412  for( ; (j+3UL) <= N; j+=3UL ) {
2413  IntrinsicType xmm1, xmm2, xmm3;
2414  for( size_t i=0UL; i<M; i+=IT::size ) {
2415  const IntrinsicType x1( x.load(i) );
2416  xmm1 = xmm1 + x1 * A.load(i,j );
2417  xmm2 = xmm2 + x1 * A.load(i,j+1UL);
2418  xmm3 = xmm3 + x1 * A.load(i,j+2UL);
2419  }
2420  y[j ] = sum( xmm1 ) * scalar;
2421  y[j+1UL] = sum( xmm2 ) * scalar;
2422  y[j+2UL] = sum( xmm3 ) * scalar;
2423  }
2424  for( ; (j+2UL) <= N; j+=2UL ) {
2425  IntrinsicType xmm1, xmm2;
2426  for( size_t i=0UL; i<M; i+=IT::size ) {
2427  const IntrinsicType x1( x.load(i) );
2428  xmm1 = xmm1 + x1 * A.load(i,j );
2429  xmm2 = xmm2 + x1 * A.load(i,j+1UL);
2430  }
2431  y[j ] = sum( xmm1 ) * scalar;
2432  y[j+1UL] = sum( xmm2 ) * scalar;
2433  }
2434  if( j < N ) {
2435  IntrinsicType xmm1;
2436  for( size_t i=0UL; i<M; i+=IT::size ) {
2437  xmm1 = xmm1 + A.load(i,j) * x.load(i);
2438  }
2439  y[j] = sum( xmm1 ) * scalar;
2440  }
2441  }
2442  //**********************************************************************************************
2443 
2444  //**BLAS-based assignment to dense vectors (default)********************************************
2457  template< typename VT1 // Type of the left-hand side target vector
2458  , typename VT2 // Type of the left-hand side vector operand
2459  , typename MT1 // Type of the right-hand side matrix operand
2460  , typename ST2 > // Type of the scalar value
2461  static inline typename EnableIf< UseDefaultKernel<VT1,VT2,MT1,ST2> >::Type
2462  selectBlasAssignKernel( VT1& y, const VT2& x, const MT1& A, ST2 scalar )
2463  {
2464  selectDefaultAssignKernel( y, x, A, scalar );
2465  }
2466  //**********************************************************************************************
2467 
2468  //**BLAS-based assignment to dense vectors (single precision)***********************************
2469 #if BLAZE_BLAS_MODE
2470 
2483  template< typename VT1 // Type of the left-hand side target vector
2484  , typename VT2 // Type of the left-hand side vector operand
2485  , typename MT1 // Type of the right-hand side matrix operand
2486  , typename ST2 > // Type of the scalar value
2487  static inline typename EnableIf< UseSinglePrecisionKernel<VT1,VT2,MT1,ST2> >::Type
2488  selectBlasAssignKernel( VT1& y, const VT2& x, const MT1& A, ST2 scalar )
2489  {
2490  sgemv( y, x, A, scalar, 0.0F );
2491  }
2492 #endif
2493  //**********************************************************************************************
2494 
2495  //**BLAS-based assignment to dense vectors (double precision)***********************************
2496 #if BLAZE_BLAS_MODE
2497 
2510  template< typename VT1 // Type of the left-hand side target vector
2511  , typename VT2 // Type of the left-hand side vector operand
2512  , typename MT1 // Type of the right-hand side matrix operand
2513  , typename ST2 > // Type of the scalar value
2514  static inline typename EnableIf< UseDoublePrecisionKernel<VT1,VT2,MT1,ST2> >::Type
2515  selectBlasAssignKernel( VT1& y, const VT2& x, const MT1& A, ST2 scalar )
2516  {
2517  dgemv( y, x, A, scalar, 0.0 );
2518  }
2519 #endif
2520  //**********************************************************************************************
2521 
2522  //**BLAS-based assignment to dense vectors (single precision complex)***************************
2523 #if BLAZE_BLAS_MODE
2524 
2538  template< typename VT1 // Type of the left-hand side target vector
2539  , typename VT2 // Type of the left-hand side vector operand
2540  , typename MT1 // Type of the right-hand side matrix operand
2541  , typename ST2 > // Type of the scalar value
2542  static inline typename EnableIf< UseSinglePrecisionComplexKernel<VT1,VT2,MT1> >::Type
2543  selectBlasAssignKernel( VT1& y, const VT2& x, const MT1& A, ST2 scalar )
2544  {
2545  cgemv( y, x, A, complex<float>( scalar, 0.0F ), complex<float>( 0.0F, 0.0F ) );
2546  }
2547 #endif
2548  //**********************************************************************************************
2549 
2550  //**BLAS-based assignment to dense vectors (double precision complex)***************************
2551 #if BLAZE_BLAS_MODE
2552 
2566  template< typename VT1 // Type of the left-hand side target vector
2567  , typename VT2 // Type of the left-hand side vector operand
2568  , typename MT1 // Type of the right-hand side matrix operand
2569  , typename ST2 > // Type of the scalar value
2570  static inline typename EnableIf< UseDoublePrecisionComplexKernel<VT1,VT2,MT1> >::Type
2571  selectBlasAssignKernel( VT1& y, const VT2& x, const MT1& A, ST2 scalar )
2572  {
2573  zgemv( y, x, A, complex<double>( scalar, 0.0 ), complex<double>( 0.0, 0.0 ) );
2574  }
2575 #endif
2576  //**********************************************************************************************
2577 
2578  //**Assignment to sparse vectors****************************************************************
2590  template< typename VT1 // Type of the target sparse vector
2591  , bool TF > // Transpose flag of the target sparse vector
2592  friend inline void assign( SparseVector<VT1,TF>& lhs, const DVecScalarMultExpr& rhs )
2593  {
2595 
2599 
2600  BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
2601 
2602  const ResultType tmp( serial( rhs ) );
2603  assign( ~lhs, tmp );
2604  }
2605  //**********************************************************************************************
2606 
2607  //**Addition assignment to dense vectors********************************************************
2619  template< typename VT1 // Type of the target dense vector
2620  , bool TF > // Transpose flag of the target dense vector
2621  friend inline void addAssign( DenseVector<VT1,TF>& lhs, const DVecScalarMultExpr& rhs )
2622  {
2624 
2625  BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
2626 
2627  typename VMM::LeftOperand left ( rhs.vector_.leftOperand() );
2628  typename VMM::RightOperand right( rhs.vector_.rightOperand() );
2629 
2630  if( right.rows() == 0UL || right.columns() == 0UL ) {
2631  return;
2632  }
2633 
2634  LT x( serial( left ) ); // Evaluation of the left-hand side dense vector operand
2635  RT A( serial( right ) ); // Evaluation of the right-hand side dense matrix operand
2636 
2637  BLAZE_INTERNAL_ASSERT( x.size() == left.size() , "Invalid vector size" );
2638  BLAZE_INTERNAL_ASSERT( A.rows() == right.rows() , "Invalid number of rows" );
2639  BLAZE_INTERNAL_ASSERT( A.columns() == right.columns(), "Invalid number of columns" );
2640  BLAZE_INTERNAL_ASSERT( A.columns() == (~lhs).size() , "Invalid vector size" );
2641 
2642  DVecScalarMultExpr::selectAddAssignKernel( ~lhs, x, A, rhs.scalar_ );
2643  }
2644  //**********************************************************************************************
2645 
2646  //**Addition assignment to dense vectors (kernel selection)*************************************
2657  template< typename VT1 // Type of the left-hand side target vector
2658  , typename VT2 // Type of the left-hand side vector operand
2659  , typename MT1 // Type of the right-hand side matrix operand
2660  , typename ST2 > // Type of the scalar value
2661  static inline void selectAddAssignKernel( VT1& y, const VT2& x, const MT1& A, ST2 scalar )
2662  {
2663  if( ( IsComputation<MT>::value && !evaluateMatrix ) ||
2664  ( A.rows() * A.columns() < TDVECDMATMULT_THRESHOLD ) )
2665  DVecScalarMultExpr::selectDefaultAddAssignKernel( y, x, A, scalar );
2666  else
2667  DVecScalarMultExpr::selectBlasAddAssignKernel( y, x, A, scalar );
2668  }
2669  //**********************************************************************************************
2670 
2671  //**Default addition assignment to dense vectors************************************************
2685  template< typename VT1 // Type of the left-hand side target vector
2686  , typename VT2 // Type of the left-hand side vector operand
2687  , typename MT1 // Type of the right-hand side matrix operand
2688  , typename ST2 > // Type of the scalar value
2689  static inline typename DisableIf< UseVectorizedDefaultKernel<VT1,VT2,MT1,ST2> >::Type
2690  selectDefaultAddAssignKernel( VT1& y, const VT2& x, const MT1& A, ST2 scalar )
2691  {
2692  y.addAssign( x * A * scalar );
2693  }
2694  //**********************************************************************************************
2695 
2696  //**Vectorized default addition assignment to dense vectors*************************************
2710  template< typename VT1 // Type of the left-hand side target vector
2711  , typename VT2 // Type of the left-hand side vector operand
2712  , typename MT1 // Type of the right-hand side matrix operand
2713  , typename ST2 > // Type of the scalar value
2714  static inline typename EnableIf< UseVectorizedDefaultKernel<VT1,VT2,MT1,ST2> >::Type
2715  selectDefaultAddAssignKernel( VT1& y, const VT2& x, const MT1& A, ST2 scalar )
2716  {
2717  typedef IntrinsicTrait<ElementType> IT;
2718 
2719  const size_t M( A.rows() );
2720  const size_t N( A.columns() );
2721 
2722  size_t j( 0UL );
2723 
2724  for( ; (j+8UL) <= N; j+=8UL ) {
2725  IntrinsicType xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7, xmm8;
2726  for( size_t i=0UL; i<M; i+=IT::size ) {
2727  const IntrinsicType x1( x.load(i) );
2728  xmm1 = xmm1 + x1 * A.load(i,j );
2729  xmm2 = xmm2 + x1 * A.load(i,j+1UL);
2730  xmm3 = xmm3 + x1 * A.load(i,j+2UL);
2731  xmm4 = xmm4 + x1 * A.load(i,j+3UL);
2732  xmm5 = xmm5 + x1 * A.load(i,j+4UL);
2733  xmm6 = xmm6 + x1 * A.load(i,j+5UL);
2734  xmm7 = xmm7 + x1 * A.load(i,j+6UL);
2735  xmm8 = xmm8 + x1 * A.load(i,j+7UL);
2736  }
2737  y[j ] += sum( xmm1 ) * scalar;
2738  y[j+1UL] += sum( xmm2 ) * scalar;
2739  y[j+2UL] += sum( xmm3 ) * scalar;
2740  y[j+3UL] += sum( xmm4 ) * scalar;
2741  y[j+4UL] += sum( xmm5 ) * scalar;
2742  y[j+5UL] += sum( xmm6 ) * scalar;
2743  y[j+6UL] += sum( xmm7 ) * scalar;
2744  y[j+7UL] += sum( xmm8 ) * scalar;
2745  }
2746  for( ; (j+4UL) <= N; j+=4UL ) {
2747  IntrinsicType xmm1, xmm2, xmm3, xmm4;
2748  for( size_t i=0UL; i<M; i+=IT::size ) {
2749  const IntrinsicType x1( x.load(i) );
2750  xmm1 = xmm1 + x1 * A.load(i,j );
2751  xmm2 = xmm2 + x1 * A.load(i,j+1UL);
2752  xmm3 = xmm3 + x1 * A.load(i,j+2UL);
2753  xmm4 = xmm4 + x1 * A.load(i,j+3UL);
2754  }
2755  y[j ] += sum( xmm1 ) * scalar;
2756  y[j+1UL] += sum( xmm2 ) * scalar;
2757  y[j+2UL] += sum( xmm3 ) * scalar;
2758  y[j+3UL] += sum( xmm4 ) * scalar;
2759  }
2760  for( ; (j+3UL) <= N; j+=3UL ) {
2761  IntrinsicType xmm1, xmm2, xmm3;
2762  for( size_t i=0UL; i<M; i+=IT::size ) {
2763  const IntrinsicType x1( x.load(i) );
2764  xmm1 = xmm1 + x1 * A.load(i,j );
2765  xmm2 = xmm2 + x1 * A.load(i,j+1UL);
2766  xmm3 = xmm3 + x1 * A.load(i,j+2UL);
2767  }
2768  y[j ] += sum( xmm1 ) * scalar;
2769  y[j+1UL] += sum( xmm2 ) * scalar;
2770  y[j+2UL] += sum( xmm3 ) * scalar;
2771  }
2772  for( ; (j+2UL) <= N; j+=2UL ) {
2773  IntrinsicType xmm1, xmm2;
2774  for( size_t i=0UL; i<M; i+=IT::size ) {
2775  const IntrinsicType x1( x.load(i) );
2776  xmm1 = xmm1 + x1 * A.load(i,j );
2777  xmm2 = xmm2 + x1 * A.load(i,j+1UL);
2778  }
2779  y[j ] += sum( xmm1 ) * scalar;
2780  y[j+1UL] += sum( xmm2 ) * scalar;
2781  }
2782  if( j < N ) {
2783  IntrinsicType xmm1;
2784  for( size_t i=0UL; i<M; i+=IT::size ) {
2785  xmm1 = xmm1 + A.load(i,j) * x.load(i);
2786  }
2787  y[j] += sum( xmm1 ) * scalar;
2788  }
2789  }
2790  //**********************************************************************************************
2791 
2792  //**BLAS-based addition assignment to dense vectors (default)***********************************
2806  template< typename VT1 // Type of the left-hand side target vector
2807  , typename VT2 // Type of the left-hand side vector operand
2808  , typename MT1 // Type of the right-hand side matrix operand
2809  , typename ST2 > // Type of the scalar value
2810  static inline typename EnableIf< UseDefaultKernel<VT1,VT2,MT1,ST2> >::Type
2811  selectBlasAddAssignKernel( VT1& y, const VT2& x, const MT1& A, ST2 scalar )
2812  {
2813  selectDefaultAddAssignKernel( y, x, A, scalar );
2814  }
2815  //**********************************************************************************************
2816 
2817  //**BLAS-based addition assignment to dense vectors (single precision)**************************
2818 #if BLAZE_BLAS_MODE
2819 
2832  template< typename VT1 // Type of the left-hand side target vector
2833  , typename VT2 // Type of the left-hand side vector operand
2834  , typename MT1 // Type of the right-hand side matrix operand
2835  , typename ST2 > // Type of the scalar value
2836  static inline typename EnableIf< UseSinglePrecisionKernel<VT1,VT2,MT1,ST2> >::Type
2837  selectBlasAddAssignKernel( VT1& y, const VT2& x, const MT1& A, ST2 scalar )
2838  {
2839  sgemv( y, x, A, scalar, 1.0F );
2840  }
2841 #endif
2842  //**********************************************************************************************
2843 
2844  //**BLAS-based addition assignment to dense vectors (double precision)**************************
2845 #if BLAZE_BLAS_MODE
2846 
2859  template< typename VT1 // Type of the left-hand side target vector
2860  , typename VT2 // Type of the left-hand side vector operand
2861  , typename MT1 // Type of the right-hand side matrix operand
2862  , typename ST2 > // Type of the scalar value
2863  static inline typename EnableIf< UseDoublePrecisionKernel<VT1,VT2,MT1,ST2> >::Type
2864  selectBlasAddAssignKernel( VT1& y, const VT2& x, const MT1& A, ST2 scalar )
2865  {
2866  dgemv( y, x, A, scalar, 1.0 );
2867  }
2868 #endif
2869  //**********************************************************************************************
2870 
2871  //**BLAS-based addition assignment to dense vectors (single precision complex)******************
2872 #if BLAZE_BLAS_MODE
2873 
2887  template< typename VT1 // Type of the left-hand side target vector
2888  , typename VT2 // Type of the left-hand side vector operand
2889  , typename MT1 // Type of the right-hand side matrix operand
2890  , typename ST2 > // Type of the scalar value
2891  static inline typename EnableIf< UseSinglePrecisionComplexKernel<VT1,VT2,MT1> >::Type
2892  selectBlasAddAssignKernel( VT1& y, const VT2& x, const MT1& A, ST2 scalar )
2893  {
2894  cgemv( y, x, A, complex<float>( scalar, 0.0F ), complex<float>( 1.0F, 0.0F ) );
2895  }
2896 #endif
2897  //**********************************************************************************************
2898 
2899  //**BLAS-based addition assignment to dense vectors (double precision complex)******************
2900 #if BLAZE_BLAS_MODE
2901 
2915  template< typename VT1 // Type of the left-hand side target vector
2916  , typename VT2 // Type of the left-hand side vector operand
2917  , typename MT1 // Type of the right-hand side matrix operand
2918  , typename ST2 > // Type of the scalar value
2919  static inline typename EnableIf< UseDoublePrecisionComplexKernel<VT1,VT2,MT1> >::Type
2920  selectBlasAddAssignKernel( VT1& y, const VT2& x, const MT1& A, ST2 scalar )
2921  {
2922  zgemv( y, x, A, complex<double>( scalar, 0.0 ), complex<double>( 1.0, 0.0 ) );
2923  }
2924 #endif
2925  //**********************************************************************************************
2926 
2927  //**Addition assignment to sparse vectors*******************************************************
2928  // No special implementation for the addition assignment to sparse vectors.
2929  //**********************************************************************************************
2930 
2931  //**Subtraction assignment to dense vectors*****************************************************
2943  template< typename VT1 // Type of the target dense vector
2944  , bool TF > // Transpose flag of the target dense vector
2945  friend inline void subAssign( DenseVector<VT1,TF>& lhs, const DVecScalarMultExpr& rhs )
2946  {
2948 
2949  BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
2950 
2951  typename VMM::LeftOperand left ( rhs.vector_.leftOperand() );
2952  typename VMM::RightOperand right( rhs.vector_.rightOperand() );
2953 
2954  if( right.rows() == 0UL || right.columns() == 0UL ) {
2955  return;
2956  }
2957 
2958  LT x( serial( left ) ); // Evaluation of the left-hand side dense vector operand
2959  RT A( serial( right ) ); // Evaluation of the right-hand side dense matrix operand
2960 
2961  BLAZE_INTERNAL_ASSERT( x.size() == left.size() , "Invalid vector size" );
2962  BLAZE_INTERNAL_ASSERT( A.rows() == right.rows() , "Invalid number of rows" );
2963  BLAZE_INTERNAL_ASSERT( A.columns() == right.columns(), "Invalid number of columns" );
2964  BLAZE_INTERNAL_ASSERT( A.columns() == (~lhs).size() , "Invalid vector size" );
2965 
2966  DVecScalarMultExpr::selectSubAssignKernel( ~lhs, x, A, rhs.scalar_ );
2967  }
2968  //**********************************************************************************************
2969 
2970  //**Subtraction assignment to dense vectors (kernel selection)**********************************
2981  template< typename VT1 // Type of the left-hand side target vector
2982  , typename VT2 // Type of the left-hand side vector operand
2983  , typename MT1 // Type of the right-hand side matrix operand
2984  , typename ST2 > // Type of the scalar value
2985  static inline void selectSubAssignKernel( VT1& y, const VT2& x, const MT1& A, ST2 scalar )
2986  {
2987  if( ( IsComputation<MT>::value && !evaluateMatrix ) ||
2988  ( A.rows() * A.columns() < TDVECDMATMULT_THRESHOLD ) )
2989  DVecScalarMultExpr::selectDefaultSubAssignKernel( y, x, A, scalar );
2990  else
2991  DVecScalarMultExpr::selectBlasSubAssignKernel( y, x, A, scalar );
2992  }
2993  //**********************************************************************************************
2994 
2995  //**Default subtraction assignment to dense vectors*********************************************
3009  template< typename VT1 // Type of the left-hand side target vector
3010  , typename VT2 // Type of the left-hand side vector operand
3011  , typename MT1 // Type of the right-hand side matrix operand
3012  , typename ST2 > // Type of the scalar value
3013  static inline typename DisableIf< UseVectorizedDefaultKernel<VT1,VT2,MT1,ST2> >::Type
3014  selectDefaultSubAssignKernel( VT1& y, const VT2& x, const MT1& A, ST2 scalar )
3015  {
3016  y.subAssign( x * A * scalar );
3017  }
3018  //**********************************************************************************************
3019 
3020  //**Vectorized default subtraction assignment to dense vectors**********************************
3034  template< typename VT1 // Type of the left-hand side target vector
3035  , typename VT2 // Type of the left-hand side vector operand
3036  , typename MT1 // Type of the right-hand side matrix operand
3037  , typename ST2 > // Type of the scalar value
3038  static inline typename EnableIf< UseVectorizedDefaultKernel<VT1,VT2,MT1,ST2> >::Type
3039  selectDefaultSubAssignKernel( VT1& y, const VT2& x, const MT1& A, ST2 scalar )
3040  {
3041  typedef IntrinsicTrait<ElementType> IT;
3042 
3043  const size_t M( A.rows() );
3044  const size_t N( A.columns() );
3045 
3046  size_t j( 0UL );
3047 
3048  for( ; (j+8UL) <= N; j+=8UL ) {
3049  IntrinsicType xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7, xmm8;
3050  for( size_t i=0UL; i<M; i+=IT::size ) {
3051  const IntrinsicType x1( x.load(i) );
3052  xmm1 = xmm1 + x1 * A.load(i,j );
3053  xmm2 = xmm2 + x1 * A.load(i,j+1UL);
3054  xmm3 = xmm3 + x1 * A.load(i,j+2UL);
3055  xmm4 = xmm4 + x1 * A.load(i,j+3UL);
3056  xmm5 = xmm5 + x1 * A.load(i,j+4UL);
3057  xmm6 = xmm6 + x1 * A.load(i,j+5UL);
3058  xmm7 = xmm7 + x1 * A.load(i,j+6UL);
3059  xmm8 = xmm8 + x1 * A.load(i,j+7UL);
3060  }
3061  y[j ] -= sum( xmm1 ) * scalar;
3062  y[j+1UL] -= sum( xmm2 ) * scalar;
3063  y[j+2UL] -= sum( xmm3 ) * scalar;
3064  y[j+3UL] -= sum( xmm4 ) * scalar;
3065  y[j+4UL] -= sum( xmm5 ) * scalar;
3066  y[j+5UL] -= sum( xmm6 ) * scalar;
3067  y[j+6UL] -= sum( xmm7 ) * scalar;
3068  y[j+7UL] -= sum( xmm8 ) * scalar;
3069  }
3070  for( ; (j+4UL) <= N; j+=4UL ) {
3071  IntrinsicType xmm1, xmm2, xmm3, xmm4;
3072  for( size_t i=0UL; i<M; i+=IT::size ) {
3073  const IntrinsicType x1( x.load(i) );
3074  xmm1 = xmm1 + x1 * A.load(i,j );
3075  xmm2 = xmm2 + x1 * A.load(i,j+1UL);
3076  xmm3 = xmm3 + x1 * A.load(i,j+2UL);
3077  xmm4 = xmm4 + x1 * A.load(i,j+3UL);
3078  }
3079  y[j ] -= sum( xmm1 ) * scalar;
3080  y[j+1UL] -= sum( xmm2 ) * scalar;
3081  y[j+2UL] -= sum( xmm3 ) * scalar;
3082  y[j+3UL] -= sum( xmm4 ) * scalar;
3083  }
3084  for( ; (j+3UL) <= N; j+=3UL ) {
3085  IntrinsicType xmm1, xmm2, xmm3;
3086  for( size_t i=0UL; i<M; i+=IT::size ) {
3087  const IntrinsicType x1( x.load(i) );
3088  xmm1 = xmm1 + x1 * A.load(i,j );
3089  xmm2 = xmm2 + x1 * A.load(i,j+1UL);
3090  xmm3 = xmm3 + x1 * A.load(i,j+2UL);
3091  }
3092  y[j ] -= sum( xmm1 ) * scalar;
3093  y[j+1UL] -= sum( xmm2 ) * scalar;
3094  y[j+2UL] -= sum( xmm3 ) * scalar;
3095  }
3096  for( ; (j+2UL) <= N; j+=2UL ) {
3097  IntrinsicType xmm1, xmm2;
3098  for( size_t i=0UL; i<M; i+=IT::size ) {
3099  const IntrinsicType x1( x.load(i) );
3100  xmm1 = xmm1 + x1 * A.load(i,j );
3101  xmm2 = xmm2 + x1 * A.load(i,j+1UL);
3102  }
3103  y[j ] -= sum( xmm1 ) * scalar;
3104  y[j+1UL] -= sum( xmm2 ) * scalar;
3105  }
3106  if( j < N ) {
3107  IntrinsicType xmm1;
3108  for( size_t i=0UL; i<M; i+=IT::size ) {
3109  xmm1 = xmm1 + A.load(i,j) * x.load(i);
3110  }
3111  y[j] -= sum( xmm1 ) * scalar;
3112  }
3113  }
3114  //**********************************************************************************************
3115 
3116  //**BLAS-based subtraction assignment to dense vectors (default)********************************
3131  template< typename VT1 // Type of the left-hand side target vector
3132  , typename VT2 // Type of the left-hand side vector operand
3133  , typename MT1 // Type of the right-hand side matrix operand
3134  , typename ST2 > // Type of the scalar value
3135  static inline typename EnableIf< UseDefaultKernel<VT1,VT2,MT1,ST2> >::Type
3136  selectBlasSubAssignKernel( VT1& y, const VT2& x, const MT1& A, ST2 scalar )
3137  {
3138  selectDefaultSubAssignKernel( y, x, A, scalar );
3139  }
3140  //**********************************************************************************************
3141 
3142  //**BLAS-based subtraction assignment to dense vectors (single precision)***********************
3143 #if BLAZE_BLAS_MODE
3144 
3157  template< typename VT1 // Type of the left-hand side target vector
3158  , typename VT2 // Type of the left-hand side vector operand
3159  , typename MT1 // Type of the right-hand side matrix operand
3160  , typename ST2 > // Type of the scalar value
3161  static inline typename EnableIf< UseSinglePrecisionKernel<VT1,VT2,MT1,ST2> >::Type
3162  selectBlasSubAssignKernel( VT1& y, const VT2& x, const MT1& A, ST2 scalar )
3163  {
3164  sgemv( y, x, A, -scalar, 1.0F );
3165  }
3166 #endif
3167  //**********************************************************************************************
3168 
3169  //**BLAS-based subtraction assignment to dense vectors (double precision)***********************
3170 #if BLAZE_BLAS_MODE
3171 
3184  template< typename VT1 // Type of the left-hand side target vector
3185  , typename VT2 // Type of the left-hand side vector operand
3186  , typename MT1 // Type of the right-hand side matrix operand
3187  , typename ST2 > // Type of the scalar value
3188  static inline typename EnableIf< UseDoublePrecisionKernel<VT1,VT2,MT1,ST2> >::Type
3189  selectBlasSubAssignKernel( VT1& y, const VT2& x, const MT1& A, ST2 scalar )
3190  {
3191  dgemv( y, x, A, -scalar, 1.0 );
3192  }
3193 #endif
3194  //**********************************************************************************************
3195 
3196  //**BLAS-based subtraction assignment to dense vectors (single precision complex)***************
3197 #if BLAZE_BLAS_MODE
3198 
3213  template< typename VT1 // Type of the left-hand side target vector
3214  , typename VT2 // Type of the left-hand side vector operand
3215  , typename MT1 // Type of the right-hand side matrix operand
3216  , typename ST2 > // Type of the scalar value
3217  static inline typename EnableIf< UseSinglePrecisionComplexKernel<VT1,VT2,MT1> >::Type
3218  selectBlasSubAssignKernel( VT1& y, const VT2& x, const MT1& A, ST2 scalar )
3219  {
3220  cgemv( y, x, A, complex<float>( -scalar, 0.0F ), complex<float>( 1.0F, 0.0F ) );
3221  }
3222 #endif
3223  //**********************************************************************************************
3224 
3225  //**BLAS-based subtraction assignment to dense vectors (double precision complex)***************
3226 #if BLAZE_BLAS_MODE
3227 
3242  template< typename VT1 // Type of the left-hand side target vector
3243  , typename VT2 // Type of the left-hand side vector operand
3244  , typename MT1 // Type of the right-hand side matrix operand
3245  , typename ST2 > // Type of the scalar value
3246  static inline typename EnableIf< UseDoublePrecisionComplexKernel<VT1,VT2,MT1> >::Type
3247  selectBlasSubAssignKernel( VT1& y, const VT2& x, const MT1& A, ST2 scalar )
3248  {
3249  zgemv( y, x, A, complex<double>( -scalar, 0.0 ), complex<double>( 1.0, 0.0 ) );
3250  }
3251 #endif
3252  //**********************************************************************************************
3253 
3254  //**Subtraction assignment to sparse vectors****************************************************
3255  // No special implementation for the subtraction assignment to sparse vectors.
3256  //**********************************************************************************************
3257 
3258  //**Multiplication assignment to dense vectors**************************************************
3270  template< typename VT1 // Type of the target dense vector
3271  , bool TF > // Transpose flag of the target dense vector
3272  friend inline void multAssign( DenseVector<VT1,TF>& lhs, const DVecScalarMultExpr& rhs )
3273  {
3275 
3279 
3280  BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
3281 
3282  const ResultType tmp( serial( rhs ) );
3283  multAssign( ~lhs, tmp );
3284  }
3285  //**********************************************************************************************
3286 
3287  //**Multiplication assignment to sparse vectors*************************************************
3288  // No special implementation for the multiplication assignment to sparse vectors.
3289  //**********************************************************************************************
3290 
3291  //**SMP assignment to dense vectors*************************************************************
3305  template< typename VT1 // Type of the target dense vector
3306  , bool TF > // Transpose flag of the target dense vector
3307  friend inline typename EnableIf< UseSMPAssign<VT1> >::Type
3308  smpAssign( DenseVector<VT1,TF>& lhs, const DVecScalarMultExpr& rhs )
3309  {
3311 
3312  BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
3313 
3314  typename VMM::LeftOperand left ( rhs.vector_.leftOperand() );
3315  typename VMM::RightOperand right( rhs.vector_.rightOperand() );
3316 
3317  if( right.rows() == 0UL ) {
3318  reset( ~lhs );
3319  return;
3320  }
3321  else if( right.columns() == 0UL ) {
3322  return;
3323  }
3324 
3325  LT x( left ); // Evaluation of the left-hand side dense vector operand
3326  RT A( right ); // Evaluation of the right-hand side dense matrix operand
3327 
3328  BLAZE_INTERNAL_ASSERT( x.size() == left.size() , "Invalid vector size" );
3329  BLAZE_INTERNAL_ASSERT( A.rows() == right.rows() , "Invalid number of rows" );
3330  BLAZE_INTERNAL_ASSERT( A.columns() == right.columns(), "Invalid number of columns" );
3331  BLAZE_INTERNAL_ASSERT( A.columns() == (~lhs).size() , "Invalid vector size" );
3332 
3333  smpAssign( ~lhs, x * A * rhs.scalar_ );
3334  }
3335  //**********************************************************************************************
3336 
3337  //**SMP assignment to sparse vectors************************************************************
3351  template< typename VT1 // Type of the target sparse vector
3352  , bool TF > // Transpose flag of the target sparse vector
3353  friend inline typename EnableIf< UseSMPAssign<VT1> >::Type
3354  smpAssign( SparseVector<VT1,TF>& lhs, const DVecScalarMultExpr& rhs )
3355  {
3357 
3361 
3362  BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
3363 
3364  const ResultType tmp( rhs );
3365  smpAssign( ~lhs, tmp );
3366  }
3367  //**********************************************************************************************
3368 
3369  //**SMP addition assignment to dense vectors****************************************************
3383  template< typename VT1 // Type of the target dense vector
3384  , bool TF > // Transpose flag of the target dense vector
3385  friend inline typename EnableIf< UseSMPAssign<VT1> >::Type
3386  smpAddAssign( DenseVector<VT1,TF>& lhs, const DVecScalarMultExpr& rhs )
3387  {
3389 
3390  BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
3391 
3392  typename VMM::LeftOperand left ( rhs.vector_.leftOperand() );
3393  typename VMM::RightOperand right( rhs.vector_.rightOperand() );
3394 
3395  if( right.rows() == 0UL || right.columns() == 0UL ) {
3396  return;
3397  }
3398 
3399  LT x( left ); // Evaluation of the left-hand side dense vector operand
3400  RT A( right ); // Evaluation of the right-hand side dense matrix operand
3401 
3402  BLAZE_INTERNAL_ASSERT( x.size() == left.size() , "Invalid vector size" );
3403  BLAZE_INTERNAL_ASSERT( A.rows() == right.rows() , "Invalid number of rows" );
3404  BLAZE_INTERNAL_ASSERT( A.columns() == right.columns(), "Invalid number of columns" );
3405  BLAZE_INTERNAL_ASSERT( A.columns() == (~lhs).size() , "Invalid vector size" );
3406 
3407  smpAddAssign( ~lhs, x * A * rhs.scalar_ );
3408  }
3409  //**********************************************************************************************
3410 
3411  //**SMP addition assignment to sparse vectors***************************************************
3412  // No special implementation for the SMP addition assignment to sparse vectors.
3413  //**********************************************************************************************
3414 
3415  //**SMP subtraction assignment to dense vectors*************************************************
3429  template< typename VT1 // Type of the target dense vector
3430  , bool TF > // Transpose flag of the target dense vector
3431  friend inline typename EnableIf< UseSMPAssign<VT1> >::Type
3432  smpSubAssign( DenseVector<VT1,TF>& lhs, const DVecScalarMultExpr& rhs )
3433  {
3435 
3436  BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
3437 
3438  typename VMM::LeftOperand left ( rhs.vector_.leftOperand() );
3439  typename VMM::RightOperand right( rhs.vector_.rightOperand() );
3440 
3441  if( right.rows() == 0UL || right.columns() == 0UL ) {
3442  return;
3443  }
3444 
3445  LT x( left ); // Evaluation of the left-hand side dense vector operand
3446  RT A( right ); // Evaluation of the right-hand side dense matrix operand
3447 
3448  BLAZE_INTERNAL_ASSERT( x.size() == left.size() , "Invalid vector size" );
3449  BLAZE_INTERNAL_ASSERT( A.rows() == right.rows() , "Invalid number of rows" );
3450  BLAZE_INTERNAL_ASSERT( A.columns() == right.columns(), "Invalid number of columns" );
3451  BLAZE_INTERNAL_ASSERT( A.columns() == (~lhs).size() , "Invalid vector size" );
3452 
3453  smpSubAssign( ~lhs, x * A * rhs.scalar_ );
3454  }
3455  //**********************************************************************************************
3456 
3457  //**SMP subtraction assignment to sparse vectors************************************************
3458  // No special implementation for the SMP subtraction assignment to sparse vectors.
3459  //**********************************************************************************************
3460 
3461  //**SMP multiplication assignment to dense vectors**********************************************
3475  template< typename VT1 // Type of the target dense vector
3476  , bool TF > // Transpose flag of the target dense vector
3477  friend inline typename EnableIf< UseSMPAssign<VT1> >::Type
3478  smpMultAssign( DenseVector<VT1,TF>& lhs, const DVecScalarMultExpr& rhs )
3479  {
3481 
3485 
3486  BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
3487 
3488  const ResultType tmp( rhs );
3489  smpMultAssign( ~lhs, tmp );
3490  }
3491  //**********************************************************************************************
3492 
3493  //**SMP multiplication assignment to sparse vectors*********************************************
3494  // No special implementation for the SMP multiplication assignment to sparse vectors.
3495  //**********************************************************************************************
3496 
3497  //**Compile time checks*************************************************************************
3506  //**********************************************************************************************
3507 };
3509 //*************************************************************************************************
3510 
3511 
3512 
3513 
3514 //=================================================================================================
3515 //
3516 // GLOBAL BINARY ARITHMETIC OPERATORS
3517 //
3518 //=================================================================================================
3519 
3520 //*************************************************************************************************
3551 template< typename T1 // Type of the left-hand side dense vector
3552  , typename T2 > // Type of the right-hand side dense matrix
3553 inline const typename DisableIf< IsMatMatMultExpr<T2>, TDVecTDMatMultExpr<T1,T2> >::Type
3555 {
3557 
3558  if( (~vec).size() != (~mat).rows() )
3559  throw std::invalid_argument( "Vector and matrix sizes do not match" );
3560 
3561  return TDVecTDMatMultExpr<T1,T2>( ~vec, ~mat );
3562 }
3563 //*************************************************************************************************
3564 
3565 
3566 
3567 
3568 //=================================================================================================
3569 //
3570 // SIZE SPECIALIZATIONS
3571 //
3572 //=================================================================================================
3573 
3574 //*************************************************************************************************
3576 template< typename MT, typename VT >
3577 struct Size< TDVecTDMatMultExpr<MT,VT> >
3578  : public Columns<MT>
3579 {};
3581 //*************************************************************************************************
3582 
3583 
3584 
3585 
3586 //=================================================================================================
3587 //
3588 // EXPRESSION TRAIT SPECIALIZATIONS
3589 //
3590 //=================================================================================================
3591 
3592 //*************************************************************************************************
3594 template< typename VT, typename MT, bool AF >
3595 struct SubvectorExprTrait< TDVecTDMatMultExpr<VT,MT>, AF >
3596 {
3597  public:
3598  //**********************************************************************************************
3599  typedef typename MultExprTrait< VT, typename SubmatrixExprTrait<const MT,AF>::Type >::Type Type;
3600  //**********************************************************************************************
3601 };
3603 //*************************************************************************************************
3604 
3605 } // namespace blaze
3606 
3607 #endif
BLAZE_ALWAYS_INLINE int16_t sum(const sse_int16_t &a)
Returns the sum of all elements in the 16-bit integral intrinsic vector.
Definition: Reduction.h:63
SelectType< IsExpression< VT >::value, const VT, const VT & >::Type LeftOperand
Composite type of the left-hand side dense vector expression.
Definition: TDVecTDMatMultExpr.h:254
Expression object for transpose dense vector-transpose dense matrix multiplications.The TDVecTDMatMultExpr class represents the compile time expression for multiplications between transpose dense vectors and column-major dense matrices.
Definition: Forward.h:135
Data type constraint.
Compile time check whether the given type is a computational expression template.This type trait clas...
Definition: IsComputation.h:89
const size_t end_
End of the unrolled calculation loop.
Definition: TDVecTDMatMultExpr.h:402
LeftOperand leftOperand() const
Returns the left-hand side dense vector operand.
Definition: TDVecTDMatMultExpr.h:336
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
RightOperand rightOperand() const
Returns the right-hand side transpose dense matrix operand.
Definition: TDVecTDMatMultExpr.h:346
#define BLAZE_BLAS_IS_PARALLEL
Compilation switch for the parallel BLAS mode.This compilation switch specifies whether the used BLAS...
Definition: BLAS.h:86
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
BLAZE_ALWAYS_INLINE size_t size(const Vector< VT, TF > &vector)
Returns the current size/dimension of the vector.
Definition: Vector.h:258
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
Header file for the IsSame and IsStrictlySame type traits.
const size_t TDVECTDMATMULT_THRESHOLD
Dense Vector/column-major dense matrix multiplication threshold.This setting specifies the threshold ...
Definition: Thresholds.h:108
Constraint on the data type.
MT::CompositeType MCT
Composite type of the right-hand side dense matrix expression.
Definition: TDVecTDMatMultExpr.h:118
MRT::ElementType MET
Element type of the right-hand side dense matrix expression.
Definition: TDVecTDMatMultExpr.h:116
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
SelectType< evaluateMatrix, const MRT, MCT >::Type RT
Type for the assignment of the right-hand side dense vector operand.
Definition: TDVecTDMatMultExpr.h:263
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
SelectType< IsExpression< MT >::value, const MT, const MT & >::Type RightOperand
Composite type of the right-hand side dense matrix expression.
Definition: TDVecTDMatMultExpr.h:257
Header file for the RequiresEvaluation type trait.
Header file for the VecScalarMultExpr base class.
Header file for the IsFloat type trait.
Base class for dense matrices.The DenseMatrix class is a base class for all dense matrix classes...
Definition: DenseMatrix.h:70
Constraint on the data type.
#define BLAZE_CONSTRAINT_MUST_BE_FLOAT_TYPE(T)
Constraint on the data type.This compile time constraint checks that the given data type T is of type...
Definition: Float.h:80
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
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.
Header file for the multiplication trait.
Header file for the IsDouble type trait.
#define BLAZE_CONSTRAINT_MUST_BE_COLUMN_MAJOR_MATRIX_TYPE(T)
Constraint on the data type.In case the given data type T is not a column-major dense or sparse matri...
Definition: StorageOrder.h:161
#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 isAligned() const
Returns whether the operands of the expression are properly aligned in memory.
Definition: TDVecTDMatMultExpr.h:380
bool canAlias(const T *alias) const
Returns whether the expression can alias with the given address alias.
Definition: TDVecTDMatMultExpr.h:358
ResultType::ElementType ElementType
Resulting element type.
Definition: TDVecTDMatMultExpr.h:248
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.
Header file for the IsBlasCompatible type trait.
TDVecTDMatMultExpr< VT, MT > This
Type of this TDVecTDMatMultExpr instance.
Definition: TDVecTDMatMultExpr.h:245
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
VT::CompositeType VCT
Composite type of the left-hand side dense vector expression.
Definition: TDVecTDMatMultExpr.h:117
#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
IntrinsicTrait< ElementType >::Type IntrinsicType
Resulting intrinsic element type.
Definition: TDVecTDMatMultExpr.h:249
SelectType< evaluateVector, const VRT, VCT >::Type LT
Type for the assignment of the left-hand side dense matrix operand.
Definition: TDVecTDMatMultExpr.h:260
Constraints on the storage order of matrix types.
Constraint on the data type.
MT::ResultType MRT
Result type of the right-hand side dense matrix expression.
Definition: TDVecTDMatMultExpr.h:114
VT::ResultType VRT
Result type of the left-hand side dense vector expression.
Definition: TDVecTDMatMultExpr.h:113
Type ElementType
Type of the sparse matrix elements.
Definition: CompressedMatrix.h:2476
Header file for the SelectType class template.
Header file for all forward declarations for expression class templates.
ReturnType operator[](size_t index) const
Subscript operator for the direct access to the vector elements.
Definition: TDVecTDMatMultExpr.h:299
Header file for the EnableIf class template.
Header file for the serial shim.
Header file for the IsNumeric type trait.
EnableIf< IsDenseMatrix< MT1 > >::Type smpSubAssign(Matrix< MT1, SO1 > &lhs, const Matrix< MT2, SO2 > &rhs)
Default implementation of the SMP subtraction assignment of a matrix to dense matrix.
Definition: DenseMatrix.h:160
Header file for the SubmatrixExprTrait class template.
bool canSMPAssign() const
Returns whether the expression can be used in SMP assignments.
Definition: TDVecTDMatMultExpr.h:390
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
LeftOperand vec_
Left-hand side dense vector of the multiplication expression.
Definition: TDVecTDMatMultExpr.h:400
#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.
Constraint on the data type.
const ResultType CompositeType
Data type for composite expression templates.
Definition: TDVecTDMatMultExpr.h:251
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.
const ElementType ReturnType
Return type for expression template evaluations.
Definition: TDVecTDMatMultExpr.h:250
VRT::ElementType VET
Element type of the left-hand side dense vector epxression.
Definition: TDVecTDMatMultExpr.h:115
ResultType::TransposeType TransposeType
Transpose type for expression template evaluations.
Definition: TDVecTDMatMultExpr.h:247
BLAZE_ALWAYS_INLINE void reset(const NonNumericProxy< MT > &proxy)
Resetting the represented element to the default initial values.
Definition: NonNumericProxy.h:833
RightOperand mat_
Right-hand side dense matrix of the multiplication expression.
Definition: TDVecTDMatMultExpr.h:401
Header file for all intrinsic functionality.
#define BLAZE_CONSTRAINT_MUST_BE_DENSE_VECTOR_TYPE(T)
Constraint on the data type.In case the given data type T is not a dense, N-dimensional vector type...
Definition: DenseVector.h:79
#define BLAZE_CONSTRAINT_MUST_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
bool isAliased(const T *alias) const
Returns whether the expression is aliased with the given address alias.
Definition: TDVecTDMatMultExpr.h:370
Header file for the IsComputation type trait class.
MultTrait< VRT, MRT >::Type ResultType
Result type for expression template evaluations.
Definition: TDVecTDMatMultExpr.h:246
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
This ResultType
Result type for expression template evaluations.
Definition: CompressedMatrix.h:2473
TDVecTDMatMultExpr(const VT &vec, const MT &mat)
Constructor for the TDVecTDMatMultExpr class.
Definition: TDVecTDMatMultExpr.h:284
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
Header file for the IsComplex type trait.
Header file for the SubvectorExprTrait class template.
Header file for the complex data type.
const size_t SMP_TDVECTDMATMULT_THRESHOLD
SMP dense vector/column-major dense matrix multiplication threshold.This threshold specifies when a d...
Definition: Thresholds.h:391
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
size_t size() const
Returns the current size/dimension of the vector.
Definition: TDVecTDMatMultExpr.h:326
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