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>
54 #include <blaze/math/Intrinsics.h>
55 #include <blaze/math/shims/Reset.h>
66 #include <blaze/system/BLAS.h>
68 #include <blaze/util/Assert.h>
69 #include <blaze/util/Complex.h>
75 #include <blaze/util/DisableIf.h>
76 #include <blaze/util/EnableIf.h>
78 #include <blaze/util/SelectType.h>
79 #include <blaze/util/Types.h>
85 
86 
87 namespace blaze {
88 
89 //=================================================================================================
90 //
91 // CLASS TDVECTDMATMULTEXPR
92 //
93 //=================================================================================================
94 
95 //*************************************************************************************************
102 template< typename VT // Type of the left-hand side dense vector
103  , typename MT > // Type of the right-hand side dense matrix
104 class TDVecTDMatMultExpr : public DenseVector< TDVecTDMatMultExpr<VT,MT>, true >
105  , private TVecMatMultExpr
106  , private Computation
107 {
108  private:
109  //**Type definitions****************************************************************************
110  typedef typename VT::ResultType VRT;
111  typedef typename MT::ResultType MRT;
112  typedef typename VRT::ElementType VET;
113  typedef typename MRT::ElementType MET;
114  typedef typename VT::CompositeType VCT;
115  typedef typename MT::CompositeType MCT;
116  //**********************************************************************************************
117 
118  //**********************************************************************************************
120  enum { evaluateVector = IsComputation<VT>::value || RequiresEvaluation<VT>::value };
121  //**********************************************************************************************
122 
123  //**********************************************************************************************
125  enum { evaluateMatrix = ( IsComputation<MT>::value && IsSame<MET,VET>::value &&
127  //**********************************************************************************************
128 
129  //**********************************************************************************************
131 
135  template< typename T1 >
136  struct UseSMPAssign {
137  enum { value = ( evaluateVector || evaluateMatrix ) };
138  };
140  //**********************************************************************************************
141 
142  //**********************************************************************************************
144 
148  template< typename T1, typename T2, typename T3 >
149  struct UseSinglePrecisionKernel {
150  enum { value = T1::vectorizable && T2::vectorizable && T3::vectorizable &&
151  IsFloat<typename T1::ElementType>::value &&
152  IsFloat<typename T2::ElementType>::value &&
153  IsFloat<typename T3::ElementType>::value };
154  };
156  //**********************************************************************************************
157 
158  //**********************************************************************************************
160 
164  template< typename T1, typename T2, typename T3 >
165  struct UseDoublePrecisionKernel {
166  enum { value = T1::vectorizable && T2::vectorizable && T3::vectorizable &&
167  IsDouble<typename T1::ElementType>::value &&
168  IsDouble<typename T2::ElementType>::value &&
169  IsDouble<typename T3::ElementType>::value };
170  };
172  //**********************************************************************************************
173 
174  //**********************************************************************************************
176 
180  template< typename T1, typename T2, typename T3 >
181  struct UseSinglePrecisionComplexKernel {
182  typedef complex<float> Type;
183  enum { value = T1::vectorizable && T2::vectorizable && T3::vectorizable &&
184  IsSame<typename T1::ElementType,Type>::value &&
185  IsSame<typename T2::ElementType,Type>::value &&
186  IsSame<typename T3::ElementType,Type>::value };
187  };
189  //**********************************************************************************************
190 
191  //**********************************************************************************************
193 
197  template< typename T1, typename T2, typename T3 >
198  struct UseDoublePrecisionComplexKernel {
199  typedef complex<double> Type;
200  enum { value = T1::vectorizable && T2::vectorizable && T3::vectorizable &&
201  IsSame<typename T1::ElementType,Type>::value &&
202  IsSame<typename T2::ElementType,Type>::value &&
203  IsSame<typename T3::ElementType,Type>::value };
204  };
206  //**********************************************************************************************
207 
208  //**********************************************************************************************
210 
213  template< typename T1, typename T2, typename T3 >
214  struct UseDefaultKernel {
215  enum { value = !BLAZE_BLAS_MODE || ( !UseSinglePrecisionKernel<T1,T2,T3>::value &&
216  !UseDoublePrecisionKernel<T1,T2,T3>::value &&
217  !UseSinglePrecisionComplexKernel<T1,T2,T3>::value &&
218  !UseDoublePrecisionComplexKernel<T1,T2,T3>::value ) };
219  };
221  //**********************************************************************************************
222 
223  //**********************************************************************************************
225 
229  template< typename T1, typename T2, typename T3 >
230  struct UseVectorizedDefaultKernel {
231  enum { value = T1::vectorizable && T2::vectorizable && T3::vectorizable &&
232  IsSame<typename T1::ElementType,typename T2::ElementType>::value &&
233  IsSame<typename T1::ElementType,typename T3::ElementType>::value &&
234  IntrinsicTrait<typename T1::ElementType>::addition &&
235  IntrinsicTrait<typename T1::ElementType>::multiplication };
236  };
238  //**********************************************************************************************
239 
240  public:
241  //**Type definitions****************************************************************************
247  typedef const ElementType ReturnType;
248  typedef const ResultType CompositeType;
249 
251  typedef typename SelectType< IsExpression<VT>::value, const VT, const VT& >::Type LeftOperand;
252 
254  typedef typename SelectType< IsExpression<MT>::value, const MT, const MT& >::Type RightOperand;
255 
258 
261  //**********************************************************************************************
262 
263  //**Compilation flags***************************************************************************
265  enum { vectorizable = VT::vectorizable && MT::vectorizable &&
269 
271  enum { smpAssignable = !evaluateVector && VT::smpAssignable &&
272  !evaluateMatrix && MT::smpAssignable };
273  //**********************************************************************************************
274 
275  //**Constructor*********************************************************************************
281  explicit inline TDVecTDMatMultExpr( const VT& vec, const MT& mat )
282  : vec_( vec ) // Left-hand side dense vector of the multiplication expression
283  , mat_( mat ) // Right-hand side dense matrix of the multiplication expression
284  , end_( ( (mat.rows()-1UL) & size_t(-2) ) + 1UL ) // End of the unrolled calculation loop
285  {
286  BLAZE_INTERNAL_ASSERT( vec_.size() == mat_.rows(), "Invalid vector and matrix sizes" );
287  }
288  //**********************************************************************************************
289 
290  //**Subscript operator**************************************************************************
296  inline ReturnType operator[]( size_t index ) const {
297  BLAZE_INTERNAL_ASSERT( index < mat_.columns(), "Invalid vector access index" );
298 
299  ElementType res;
300 
301  if( mat_.rows() != 0UL ) {
302  res = vec_[0UL] * mat_(0UL,index);
303  for( size_t j=1UL; j<end_; j+=2UL ) {
304  res += vec_[j] * mat_(j,index) + vec_[j+1UL] * mat_(j+1UL,index);
305  }
306  if( end_ < mat_.rows() ) {
307  res += vec_[end_] * mat_(end_,index);
308  }
309  }
310  else {
311  reset( res );
312  }
313 
314  return res;
315  }
316  //**********************************************************************************************
317 
318  //**Size function*******************************************************************************
323  inline size_t size() const {
324  return mat_.columns();
325  }
326  //**********************************************************************************************
327 
328  //**Left operand access*************************************************************************
333  inline LeftOperand leftOperand() const {
334  return vec_;
335  }
336  //**********************************************************************************************
337 
338  //**Right operand access************************************************************************
343  inline RightOperand rightOperand() const {
344  return mat_;
345  }
346  //**********************************************************************************************
347 
348  //**********************************************************************************************
354  template< typename T >
355  inline bool canAlias( const T* alias ) const {
356  return ( vec_.isAliased( alias ) || mat_.isAliased( alias ) );
357  }
358  //**********************************************************************************************
359 
360  //**********************************************************************************************
366  template< typename T >
367  inline bool isAliased( const T* alias ) const {
368  return ( vec_.isAliased( alias ) || mat_.isAliased( alias ) );
369  }
370  //**********************************************************************************************
371 
372  //**********************************************************************************************
377  inline bool isAligned() const {
378  return vec_.isAligned() && mat_.isAligned();
379  }
380  //**********************************************************************************************
381 
382  //**********************************************************************************************
387  inline bool canSMPAssign() const {
388  return ( !BLAZE_BLAS_IS_PARALLEL ||
389  ( IsComputation<MT>::value && !evaluateMatrix ) ||
390  ( mat_.rows() * mat_.columns() < TDVECTDMATMULT_THRESHOLD ) ) &&
392  }
393  //**********************************************************************************************
394 
395  private:
396  //**Member variables****************************************************************************
399  const size_t end_;
400  //**********************************************************************************************
401 
402  //**Assignment to dense vectors*****************************************************************
415  template< typename VT1 > // Type of the target dense vector
416  friend inline void assign( DenseVector<VT1,true>& lhs, const TDVecTDMatMultExpr& rhs )
417  {
419 
420  BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
421 
422  if( rhs.mat_.rows() == 0UL ) {
423  reset( ~lhs );
424  return;
425  }
426  else if( rhs.mat_.columns() == 0UL ) {
427  return;
428  }
429 
430  LT x( serial( rhs.vec_ ) ); // Evaluation of the left-hand side dense vector operand
431  RT A( serial( rhs.mat_ ) ); // Evaluation of the right-hand side dense matrix operand
432 
433  BLAZE_INTERNAL_ASSERT( x.size() == rhs.vec_.size() , "Invalid vector size" );
434  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.mat_.rows() , "Invalid number of rows" );
435  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.mat_.columns(), "Invalid number of columns" );
436  BLAZE_INTERNAL_ASSERT( A.columns() == (~lhs).size() , "Invalid vector size" );
437 
438  TDVecTDMatMultExpr::selectAssignKernel( ~lhs, x, A );
439  }
441  //**********************************************************************************************
442 
443  //**Assignment to dense vectors (kernel selection)**********************************************
454  template< typename VT1 // Type of the left-hand side target vector
455  , typename VT2 // Type of the left-hand side vector operand
456  , typename MT1 > // Type of the right-hand side matrix operand
457  static inline void selectAssignKernel( VT1& y, const VT2& x, const MT1& A )
458  {
459  if( ( IsComputation<MT>::value && !evaluateMatrix ) ||
460  ( A.rows() * A.columns() < TDVECTDMATMULT_THRESHOLD ) )
461  TDVecTDMatMultExpr::selectDefaultAssignKernel( y, x, A );
462  else
463  TDVecTDMatMultExpr::selectBlasAssignKernel( y, x, A );
464  }
466  //**********************************************************************************************
467 
468  //**Default assignment to dense vectors*********************************************************
482  template< typename VT1 // Type of the left-hand side target vector
483  , typename VT2 // Type of the left-hand side vector operand
484  , typename MT1 > // Type of the right-hand side matrix operand
485  static inline typename DisableIf< UseVectorizedDefaultKernel<VT1,VT2,MT1> >::Type
486  selectDefaultAssignKernel( VT1& y, const VT2& x, const MT1& A )
487  {
488  y.assign( x * A );
489  }
491  //**********************************************************************************************
492 
493  //**Vectorized default assignment to dense vectors**********************************************
507  template< typename VT1 // Type of the left-hand side target vector
508  , typename VT2 // Type of the left-hand side vector operand
509  , typename MT1 > // Type of the right-hand side matrix operand
510  static inline typename EnableIf< UseVectorizedDefaultKernel<VT1,VT2,MT1> >::Type
511  selectDefaultAssignKernel( VT1& y, const VT2& x, const MT1& A )
512  {
513  typedef IntrinsicTrait<ElementType> IT;
514 
515  const size_t M( A.rows() );
516  const size_t N( A.columns() );
517 
518  size_t j( 0UL );
519 
520  for( ; (j+8UL) <= N; j+=8UL ) {
521  IntrinsicType xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7, xmm8;
522  for( size_t i=0UL; i<M; i+=IT::size ) {
523  const IntrinsicType x1( x.load(i) );
524  xmm1 = xmm1 + x1 * A.load(i,j );
525  xmm2 = xmm2 + x1 * A.load(i,j+1UL);
526  xmm3 = xmm3 + x1 * A.load(i,j+2UL);
527  xmm4 = xmm4 + x1 * A.load(i,j+3UL);
528  xmm5 = xmm5 + x1 * A.load(i,j+4UL);
529  xmm6 = xmm6 + x1 * A.load(i,j+5UL);
530  xmm7 = xmm7 + x1 * A.load(i,j+6UL);
531  xmm8 = xmm8 + x1 * A.load(i,j+7UL);
532  }
533  y[j ] = sum( xmm1 );
534  y[j+1UL] = sum( xmm2 );
535  y[j+2UL] = sum( xmm3 );
536  y[j+3UL] = sum( xmm4 );
537  y[j+4UL] = sum( xmm5 );
538  y[j+5UL] = sum( xmm6 );
539  y[j+6UL] = sum( xmm7 );
540  y[j+7UL] = sum( xmm8 );
541  }
542  for( ; (j+4UL) <= N; j+=4UL ) {
543  IntrinsicType xmm1, xmm2, xmm3, xmm4;
544  for( size_t i=0UL; i<M; i+=IT::size ) {
545  const IntrinsicType x1( x.load(i) );
546  xmm1 = xmm1 + x1 * A.load(i,j );
547  xmm2 = xmm2 + x1 * A.load(i,j+1UL);
548  xmm3 = xmm3 + x1 * A.load(i,j+2UL);
549  xmm4 = xmm4 + x1 * A.load(i,j+3UL);
550  }
551  y[j ] = sum( xmm1 );
552  y[j+1UL] = sum( xmm2 );
553  y[j+2UL] = sum( xmm3 );
554  y[j+3UL] = sum( xmm4 );
555  }
556  for( ; (j+3UL) <= N; j+=3UL ) {
557  IntrinsicType xmm1, xmm2, xmm3;
558  for( size_t i=0UL; i<M; i+=IT::size ) {
559  const IntrinsicType x1( x.load(i) );
560  xmm1 = xmm1 + x1 * A.load(i,j );
561  xmm2 = xmm2 + x1 * A.load(i,j+1UL);
562  xmm3 = xmm3 + x1 * A.load(i,j+2UL);
563  }
564  y[j ] = sum( xmm1 );
565  y[j+1UL] = sum( xmm2 );
566  y[j+2UL] = sum( xmm3 );
567  }
568  for( ; (j+2UL) <= N; j+=2UL ) {
569  IntrinsicType xmm1, xmm2;
570  for( size_t i=0UL; i<M; i+=IT::size ) {
571  const IntrinsicType x1( x.load(i) );
572  xmm1 = xmm1 + x1 * A.load(i,j );
573  xmm2 = xmm2 + x1 * A.load(i,j+1UL);
574  }
575  y[j ] = sum( xmm1 );
576  y[j+1UL] = sum( xmm2 );
577  }
578  if( j < N ) {
579  IntrinsicType xmm1;
580  for( size_t i=0UL; i<M; i+=IT::size ) {
581  xmm1 = xmm1 + A.load(i,j) * x.load(i);
582  }
583  y[j] = sum( xmm1 );
584  }
585  }
587  //**********************************************************************************************
588 
589  //**BLAS-based assignment to dense vectors (default)********************************************
603  template< typename VT1 // Type of the left-hand side target vector
604  , typename VT2 // Type of the left-hand side vector operand
605  , typename MT1 > // Type of the right-hand side matrix operand
606  static inline typename EnableIf< UseDefaultKernel<VT1,VT2,MT1> >::Type
607  selectBlasAssignKernel( VT1& y, const VT2& x, const MT1& A )
608  {
609  selectDefaultAssignKernel( y, x, A );
610  }
612  //**********************************************************************************************
613 
614  //**BLAS-based assignment to dense vectors (single precision)***********************************
615 #if BLAZE_BLAS_MODE
616 
629  template< typename VT1 // Type of the left-hand side target vector
630  , typename VT2 // Type of the left-hand side vector operand
631  , typename MT1 > // Type of the right-hand side matrix operand
632  static inline typename EnableIf< UseSinglePrecisionKernel<VT1,VT2,MT1> >::Type
633  selectBlasAssignKernel( VT1& y, const VT2& x, const MT1& A )
634  {
635  using boost::numeric_cast;
636 
640 
641  const int M ( numeric_cast<int>( A.rows() ) );
642  const int N ( numeric_cast<int>( A.columns() ) );
643  const int lda( numeric_cast<int>( A.spacing() ) );
644 
645  cblas_sgemv( CblasColMajor, CblasTrans, M, N, 1.0F,
646  A.data(), lda, x.data(), 1, 0.0F, y.data(), 1 );
647  }
649 #endif
650  //**********************************************************************************************
651 
652  //**BLAS-based assignment to dense vectors (double precision)***********************************
653 #if BLAZE_BLAS_MODE
654 
667  template< typename VT1 // Type of the left-hand side target vector
668  , typename VT2 // Type of the left-hand side vector operand
669  , typename MT1 > // Type of the right-hand side matrix operand
670  static inline typename EnableIf< UseDoublePrecisionKernel<VT1,VT2,MT1> >::Type
671  selectBlasAssignKernel( VT1& y, const VT2& x, const MT1& A )
672  {
673  using boost::numeric_cast;
674 
678 
679  const int M ( numeric_cast<int>( A.rows() ) );
680  const int N ( numeric_cast<int>( A.columns() ) );
681  const int lda( numeric_cast<int>( A.spacing() ) );
682 
683  cblas_dgemv( CblasColMajor, CblasTrans, M, N, 1.0,
684  A.data(), lda, x.data(), 1, 0.0, y.data(), 1 );
685  }
687 #endif
688  //**********************************************************************************************
689 
690  //**BLAS-based assignment to dense vectors (single precision complex)***************************
691 #if BLAZE_BLAS_MODE
692 
705  template< typename VT1 // Type of the left-hand side target vector
706  , typename VT2 // Type of the left-hand side vector operand
707  , typename MT1 > // Type of the right-hand side matrix operand
708  static inline typename EnableIf< UseSinglePrecisionComplexKernel<VT1,VT2,MT1> >::Type
709  selectBlasAssignKernel( VT1& y, const VT2& x, const MT1& A )
710  {
711  using boost::numeric_cast;
712 
716  BLAZE_CONSTRAINT_MUST_BE_FLOAT_TYPE ( typename VT1::ElementType::value_type );
717  BLAZE_CONSTRAINT_MUST_BE_FLOAT_TYPE ( typename VT2::ElementType::value_type );
718  BLAZE_CONSTRAINT_MUST_BE_FLOAT_TYPE ( typename MT1::ElementType::value_type );
719 
720  const int M ( numeric_cast<int>( A.rows() ) );
721  const int N ( numeric_cast<int>( A.columns() ) );
722  const int lda( numeric_cast<int>( A.spacing() ) );
723  const complex<float> alpha( 1.0F, 0.0F );
724  const complex<float> beta ( 0.0F, 0.0F );
725 
726  cblas_cgemv( CblasColMajor, CblasTrans, M, N, &alpha,
727  A.data(), lda, x.data(), 1, &beta, y.data(), 1 );
728  }
730 #endif
731  //**********************************************************************************************
732 
733  //**BLAS-based assignment to dense vectors (double precision complex)***************************
734 #if BLAZE_BLAS_MODE
735 
748  template< typename VT1 // Type of the left-hand side target vector
749  , typename VT2 // Type of the left-hand side vector operand
750  , typename MT1 > // Type of the right-hand side matrix operand
751  static inline typename EnableIf< UseDoublePrecisionComplexKernel<VT1,VT2,MT1> >::Type
752  selectBlasAssignKernel( VT1& y, const VT2& x, const MT1& A )
753  {
754  using boost::numeric_cast;
755 
759  BLAZE_CONSTRAINT_MUST_BE_DOUBLE_TYPE ( typename VT1::ElementType::value_type );
760  BLAZE_CONSTRAINT_MUST_BE_DOUBLE_TYPE ( typename VT2::ElementType::value_type );
761  BLAZE_CONSTRAINT_MUST_BE_DOUBLE_TYPE ( typename MT1::ElementType::value_type );
762 
763  const int M ( numeric_cast<int>( A.rows() ) );
764  const int N ( numeric_cast<int>( A.columns() ) );
765  const int lda( numeric_cast<int>( A.spacing() ) );
766  const complex<double> alpha( 1.0, 0.0 );
767  const complex<double> beta ( 0.0, 0.0 );
768 
769  cblas_zgemv( CblasColMajor, CblasTrans, M, N, &alpha,
770  A.data(), lda, x.data(), 1, &beta, y.data(), 1 );
771  }
773 #endif
774  //**********************************************************************************************
775 
776  //**Assignment to sparse vectors****************************************************************
789  template< typename VT1 > // Type of the target sparse vector
790  friend inline void assign( SparseVector<VT1,true>& lhs, const TDVecTDMatMultExpr& rhs )
791  {
793 
797 
798  BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
799 
800  const ResultType tmp( serial( rhs ) );
801  assign( ~lhs, tmp );
802  }
804  //**********************************************************************************************
805 
806  //**Addition assignment to dense vectors********************************************************
819  template< typename VT1 > // Type of the target dense vector
820  friend inline void addAssign( DenseVector<VT1,true>& lhs, const TDVecTDMatMultExpr& rhs )
821  {
823 
824  BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
825 
826  if( rhs.mat_.rows() == 0UL || rhs.mat_.columns() == 0UL ) {
827  return;
828  }
829 
830  LT x( serial( rhs.vec_ ) ); // Evaluation of the left-hand side dense vector operand
831  RT A( serial( rhs.mat_ ) ); // Evaluation of the right-hand side dense matrix operand
832 
833  BLAZE_INTERNAL_ASSERT( x.size() == rhs.vec_.size() , "Invalid vector size" );
834  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.mat_.rows() , "Invalid number of rows" );
835  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.mat_.columns(), "Invalid number of columns" );
836  BLAZE_INTERNAL_ASSERT( A.columns() == (~lhs).size() , "Invalid vector size" );
837 
838  TDVecTDMatMultExpr::selectAddAssignKernel( ~lhs, x, A );
839  }
841  //**********************************************************************************************
842 
843  //**Addition assignment to dense vectors (kernel selection)*************************************
854  template< typename VT1 // Type of the left-hand side target vector
855  , typename VT2 // Type of the left-hand side vector operand
856  , typename MT1 > // Type of the right-hand side matrix operand
857  static inline void selectAddAssignKernel( VT1& y, const VT2& x, const MT1& A )
858  {
859  if( ( IsComputation<MT>::value && !evaluateMatrix ) ||
860  ( A.rows() * A.columns() < TDVECTDMATMULT_THRESHOLD ) )
861  TDVecTDMatMultExpr::selectDefaultAddAssignKernel( y, x, A );
862  else
863  TDVecTDMatMultExpr::selectBlasAddAssignKernel( y, x, A );
864  }
866  //**********************************************************************************************
867 
868  //**Default addition assignment to dense vectors************************************************
882  template< typename VT1 // Type of the left-hand side target vector
883  , typename VT2 // Type of the left-hand side vector operand
884  , typename MT1 > // Type of the right-hand side matrix operand
885  static inline typename DisableIf< UseVectorizedDefaultKernel<VT1,VT2,MT1> >::Type
886  selectDefaultAddAssignKernel( VT1& y, const VT2& x, const MT1& A )
887  {
888  y.addAssign( x * A );
889  }
891  //**********************************************************************************************
892 
893  //**Vectorized default addition assignment to dense vectors*************************************
907  template< typename VT1 // Type of the left-hand side target vector
908  , typename VT2 // Type of the left-hand side vector operand
909  , typename MT1 > // Type of the right-hand side matrix operand
910  static inline typename EnableIf< UseVectorizedDefaultKernel<VT1,VT2,MT1> >::Type
911  selectDefaultAddAssignKernel( VT1& y, const VT2& x, const MT1& A )
912  {
913  typedef IntrinsicTrait<ElementType> IT;
914 
915  const size_t M( A.rows() );
916  const size_t N( A.columns() );
917 
918  size_t j( 0UL );
919 
920  for( ; (j+8UL) <= N; j+=8UL ) {
921  IntrinsicType xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7, xmm8;
922  for( size_t i=0UL; i<M; i+=IT::size ) {
923  const IntrinsicType x1( x.load(i) );
924  xmm1 = xmm1 + x1 * A.load(i,j );
925  xmm2 = xmm2 + x1 * A.load(i,j+1UL);
926  xmm3 = xmm3 + x1 * A.load(i,j+2UL);
927  xmm4 = xmm4 + x1 * A.load(i,j+3UL);
928  xmm5 = xmm5 + x1 * A.load(i,j+4UL);
929  xmm6 = xmm6 + x1 * A.load(i,j+5UL);
930  xmm7 = xmm7 + x1 * A.load(i,j+6UL);
931  xmm8 = xmm8 + x1 * A.load(i,j+7UL);
932  }
933  y[j ] += sum( xmm1 );
934  y[j+1UL] += sum( xmm2 );
935  y[j+2UL] += sum( xmm3 );
936  y[j+3UL] += sum( xmm4 );
937  y[j+4UL] += sum( xmm5 );
938  y[j+5UL] += sum( xmm6 );
939  y[j+6UL] += sum( xmm7 );
940  y[j+7UL] += sum( xmm8 );
941  }
942  for( ; (j+4UL) <= N; j+=4UL ) {
943  IntrinsicType xmm1, xmm2, xmm3, xmm4;
944  for( size_t i=0UL; i<M; i+=IT::size ) {
945  const IntrinsicType x1( x.load(i) );
946  xmm1 = xmm1 + x1 * A.load(i,j );
947  xmm2 = xmm2 + x1 * A.load(i,j+1UL);
948  xmm3 = xmm3 + x1 * A.load(i,j+2UL);
949  xmm4 = xmm4 + x1 * A.load(i,j+3UL);
950  }
951  y[j ] += sum( xmm1 );
952  y[j+1UL] += sum( xmm2 );
953  y[j+2UL] += sum( xmm3 );
954  y[j+3UL] += sum( xmm4 );
955  }
956  for( ; (j+3UL) <= N; j+=3UL ) {
957  IntrinsicType xmm1, xmm2, xmm3;
958  for( size_t i=0UL; i<M; i+=IT::size ) {
959  const IntrinsicType x1( x.load(i) );
960  xmm1 = xmm1 + x1 * A.load(i,j );
961  xmm2 = xmm2 + x1 * A.load(i,j+1UL);
962  xmm3 = xmm3 + x1 * A.load(i,j+2UL);
963  }
964  y[j ] += sum( xmm1 );
965  y[j+1UL] += sum( xmm2 );
966  y[j+2UL] += sum( xmm3 );
967  }
968  for( ; (j+2UL) <= N; j+=2UL ) {
969  IntrinsicType xmm1, xmm2;
970  for( size_t i=0UL; i<M; i+=IT::size ) {
971  const IntrinsicType x1( x.load(i) );
972  xmm1 = xmm1 + x1 * A.load(i,j );
973  xmm2 = xmm2 + x1 * A.load(i,j+1UL);
974  }
975  y[j ] += sum( xmm1 );
976  y[j+1UL] += sum( xmm2 );
977  }
978  if( j < N ) {
979  IntrinsicType xmm1;
980  for( size_t i=0UL; i<M; i+=IT::size ) {
981  xmm1 = xmm1 + A.load(i,j) * x.load(i);
982  }
983  y[j] += sum( xmm1 );
984  }
985  }
987  //**********************************************************************************************
988 
989  //**BLAS-based addition assignment to dense vectors (default)***********************************
1003  template< typename VT1 // Type of the left-hand side target vector
1004  , typename VT2 // Type of the left-hand side vector operand
1005  , typename MT1 > // Type of the right-hand side matrix operand
1006  static inline typename EnableIf< UseDefaultKernel<VT1,VT2,MT1> >::Type
1007  selectBlasAddAssignKernel( VT1& y, const VT2& x, const MT1& A )
1008  {
1009  selectDefaultAddAssignKernel( y, x, A );
1010  }
1012  //**********************************************************************************************
1013 
1014  //**BLAS-based addition assignment to dense vectors (single precision)**************************
1015 #if BLAZE_BLAS_MODE
1016 
1029  template< typename VT1 // Type of the left-hand side target vector
1030  , typename VT2 // Type of the left-hand side vector operand
1031  , typename MT1 > // Type of the right-hand side matrix operand
1032  static inline typename EnableIf< UseSinglePrecisionKernel<VT1,VT2,MT1> >::Type
1033  selectBlasAddAssignKernel( VT1& y, const VT2& x, const MT1& A )
1034  {
1035  using boost::numeric_cast;
1036 
1040 
1041  const int M ( numeric_cast<int>( A.rows() ) );
1042  const int N ( numeric_cast<int>( A.columns() ) );
1043  const int lda( numeric_cast<int>( A.spacing() ) );
1044 
1045  cblas_sgemv( CblasColMajor, CblasTrans, M, N, 1.0F,
1046  A.data(), lda, x.data(), 1, 1.0F, y.data(), 1 );
1047  }
1049 #endif
1050  //**********************************************************************************************
1051 
1052  //**BLAS-based addition assignment to dense vectors (double precision)**************************
1053 #if BLAZE_BLAS_MODE
1054 
1067  template< typename VT1 // Type of the left-hand side target vector
1068  , typename VT2 // Type of the left-hand side vector operand
1069  , typename MT1 > // Type of the right-hand side matrix operand
1070  static inline typename EnableIf< UseDoublePrecisionKernel<VT1,VT2,MT1> >::Type
1071  selectBlasAddAssignKernel( VT1& y, const VT2& x, const MT1& A )
1072  {
1073  using boost::numeric_cast;
1074 
1078 
1079  const int M ( numeric_cast<int>( A.rows() ) );
1080  const int N ( numeric_cast<int>( A.columns() ) );
1081  const int lda( numeric_cast<int>( A.spacing() ) );
1082 
1083  cblas_dgemv( CblasColMajor, CblasTrans, M, N, 1.0,
1084  A.data(), lda, x.data(), 1, 1.0, y.data(), 1 );
1085  }
1087 #endif
1088  //**********************************************************************************************
1089 
1090  //**BLAS-based addition assignment to dense vectors (single precision complex)******************
1091 #if BLAZE_BLAS_MODE
1092 
1105  template< typename VT1 // Type of the left-hand side target vector
1106  , typename VT2 // Type of the left-hand side vector operand
1107  , typename MT1 > // Type of the right-hand side matrix operand
1108  static inline typename EnableIf< UseSinglePrecisionComplexKernel<VT1,VT2,MT1> >::Type
1109  selectBlasAddAssignKernel( VT1& y, const VT2& x, const MT1& A )
1110  {
1111  using boost::numeric_cast;
1112 
1116  BLAZE_CONSTRAINT_MUST_BE_FLOAT_TYPE ( typename VT1::ElementType::value_type );
1117  BLAZE_CONSTRAINT_MUST_BE_FLOAT_TYPE ( typename VT2::ElementType::value_type );
1118  BLAZE_CONSTRAINT_MUST_BE_FLOAT_TYPE ( typename MT1::ElementType::value_type );
1119 
1120  const int M ( numeric_cast<int>( A.rows() ) );
1121  const int N ( numeric_cast<int>( A.columns() ) );
1122  const int lda( numeric_cast<int>( A.spacing() ) );
1123  const complex<float> alpha( 1.0F, 0.0F );
1124  const complex<float> beta ( 1.0F, 0.0F );
1125 
1126  cblas_cgemv( CblasColMajor, CblasTrans, M, N, &alpha,
1127  A.data(), lda, x.data(), 1, &beta, y.data(), 1 );
1128  }
1130 #endif
1131  //**********************************************************************************************
1132 
1133  //**BLAS-based addition assignment to dense vectors (double precision complex)******************
1134 #if BLAZE_BLAS_MODE
1135 
1148  template< typename VT1 // Type of the left-hand side target vector
1149  , typename VT2 // Type of the left-hand side vector operand
1150  , typename MT1 > // Type of the right-hand side matrix operand
1151  static inline typename EnableIf< UseDoublePrecisionComplexKernel<VT1,VT2,MT1> >::Type
1152  selectBlasAddAssignKernel( VT1& y, const VT2& x, const MT1& A )
1153  {
1154  using boost::numeric_cast;
1155 
1159  BLAZE_CONSTRAINT_MUST_BE_DOUBLE_TYPE ( typename VT1::ElementType::value_type );
1160  BLAZE_CONSTRAINT_MUST_BE_DOUBLE_TYPE ( typename VT2::ElementType::value_type );
1161  BLAZE_CONSTRAINT_MUST_BE_DOUBLE_TYPE ( typename MT1::ElementType::value_type );
1162 
1163  const int M ( numeric_cast<int>( A.rows() ) );
1164  const int N ( numeric_cast<int>( A.columns() ) );
1165  const int lda( numeric_cast<int>( A.spacing() ) );
1166  const complex<double> alpha( 1.0, 0.0 );
1167  const complex<double> beta ( 1.0, 0.0 );
1168 
1169  cblas_zgemv( CblasColMajor, CblasTrans, M, N, &alpha,
1170  A.data(), lda, x.data(), 1, &beta, y.data(), 1 );
1171  }
1173 #endif
1174  //**********************************************************************************************
1175 
1176  //**Addition assignment to sparse vectors*******************************************************
1177  // No special implementation for the addition assignment to sparse vectors.
1178  //**********************************************************************************************
1179 
1180  //**Subtraction assignment to dense vectors*****************************************************
1193  template< typename VT1 > // Type of the target dense vector
1194  friend inline void subAssign( DenseVector<VT1,true>& lhs, const TDVecTDMatMultExpr& rhs )
1195  {
1197 
1198  BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
1199 
1200  if( rhs.mat_.rows() == 0UL || rhs.mat_.columns() == 0UL ) {
1201  return;
1202  }
1203 
1204  LT x( serial( rhs.vec_ ) ); // Evaluation of the left-hand side dense vector operand
1205  RT A( serial( rhs.mat_ ) ); // Evaluation of the right-hand side dense matrix operand
1206 
1207  BLAZE_INTERNAL_ASSERT( x.size() == rhs.vec_.size() , "Invalid vector size" );
1208  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.mat_.rows() , "Invalid number of rows" );
1209  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.mat_.columns(), "Invalid number of columns" );
1210  BLAZE_INTERNAL_ASSERT( A.columns() == (~lhs).size() , "Invalid vector size" );
1211 
1212  TDVecTDMatMultExpr::selectSubAssignKernel( ~lhs, x, A );
1213  }
1215  //**********************************************************************************************
1216 
1217  //**Subtraction assignment to dense vectors (kernel selection)**********************************
1228  template< typename VT1 // Type of the left-hand side target vector
1229  , typename VT2 // Type of the left-hand side vector operand
1230  , typename MT1 > // Type of the right-hand side matrix operand
1231  static inline void selectSubAssignKernel( VT1& y, const VT2& x, const MT1& A )
1232  {
1233  if( ( IsComputation<MT>::value && !evaluateMatrix ) ||
1234  ( A.rows() * A.columns() < TDVECTDMATMULT_THRESHOLD ) )
1235  TDVecTDMatMultExpr::selectDefaultSubAssignKernel( y, x, A );
1236  else
1237  TDVecTDMatMultExpr::selectBlasSubAssignKernel( y, x, A );
1238  }
1240  //**********************************************************************************************
1241 
1242  //**Default subtraction assignment to dense vectors*********************************************
1256  template< typename VT1 // Type of the left-hand side target vector
1257  , typename VT2 // Type of the left-hand side vector operand
1258  , typename MT1 > // Type of the right-hand side matrix operand
1259  static inline typename DisableIf< UseVectorizedDefaultKernel<VT1,VT2,MT1> >::Type
1260  selectDefaultSubAssignKernel( VT1& y, const VT2& x, const MT1& A )
1261  {
1262  y.subAssign( x * A );
1263  }
1265  //**********************************************************************************************
1266 
1267  //**Vectorized default subtraction assignment to dense vectors**********************************
1281  template< typename VT1 // Type of the left-hand side target vector
1282  , typename VT2 // Type of the left-hand side vector operand
1283  , typename MT1 > // Type of the right-hand side matrix operand
1284  static inline typename EnableIf< UseVectorizedDefaultKernel<VT1,VT2,MT1> >::Type
1285  selectDefaultSubAssignKernel( VT1& y, const VT2& x, const MT1& A )
1286  {
1287  typedef IntrinsicTrait<ElementType> IT;
1288 
1289  const size_t M( A.rows() );
1290  const size_t N( A.columns() );
1291 
1292  size_t j( 0UL );
1293 
1294  for( ; (j+8UL) <= N; j+=8UL ) {
1295  IntrinsicType xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7, xmm8;
1296  for( size_t i=0UL; i<M; i+=IT::size ) {
1297  const IntrinsicType x1( x.load(i) );
1298  xmm1 = xmm1 + x1 * A.load(i,j );
1299  xmm2 = xmm2 + x1 * A.load(i,j+1UL);
1300  xmm3 = xmm3 + x1 * A.load(i,j+2UL);
1301  xmm4 = xmm4 + x1 * A.load(i,j+3UL);
1302  xmm5 = xmm5 + x1 * A.load(i,j+4UL);
1303  xmm6 = xmm6 + x1 * A.load(i,j+5UL);
1304  xmm7 = xmm7 + x1 * A.load(i,j+6UL);
1305  xmm8 = xmm8 + x1 * A.load(i,j+7UL);
1306  }
1307  y[j ] -= sum( xmm1 );
1308  y[j+1UL] -= sum( xmm2 );
1309  y[j+2UL] -= sum( xmm3 );
1310  y[j+3UL] -= sum( xmm4 );
1311  y[j+4UL] -= sum( xmm5 );
1312  y[j+5UL] -= sum( xmm6 );
1313  y[j+6UL] -= sum( xmm7 );
1314  y[j+7UL] -= sum( xmm8 );
1315  }
1316  for( ; (j+4UL) <= N; j+=4UL ) {
1317  IntrinsicType xmm1, xmm2, xmm3, xmm4;
1318  for( size_t i=0UL; i<M; i+=IT::size ) {
1319  const IntrinsicType x1( x.load(i) );
1320  xmm1 = xmm1 + x1 * A.load(i,j );
1321  xmm2 = xmm2 + x1 * A.load(i,j+1UL);
1322  xmm3 = xmm3 + x1 * A.load(i,j+2UL);
1323  xmm4 = xmm4 + x1 * A.load(i,j+3UL);
1324  }
1325  y[j ] -= sum( xmm1 );
1326  y[j+1UL] -= sum( xmm2 );
1327  y[j+2UL] -= sum( xmm3 );
1328  y[j+3UL] -= sum( xmm4 );
1329  }
1330  for( ; (j+3UL) <= N; j+=3UL ) {
1331  IntrinsicType xmm1, xmm2, xmm3;
1332  for( size_t i=0UL; i<M; i+=IT::size ) {
1333  const IntrinsicType x1( x.load(i) );
1334  xmm1 = xmm1 + x1 * A.load(i,j );
1335  xmm2 = xmm2 + x1 * A.load(i,j+1UL);
1336  xmm3 = xmm3 + x1 * A.load(i,j+2UL);
1337  }
1338  y[j ] -= sum( xmm1 );
1339  y[j+1UL] -= sum( xmm2 );
1340  y[j+2UL] -= sum( xmm3 );
1341  }
1342  for( ; (j+2UL) <= N; j+=2UL ) {
1343  IntrinsicType xmm1, xmm2;
1344  for( size_t i=0UL; i<M; i+=IT::size ) {
1345  const IntrinsicType x1( x.load(i) );
1346  xmm1 = xmm1 + x1 * A.load(i,j );
1347  xmm2 = xmm2 + x1 * A.load(i,j+1UL);
1348  }
1349  y[j ] -= sum( xmm1 );
1350  y[j+1UL] -= sum( xmm2 );
1351  }
1352  if( j < N ) {
1353  IntrinsicType xmm1;
1354  for( size_t i=0UL; i<M; i+=IT::size ) {
1355  xmm1 = xmm1 + A.load(i,j) * x.load(i);
1356  }
1357  y[j] -= sum( xmm1 );
1358  }
1359  }
1361  //**********************************************************************************************
1362 
1363  //**BLAS-based subtraction assignment to dense vectors (default)********************************
1377  template< typename VT1 // Type of the left-hand side target vector
1378  , typename VT2 // Type of the left-hand side vector operand
1379  , typename MT1 > // Type of the right-hand side matrix operand
1380  static inline typename EnableIf< UseDefaultKernel<VT1,VT2,MT1> >::Type
1381  selectBlasSubAssignKernel( VT1& y, const VT2& x, const MT1& A )
1382  {
1383  selectDefaultSubAssignKernel( y, x, A );
1384  }
1386  //**********************************************************************************************
1387 
1388  //**BLAS-based subtraction assignment to dense vectors (single precision)***********************
1389 #if BLAZE_BLAS_MODE
1390 
1403  template< typename VT1 // Type of the left-hand side target vector
1404  , typename VT2 // Type of the left-hand side vector operand
1405  , typename MT1 > // Type of the right-hand side matrix operand
1406  static inline typename EnableIf< UseSinglePrecisionKernel<VT1,VT2,MT1> >::Type
1407  selectBlasSubAssignKernel( VT1& y, const VT2& x, const MT1& A )
1408  {
1409  using boost::numeric_cast;
1410 
1414 
1415  const int M ( numeric_cast<int>( A.rows() ) );
1416  const int N ( numeric_cast<int>( A.columns() ) );
1417  const int lda( numeric_cast<int>( A.spacing() ) );
1418 
1419  cblas_sgemv( CblasColMajor, CblasTrans, M, N, -1.0F,
1420  A.data(), lda, x.data(), 1, 1.0F, y.data(), 1 );
1421  }
1423 #endif
1424  //**********************************************************************************************
1425 
1426  //**BLAS-based subtraction assignment to dense vectors (double precision)***********************
1427 #if BLAZE_BLAS_MODE
1428 
1441  template< typename VT1 // Type of the left-hand side target vector
1442  , typename VT2 // Type of the left-hand side vector operand
1443  , typename MT1 > // Type of the right-hand side matrix operand
1444  static inline typename EnableIf< UseDoublePrecisionKernel<VT1,VT2,MT1> >::Type
1445  selectBlasSubAssignKernel( VT1& y, const VT2& x, const MT1& A )
1446  {
1447  using boost::numeric_cast;
1448 
1452 
1453  const int M ( numeric_cast<int>( A.rows() ) );
1454  const int N ( numeric_cast<int>( A.columns() ) );
1455  const int lda( numeric_cast<int>( A.spacing() ) );
1456 
1457  cblas_dgemv( CblasColMajor, CblasTrans, M, N, -1.0,
1458  A.data(), lda, x.data(), 1, 1.0, y.data(), 1 );
1459  }
1461 #endif
1462  //**********************************************************************************************
1463 
1464  //**BLAS-based subtraction assignment to dense vectors (single precision complex)***************
1465 #if BLAZE_BLAS_MODE
1466 
1479  template< typename VT1 // Type of the left-hand side target vector
1480  , typename VT2 // Type of the left-hand side vector operand
1481  , typename MT1 > // Type of the right-hand side matrix operand
1482  static inline typename EnableIf< UseSinglePrecisionComplexKernel<VT1,VT2,MT1> >::Type
1483  selectBlasSubAssignKernel( VT1& y, const VT2& x, const MT1& A )
1484  {
1485  using boost::numeric_cast;
1486 
1490  BLAZE_CONSTRAINT_MUST_BE_FLOAT_TYPE ( typename VT1::ElementType::value_type );
1491  BLAZE_CONSTRAINT_MUST_BE_FLOAT_TYPE ( typename VT2::ElementType::value_type );
1492  BLAZE_CONSTRAINT_MUST_BE_FLOAT_TYPE ( typename MT1::ElementType::value_type );
1493 
1494  const int M ( numeric_cast<int>( A.rows() ) );
1495  const int N ( numeric_cast<int>( A.columns() ) );
1496  const int lda( numeric_cast<int>( A.spacing() ) );
1497  const complex<float> alpha( -1.0F, 0.0F );
1498  const complex<float> beta ( 1.0F, 0.0F );
1499 
1500  cblas_cgemv( CblasColMajor, CblasTrans, M, N, &alpha,
1501  A.data(), lda, x.data(), 1, &beta, y.data(), 1 );
1502  }
1504 #endif
1505  //**********************************************************************************************
1506 
1507  //**BLAS-based subtraction assignment to dense vectors (double precision complex)***************
1508 #if BLAZE_BLAS_MODE
1509 
1522  template< typename VT1 // Type of the left-hand side target vector
1523  , typename VT2 // Type of the left-hand side vector operand
1524  , typename MT1 > // Type of the right-hand side matrix operand
1525  static inline typename EnableIf< UseDoublePrecisionComplexKernel<VT1,VT2,MT1> >::Type
1526  selectBlasSubAssignKernel( VT1& y, const VT2& x, const MT1& A )
1527  {
1528  using boost::numeric_cast;
1529 
1533  BLAZE_CONSTRAINT_MUST_BE_DOUBLE_TYPE ( typename VT1::ElementType::value_type );
1534  BLAZE_CONSTRAINT_MUST_BE_DOUBLE_TYPE ( typename VT2::ElementType::value_type );
1535  BLAZE_CONSTRAINT_MUST_BE_DOUBLE_TYPE ( typename MT1::ElementType::value_type );
1536 
1537  const int M ( numeric_cast<int>( A.rows() ) );
1538  const int N ( numeric_cast<int>( A.columns() ) );
1539  const int lda( numeric_cast<int>( A.spacing() ) );
1540  const complex<double> alpha( -1.0, 0.0 );
1541  const complex<double> beta ( 1.0, 0.0 );
1542 
1543  cblas_zgemv( CblasColMajor, CblasTrans, M, N, &alpha,
1544  A.data(), lda, x.data(), 1, &beta, y.data(), 1 );
1545  }
1547 #endif
1548  //**********************************************************************************************
1549 
1550  //**Subtraction assignment to sparse vectors****************************************************
1551  // No special implementation for the subtraction assignment to sparse vectors.
1552  //**********************************************************************************************
1553 
1554  //**Multiplication assignment to dense vectors**************************************************
1567  template< typename VT1 > // Type of the target dense vector
1568  friend inline void multAssign( DenseVector<VT1,true>& lhs, const TDVecTDMatMultExpr& rhs )
1569  {
1571 
1575 
1576  BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
1577 
1578  const ResultType tmp( serial( rhs ) );
1579  multAssign( ~lhs, tmp );
1580  }
1582  //**********************************************************************************************
1583 
1584  //**Multiplication assignment to sparse vectors*************************************************
1585  // No special implementation for the multiplication assignment to sparse vectors.
1586  //**********************************************************************************************
1587 
1588  //**SMP assignment to dense vectors*************************************************************
1603  template< typename VT1 > // Type of the target dense vector
1604  friend inline typename EnableIf< UseSMPAssign<VT1> >::Type
1605  smpAssign( DenseVector<VT1,true>& lhs, const TDVecTDMatMultExpr& rhs )
1606  {
1608 
1609  BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
1610 
1611  if( rhs.mat_.rows() == 0UL ) {
1612  reset( ~lhs );
1613  return;
1614  }
1615  else if( rhs.mat_.columns() == 0UL ) {
1616  return;
1617  }
1618 
1619  LT x( rhs.vec_ ); // Evaluation of the left-hand side dense vector operand
1620  RT A( rhs.mat_ ); // Evaluation of the right-hand side dense matrix operand
1621 
1622  BLAZE_INTERNAL_ASSERT( x.size() == rhs.vec_.size() , "Invalid vector size" );
1623  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.mat_.rows() , "Invalid number of rows" );
1624  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.mat_.columns(), "Invalid number of columns" );
1625  BLAZE_INTERNAL_ASSERT( A.columns() == (~lhs).size() , "Invalid vector size" );
1626 
1627  smpAssign( ~lhs, x * A );
1628  }
1630  //**********************************************************************************************
1631 
1632  //**SMP assignment to sparse vectors************************************************************
1647  template< typename VT1 > // Type of the target sparse vector
1648  friend inline typename EnableIf< UseSMPAssign<VT1> >::Type
1649  smpAssign( SparseVector<VT1,true>& lhs, const TDVecTDMatMultExpr& rhs )
1650  {
1652 
1656 
1657  BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
1658 
1659  const ResultType tmp( rhs );
1660  smpAssign( ~lhs, tmp );
1661  }
1663  //**********************************************************************************************
1664 
1665  //**SMP addition assignment to dense vectors****************************************************
1680  template< typename VT1 > // Type of the target dense vector
1681  friend inline typename EnableIf< UseSMPAssign<VT1> >::Type
1682  smpAddAssign( DenseVector<VT1,true>& lhs, const TDVecTDMatMultExpr& rhs )
1683  {
1685 
1686  BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
1687 
1688  if( rhs.mat_.rows() == 0UL || rhs.mat_.columns() == 0UL ) {
1689  return;
1690  }
1691 
1692  LT x( rhs.vec_ ); // Evaluation of the left-hand side dense vector operand
1693  RT A( rhs.mat_ ); // Evaluation of the right-hand side dense matrix operand
1694 
1695  BLAZE_INTERNAL_ASSERT( x.size() == rhs.vec_.size() , "Invalid vector size" );
1696  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.mat_.rows() , "Invalid number of rows" );
1697  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.mat_.columns(), "Invalid number of columns" );
1698  BLAZE_INTERNAL_ASSERT( A.columns() == (~lhs).size() , "Invalid vector size" );
1699 
1700  smpAddAssign( ~lhs, x * A );
1701  }
1703  //**********************************************************************************************
1704 
1705  //**SMP addition assignment to sparse vectors***************************************************
1706  // No special implementation for the SMP addition assignment to sparse vectors.
1707  //**********************************************************************************************
1708 
1709  //**SMP subtraction assignment to dense vectors*************************************************
1724  template< typename VT1 > // Type of the target dense vector
1725  friend inline typename EnableIf< UseSMPAssign<VT1> >::Type
1726  smpSubAssign( DenseVector<VT1,true>& lhs, const TDVecTDMatMultExpr& rhs )
1727  {
1729 
1730  BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
1731 
1732  if( rhs.mat_.rows() == 0UL || rhs.mat_.columns() == 0UL ) {
1733  return;
1734  }
1735 
1736  LT x( rhs.vec_ ); // Evaluation of the left-hand side dense vector operand
1737  RT A( rhs.mat_ ); // Evaluation of the right-hand side dense matrix operand
1738 
1739  BLAZE_INTERNAL_ASSERT( x.size() == rhs.vec_.size() , "Invalid vector size" );
1740  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.mat_.rows() , "Invalid number of rows" );
1741  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.mat_.columns(), "Invalid number of columns" );
1742  BLAZE_INTERNAL_ASSERT( A.columns() == (~lhs).size() , "Invalid vector size" );
1743 
1744  smpSubAssign( ~lhs, x * A );
1745  }
1747  //**********************************************************************************************
1748 
1749  //**SMP subtraction assignment to sparse vectors************************************************
1750  // No special implementation for the SMP subtraction assignment to sparse vectors.
1751  //**********************************************************************************************
1752 
1753  //**SMP multiplication assignment to dense vectors**********************************************
1768  template< typename VT1 > // Type of the target dense vector
1769  friend inline typename EnableIf< UseSMPAssign<VT1> >::Type
1770  smpMultAssign( DenseVector<VT1,true>& lhs, const TDVecTDMatMultExpr& rhs )
1771  {
1773 
1777 
1778  BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
1779 
1780  const ResultType tmp( rhs );
1781  smpMultAssign( ~lhs, tmp );
1782  }
1784  //**********************************************************************************************
1785 
1786  //**SMP multiplication assignment to sparse vectors*********************************************
1787  // No special implementation for the SMP multiplication assignment to sparse vectors.
1788  //**********************************************************************************************
1789 
1790  //**Compile time checks*************************************************************************
1797  //**********************************************************************************************
1798 };
1799 //*************************************************************************************************
1800 
1801 
1802 
1803 
1804 //=================================================================================================
1805 //
1806 // DVECSCALARMULTEXPR SPECIALIZATION
1807 //
1808 //=================================================================================================
1809 
1810 //*************************************************************************************************
1818 template< typename VT // Type of the left-hand side dense vector
1819  , typename MT // Type of the right-hand side dense matrix
1820  , typename ST > // Type of the side scalar value
1821 class DVecScalarMultExpr< TDVecTDMatMultExpr<VT,MT>, ST, true >
1822  : public DenseVector< DVecScalarMultExpr< TDVecTDMatMultExpr<VT,MT>, ST, true >, true >
1823  , private VecScalarMultExpr
1824  , private Computation
1825 {
1826  private:
1827  //**Type definitions****************************************************************************
1828  typedef TDVecTDMatMultExpr<VT,MT> VMM;
1829  typedef typename VMM::ResultType RES;
1830  typedef typename VT::ResultType VRT;
1831  typedef typename MT::ResultType MRT;
1832  typedef typename VRT::ElementType VET;
1833  typedef typename MRT::ElementType MET;
1834  typedef typename VT::CompositeType VCT;
1835  typedef typename MT::CompositeType MCT;
1836  //**********************************************************************************************
1837 
1838  //**********************************************************************************************
1840  enum { evaluateVector = IsComputation<VT>::value || RequiresEvaluation<VT>::value };
1841  //**********************************************************************************************
1842 
1843  //**********************************************************************************************
1845  enum { evaluateMatrix = ( IsComputation<MT>::value && IsSame<MET,VET>::value &&
1846  IsBlasCompatible<MET>::value ) || RequiresEvaluation<MT>::value };
1847  //**********************************************************************************************
1848 
1849  //**********************************************************************************************
1851 
1854  template< typename T1 >
1855  struct UseSMPAssign {
1856  enum { value = T1::smpAssignable && ( evaluateVector || evaluateMatrix ) };
1857  };
1858  //**********************************************************************************************
1859 
1860  //**********************************************************************************************
1862 
1865  template< typename T1, typename T2, typename T3, typename T4 >
1866  struct UseSinglePrecisionKernel {
1867  enum { value = T1::vectorizable && T2::vectorizable && T3::vectorizable &&
1868  IsFloat<typename T1::ElementType>::value &&
1869  IsFloat<typename T2::ElementType>::value &&
1870  IsFloat<typename T3::ElementType>::value &&
1871  !IsComplex<T4>::value };
1872  };
1873  //**********************************************************************************************
1874 
1875  //**********************************************************************************************
1877 
1880  template< typename T1, typename T2, typename T3, typename T4 >
1881  struct UseDoublePrecisionKernel {
1882  enum { value = T1::vectorizable && T2::vectorizable && T3::vectorizable &&
1883  IsDouble<typename T1::ElementType>::value &&
1884  IsDouble<typename T2::ElementType>::value &&
1885  IsDouble<typename T3::ElementType>::value &&
1886  !IsComplex<T4>::value };
1887  };
1888  //**********************************************************************************************
1889 
1890  //**********************************************************************************************
1892 
1895  template< typename T1, typename T2, typename T3 >
1896  struct UseSinglePrecisionComplexKernel {
1897  typedef complex<float> Type;
1898  enum { value = T1::vectorizable && T2::vectorizable && T3::vectorizable &&
1899  IsSame<typename T1::ElementType,Type>::value &&
1900  IsSame<typename T2::ElementType,Type>::value &&
1901  IsSame<typename T3::ElementType,Type>::value };
1902  };
1903  //**********************************************************************************************
1904 
1905  //**********************************************************************************************
1907 
1910  template< typename T1, typename T2, typename T3 >
1911  struct UseDoublePrecisionComplexKernel {
1912  typedef complex<double> Type;
1913  enum { value = T1::vectorizable && T2::vectorizable && T3::vectorizable &&
1914  IsSame<typename T1::ElementType,Type>::value &&
1915  IsSame<typename T2::ElementType,Type>::value &&
1916  IsSame<typename T3::ElementType,Type>::value };
1917  };
1918  //**********************************************************************************************
1919 
1920  //**********************************************************************************************
1922 
1924  template< typename T1, typename T2, typename T3, typename T4 >
1925  struct UseDefaultKernel {
1926  enum { value = !BLAZE_BLAS_MODE || ( !UseSinglePrecisionKernel<T1,T2,T3,T4>::value &&
1927  !UseDoublePrecisionKernel<T1,T2,T3,T4>::value &&
1928  !UseSinglePrecisionComplexKernel<T1,T2,T3>::value &&
1929  !UseDoublePrecisionComplexKernel<T1,T2,T3>::value ) };
1930  };
1931  //**********************************************************************************************
1932 
1933  //**********************************************************************************************
1935 
1938  template< typename T1, typename T2, typename T3, typename T4 >
1939  struct UseVectorizedDefaultKernel {
1940  enum { value = T1::vectorizable && T2::vectorizable && T3::vectorizable &&
1941  IsSame<typename T1::ElementType,typename T2::ElementType>::value &&
1942  IsSame<typename T1::ElementType,typename T3::ElementType>::value &&
1943  IsSame<typename T1::ElementType,T4>::value &&
1944  IntrinsicTrait<typename T1::ElementType>::addition &&
1945  IntrinsicTrait<typename T1::ElementType>::multiplication };
1946  };
1947  //**********************************************************************************************
1948 
1949  public:
1950  //**Type definitions****************************************************************************
1951  typedef DVecScalarMultExpr<VMM,ST,true> This;
1952  typedef typename MultTrait<RES,ST>::Type ResultType;
1953  typedef typename ResultType::TransposeType TransposeType;
1954  typedef typename ResultType::ElementType ElementType;
1955  typedef typename IntrinsicTrait<ElementType>::Type IntrinsicType;
1956  typedef const ElementType ReturnType;
1957  typedef const ResultType CompositeType;
1958 
1960  typedef const TDVecTDMatMultExpr<VT,MT> LeftOperand;
1961 
1963  typedef ST RightOperand;
1964 
1966  typedef typename SelectType< evaluateVector, const VRT, VCT >::Type LT;
1967 
1969  typedef typename SelectType< evaluateMatrix, const MRT, MCT >::Type RT;
1970  //**********************************************************************************************
1971 
1972  //**Compilation flags***************************************************************************
1974  enum { vectorizable = VT::vectorizable && MT::vectorizable &&
1975  IsSame<VET,MET>::value &&
1976  IsSame<VET,ST>::value &&
1977  IntrinsicTrait<VET>::addition &&
1978  IntrinsicTrait<VET>::multiplication };
1979 
1981  enum { smpAssignable = !evaluateVector && VT::smpAssignable &&
1982  !evaluateMatrix && MT::smpAssignable };
1983  //**********************************************************************************************
1984 
1985  //**Constructor*********************************************************************************
1991  explicit inline DVecScalarMultExpr( const VMM& vector, ST scalar )
1992  : vector_( vector ) // Left-hand side dense vector of the multiplication expression
1993  , scalar_( scalar ) // Right-hand side scalar of the multiplication expression
1994  {}
1995  //**********************************************************************************************
1996 
1997  //**Subscript operator**************************************************************************
2003  inline ReturnType operator[]( size_t index ) const {
2004  BLAZE_INTERNAL_ASSERT( index < vector_.size(), "Invalid vector access index" );
2005  return vector_[index] * scalar_;
2006  }
2007  //**********************************************************************************************
2008 
2009  //**Size function*******************************************************************************
2014  inline size_t size() const {
2015  return vector_.size();
2016  }
2017  //**********************************************************************************************
2018 
2019  //**Left operand access*************************************************************************
2024  inline LeftOperand leftOperand() const {
2025  return vector_;
2026  }
2027  //**********************************************************************************************
2028 
2029  //**Right operand access************************************************************************
2034  inline RightOperand rightOperand() const {
2035  return scalar_;
2036  }
2037  //**********************************************************************************************
2038 
2039  //**********************************************************************************************
2045  template< typename T >
2046  inline bool canAlias( const T* alias ) const {
2047  return vector_.canAlias( alias );
2048  }
2049  //**********************************************************************************************
2050 
2051  //**********************************************************************************************
2057  template< typename T >
2058  inline bool isAliased( const T* alias ) const {
2059  return vector_.isAliased( alias );
2060  }
2061  //**********************************************************************************************
2062 
2063  //**********************************************************************************************
2068  inline bool isAligned() const {
2069  return vector_.isAligned();
2070  }
2071  //**********************************************************************************************
2072 
2073  //**********************************************************************************************
2078  inline bool canSMPAssign() const {
2079  typename VMM::RightOperand A( vector_.rightOperand() );
2080  return ( !BLAZE_BLAS_IS_PARALLEL ||
2081  ( IsComputation<MT>::value && !evaluateMatrix ) ||
2082  ( A.rows() * A.columns() < TDVECTDMATMULT_THRESHOLD ) ) &&
2084  }
2085  //**********************************************************************************************
2086 
2087  private:
2088  //**Member variables****************************************************************************
2089  LeftOperand vector_;
2090  RightOperand scalar_;
2091  //**********************************************************************************************
2092 
2093  //**Assignment to dense vectors*****************************************************************
2105  template< typename VT1 // Type of the target dense vector
2106  , bool TF > // Transpose flag of the target dense vector
2107  friend inline void assign( DenseVector<VT1,TF>& lhs, const DVecScalarMultExpr& rhs )
2108  {
2110 
2111  BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
2112 
2113  typename VMM::LeftOperand left ( rhs.vector_.leftOperand() );
2114  typename VMM::RightOperand right( rhs.vector_.rightOperand() );
2115 
2116  if( right.rows() == 0UL ) {
2117  reset( ~lhs );
2118  return;
2119  }
2120  else if( right.columns() == 0UL ) {
2121  return;
2122  }
2123 
2124  LT x( serial( left ) ); // Evaluation of the left-hand side dense vector operand
2125  RT A( serial( right ) ); // Evaluation of the right-hand side dense matrix operand
2126 
2127  BLAZE_INTERNAL_ASSERT( x.size() == left.size() , "Invalid vector size" );
2128  BLAZE_INTERNAL_ASSERT( A.rows() == right.rows() , "Invalid number of rows" );
2129  BLAZE_INTERNAL_ASSERT( A.columns() == right.columns(), "Invalid number of columns" );
2130  BLAZE_INTERNAL_ASSERT( A.columns() == (~lhs).size() , "Invalid vector size" );
2131 
2132  DVecScalarMultExpr::selectAssignKernel( ~lhs, x, A, rhs.scalar_ );
2133  }
2134  //**********************************************************************************************
2135 
2136  //**Assignment to dense vectors (kernel selection)**********************************************
2147  template< typename VT1 // Type of the left-hand side target vector
2148  , typename VT2 // Type of the left-hand side vector operand
2149  , typename MT1 // Type of the right-hand side matrix operand
2150  , typename ST2 > // Type of the scalar value
2151  static inline void selectAssignKernel( VT1& y, const VT2& x, const MT1& A, ST2 scalar )
2152  {
2153  if( ( IsComputation<MT>::value && !evaluateMatrix ) ||
2154  ( A.rows() * A.columns() < TDVECTDMATMULT_THRESHOLD ) )
2155  DVecScalarMultExpr::selectDefaultAssignKernel( y, x, A, scalar );
2156  else
2157  DVecScalarMultExpr::selectBlasAssignKernel( y, x, A, scalar );
2158  }
2159  //**********************************************************************************************
2160 
2161  //**Default assignment to dense vectors*********************************************************
2175  template< typename VT1 // Type of the left-hand side target vector
2176  , typename VT2 // Type of the left-hand side vector operand
2177  , typename MT1 // Type of the right-hand side matrix operand
2178  , typename ST2 > // Type of the scalar value
2179  static inline typename DisableIf< UseVectorizedDefaultKernel<VT1,VT2,MT1,ST2> >::Type
2180  selectDefaultAssignKernel( VT1& y, const VT2& x, const MT1& A, ST2 scalar )
2181  {
2182  y.assign( x * A * scalar );
2183  }
2184  //**********************************************************************************************
2185 
2186  //**Vectorized default assignment to dense vectors**********************************************
2200  template< typename VT1 // Type of the left-hand side target vector
2201  , typename VT2 // Type of the left-hand side vector operand
2202  , typename MT1 // Type of the right-hand side matrix operand
2203  , typename ST2 > // Type of the scalar value
2204  static inline typename EnableIf< UseVectorizedDefaultKernel<VT1,VT2,MT1,ST2> >::Type
2205  selectDefaultAssignKernel( VT1& y, const VT2& x, const MT1& A, ST2 scalar )
2206  {
2207  typedef IntrinsicTrait<ElementType> IT;
2208 
2209  const size_t M( A.rows() );
2210  const size_t N( A.columns() );
2211 
2212  size_t j( 0UL );
2213 
2214  for( ; (j+8UL) <= N; j+=8UL ) {
2215  IntrinsicType xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7, xmm8;
2216  for( size_t i=0UL; i<M; i+=IT::size ) {
2217  const IntrinsicType x1( x.load(i) );
2218  xmm1 = xmm1 + x1 * A.load(i,j );
2219  xmm2 = xmm2 + x1 * A.load(i,j+1UL);
2220  xmm3 = xmm3 + x1 * A.load(i,j+2UL);
2221  xmm4 = xmm4 + x1 * A.load(i,j+3UL);
2222  xmm5 = xmm5 + x1 * A.load(i,j+4UL);
2223  xmm6 = xmm6 + x1 * A.load(i,j+5UL);
2224  xmm7 = xmm7 + x1 * A.load(i,j+6UL);
2225  xmm8 = xmm8 + x1 * A.load(i,j+7UL);
2226  }
2227  y[j ] = sum( xmm1 ) * scalar;
2228  y[j+1UL] = sum( xmm2 ) * scalar;
2229  y[j+2UL] = sum( xmm3 ) * scalar;
2230  y[j+3UL] = sum( xmm4 ) * scalar;
2231  y[j+4UL] = sum( xmm5 ) * scalar;
2232  y[j+5UL] = sum( xmm6 ) * scalar;
2233  y[j+6UL] = sum( xmm7 ) * scalar;
2234  y[j+7UL] = sum( xmm8 ) * scalar;
2235  }
2236  for( ; (j+4UL) <= N; j+=4UL ) {
2237  IntrinsicType xmm1, xmm2, xmm3, xmm4;
2238  for( size_t i=0UL; i<M; i+=IT::size ) {
2239  const IntrinsicType x1( x.load(i) );
2240  xmm1 = xmm1 + x1 * A.load(i,j );
2241  xmm2 = xmm2 + x1 * A.load(i,j+1UL);
2242  xmm3 = xmm3 + x1 * A.load(i,j+2UL);
2243  xmm4 = xmm4 + x1 * A.load(i,j+3UL);
2244  }
2245  y[j ] = sum( xmm1 ) * scalar;
2246  y[j+1UL] = sum( xmm2 ) * scalar;
2247  y[j+2UL] = sum( xmm3 ) * scalar;
2248  y[j+3UL] = sum( xmm4 ) * scalar;
2249  }
2250  for( ; (j+3UL) <= N; j+=3UL ) {
2251  IntrinsicType xmm1, xmm2, xmm3;
2252  for( size_t i=0UL; i<M; i+=IT::size ) {
2253  const IntrinsicType x1( x.load(i) );
2254  xmm1 = xmm1 + x1 * A.load(i,j );
2255  xmm2 = xmm2 + x1 * A.load(i,j+1UL);
2256  xmm3 = xmm3 + x1 * A.load(i,j+2UL);
2257  }
2258  y[j ] = sum( xmm1 ) * scalar;
2259  y[j+1UL] = sum( xmm2 ) * scalar;
2260  y[j+2UL] = sum( xmm3 ) * scalar;
2261  }
2262  for( ; (j+2UL) <= N; j+=2UL ) {
2263  IntrinsicType xmm1, xmm2;
2264  for( size_t i=0UL; i<M; i+=IT::size ) {
2265  const IntrinsicType x1( x.load(i) );
2266  xmm1 = xmm1 + x1 * A.load(i,j );
2267  xmm2 = xmm2 + x1 * A.load(i,j+1UL);
2268  }
2269  y[j ] = sum( xmm1 ) * scalar;
2270  y[j+1UL] = sum( xmm2 ) * scalar;
2271  }
2272  if( j < N ) {
2273  IntrinsicType xmm1;
2274  for( size_t i=0UL; i<M; i+=IT::size ) {
2275  xmm1 = xmm1 + A.load(i,j) * x.load(i);
2276  }
2277  y[j] = sum( xmm1 ) * scalar;
2278  }
2279  }
2280  //**********************************************************************************************
2281 
2282  //**BLAS-based assignment to dense vectors (default)********************************************
2295  template< typename VT1 // Type of the left-hand side target vector
2296  , typename VT2 // Type of the left-hand side vector operand
2297  , typename MT1 // Type of the right-hand side matrix operand
2298  , typename ST2 > // Type of the scalar value
2299  static inline typename EnableIf< UseDefaultKernel<VT1,VT2,MT1,ST2> >::Type
2300  selectBlasAssignKernel( VT1& y, const VT2& x, const MT1& A, ST2 scalar )
2301  {
2302  selectDefaultAssignKernel( y, x, A, scalar );
2303  }
2304  //**********************************************************************************************
2305 
2306  //**BLAS-based assignment to dense vectors (single precision)***********************************
2307 #if BLAZE_BLAS_MODE
2308 
2321  template< typename VT1 // Type of the left-hand side target vector
2322  , typename VT2 // Type of the left-hand side vector operand
2323  , typename MT1 // Type of the right-hand side matrix operand
2324  , typename ST2 > // Type of the scalar value
2325  static inline typename EnableIf< UseSinglePrecisionKernel<VT1,VT2,MT1,ST2> >::Type
2326  selectBlasAssignKernel( VT1& y, const VT2& x, const MT1& A, ST2 scalar )
2327  {
2328  using boost::numeric_cast;
2329 
2333 
2334  const int M ( numeric_cast<int>( A.rows() ) );
2335  const int N ( numeric_cast<int>( A.columns() ) );
2336  const int lda( numeric_cast<int>( A.spacing() ) );
2337 
2338  cblas_sgemv( CblasColMajor, CblasTrans, M, N, scalar,
2339  A.data(), lda, x.data(), 1, 0.0F, y.data(), 1 );
2340  }
2341 #endif
2342  //**********************************************************************************************
2343 
2344  //**BLAS-based assignment to dense vectors (double precision)***********************************
2345 #if BLAZE_BLAS_MODE
2346 
2359  template< typename VT1 // Type of the left-hand side target vector
2360  , typename VT2 // Type of the left-hand side vector operand
2361  , typename MT1 // Type of the right-hand side matrix operand
2362  , typename ST2 > // Type of the scalar value
2363  static inline typename EnableIf< UseDoublePrecisionKernel<VT1,VT2,MT1,ST2> >::Type
2364  selectBlasAssignKernel( VT1& y, const VT2& x, const MT1& A, ST2 scalar )
2365  {
2366  using boost::numeric_cast;
2367 
2371 
2372  const int M ( numeric_cast<int>( A.rows() ) );
2373  const int N ( numeric_cast<int>( A.columns() ) );
2374  const int lda( numeric_cast<int>( A.spacing() ) );
2375 
2376  cblas_dgemv( CblasColMajor, CblasTrans, M, N, scalar,
2377  A.data(), lda, x.data(), 1, 0.0, y.data(), 1 );
2378  }
2379 #endif
2380  //**********************************************************************************************
2381 
2382  //**BLAS-based assignment to dense vectors (single precision complex)***************************
2383 #if BLAZE_BLAS_MODE
2384 
2398  template< typename VT1 // Type of the left-hand side target vector
2399  , typename VT2 // Type of the left-hand side vector operand
2400  , typename MT1 // Type of the right-hand side matrix operand
2401  , typename ST2 > // Type of the scalar value
2402  static inline typename EnableIf< UseSinglePrecisionComplexKernel<VT1,VT2,MT1> >::Type
2403  selectBlasAssignKernel( VT1& y, const VT2& x, const MT1& A, ST2 scalar )
2404  {
2405  using boost::numeric_cast;
2406 
2410  BLAZE_CONSTRAINT_MUST_BE_FLOAT_TYPE ( typename VT1::ElementType::value_type );
2411  BLAZE_CONSTRAINT_MUST_BE_FLOAT_TYPE ( typename VT2::ElementType::value_type );
2412  BLAZE_CONSTRAINT_MUST_BE_FLOAT_TYPE ( typename MT1::ElementType::value_type );
2413 
2414  const int M ( numeric_cast<int>( A.rows() ) );
2415  const int N ( numeric_cast<int>( A.columns() ) );
2416  const int lda( numeric_cast<int>( A.spacing() ) );
2417  const complex<float> alpha( scalar );
2418  const complex<float> beta ( 0.0F, 0.0F );
2419 
2420  cblas_cgemv( CblasColMajor, CblasTrans, M, N, &alpha,
2421  A.data(), lda, x.data(), 1, &beta, y.data(), 1 );
2422  }
2423 #endif
2424  //**********************************************************************************************
2425 
2426  //**BLAS-based assignment to dense vectors (double precision complex)***************************
2427 #if BLAZE_BLAS_MODE
2428 
2442  template< typename VT1 // Type of the left-hand side target vector
2443  , typename VT2 // Type of the left-hand side vector operand
2444  , typename MT1 // Type of the right-hand side matrix operand
2445  , typename ST2 > // Type of the scalar value
2446  static inline typename EnableIf< UseDoublePrecisionComplexKernel<VT1,VT2,MT1> >::Type
2447  selectBlasAssignKernel( VT1& y, const VT2& x, const MT1& A, ST2 scalar )
2448  {
2449  using boost::numeric_cast;
2450 
2454  BLAZE_CONSTRAINT_MUST_BE_DOUBLE_TYPE ( typename VT1::ElementType::value_type );
2455  BLAZE_CONSTRAINT_MUST_BE_DOUBLE_TYPE ( typename VT2::ElementType::value_type );
2456  BLAZE_CONSTRAINT_MUST_BE_DOUBLE_TYPE ( typename MT1::ElementType::value_type );
2457 
2458  const int M ( numeric_cast<int>( A.rows() ) );
2459  const int N ( numeric_cast<int>( A.columns() ) );
2460  const int lda( numeric_cast<int>( A.spacing() ) );
2461  const complex<double> alpha( scalar );
2462  const complex<double> beta ( 0.0, 0.0 );
2463 
2464  cblas_zgemv( CblasColMajor, CblasTrans, M, N, &alpha,
2465  A.data(), lda, x.data(), 1, &beta, y.data(), 1 );
2466  }
2467 #endif
2468  //**********************************************************************************************
2469 
2470  //**Assignment to sparse vectors****************************************************************
2482  template< typename VT1 // Type of the target sparse vector
2483  , bool TF > // Transpose flag of the target sparse vector
2484  friend inline void assign( SparseVector<VT1,TF>& lhs, const DVecScalarMultExpr& rhs )
2485  {
2487 
2491 
2492  BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
2493 
2494  const ResultType tmp( serial( rhs ) );
2495  assign( ~lhs, tmp );
2496  }
2497  //**********************************************************************************************
2498 
2499  //**Addition assignment to dense vectors********************************************************
2511  template< typename VT1 // Type of the target dense vector
2512  , bool TF > // Transpose flag of the target dense vector
2513  friend inline void addAssign( DenseVector<VT1,TF>& lhs, const DVecScalarMultExpr& rhs )
2514  {
2516 
2517  BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
2518 
2519  typename VMM::LeftOperand left ( rhs.vector_.leftOperand() );
2520  typename VMM::RightOperand right( rhs.vector_.rightOperand() );
2521 
2522  if( right.rows() == 0UL || right.columns() == 0UL ) {
2523  return;
2524  }
2525 
2526  LT x( serial( left ) ); // Evaluation of the left-hand side dense vector operand
2527  RT A( serial( right ) ); // Evaluation of the right-hand side dense matrix operand
2528 
2529  BLAZE_INTERNAL_ASSERT( x.size() == left.size() , "Invalid vector size" );
2530  BLAZE_INTERNAL_ASSERT( A.rows() == right.rows() , "Invalid number of rows" );
2531  BLAZE_INTERNAL_ASSERT( A.columns() == right.columns(), "Invalid number of columns" );
2532  BLAZE_INTERNAL_ASSERT( A.columns() == (~lhs).size() , "Invalid vector size" );
2533 
2534  DVecScalarMultExpr::selectAddAssignKernel( ~lhs, x, A, rhs.scalar_ );
2535  }
2536  //**********************************************************************************************
2537 
2538  //**Addition assignment to dense vectors (kernel selection)*************************************
2549  template< typename VT1 // Type of the left-hand side target vector
2550  , typename VT2 // Type of the left-hand side vector operand
2551  , typename MT1 // Type of the right-hand side matrix operand
2552  , typename ST2 > // Type of the scalar value
2553  static inline void selectAddAssignKernel( VT1& y, const VT2& x, const MT1& A, ST2 scalar )
2554  {
2555  if( ( IsComputation<MT>::value && !evaluateMatrix ) ||
2556  ( A.rows() * A.columns() < TDVECDMATMULT_THRESHOLD ) )
2557  DVecScalarMultExpr::selectDefaultAddAssignKernel( y, x, A, scalar );
2558  else
2559  DVecScalarMultExpr::selectBlasAddAssignKernel( y, x, A, scalar );
2560  }
2561  //**********************************************************************************************
2562 
2563  //**Default addition assignment to dense vectors************************************************
2577  template< typename VT1 // Type of the left-hand side target vector
2578  , typename VT2 // Type of the left-hand side vector operand
2579  , typename MT1 // Type of the right-hand side matrix operand
2580  , typename ST2 > // Type of the scalar value
2581  static inline typename DisableIf< UseVectorizedDefaultKernel<VT1,VT2,MT1,ST2> >::Type
2582  selectDefaultAddAssignKernel( VT1& y, const VT2& x, const MT1& A, ST2 scalar )
2583  {
2584  y.addAssign( x * A * scalar );
2585  }
2586  //**********************************************************************************************
2587 
2588  //**Vectorized default addition assignment to dense vectors*************************************
2602  template< typename VT1 // Type of the left-hand side target vector
2603  , typename VT2 // Type of the left-hand side vector operand
2604  , typename MT1 // Type of the right-hand side matrix operand
2605  , typename ST2 > // Type of the scalar value
2606  static inline typename EnableIf< UseVectorizedDefaultKernel<VT1,VT2,MT1,ST2> >::Type
2607  selectDefaultAddAssignKernel( VT1& y, const VT2& x, const MT1& A, ST2 scalar )
2608  {
2609  typedef IntrinsicTrait<ElementType> IT;
2610 
2611  const size_t M( A.rows() );
2612  const size_t N( A.columns() );
2613 
2614  size_t j( 0UL );
2615 
2616  for( ; (j+8UL) <= N; j+=8UL ) {
2617  IntrinsicType xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7, xmm8;
2618  for( size_t i=0UL; i<M; i+=IT::size ) {
2619  const IntrinsicType x1( x.load(i) );
2620  xmm1 = xmm1 + x1 * A.load(i,j );
2621  xmm2 = xmm2 + x1 * A.load(i,j+1UL);
2622  xmm3 = xmm3 + x1 * A.load(i,j+2UL);
2623  xmm4 = xmm4 + x1 * A.load(i,j+3UL);
2624  xmm5 = xmm5 + x1 * A.load(i,j+4UL);
2625  xmm6 = xmm6 + x1 * A.load(i,j+5UL);
2626  xmm7 = xmm7 + x1 * A.load(i,j+6UL);
2627  xmm8 = xmm8 + x1 * A.load(i,j+7UL);
2628  }
2629  y[j ] += sum( xmm1 ) * scalar;
2630  y[j+1UL] += sum( xmm2 ) * scalar;
2631  y[j+2UL] += sum( xmm3 ) * scalar;
2632  y[j+3UL] += sum( xmm4 ) * scalar;
2633  y[j+4UL] += sum( xmm5 ) * scalar;
2634  y[j+5UL] += sum( xmm6 ) * scalar;
2635  y[j+6UL] += sum( xmm7 ) * scalar;
2636  y[j+7UL] += sum( xmm8 ) * scalar;
2637  }
2638  for( ; (j+4UL) <= N; j+=4UL ) {
2639  IntrinsicType xmm1, xmm2, xmm3, xmm4;
2640  for( size_t i=0UL; i<M; i+=IT::size ) {
2641  const IntrinsicType x1( x.load(i) );
2642  xmm1 = xmm1 + x1 * A.load(i,j );
2643  xmm2 = xmm2 + x1 * A.load(i,j+1UL);
2644  xmm3 = xmm3 + x1 * A.load(i,j+2UL);
2645  xmm4 = xmm4 + x1 * A.load(i,j+3UL);
2646  }
2647  y[j ] += sum( xmm1 ) * scalar;
2648  y[j+1UL] += sum( xmm2 ) * scalar;
2649  y[j+2UL] += sum( xmm3 ) * scalar;
2650  y[j+3UL] += sum( xmm4 ) * scalar;
2651  }
2652  for( ; (j+3UL) <= N; j+=3UL ) {
2653  IntrinsicType xmm1, xmm2, xmm3;
2654  for( size_t i=0UL; i<M; i+=IT::size ) {
2655  const IntrinsicType x1( x.load(i) );
2656  xmm1 = xmm1 + x1 * A.load(i,j );
2657  xmm2 = xmm2 + x1 * A.load(i,j+1UL);
2658  xmm3 = xmm3 + x1 * A.load(i,j+2UL);
2659  }
2660  y[j ] += sum( xmm1 ) * scalar;
2661  y[j+1UL] += sum( xmm2 ) * scalar;
2662  y[j+2UL] += sum( xmm3 ) * scalar;
2663  }
2664  for( ; (j+2UL) <= N; j+=2UL ) {
2665  IntrinsicType xmm1, xmm2;
2666  for( size_t i=0UL; i<M; i+=IT::size ) {
2667  const IntrinsicType x1( x.load(i) );
2668  xmm1 = xmm1 + x1 * A.load(i,j );
2669  xmm2 = xmm2 + x1 * A.load(i,j+1UL);
2670  }
2671  y[j ] += sum( xmm1 ) * scalar;
2672  y[j+1UL] += sum( xmm2 ) * scalar;
2673  }
2674  if( j < N ) {
2675  IntrinsicType xmm1;
2676  for( size_t i=0UL; i<M; i+=IT::size ) {
2677  xmm1 = xmm1 + A.load(i,j) * x.load(i);
2678  }
2679  y[j] += sum( xmm1 ) * scalar;
2680  }
2681  }
2682  //**********************************************************************************************
2683 
2684  //**BLAS-based addition assignment to dense vectors (default)***********************************
2698  template< typename VT1 // Type of the left-hand side target vector
2699  , typename VT2 // Type of the left-hand side vector operand
2700  , typename MT1 // Type of the right-hand side matrix operand
2701  , typename ST2 > // Type of the scalar value
2702  static inline typename EnableIf< UseDefaultKernel<VT1,VT2,MT1,ST2> >::Type
2703  selectBlasAddAssignKernel( VT1& y, const VT2& x, const MT1& A, ST2 scalar )
2704  {
2705  selectDefaultAddAssignKernel( y, x, A, scalar );
2706  }
2707  //**********************************************************************************************
2708 
2709  //**BLAS-based addition assignment to dense vectors (single precision)**************************
2710 #if BLAZE_BLAS_MODE
2711 
2724  template< typename VT1 // Type of the left-hand side target vector
2725  , typename VT2 // Type of the left-hand side vector operand
2726  , typename MT1 // Type of the right-hand side matrix operand
2727  , typename ST2 > // Type of the scalar value
2728  static inline typename EnableIf< UseSinglePrecisionKernel<VT1,VT2,MT1,ST2> >::Type
2729  selectBlasAddAssignKernel( VT1& y, const VT2& x, const MT1& A, ST2 scalar )
2730  {
2731  using boost::numeric_cast;
2732 
2736 
2737  const int M ( numeric_cast<int>( A.rows() ) );
2738  const int N ( numeric_cast<int>( A.columns() ) );
2739  const int lda( numeric_cast<int>( A.spacing() ) );
2740 
2741  cblas_sgemv( CblasColMajor, CblasTrans, M, N, scalar,
2742  A.data(), lda, x.data(), 1, 1.0F, y.data(), 1 );
2743  }
2744 #endif
2745  //**********************************************************************************************
2746 
2747  //**BLAS-based addition assignment to dense vectors (double precision)**************************
2748 #if BLAZE_BLAS_MODE
2749 
2762  template< typename VT1 // Type of the left-hand side target vector
2763  , typename VT2 // Type of the left-hand side vector operand
2764  , typename MT1 // Type of the right-hand side matrix operand
2765  , typename ST2 > // Type of the scalar value
2766  static inline typename EnableIf< UseDoublePrecisionKernel<VT1,VT2,MT1,ST2> >::Type
2767  selectBlasAddAssignKernel( VT1& y, const VT2& x, const MT1& A, ST2 scalar )
2768  {
2769  using boost::numeric_cast;
2770 
2774 
2775  const int M ( numeric_cast<int>( A.rows() ) );
2776  const int N ( numeric_cast<int>( A.columns() ) );
2777  const int lda( numeric_cast<int>( A.spacing() ) );
2778 
2779  cblas_dgemv( CblasColMajor, CblasTrans, M, N, scalar,
2780  A.data(), lda, x.data(), 1, 1.0, y.data(), 1 );
2781  }
2782 #endif
2783  //**********************************************************************************************
2784 
2785  //**BLAS-based addition assignment to dense vectors (single precision complex)******************
2786 #if BLAZE_BLAS_MODE
2787 
2801  template< typename VT1 // Type of the left-hand side target vector
2802  , typename VT2 // Type of the left-hand side vector operand
2803  , typename MT1 // Type of the right-hand side matrix operand
2804  , typename ST2 > // Type of the scalar value
2805  static inline typename EnableIf< UseSinglePrecisionComplexKernel<VT1,VT2,MT1> >::Type
2806  selectBlasAddAssignKernel( VT1& y, const VT2& x, const MT1& A, ST2 scalar )
2807  {
2808  using boost::numeric_cast;
2809 
2813  BLAZE_CONSTRAINT_MUST_BE_FLOAT_TYPE ( typename VT1::ElementType::value_type );
2814  BLAZE_CONSTRAINT_MUST_BE_FLOAT_TYPE ( typename VT2::ElementType::value_type );
2815  BLAZE_CONSTRAINT_MUST_BE_FLOAT_TYPE ( typename MT1::ElementType::value_type );
2816 
2817  const int M ( numeric_cast<int>( A.rows() ) );
2818  const int N ( numeric_cast<int>( A.columns() ) );
2819  const int lda( numeric_cast<int>( A.spacing() ) );
2820  const complex<float> alpha( scalar );
2821  const complex<float> beta ( 1.0F, 0.0F );
2822 
2823  cblas_cgemv( CblasColMajor, CblasTrans, M, N, &alpha,
2824  A.data(), lda, x.data(), 1, &beta, y.data(), 1 );
2825  }
2826 #endif
2827  //**********************************************************************************************
2828 
2829  //**BLAS-based addition assignment to dense vectors (double precision complex)******************
2830 #if BLAZE_BLAS_MODE
2831 
2845  template< typename VT1 // Type of the left-hand side target vector
2846  , typename VT2 // Type of the left-hand side vector operand
2847  , typename MT1 // Type of the right-hand side matrix operand
2848  , typename ST2 > // Type of the scalar value
2849  static inline typename EnableIf< UseDoublePrecisionComplexKernel<VT1,VT2,MT1> >::Type
2850  selectBlasAddAssignKernel( VT1& y, const VT2& x, const MT1& A, ST2 scalar )
2851  {
2852  using boost::numeric_cast;
2853 
2857  BLAZE_CONSTRAINT_MUST_BE_DOUBLE_TYPE ( typename VT1::ElementType::value_type );
2858  BLAZE_CONSTRAINT_MUST_BE_DOUBLE_TYPE ( typename VT2::ElementType::value_type );
2859  BLAZE_CONSTRAINT_MUST_BE_DOUBLE_TYPE ( typename MT1::ElementType::value_type );
2860 
2861  const int M ( numeric_cast<int>( A.rows() ) );
2862  const int N ( numeric_cast<int>( A.columns() ) );
2863  const int lda( numeric_cast<int>( A.spacing() ) );
2864  const complex<double> alpha( scalar );
2865  const complex<double> beta ( 1.0, 0.0 );
2866 
2867  cblas_zgemv( CblasColMajor, CblasTrans, M, N, &alpha,
2868  A.data(), lda, x.data(), 1, &beta, y.data(), 1 );
2869  }
2870 #endif
2871  //**********************************************************************************************
2872 
2873  //**Addition assignment to sparse vectors*******************************************************
2874  // No special implementation for the addition assignment to sparse vectors.
2875  //**********************************************************************************************
2876 
2877  //**Subtraction assignment to dense vectors*****************************************************
2889  template< typename VT1 // Type of the target dense vector
2890  , bool TF > // Transpose flag of the target dense vector
2891  friend inline void subAssign( DenseVector<VT1,TF>& lhs, const DVecScalarMultExpr& rhs )
2892  {
2894 
2895  BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
2896 
2897  typename VMM::LeftOperand left ( rhs.vector_.leftOperand() );
2898  typename VMM::RightOperand right( rhs.vector_.rightOperand() );
2899 
2900  if( right.rows() == 0UL || right.columns() == 0UL ) {
2901  return;
2902  }
2903 
2904  LT x( serial( left ) ); // Evaluation of the left-hand side dense vector operand
2905  RT A( serial( right ) ); // Evaluation of the right-hand side dense matrix operand
2906 
2907  BLAZE_INTERNAL_ASSERT( x.size() == left.size() , "Invalid vector size" );
2908  BLAZE_INTERNAL_ASSERT( A.rows() == right.rows() , "Invalid number of rows" );
2909  BLAZE_INTERNAL_ASSERT( A.columns() == right.columns(), "Invalid number of columns" );
2910  BLAZE_INTERNAL_ASSERT( A.columns() == (~lhs).size() , "Invalid vector size" );
2911 
2912  DVecScalarMultExpr::selectSubAssignKernel( ~lhs, x, A, rhs.scalar_ );
2913  }
2914  //**********************************************************************************************
2915 
2916  //**Subtraction assignment to dense vectors (kernel selection)**********************************
2927  template< typename VT1 // Type of the left-hand side target vector
2928  , typename VT2 // Type of the left-hand side vector operand
2929  , typename MT1 // Type of the right-hand side matrix operand
2930  , typename ST2 > // Type of the scalar value
2931  static inline void selectSubAssignKernel( VT1& y, const VT2& x, const MT1& A, ST2 scalar )
2932  {
2933  if( ( IsComputation<MT>::value && !evaluateMatrix ) ||
2934  ( A.rows() * A.columns() < TDVECDMATMULT_THRESHOLD ) )
2935  DVecScalarMultExpr::selectDefaultSubAssignKernel( y, x, A, scalar );
2936  else
2937  DVecScalarMultExpr::selectBlasSubAssignKernel( y, x, A, scalar );
2938  }
2939  //**********************************************************************************************
2940 
2941  //**Default subtraction assignment to dense vectors*********************************************
2955  template< typename VT1 // Type of the left-hand side target vector
2956  , typename VT2 // Type of the left-hand side vector operand
2957  , typename MT1 // Type of the right-hand side matrix operand
2958  , typename ST2 > // Type of the scalar value
2959  static inline typename DisableIf< UseVectorizedDefaultKernel<VT1,VT2,MT1,ST2> >::Type
2960  selectDefaultSubAssignKernel( VT1& y, const VT2& x, const MT1& A, ST2 scalar )
2961  {
2962  y.subAssign( x * A * scalar );
2963  }
2964  //**********************************************************************************************
2965 
2966  //**Vectorized default subtraction assignment to dense vectors**********************************
2980  template< typename VT1 // Type of the left-hand side target vector
2981  , typename VT2 // Type of the left-hand side vector operand
2982  , typename MT1 // Type of the right-hand side matrix operand
2983  , typename ST2 > // Type of the scalar value
2984  static inline typename EnableIf< UseVectorizedDefaultKernel<VT1,VT2,MT1,ST2> >::Type
2985  selectDefaultSubAssignKernel( VT1& y, const VT2& x, const MT1& A, ST2 scalar )
2986  {
2987  typedef IntrinsicTrait<ElementType> IT;
2988 
2989  const size_t M( A.rows() );
2990  const size_t N( A.columns() );
2991 
2992  size_t j( 0UL );
2993 
2994  for( ; (j+8UL) <= N; j+=8UL ) {
2995  IntrinsicType xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7, xmm8;
2996  for( size_t i=0UL; i<M; i+=IT::size ) {
2997  const IntrinsicType x1( x.load(i) );
2998  xmm1 = xmm1 + x1 * A.load(i,j );
2999  xmm2 = xmm2 + x1 * A.load(i,j+1UL);
3000  xmm3 = xmm3 + x1 * A.load(i,j+2UL);
3001  xmm4 = xmm4 + x1 * A.load(i,j+3UL);
3002  xmm5 = xmm5 + x1 * A.load(i,j+4UL);
3003  xmm6 = xmm6 + x1 * A.load(i,j+5UL);
3004  xmm7 = xmm7 + x1 * A.load(i,j+6UL);
3005  xmm8 = xmm8 + x1 * A.load(i,j+7UL);
3006  }
3007  y[j ] -= sum( xmm1 ) * scalar;
3008  y[j+1UL] -= sum( xmm2 ) * scalar;
3009  y[j+2UL] -= sum( xmm3 ) * scalar;
3010  y[j+3UL] -= sum( xmm4 ) * scalar;
3011  y[j+4UL] -= sum( xmm5 ) * scalar;
3012  y[j+5UL] -= sum( xmm6 ) * scalar;
3013  y[j+6UL] -= sum( xmm7 ) * scalar;
3014  y[j+7UL] -= sum( xmm8 ) * scalar;
3015  }
3016  for( ; (j+4UL) <= N; j+=4UL ) {
3017  IntrinsicType xmm1, xmm2, xmm3, xmm4;
3018  for( size_t i=0UL; i<M; i+=IT::size ) {
3019  const IntrinsicType x1( x.load(i) );
3020  xmm1 = xmm1 + x1 * A.load(i,j );
3021  xmm2 = xmm2 + x1 * A.load(i,j+1UL);
3022  xmm3 = xmm3 + x1 * A.load(i,j+2UL);
3023  xmm4 = xmm4 + x1 * A.load(i,j+3UL);
3024  }
3025  y[j ] -= sum( xmm1 ) * scalar;
3026  y[j+1UL] -= sum( xmm2 ) * scalar;
3027  y[j+2UL] -= sum( xmm3 ) * scalar;
3028  y[j+3UL] -= sum( xmm4 ) * scalar;
3029  }
3030  for( ; (j+3UL) <= N; j+=3UL ) {
3031  IntrinsicType xmm1, xmm2, xmm3;
3032  for( size_t i=0UL; i<M; i+=IT::size ) {
3033  const IntrinsicType x1( x.load(i) );
3034  xmm1 = xmm1 + x1 * A.load(i,j );
3035  xmm2 = xmm2 + x1 * A.load(i,j+1UL);
3036  xmm3 = xmm3 + x1 * A.load(i,j+2UL);
3037  }
3038  y[j ] -= sum( xmm1 ) * scalar;
3039  y[j+1UL] -= sum( xmm2 ) * scalar;
3040  y[j+2UL] -= sum( xmm3 ) * scalar;
3041  }
3042  for( ; (j+2UL) <= N; j+=2UL ) {
3043  IntrinsicType xmm1, xmm2;
3044  for( size_t i=0UL; i<M; i+=IT::size ) {
3045  const IntrinsicType x1( x.load(i) );
3046  xmm1 = xmm1 + x1 * A.load(i,j );
3047  xmm2 = xmm2 + x1 * A.load(i,j+1UL);
3048  }
3049  y[j ] -= sum( xmm1 ) * scalar;
3050  y[j+1UL] -= sum( xmm2 ) * scalar;
3051  }
3052  if( j < N ) {
3053  IntrinsicType xmm1;
3054  for( size_t i=0UL; i<M; i+=IT::size ) {
3055  xmm1 = xmm1 + A.load(i,j) * x.load(i);
3056  }
3057  y[j] -= sum( xmm1 ) * scalar;
3058  }
3059  }
3060  //**********************************************************************************************
3061 
3062  //**BLAS-based subtraction assignment to dense vectors (default)********************************
3077  template< typename VT1 // Type of the left-hand side target vector
3078  , typename VT2 // Type of the left-hand side vector operand
3079  , typename MT1 // Type of the right-hand side matrix operand
3080  , typename ST2 > // Type of the scalar value
3081  static inline typename EnableIf< UseDefaultKernel<VT1,VT2,MT1,ST2> >::Type
3082  selectBlasSubAssignKernel( VT1& y, const VT2& x, const MT1& A, ST2 scalar )
3083  {
3084  selectDefaultSubAssignKernel( y, x, A, scalar );
3085  }
3086  //**********************************************************************************************
3087 
3088  //**BLAS-based subtraction assignment to dense vectors (single precision)***********************
3089 #if BLAZE_BLAS_MODE
3090 
3103  template< typename VT1 // Type of the left-hand side target vector
3104  , typename VT2 // Type of the left-hand side vector operand
3105  , typename MT1 // Type of the right-hand side matrix operand
3106  , typename ST2 > // Type of the scalar value
3107  static inline typename EnableIf< UseSinglePrecisionKernel<VT1,VT2,MT1,ST2> >::Type
3108  selectBlasSubAssignKernel( VT1& y, const VT2& x, const MT1& A, ST2 scalar )
3109  {
3110  using boost::numeric_cast;
3111 
3115 
3116  const int M ( numeric_cast<int>( A.rows() ) );
3117  const int N ( numeric_cast<int>( A.columns() ) );
3118  const int lda( numeric_cast<int>( A.spacing() ) );
3119 
3120  cblas_sgemv( CblasColMajor, CblasTrans, M, N, -scalar,
3121  A.data(), lda, x.data(), 1, 1.0F, y.data(), 1 );
3122  }
3123 #endif
3124  //**********************************************************************************************
3125 
3126  //**BLAS-based subtraction assignment to dense vectors (double precision)***********************
3127 #if BLAZE_BLAS_MODE
3128 
3141  template< typename VT1 // Type of the left-hand side target vector
3142  , typename VT2 // Type of the left-hand side vector operand
3143  , typename MT1 // Type of the right-hand side matrix operand
3144  , typename ST2 > // Type of the scalar value
3145  static inline typename EnableIf< UseDoublePrecisionKernel<VT1,VT2,MT1,ST2> >::Type
3146  selectBlasSubAssignKernel( VT1& y, const VT2& x, const MT1& A, ST2 scalar )
3147  {
3148  using boost::numeric_cast;
3149 
3153 
3154  const int M ( numeric_cast<int>( A.rows() ) );
3155  const int N ( numeric_cast<int>( A.columns() ) );
3156  const int lda( numeric_cast<int>( A.spacing() ) );
3157 
3158  cblas_dgemv( CblasColMajor, CblasTrans, M, N, -scalar,
3159  A.data(), lda, x.data(), 1, 1.0, y.data(), 1 );
3160  }
3161 #endif
3162  //**********************************************************************************************
3163 
3164  //**BLAS-based subtraction assignment to dense vectors (single precision complex)***************
3165 #if BLAZE_BLAS_MODE
3166 
3181  template< typename VT1 // Type of the left-hand side target vector
3182  , typename VT2 // Type of the left-hand side vector operand
3183  , typename MT1 // Type of the right-hand side matrix operand
3184  , typename ST2 > // Type of the scalar value
3185  static inline typename EnableIf< UseSinglePrecisionComplexKernel<VT1,VT2,MT1> >::Type
3186  selectBlasSubAssignKernel( VT1& y, const VT2& x, const MT1& A, ST2 scalar )
3187  {
3188  using boost::numeric_cast;
3189 
3193  BLAZE_CONSTRAINT_MUST_BE_FLOAT_TYPE ( typename VT1::ElementType::value_type );
3194  BLAZE_CONSTRAINT_MUST_BE_FLOAT_TYPE ( typename VT2::ElementType::value_type );
3195  BLAZE_CONSTRAINT_MUST_BE_FLOAT_TYPE ( typename MT1::ElementType::value_type );
3196 
3197  const int M ( numeric_cast<int>( A.rows() ) );
3198  const int N ( numeric_cast<int>( A.columns() ) );
3199  const int lda( numeric_cast<int>( A.spacing() ) );
3200  const complex<float> alpha( -scalar );
3201  const complex<float> beta ( 1.0F, 0.0F );
3202 
3203  cblas_cgemv( CblasColMajor, CblasTrans, M, N, &alpha,
3204  A.data(), lda, x.data(), 1, &beta, y.data(), 1 );
3205  }
3206 #endif
3207  //**********************************************************************************************
3208 
3209  //**BLAS-based subtraction assignment to dense vectors (double precision complex)***************
3210 #if BLAZE_BLAS_MODE
3211 
3226  template< typename VT1 // Type of the left-hand side target vector
3227  , typename VT2 // Type of the left-hand side vector operand
3228  , typename MT1 // Type of the right-hand side matrix operand
3229  , typename ST2 > // Type of the scalar value
3230  static inline typename EnableIf< UseDoublePrecisionComplexKernel<VT1,VT2,MT1> >::Type
3231  selectBlasSubAssignKernel( VT1& y, const VT2& x, const MT1& A, ST2 scalar )
3232  {
3233  using boost::numeric_cast;
3234 
3238  BLAZE_CONSTRAINT_MUST_BE_DOUBLE_TYPE ( typename VT1::ElementType::value_type );
3239  BLAZE_CONSTRAINT_MUST_BE_DOUBLE_TYPE ( typename VT2::ElementType::value_type );
3240  BLAZE_CONSTRAINT_MUST_BE_DOUBLE_TYPE ( typename MT1::ElementType::value_type );
3241 
3242  const int M ( numeric_cast<int>( A.rows() ) );
3243  const int N ( numeric_cast<int>( A.columns() ) );
3244  const int lda( numeric_cast<int>( A.spacing() ) );
3245  const complex<double> alpha( -scalar );
3246  const complex<double> beta ( 1.0, 0.0 );
3247 
3248  cblas_zgemv( CblasColMajor, CblasTrans, M, N, &alpha,
3249  A.data(), lda, x.data(), 1, &beta, y.data(), 1 );
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 // EXPRESSION TRAIT SPECIALIZATIONS
3571 //
3572 //=================================================================================================
3573 
3574 //*************************************************************************************************
3576 template< typename VT, typename MT, bool AF >
3577 struct SubvectorExprTrait< TDVecTDMatMultExpr<VT,MT>, AF >
3578 {
3579  public:
3580  //**********************************************************************************************
3581  typedef typename MultExprTrait< VT, typename SubmatrixExprTrait<const MT,AF>::Type >::Type Type;
3582  //**********************************************************************************************
3583 };
3585 //*************************************************************************************************
3586 
3587 } // namespace blaze
3588 
3589 #endif
SelectType< IsExpression< VT >::value, const VT, const VT & >::Type LeftOperand
Composite type of the left-hand side dense vector expression.
Definition: TDVecTDMatMultExpr.h:251
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:399
LeftOperand leftOperand() const
Returns the left-hand side dense vector operand.
Definition: TDVecTDMatMultExpr.h:333
RightOperand rightOperand() const
Returns the right-hand side transpose dense matrix operand.
Definition: TDVecTDMatMultExpr.h:343
void reset(DynamicMatrix< Type, SO > &m)
Resetting the given dense matrix.
Definition: DynamicMatrix.h:4599
#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:4329
void smpSubAssign(DenseMatrix< MT1, SO1 > &lhs, const Matrix< MT2, SO2 > &rhs)
Default implementation of the SMP subtraction assignment of a matrix to dense matrix.
Definition: DenseMatrix.h:152
Efficient implementation of a compressed matrix.The CompressedMatrix class template is the represent...
Definition: CompressedMatrix.h:199
#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
void smpMultAssign(DenseVector< 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:179
int16_t sum(const sse_int16_t &a)
Returns the sum of all elements in the 16-bit integral intrinsic vector.
Definition: Reduction.h:62
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:115
MRT::ElementType MET
Element type of the right-hand side dense matrix expression.
Definition: TDVecTDMatMultExpr.h:113
const This & CompositeType
Data type for composite expression templates.
Definition: CompressedMatrix.h:2408
Type ElementType
Type of the sparse matrix elements.
Definition: CompressedMatrix.h:251
SelectType< evaluateMatrix, const MRT, MCT >::Type RT
Type for the assignment of the right-hand side dense vector operand.
Definition: TDVecTDMatMultExpr.h:260
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:690
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:254
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.
void smpAddAssign(DenseMatrix< 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:122
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:253
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:377
bool canAlias(const T *alias) const
Returns whether the expression can alias with the given address alias.
Definition: TDVecTDMatMultExpr.h:355
ResultType::ElementType ElementType
Resulting element type.
Definition: TDVecTDMatMultExpr.h:245
Header file for the IsMatMatMultExpr type trait class.
Header file for the IsBlasCompatible type trait.
TDVecTDMatMultExpr< VT, MT > This
Type of this TDVecTDMatMultExpr instance.
Definition: TDVecTDMatMultExpr.h:242
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:271
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:114
#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:246
SelectType< evaluateVector, const VRT, VCT >::Type LT
Type for the assignment of the left-hand side dense matrix operand.
Definition: TDVecTDMatMultExpr.h:257
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:111
VT::ResultType VRT
Result type of the left-hand side dense vector expression.
Definition: TDVecTDMatMultExpr.h:110
Type ElementType
Type of the sparse matrix elements.
Definition: CompressedMatrix.h:2406
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:361
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:296
Header file for the EnableIf class template.
Header file for the serial shim.
void smpAssign(DenseMatrix< MT1, SO1 > &lhs, const Matrix< MT2, SO2 > &rhs)
Default implementation of the SMP assignment of a matrix to a dense matrix.
Definition: DenseMatrix.h:92
Header file for the IsNumeric type trait.
Header file for the SubmatrixExprTrait class template.
bool canSMPAssign() const
Returns whether the expression can be used in SMP assignments.
Definition: TDVecTDMatMultExpr.h:387
System settings for the BLAS mode.
Intrinsic characteristics of data types.The IntrinsicTrait class template provides the intrinsic char...
Definition: IntrinsicTrait.h:748
Header file for run time assertion macros.
Base template for the MultTrait class.
Definition: MultTrait.h:141
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:301
LeftOperand vec_
Left-hand side dense vector of the multiplication expression.
Definition: TDVecTDMatMultExpr.h:397
#define BLAZE_CONSTRAINT_MUST_BE_NUMERIC_TYPE(T)
Constraint on the data type.In case the given data type T is not a numeric (integral or floating poin...
Definition: Numeric.h:79
Header file for the reset shim.
const ResultType CompositeType
Data type for composite expression templates.
Definition: TDVecTDMatMultExpr.h:248
Compile time check for data types.This type trait tests whether or not the given template parameter i...
Definition: IsBlasCompatible.h:99
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:331
Header file for the TVecMatMultExpr base class.
const ElementType ReturnType
Return type for expression template evaluations.
Definition: TDVecTDMatMultExpr.h:247
VRT::ElementType VET
Element type of the left-hand side dense vector epxression.
Definition: TDVecTDMatMultExpr.h:112
ResultType::TransposeType TransposeType
Transpose type for expression template evaluations.
Definition: TDVecTDMatMultExpr.h:244
RightOperand mat_
Right-hand side dense matrix of the multiplication expression.
Definition: TDVecTDMatMultExpr.h:398
Header file for all intrinsic functionality.
#define BLAZE_CONSTRAINT_MUST_BE_DENSE_VECTOR_TYPE(T)
Constraint on the data type.In case the given data type T is not a dense, N-dimensional vector type...
Definition: DenseVector.h:79
#define BLAZE_CONSTRAINT_MUST_BE_COMPLEX_TYPE(T)
Constraint on the data type.This compile time constraint checks that the given data type T is a compl...
Definition: Complex.h:80
bool isAliased(const T *alias) const
Returns whether the expression is aliased with the given address alias.
Definition: TDVecTDMatMultExpr.h:367
Header file for the IsComputation type trait class.
MultTrait< VRT, MRT >::Type ResultType
Result type for expression template evaluations.
Definition: TDVecTDMatMultExpr.h:243
CompressedMatrix< Type,!SO > TransposeType
Transpose type for expression template evaluations.
Definition: CompressedMatrix.h:250
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:2403
TDVecTDMatMultExpr(const VT &vec, const MT &mat)
Constructor for the TDVecTDMatMultExpr class.
Definition: TDVecTDMatMultExpr.h:281
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.
Size type of the Blaze library.
Header file for the thresholds for matrix/vector and matrix/matrix multiplications.
size_t rows(const Matrix< MT, SO > &m)
Returns the current number of rows of the matrix.
Definition: Matrix.h:154
#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:323
Header file for the IsExpression type trait class.
Header file for the FunctionTrace class.