All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
TDMatSVecMultExpr.h
Go to the documentation of this file.
1 //=================================================================================================
20 //=================================================================================================
21 
22 #ifndef _BLAZE_MATH_EXPRESSIONS_TDMATSVECMULTEXPR_H_
23 #define _BLAZE_MATH_EXPRESSIONS_TDMATSVECMULTEXPR_H_
24 
25 
26 //*************************************************************************************************
27 // Includes
28 //*************************************************************************************************
29 
30 #include <stdexcept>
40 #include <blaze/math/Intrinsics.h>
41 #include <blaze/math/shims/Reset.h>
48 #include <blaze/util/Assert.h>
50 #include <blaze/util/DisableIf.h>
52 #include <blaze/util/SelectType.h>
53 #include <blaze/util/Types.h>
56 
57 
58 namespace blaze {
59 
60 //=================================================================================================
61 //
62 // CLASS TDMATSVECMULTEXPR
63 //
64 //=================================================================================================
65 
66 //*************************************************************************************************
73 template< typename MT // Type of the left-hand side dense matrix
74  , typename VT > // Type of the right-hand side sparse vector
75 class TDMatSVecMultExpr : public DenseVector< TDMatSVecMultExpr<MT,VT>, false >
76  , private MatVecMultExpr
77  , private Computation
78 {
79  private:
80  //**Type definitions****************************************************************************
81  typedef typename MT::ResultType MRT;
82  typedef typename VT::ResultType VRT;
83  typedef typename MRT::ElementType MET;
84  typedef typename VRT::ElementType VET;
85  typedef typename MT::CompositeType MCT;
86  typedef typename VT::CompositeType VCT;
87  //**********************************************************************************************
88 
89  //**********************************************************************************************
91  enum { evaluate = IsComputation<MT>::value && !MT::vectorizable &&
93  //**********************************************************************************************
94 
95  //**********************************************************************************************
97 
98 
101  template< typename T1, typename T2, typename T3 >
102  struct UseVectorizedKernel {
103  enum { value = T1::vectorizable && T2::vectorizable &&
108  };
110  //**********************************************************************************************
111 
112  //**********************************************************************************************
114 
115 
118  template< typename T1, typename T2, typename T3 >
119  struct UseOptimizedKernel {
120  enum { value = !UseVectorizedKernel<T1,T2,T3>::value &&
121  !IsResizable<typename T1::ElementType>::value &&
122  !IsResizable<VET>::value };
123  };
125  //**********************************************************************************************
126 
127  //**********************************************************************************************
129 
130 
132  template< typename T1, typename T2, typename T3 >
133  struct UseDefaultKernel {
134  enum { value = !UseVectorizedKernel<T1,T2,T3>::value &&
135  !UseOptimizedKernel<T1,T2,T3>::value };
136  };
138  //**********************************************************************************************
139 
140  public:
141  //**Type definitions****************************************************************************
144  typedef typename ResultType::TransposeType TransposeType;
145  typedef typename ResultType::ElementType ElementType;
147  typedef const ElementType ReturnType;
148  typedef const ResultType CompositeType;
149 
151  typedef typename SelectType< IsExpression<MT>::value, const MT, const MT& >::Type LeftOperand;
152 
154  typedef typename SelectType< IsExpression<VT>::value, const VT, const VT& >::Type RightOperand;
155 
158 
160  typedef typename SelectType< IsComputation<VT>::value, const VRT, typename VT::CompositeType >::Type RT;
161  //**********************************************************************************************
162 
163  //**Compilation flags***************************************************************************
165  enum { vectorizable = 0 };
166  //**********************************************************************************************
167 
168  //**Constructor*********************************************************************************
174  explicit inline TDMatSVecMultExpr( const MT& mat, const VT& vec )
175  : mat_( mat ) // Left-hand side dense matrix of the multiplication expression
176  , vec_( vec ) // Right-hand side sparse vector of the multiplication expression
177  {
178  BLAZE_INTERNAL_ASSERT( mat_.columns() == vec_.size(), "Invalid matrix and vector sizes" );
179  }
180  //**********************************************************************************************
181 
182  //**Subscript operator**************************************************************************
188  inline ReturnType operator[]( size_t index ) const {
189  BLAZE_INTERNAL_ASSERT( index < mat_.rows(), "Invalid vector access index" );
190 
191  typedef typename RemoveReference<VCT>::Type::ConstIterator ConstIterator;
192 
193  VCT x( vec_ ); // Evaluation of the right-hand side sparse vector operand
194 
195  BLAZE_INTERNAL_ASSERT( x.size() == vec_.size(), "Invalid vector size" );
196 
197  ConstIterator element( x.begin() );
198  ElementType res;
199 
200  if( element != x.end() ) {
201  res = mat_( index, element->index() ) * element->value();
202  ++element;
203  for( ; element!=x.end(); ++element ) {
204  res += mat_( index, element->index() ) * element->value();
205  }
206  }
207  else {
208  reset( res );
209  }
210 
211  return res;
212  }
213  //**********************************************************************************************
214 
215  //**Size function*******************************************************************************
220  inline size_t size() const {
221  return mat_.rows();
222  }
223  //**********************************************************************************************
224 
225  //**Left function*******************************************************************************
230  inline LeftOperand leftOperand() const {
231  return mat_;
232  }
233  //**********************************************************************************************
234 
235  //**Right function******************************************************************************
240  inline RightOperand rightOperand() const {
241  return vec_;
242  }
243  //**********************************************************************************************
244 
245  //**********************************************************************************************
251  template< typename T >
252  inline bool canAlias( const T* alias ) const {
253  return mat_.isAliased( alias ) || vec_.isAliased( alias );
254  }
255  //**********************************************************************************************
256 
257  //**********************************************************************************************
263  template< typename T >
264  inline bool isAliased( const T* alias ) const {
265  return mat_.isAliased( alias ) || vec_.isAliased( alias );
266  }
267  //**********************************************************************************************
268 
269  private:
270  //**Member variables****************************************************************************
273  //**********************************************************************************************
274 
275  //**Assignment to dense vectors*****************************************************************
287  template< typename VT1 > // Type of the target dense vector
288  friend inline void assign( DenseVector<VT1,false>& lhs, const TDMatSVecMultExpr& rhs )
289  {
291 
292  BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
293 
294  // Evaluation of the right-hand side sparse vector operand
295  RT x( rhs.vec_ );
296  if( x.nonZeros() == 0UL ) {
297  reset( ~lhs );
298  return;
299  }
300 
301  // Evaluation of the left-hand side dense matrix operand
302  LT A( rhs.mat_ );
303 
304  // Checking the evaluated operands
305  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.mat_.rows() , "Invalid number of rows" );
306  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.mat_.columns(), "Invalid number of columns" );
307  BLAZE_INTERNAL_ASSERT( x.size() == rhs.vec_.size() , "Invalid vector size" );
308  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).size() , "Invalid vector size" );
309 
310  // Performing the dense matrix-sparse vector multiplication
311  TDMatSVecMultExpr::selectAssignKernel( ~lhs, A, x );
312  }
314  //**********************************************************************************************
315 
316  //**Default assignment to dense vectors*********************************************************
330  template< typename VT1 // Type of the left-hand side target vector
331  , typename MT1 // Type of the left-hand side matrix operand
332  , typename VT2 > // Type of the right-hand side vector operand
333  static inline typename EnableIf< UseDefaultKernel<VT1,MT1,VT2> >::Type
334  selectAssignKernel( VT1& y, const MT1& A, const VT2& x )
335  {
336  typedef typename RemoveReference<RT>::Type::ConstIterator ConstIterator;
337 
338  BLAZE_INTERNAL_ASSERT( x.nonZeros() != 0UL, "Invalid number of non-zero elements" );
339 
340  const size_t M( A.rows() );
341 
342  ConstIterator element( x.begin() );
343  const ConstIterator end( x.end() );
344 
345  for( size_t i=0UL; i<M; ++i ) {
346  y[i] = A(i,element->index()) * element->value();
347  }
348 
349  ++element;
350 
351  for( ; element!=end; ++element ) {
352  for( size_t i=0UL; i<M; ++i ) {
353  y[i] += A(i,element->index()) * element->value();
354  }
355  }
356  }
358  //**********************************************************************************************
359 
360  //**Optimized assignment to dense vectors*******************************************************
374  template< typename VT1 // Type of the left-hand side target vector
375  , typename MT1 // Type of the left-hand side matrix operand
376  , typename VT2 > // Type of the right-hand side vector operand
377  static inline typename EnableIf< UseOptimizedKernel<VT1,MT1,VT2> >::Type
378  selectAssignKernel( VT1& y, const MT1& A, const VT2& x )
379  {
380  typedef typename RemoveReference<RT>::Type::ConstIterator ConstIterator;
381 
382  BLAZE_INTERNAL_ASSERT( x.nonZeros() != 0UL, "Invalid number of non-zero elements" );
383 
384  const size_t M( A.rows() );
385 
386  ConstIterator element( x.begin() );
387  const ConstIterator end( x.end() );
388 
389  const size_t jend( x.nonZeros() & size_t(-4) );
390  BLAZE_INTERNAL_ASSERT( ( x.nonZeros() - ( x.nonZeros() % 4UL ) ) == jend, "Invalid end calculation" );
391 
392  if( jend > 3UL )
393  {
394  const size_t j1( element->index() );
395  const VET v1( element->value() );
396  ++element;
397  const size_t j2( element->index() );
398  const VET v2( element->value() );
399  ++element;
400  const size_t j3( element->index() );
401  const VET v3( element->value() );
402  ++element;
403  const size_t j4( element->index() );
404  const VET v4( element->value() );
405  ++element;
406 
407  for( size_t i=0UL; i<M; ++i ) {
408  y[i] = A(i,j1) * v1 + A(i,j2) * v2 + A(i,j3) * v3 + A(i,j4) * v4;
409  }
410  }
411  else
412  {
413  const size_t j1( element->index() );
414  const VET v1( element->value() );
415  ++element;
416 
417  for( size_t i=0UL; i<M; ++i ) {
418  y[i] = A(i,j1) * v1;
419  }
420  }
421 
422  for( size_t j=(jend>3UL)?(4UL):(1UL); (j+4UL)<=jend; j+=4UL )
423  {
424  const size_t j1( element->index() );
425  const VET v1( element->value() );
426  ++element;
427  const size_t j2( element->index() );
428  const VET v2( element->value() );
429  ++element;
430  const size_t j3( element->index() );
431  const VET v3( element->value() );
432  ++element;
433  const size_t j4( element->index() );
434  const VET v4( element->value() );
435  ++element;
436 
437  for( size_t i=0UL; i<M; ++i ) {
438  y[i] += A(i,j1) * v1 + A(i,j2) * v2 + A(i,j3) * v3 + A(i,j4) * v4;
439  }
440  }
441  for( ; element!=end; ++element )
442  {
443  const size_t j1( element->index() );
444  const VET v1( element->value() );
445 
446  for( size_t i=0UL; i<M; ++i ) {
447  y[i] += A(i,j1) * v1;
448  }
449  }
450  }
452  //**********************************************************************************************
453 
454  //**Vectorized assignment to dense vectors******************************************************
468  template< typename VT1 // Type of the left-hand side target vector
469  , typename MT1 // Type of the left-hand side matrix operand
470  , typename VT2 > // Type of the right-hand side vector operand
471  static inline typename EnableIf< UseVectorizedKernel<VT1,MT1,VT2> >::Type
472  selectAssignKernel( VT1& y, const MT1& A, const VT2& x )
473  {
474  typedef IntrinsicTrait<ElementType> IT;
475  typedef typename RemoveReference<RT>::Type::ConstIterator ConstIterator;
476 
477  BLAZE_INTERNAL_ASSERT( x.nonZeros() != 0UL, "Invalid number of non-zero elements" );
478 
479  const size_t M( A.rows() );
480 
481  ConstIterator element( x.begin() );
482  const ConstIterator end( x.end() );
483 
484  const size_t jend( x.nonZeros() & size_t(-4) );
485  BLAZE_INTERNAL_ASSERT( ( x.nonZeros() - ( x.nonZeros() % 4UL ) ) == jend, "Invalid end calculation" );
486 
487  if( jend > 3UL )
488  {
489  const size_t j1( element->index() );
490  const IntrinsicType v1( set( element->value() ) );
491  ++element;
492  const size_t j2( element->index() );
493  const IntrinsicType v2( set( element->value() ) );
494  ++element;
495  const size_t j3( element->index() );
496  const IntrinsicType v3( set( element->value() ) );
497  ++element;
498  const size_t j4( element->index() );
499  const IntrinsicType v4( set( element->value() ) );
500  ++element;
501 
502  for( size_t i=0UL; i<M; i+=IT::size ) {
503  store( &y[i], A.get(i,j1) * v1 + A.get(i,j2) * v2 + A.get(i,j3) * v3 + A.get(i,j4) * v4 );
504  }
505  }
506  else
507  {
508  const size_t j1( element->index() );
509  const IntrinsicType v1( set( element->value() ) );
510  ++element;
511 
512  for( size_t i=0UL; i<M; i+=IT::size ) {
513  store( &y[i], A.get(i,j1) * v1 );
514  }
515  }
516 
517  for( size_t j=(jend>3UL)?(4UL):(1UL); (j+4UL)<=jend; j+=4UL )
518  {
519  const size_t j1( element->index() );
520  const IntrinsicType v1( set( element->value() ) );
521  ++element;
522  const size_t j2( element->index() );
523  const IntrinsicType v2( set( element->value() ) );
524  ++element;
525  const size_t j3( element->index() );
526  const IntrinsicType v3( set( element->value() ) );
527  ++element;
528  const size_t j4( element->index() );
529  const IntrinsicType v4( set( element->value() ) );
530  ++element;
531 
532  for( size_t i=0UL; i<M; i+=IT::size ) {
533  store( &y[i], load( &y[i] ) + A.get(i,j1) * v1 + A.get(i,j2) * v2 + A.get(i,j3) * v3 + A.get(i,j4) * v4 );
534  }
535  }
536  for( ; element!=end; ++element )
537  {
538  const size_t j1( element->index() );
539  const IntrinsicType v1( set( element->value() ) );
540 
541  for( size_t i=0UL; i<M; i+=IT::size ) {
542  store( &y[i], load( &y[i] ) + A.get(i,j1) * v1 );
543  }
544  }
545  }
547  //**********************************************************************************************
548 
549  //**Assignment to sparse vectors****************************************************************
561  template< typename VT1 > // Type of the target sparse vector
562  friend inline void assign( SparseVector<VT1,false>& lhs, const TDMatSVecMultExpr& rhs )
563  {
565 
568  BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( typename ResultType::CompositeType );
569 
570  BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
571 
572  const ResultType tmp( rhs );
573  assign( ~lhs, tmp );
574  }
576  //**********************************************************************************************
577 
578  //**Addition assignment to dense vectors********************************************************
591  template< typename VT1 > // Type of the target dense vector
592  friend inline void addAssign( DenseVector<VT1,false>& lhs, const TDMatSVecMultExpr& rhs )
593  {
595 
596  BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
597 
598  typedef typename RemoveReference<RT>::Type::ConstIterator ConstIterator;
599 
600  // Evaluation of the right-hand side sparse vector operand
601  RT x( rhs.vec_ );
602  if( x.nonZeros() == 0UL ) return;
603 
604  // Evaluation of the left-hand side dense matrix operand
605  LT A( rhs.mat_ );
606 
607  // Checking the evaluated operands
608  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.mat_.rows() , "Invalid number of rows" );
609  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.mat_.columns(), "Invalid number of columns" );
610  BLAZE_INTERNAL_ASSERT( x.size() == rhs.vec_.size() , "Invalid vector size" );
611  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).size() , "Invalid vector size" );
612 
613  // Performing the dense matrix-sparse vector multiplication
614  TDMatSVecMultExpr::selectAddAssignKernel( ~lhs, A, x );
615  }
617  //**********************************************************************************************
618 
619  //**Default addition assignment to dense vectors************************************************
633  template< typename VT1 // Type of the left-hand side target vector
634  , typename MT1 // Type of the left-hand side matrix operand
635  , typename VT2 > // Type of the right-hand side vector operand
636  static inline typename EnableIf< UseDefaultKernel<VT1,MT1,VT2> >::Type
637  selectAddAssignKernel( VT1& y, const MT1& A, const VT2& x )
638  {
639  typedef typename RemoveReference<RT>::Type::ConstIterator ConstIterator;
640 
641  BLAZE_INTERNAL_ASSERT( x.nonZeros() != 0UL, "Invalid number of non-zero elements" );
642 
643  const size_t M( A.rows() );
644 
645  ConstIterator element( x.begin() );
646  const ConstIterator end( x.end() );
647 
648  for( ; element!=end; ++element ) {
649  for( size_t i=0UL; i<M; ++i ) {
650  y[i] += A(i,element->index()) * element->value();
651  }
652  }
653  }
655  //**********************************************************************************************
656 
657  //**Optimized addition assignment to dense vectors**********************************************
671  template< typename VT1 // Type of the left-hand side target vector
672  , typename MT1 // Type of the left-hand side matrix operand
673  , typename VT2 > // Type of the right-hand side vector operand
674  static inline typename EnableIf< UseOptimizedKernel<VT1,MT1,VT2> >::Type
675  selectAddAssignKernel( VT1& y, const MT1& A, const VT2& x )
676  {
677  typedef typename RemoveReference<RT>::Type::ConstIterator ConstIterator;
678 
679  BLAZE_INTERNAL_ASSERT( x.nonZeros() != 0UL, "Invalid number of non-zero elements" );
680 
681  const size_t M( A.rows() );
682 
683  ConstIterator element( x.begin() );
684  const ConstIterator end( x.end() );
685 
686  const size_t jend( x.nonZeros() & size_t(-4) );
687  BLAZE_INTERNAL_ASSERT( ( x.nonZeros() - ( x.nonZeros() % 4UL ) ) == jend, "Invalid end calculation" );
688 
689  for( size_t j=0UL; (j+4UL)<=jend; j+=4UL )
690  {
691  const size_t j1( element->index() );
692  const VET v1( element->value() );
693  ++element;
694  const size_t j2( element->index() );
695  const VET v2( element->value() );
696  ++element;
697  const size_t j3( element->index() );
698  const VET v3( element->value() );
699  ++element;
700  const size_t j4( element->index() );
701  const VET v4( element->value() );
702  ++element;
703 
704  for( size_t i=0UL; i<M; ++i ) {
705  y[i] += A(i,j1) * v1 + A(i,j2) * v2 + A(i,j3) * v3 + A(i,j4) * v4;
706  }
707  }
708  for( ; element!=end; ++element )
709  {
710  const size_t j1( element->index() );
711  const VET v1( element->value() );
712 
713  for( size_t i=0UL; i<M; ++i ) {
714  y[i] += A(i,j1) * v1;
715  }
716  }
717  }
719  //**********************************************************************************************
720 
721  //**Vectorized addition assignment to dense vectors*********************************************
735  template< typename VT1 // Type of the left-hand side target vector
736  , typename MT1 // Type of the left-hand side matrix operand
737  , typename VT2 > // Type of the right-hand side vector operand
738  static inline typename EnableIf< UseVectorizedKernel<VT1,MT1,VT2> >::Type
739  selectAddAssignKernel( VT1& y, const MT1& A, const VT2& x )
740  {
741  typedef IntrinsicTrait<ElementType> IT;
742  typedef typename RemoveReference<RT>::Type::ConstIterator ConstIterator;
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 IntrinsicType v1( set( element->value() ) );
758  ++element;
759  const size_t j2( element->index() );
760  const IntrinsicType v2( set( element->value() ) );
761  ++element;
762  const size_t j3( element->index() );
763  const IntrinsicType v3( set( element->value() ) );
764  ++element;
765  const size_t j4( element->index() );
766  const IntrinsicType v4( set( element->value() ) );
767  ++element;
768 
769  for( size_t i=0UL; i<M; i+=IT::size ) {
770  store( &y[i], load( &y[i] ) + A.get(i,j1) * v1 + A.get(i,j2) * v2 + A.get(i,j3) * v3 + A.get(i,j4) * v4 );
771  }
772  }
773  for( ; element!=end; ++element )
774  {
775  const size_t j1( element->index() );
776  const IntrinsicType v1( set( element->value() ) );
777 
778  for( size_t i=0UL; i<M; i+=IT::size ) {
779  store( &y[i], load( &y[i] ) + A.get(i,j1) * v1 );
780  }
781  }
782  }
784  //**********************************************************************************************
785 
786  //**Addition assignment to sparse vectors*******************************************************
787  // No special implementation for the addition assignment to sparse vectors.
788  //**********************************************************************************************
789 
790  //**Subtraction assignment to dense vectors*****************************************************
803  template< typename VT1 > // Type of the target dense vector
804  friend inline void subAssign( DenseVector<VT1,false>& lhs, const TDMatSVecMultExpr& rhs )
805  {
807 
808  BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
809 
810  typedef typename RemoveReference<RT>::Type::ConstIterator ConstIterator;
811 
812  // Evaluation of the right-hand side sparse vector operand
813  RT x( rhs.vec_ );
814  if( x.nonZeros() == 0UL ) return;
815 
816  // Evaluation of the left-hand side dense matrix operand
817  LT A( rhs.mat_ );
818 
819  // Checking the evaluated operands
820  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.mat_.rows() , "Invalid number of rows" );
821  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.mat_.columns(), "Invalid number of columns" );
822  BLAZE_INTERNAL_ASSERT( x.size() == rhs.vec_.size() , "Invalid vector size" );
823  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).size() , "Invalid vector size" );
824 
825  // Performing the dense matrix-sparse vector multiplication
826  TDMatSVecMultExpr::selectSubAssignKernel( ~lhs, A, x );
827  }
829  //**********************************************************************************************
830 
831  //**Default subtraction assignment to dense vectors*********************************************
845  template< typename VT1 // Type of the left-hand side target vector
846  , typename MT1 // Type of the left-hand side matrix operand
847  , typename VT2 > // Type of the right-hand side vector operand
848  static inline typename EnableIf< UseDefaultKernel<VT1,MT1,VT2> >::Type
849  selectSubAssignKernel( VT1& y, const MT1& A, const VT2& x )
850  {
851  typedef typename RemoveReference<RT>::Type::ConstIterator ConstIterator;
852 
853  BLAZE_INTERNAL_ASSERT( x.nonZeros() != 0UL, "Invalid number of non-zero elements" );
854 
855  const size_t M( A.rows() );
856 
857  ConstIterator element( x.begin() );
858  const ConstIterator end( x.end() );
859 
860  for( ; element!=end; ++element ) {
861  for( size_t i=0UL; i<M; ++i ) {
862  y[i] -= A(i,element->index()) * element->value();
863  }
864  }
865  }
867  //**********************************************************************************************
868 
869  //**Optimized subtraction assignment to dense vectors*******************************************
883  template< typename VT1 // Type of the left-hand side target vector
884  , typename MT1 // Type of the left-hand side matrix operand
885  , typename VT2 > // Type of the right-hand side vector operand
886  static inline typename EnableIf< UseOptimizedKernel<VT1,MT1,VT2> >::Type
887  selectSubAssignKernel( VT1& y, const MT1& A, const VT2& x )
888  {
889  typedef typename RemoveReference<RT>::Type::ConstIterator ConstIterator;
890 
891  BLAZE_INTERNAL_ASSERT( x.nonZeros() != 0UL, "Invalid number of non-zero elements" );
892 
893  const size_t M( A.rows() );
894 
895  ConstIterator element( x.begin() );
896  const ConstIterator end( x.end() );
897 
898  const size_t jend( x.nonZeros() & size_t(-4) );
899  BLAZE_INTERNAL_ASSERT( ( x.nonZeros() - ( x.nonZeros() % 4UL ) ) == jend, "Invalid end calculation" );
900 
901  for( size_t j=0UL; (j+4UL)<=jend; j+=4UL )
902  {
903  const size_t j1( element->index() );
904  const VET v1( element->value() );
905  ++element;
906  const size_t j2( element->index() );
907  const VET v2( element->value() );
908  ++element;
909  const size_t j3( element->index() );
910  const VET v3( element->value() );
911  ++element;
912  const size_t j4( element->index() );
913  const VET v4( element->value() );
914  ++element;
915 
916  for( size_t i=0UL; i<M; ++i ) {
917  y[i] -= A(i,j1) * v1 + A(i,j2) * v2 + A(i,j3) * v3 + A(i,j4) * v4;
918  }
919  }
920  for( ; element!=end; ++element )
921  {
922  const size_t j1( element->index() );
923  const VET v1( element->value() );
924 
925  for( size_t i=0UL; i<M; ++i ) {
926  y[i] -= A(i,j1) * v1;
927  }
928  }
929  }
931  //**********************************************************************************************
932 
933  //**Vectorized subtraction assignment to dense vectors******************************************
947  template< typename VT1 // Type of the left-hand side target vector
948  , typename MT1 // Type of the left-hand side matrix operand
949  , typename VT2 > // Type of the right-hand side vector operand
950  static inline typename EnableIf< UseVectorizedKernel<VT1,MT1,VT2> >::Type
951  selectSubAssignKernel( VT1& y, const MT1& A, const VT2& x )
952  {
953  typedef IntrinsicTrait<ElementType> IT;
954  typedef typename RemoveReference<RT>::Type::ConstIterator ConstIterator;
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 IntrinsicType v1( set( element->value() ) );
970  ++element;
971  const size_t j2( element->index() );
972  const IntrinsicType v2( set( element->value() ) );
973  ++element;
974  const size_t j3( element->index() );
975  const IntrinsicType v3( set( element->value() ) );
976  ++element;
977  const size_t j4( element->index() );
978  const IntrinsicType v4( set( element->value() ) );
979  ++element;
980 
981  for( size_t i=0UL; i<M; i+=IT::size ) {
982  store( &y[i], load( &y[i] ) - A.get(i,j1) * v1 - A.get(i,j2) * v2 - A.get(i,j3) * v3 - A.get(i,j4) * v4 );
983  }
984  }
985  for( ; element!=end; ++element )
986  {
987  const size_t j1( element->index() );
988  const IntrinsicType v1( set( element->value() ) );
989 
990  for( size_t i=0UL; i<M; i+=IT::size ) {
991  store( &y[i], load( &y[i] ) - A.get(i,j1) * v1 );
992  }
993  }
994  }
996  //**********************************************************************************************
997 
998  //**Subtraction assignment to sparse vectors****************************************************
999  // No special implementation for the subtraction assignment to sparse vectors.
1000  //**********************************************************************************************
1001 
1002  //**Multiplication assignment to dense vectors**************************************************
1015  template< typename VT1 > // Type of the target dense vector
1016  friend inline void multAssign( DenseVector<VT1,false>& lhs, const TDMatSVecMultExpr& rhs )
1017  {
1019 
1022  BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( typename ResultType::CompositeType );
1023 
1024  BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
1025 
1026  const ResultType tmp( rhs );
1027  multAssign( ~lhs, tmp );
1028  }
1030  //**********************************************************************************************
1031 
1032  //**Multiplication assignment to sparse vectors*************************************************
1033  // No special implementation for the multiplication assignment to sparse vectors.
1034  //**********************************************************************************************
1035 
1036  //**Compile time checks*************************************************************************
1043  //**********************************************************************************************
1044 };
1045 //*************************************************************************************************
1046 
1047 
1048 
1049 
1050 //=================================================================================================
1051 //
1052 // GLOBAL BINARY ARITHMETIC OPERATORS
1053 //
1054 //=================================================================================================
1055 
1056 //*************************************************************************************************
1088 template< typename T1 // Type of the left-hand side dense matrix
1089  , typename T2 > // Type of the right-hand side sparse vector
1090 inline const typename DisableIf< IsMatMatMultExpr<T1>, TDMatSVecMultExpr<T1,T2> >::Type
1092 {
1094 
1095  if( (~mat).columns() != (~vec).size() )
1096  throw std::invalid_argument( "Matrix and vector sizes do not match" );
1097 
1098  return TDMatSVecMultExpr<T1,T2>( ~mat, ~vec );
1099 }
1100 //*************************************************************************************************
1101 
1102 } // namespace blaze
1103 
1104 #endif