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>
67 #include <blaze/util/Assert.h>
69 #include <blaze/util/DisableIf.h>
71 #include <blaze/util/SelectType.h>
72 #include <blaze/util/Types.h>
75 
76 
77 namespace blaze {
78 
79 //=================================================================================================
80 //
81 // CLASS TDMATSVECMULTEXPR
82 //
83 //=================================================================================================
84 
85 //*************************************************************************************************
92 template< typename MT // Type of the left-hand side dense matrix
93  , typename VT > // Type of the right-hand side sparse vector
94 class TDMatSVecMultExpr : public DenseVector< TDMatSVecMultExpr<MT,VT>, false >
95  , private MatVecMultExpr
96  , private Computation
97 {
98  private:
99  //**Type definitions****************************************************************************
100  typedef typename MT::ResultType MRT;
101  typedef typename VT::ResultType VRT;
102  typedef typename MRT::ElementType MET;
103  typedef typename VRT::ElementType VET;
104  typedef typename MT::CompositeType MCT;
105  typedef typename VT::CompositeType VCT;
106  //**********************************************************************************************
107 
108  //**********************************************************************************************
110  enum { evaluateMatrix = ( IsComputation<MT>::value && IsSame<MET,VET>::value &&
112  //**********************************************************************************************
113 
114  //**********************************************************************************************
116  enum { evaluateVector = IsComputation<VT>::value || RequiresEvaluation<VT>::value };
117  //**********************************************************************************************
118 
119  //**********************************************************************************************
121 
124  template< typename T1, typename T2, typename T3 >
125  struct UseSMPAssignKernel {
126  enum { value = evaluateMatrix || evaluateVector };
127  };
129  //**********************************************************************************************
130 
131  //**********************************************************************************************
133 
137  template< typename T1, typename T2, typename T3 >
138  struct UseVectorizedKernel {
139  enum { value = !UseSMPAssignKernel<T1,T2,T3>::value &&
140  T1::vectorizable && T2::vectorizable &&
145  };
147  //**********************************************************************************************
148 
149  //**********************************************************************************************
151 
155  template< typename T1, typename T2, typename T3 >
156  struct UseOptimizedKernel {
157  enum { value = !UseSMPAssignKernel<T1,T2,T3>::value &&
158  !UseVectorizedKernel<T1,T2,T3>::value &&
161  };
163  //**********************************************************************************************
164 
165  //**********************************************************************************************
167 
170  template< typename T1, typename T2, typename T3 >
171  struct UseDefaultKernel {
172  enum { value = !UseSMPAssignKernel<T1,T2,T3>::value &&
173  !UseVectorizedKernel<T1,T2,T3>::value &&
174  !UseOptimizedKernel<T1,T2,T3>::value };
175  };
177  //**********************************************************************************************
178 
179  public:
180  //**Type definitions****************************************************************************
186  typedef const ElementType ReturnType;
187  typedef const ResultType CompositeType;
188 
190  typedef typename SelectType< IsExpression<MT>::value, const MT, const MT& >::Type LeftOperand;
191 
193  typedef typename SelectType< IsExpression<VT>::value, const VT, const VT& >::Type RightOperand;
194 
197 
200  //**********************************************************************************************
201 
202  //**Compilation flags***************************************************************************
204  enum { vectorizable = MT::vectorizable &&
208 
210  enum { smpAssignable = !evaluateMatrix && !evaluateVector };
211  //**********************************************************************************************
212 
213  //**Constructor*********************************************************************************
219  explicit inline TDMatSVecMultExpr( const MT& mat, const VT& vec )
220  : mat_( mat ) // Left-hand side dense matrix of the multiplication expression
221  , vec_( vec ) // Right-hand side sparse vector of the multiplication expression
222  {
223  BLAZE_INTERNAL_ASSERT( mat_.columns() == vec_.size(), "Invalid matrix and vector sizes" );
224  }
225  //**********************************************************************************************
226 
227  //**Subscript operator**************************************************************************
233  inline ReturnType operator[]( size_t index ) const {
234  BLAZE_INTERNAL_ASSERT( index < mat_.rows(), "Invalid vector access index" );
235 
237 
238  VCT x( vec_ ); // Evaluation of the right-hand side sparse vector operand
239 
240  BLAZE_INTERNAL_ASSERT( x.size() == vec_.size(), "Invalid vector size" );
241 
242  ConstIterator element( x.begin() );
243  ElementType res;
244 
245  if( element != x.end() ) {
246  res = mat_( index, element->index() ) * element->value();
247  ++element;
248  for( ; element!=x.end(); ++element ) {
249  res += mat_( index, element->index() ) * element->value();
250  }
251  }
252  else {
253  reset( res );
254  }
255 
256  return res;
257  }
258  //**********************************************************************************************
259 
260  //**Size function*******************************************************************************
265  inline size_t size() const {
266  return mat_.rows();
267  }
268  //**********************************************************************************************
269 
270  //**Left operand access*************************************************************************
275  inline LeftOperand leftOperand() const {
276  return mat_;
277  }
278  //**********************************************************************************************
279 
280  //**Right operand access************************************************************************
285  inline RightOperand rightOperand() const {
286  return vec_;
287  }
288  //**********************************************************************************************
289 
290  //**********************************************************************************************
296  template< typename T >
297  inline bool canAlias( const T* alias ) const {
298  return mat_.isAliased( alias ) || vec_.isAliased( alias );
299  }
300  //**********************************************************************************************
301 
302  //**********************************************************************************************
308  template< typename T >
309  inline bool isAliased( const T* alias ) const {
310  return mat_.isAliased( alias ) || vec_.isAliased( alias );
311  }
312  //**********************************************************************************************
313 
314  //**********************************************************************************************
319  inline bool isAligned() const {
320  return mat_.isAligned();
321  }
322  //**********************************************************************************************
323 
324  //**********************************************************************************************
329  inline bool canSMPAssign() const {
330  return ( size() > SMP_TDMATSVECMULT_THRESHOLD );
331  }
332  //**********************************************************************************************
333 
334  private:
335  //**Member variables****************************************************************************
336  LeftOperand mat_;
337  RightOperand vec_;
338  //**********************************************************************************************
339 
340  //**Assignment to dense vectors*****************************************************************
353  template< typename VT1 > // Type of the target dense vector
354  friend inline void assign( DenseVector<VT1,false>& lhs, const TDMatSVecMultExpr& rhs )
355  {
357 
358  BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
359 
360  // Evaluation of the right-hand side sparse vector operand
361  RT x( rhs.vec_ );
362  if( x.nonZeros() == 0UL ) {
363  reset( ~lhs );
364  return;
365  }
366 
367  // Evaluation of the left-hand side dense matrix operand
368  LT A( rhs.mat_ );
369 
370  // Checking the evaluated operands
371  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.mat_.rows() , "Invalid number of rows" );
372  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.mat_.columns(), "Invalid number of columns" );
373  BLAZE_INTERNAL_ASSERT( x.size() == rhs.vec_.size() , "Invalid vector size" );
374  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).size() , "Invalid vector size" );
375 
376  // Performing the dense matrix-sparse vector multiplication
377  TDMatSVecMultExpr::selectAssignKernel( ~lhs, A, x );
378  }
380  //**********************************************************************************************
381 
382  //**Default assignment to dense vectors*********************************************************
396  template< typename VT1 // Type of the left-hand side target vector
397  , typename MT1 // Type of the left-hand side matrix operand
398  , typename VT2 > // Type of the right-hand side vector operand
399  static inline typename EnableIf< UseDefaultKernel<VT1,MT1,VT2> >::Type
400  selectAssignKernel( VT1& y, const MT1& A, const VT2& x )
401  {
403 
404  BLAZE_INTERNAL_ASSERT( x.nonZeros() != 0UL, "Invalid number of non-zero elements" );
405 
406  const size_t M( A.rows() );
407 
408  ConstIterator element( x.begin() );
409  const ConstIterator end( x.end() );
410 
411  for( size_t i=0UL; i<M; ++i ) {
412  y[i] = A(i,element->index()) * element->value();
413  }
414 
415  ++element;
416 
417  for( ; element!=end; ++element ) {
418  for( size_t i=0UL; i<M; ++i ) {
419  y[i] += A(i,element->index()) * element->value();
420  }
421  }
422  }
424  //**********************************************************************************************
425 
426  //**Optimized assignment to dense vectors*******************************************************
440  template< typename VT1 // Type of the left-hand side target vector
441  , typename MT1 // Type of the left-hand side matrix operand
442  , typename VT2 > // Type of the right-hand side vector operand
443  static inline typename EnableIf< UseOptimizedKernel<VT1,MT1,VT2> >::Type
444  selectAssignKernel( VT1& y, const MT1& A, const VT2& x )
445  {
447 
448  BLAZE_INTERNAL_ASSERT( x.nonZeros() != 0UL, "Invalid number of non-zero elements" );
449 
450  const size_t M( A.rows() );
451 
452  ConstIterator element( x.begin() );
453  const ConstIterator end( x.end() );
454 
455  const size_t jend( x.nonZeros() & size_t(-4) );
456  BLAZE_INTERNAL_ASSERT( ( x.nonZeros() - ( x.nonZeros() % 4UL ) ) == jend, "Invalid end calculation" );
457 
458  if( jend > 3UL )
459  {
460  const size_t j1( element->index() );
461  const VET v1( element->value() );
462  ++element;
463  const size_t j2( element->index() );
464  const VET v2( element->value() );
465  ++element;
466  const size_t j3( element->index() );
467  const VET v3( element->value() );
468  ++element;
469  const size_t j4( element->index() );
470  const VET v4( element->value() );
471  ++element;
472 
473  for( size_t i=0UL; i<M; ++i ) {
474  y[i] = A(i,j1) * v1 + A(i,j2) * v2 + A(i,j3) * v3 + A(i,j4) * v4;
475  }
476  }
477  else
478  {
479  const size_t j1( element->index() );
480  const VET v1( element->value() );
481  ++element;
482 
483  for( size_t i=0UL; i<M; ++i ) {
484  y[i] = A(i,j1) * v1;
485  }
486  }
487 
488  for( size_t j=(jend>3UL)?(4UL):(1UL); (j+4UL)<=jend; j+=4UL )
489  {
490  const size_t j1( element->index() );
491  const VET v1( element->value() );
492  ++element;
493  const size_t j2( element->index() );
494  const VET v2( element->value() );
495  ++element;
496  const size_t j3( element->index() );
497  const VET v3( element->value() );
498  ++element;
499  const size_t j4( element->index() );
500  const VET v4( element->value() );
501  ++element;
502 
503  for( size_t i=0UL; i<M; ++i ) {
504  y[i] += A(i,j1) * v1 + A(i,j2) * v2 + A(i,j3) * v3 + A(i,j4) * v4;
505  }
506  }
507  for( ; element!=end; ++element )
508  {
509  const size_t j1( element->index() );
510  const VET v1( element->value() );
511 
512  for( size_t i=0UL; i<M; ++i ) {
513  y[i] += A(i,j1) * v1;
514  }
515  }
516  }
518  //**********************************************************************************************
519 
520  //**Vectorized assignment to dense vectors******************************************************
534  template< typename VT1 // Type of the left-hand side target vector
535  , typename MT1 // Type of the left-hand side matrix operand
536  , typename VT2 > // Type of the right-hand side vector operand
537  static inline typename EnableIf< UseVectorizedKernel<VT1,MT1,VT2> >::Type
538  selectAssignKernel( VT1& y, const MT1& A, const VT2& x )
539  {
540  typedef IntrinsicTrait<ElementType> IT;
542 
543  BLAZE_INTERNAL_ASSERT( x.nonZeros() != 0UL, "Invalid number of non-zero elements" );
544 
545  const size_t M( A.rows() );
546 
547  ConstIterator element( x.begin() );
548  const ConstIterator end( x.end() );
549 
550  const size_t jend( x.nonZeros() & size_t(-4) );
551  BLAZE_INTERNAL_ASSERT( ( x.nonZeros() - ( x.nonZeros() % 4UL ) ) == jend, "Invalid end calculation" );
552 
553  if( jend > 3UL )
554  {
555  const size_t j1( element->index() );
556  const IntrinsicType v1( set( element->value() ) );
557  ++element;
558  const size_t j2( element->index() );
559  const IntrinsicType v2( set( element->value() ) );
560  ++element;
561  const size_t j3( element->index() );
562  const IntrinsicType v3( set( element->value() ) );
563  ++element;
564  const size_t j4( element->index() );
565  const IntrinsicType v4( set( element->value() ) );
566  ++element;
567 
568  for( size_t i=0UL; i<M; i+=IT::size ) {
569  y.store( i, A.load(i,j1) * v1 + A.load(i,j2) * v2 + A.load(i,j3) * v3 + A.load(i,j4) * v4 );
570  }
571  }
572  else
573  {
574  const size_t j1( element->index() );
575  const IntrinsicType v1( set( element->value() ) );
576  ++element;
577 
578  for( size_t i=0UL; i<M; i+=IT::size ) {
579  y.store( i, A.load(i,j1) * v1 );
580  }
581  }
582 
583  for( size_t j=(jend>3UL)?(4UL):(1UL); (j+4UL)<=jend; j+=4UL )
584  {
585  const size_t j1( element->index() );
586  const IntrinsicType v1( set( element->value() ) );
587  ++element;
588  const size_t j2( element->index() );
589  const IntrinsicType v2( set( element->value() ) );
590  ++element;
591  const size_t j3( element->index() );
592  const IntrinsicType v3( set( element->value() ) );
593  ++element;
594  const size_t j4( element->index() );
595  const IntrinsicType v4( set( element->value() ) );
596  ++element;
597 
598  for( size_t i=0UL; i<M; i+=IT::size ) {
599  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 );
600  }
601  }
602  for( ; element!=end; ++element )
603  {
604  const size_t j1( element->index() );
605  const IntrinsicType v1( set( element->value() ) );
606 
607  for( size_t i=0UL; i<M; i+=IT::size ) {
608  y.store( i, y.load(i) + A.load(i,j1) * v1 );
609  }
610  }
611  }
613  //**********************************************************************************************
614 
615  //**SMP assignment to dense vectors*************************************************************
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< UseSMPAssignKernel<VT1,MT1,VT2> >::Type
633  selectAssignKernel( VT1& y, const MT1& A, const VT2& x )
634  {
635  smpAssign( y, A * x );
636  }
638  //**********************************************************************************************
639 
640  //**Assignment to sparse vectors****************************************************************
653  template< typename VT1 > // Type of the target sparse vector
654  friend inline void assign( SparseVector<VT1,false>& lhs, const TDMatSVecMultExpr& rhs )
655  {
657 
661 
662  BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
663 
664  const ResultType tmp( rhs );
665  smpAssign( ~lhs, tmp );
666  }
668  //**********************************************************************************************
669 
670  //**Addition assignment to dense vectors********************************************************
683  template< typename VT1 > // Type of the target dense vector
684  friend inline void addAssign( DenseVector<VT1,false>& lhs, const TDMatSVecMultExpr& rhs )
685  {
687 
688  BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
689 
691 
692  // Evaluation of the right-hand side sparse vector operand
693  RT x( rhs.vec_ );
694  if( x.nonZeros() == 0UL ) return;
695 
696  // Evaluation of the left-hand side dense matrix operand
697  LT A( rhs.mat_ );
698 
699  // Checking the evaluated operands
700  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.mat_.rows() , "Invalid number of rows" );
701  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.mat_.columns(), "Invalid number of columns" );
702  BLAZE_INTERNAL_ASSERT( x.size() == rhs.vec_.size() , "Invalid vector size" );
703  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).size() , "Invalid vector size" );
704 
705  // Performing the dense matrix-sparse vector multiplication
706  TDMatSVecMultExpr::selectAddAssignKernel( ~lhs, A, x );
707  }
709  //**********************************************************************************************
710 
711  //**Default addition assignment to dense vectors************************************************
725  template< typename VT1 // Type of the left-hand side target vector
726  , typename MT1 // Type of the left-hand side matrix operand
727  , typename VT2 > // Type of the right-hand side vector operand
728  static inline typename EnableIf< UseDefaultKernel<VT1,MT1,VT2> >::Type
729  selectAddAssignKernel( VT1& y, const MT1& A, const VT2& x )
730  {
732 
733  BLAZE_INTERNAL_ASSERT( x.nonZeros() != 0UL, "Invalid number of non-zero elements" );
734 
735  const size_t M( A.rows() );
736 
737  ConstIterator element( x.begin() );
738  const ConstIterator end( x.end() );
739 
740  for( ; element!=end; ++element ) {
741  for( size_t i=0UL; i<M; ++i ) {
742  y[i] += A(i,element->index()) * element->value();
743  }
744  }
745  }
747  //**********************************************************************************************
748 
749  //**Optimized addition assignment to dense vectors**********************************************
763  template< typename VT1 // Type of the left-hand side target vector
764  , typename MT1 // Type of the left-hand side matrix operand
765  , typename VT2 > // Type of the right-hand side vector operand
766  static inline typename EnableIf< UseOptimizedKernel<VT1,MT1,VT2> >::Type
767  selectAddAssignKernel( VT1& y, const MT1& A, const VT2& x )
768  {
770 
771  BLAZE_INTERNAL_ASSERT( x.nonZeros() != 0UL, "Invalid number of non-zero elements" );
772 
773  const size_t M( A.rows() );
774 
775  ConstIterator element( x.begin() );
776  const ConstIterator end( x.end() );
777 
778  const size_t jend( x.nonZeros() & size_t(-4) );
779  BLAZE_INTERNAL_ASSERT( ( x.nonZeros() - ( x.nonZeros() % 4UL ) ) == jend, "Invalid end calculation" );
780 
781  for( size_t j=0UL; (j+4UL)<=jend; j+=4UL )
782  {
783  const size_t j1( element->index() );
784  const VET v1( element->value() );
785  ++element;
786  const size_t j2( element->index() );
787  const VET v2( element->value() );
788  ++element;
789  const size_t j3( element->index() );
790  const VET v3( element->value() );
791  ++element;
792  const size_t j4( element->index() );
793  const VET v4( element->value() );
794  ++element;
795 
796  for( size_t i=0UL; i<M; ++i ) {
797  y[i] += A(i,j1) * v1 + A(i,j2) * v2 + A(i,j3) * v3 + A(i,j4) * v4;
798  }
799  }
800  for( ; element!=end; ++element )
801  {
802  const size_t j1( element->index() );
803  const VET v1( element->value() );
804 
805  for( size_t i=0UL; i<M; ++i ) {
806  y[i] += A(i,j1) * v1;
807  }
808  }
809  }
811  //**********************************************************************************************
812 
813  //**Vectorized addition assignment to dense vectors*********************************************
827  template< typename VT1 // Type of the left-hand side target vector
828  , typename MT1 // Type of the left-hand side matrix operand
829  , typename VT2 > // Type of the right-hand side vector operand
830  static inline typename EnableIf< UseVectorizedKernel<VT1,MT1,VT2> >::Type
831  selectAddAssignKernel( VT1& y, const MT1& A, const VT2& x )
832  {
833  typedef IntrinsicTrait<ElementType> IT;
835 
836  BLAZE_INTERNAL_ASSERT( x.nonZeros() != 0UL, "Invalid number of non-zero elements" );
837 
838  const size_t M( A.rows() );
839 
840  ConstIterator element( x.begin() );
841  const ConstIterator end( x.end() );
842 
843  const size_t jend( x.nonZeros() & size_t(-4) );
844  BLAZE_INTERNAL_ASSERT( ( x.nonZeros() - ( x.nonZeros() % 4UL ) ) == jend, "Invalid end calculation" );
845 
846  for( size_t j=0UL; (j+4UL)<=jend; j+=4UL )
847  {
848  const size_t j1( element->index() );
849  const IntrinsicType v1( set( element->value() ) );
850  ++element;
851  const size_t j2( element->index() );
852  const IntrinsicType v2( set( element->value() ) );
853  ++element;
854  const size_t j3( element->index() );
855  const IntrinsicType v3( set( element->value() ) );
856  ++element;
857  const size_t j4( element->index() );
858  const IntrinsicType v4( set( element->value() ) );
859  ++element;
860 
861  for( size_t i=0UL; i<M; i+=IT::size ) {
862  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 );
863  }
864  }
865  for( ; element!=end; ++element )
866  {
867  const size_t j1( element->index() );
868  const IntrinsicType v1( set( element->value() ) );
869 
870  for( size_t i=0UL; i<M; i+=IT::size ) {
871  y.store( i, y.load(i) + A.load(i,j1) * v1 );
872  }
873  }
874  }
876  //**********************************************************************************************
877 
878  //**SMP addition assignment to dense vectors****************************************************
892  template< typename VT1 // Type of the left-hand side target vector
893  , typename MT1 // Type of the left-hand side matrix operand
894  , typename VT2 > // Type of the right-hand side vector operand
895  static inline typename EnableIf< UseSMPAssignKernel<VT1,MT1,VT2> >::Type
896  selectAddAssignKernel( VT1& y, const MT1& A, const VT2& x )
897  {
898  smpAddAssign( y, A * x );
899  }
901  //**********************************************************************************************
902 
903  //**Addition assignment to sparse vectors*******************************************************
904  // No special implementation for the addition assignment to sparse vectors.
905  //**********************************************************************************************
906 
907  //**Subtraction assignment to dense vectors*****************************************************
920  template< typename VT1 > // Type of the target dense vector
921  friend inline void subAssign( DenseVector<VT1,false>& lhs, const TDMatSVecMultExpr& rhs )
922  {
924 
925  BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
926 
928 
929  // Evaluation of the right-hand side sparse vector operand
930  RT x( rhs.vec_ );
931  if( x.nonZeros() == 0UL ) return;
932 
933  // Evaluation of the left-hand side dense matrix operand
934  LT A( rhs.mat_ );
935 
936  // Checking the evaluated operands
937  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.mat_.rows() , "Invalid number of rows" );
938  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.mat_.columns(), "Invalid number of columns" );
939  BLAZE_INTERNAL_ASSERT( x.size() == rhs.vec_.size() , "Invalid vector size" );
940  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).size() , "Invalid vector size" );
941 
942  // Performing the dense matrix-sparse vector multiplication
943  TDMatSVecMultExpr::selectSubAssignKernel( ~lhs, A, x );
944  }
946  //**********************************************************************************************
947 
948  //**Default subtraction assignment to dense vectors*********************************************
962  template< typename VT1 // Type of the left-hand side target vector
963  , typename MT1 // Type of the left-hand side matrix operand
964  , typename VT2 > // Type of the right-hand side vector operand
965  static inline typename EnableIf< UseDefaultKernel<VT1,MT1,VT2> >::Type
966  selectSubAssignKernel( VT1& y, const MT1& A, const VT2& x )
967  {
969 
970  BLAZE_INTERNAL_ASSERT( x.nonZeros() != 0UL, "Invalid number of non-zero elements" );
971 
972  const size_t M( A.rows() );
973 
974  ConstIterator element( x.begin() );
975  const ConstIterator end( x.end() );
976 
977  for( ; element!=end; ++element ) {
978  for( size_t i=0UL; i<M; ++i ) {
979  y[i] -= A(i,element->index()) * element->value();
980  }
981  }
982  }
984  //**********************************************************************************************
985 
986  //**Optimized subtraction assignment to dense vectors*******************************************
1000  template< typename VT1 // Type of the left-hand side target vector
1001  , typename MT1 // Type of the left-hand side matrix operand
1002  , typename VT2 > // Type of the right-hand side vector operand
1003  static inline typename EnableIf< UseOptimizedKernel<VT1,MT1,VT2> >::Type
1004  selectSubAssignKernel( VT1& y, const MT1& A, const VT2& x )
1005  {
1007 
1008  BLAZE_INTERNAL_ASSERT( x.nonZeros() != 0UL, "Invalid number of non-zero elements" );
1009 
1010  const size_t M( A.rows() );
1011 
1012  ConstIterator element( x.begin() );
1013  const ConstIterator end( x.end() );
1014 
1015  const size_t jend( x.nonZeros() & size_t(-4) );
1016  BLAZE_INTERNAL_ASSERT( ( x.nonZeros() - ( x.nonZeros() % 4UL ) ) == jend, "Invalid end calculation" );
1017 
1018  for( size_t j=0UL; (j+4UL)<=jend; j+=4UL )
1019  {
1020  const size_t j1( element->index() );
1021  const VET v1( element->value() );
1022  ++element;
1023  const size_t j2( element->index() );
1024  const VET v2( element->value() );
1025  ++element;
1026  const size_t j3( element->index() );
1027  const VET v3( element->value() );
1028  ++element;
1029  const size_t j4( element->index() );
1030  const VET v4( element->value() );
1031  ++element;
1032 
1033  for( size_t i=0UL; i<M; ++i ) {
1034  y[i] -= A(i,j1) * v1 + A(i,j2) * v2 + A(i,j3) * v3 + A(i,j4) * v4;
1035  }
1036  }
1037  for( ; element!=end; ++element )
1038  {
1039  const size_t j1( element->index() );
1040  const VET v1( element->value() );
1041 
1042  for( size_t i=0UL; i<M; ++i ) {
1043  y[i] -= A(i,j1) * v1;
1044  }
1045  }
1046  }
1048  //**********************************************************************************************
1049 
1050  //**Vectorized subtraction assignment to dense vectors******************************************
1064  template< typename VT1 // Type of the left-hand side target vector
1065  , typename MT1 // Type of the left-hand side matrix operand
1066  , typename VT2 > // Type of the right-hand side vector operand
1067  static inline typename EnableIf< UseVectorizedKernel<VT1,MT1,VT2> >::Type
1068  selectSubAssignKernel( VT1& y, const MT1& A, const VT2& x )
1069  {
1070  typedef IntrinsicTrait<ElementType> IT;
1072 
1073  BLAZE_INTERNAL_ASSERT( x.nonZeros() != 0UL, "Invalid number of non-zero elements" );
1074 
1075  const size_t M( A.rows() );
1076 
1077  ConstIterator element( x.begin() );
1078  const ConstIterator end( x.end() );
1079 
1080  const size_t jend( x.nonZeros() & size_t(-4) );
1081  BLAZE_INTERNAL_ASSERT( ( x.nonZeros() - ( x.nonZeros() % 4UL ) ) == jend, "Invalid end calculation" );
1082 
1083  for( size_t j=0UL; (j+4UL)<=jend; j+=4UL )
1084  {
1085  const size_t j1( element->index() );
1086  const IntrinsicType v1( set( element->value() ) );
1087  ++element;
1088  const size_t j2( element->index() );
1089  const IntrinsicType v2( set( element->value() ) );
1090  ++element;
1091  const size_t j3( element->index() );
1092  const IntrinsicType v3( set( element->value() ) );
1093  ++element;
1094  const size_t j4( element->index() );
1095  const IntrinsicType v4( set( element->value() ) );
1096  ++element;
1097 
1098  for( size_t i=0UL; i<M; i+=IT::size ) {
1099  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 );
1100  }
1101  }
1102  for( ; element!=end; ++element )
1103  {
1104  const size_t j1( element->index() );
1105  const IntrinsicType v1( set( element->value() ) );
1106 
1107  for( size_t i=0UL; i<M; i+=IT::size ) {
1108  y.store( i, y.load(i) - A.load(i,j1) * v1 );
1109  }
1110  }
1111  }
1113  //**********************************************************************************************
1114 
1115  //**SMP subtraction assignment to dense vectors*************************************************
1129  template< typename VT1 // Type of the left-hand side target vector
1130  , typename MT1 // Type of the left-hand side matrix operand
1131  , typename VT2 > // Type of the right-hand side vector operand
1132  static inline typename EnableIf< UseSMPAssignKernel<VT1,MT1,VT2> >::Type
1133  selectSubAssignKernel( VT1& y, const MT1& A, const VT2& x )
1134  {
1135  smpSubAssign( y, A * x );
1136  }
1138  //**********************************************************************************************
1139 
1140  //**Subtraction assignment to sparse vectors****************************************************
1141  // No special implementation for the subtraction assignment to sparse vectors.
1142  //**********************************************************************************************
1143 
1144  //**Multiplication assignment to dense vectors**************************************************
1157  template< typename VT1 > // Type of the target dense vector
1158  friend inline void multAssign( DenseVector<VT1,false>& lhs, const TDMatSVecMultExpr& rhs )
1159  {
1161 
1165 
1166  BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
1167 
1168  const ResultType tmp( rhs );
1169  smpMultAssign( ~lhs, tmp );
1170  }
1172  //**********************************************************************************************
1173 
1174  //**Multiplication assignment to sparse vectors*************************************************
1175  // No special implementation for the multiplication assignment to sparse vectors.
1176  //**********************************************************************************************
1177 
1178  //**Compile time checks*************************************************************************
1185  //**********************************************************************************************
1186 };
1187 //*************************************************************************************************
1188 
1189 
1190 
1191 
1192 //=================================================================================================
1193 //
1194 // GLOBAL BINARY ARITHMETIC OPERATORS
1195 //
1196 //=================================================================================================
1197 
1198 //*************************************************************************************************
1230 template< typename T1 // Type of the left-hand side dense matrix
1231  , typename T2 > // Type of the right-hand side sparse vector
1232 inline const typename DisableIf< IsMatMatMultExpr<T1>, TDMatSVecMultExpr<T1,T2> >::Type
1234 {
1236 
1237  if( (~mat).columns() != (~vec).size() )
1238  throw std::invalid_argument( "Matrix and vector sizes do not match" );
1239 
1240  return TDMatSVecMultExpr<T1,T2>( ~mat, ~vec );
1241 }
1242 //*************************************************************************************************
1243 
1244 
1245 
1246 
1247 //=================================================================================================
1248 //
1249 // EXPRESSION TRAIT SPECIALIZATIONS
1250 //
1251 //=================================================================================================
1252 
1253 //*************************************************************************************************
1255 template< typename MT, typename VT, bool AF >
1256 struct SubvectorExprTrait< TDMatSVecMultExpr<MT,VT>, AF >
1257 {
1258  public:
1259  //**********************************************************************************************
1260  typedef typename MultExprTrait< typename SubmatrixExprTrait<const MT,AF>::Type, VT >::Type Type;
1261  //**********************************************************************************************
1262 };
1264 //*************************************************************************************************
1265 
1266 } // namespace blaze
1267 
1268 #endif
ResultType::ElementType ElementType
Resulting element type.
Definition: TDMatSVecMultExpr.h:184
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:265
void reset(DynamicMatrix< Type, SO > &m)
Resetting the given dense matrix.
Definition: DynamicMatrix.h:4579
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:4075
VT::ResultType VRT
Result type of the right-hand side sparse vector expression.
Definition: TDMatSVecMultExpr.h:101
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:151
#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:197
#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:178
RightOperand vec_
Right-hand side sparse vector of the multiplication expression.
Definition: TDMatSVecMultExpr.h:337
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:103
bool isAligned() const
Returns whether the operands of the expression are properly aligned in memory.
Definition: TDMatSVecMultExpr.h:319
const This & CompositeType
Data type for composite expression templates.
Definition: CompressedMatrix.h:2384
Type ElementType
Type of the sparse matrix elements.
Definition: CompressedMatrix.h:249
const size_t SMP_TDMATSVECMULT_THRESHOLD
SMP column-major dense matrix/sparse vector multiplication threshold.This threshold represents the sy...
Definition: Thresholds.h:204
Header file for the DenseVector base class.
MRT::ElementType MET
Element type of the left-hand side dense matrix expression.
Definition: TDMatSVecMultExpr.h:102
TDMatSVecMultExpr< MT, VT > This
Type of this TDMatSVecMultExpr instance.
Definition: TDMatSVecMultExpr.h:181
MultTrait< MRT, VRT >::Type ResultType
Result type for expression template evaluations.
Definition: TDMatSVecMultExpr.h:182
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:193
Constraint on the data type.
ReturnType operator[](size_t index) const
Subscript operator for the direct access to the vector elements.
Definition: TDMatSVecMultExpr.h:233
bool isAliased(const T *alias) const
Returns whether the expression is aliased with the given address alias.
Definition: TDMatSVecMultExpr.h:309
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:121
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:251
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:186
Header file for the dense vector SMP implementation.
bool canSMPAssign() const
Returns whether the expression can be used in SMP assignments.
Definition: TDMatSVecMultExpr.h:329
#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:2388
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:179
LeftOperand mat_
Left-hand side dense matrix of the multiplication expression.
Definition: TDMatSVecMultExpr.h:336
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:185
#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:187
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:219
Type ElementType
Type of the sparse matrix elements.
Definition: CompressedMatrix.h:2382
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:269
Header file for the SelectType class template.
Header file for all forward declarations for expression class templates.
Constraint on the data type.
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:91
SelectType< evaluateVector, const VRT, typename VT::CompositeType >::Type RT
Type for the assignment of the right-hand side dense matrix operand.
Definition: TDMatSVecMultExpr.h:199
Expression object for transpose dense matrix-sparse vector multiplications.The TDMatSVecMultExpr clas...
Definition: Forward.h:126
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:275
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:209
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:105
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:239
MT::ResultType MRT
Result type of the left-hand side dense matrix expression.
Definition: TDMatSVecMultExpr.h:100
SelectType< evaluateMatrix, const MRT, MCT >::Type LT
Type for the assignment of the left-hand side dense matrix operand.
Definition: TDMatSVecMultExpr.h:196
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:297
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:285
Header file for the IsComputation type trait class.
ResultType::TransposeType TransposeType
Transpose type for expression template evaluations.
Definition: TDMatSVecMultExpr.h:183
Header file for the sparse vector SMP implementation.
Base class for sparse vectors.The SparseVector class is a base class for all arbitrarily sized (N-dim...
Definition: Forward.h:105
#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:2379
size_t columns(const Matrix< MT, SO > &m)
Returns the current number of columns of the matrix.
Definition: Matrix.h:154
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:190
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:104
Header file for the IsExpression type trait class.
Header file for the FunctionTrace class.