All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
DMatDVecMultExpr.h
Go to the documentation of this file.
1 //=================================================================================================
33 //=================================================================================================
34 
35 #ifndef _BLAZE_MATH_EXPRESSIONS_DMATDVECMULTEXPR_H_
36 #define _BLAZE_MATH_EXPRESSIONS_DMATDVECMULTEXPR_H_
37 
38 
39 //*************************************************************************************************
40 // Includes
41 //*************************************************************************************************
42 
43 #include <stdexcept>
44 #include <boost/cast.hpp>
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 DMATDVECMULTEXPR
92 //
93 //=================================================================================================
94 
95 //*************************************************************************************************
102 template< typename MT // Type of the left-hand side dense matrix
103  , typename VT > // Type of the right-hand side dense vector
104 class DMatDVecMultExpr : public DenseVector< DMatDVecMultExpr<MT,VT>, false >
105  , private MatVecMultExpr
106  , private Computation
107 {
108  private:
109  //**Type definitions****************************************************************************
110  typedef typename MT::ResultType MRT;
111  typedef typename VT::ResultType VRT;
112  typedef typename MRT::ElementType MET;
113  typedef typename VRT::ElementType VET;
114  typedef typename MT::CompositeType MCT;
115  typedef typename VT::CompositeType VCT;
116  //**********************************************************************************************
117 
118  //**********************************************************************************************
120  enum { evaluateMatrix = ( IsComputation<MT>::value && IsSame<MET,VET>::value &&
122  //**********************************************************************************************
123 
124  //**********************************************************************************************
126  enum { evaluateVector = IsComputation<VT>::value || RequiresEvaluation<VT>::value };
127  //**********************************************************************************************
128 
129  //**********************************************************************************************
131 
135  template< typename T1 >
136  struct UseSMPAssign {
137  enum { value = ( evaluateMatrix || evaluateVector ) };
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 &&
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 &&
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 &&
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 &&
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 &&
236  };
238  //**********************************************************************************************
239 
240  public:
241  //**Type definitions****************************************************************************
247  typedef const ElementType ReturnType;
248  typedef const ResultType CompositeType;
249 
251  typedef typename SelectType< IsExpression<MT>::value, const MT, const MT& >::Type LeftOperand;
252 
254  typedef typename SelectType< IsExpression<VT>::value, const VT, const VT& >::Type RightOperand;
255 
258 
261  //**********************************************************************************************
262 
263  //**Compilation flags***************************************************************************
265  enum { vectorizable = MT::vectorizable && VT::vectorizable &&
269 
271  enum { smpAssignable = !evaluateMatrix && MT::smpAssignable &&
272  !evaluateVector && VT::smpAssignable };
273  //**********************************************************************************************
274 
275  //**Constructor*********************************************************************************
281  explicit inline DMatDVecMultExpr( const MT& mat, const VT& vec )
282  : mat_( mat ) // Left-hand side dense matrix of the multiplication expression
283  , vec_( vec ) // Right-hand side dense vector of the multiplication expression
284  , end_( ( (mat.columns()-1UL) & size_t(-2) ) + 1UL ) // End of the unrolled calculation loop
285  {
286  BLAZE_INTERNAL_ASSERT( mat_.columns() == vec_.size(), "Invalid matrix and vector sizes" );
287  }
288  //**********************************************************************************************
289 
290  //**Subscript operator**************************************************************************
296  inline ReturnType operator[]( size_t index ) const {
297  BLAZE_INTERNAL_ASSERT( index < mat_.rows(), "Invalid vector access index" );
298 
299  ElementType res;
300 
301  if( mat_.columns() != 0UL ) {
302  res = mat_(index,0UL) * vec_[0UL];
303  for( size_t j=1UL; j<end_; j+=2UL ) {
304  res += mat_(index,j) * vec_[j] + mat_(index,j+1UL) * vec_[j+1UL];
305  }
306  if( end_ < mat_.columns() ) {
307  res += mat_(index,end_) * vec_[end_];
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_.rows();
325  }
326  //**********************************************************************************************
327 
328  //**Left operand access*************************************************************************
333  inline LeftOperand leftOperand() const {
334  return mat_;
335  }
336  //**********************************************************************************************
337 
338  //**Right operand access************************************************************************
343  inline RightOperand rightOperand() const {
344  return vec_;
345  }
346  //**********************************************************************************************
347 
348  //**********************************************************************************************
354  template< typename T >
355  inline bool canAlias( const T* alias ) const {
356  return ( mat_.isAliased( alias ) || vec_.isAliased( alias ) );
357  }
358  //**********************************************************************************************
359 
360  //**********************************************************************************************
366  template< typename T >
367  inline bool isAliased( const T* alias ) const {
368  return ( mat_.isAliased( alias ) || vec_.isAliased( alias ) );
369  }
370  //**********************************************************************************************
371 
372  //**********************************************************************************************
377  inline bool isAligned() const {
378  return mat_.isAligned() && vec_.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() < DMATDVECMULT_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,false>& lhs, const DMatDVecMultExpr& rhs )
417  {
419 
420  BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
421 
422  if( rhs.mat_.rows() == 0UL ) {
423  return;
424  }
425  else if( rhs.mat_.columns() == 0UL ) {
426  reset( ~lhs );
427  return;
428  }
429 
430  LT A( serial( rhs.mat_ ) ); // Evaluation of the left-hand side dense matrix operand
431  RT x( serial( rhs.vec_ ) ); // Evaluation of the right-hand side dense vector operand
432 
433  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.mat_.rows() , "Invalid number of rows" );
434  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.mat_.columns(), "Invalid number of columns" );
435  BLAZE_INTERNAL_ASSERT( x.size() == rhs.vec_.size() , "Invalid vector size" );
436  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).size() , "Invalid vector size" );
437 
438  DMatDVecMultExpr::selectAssignKernel( ~lhs, A, x );
439  }
441  //**********************************************************************************************
442 
443  //**Assignment to dense vectors (kernel selection)**********************************************
454  template< typename VT1 // Type of the left-hand side target vector
455  , typename MT1 // Type of the left-hand side matrix operand
456  , typename VT2 > // Type of the right-hand side vector operand
457  static inline void selectAssignKernel( VT1& y, const MT1& A, const VT2& x )
458  {
459  if( ( IsComputation<MT>::value && !evaluateMatrix ) ||
460  ( A.rows() * A.columns() < DMATDVECMULT_THRESHOLD ) )
461  DMatDVecMultExpr::selectDefaultAssignKernel( y, A, x );
462  else
463  DMatDVecMultExpr::selectBlasAssignKernel( y, A, x );
464  }
466  //**********************************************************************************************
467 
468  //**Default assignment to dense vectors*********************************************************
482  template< typename VT1 // Type of the left-hand side target vector
483  , typename MT1 // Type of the left-hand side matrix operand
484  , typename VT2 > // Type of the right-hand side vector operand
485  static inline typename DisableIf< UseVectorizedDefaultKernel<VT1,MT1,VT2> >::Type
486  selectDefaultAssignKernel( VT1& y, const MT1& A, const VT2& x )
487  {
488  y.assign( A * x );
489  }
491  //**********************************************************************************************
492 
493  //**Vectorized default assignment to dense vectors**********************************************
507  template< typename VT1 // Type of the left-hand side target vector
508  , typename MT1 // Type of the left-hand side matrix operand
509  , typename VT2 > // Type of the right-hand side vector operand
510  static inline typename EnableIf< UseVectorizedDefaultKernel<VT1,MT1,VT2> >::Type
511  selectDefaultAssignKernel( VT1& y, const MT1& A, const VT2& x )
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 i( 0UL );
519 
520  for( ; (i+8UL) <= M; i+=8UL ) {
521  IntrinsicType xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7, xmm8;
522  for( size_t j=0UL; j<N; j+=IT::size ) {
523  const IntrinsicType x1( x.load(j) );
524  xmm1 = xmm1 + A.load(i ,j) * x1;
525  xmm2 = xmm2 + A.load(i+1UL,j) * x1;
526  xmm3 = xmm3 + A.load(i+2UL,j) * x1;
527  xmm4 = xmm4 + A.load(i+3UL,j) * x1;
528  xmm5 = xmm5 + A.load(i+4UL,j) * x1;
529  xmm6 = xmm6 + A.load(i+5UL,j) * x1;
530  xmm7 = xmm7 + A.load(i+6UL,j) * x1;
531  xmm8 = xmm8 + A.load(i+7UL,j) * x1;
532  }
533  y[i ] = sum( xmm1 );
534  y[i+1UL] = sum( xmm2 );
535  y[i+2UL] = sum( xmm3 );
536  y[i+3UL] = sum( xmm4 );
537  y[i+4UL] = sum( xmm5 );
538  y[i+5UL] = sum( xmm6 );
539  y[i+6UL] = sum( xmm7 );
540  y[i+7UL] = sum( xmm8 );
541  }
542  for( ; (i+4UL) <= M; i+=4UL ) {
543  IntrinsicType xmm1, xmm2, xmm3, xmm4;
544  for( size_t j=0UL; j<N; j+=IT::size ) {
545  const IntrinsicType x1( x.load(j) );
546  xmm1 = xmm1 + A.load(i ,j) * x1;
547  xmm2 = xmm2 + A.load(i+1UL,j) * x1;
548  xmm3 = xmm3 + A.load(i+2UL,j) * x1;
549  xmm4 = xmm4 + A.load(i+3UL,j) * x1;
550  }
551  y[i ] = sum( xmm1 );
552  y[i+1UL] = sum( xmm2 );
553  y[i+2UL] = sum( xmm3 );
554  y[i+3UL] = sum( xmm4 );
555  }
556  for( ; (i+3UL) <= M; i+=3UL ) {
557  IntrinsicType xmm1, xmm2, xmm3;
558  for( size_t j=0UL; j<N; j+=IT::size ) {
559  const IntrinsicType x1( x.load(j) );
560  xmm1 = xmm1 + A.load(i ,j) * x1;
561  xmm2 = xmm2 + A.load(i+1UL,j) * x1;
562  xmm3 = xmm3 + A.load(i+2UL,j) * x1;
563  }
564  y[i ] = sum( xmm1 );
565  y[i+1UL] = sum( xmm2 );
566  y[i+2UL] = sum( xmm3 );
567  }
568  for( ; (i+2UL) <= M; i+=2UL ) {
569  IntrinsicType xmm1, xmm2;
570  for( size_t j=0UL; j<N; j+=IT::size ) {
571  const IntrinsicType x1( x.load(j) );
572  xmm1 = xmm1 + A.load(i ,j) * x1;
573  xmm2 = xmm2 + A.load(i+1UL,j) * x1;
574  }
575  y[i ] = sum( xmm1 );
576  y[i+1UL] = sum( xmm2 );
577  }
578  if( i < M ) {
579  IntrinsicType xmm1;
580  for( size_t j=0UL; j<N; j+=IT::size ) {
581  xmm1 = xmm1 + A.load(i,j) * x.load(j);
582  }
583  y[i] = 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 MT1 // Type of the left-hand side matrix operand
605  , typename VT2 > // Type of the right-hand side vector operand
606  static inline typename EnableIf< UseDefaultKernel<VT1,MT1,VT2> >::Type
607  selectBlasAssignKernel( VT1& y, const MT1& A, const VT2& x )
608  {
609  selectDefaultAssignKernel( y, A, x );
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 MT1 // Type of the left-hand side matrix operand
631  , typename VT2 > // Type of the right-hand side vector operand
632  static inline typename EnableIf< UseSinglePrecisionKernel<VT1,MT1,VT2> >::Type
633  selectBlasAssignKernel( VT1& y, const MT1& A, const VT2& x )
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( CblasRowMajor, CblasNoTrans, 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 MT1 // Type of the left-hand side matrix operand
669  , typename VT2 > // Type of the right-hand side vector operand
670  static inline typename EnableIf< UseDoublePrecisionKernel<VT1,MT1,VT2> >::Type
671  selectBlasAssignKernel( VT1& y, const MT1& A, const VT2& x )
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( CblasRowMajor, CblasNoTrans, 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 MT1 // Type of the left-hand side matrix operand
707  , typename VT2 > // Type of the right-hand side vector operand
708  static inline typename EnableIf< UseSinglePrecisionComplexKernel<VT1,MT1,VT2> >::Type
709  selectBlasAssignKernel( VT1& y, const MT1& A, const VT2& x )
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 MT1::ElementType::value_type );
718  BLAZE_CONSTRAINT_MUST_BE_FLOAT_TYPE ( typename VT2::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( CblasRowMajor, CblasNoTrans, 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 MT1 // Type of the left-hand side matrix operand
750  , typename VT2 > // Type of the right-hand side vector operand
751  static inline typename EnableIf< UseDoublePrecisionComplexKernel<VT1,MT1,VT2> >::Type
752  selectBlasAssignKernel( VT1& y, const MT1& A, const VT2& x )
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 MT1::ElementType::value_type );
761  BLAZE_CONSTRAINT_MUST_BE_DOUBLE_TYPE ( typename VT2::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( CblasRowMajor, CblasNoTrans, 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,false>& lhs, const DMatDVecMultExpr& 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,false>& lhs, const DMatDVecMultExpr& 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 A( serial( rhs.mat_ ) ); // Evaluation of the left-hand side dense matrix operand
831  RT x( serial( rhs.vec_ ) ); // Evaluation of the right-hand side dense vector operand
832 
833  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.mat_.rows() , "Invalid number of rows" );
834  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.mat_.columns(), "Invalid number of columns" );
835  BLAZE_INTERNAL_ASSERT( x.size() == rhs.vec_.size() , "Invalid vector size" );
836  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).size() , "Invalid vector size" );
837 
838  DMatDVecMultExpr::selectAddAssignKernel( ~lhs, A, x );
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 MT1 // Type of the left-hand side matrix operand
856  , typename VT2 > // Type of the right-hand side vector operand
857  static inline void selectAddAssignKernel( VT1& y, const MT1& A, const VT2& x )
858  {
859  if( ( IsComputation<MT>::value && !evaluateMatrix ) ||
860  ( A.rows() * A.columns() < DMATDVECMULT_THRESHOLD ) )
861  DMatDVecMultExpr::selectDefaultAddAssignKernel( y, A, x );
862  else
863  DMatDVecMultExpr::selectBlasAddAssignKernel( y, A, x );
864  }
866  //**********************************************************************************************
867 
868  //**Default addition assignment to dense vectors************************************************
882  template< typename VT1 // Type of the left-hand side target vector
883  , typename MT1 // Type of the left-hand side matrix operand
884  , typename VT2 > // Type of the right-hand side vector operand
885  static inline typename DisableIf< UseVectorizedDefaultKernel<VT1,MT1,VT2> >::Type
886  selectDefaultAddAssignKernel( VT1& y, const MT1& A, const VT2& x )
887  {
888  y.addAssign( A * x );
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 MT1 // Type of the left-hand side matrix operand
909  , typename VT2 > // Type of the right-hand side vector operand
910  static inline typename EnableIf< UseVectorizedDefaultKernel<VT1,MT1,VT2> >::Type
911  selectDefaultAddAssignKernel( VT1& y, const MT1& A, const VT2& x )
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 i( 0UL );
919 
920  for( ; (i+8UL) <= M; i+=8UL ) {
921  IntrinsicType xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7, xmm8;
922  for( size_t j=0UL; j<N; j+=IT::size ) {
923  const IntrinsicType x1( x.load(j) );
924  xmm1 = xmm1 + A.load(i ,j) * x1;
925  xmm2 = xmm2 + A.load(i+1UL,j) * x1;
926  xmm3 = xmm3 + A.load(i+2UL,j) * x1;
927  xmm4 = xmm4 + A.load(i+3UL,j) * x1;
928  xmm5 = xmm5 + A.load(i+4UL,j) * x1;
929  xmm6 = xmm6 + A.load(i+5UL,j) * x1;
930  xmm7 = xmm7 + A.load(i+6UL,j) * x1;
931  xmm8 = xmm8 + A.load(i+7UL,j) * x1;
932  }
933  y[i ] += sum( xmm1 );
934  y[i+1UL] += sum( xmm2 );
935  y[i+2UL] += sum( xmm3 );
936  y[i+3UL] += sum( xmm4 );
937  y[i+4UL] += sum( xmm5 );
938  y[i+5UL] += sum( xmm6 );
939  y[i+6UL] += sum( xmm7 );
940  y[i+7UL] += sum( xmm8 );
941  }
942  for( ; (i+4UL) <= M; i+=4UL ) {
943  IntrinsicType xmm1, xmm2, xmm3, xmm4;
944  for( size_t j=0UL; j<N; j+=IT::size ) {
945  const IntrinsicType x1( x.load(j) );
946  xmm1 = xmm1 + A.load(i ,j) * x1;
947  xmm2 = xmm2 + A.load(i+1UL,j) * x1;
948  xmm3 = xmm3 + A.load(i+2UL,j) * x1;
949  xmm4 = xmm4 + A.load(i+3UL,j) * x1;
950  }
951  y[i ] += sum( xmm1 );
952  y[i+1UL] += sum( xmm2 );
953  y[i+2UL] += sum( xmm3 );
954  y[i+3UL] += sum( xmm4 );
955  }
956  for( ; (i+3UL) <= M; i+=3UL ) {
957  IntrinsicType xmm1, xmm2, xmm3;
958  for( size_t j=0UL; j<N; j+=IT::size ) {
959  const IntrinsicType x1( x.load(j) );
960  xmm1 = xmm1 + A.load(i ,j) * x1;
961  xmm2 = xmm2 + A.load(i+1UL,j) * x1;
962  xmm3 = xmm3 + A.load(i+2UL,j) * x1;
963  }
964  y[i ] += sum( xmm1 );
965  y[i+1UL] += sum( xmm2 );
966  y[i+2UL] += sum( xmm3 );
967  }
968  for( ; (i+2UL) <= M; i+=2UL ) {
969  IntrinsicType xmm1, xmm2;
970  for( size_t j=0UL; j<N; j+=IT::size ) {
971  const IntrinsicType x1( x.load(j) );
972  xmm1 = xmm1 + A.load(i ,j) * x1;
973  xmm2 = xmm2 + A.load(i+1UL,j) * x1;
974  }
975  y[i ] += sum( xmm1 );
976  y[i+1UL] += sum( xmm2 );
977  }
978  if( i < M ) {
979  IntrinsicType xmm1;
980  for( size_t j=0UL; j<N; j+=IT::size ) {
981  xmm1 = xmm1 + A.load(i,j) * x.load(j);
982  }
983  y[i] += 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 MT1 // Type of the left-hand side matrix operand
1005  , typename VT2 > // Type of the right-hand side vector operand
1006  static inline typename EnableIf< UseDefaultKernel<VT1,MT1,VT2> >::Type
1007  selectBlasAddAssignKernel( VT1& y, const MT1& A, const VT2& x )
1008  {
1009  selectDefaultAddAssignKernel( y, A, x );
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 MT1 // Type of the left-hand side matrix operand
1031  , typename VT2 > // Type of the right-hand side vector operand
1032  static inline typename EnableIf< UseSinglePrecisionKernel<VT1,MT1,VT2> >::Type
1033  selectBlasAddAssignKernel( VT1& y, const MT1& A, const VT2& x )
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( CblasRowMajor, CblasNoTrans, 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 MT1 // Type of the left-hand side matrix operand
1069  , typename VT2 > // Type of the right-hand side vector operand
1070  static inline typename EnableIf< UseDoublePrecisionKernel<VT1,MT1,VT2> >::Type
1071  selectBlasAddAssignKernel( VT1& y, const MT1& A, const VT2& x )
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( CblasRowMajor, CblasNoTrans, 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 MT1 // Type of the left-hand side matrix operand
1107  , typename VT2 > // Type of the right-hand side vector operand
1108  static inline typename EnableIf< UseSinglePrecisionComplexKernel<VT1,MT1,VT2> >::Type
1109  selectBlasAddAssignKernel( VT1& y, const MT1& A, const VT2& x )
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 MT1::ElementType::value_type );
1118  BLAZE_CONSTRAINT_MUST_BE_FLOAT_TYPE ( typename VT2::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( CblasRowMajor, CblasNoTrans, 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 MT1 // Type of the left-hand side matrix operand
1150  , typename VT2 > // Type of the right-hand side vector operand
1151  static inline typename EnableIf< UseDoublePrecisionComplexKernel<VT1,MT1,VT2> >::Type
1152  selectBlasAddAssignKernel( VT1& y, const MT1& A, const VT2& x )
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 MT1::ElementType::value_type );
1161  BLAZE_CONSTRAINT_MUST_BE_DOUBLE_TYPE ( typename VT2::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( CblasRowMajor, CblasNoTrans, 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,false>& lhs, const DMatDVecMultExpr& 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 A( serial( rhs.mat_ ) ); // Evaluation of the left-hand side dense matrix operand
1205  RT x( serial( rhs.vec_ ) ); // Evaluation of the right-hand side dense vector operand
1206 
1207  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.mat_.rows() , "Invalid number of rows" );
1208  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.mat_.columns(), "Invalid number of columns" );
1209  BLAZE_INTERNAL_ASSERT( x.size() == rhs.vec_.size() , "Invalid vector size" );
1210  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).size() , "Invalid vector size" );
1211 
1212  DMatDVecMultExpr::selectSubAssignKernel( ~lhs, A, x );
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 MT1 // Type of the left-hand side matrix operand
1230  , typename VT2 > // Type of the right-hand side vector operand
1231  static inline void selectSubAssignKernel( VT1& y, const MT1& A, const VT2& x )
1232  {
1233  if( ( IsComputation<MT>::value && !evaluateMatrix ) ||
1234  ( A.rows() * A.columns() < DMATDVECMULT_THRESHOLD ) )
1235  DMatDVecMultExpr::selectDefaultSubAssignKernel( y, A, x );
1236  else
1237  DMatDVecMultExpr::selectBlasSubAssignKernel( y, A, x );
1238  }
1240  //**********************************************************************************************
1241 
1242  //**Default subtraction assignment to dense vectors*********************************************
1256  template< typename VT1 // Type of the left-hand side target vector
1257  , typename MT1 // Type of the left-hand side matrix operand
1258  , typename VT2 > // Type of the right-hand side vector operand
1259  static inline typename DisableIf< UseVectorizedDefaultKernel<VT1,MT1,VT2> >::Type
1260  selectDefaultSubAssignKernel( VT1& y, const MT1& A, const VT2& x )
1261  {
1262  y.subAssign( A * x );
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 MT1 // Type of the left-hand side matrix operand
1283  , typename VT2 > // Type of the right-hand side vector operand
1284  static inline typename EnableIf< UseVectorizedDefaultKernel<VT1,MT1,VT2> >::Type
1285  selectDefaultSubAssignKernel( VT1& y, const MT1& A, const VT2& x )
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 i( 0UL );
1293 
1294  for( ; (i+8UL) <= M; i+=8UL ) {
1295  IntrinsicType xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7, xmm8;
1296  for( size_t j=0UL; j<N; j+=IT::size ) {
1297  const IntrinsicType x1( x.load(j) );
1298  xmm1 = xmm1 + A.load(i ,j) * x1;
1299  xmm2 = xmm2 + A.load(i+1UL,j) * x1;
1300  xmm3 = xmm3 + A.load(i+2UL,j) * x1;
1301  xmm4 = xmm4 + A.load(i+3UL,j) * x1;
1302  xmm5 = xmm5 + A.load(i+4UL,j) * x1;
1303  xmm6 = xmm6 + A.load(i+5UL,j) * x1;
1304  xmm7 = xmm7 + A.load(i+6UL,j) * x1;
1305  xmm8 = xmm8 + A.load(i+7UL,j) * x1;
1306  }
1307  y[i ] -= sum( xmm1 );
1308  y[i+1UL] -= sum( xmm2 );
1309  y[i+2UL] -= sum( xmm3 );
1310  y[i+3UL] -= sum( xmm4 );
1311  y[i+4UL] -= sum( xmm5 );
1312  y[i+5UL] -= sum( xmm6 );
1313  y[i+6UL] -= sum( xmm7 );
1314  y[i+7UL] -= sum( xmm8 );
1315  }
1316  for( ; (i+4UL) <= M; i+=4UL ) {
1317  IntrinsicType xmm1, xmm2, xmm3, xmm4;
1318  for( size_t j=0UL; j<N; j+=IT::size ) {
1319  const IntrinsicType x1( x.load(j) );
1320  xmm1 = xmm1 + A.load(i ,j) * x1;
1321  xmm2 = xmm2 + A.load(i+1UL,j) * x1;
1322  xmm3 = xmm3 + A.load(i+2UL,j) * x1;
1323  xmm4 = xmm4 + A.load(i+3UL,j) * x1;
1324  }
1325  y[i ] -= sum( xmm1 );
1326  y[i+1UL] -= sum( xmm2 );
1327  y[i+2UL] -= sum( xmm3 );
1328  y[i+3UL] -= sum( xmm4 );
1329  }
1330  for( ; (i+3UL) <= M; i+=3UL ) {
1331  IntrinsicType xmm1, xmm2, xmm3;
1332  for( size_t j=0UL; j<N; j+=IT::size ) {
1333  const IntrinsicType x1( x.load(j) );
1334  xmm1 = xmm1 + A.load(i ,j) * x1;
1335  xmm2 = xmm2 + A.load(i+1UL,j) * x1;
1336  xmm3 = xmm3 + A.load(i+2UL,j) * x1;
1337  }
1338  y[i ] -= sum( xmm1 );
1339  y[i+1UL] -= sum( xmm2 );
1340  y[i+2UL] -= sum( xmm3 );
1341  }
1342  for( ; (i+2UL) <= M; i+=2UL ) {
1343  IntrinsicType xmm1, xmm2;
1344  for( size_t j=0UL; j<N; j+=IT::size ) {
1345  const IntrinsicType x1( x.load(j) );
1346  xmm1 = xmm1 + A.load(i ,j) * x1;
1347  xmm2 = xmm2 + A.load(i+1UL,j) * x1;
1348  }
1349  y[i ] -= sum( xmm1 );
1350  y[i+1UL] -= sum( xmm2 );
1351  }
1352  if( i < M ) {
1353  IntrinsicType xmm1;
1354  for( size_t j=0UL; j<N; j+=IT::size ) {
1355  xmm1 = xmm1 + A.load(i,j) * x.load(j);
1356  }
1357  y[i] -= 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 MT1 // Type of the left-hand side matrix operand
1379  , typename VT2 > // Type of the right-hand side vector operand
1380  static inline typename EnableIf< UseDefaultKernel<VT1,MT1,VT2> >::Type
1381  selectBlasSubAssignKernel( VT1& y, const MT1& A, const VT2& x )
1382  {
1383  selectDefaultSubAssignKernel( y, A, x );
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 MT1 // Type of the left-hand side matrix operand
1405  , typename VT2 > // Type of the right-hand side vector operand
1406  static inline typename EnableIf< UseSinglePrecisionKernel<VT1,MT1,VT2> >::Type
1407  selectBlasSubAssignKernel( VT1& y, const MT1& A, const VT2& x )
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( CblasRowMajor, CblasNoTrans, 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 MT1 // Type of the left-hand side matrix operand
1443  , typename VT2 > // Type of the right-hand side vector operand
1444  static inline typename EnableIf< UseDoublePrecisionKernel<VT1,MT1,VT2> >::Type
1445  selectBlasSubAssignKernel( VT1& y, const MT1& A, const VT2& x )
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( CblasRowMajor, CblasNoTrans, 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 MT1 // Type of the left-hand side matrix operand
1481  , typename VT2 > // Type of the right-hand side vector operand
1482  static inline typename EnableIf< UseSinglePrecisionComplexKernel<VT1,MT1,VT2> >::Type
1483  selectBlasSubAssignKernel( VT1& y, const MT1& A, const VT2& x )
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 MT1::ElementType::value_type );
1492  BLAZE_CONSTRAINT_MUST_BE_FLOAT_TYPE ( typename VT2::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( CblasRowMajor, CblasNoTrans, 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 MT1 // Type of the left-hand side matrix operand
1524  , typename VT2 > // Type of the right-hand side vector operand
1525  static inline typename EnableIf< UseDoublePrecisionComplexKernel<VT1,MT1,VT2> >::Type
1526  selectBlasSubAssignKernel( VT1& y, const MT1& A, const VT2& x )
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 MT1::ElementType::value_type );
1535  BLAZE_CONSTRAINT_MUST_BE_DOUBLE_TYPE ( typename VT2::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( CblasRowMajor, CblasNoTrans, 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,false>& lhs, const DMatDVecMultExpr& 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,false>& lhs, const DMatDVecMultExpr& rhs )
1606  {
1608 
1609  BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
1610 
1611  if( rhs.mat_.rows() == 0UL ) {
1612  return;
1613  }
1614  else if( rhs.mat_.columns() == 0UL ) {
1615  reset( ~lhs );
1616  return;
1617  }
1618 
1619  LT A( rhs.mat_ ); // Evaluation of the left-hand side dense matrix operand
1620  RT x( rhs.vec_ ); // Evaluation of the right-hand side dense vector operand
1621 
1622  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.mat_.rows() , "Invalid number of rows" );
1623  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.mat_.columns(), "Invalid number of columns" );
1624  BLAZE_INTERNAL_ASSERT( x.size() == rhs.vec_.size() , "Invalid vector size" );
1625  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).size() , "Invalid vector size" );
1626 
1627  smpAssign( ~lhs, A * x );
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,false>& lhs, const DMatDVecMultExpr& 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,false>& lhs, const DMatDVecMultExpr& 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 A( rhs.mat_ ); // Evaluation of the left-hand side dense matrix operand
1693  RT x( rhs.vec_ ); // Evaluation of the right-hand side dense vector operand
1694 
1695  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.mat_.rows() , "Invalid number of rows" );
1696  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.mat_.columns(), "Invalid number of columns" );
1697  BLAZE_INTERNAL_ASSERT( x.size() == rhs.vec_.size() , "Invalid vector size" );
1698  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).size() , "Invalid vector size" );
1699 
1700  smpAddAssign( ~lhs, A * x );
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,false>& lhs, const DMatDVecMultExpr& 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 A( rhs.mat_ ); // Evaluation of the left-hand side dense matrix operand
1737  RT x( rhs.vec_ ); // Evaluation of the right-hand side dense vector operand
1738 
1739  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.mat_.rows() , "Invalid number of rows" );
1740  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.mat_.columns(), "Invalid number of columns" );
1741  BLAZE_INTERNAL_ASSERT( x.size() == rhs.vec_.size() , "Invalid vector size" );
1742  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).size() , "Invalid vector size" );
1743 
1744  smpSubAssign( ~lhs, A * x );
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,false>& lhs, const DMatDVecMultExpr& 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 MT // Type of the left-hand side dense matrix
1819  , typename VT // Type of the right-hand side dense vector
1820  , typename ST > // Type of the scalar value
1821 class DVecScalarMultExpr< DMatDVecMultExpr<MT,VT>, ST, false >
1822  : public DenseVector< DVecScalarMultExpr< DMatDVecMultExpr<MT,VT>, ST, false >, false >
1823  , private VecScalarMultExpr
1824  , private Computation
1825 {
1826  private:
1827  //**Type definitions****************************************************************************
1828  typedef DMatDVecMultExpr<MT,VT> MVM;
1829  typedef typename MVM::ResultType RES;
1830  typedef typename MT::ResultType MRT;
1831  typedef typename VT::ResultType VRT;
1832  typedef typename MRT::ElementType MET;
1833  typedef typename VRT::ElementType VET;
1834  typedef typename MT::CompositeType MCT;
1835  typedef typename VT::CompositeType VCT;
1836  //**********************************************************************************************
1837 
1838  //**********************************************************************************************
1840  enum { evaluateMatrix = ( IsComputation<MT>::value && IsSame<MET,VET>::value &&
1841  IsBlasCompatible<MET>::value ) || RequiresEvaluation<MT>::value };
1842  //**********************************************************************************************
1843 
1844  //**********************************************************************************************
1846  enum { evaluateVector = IsComputation<VT>::value || RequiresEvaluation<MT>::value };
1847  //**********************************************************************************************
1848 
1849  //**********************************************************************************************
1851 
1854  template< typename T1 >
1855  struct UseSMPAssign {
1856  enum { value = ( evaluateMatrix || evaluateVector ) };
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<MVM,ST,false> 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 DMatDVecMultExpr<MT,VT> LeftOperand;
1961 
1963  typedef ST RightOperand;
1964 
1966  typedef typename SelectType< evaluateMatrix, const MRT, MCT >::Type LT;
1967 
1969  typedef typename SelectType< evaluateVector, const VRT, VCT >::Type RT;
1970  //**********************************************************************************************
1971 
1972  //**Compilation flags***************************************************************************
1974  enum { vectorizable = MT::vectorizable && VT::vectorizable &&
1975  IsSame<MET,VET>::value &&
1976  IsSame<MET,ST>::value &&
1977  IntrinsicTrait<MET>::addition &&
1978  IntrinsicTrait<MET>::multiplication };
1979 
1981  enum { smpAssignable = !evaluateMatrix && MT::smpAssignable &&
1982  !evaluateVector && VT::smpAssignable };
1983  //**********************************************************************************************
1984 
1985  //**Constructor*********************************************************************************
1991  explicit inline DVecScalarMultExpr( const MVM& 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 MVM::LeftOperand A( vector_.leftOperand() );
2080  return ( !BLAZE_BLAS_IS_PARALLEL ||
2081  ( IsComputation<MT>::value && !evaluateMatrix ) ||
2082  ( A.rows() * A.columns() < DMATDVECMULT_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  friend inline void assign( DenseVector<VT1,false>& lhs, const DVecScalarMultExpr& rhs )
2107  {
2109 
2110  BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
2111 
2112  typename MVM::LeftOperand left ( rhs.vector_.leftOperand() );
2113  typename MVM::RightOperand right( rhs.vector_.rightOperand() );
2114 
2115  if( left.rows() == 0UL ) {
2116  return;
2117  }
2118  else if( left.columns() == 0UL ) {
2119  reset( ~lhs );
2120  return;
2121  }
2122 
2123  LT A( serial( left ) ); // Evaluation of the left-hand side dense matrix operand
2124  RT x( serial( right ) ); // Evaluation of the right-hand side dense vector operand
2125 
2126  BLAZE_INTERNAL_ASSERT( A.rows() == left.rows() , "Invalid number of rows" );
2127  BLAZE_INTERNAL_ASSERT( A.columns() == left.columns(), "Invalid number of columns" );
2128  BLAZE_INTERNAL_ASSERT( x.size() == right.size() , "Invalid vector size" );
2129  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).size() , "Invalid vector size" );
2130 
2131  DVecScalarMultExpr::selectAssignKernel( ~lhs, A, x, rhs.scalar_ );
2132  }
2133  //**********************************************************************************************
2134 
2135  //**Assignment to dense vectors (kernel selection)**********************************************
2146  template< typename VT1 // Type of the left-hand side target vector
2147  , typename MT1 // Type of the left-hand side matrix operand
2148  , typename VT2 // Type of the right-hand side vector operand
2149  , typename ST2 > // Type of the scalar value
2150  static inline void selectAssignKernel( VT1& y, const MT1& A, const VT2& x, ST2 scalar )
2151  {
2152  if( ( IsComputation<MT>::value && !evaluateMatrix ) ||
2153  ( A.rows() * A.columns() < DMATDVECMULT_THRESHOLD ) )
2154  DVecScalarMultExpr::selectDefaultAssignKernel( y, A, x, scalar );
2155  else
2156  DVecScalarMultExpr::selectBlasAssignKernel( y, A, x, scalar );
2157  }
2158  //**********************************************************************************************
2159 
2160  //**Default assignment to dense vectors*********************************************************
2174  template< typename VT1 // Type of the left-hand side target vector
2175  , typename MT1 // Type of the left-hand side matrix operand
2176  , typename VT2 // Type of the right-hand side vector operand
2177  , typename ST2 > // Type of the scalar value
2178  static inline typename DisableIf< UseVectorizedDefaultKernel<VT1,MT1,VT2,ST2> >::Type
2179  selectDefaultAssignKernel( VT1& y, const MT1& A, const VT2& x, ST2 scalar )
2180  {
2181  y.assign( A * x * scalar );
2182  }
2183  //**********************************************************************************************
2184 
2185  //**Vectorized default assignment to dense vectors**********************************************
2199  template< typename VT1 // Type of the left-hand side target vector
2200  , typename MT1 // Type of the left-hand side matrix operand
2201  , typename VT2 // Type of the right-hand side vector operand
2202  , typename ST2 > // Type of the scalar value
2203  static inline typename EnableIf< UseVectorizedDefaultKernel<VT1,MT1,VT2,ST2> >::Type
2204  selectDefaultAssignKernel( VT1& y, const MT1& A, const VT2& x, ST2 scalar )
2205  {
2206  typedef IntrinsicTrait<ElementType> IT;
2207 
2208  const size_t M( A.rows() );
2209  const size_t N( A.columns() );
2210 
2211  size_t i( 0UL );
2212 
2213  for( ; (i+8UL) <= M; i+=8UL ) {
2214  IntrinsicType xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7, xmm8;
2215  for( size_t j=0UL; j<N; j+=IT::size ) {
2216  const IntrinsicType x1( x.load(j) );
2217  xmm1 = xmm1 + A.load(i ,j) * x1;
2218  xmm2 = xmm2 + A.load(i+1UL,j) * x1;
2219  xmm3 = xmm3 + A.load(i+2UL,j) * x1;
2220  xmm4 = xmm4 + A.load(i+3UL,j) * x1;
2221  xmm5 = xmm5 + A.load(i+4UL,j) * x1;
2222  xmm6 = xmm6 + A.load(i+5UL,j) * x1;
2223  xmm7 = xmm7 + A.load(i+6UL,j) * x1;
2224  xmm8 = xmm8 + A.load(i+7UL,j) * x1;
2225  }
2226  y[i ] = sum( xmm1 ) * scalar;
2227  y[i+1UL] = sum( xmm2 ) * scalar;
2228  y[i+2UL] = sum( xmm3 ) * scalar;
2229  y[i+3UL] = sum( xmm4 ) * scalar;
2230  y[i+4UL] = sum( xmm5 ) * scalar;
2231  y[i+5UL] = sum( xmm6 ) * scalar;
2232  y[i+6UL] = sum( xmm7 ) * scalar;
2233  y[i+7UL] = sum( xmm8 ) * scalar;
2234  }
2235  for( ; (i+4UL) <= M; i+=4UL ) {
2236  IntrinsicType xmm1, xmm2, xmm3, xmm4;
2237  for( size_t j=0UL; j<N; j+=IT::size ) {
2238  const IntrinsicType x1( x.load(j) );
2239  xmm1 = xmm1 + A.load(i ,j) * x1;
2240  xmm2 = xmm2 + A.load(i+1UL,j) * x1;
2241  xmm3 = xmm3 + A.load(i+2UL,j) * x1;
2242  xmm4 = xmm4 + A.load(i+3UL,j) * x1;
2243  }
2244  y[i ] = sum( xmm1 ) * scalar;
2245  y[i+1UL] = sum( xmm2 ) * scalar;
2246  y[i+2UL] = sum( xmm3 ) * scalar;
2247  y[i+3UL] = sum( xmm4 ) * scalar;
2248  }
2249  for( ; (i+3UL) <= M; i+=3UL ) {
2250  IntrinsicType xmm1, xmm2, xmm3;
2251  for( size_t j=0UL; j<N; j+=IT::size ) {
2252  const IntrinsicType x1( x.load(j) );
2253  xmm1 = xmm1 + A.load(i ,j) * x1;
2254  xmm2 = xmm2 + A.load(i+1UL,j) * x1;
2255  xmm3 = xmm3 + A.load(i+2UL,j) * x1;
2256  }
2257  y[i ] = sum( xmm1 ) * scalar;
2258  y[i+1UL] = sum( xmm2 ) * scalar;
2259  y[i+2UL] = sum( xmm3 ) * scalar;
2260  }
2261  for( ; (i+2UL) <= M; i+=2UL ) {
2262  IntrinsicType xmm1, xmm2;
2263  for( size_t j=0UL; j<N; j+=IT::size ) {
2264  const IntrinsicType x1( x.load(j) );
2265  xmm1 = xmm1 + A.load(i ,j) * x1;
2266  xmm2 = xmm2 + A.load(i+1UL,j) * x1;
2267  }
2268  y[i ] = sum( xmm1 ) * scalar;
2269  y[i+1UL] = sum( xmm2 ) * scalar;
2270  }
2271  if( i < M ) {
2272  IntrinsicType xmm1;
2273  for( size_t j=0UL; j<N; j+=IT::size ) {
2274  xmm1 = xmm1 + A.load(i,j) * x.load(j);
2275  }
2276  y[i] = sum( xmm1 ) * scalar;
2277  }
2278  }
2279  //**********************************************************************************************
2280 
2281  //**BLAS-based assignment to dense vectors (default)********************************************
2295  template< typename VT1 // Type of the left-hand side target vector
2296  , typename MT1 // Type of the left-hand side matrix operand
2297  , typename VT2 // Type of the right-hand side vector operand
2298  , typename ST2 > // Type of the scalar value
2299  static inline typename EnableIf< UseDefaultKernel<VT1,MT1,VT2,ST2> >::Type
2300  selectBlasAssignKernel( VT1& y, const MT1& A, const VT2& x, ST2 scalar )
2301  {
2302  selectDefaultAssignKernel( y, A, x, 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 MT1 // Type of the left-hand side matrix operand
2323  , typename VT2 // Type of the right-hand side vector operand
2324  , typename ST2 > // Type of the scalar value
2325  static inline typename EnableIf< UseSinglePrecisionKernel<VT1,MT1,VT2,ST2> >::Type
2326  selectBlasAssignKernel( VT1& y, const MT1& A, const VT2& x, 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( CblasRowMajor, CblasNoTrans, 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 MT1 // Type of the left-hand side matrix operand
2361  , typename VT2 // Type of the right-hand side vector operand
2362  , typename ST2 > // Type of the scalar value
2363  static inline typename EnableIf< UseDoublePrecisionKernel<VT1,MT1,VT2,ST2> >::Type
2364  selectBlasAssignKernel( VT1& y, const MT1& A, const VT2& x, 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( CblasRowMajor, CblasNoTrans, 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 
2397  template< typename VT1 // Type of the left-hand side target vector
2398  , typename MT1 // Type of the left-hand side matrix operand
2399  , typename VT2 // Type of the right-hand side vector operand
2400  , typename ST2 > // Type of the scalar value
2401  static inline typename EnableIf< UseSinglePrecisionComplexKernel<VT1,MT1,VT2> >::Type
2402  selectBlasAssignKernel( VT1& y, const MT1& A, const VT2& x, ST2 scalar )
2403  {
2404  using boost::numeric_cast;
2405 
2409  BLAZE_CONSTRAINT_MUST_BE_FLOAT_TYPE ( typename VT1::ElementType::value_type );
2410  BLAZE_CONSTRAINT_MUST_BE_FLOAT_TYPE ( typename MT1::ElementType::value_type );
2411  BLAZE_CONSTRAINT_MUST_BE_FLOAT_TYPE ( typename VT2::ElementType::value_type );
2412 
2413  const int M ( numeric_cast<int>( A.rows() ) );
2414  const int N ( numeric_cast<int>( A.columns() ) );
2415  const int lda( numeric_cast<int>( A.spacing() ) );
2416  const complex<float> alpha( scalar );
2417  const complex<float> beta ( 0.0F, 0.0F );
2418 
2419  cblas_cgemv( CblasRowMajor, CblasNoTrans, M, N, &alpha,
2420  A.data(), lda, x.data(), 1, &beta, y.data(), 1 );
2421  }
2422 #endif
2423  //**********************************************************************************************
2424 
2425  //**BLAS-based assignment to dense vectors (double precision complex)***************************
2426 #if BLAZE_BLAS_MODE
2427 
2440  template< typename VT1 // Type of the left-hand side target vector
2441  , typename MT1 // Type of the left-hand side matrix operand
2442  , typename VT2 // Type of the right-hand side vector operand
2443  , typename ST2 > // Type of the scalar value
2444  static inline typename EnableIf< UseDoublePrecisionComplexKernel<VT1,MT1,VT2> >::Type
2445  selectBlasAssignKernel( VT1& y, const MT1& A, const VT2& x, ST2 scalar )
2446  {
2447  using boost::numeric_cast;
2448 
2452  BLAZE_CONSTRAINT_MUST_BE_DOUBLE_TYPE ( typename VT1::ElementType::value_type );
2453  BLAZE_CONSTRAINT_MUST_BE_DOUBLE_TYPE ( typename MT1::ElementType::value_type );
2454  BLAZE_CONSTRAINT_MUST_BE_DOUBLE_TYPE ( typename VT2::ElementType::value_type );
2455 
2456  const int M ( numeric_cast<int>( A.rows() ) );
2457  const int N ( numeric_cast<int>( A.columns() ) );
2458  const int lda( numeric_cast<int>( A.spacing() ) );
2459  const complex<double> alpha( scalar );
2460  const complex<double> beta ( 0.0, 0.0 );
2461 
2462  cblas_zgemv( CblasRowMajor, CblasNoTrans, M, N, &alpha,
2463  A.data(), lda, x.data(), 1, &beta, y.data(), 1 );
2464  }
2465 #endif
2466  //**********************************************************************************************
2467 
2468  //**Assignment to sparse vectors****************************************************************
2480  template< typename VT1 > // Type of the target sparse vector
2481  friend inline void assign( SparseVector<VT1,false>& lhs, const DVecScalarMultExpr& rhs )
2482  {
2484 
2488 
2489  BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
2490 
2491  const ResultType tmp( serial( rhs ) );
2492  assign( ~lhs, tmp );
2493  }
2494  //**********************************************************************************************
2495 
2496  //**Addition assignment to dense vectors********************************************************
2508  template< typename VT1 > // Type of the target dense vector
2509  friend inline void addAssign( DenseVector<VT1,false>& lhs, const DVecScalarMultExpr& rhs )
2510  {
2512 
2513  BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
2514 
2515  typename MVM::LeftOperand left ( rhs.vector_.leftOperand() );
2516  typename MVM::RightOperand right( rhs.vector_.rightOperand() );
2517 
2518  if( left.rows() == 0UL || left.columns() == 0UL ) {
2519  return;
2520  }
2521 
2522  LT A( serial( left ) ); // Evaluation of the left-hand side dense matrix operand
2523  RT x( serial( right ) ); // Evaluation of the right-hand side dense vector operand
2524 
2525  BLAZE_INTERNAL_ASSERT( A.rows() == left.rows() , "Invalid number of rows" );
2526  BLAZE_INTERNAL_ASSERT( A.columns() == left.columns(), "Invalid number of columns" );
2527  BLAZE_INTERNAL_ASSERT( x.size() == right.size() , "Invalid vector size" );
2528  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).size() , "Invalid vector size" );
2529 
2530  DVecScalarMultExpr::selectAddAssignKernel( ~lhs, A, x, rhs.scalar_ );
2531  }
2532  //**********************************************************************************************
2533 
2534  //**Addition assignment to dense vectors (kernel selection)*************************************
2545  template< typename VT1 // Type of the left-hand side target vector
2546  , typename MT1 // Type of the left-hand side matrix operand
2547  , typename VT2 // Type of the right-hand side vector operand
2548  , typename ST2 > // Type of the scalar value
2549  static inline void selectAddAssignKernel( VT1& y, const MT1& A, const VT2& x, ST2 scalar )
2550  {
2551  if( ( IsComputation<MT>::value && !evaluateMatrix ) ||
2552  ( A.rows() * A.columns() < DMATDVECMULT_THRESHOLD ) )
2553  DVecScalarMultExpr::selectDefaultAddAssignKernel( y, A, x, scalar );
2554  else
2555  DVecScalarMultExpr::selectBlasAddAssignKernel( y, A, x, scalar );
2556  }
2557  //**********************************************************************************************
2558 
2559  //**Default addition assignment to dense vectors************************************************
2573  template< typename VT1 // Type of the left-hand side target vector
2574  , typename MT1 // Type of the left-hand side matrix operand
2575  , typename VT2 // Type of the right-hand side vector operand
2576  , typename ST2 > // Type of the scalar value
2577  static inline typename DisableIf< UseVectorizedDefaultKernel<VT1,MT1,VT2,ST2> >::Type
2578  selectDefaultAddAssignKernel( VT1& y, const MT1& A, const VT2& x, ST2 scalar )
2579  {
2580  y.addAssign( A * x * scalar );
2581  }
2582  //**********************************************************************************************
2583 
2584  //**Vectorized default addition assignment to dense vectors*************************************
2598  template< typename VT1 // Type of the left-hand side target vector
2599  , typename MT1 // Type of the left-hand side matrix operand
2600  , typename VT2 // Type of the right-hand side vector operand
2601  , typename ST2 > // Type of the scalar value
2602  static inline typename EnableIf< UseVectorizedDefaultKernel<VT1,MT1,VT2,ST2> >::Type
2603  selectDefaultAddAssignKernel( VT1& y, const MT1& A, const VT2& x, ST2 scalar )
2604  {
2605  typedef IntrinsicTrait<ElementType> IT;
2606 
2607  const size_t M( A.rows() );
2608  const size_t N( A.columns() );
2609 
2610  size_t i( 0UL );
2611 
2612  for( ; (i+8UL) <= M; i+=8UL ) {
2613  IntrinsicType xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7, xmm8;
2614  for( size_t j=0UL; j<N; j+=IT::size ) {
2615  const IntrinsicType x1( x.load(j) );
2616  xmm1 = xmm1 + A.load(i ,j) * x1;
2617  xmm2 = xmm2 + A.load(i+1UL,j) * x1;
2618  xmm3 = xmm3 + A.load(i+2UL,j) * x1;
2619  xmm4 = xmm4 + A.load(i+3UL,j) * x1;
2620  xmm5 = xmm5 + A.load(i+4UL,j) * x1;
2621  xmm6 = xmm6 + A.load(i+5UL,j) * x1;
2622  xmm7 = xmm7 + A.load(i+6UL,j) * x1;
2623  xmm8 = xmm8 + A.load(i+7UL,j) * x1;
2624  }
2625  y[i ] += sum( xmm1 ) * scalar;
2626  y[i+1UL] += sum( xmm2 ) * scalar;
2627  y[i+2UL] += sum( xmm3 ) * scalar;
2628  y[i+3UL] += sum( xmm4 ) * scalar;
2629  y[i+4UL] += sum( xmm5 ) * scalar;
2630  y[i+5UL] += sum( xmm6 ) * scalar;
2631  y[i+6UL] += sum( xmm7 ) * scalar;
2632  y[i+7UL] += sum( xmm8 ) * scalar;
2633  }
2634  for( ; (i+4UL) <= M; i+=4UL ) {
2635  IntrinsicType xmm1, xmm2, xmm3, xmm4;
2636  for( size_t j=0UL; j<N; j+=IT::size ) {
2637  const IntrinsicType x1( x.load(j) );
2638  xmm1 = xmm1 + A.load(i ,j) * x1;
2639  xmm2 = xmm2 + A.load(i+1UL,j) * x1;
2640  xmm3 = xmm3 + A.load(i+2UL,j) * x1;
2641  xmm4 = xmm4 + A.load(i+3UL,j) * x1;
2642  }
2643  y[i ] += sum( xmm1 ) * scalar;
2644  y[i+1UL] += sum( xmm2 ) * scalar;
2645  y[i+2UL] += sum( xmm3 ) * scalar;
2646  y[i+3UL] += sum( xmm4 ) * scalar;
2647  }
2648  for( ; (i+3UL) <= M; i+=3UL ) {
2649  IntrinsicType xmm1, xmm2, xmm3;
2650  for( size_t j=0UL; j<N; j+=IT::size ) {
2651  const IntrinsicType x1( x.load(j) );
2652  xmm1 = xmm1 + A.load(i ,j) * x1;
2653  xmm2 = xmm2 + A.load(i+1UL,j) * x1;
2654  xmm3 = xmm3 + A.load(i+2UL,j) * x1;
2655  }
2656  y[i ] += sum( xmm1 ) * scalar;
2657  y[i+1UL] += sum( xmm2 ) * scalar;
2658  y[i+2UL] += sum( xmm3 ) * scalar;
2659  }
2660  for( ; (i+2UL) <= M; i+=2UL ) {
2661  IntrinsicType xmm1, xmm2;
2662  for( size_t j=0UL; j<N; j+=IT::size ) {
2663  const IntrinsicType x1( x.load(j) );
2664  xmm1 = xmm1 + A.load(i ,j) * x1;
2665  xmm2 = xmm2 + A.load(i+1UL,j) * x1;
2666  }
2667  y[i ] += sum( xmm1 ) * scalar;
2668  y[i+1UL] += sum( xmm2 ) * scalar;
2669  }
2670  if( i < M ) {
2671  IntrinsicType xmm1;
2672  for( size_t j=0UL; j<N; j+=IT::size ) {
2673  xmm1 = xmm1 + A.load(i,j) * x.load(j);
2674  }
2675  y[i] += sum( xmm1 ) * scalar;
2676  }
2677  }
2678  //**********************************************************************************************
2679 
2680  //**BLAS-based addition assignment to dense vectors (default)***********************************
2694  template< typename VT1 // Type of the left-hand side target vector
2695  , typename MT1 // Type of the left-hand side matrix operand
2696  , typename VT2 // Type of the right-hand side vector operand
2697  , typename ST2 > // Type of the scalar value
2698  static inline typename EnableIf< UseDefaultKernel<VT1,MT1,VT2,ST2> >::Type
2699  selectBlasAddAssignKernel( VT1& y, const MT1& A, const VT2& x, ST2 scalar )
2700  {
2701  selectDefaultAddAssignKernel( y, A, x, scalar );
2702  }
2703  //**********************************************************************************************
2704 
2705  //**BLAS-based addition assignment to dense vectors (single precision)**************************
2706 #if BLAZE_BLAS_MODE
2707 
2720  template< typename VT1 // Type of the left-hand side target vector
2721  , typename MT1 // Type of the left-hand side matrix operand
2722  , typename VT2 // Type of the right-hand side vector operand
2723  , typename ST2 > // Type of the scalar value
2724  static inline typename EnableIf< UseSinglePrecisionKernel<VT1,MT1,VT2,ST2> >::Type
2725  selectBlasAddAssignKernel( VT1& y, const MT1& A, const VT2& x, ST2 scalar )
2726  {
2727  using boost::numeric_cast;
2728 
2732 
2733  const int M ( numeric_cast<int>( A.rows() ) );
2734  const int N ( numeric_cast<int>( A.columns() ) );
2735  const int lda( numeric_cast<int>( A.spacing() ) );
2736 
2737  cblas_sgemv( CblasRowMajor, CblasNoTrans, M, N, scalar,
2738  A.data(), lda, x.data(), 1, 1.0F, y.data(), 1 );
2739  }
2740 #endif
2741  //**********************************************************************************************
2742 
2743  //**BLAS-based addition assignment to dense vectors (double precision)**************************
2744 #if BLAZE_BLAS_MODE
2745 
2758  template< typename VT1 // Type of the left-hand side target vector
2759  , typename MT1 // Type of the left-hand side matrix operand
2760  , typename VT2 // Type of the right-hand side vector operand
2761  , typename ST2 > // Type of the scalar value
2762  static inline typename EnableIf< UseDoublePrecisionKernel<VT1,MT1,VT2,ST2> >::Type
2763  selectBlasAddAssignKernel( VT1& y, const MT1& A, const VT2& x, ST2 scalar )
2764  {
2765  using boost::numeric_cast;
2766 
2770 
2771  const int M ( numeric_cast<int>( A.rows() ) );
2772  const int N ( numeric_cast<int>( A.columns() ) );
2773  const int lda( numeric_cast<int>( A.spacing() ) );
2774 
2775  cblas_dgemv( CblasRowMajor, CblasNoTrans, M, N, scalar,
2776  A.data(), lda, x.data(), 1, 1.0, y.data(), 1 );
2777  }
2778 #endif
2779  //**********************************************************************************************
2780 
2781  //**BLAS-based addition assignment to dense vectors (single precision complex)******************
2782 #if BLAZE_BLAS_MODE
2783 
2796  template< typename VT1 // Type of the left-hand side target vector
2797  , typename MT1 // Type of the left-hand side matrix operand
2798  , typename VT2 // Type of the right-hand side vector operand
2799  , typename ST2 > // Type of the scalar value
2800  static inline typename EnableIf< UseSinglePrecisionComplexKernel<VT1,MT1,VT2> >::Type
2801  selectBlasAddAssignKernel( VT1& y, const MT1& A, const VT2& x, ST2 scalar )
2802  {
2803  using boost::numeric_cast;
2804 
2808  BLAZE_CONSTRAINT_MUST_BE_FLOAT_TYPE ( typename VT1::ElementType::value_type );
2809  BLAZE_CONSTRAINT_MUST_BE_FLOAT_TYPE ( typename MT1::ElementType::value_type );
2810  BLAZE_CONSTRAINT_MUST_BE_FLOAT_TYPE ( typename VT2::ElementType::value_type );
2811 
2812  const int M ( numeric_cast<int>( A.rows() ) );
2813  const int N ( numeric_cast<int>( A.columns() ) );
2814  const int lda( numeric_cast<int>( A.spacing() ) );
2815  const complex<float> alpha( scalar );
2816  const complex<float> beta ( 1.0F, 0.0F );
2817 
2818  cblas_cgemv( CblasRowMajor, CblasNoTrans, M, N, &alpha,
2819  A.data(), lda, x.data(), 1, &beta, y.data(), 1 );
2820  }
2821 #endif
2822  //**********************************************************************************************
2823 
2824  //**BLAS-based addition assignment to dense vectors (double precision complex)******************
2825 #if BLAZE_BLAS_MODE
2826 
2839  template< typename VT1 // Type of the left-hand side target vector
2840  , typename MT1 // Type of the left-hand side matrix operand
2841  , typename VT2 // Type of the right-hand side vector operand
2842  , typename ST2 > // Type of the scalar value
2843  static inline typename EnableIf< UseDoublePrecisionComplexKernel<VT1,MT1,VT2> >::Type
2844  selectBlasAddAssignKernel( VT1& y, const MT1& A, const VT2& x, ST2 scalar )
2845  {
2846  using boost::numeric_cast;
2847 
2851  BLAZE_CONSTRAINT_MUST_BE_DOUBLE_TYPE ( typename VT1::ElementType::value_type );
2852  BLAZE_CONSTRAINT_MUST_BE_DOUBLE_TYPE ( typename MT1::ElementType::value_type );
2853  BLAZE_CONSTRAINT_MUST_BE_DOUBLE_TYPE ( typename VT2::ElementType::value_type );
2854 
2855  const int M ( numeric_cast<int>( A.rows() ) );
2856  const int N ( numeric_cast<int>( A.columns() ) );
2857  const int lda( numeric_cast<int>( A.spacing() ) );
2858  const complex<double> alpha( scalar );
2859  const complex<double> beta ( 1.0, 0.0 );
2860 
2861  cblas_zgemv( CblasRowMajor, CblasNoTrans, M, N, &alpha,
2862  A.data(), lda, x.data(), 1, &beta, y.data(), 1 );
2863  }
2864 #endif
2865  //**********************************************************************************************
2866 
2867  //**Addition assignment to sparse vectors*******************************************************
2868  // No special implementation for the addition assignment to sparse vectors.
2869  //**********************************************************************************************
2870 
2871  //**Subtraction assignment to dense vectors*****************************************************
2883  template< typename VT1 > // Type of the target dense vector
2884  friend inline void subAssign( DenseVector<VT1,false>& lhs, const DVecScalarMultExpr& rhs )
2885  {
2887 
2888  BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
2889 
2890  typename MVM::LeftOperand left ( rhs.vector_.leftOperand() );
2891  typename MVM::RightOperand right( rhs.vector_.rightOperand() );
2892 
2893  if( left.rows() == 0UL || left.columns() == 0UL ) {
2894  return;
2895  }
2896 
2897  LT A( serial( left ) ); // Evaluation of the left-hand side dense matrix operand
2898  RT x( serial( right ) ); // Evaluation of the right-hand side dense vector operand
2899 
2900  BLAZE_INTERNAL_ASSERT( A.rows() == left.rows() , "Invalid number of rows" );
2901  BLAZE_INTERNAL_ASSERT( A.columns() == left.columns(), "Invalid number of columns" );
2902  BLAZE_INTERNAL_ASSERT( x.size() == right.size() , "Invalid vector size" );
2903  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).size() , "Invalid vector size" );
2904 
2905  DVecScalarMultExpr::selectSubAssignKernel( ~lhs, A, x, rhs.scalar_ );
2906  }
2907  //**********************************************************************************************
2908 
2909  //**Subtraction assignment to dense vectors (kernel selection)**********************************
2920  template< typename VT1 // Type of the left-hand side target vector
2921  , typename MT1 // Type of the left-hand side matrix operand
2922  , typename VT2 // Type of the right-hand side vector operand
2923  , typename ST2 > // Type of the scalar value
2924  static inline void selectSubAssignKernel( VT1& y, const MT1& A, const VT2& x, ST2 scalar )
2925  {
2926  if( ( IsComputation<MT>::value && !evaluateMatrix ) ||
2927  ( A.rows() * A.columns() < DMATDVECMULT_THRESHOLD ) )
2928  DVecScalarMultExpr::selectDefaultSubAssignKernel( y, A, x, scalar );
2929  else
2930  DVecScalarMultExpr::selectBlasSubAssignKernel( y, A, x, scalar );
2931  }
2932  //**********************************************************************************************
2933 
2934  //**Default subtraction assignment to dense vectors*********************************************
2948  template< typename VT1 // Type of the left-hand side target vector
2949  , typename MT1 // Type of the left-hand side matrix operand
2950  , typename VT2 // Type of the right-hand side vector operand
2951  , typename ST2 > // Type of the scalar value
2952  static inline typename DisableIf< UseVectorizedDefaultKernel<VT1,MT1,VT2,ST2> >::Type
2953  selectDefaultSubAssignKernel( VT1& y, const MT1& A, const VT2& x, ST2 scalar )
2954  {
2955  y.subAssign( A * x * scalar );
2956  }
2957  //**********************************************************************************************
2958 
2959  //**Vectorized default subtraction assignment to dense vectors**********************************
2973  template< typename VT1 // Type of the left-hand side target vector
2974  , typename MT1 // Type of the left-hand side matrix operand
2975  , typename VT2 // Type of the right-hand side vector operand
2976  , typename ST2 > // Type of the scalar value
2977  static inline typename EnableIf< UseVectorizedDefaultKernel<VT1,MT1,VT2,ST2> >::Type
2978  selectDefaultSubAssignKernel( VT1& y, const MT1& A, const VT2& x, ST2 scalar )
2979  {
2980  typedef IntrinsicTrait<ElementType> IT;
2981 
2982  const size_t M( A.rows() );
2983  const size_t N( A.columns() );
2984 
2985  size_t i( 0UL );
2986 
2987  for( ; (i+8UL) <= M; i+=8UL ) {
2988  IntrinsicType xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7, xmm8;
2989  for( size_t j=0UL; j<N; j+=IT::size ) {
2990  const IntrinsicType x1( x.load(j) );
2991  xmm1 = xmm1 + A.load(i ,j) * x1;
2992  xmm2 = xmm2 + A.load(i+1UL,j) * x1;
2993  xmm3 = xmm3 + A.load(i+2UL,j) * x1;
2994  xmm4 = xmm4 + A.load(i+3UL,j) * x1;
2995  xmm5 = xmm5 + A.load(i+4UL,j) * x1;
2996  xmm6 = xmm6 + A.load(i+5UL,j) * x1;
2997  xmm7 = xmm7 + A.load(i+6UL,j) * x1;
2998  xmm8 = xmm8 + A.load(i+7UL,j) * x1;
2999  }
3000  y[i ] -= sum( xmm1 ) * scalar;
3001  y[i+1UL] -= sum( xmm2 ) * scalar;
3002  y[i+2UL] -= sum( xmm3 ) * scalar;
3003  y[i+3UL] -= sum( xmm4 ) * scalar;
3004  y[i+4UL] -= sum( xmm5 ) * scalar;
3005  y[i+5UL] -= sum( xmm6 ) * scalar;
3006  y[i+6UL] -= sum( xmm7 ) * scalar;
3007  y[i+7UL] -= sum( xmm8 ) * scalar;
3008  }
3009  for( ; (i+4UL) <= M; i+=4UL ) {
3010  IntrinsicType xmm1, xmm2, xmm3, xmm4;
3011  for( size_t j=0UL; j<N; j+=IT::size ) {
3012  const IntrinsicType x1( x.load(j) );
3013  xmm1 = xmm1 + A.load(i ,j) * x1;
3014  xmm2 = xmm2 + A.load(i+1UL,j) * x1;
3015  xmm3 = xmm3 + A.load(i+2UL,j) * x1;
3016  xmm4 = xmm4 + A.load(i+3UL,j) * x1;
3017  }
3018  y[i ] -= sum( xmm1 ) * scalar;
3019  y[i+1UL] -= sum( xmm2 ) * scalar;
3020  y[i+2UL] -= sum( xmm3 ) * scalar;
3021  y[i+3UL] -= sum( xmm4 ) * scalar;
3022  }
3023  for( ; (i+3UL) <= M; i+=3UL ) {
3024  IntrinsicType xmm1, xmm2, xmm3;
3025  for( size_t j=0UL; j<N; j+=IT::size ) {
3026  const IntrinsicType x1( x.load(j) );
3027  xmm1 = xmm1 + A.load(i ,j) * x1;
3028  xmm2 = xmm2 + A.load(i+1UL,j) * x1;
3029  xmm3 = xmm3 + A.load(i+2UL,j) * x1;
3030  }
3031  y[i ] -= sum( xmm1 ) * scalar;
3032  y[i+1UL] -= sum( xmm2 ) * scalar;
3033  y[i+2UL] -= sum( xmm3 ) * scalar;
3034  }
3035  for( ; (i+2UL) <= M; i+=2UL ) {
3036  IntrinsicType xmm1, xmm2;
3037  for( size_t j=0UL; j<N; j+=IT::size ) {
3038  const IntrinsicType x1( x.load(j) );
3039  xmm1 = xmm1 + A.load(i ,j) * x1;
3040  xmm2 = xmm2 + A.load(i+1UL,j) * x1;
3041  }
3042  y[i ] -= sum( xmm1 ) * scalar;
3043  y[i+1UL] -= sum( xmm2 ) * scalar;
3044  }
3045  if( i < M ) {
3046  IntrinsicType xmm1;
3047  for( size_t j=0UL; j<N; j+=IT::size ) {
3048  xmm1 = xmm1 + A.load(i,j) * x.load(j);
3049  }
3050  y[i] -= sum( xmm1 ) * scalar;
3051  }
3052  }
3053  //**********************************************************************************************
3054 
3055  //**BLAS-based subtraction assignment to dense vectors (default)********************************
3069  template< typename VT1 // Type of the left-hand side target vector
3070  , typename MT1 // Type of the left-hand side matrix operand
3071  , typename VT2 // Type of the right-hand side vector operand
3072  , typename ST2 > // Type of the scalar value
3073  static inline typename EnableIf< UseDefaultKernel<VT1,MT1,VT2,ST2> >::Type
3074  selectBlasSubAssignKernel( VT1& y, const MT1& A, const VT2& x, ST2 scalar )
3075  {
3076  selectDefaultSubAssignKernel( y, A, x, scalar );
3077  }
3078  //**********************************************************************************************
3079 
3080  //**BLAS-based subtraction assignment to dense vectors (single precision)***********************
3081 #if BLAZE_BLAS_MODE
3082 
3095  template< typename VT1 // Type of the left-hand side target vector
3096  , typename MT1 // Type of the left-hand side matrix operand
3097  , typename VT2 // Type of the right-hand side vector operand
3098  , typename ST2 > // Type of the scalar value
3099  static inline typename EnableIf< UseSinglePrecisionKernel<VT1,MT1,VT2,ST2> >::Type
3100  selectBlasSubAssignKernel( VT1& y, const MT1& A, const VT2& x, ST2 scalar )
3101  {
3102  using boost::numeric_cast;
3103 
3107 
3108  const int M ( numeric_cast<int>( A.rows() ) );
3109  const int N ( numeric_cast<int>( A.columns() ) );
3110  const int lda( numeric_cast<int>( A.spacing() ) );
3111 
3112  cblas_sgemv( CblasRowMajor, CblasNoTrans, M, N, -scalar,
3113  A.data(), lda, x.data(), 1, 1.0F, y.data(), 1 );
3114  }
3115 #endif
3116  //**********************************************************************************************
3117 
3118  //**BLAS-based subtraction assignment to dense vectors (double precision)***********************
3119 #if BLAZE_BLAS_MODE
3120 
3133  template< typename VT1 // Type of the left-hand side target vector
3134  , typename MT1 // Type of the left-hand side matrix operand
3135  , typename VT2 // Type of the right-hand side vector operand
3136  , typename ST2 > // Type of the scalar value
3137  static inline typename EnableIf< UseDoublePrecisionKernel<VT1,MT1,VT2,ST2> >::Type
3138  selectBlasSubAssignKernel( VT1& y, const MT1& A, const VT2& x, ST2 scalar )
3139  {
3140  using boost::numeric_cast;
3141 
3145 
3146  const int M ( numeric_cast<int>( A.rows() ) );
3147  const int N ( numeric_cast<int>( A.columns() ) );
3148  const int lda( numeric_cast<int>( A.spacing() ) );
3149 
3150  cblas_dgemv( CblasRowMajor, CblasNoTrans, M, N, -scalar,
3151  A.data(), lda, x.data(), 1, 1.0, y.data(), 1 );
3152  }
3153 #endif
3154  //**********************************************************************************************
3155 
3156  //**BLAS-based subtraction assignment to dense vectors (single precision complex)***************
3157 #if BLAZE_BLAS_MODE
3158 
3171  template< typename VT1 // Type of the left-hand side target vector
3172  , typename MT1 // Type of the left-hand side matrix operand
3173  , typename VT2 // Type of the right-hand side vector operand
3174  , typename ST2 > // Type of the scalar value
3175  static inline typename EnableIf< UseSinglePrecisionComplexKernel<VT1,MT1,VT2> >::Type
3176  selectBlasSubAssignKernel( VT1& y, const MT1& A, const VT2& x, ST2 scalar )
3177  {
3178  using boost::numeric_cast;
3179 
3183  BLAZE_CONSTRAINT_MUST_BE_FLOAT_TYPE ( typename VT1::ElementType::value_type );
3184  BLAZE_CONSTRAINT_MUST_BE_FLOAT_TYPE ( typename MT1::ElementType::value_type );
3185  BLAZE_CONSTRAINT_MUST_BE_FLOAT_TYPE ( typename VT2::ElementType::value_type );
3186 
3187  const int M ( numeric_cast<int>( A.rows() ) );
3188  const int N ( numeric_cast<int>( A.columns() ) );
3189  const int lda( numeric_cast<int>( A.spacing() ) );
3190  const complex<float> alpha( -scalar );
3191  const complex<float> beta ( 1.0F, 0.0F );
3192 
3193  cblas_cgemv( CblasRowMajor, CblasNoTrans, M, N, &alpha,
3194  A.data(), lda, x.data(), 1, &beta, y.data(), 1 );
3195  }
3196 #endif
3197  //**********************************************************************************************
3198 
3199  //**BLAS-based subtraction assignment to dense vectors (double precision complex)***************
3200 #if BLAZE_BLAS_MODE
3201 
3214  template< typename VT1 // Type of the left-hand side target vector
3215  , typename MT1 // Type of the left-hand side matrix operand
3216  , typename VT2 // Type of the right-hand side vector operand
3217  , typename ST2 > // Type of the scalar value
3218  static inline typename EnableIf< UseDoublePrecisionComplexKernel<VT1,MT1,VT2> >::Type
3219  selectBlasSubAssignKernel( VT1& y, const MT1& A, const VT2& x, ST2 scalar )
3220  {
3221  using boost::numeric_cast;
3222 
3226  BLAZE_CONSTRAINT_MUST_BE_DOUBLE_TYPE ( typename VT1::ElementType::value_type );
3227  BLAZE_CONSTRAINT_MUST_BE_DOUBLE_TYPE ( typename MT1::ElementType::value_type );
3228  BLAZE_CONSTRAINT_MUST_BE_DOUBLE_TYPE ( typename VT2::ElementType::value_type );
3229 
3230  const int M ( numeric_cast<int>( A.rows() ) );
3231  const int N ( numeric_cast<int>( A.columns() ) );
3232  const int lda( numeric_cast<int>( A.spacing() ) );
3233  const complex<double> alpha( -scalar );
3234  const complex<double> beta ( 1.0, 0.0 );
3235 
3236  cblas_zgemv( CblasRowMajor, CblasNoTrans, M, N, &alpha,
3237  A.data(), lda, x.data(), 1, &beta, y.data(), 1 );
3238  }
3239 #endif
3240  //**********************************************************************************************
3241 
3242  //**Subtraction assignment to sparse vectors****************************************************
3243  // No special implementation for the subtraction assignment to sparse vectors.
3244  //**********************************************************************************************
3245 
3246  //**Multiplication assignment to dense vectors**************************************************
3258  template< typename VT1 > // Type of the target dense vector
3259  friend inline void multAssign( DenseVector<VT1,false>& lhs, const DVecScalarMultExpr& rhs )
3260  {
3262 
3266 
3267  BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
3268 
3269  const ResultType tmp( serial( rhs ) );
3270  multAssign( ~lhs, tmp );
3271  }
3272  //**********************************************************************************************
3273 
3274  //**Multiplication assignment to sparse vectors*************************************************
3275  // No special implementation for the multiplication assignment to sparse vectors.
3276  //**********************************************************************************************
3277 
3278  //**SMP assignment to dense vectors*************************************************************
3292  template< typename VT1 > // Type of the target dense vector
3293  friend inline typename EnableIf< UseSMPAssign<VT1> >::Type
3294  smpAssign( DenseVector<VT1,false>& lhs, const DVecScalarMultExpr& rhs )
3295  {
3297 
3298  BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
3299 
3300  typename MVM::LeftOperand left ( rhs.vector_.leftOperand() );
3301  typename MVM::RightOperand right( rhs.vector_.rightOperand() );
3302 
3303  if( left.rows() == 0UL ) {
3304  return;
3305  }
3306  else if( left.columns() == 0UL ) {
3307  reset( ~lhs );
3308  return;
3309  }
3310 
3311  LT A( left ); // Evaluation of the left-hand side dense matrix operand
3312  RT x( right ); // Evaluation of the right-hand side dense vector operand
3313 
3314  BLAZE_INTERNAL_ASSERT( A.rows() == left.rows() , "Invalid number of rows" );
3315  BLAZE_INTERNAL_ASSERT( A.columns() == left.columns(), "Invalid number of columns" );
3316  BLAZE_INTERNAL_ASSERT( x.size() == right.size() , "Invalid vector size" );
3317  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).size() , "Invalid vector size" );
3318 
3319  smpAssign( ~lhs, A * x * rhs.scalar_ );
3320  }
3321  //**********************************************************************************************
3322 
3323  //**SMP assignment to sparse vectors************************************************************
3337  template< typename VT1 > // Type of the target sparse vector
3338  friend inline typename EnableIf< UseSMPAssign<VT1> >::Type
3339  smpAssign( SparseVector<VT1,false>& lhs, const DVecScalarMultExpr& rhs )
3340  {
3342 
3346 
3347  BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
3348 
3349  const ResultType tmp( rhs );
3350  smpAssign( ~lhs, tmp );
3351  }
3352  //**********************************************************************************************
3353 
3354  //**SMP addition assignment to dense vectors****************************************************
3368  template< typename VT1 > // Type of the target dense vector
3369  friend inline typename EnableIf< UseSMPAssign<VT1> >::Type
3370  smpAddAssign( DenseVector<VT1,false>& lhs, const DVecScalarMultExpr& rhs )
3371  {
3373 
3374  BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
3375 
3376  typename MVM::LeftOperand left ( rhs.vector_.leftOperand() );
3377  typename MVM::RightOperand right( rhs.vector_.rightOperand() );
3378 
3379  if( left.rows() == 0UL || left.columns() == 0UL ) {
3380  return;
3381  }
3382 
3383  LT A( left ); // Evaluation of the left-hand side dense matrix operand
3384  RT x( right ); // Evaluation of the right-hand side dense vector operand
3385 
3386  BLAZE_INTERNAL_ASSERT( A.rows() == left.rows() , "Invalid number of rows" );
3387  BLAZE_INTERNAL_ASSERT( A.columns() == left.columns(), "Invalid number of columns" );
3388  BLAZE_INTERNAL_ASSERT( x.size() == right.size() , "Invalid vector size" );
3389  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).size() , "Invalid vector size" );
3390 
3391  smpAddAssign( ~lhs, A * x * rhs.scalar_ );
3392  }
3393  //**********************************************************************************************
3394 
3395  //**SMP addition assignment to sparse vectors***************************************************
3396  // No special implementation for the SMP addition assignment to sparse vectors.
3397  //**********************************************************************************************
3398 
3399  //**SMP subtraction assignment to dense vectors*************************************************
3413  template< typename VT1 > // Type of the target dense vector
3414  friend inline typename EnableIf< UseSMPAssign<VT1> >::Type
3415  smpSubAssign( DenseVector<VT1,false>& lhs, const DVecScalarMultExpr& rhs )
3416  {
3418 
3419  BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
3420 
3421  typename MVM::LeftOperand left ( rhs.vector_.leftOperand() );
3422  typename MVM::RightOperand right( rhs.vector_.rightOperand() );
3423 
3424  if( left.rows() == 0UL || left.columns() == 0UL ) {
3425  return;
3426  }
3427 
3428  LT A( left ); // Evaluation of the left-hand side dense matrix operand
3429  RT x( right ); // Evaluation of the right-hand side dense vector operand
3430 
3431  BLAZE_INTERNAL_ASSERT( A.rows() == left.rows() , "Invalid number of rows" );
3432  BLAZE_INTERNAL_ASSERT( A.columns() == left.columns(), "Invalid number of columns" );
3433  BLAZE_INTERNAL_ASSERT( x.size() == right.size() , "Invalid vector size" );
3434  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).size() , "Invalid vector size" );
3435 
3436  smpSubAssign( ~lhs, A * x * rhs.scalar_ );
3437  }
3438  //**********************************************************************************************
3439 
3440  //**SMP subtraction assignment to sparse vectors************************************************
3441  // No special implementation for the SMP subtraction assignment to sparse vectors.
3442  //**********************************************************************************************
3443 
3444  //**SMP multiplication assignment to dense vectors**********************************************
3458  template< typename VT1 > // Type of the target dense vector
3459  friend inline typename EnableIf< UseSMPAssign<VT1> >::Type
3460  smpMultAssign( DenseVector<VT1,false>& lhs, const DVecScalarMultExpr& rhs )
3461  {
3463 
3467 
3468  BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
3469 
3470  const ResultType tmp( rhs );
3471  smpMultAssign( ~lhs, tmp );
3472  }
3473  //**********************************************************************************************
3474 
3475  //**SMP multiplication assignment to sparse vectors*********************************************
3476  // No special implementation for the SMP multiplication assignment to sparse vectors.
3477  //**********************************************************************************************
3478 
3479  //**Compile time checks*************************************************************************
3488  //**********************************************************************************************
3489 };
3491 //*************************************************************************************************
3492 
3493 
3494 
3495 
3496 //=================================================================================================
3497 //
3498 // GLOBAL BINARY ARITHMETIC OPERATORS
3499 //
3500 //=================================================================================================
3501 
3502 //*************************************************************************************************
3532 template< typename T1 // Type of the left-hand side dense matrix
3533  , typename T2 > // Type of the right-hand side dense vector
3534 inline const typename DisableIf< IsMatMatMultExpr<T1>, DMatDVecMultExpr<T1,T2> >::Type
3536 {
3538 
3539  if( (~mat).columns() != (~vec).size() )
3540  throw std::invalid_argument( "Matrix and vector sizes do not match" );
3541 
3542  return DMatDVecMultExpr<T1,T2>( ~mat, ~vec );
3543 }
3544 //*************************************************************************************************
3545 
3546 
3547 
3548 
3549 //=================================================================================================
3550 //
3551 // GLOBAL RESTRUCTURING BINARY ARITHMETIC OPERATORS
3552 //
3553 //=================================================================================================
3554 
3555 //*************************************************************************************************
3568 template< typename T1 // Type of the left-hand side dense matrix
3569  , bool SO // Storage order of the left-hand side dense matrix
3570  , typename T2 > // Type of the right-hand side dense vector
3571 inline const typename EnableIf< IsMatMatMultExpr<T1>, MultExprTrait<T1,T2> >::Type::Type
3573 {
3575 
3576  return (~mat).leftOperand() * ( (~mat).rightOperand() * vec );
3577 }
3578 //*************************************************************************************************
3579 
3580 
3581 
3582 
3583 //=================================================================================================
3584 //
3585 // EXPRESSION TRAIT SPECIALIZATIONS
3586 //
3587 //=================================================================================================
3588 
3589 //*************************************************************************************************
3591 template< typename MT, typename VT, bool AF >
3592 struct SubvectorExprTrait< DMatDVecMultExpr<MT,VT>, AF >
3593 {
3594  public:
3595  //**********************************************************************************************
3596  typedef typename MultExprTrait< typename SubmatrixExprTrait<const MT,AF>::Type, VT >::Type Type;
3597  //**********************************************************************************************
3598 };
3600 //*************************************************************************************************
3601 
3602 } // namespace blaze
3603 
3604 #endif
Data type constraint.
Compile time check whether the given type is a computational expression template.This type trait clas...
Definition: IsComputation.h:89
void reset(DynamicMatrix< Type, SO > &m)
Resetting the given dense matrix.
Definition: DynamicMatrix.h:4599
SelectType< IsExpression< VT >::value, const VT, const VT & >::Type RightOperand
Composite type of the right-hand side dense vector expression.
Definition: DMatDVecMultExpr.h:254
#define BLAZE_BLAS_IS_PARALLEL
Compilation switch for the parallel BLAS mode.This compilation switch specifies whether the used BLAS...
Definition: BLAS.h:86
RightOperand rightOperand() const
Returns the right-hand side dense vector operand.
Definition: DMatDVecMultExpr.h:343
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
DMatDVecMultExpr(const MT &mat, const VT &vec)
Constructor for the DMatDVecMultExpr class.
Definition: DMatDVecMultExpr.h:281
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
#define BLAZE_CONSTRAINT_MUST_BE_COLUMN_VECTOR_TYPE(T)
Constraint on the data type.In case the given data type T is not a column dense or sparse vector type...
Definition: TransposeFlag.h:159
Efficient implementation of a compressed matrix.The CompressedMatrix class template is the represent...
Definition: CompressedMatrix.h:199
Expression object for dense matrix-dense vector multiplications.The DMatDVecMultExpr class represents...
Definition: DMatDVecMultExpr.h:104
#define BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE(T)
Constraint on the data type.In case the given data type T is not a dense, N-dimensional matrix type...
Definition: DenseMatrix.h:79
MT::ResultType MRT
Result type of the left-hand side dense matrix expression.
Definition: DMatDVecMultExpr.h:110
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.
Constraint on the data type.
bool isAligned() const
Returns whether the operands of the expression are properly aligned in memory.
Definition: DMatDVecMultExpr.h:377
MultTrait< MRT, VRT >::Type ResultType
Result type for expression template evaluations.
Definition: DMatDVecMultExpr.h:243
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
Header file for the DenseVector base class.
const size_t SMP_DMATDVECMULT_THRESHOLD
SMP row-major dense matrix/dense vector multiplication threshold.This threshold specifies when a row-...
Definition: Thresholds.h:322
Compile time check for double precision floating point types.This type trait tests whether or not the...
Definition: IsDouble.h:75
const DMatSerialExpr< MT, SO > serial(const DenseMatrix< MT, SO > &dm)
Forces the serial evaluation of the given dense matrix expression dm.
Definition: DMatSerialExpr.h: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
Header file for the RequiresEvaluation type trait.
DMatDVecMultExpr< MT, VT > This
Type of this DMatDVecMultExpr instance.
Definition: DMatDVecMultExpr.h:242
Header file for the VecScalarMultExpr base class.
Header file for the IsFloat type trait.
Base class for dense matrices.The DenseMatrix class is a base class for all dense matrix classes...
Definition: DenseMatrix.h:70
Constraint on the data type.
#define BLAZE_CONSTRAINT_MUST_BE_FLOAT_TYPE(T)
Constraint on the data type.This compile time constraint checks that the given data type T is of type...
Definition: Float.h:80
size_t size() const
Returns the current size/dimension of the vector.
Definition: DMatDVecMultExpr.h:323
const size_t end_
End of the unrolled calculation loop.
Definition: DMatDVecMultExpr.h:399
Constraint on the data type.
VT::CompositeType VCT
Composite type of the right-hand side dense vector expression.
Definition: DMatDVecMultExpr.h:115
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
MRT::ElementType MET
Element type of the left-hand side dense matrix expression.
Definition: DMatDVecMultExpr.h:112
const This & CompositeType
Data type for composite expression templates.
Definition: CompressedMatrix.h:253
SelectType< evaluateVector, const VRT, VCT >::Type RT
Type for the assignment of the right-hand side dense vector operand.
Definition: DMatDVecMultExpr.h:260
Compile time type selection.The SelectType class template selects one of the two given types T1 and T...
Definition: SelectType.h:59
Header file for the DisableIf class template.
Header file for the multiplication trait.
Header file for the IsDouble type trait.
#define BLAZE_CONSTRAINT_MUST_BE_DOUBLE_TYPE(T)
Constraint on the data type.This compile time constraint checks that the given data type T is of type...
Definition: Double.h:80
Header file for the IsMatMatMultExpr type trait class.
Header file for the IsBlasCompatible type trait.
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
MT::CompositeType MCT
Composite type of the left-hand side dense matrix expression.
Definition: DMatDVecMultExpr.h:114
LeftOperand leftOperand() const
Returns the left-hand side dense matrix operand.
Definition: DMatDVecMultExpr.h:333
#define BLAZE_BLAS_MODE
Compilation switch for the BLAS mode.This compilation switch enables/disables the BLAS mode...
Definition: BLAS.h:65
bool canSMPAssign() const
Returns whether the expression can be used in SMP assignments.
Definition: DMatDVecMultExpr.h:387
Constraint on the data type.
Base class for all matrix/vector multiplication expression templates.The MatVecMultExpr class serves ...
Definition: MatVecMultExpr.h:66
#define BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE(T)
Constraint on the data type.In case the given data type T is not a reference type, a compilation error is created.
Definition: Reference.h:78
SelectType< evaluateMatrix, const MRT, MCT >::Type LT
Type for the assignment of the left-hand side dense matrix operand.
Definition: DMatDVecMultExpr.h:257
Constraints on the storage order of matrix types.
Constraint on the data type.
ResultType::ElementType ElementType
Resulting element type.
Definition: DMatDVecMultExpr.h:245
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.
LeftOperand mat_
Left-hand side dense matrix of the multiplication expression.
Definition: DMatDVecMultExpr.h:397
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.
#define BLAZE_CONSTRAINT_MUST_BE_ROW_MAJOR_MATRIX_TYPE(T)
Constraint on the data type.In case the given data type T is not a row-major dense or sparse matrix t...
Definition: StorageOrder.h:81
System settings for the BLAS mode.
Intrinsic characteristics of data types.The IntrinsicTrait class template provides the intrinsic char...
Definition: IntrinsicTrait.h:748
Header file for run time assertion macros.
Base template for the MultTrait class.
Definition: MultTrait.h:141
RightOperand vec_
Right-hand side dense vector of the multiplication expression.
Definition: DMatDVecMultExpr.h:398
bool canAlias(const T *alias) const
Returns whether the expression can alias with the given address alias.
Definition: DMatDVecMultExpr.h:355
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
VT::ResultType VRT
Result type of the right-hand side dense vector expression.
Definition: DMatDVecMultExpr.h:111
#define BLAZE_CONSTRAINT_MUST_BE_NUMERIC_TYPE(T)
Constraint on the data type.In case the given data type T is not a numeric (integral or floating poin...
Definition: Numeric.h:79
Header file for the reset shim.
const ResultType CompositeType
Data type for composite expression templates.
Definition: DMatDVecMultExpr.h: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
SelectType< IsExpression< MT >::value, const MT, const MT & >::Type LeftOperand
Composite type of the left-hand side dense matrix expression.
Definition: DMatDVecMultExpr.h:251
bool isAliased(const T *alias) const
Returns whether the expression is aliased with the given address alias.
Definition: DMatDVecMultExpr.h:367
ResultType::TransposeType TransposeType
Transpose type for expression template evaluations.
Definition: DMatDVecMultExpr.h:244
Header file for all intrinsic functionality.
#define BLAZE_CONSTRAINT_MUST_BE_DENSE_VECTOR_TYPE(T)
Constraint on the data type.In case the given data type T is not a dense, N-dimensional vector type...
Definition: DenseVector.h:79
#define BLAZE_CONSTRAINT_MUST_BE_COMPLEX_TYPE(T)
Constraint on the data type.This compile time constraint checks that the given data type T is a compl...
Definition: Complex.h:80
Header file for the IsComputation type trait class.
CompressedMatrix< Type,!SO > TransposeType
Transpose type for expression template evaluations.
Definition: CompressedMatrix.h:250
Base class for all compute expression templates.The Computation class serves as a tag for all computa...
Definition: Computation.h:59
IntrinsicTrait< ElementType >::Type IntrinsicType
Resulting intrinsic element type.
Definition: DMatDVecMultExpr.h:246
#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
const ElementType ReturnType
Return type for expression template evaluations.
Definition: DMatDVecMultExpr.h:247
size_t columns(const Matrix< MT, SO > &m)
Returns the current number of columns of the matrix.
Definition: Matrix.h:170
Header file for basic type definitions.
Header file for the IsComplex type trait.
Header file for the SubvectorExprTrait class template.
Header file for the complex data type.
ReturnType operator[](size_t index) const
Subscript operator for the direct access to the vector elements.
Definition: DMatDVecMultExpr.h:296
Header file for the MatVecMultExpr base class.
Compile time check for single precision floating point types.This type trait tests whether or not the...
Definition: IsFloat.h:75
const size_t DMATDVECMULT_THRESHOLD
Row-major dense matrix/dense vector multiplication threshold.This setting specifies the threshold bet...
Definition: Thresholds.h:57
VRT::ElementType VET
Element type of the right-hand side dense vector expression.
Definition: DMatDVecMultExpr.h:113
Constraint on the data type.
Size type of the Blaze library.
Header file for the thresholds for matrix/vector and matrix/matrix multiplications.
#define BLAZE_INTERNAL_ASSERT(expr, msg)
Run time assertion macro for internal checks.In case of an invalid run time expression, the program execution is terminated. The BLAZE_INTERNAL_ASSERT macro can be disabled by setting the BLAZE_USER_ASSERTION flag to zero or by defining NDEBUG during the compilation.
Definition: Assert.h:101
Header file for the IsExpression type trait class.
Header file for the FunctionTrace class.