All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
TDMatSVecMultExpr.h
Go to the documentation of this file.
1 //=================================================================================================
33 //=================================================================================================
34 
35 #ifndef _BLAZE_MATH_EXPRESSIONS_TDMATSVECMULTEXPR_H_
36 #define _BLAZE_MATH_EXPRESSIONS_TDMATSVECMULTEXPR_H_
37 
38 
39 //*************************************************************************************************
40 // Includes
41 //*************************************************************************************************
42 
43 #include <stdexcept>
53 #include <blaze/math/Intrinsics.h>
54 #include <blaze/math/shims/Reset.h>
66 #include <blaze/util/Assert.h>
68 #include <blaze/util/DisableIf.h>
70 #include <blaze/util/SelectType.h>
71 #include <blaze/util/Types.h>
74 
75 
76 namespace blaze {
77 
78 //=================================================================================================
79 //
80 // CLASS TDMATSVECMULTEXPR
81 //
82 //=================================================================================================
83 
84 //*************************************************************************************************
91 template< typename MT // Type of the left-hand side dense matrix
92  , typename VT > // Type of the right-hand side sparse vector
93 class TDMatSVecMultExpr : public DenseVector< TDMatSVecMultExpr<MT,VT>, false >
94  , private MatVecMultExpr
95  , private Computation
96 {
97  private:
98  //**Type definitions****************************************************************************
99  typedef typename MT::ResultType MRT;
100  typedef typename VT::ResultType VRT;
101  typedef typename MRT::ElementType MET;
102  typedef typename VRT::ElementType VET;
103  typedef typename MT::CompositeType MCT;
104  typedef typename VT::CompositeType VCT;
105  //**********************************************************************************************
106 
107  //**********************************************************************************************
109  enum { evaluateMatrix = ( IsComputation<MT>::value && IsSame<MET,VET>::value &&
111  //**********************************************************************************************
112 
113  //**********************************************************************************************
115  enum { evaluateVector = IsComputation<VT>::value || RequiresEvaluation<VT>::value };
116  //**********************************************************************************************
117 
118  //**********************************************************************************************
120 
124  template< typename T1 >
125  struct UseSMPAssign {
126  enum { value = ( evaluateMatrix || evaluateVector ) };
127  };
129  //**********************************************************************************************
130 
131  //**********************************************************************************************
133 
137  template< typename T1, typename T2, typename T3 >
138  struct UseVectorizedKernel {
139  enum { value = T1::vectorizable && T2::vectorizable &&
144  };
146  //**********************************************************************************************
147 
148  //**********************************************************************************************
150 
154  template< typename T1, typename T2, typename T3 >
155  struct UseOptimizedKernel {
156  enum { value = !UseVectorizedKernel<T1,T2,T3>::value &&
159  };
161  //**********************************************************************************************
162 
163  //**********************************************************************************************
165 
168  template< typename T1, typename T2, typename T3 >
169  struct UseDefaultKernel {
170  enum { value = !UseVectorizedKernel<T1,T2,T3>::value &&
171  !UseOptimizedKernel<T1,T2,T3>::value };
172  };
174  //**********************************************************************************************
175 
176  public:
177  //**Type definitions****************************************************************************
183  typedef const ElementType ReturnType;
184  typedef const ResultType CompositeType;
185 
187  typedef typename SelectType< IsExpression<MT>::value, const MT, const MT& >::Type LeftOperand;
188 
190  typedef typename SelectType< IsExpression<VT>::value, const VT, const VT& >::Type RightOperand;
191 
194 
197  //**********************************************************************************************
198 
199  //**Compilation flags***************************************************************************
201  enum { vectorizable = MT::vectorizable &&
205 
207  enum { smpAssignable = !evaluateMatrix && MT::smpAssignable &&
208  !evaluateVector && VT::smpAssignable };
209  //**********************************************************************************************
210 
211  //**Constructor*********************************************************************************
217  explicit inline TDMatSVecMultExpr( const MT& mat, const VT& vec )
218  : mat_( mat ) // Left-hand side dense matrix of the multiplication expression
219  , vec_( vec ) // Right-hand side sparse vector of the multiplication expression
220  {
221  BLAZE_INTERNAL_ASSERT( mat_.columns() == vec_.size(), "Invalid matrix and vector sizes" );
222  }
223  //**********************************************************************************************
224 
225  //**Subscript operator**************************************************************************
231  inline ReturnType operator[]( size_t index ) const {
232  BLAZE_INTERNAL_ASSERT( index < mat_.rows(), "Invalid vector access index" );
233 
235 
236  VCT x( vec_ ); // Evaluation of the right-hand side sparse vector operand
237 
238  BLAZE_INTERNAL_ASSERT( x.size() == vec_.size(), "Invalid vector size" );
239 
240  ConstIterator element( x.begin() );
241  ElementType res;
242 
243  if( element != x.end() ) {
244  res = mat_( index, element->index() ) * element->value();
245  ++element;
246  for( ; element!=x.end(); ++element ) {
247  res += mat_( index, element->index() ) * element->value();
248  }
249  }
250  else {
251  reset( res );
252  }
253 
254  return res;
255  }
256  //**********************************************************************************************
257 
258  //**Size function*******************************************************************************
263  inline size_t size() const {
264  return mat_.rows();
265  }
266  //**********************************************************************************************
267 
268  //**Left operand access*************************************************************************
273  inline LeftOperand leftOperand() const {
274  return mat_;
275  }
276  //**********************************************************************************************
277 
278  //**Right operand access************************************************************************
283  inline RightOperand rightOperand() const {
284  return vec_;
285  }
286  //**********************************************************************************************
287 
288  //**********************************************************************************************
294  template< typename T >
295  inline bool canAlias( const T* alias ) const {
296  return mat_.isAliased( alias ) || vec_.isAliased( alias );
297  }
298  //**********************************************************************************************
299 
300  //**********************************************************************************************
306  template< typename T >
307  inline bool isAliased( const T* alias ) const {
308  return mat_.isAliased( alias ) || vec_.isAliased( alias );
309  }
310  //**********************************************************************************************
311 
312  //**********************************************************************************************
317  inline bool isAligned() const {
318  return mat_.isAligned();
319  }
320  //**********************************************************************************************
321 
322  //**********************************************************************************************
327  inline bool canSMPAssign() const {
328  return ( size() > SMP_TDMATSVECMULT_THRESHOLD );
329  }
330  //**********************************************************************************************
331 
332  private:
333  //**Member variables****************************************************************************
336  //**********************************************************************************************
337 
338  //**Assignment to dense vectors*****************************************************************
351  template< typename VT1 > // Type of the target dense vector
352  friend inline void assign( DenseVector<VT1,false>& lhs, const TDMatSVecMultExpr& rhs )
353  {
355 
356  BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
357 
358  // Evaluation of the right-hand side sparse vector operand
359  RT x( serial( rhs.vec_ ) );
360  if( x.nonZeros() == 0UL ) {
361  reset( ~lhs );
362  return;
363  }
364 
365  // Evaluation of the left-hand side dense matrix operand
366  LT A( serial( rhs.mat_ ) );
367 
368  // Checking the evaluated operands
369  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.mat_.rows() , "Invalid number of rows" );
370  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.mat_.columns(), "Invalid number of columns" );
371  BLAZE_INTERNAL_ASSERT( x.size() == rhs.vec_.size() , "Invalid vector size" );
372  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).size() , "Invalid vector size" );
373 
374  // Performing the dense matrix-sparse vector multiplication
375  TDMatSVecMultExpr::selectAssignKernel( ~lhs, A, x );
376  }
378  //**********************************************************************************************
379 
380  //**Default assignment to dense vectors*********************************************************
394  template< typename VT1 // Type of the left-hand side target vector
395  , typename MT1 // Type of the left-hand side matrix operand
396  , typename VT2 > // Type of the right-hand side vector operand
397  static inline typename EnableIf< UseDefaultKernel<VT1,MT1,VT2> >::Type
398  selectAssignKernel( VT1& y, const MT1& A, const VT2& x )
399  {
401 
402  BLAZE_INTERNAL_ASSERT( x.nonZeros() != 0UL, "Invalid number of non-zero elements" );
403 
404  const size_t M( A.rows() );
405 
406  ConstIterator element( x.begin() );
407  const ConstIterator end( x.end() );
408 
409  for( size_t i=0UL; i<M; ++i ) {
410  y[i] = A(i,element->index()) * element->value();
411  }
412 
413  ++element;
414 
415  for( ; element!=end; ++element ) {
416  for( size_t i=0UL; i<M; ++i ) {
417  y[i] += A(i,element->index()) * element->value();
418  }
419  }
420  }
422  //**********************************************************************************************
423 
424  //**Optimized assignment to dense vectors*******************************************************
438  template< typename VT1 // Type of the left-hand side target vector
439  , typename MT1 // Type of the left-hand side matrix operand
440  , typename VT2 > // Type of the right-hand side vector operand
441  static inline typename EnableIf< UseOptimizedKernel<VT1,MT1,VT2> >::Type
442  selectAssignKernel( VT1& y, const MT1& A, const VT2& x )
443  {
445 
446  BLAZE_INTERNAL_ASSERT( x.nonZeros() != 0UL, "Invalid number of non-zero elements" );
447 
448  const size_t M( A.rows() );
449 
450  ConstIterator element( x.begin() );
451  const ConstIterator end( x.end() );
452 
453  const size_t jend( x.nonZeros() & size_t(-4) );
454  BLAZE_INTERNAL_ASSERT( ( x.nonZeros() - ( x.nonZeros() % 4UL ) ) == jend, "Invalid end calculation" );
455 
456  if( jend > 3UL )
457  {
458  const size_t j1( element->index() );
459  const VET v1( element->value() );
460  ++element;
461  const size_t j2( element->index() );
462  const VET v2( element->value() );
463  ++element;
464  const size_t j3( element->index() );
465  const VET v3( element->value() );
466  ++element;
467  const size_t j4( element->index() );
468  const VET v4( element->value() );
469  ++element;
470 
471  for( size_t i=0UL; i<M; ++i ) {
472  y[i] = A(i,j1) * v1 + A(i,j2) * v2 + A(i,j3) * v3 + A(i,j4) * v4;
473  }
474  }
475  else
476  {
477  const size_t j1( element->index() );
478  const VET v1( element->value() );
479  ++element;
480 
481  for( size_t i=0UL; i<M; ++i ) {
482  y[i] = A(i,j1) * v1;
483  }
484  }
485 
486  for( size_t j=(jend>3UL)?(4UL):(1UL); (j+4UL)<=jend; j+=4UL )
487  {
488  const size_t j1( element->index() );
489  const VET v1( element->value() );
490  ++element;
491  const size_t j2( element->index() );
492  const VET v2( element->value() );
493  ++element;
494  const size_t j3( element->index() );
495  const VET v3( element->value() );
496  ++element;
497  const size_t j4( element->index() );
498  const VET v4( element->value() );
499  ++element;
500 
501  for( size_t i=0UL; i<M; ++i ) {
502  y[i] += A(i,j1) * v1 + A(i,j2) * v2 + A(i,j3) * v3 + A(i,j4) * v4;
503  }
504  }
505  for( ; element!=end; ++element )
506  {
507  const size_t j1( element->index() );
508  const VET v1( element->value() );
509 
510  for( size_t i=0UL; i<M; ++i ) {
511  y[i] += A(i,j1) * v1;
512  }
513  }
514  }
516  //**********************************************************************************************
517 
518  //**Vectorized assignment to dense vectors******************************************************
532  template< typename VT1 // Type of the left-hand side target vector
533  , typename MT1 // Type of the left-hand side matrix operand
534  , typename VT2 > // Type of the right-hand side vector operand
535  static inline typename EnableIf< UseVectorizedKernel<VT1,MT1,VT2> >::Type
536  selectAssignKernel( VT1& y, const MT1& A, const VT2& x )
537  {
538  typedef IntrinsicTrait<ElementType> IT;
540 
541  BLAZE_INTERNAL_ASSERT( x.nonZeros() != 0UL, "Invalid number of non-zero elements" );
542 
543  const size_t M( A.rows() );
544 
545  ConstIterator element( x.begin() );
546  const ConstIterator end( x.end() );
547 
548  const size_t jend( x.nonZeros() & size_t(-4) );
549  BLAZE_INTERNAL_ASSERT( ( x.nonZeros() - ( x.nonZeros() % 4UL ) ) == jend, "Invalid end calculation" );
550 
551  if( jend > 3UL )
552  {
553  const size_t j1( element->index() );
554  const IntrinsicType v1( set( element->value() ) );
555  ++element;
556  const size_t j2( element->index() );
557  const IntrinsicType v2( set( element->value() ) );
558  ++element;
559  const size_t j3( element->index() );
560  const IntrinsicType v3( set( element->value() ) );
561  ++element;
562  const size_t j4( element->index() );
563  const IntrinsicType v4( set( element->value() ) );
564  ++element;
565 
566  for( size_t i=0UL; i<M; i+=IT::size ) {
567  y.store( i, A.load(i,j1) * v1 + A.load(i,j2) * v2 + A.load(i,j3) * v3 + A.load(i,j4) * v4 );
568  }
569  }
570  else
571  {
572  const size_t j1( element->index() );
573  const IntrinsicType v1( set( element->value() ) );
574  ++element;
575 
576  for( size_t i=0UL; i<M; i+=IT::size ) {
577  y.store( i, A.load(i,j1) * v1 );
578  }
579  }
580 
581  for( size_t j=(jend>3UL)?(4UL):(1UL); (j+4UL)<=jend; j+=4UL )
582  {
583  const size_t j1( element->index() );
584  const IntrinsicType v1( set( element->value() ) );
585  ++element;
586  const size_t j2( element->index() );
587  const IntrinsicType v2( set( element->value() ) );
588  ++element;
589  const size_t j3( element->index() );
590  const IntrinsicType v3( set( element->value() ) );
591  ++element;
592  const size_t j4( element->index() );
593  const IntrinsicType v4( set( element->value() ) );
594  ++element;
595 
596  for( size_t i=0UL; i<M; i+=IT::size ) {
597  y.store( i, y.load(i) + A.load(i,j1) * v1 + A.load(i,j2) * v2 + A.load(i,j3) * v3 + A.load(i,j4) * v4 );
598  }
599  }
600  for( ; element!=end; ++element )
601  {
602  const size_t j1( element->index() );
603  const IntrinsicType v1( set( element->value() ) );
604 
605  for( size_t i=0UL; i<M; i+=IT::size ) {
606  y.store( i, y.load(i) + A.load(i,j1) * v1 );
607  }
608  }
609  }
611  //**********************************************************************************************
612 
613  //**Assignment to sparse vectors****************************************************************
626  template< typename VT1 > // Type of the target sparse vector
627  friend inline void assign( SparseVector<VT1,false>& lhs, const TDMatSVecMultExpr& rhs )
628  {
630 
634 
635  BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
636 
637  const ResultType tmp( serial( rhs ) );
638  assign( ~lhs, tmp );
639  }
641  //**********************************************************************************************
642 
643  //**Addition assignment to dense vectors********************************************************
656  template< typename VT1 > // Type of the target dense vector
657  friend inline void addAssign( DenseVector<VT1,false>& lhs, const TDMatSVecMultExpr& rhs )
658  {
660 
661  BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
662 
664 
665  // Evaluation of the right-hand side sparse vector operand
666  RT x( serial( rhs.vec_ ) );
667  if( x.nonZeros() == 0UL ) return;
668 
669  // Evaluation of the left-hand side dense matrix operand
670  LT A( serial( rhs.mat_ ) );
671 
672  // Checking the evaluated operands
673  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.mat_.rows() , "Invalid number of rows" );
674  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.mat_.columns(), "Invalid number of columns" );
675  BLAZE_INTERNAL_ASSERT( x.size() == rhs.vec_.size() , "Invalid vector size" );
676  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).size() , "Invalid vector size" );
677 
678  // Performing the dense matrix-sparse vector multiplication
679  TDMatSVecMultExpr::selectAddAssignKernel( ~lhs, A, x );
680  }
682  //**********************************************************************************************
683 
684  //**Default addition assignment to dense vectors************************************************
698  template< typename VT1 // Type of the left-hand side target vector
699  , typename MT1 // Type of the left-hand side matrix operand
700  , typename VT2 > // Type of the right-hand side vector operand
701  static inline typename EnableIf< UseDefaultKernel<VT1,MT1,VT2> >::Type
702  selectAddAssignKernel( VT1& y, const MT1& A, const VT2& x )
703  {
705 
706  BLAZE_INTERNAL_ASSERT( x.nonZeros() != 0UL, "Invalid number of non-zero elements" );
707 
708  const size_t M( A.rows() );
709 
710  ConstIterator element( x.begin() );
711  const ConstIterator end( x.end() );
712 
713  for( ; element!=end; ++element ) {
714  for( size_t i=0UL; i<M; ++i ) {
715  y[i] += A(i,element->index()) * element->value();
716  }
717  }
718  }
720  //**********************************************************************************************
721 
722  //**Optimized addition assignment to dense vectors**********************************************
736  template< typename VT1 // Type of the left-hand side target vector
737  , typename MT1 // Type of the left-hand side matrix operand
738  , typename VT2 > // Type of the right-hand side vector operand
739  static inline typename EnableIf< UseOptimizedKernel<VT1,MT1,VT2> >::Type
740  selectAddAssignKernel( VT1& y, const MT1& A, const VT2& x )
741  {
743 
744  BLAZE_INTERNAL_ASSERT( x.nonZeros() != 0UL, "Invalid number of non-zero elements" );
745 
746  const size_t M( A.rows() );
747 
748  ConstIterator element( x.begin() );
749  const ConstIterator end( x.end() );
750 
751  const size_t jend( x.nonZeros() & size_t(-4) );
752  BLAZE_INTERNAL_ASSERT( ( x.nonZeros() - ( x.nonZeros() % 4UL ) ) == jend, "Invalid end calculation" );
753 
754  for( size_t j=0UL; (j+4UL)<=jend; j+=4UL )
755  {
756  const size_t j1( element->index() );
757  const VET v1( element->value() );
758  ++element;
759  const size_t j2( element->index() );
760  const VET v2( element->value() );
761  ++element;
762  const size_t j3( element->index() );
763  const VET v3( element->value() );
764  ++element;
765  const size_t j4( element->index() );
766  const VET v4( element->value() );
767  ++element;
768 
769  for( size_t i=0UL; i<M; ++i ) {
770  y[i] += A(i,j1) * v1 + A(i,j2) * v2 + A(i,j3) * v3 + A(i,j4) * v4;
771  }
772  }
773  for( ; element!=end; ++element )
774  {
775  const size_t j1( element->index() );
776  const VET v1( element->value() );
777 
778  for( size_t i=0UL; i<M; ++i ) {
779  y[i] += A(i,j1) * v1;
780  }
781  }
782  }
784  //**********************************************************************************************
785 
786  //**Vectorized addition assignment to dense vectors*********************************************
800  template< typename VT1 // Type of the left-hand side target vector
801  , typename MT1 // Type of the left-hand side matrix operand
802  , typename VT2 > // Type of the right-hand side vector operand
803  static inline typename EnableIf< UseVectorizedKernel<VT1,MT1,VT2> >::Type
804  selectAddAssignKernel( VT1& y, const MT1& A, const VT2& x )
805  {
806  typedef IntrinsicTrait<ElementType> IT;
808 
809  BLAZE_INTERNAL_ASSERT( x.nonZeros() != 0UL, "Invalid number of non-zero elements" );
810 
811  const size_t M( A.rows() );
812 
813  ConstIterator element( x.begin() );
814  const ConstIterator end( x.end() );
815 
816  const size_t jend( x.nonZeros() & size_t(-4) );
817  BLAZE_INTERNAL_ASSERT( ( x.nonZeros() - ( x.nonZeros() % 4UL ) ) == jend, "Invalid end calculation" );
818 
819  for( size_t j=0UL; (j+4UL)<=jend; j+=4UL )
820  {
821  const size_t j1( element->index() );
822  const IntrinsicType v1( set( element->value() ) );
823  ++element;
824  const size_t j2( element->index() );
825  const IntrinsicType v2( set( element->value() ) );
826  ++element;
827  const size_t j3( element->index() );
828  const IntrinsicType v3( set( element->value() ) );
829  ++element;
830  const size_t j4( element->index() );
831  const IntrinsicType v4( set( element->value() ) );
832  ++element;
833 
834  for( size_t i=0UL; i<M; i+=IT::size ) {
835  y.store( i, y.load(i) + A.load(i,j1) * v1 + A.load(i,j2) * v2 + A.load(i,j3) * v3 + A.load(i,j4) * v4 );
836  }
837  }
838  for( ; element!=end; ++element )
839  {
840  const size_t j1( element->index() );
841  const IntrinsicType v1( set( element->value() ) );
842 
843  for( size_t i=0UL; i<M; i+=IT::size ) {
844  y.store( i, y.load(i) + A.load(i,j1) * v1 );
845  }
846  }
847  }
849  //**********************************************************************************************
850 
851  //**Addition assignment to sparse vectors*******************************************************
852  // No special implementation for the addition assignment to sparse vectors.
853  //**********************************************************************************************
854 
855  //**Subtraction assignment to dense vectors*****************************************************
868  template< typename VT1 > // Type of the target dense vector
869  friend inline void subAssign( DenseVector<VT1,false>& lhs, const TDMatSVecMultExpr& rhs )
870  {
872 
873  BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
874 
876 
877  // Evaluation of the right-hand side sparse vector operand
878  RT x( serial( rhs.vec_ ) );
879  if( x.nonZeros() == 0UL ) return;
880 
881  // Evaluation of the left-hand side dense matrix operand
882  LT A( serial( rhs.mat_ ) );
883 
884  // Checking the evaluated operands
885  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.mat_.rows() , "Invalid number of rows" );
886  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.mat_.columns(), "Invalid number of columns" );
887  BLAZE_INTERNAL_ASSERT( x.size() == rhs.vec_.size() , "Invalid vector size" );
888  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).size() , "Invalid vector size" );
889 
890  // Performing the dense matrix-sparse vector multiplication
891  TDMatSVecMultExpr::selectSubAssignKernel( ~lhs, A, x );
892  }
894  //**********************************************************************************************
895 
896  //**Default subtraction assignment to dense vectors*********************************************
910  template< typename VT1 // Type of the left-hand side target vector
911  , typename MT1 // Type of the left-hand side matrix operand
912  , typename VT2 > // Type of the right-hand side vector operand
913  static inline typename EnableIf< UseDefaultKernel<VT1,MT1,VT2> >::Type
914  selectSubAssignKernel( VT1& y, const MT1& A, const VT2& x )
915  {
917 
918  BLAZE_INTERNAL_ASSERT( x.nonZeros() != 0UL, "Invalid number of non-zero elements" );
919 
920  const size_t M( A.rows() );
921 
922  ConstIterator element( x.begin() );
923  const ConstIterator end( x.end() );
924 
925  for( ; element!=end; ++element ) {
926  for( size_t i=0UL; i<M; ++i ) {
927  y[i] -= A(i,element->index()) * element->value();
928  }
929  }
930  }
932  //**********************************************************************************************
933 
934  //**Optimized subtraction assignment to dense vectors*******************************************
948  template< typename VT1 // Type of the left-hand side target vector
949  , typename MT1 // Type of the left-hand side matrix operand
950  , typename VT2 > // Type of the right-hand side vector operand
951  static inline typename EnableIf< UseOptimizedKernel<VT1,MT1,VT2> >::Type
952  selectSubAssignKernel( VT1& y, const MT1& A, const VT2& x )
953  {
955 
956  BLAZE_INTERNAL_ASSERT( x.nonZeros() != 0UL, "Invalid number of non-zero elements" );
957 
958  const size_t M( A.rows() );
959 
960  ConstIterator element( x.begin() );
961  const ConstIterator end( x.end() );
962 
963  const size_t jend( x.nonZeros() & size_t(-4) );
964  BLAZE_INTERNAL_ASSERT( ( x.nonZeros() - ( x.nonZeros() % 4UL ) ) == jend, "Invalid end calculation" );
965 
966  for( size_t j=0UL; (j+4UL)<=jend; j+=4UL )
967  {
968  const size_t j1( element->index() );
969  const VET v1( element->value() );
970  ++element;
971  const size_t j2( element->index() );
972  const VET v2( element->value() );
973  ++element;
974  const size_t j3( element->index() );
975  const VET v3( element->value() );
976  ++element;
977  const size_t j4( element->index() );
978  const VET v4( element->value() );
979  ++element;
980 
981  for( size_t i=0UL; i<M; ++i ) {
982  y[i] -= A(i,j1) * v1 + A(i,j2) * v2 + A(i,j3) * v3 + A(i,j4) * v4;
983  }
984  }
985  for( ; element!=end; ++element )
986  {
987  const size_t j1( element->index() );
988  const VET v1( element->value() );
989 
990  for( size_t i=0UL; i<M; ++i ) {
991  y[i] -= A(i,j1) * v1;
992  }
993  }
994  }
996  //**********************************************************************************************
997 
998  //**Vectorized subtraction assignment to dense vectors******************************************
1012  template< typename VT1 // Type of the left-hand side target vector
1013  , typename MT1 // Type of the left-hand side matrix operand
1014  , typename VT2 > // Type of the right-hand side vector operand
1015  static inline typename EnableIf< UseVectorizedKernel<VT1,MT1,VT2> >::Type
1016  selectSubAssignKernel( VT1& y, const MT1& A, const VT2& x )
1017  {
1018  typedef IntrinsicTrait<ElementType> IT;
1020 
1021  BLAZE_INTERNAL_ASSERT( x.nonZeros() != 0UL, "Invalid number of non-zero elements" );
1022 
1023  const size_t M( A.rows() );
1024 
1025  ConstIterator element( x.begin() );
1026  const ConstIterator end( x.end() );
1027 
1028  const size_t jend( x.nonZeros() & size_t(-4) );
1029  BLAZE_INTERNAL_ASSERT( ( x.nonZeros() - ( x.nonZeros() % 4UL ) ) == jend, "Invalid end calculation" );
1030 
1031  for( size_t j=0UL; (j+4UL)<=jend; j+=4UL )
1032  {
1033  const size_t j1( element->index() );
1034  const IntrinsicType v1( set( element->value() ) );
1035  ++element;
1036  const size_t j2( element->index() );
1037  const IntrinsicType v2( set( element->value() ) );
1038  ++element;
1039  const size_t j3( element->index() );
1040  const IntrinsicType v3( set( element->value() ) );
1041  ++element;
1042  const size_t j4( element->index() );
1043  const IntrinsicType v4( set( element->value() ) );
1044  ++element;
1045 
1046  for( size_t i=0UL; i<M; i+=IT::size ) {
1047  y.store( i, y.load(i) - A.load(i,j1) * v1 - A.load(i,j2) * v2 - A.load(i,j3) * v3 - A.load(i,j4) * v4 );
1048  }
1049  }
1050  for( ; element!=end; ++element )
1051  {
1052  const size_t j1( element->index() );
1053  const IntrinsicType v1( set( element->value() ) );
1054 
1055  for( size_t i=0UL; i<M; i+=IT::size ) {
1056  y.store( i, y.load(i) - A.load(i,j1) * v1 );
1057  }
1058  }
1059  }
1061  //**********************************************************************************************
1062 
1063  //**Subtraction assignment to sparse vectors****************************************************
1064  // No special implementation for the subtraction assignment to sparse vectors.
1065  //**********************************************************************************************
1066 
1067  //**Multiplication assignment to dense vectors**************************************************
1080  template< typename VT1 > // Type of the target dense vector
1081  friend inline void multAssign( DenseVector<VT1,false>& lhs, const TDMatSVecMultExpr& rhs )
1082  {
1084 
1088 
1089  BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
1090 
1091  const ResultType tmp( serial( rhs ) );
1092  multAssign( ~lhs, tmp );
1093  }
1095  //**********************************************************************************************
1096 
1097  //**Multiplication assignment to sparse vectors*************************************************
1098  // No special implementation for the multiplication assignment to sparse vectors.
1099  //**********************************************************************************************
1100 
1101  //**SMP assignment to dense vectors*****************************************************************
1116  template< typename VT1 > // Type of the target dense vector
1117  friend inline typename EnableIf< UseSMPAssign<VT1> >::Type
1118  smpAssign( DenseVector<VT1,false>& lhs, const TDMatSVecMultExpr& rhs )
1119  {
1121 
1122  BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
1123 
1124  // Evaluation of the right-hand side sparse vector operand
1125  RT x( rhs.vec_ );
1126  if( x.nonZeros() == 0UL ) {
1127  reset( ~lhs );
1128  return;
1129  }
1130 
1131  // Evaluation of the left-hand side dense matrix operand
1132  LT A( rhs.mat_ );
1133 
1134  // Checking the evaluated operands
1135  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.mat_.rows() , "Invalid number of rows" );
1136  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.mat_.columns(), "Invalid number of columns" );
1137  BLAZE_INTERNAL_ASSERT( x.size() == rhs.vec_.size() , "Invalid vector size" );
1138  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).size() , "Invalid vector size" );
1139 
1140  // Performing the dense matrix-sparse vector multiplication
1141  smpAssign( ~lhs, A * x );
1142  }
1144  //**********************************************************************************************
1145 
1146  //**SMP assignment to sparse vectors************************************************************
1161  template< typename VT1 > // Type of the target sparse vector
1162  friend inline typename EnableIf< UseSMPAssign<VT1> >::Type
1163  smpAssign( SparseVector<VT1,false>& lhs, const TDMatSVecMultExpr& rhs )
1164  {
1166 
1170 
1171  BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
1172 
1173  const ResultType tmp( rhs );
1174  smpAssign( ~lhs, tmp );
1175  }
1177  //**********************************************************************************************
1178 
1179  //**SMP addition assignment to dense vectors****************************************************
1194  template< typename VT1 > // Type of the target dense vector
1195  friend inline typename EnableIf< UseSMPAssign<VT1> >::Type
1196  smpAddAssign( DenseVector<VT1,false>& lhs, const TDMatSVecMultExpr& rhs )
1197  {
1199 
1200  BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
1201 
1203 
1204  // Evaluation of the right-hand side sparse vector operand
1205  RT x( rhs.vec_ );
1206  if( x.nonZeros() == 0UL ) return;
1207 
1208  // Evaluation of the left-hand side dense matrix operand
1209  LT A( rhs.mat_ );
1210 
1211  // Checking the evaluated operands
1212  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.mat_.rows() , "Invalid number of rows" );
1213  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.mat_.columns(), "Invalid number of columns" );
1214  BLAZE_INTERNAL_ASSERT( x.size() == rhs.vec_.size() , "Invalid vector size" );
1215  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).size() , "Invalid vector size" );
1216 
1217  // Performing the dense matrix-sparse vector multiplication
1218  smpAddAssign( ~lhs, A * x );
1219  }
1221  //**********************************************************************************************
1222 
1223  //**SMP addition assignment to sparse vectors***************************************************
1224  // No special implementation for the SMP addition assignment to sparse vectors.
1225  //**********************************************************************************************
1226 
1227  //**SMP subtraction assignment to dense vectors*************************************************
1242  template< typename VT1 > // Type of the target dense vector
1243  friend inline typename EnableIf< UseSMPAssign<VT1> >::Type
1244  smpSubAssign( DenseVector<VT1,false>& lhs, const TDMatSVecMultExpr& rhs )
1245  {
1247 
1248  BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
1249 
1251 
1252  // Evaluation of the right-hand side sparse vector operand
1253  RT x( rhs.vec_ );
1254  if( x.nonZeros() == 0UL ) return;
1255 
1256  // Evaluation of the left-hand side dense matrix operand
1257  LT A( rhs.mat_ );
1258 
1259  // Checking the evaluated operands
1260  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.mat_.rows() , "Invalid number of rows" );
1261  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.mat_.columns(), "Invalid number of columns" );
1262  BLAZE_INTERNAL_ASSERT( x.size() == rhs.vec_.size() , "Invalid vector size" );
1263  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).size() , "Invalid vector size" );
1264 
1265  // Performing the dense matrix-sparse vector multiplication
1266  smpSubAssign( ~lhs, A * x );
1267  }
1269  //**********************************************************************************************
1270 
1271  //**SMP subtraction assignment to sparse vectors************************************************
1272  // No special implementation for the SMP subtraction assignment to sparse vectors.
1273  //**********************************************************************************************
1274 
1275  //**SMP multiplication assignment to dense vectors**********************************************
1290  template< typename VT1 > // Type of the target dense vector
1291  friend inline typename EnableIf< UseSMPAssign<VT1> >::Type
1292  smpMultAssign( DenseVector<VT1,false>& lhs, const TDMatSVecMultExpr& rhs )
1293  {
1295 
1299 
1300  BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
1301 
1302  const ResultType tmp( rhs );
1303  smpMultAssign( ~lhs, tmp );
1304  }
1306  //**********************************************************************************************
1307 
1308  //**SMP multiplication assignment to sparse vectors*********************************************
1309  // No special implementation for the SMP multiplication assignment to sparse vectors.
1310  //**********************************************************************************************
1311 
1312  //**Compile time checks*************************************************************************
1319  //**********************************************************************************************
1320 };
1321 //*************************************************************************************************
1322 
1323 
1324 
1325 
1326 //=================================================================================================
1327 //
1328 // GLOBAL BINARY ARITHMETIC OPERATORS
1329 //
1330 //=================================================================================================
1331 
1332 //*************************************************************************************************
1364 template< typename T1 // Type of the left-hand side dense matrix
1365  , typename T2 > // Type of the right-hand side sparse vector
1366 inline const typename DisableIf< IsMatMatMultExpr<T1>, TDMatSVecMultExpr<T1,T2> >::Type
1368 {
1370 
1371  if( (~mat).columns() != (~vec).size() )
1372  throw std::invalid_argument( "Matrix and vector sizes do not match" );
1373 
1374  return TDMatSVecMultExpr<T1,T2>( ~mat, ~vec );
1375 }
1376 //*************************************************************************************************
1377 
1378 
1379 
1380 
1381 //=================================================================================================
1382 //
1383 // EXPRESSION TRAIT SPECIALIZATIONS
1384 //
1385 //=================================================================================================
1386 
1387 //*************************************************************************************************
1389 template< typename MT, typename VT, bool AF >
1390 struct SubvectorExprTrait< TDMatSVecMultExpr<MT,VT>, AF >
1391 {
1392  public:
1393  //**********************************************************************************************
1394  typedef typename MultExprTrait< typename SubmatrixExprTrait<const MT,AF>::Type, VT >::Type Type;
1395  //**********************************************************************************************
1396 };
1398 //*************************************************************************************************
1399 
1400 } // namespace blaze
1401 
1402 #endif
ResultType::ElementType ElementType
Resulting element type.
Definition: TDMatSVecMultExpr.h:181
Compile time check whether the given type is a computational expression template.This type trait clas...
Definition: IsComputation.h:89
size_t size() const
Returns the current size/dimension of the vector.
Definition: TDMatSVecMultExpr.h:263
void reset(DynamicMatrix< Type, SO > &m)
Resetting the given dense matrix.
Definition: DynamicMatrix.h:4599
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
VT::ResultType VRT
Result type of the right-hand side sparse vector expression.
Definition: TDMatSVecMultExpr.h:100
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
#define BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE(T)
Constraint on the data type.In case the given data type T is not a dense, N-dimensional matrix type...
Definition: DenseMatrix.h:79
void smpMultAssign(DenseVector< VT1, TF1 > &lhs, const Vector< VT2, TF2 > &rhs)
Default implementation of the SMP multiplication assignment of a vector to a dense vector...
Definition: DenseVector.h:179
RightOperand vec_
Right-hand side sparse vector of the multiplication expression.
Definition: TDMatSVecMultExpr.h:335
Header file for the IsSame and IsStrictlySame type traits.
VRT::ElementType VET
Element type of the right-hand side sparse vector expression.
Definition: TDMatSVecMultExpr.h:102
bool isAligned() const
Returns whether the operands of the expression are properly aligned in memory.
Definition: TDMatSVecMultExpr.h:317
const size_t SMP_TDMATSVECMULT_THRESHOLD
SMP column-major dense matrix/sparse vector multiplication threshold.This threshold specifies when a ...
Definition: Thresholds.h:437
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.
MRT::ElementType MET
Element type of the left-hand side dense matrix expression.
Definition: TDMatSVecMultExpr.h:101
TDMatSVecMultExpr< MT, VT > This
Type of this TDMatSVecMultExpr instance.
Definition: TDMatSVecMultExpr.h:178
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
MultTrait< MRT, VRT >::Type ResultType
Result type for expression template evaluations.
Definition: TDMatSVecMultExpr.h:179
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.
Base class for dense matrices.The DenseMatrix class is a base class for all dense matrix classes...
Definition: DenseMatrix.h:70
SelectType< IsExpression< VT >::value, const VT, const VT & >::Type RightOperand
Composite type of the right-hand side dense vector expression.
Definition: TDMatSVecMultExpr.h:190
Constraint on the data type.
ReturnType operator[](size_t index) const
Subscript operator for the direct access to the vector elements.
Definition: TDMatSVecMultExpr.h:231
bool isAliased(const T *alias) const
Returns whether the expression is aliased with the given address alias.
Definition: TDMatSVecMultExpr.h:307
Constraint on the data type.
Header file for the MultExprTrait class template.
void smpAddAssign(DenseMatrix< MT1, SO1 > &lhs, const Matrix< MT2, SO2 > &rhs)
Default implementation of the SMP addition assignment of a matrix to a dense matrix.
Definition: DenseMatrix.h:122
Compile time check to query the requirement to evaluate an expression.Via this type trait it is possi...
Definition: RequiresEvaluation.h:90
const This & CompositeType
Data type for composite expression templates.
Definition: CompressedMatrix.h:253
Compile time type selection.The SelectType class template selects one of the two given types T1 and T...
Definition: SelectType.h:59
Header file for the DisableIf class template.
Header file for the multiplication trait.
const ElementType ReturnType
Return type for expression template evaluations.
Definition: TDMatSVecMultExpr.h:183
bool canSMPAssign() const
Returns whether the expression can be used in SMP assignments.
Definition: TDMatSVecMultExpr.h:327
#define BLAZE_CONSTRAINT_MUST_BE_COLUMN_MAJOR_MATRIX_TYPE(T)
Constraint on the data type.In case the given data type T is not a column-major dense or sparse matri...
Definition: StorageOrder.h:161
const Element * ConstIterator
Iterator over constant elements.
Definition: CompressedMatrix.h:2412
Header file for the IsMatMatMultExpr type trait class.
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
LeftOperand mat_
Left-hand side dense matrix of the multiplication expression.
Definition: TDMatSVecMultExpr.h:334
Base class for N-dimensional dense vectors.The DenseVector class is a base class for all arbitrarily ...
Definition: DenseVector.h:70
IntrinsicTrait< ElementType >::Type IntrinsicType
Resulting intrinsic element type.
Definition: TDMatSVecMultExpr.h:182
#define BLAZE_CONSTRAINT_MUST_BE_SPARSE_VECTOR_TYPE(T)
Constraint on the data type.In case the given data type T is not a sparse, N-dimensional vector type...
Definition: SparseVector.h:79
Constraint on the data type.
#define BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE(T)
Constraint on the data type.In case the given data type T is not a reference type, a compilation error is created.
Definition: Reference.h:78
const ResultType CompositeType
Data type for composite expression templates.
Definition: TDMatSVecMultExpr.h:184
Constraints on the storage order of matrix types.
Constraint on the data type.
TDMatSVecMultExpr(const MT &mat, const VT &vec)
Constructor for the TDMatSVecMultExpr class.
Definition: TDMatSVecMultExpr.h:217
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.
Constraint on the data type.
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
SelectType< evaluateVector, const VRT, typename VT::CompositeType >::Type RT
Type for the assignment of the right-hand side dense matrix operand.
Definition: TDMatSVecMultExpr.h:196
Expression object for transpose dense matrix-sparse vector multiplications.The TDMatSVecMultExpr clas...
Definition: Forward.h:130
Compile time check for resizable data types.This type trait tests whether the given data type is a re...
Definition: IsResizable.h:75
Header file for the SubmatrixExprTrait class template.
Removal of reference modifiers.The RemoveCV type trait removes any reference modifiers from the given...
Definition: RemoveReference.h:69
Intrinsic characteristics of data types.The IntrinsicTrait class template provides the intrinsic char...
Definition: IntrinsicTrait.h:748
LeftOperand leftOperand() const
Returns the left-hand side transpose dense matrix operand.
Definition: TDMatSVecMultExpr.h:273
Header file for run time assertion macros.
Base template for the MultTrait class.
Definition: MultTrait.h:141
void addAssign(Matrix< MT1, SO1 > &lhs, const Matrix< MT2, SO2 > &rhs)
Default implementation of the addition assignment of a matrix to a matrix.
Definition: Matrix.h:301
Substitution Failure Is Not An Error (SFINAE) class.The EnableIf class template is an auxiliary tool ...
Definition: EnableIf.h:184
VT::CompositeType VCT
Composite type of the right-hand side sparse vector expression.
Definition: TDMatSVecMultExpr.h:104
Header file for the reset shim.
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
MT::ResultType MRT
Result type of the left-hand side dense matrix expression.
Definition: TDMatSVecMultExpr.h:99
SelectType< evaluateMatrix, const MRT, MCT >::Type LT
Type for the assignment of the left-hand side dense matrix operand.
Definition: TDMatSVecMultExpr.h:193
Header file for the RemoveReference type trait.
bool canAlias(const T *alias) const
Returns whether the expression can alias with the given address alias.
Definition: TDMatSVecMultExpr.h:295
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
RightOperand rightOperand() const
Returns the right-hand side sparse vector operand.
Definition: TDMatSVecMultExpr.h:283
Header file for the IsComputation type trait class.
ResultType::TransposeType TransposeType
Transpose type for expression template evaluations.
Definition: TDMatSVecMultExpr.h:180
Base class for sparse vectors.The SparseVector class is a base class for all arbitrarily sized (N-dim...
Definition: Forward.h:108
#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
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 SubvectorExprTrait class template.
Header file for the MatVecMultExpr base class.
SelectType< IsExpression< MT >::value, const MT, const MT & >::Type LeftOperand
Composite type of the left-hand side dense matrix expression.
Definition: TDMatSVecMultExpr.h:187
Header file for the IsResizable type trait.
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
EnableIf< IsIntegral< T >, Set< T, sizeof(T)> >::Type::Type set(T value)
Sets all values in the vector to the given integral value.
Definition: Set.h:209
MT::CompositeType MCT
Composite type of the left-hand side dense matrix expression.
Definition: TDMatSVecMultExpr.h:103
Header file for the IsExpression type trait class.
Header file for the FunctionTrace class.