All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
TSVecDMatMultExpr.h
Go to the documentation of this file.
1 //=================================================================================================
20 //=================================================================================================
21 
22 #ifndef _BLAZE_MATH_EXPRESSIONS_TSVECDMATMULTEXPR_H_
23 #define _BLAZE_MATH_EXPRESSIONS_TSVECDMATMULTEXPR_H_
24 
25 
26 //*************************************************************************************************
27 // Includes
28 //*************************************************************************************************
29 
30 #include <stdexcept>
40 #include <blaze/math/Intrinsics.h>
41 #include <blaze/math/shims/Reset.h>
49 #include <blaze/util/Assert.h>
51 #include <blaze/util/DisableIf.h>
52 #include <blaze/util/EnableIf.h>
54 #include <blaze/util/SelectType.h>
55 #include <blaze/util/Types.h>
58 
59 
60 namespace blaze {
61 
62 //=================================================================================================
63 //
64 // CLASS TSVECDMATMULTEXPR
65 //
66 //=================================================================================================
67 
68 //*************************************************************************************************
75 template< typename VT // Type of the left-hand side sparse vector
76  , typename MT > // Type of the right-hand side dense matrix
77 class TSVecDMatMultExpr : public DenseVector< TSVecDMatMultExpr<VT,MT>, true >
78  , private TVecMatMultExpr
79  , private Computation
80 {
81  private:
82  //**Type definitions****************************************************************************
83  typedef typename VT::ResultType VRT;
84  typedef typename MT::ResultType MRT;
85  typedef typename VRT::ElementType VET;
86  typedef typename MRT::ElementType MET;
87  typedef typename VT::CompositeType VCT;
88  typedef typename MT::CompositeType MCT;
89  //**********************************************************************************************
90 
91  //**********************************************************************************************
93  enum { evaluate = IsComputation<MT>::value && !MT::vectorizable &&
95  //**********************************************************************************************
96 
97  //**********************************************************************************************
99 
100 
103  template< typename T1, typename T2, typename T3 >
104  struct UseVectorizedKernel {
105  enum { value = T1::vectorizable && T3::vectorizable &&
110  };
112  //**********************************************************************************************
113 
114  //**********************************************************************************************
116 
117 
120  template< typename T1, typename T2, typename T3 >
121  struct UseOptimizedKernel {
122  enum { value = !UseVectorizedKernel<T1,T2,T3>::value &&
123  !IsResizable<typename T1::ElementType>::value &&
124  !IsResizable<VET>::value };
125  };
127  //**********************************************************************************************
128 
129  //**********************************************************************************************
131 
132 
134  template< typename T1, typename T2, typename T3 >
135  struct UseDefaultKernel {
136  enum { value = !UseVectorizedKernel<T1,T2,T3>::value &&
137  !UseOptimizedKernel<T1,T2,T3>::value };
138  };
140  //**********************************************************************************************
141 
142  public:
143  //**Type definitions****************************************************************************
146  typedef typename ResultType::TransposeType TransposeType;
147  typedef typename ResultType::ElementType ElementType;
149  typedef const ElementType ReturnType;
150  typedef const ResultType CompositeType;
151 
153  typedef typename SelectType< IsExpression<VT>::value, const VT, const VT& >::Type LeftOperand;
154 
156  typedef typename SelectType< IsExpression<MT>::value, const MT, const MT& >::Type RightOperand;
157 
159  typedef typename SelectType< IsComputation<VT>::value, const VRT, VCT >::Type LT;
160 
163  //**********************************************************************************************
164 
165  //**Compilation flags***************************************************************************
167  enum { vectorizable = 0 };
168  //**********************************************************************************************
169 
170  //**Constructor*********************************************************************************
176  explicit inline TSVecDMatMultExpr( const VT& vec, const MT& mat )
177  : vec_( vec ) // Left-hand side sparse vector of the multiplication expression
178  , mat_( mat ) // Right-hand side dense matrix of the multiplication expression
179  {
180  BLAZE_INTERNAL_ASSERT( vec_.size() == mat_.rows(), "Invalid vector and matrix sizes" );
181  }
182  //**********************************************************************************************
183 
184  //**Subscript operator**************************************************************************
190  inline ReturnType operator[]( size_t index ) const {
191  BLAZE_INTERNAL_ASSERT( index < mat_.columns(), "Invalid vector access index" );
192 
193  typedef typename RemoveReference<LT>::Type::ConstIterator ConstIterator;
194 
195  LT x( vec_ ); // Evaluation of the left-hand side sparse vector operand
196 
197  BLAZE_INTERNAL_ASSERT( x.size() == vec_.size(), "Invalid vector size" );
198 
199  const ConstIterator end( x.end() );
200  ConstIterator element( x.begin() );
201  ElementType res;
202 
203  if( element != end ) {
204  res = element->value() * mat_( element->index(), index );
205  ++element;
206  for( ; element!=end; ++element )
207  res += element->value() * mat_( element->index(), index );
208  }
209  else {
210  reset( res );
211  }
212 
213  return res;
214  }
215  //**********************************************************************************************
216 
217  //**Size function*******************************************************************************
222  inline size_t size() const {
223  return mat_.columns();
224  }
225  //**********************************************************************************************
226 
227  //**Left operand access*************************************************************************
232  inline LeftOperand leftOperand() const {
233  return vec_;
234  }
235  //**********************************************************************************************
236 
237  //**Right operand access************************************************************************
242  inline RightOperand rightOperand() const {
243  return mat_;
244  }
245  //**********************************************************************************************
246 
247  //**********************************************************************************************
253  template< typename T >
254  inline bool canAlias( const T* alias ) const {
255  return vec_.isAliased( alias ) || mat_.isAliased( alias );
256  }
257  //**********************************************************************************************
258 
259  //**********************************************************************************************
265  template< typename T >
266  inline bool isAliased( const T* alias ) const {
267  return vec_.isAliased( alias ) || mat_.isAliased( alias );
268  }
269  //**********************************************************************************************
270 
271  private:
272  //**Member variables****************************************************************************
275  //**********************************************************************************************
276 
277  //**Assignment to dense vectors*****************************************************************
289  template< typename VT2 > // Type of the target dense vector
290  friend inline void assign( DenseVector<VT2,true>& lhs, const TSVecDMatMultExpr& rhs )
291  {
293 
294  BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
295 
296  // Evaluation of the left-hand side sparse vector operand
297  LT x( rhs.vec_ );
298  if( x.nonZeros() == 0UL ) {
299  reset( ~lhs );
300  return;
301  }
302 
303  // Evaluation of the right-hand side dense matrix operand
304  RT A( rhs.mat_ );
305 
306  // Checking the evaluated operands
307  BLAZE_INTERNAL_ASSERT( x.size() == rhs.vec_.size() , "Invalid vector size" );
308  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.mat_.rows() , "Invalid number of rows" );
309  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.mat_.columns(), "Invalid number of columns" );
310  BLAZE_INTERNAL_ASSERT( A.columns() == (~lhs).size() , "Invalid vector size" );
311 
312  // Performing the sparse vector-dense matrix multiplication
313  TSVecDMatMultExpr::selectAssignKernel( ~lhs, x, A );
314  }
316  //**********************************************************************************************
317 
318  //**Default assignment to dense vectors*********************************************************
332  template< typename VT1 // Type of the left-hand side target vector
333  , typename VT2 // Type of the left-hand side vector operand
334  , typename MT1 > // Type of the right-hand side matrix operand
335  static inline typename EnableIf< UseDefaultKernel<VT1,VT2,MT1> >::Type
336  selectAssignKernel( VT1& y, const VT2& x, const MT1& A )
337  {
338  typedef typename RemoveReference<LT>::Type::ConstIterator ConstIterator;
339 
340  BLAZE_INTERNAL_ASSERT( x.nonZeros() != 0UL, "Invalid number of non-zero elements" );
341 
342  const size_t N( A.columns() );
343 
344  ConstIterator element( x.begin() );
345  const ConstIterator end( x.end() );
346 
347  for( size_t j=0UL; j<N; ++j ) {
348  y[j] = element->value() * A(element->index(),j);
349  }
350 
351  ++element;
352 
353  for( ; element!=end; ++element ) {
354  for( size_t j=0UL; j<N; ++j ) {
355  y[j] += element->value() * A(element->index(),j);
356  }
357  }
358  }
360  //**********************************************************************************************
361 
362  //**Optimized assignment to dense vectors*******************************************************
376  template< typename VT1 // Type of the left-hand side target vector
377  , typename VT2 // Type of the left-hand side vector operand
378  , typename MT1 > // Type of the right-hand side matrix operand
379  static inline typename EnableIf< UseOptimizedKernel<VT1,VT2,MT1> >::Type
380  selectAssignKernel( VT1& y, const VT2& x, const MT1& A )
381  {
382  typedef typename RemoveReference<LT>::Type::ConstIterator ConstIterator;
383 
384  BLAZE_INTERNAL_ASSERT( x.nonZeros() != 0UL, "Invalid number of non-zero elements" );
385 
386  const size_t N( A.columns() );
387 
388  ConstIterator element( x.begin() );
389  const ConstIterator end( x.end() );
390 
391  const size_t iend( x.nonZeros() & size_t(-4) );
392  BLAZE_INTERNAL_ASSERT( ( x.nonZeros() - ( x.nonZeros() % 4UL ) ) == iend, "Invalid end calculation" );
393 
394  if( iend > 3UL )
395  {
396  const size_t i1( element->index() );
397  const VET v1( element->value() );
398  ++element;
399  const size_t i2( element->index() );
400  const VET v2( element->value() );
401  ++element;
402  const size_t i3( element->index() );
403  const VET v3( element->value() );
404  ++element;
405  const size_t i4( element->index() );
406  const VET v4( element->value() );
407  ++element;
408 
409  for( size_t j=0UL; j<N; ++j ) {
410  y[j] = v1 * A(i1,j) + v2 * A(i2,j) + v3 * A(i3,j) + v4 * A(i4,j);
411  }
412  }
413  else
414  {
415  const size_t i1( element->index() );
416  const VET v1( element->value() );
417  ++element;
418 
419  for( size_t j=0UL; j<N; ++j ) {
420  y[j] = v1 * A(i1,j);
421  }
422  }
423 
424  for( size_t i=(iend>3UL)?(4UL):(1UL); (i+4UL)<=iend; i+=4UL )
425  {
426  const size_t i1( element->index() );
427  const VET v1( element->value() );
428  ++element;
429  const size_t i2( element->index() );
430  const VET v2( element->value() );
431  ++element;
432  const size_t i3( element->index() );
433  const VET v3( element->value() );
434  ++element;
435  const size_t i4( element->index() );
436  const VET v4( element->value() );
437  ++element;
438 
439  for( size_t j=0UL; j<N; ++j ) {
440  y[j] += v1 * A(i1,j) + v2 * A(i2,j) + v3 * A(i3,j) + v4 * A(i4,j);
441  }
442  }
443  for( ; element!=end; ++element )
444  {
445  const size_t i1( element->index() );
446  const VET v1( element->value() );
447 
448  for( size_t j=0UL; j<N; ++j ) {
449  y[j] += v1 * A(i1,j);
450  }
451  }
452  }
454  //**********************************************************************************************
455 
456  //**Vectorized assignment to dense vectors******************************************************
470  template< typename VT1 // Type of the left-hand side target vector
471  , typename VT2 // Type of the left-hand side vector operand
472  , typename MT1 > // Type of the right-hand side matrix operand
473  static inline typename EnableIf< UseVectorizedKernel<VT1,VT2,MT1> >::Type
474  selectAssignKernel( VT1& y, const VT2& x, const MT1& A )
475  {
476  typedef IntrinsicTrait<ElementType> IT;
477  typedef typename RemoveReference<LT>::Type::ConstIterator ConstIterator;
478 
479  BLAZE_INTERNAL_ASSERT( x.nonZeros() != 0UL, "Invalid number of non-zero elements" );
480 
481  const size_t N( A.columns() );
482 
483  ConstIterator element( x.begin() );
484  const ConstIterator end( x.end() );
485 
486  const size_t iend( x.nonZeros() & size_t(-4) );
487  BLAZE_INTERNAL_ASSERT( ( x.nonZeros() - ( x.nonZeros() % 4UL ) ) == iend, "Invalid end calculation" );
488 
489  if( iend > 3UL )
490  {
491  const size_t i1( element->index() );
492  const IntrinsicType v1( set( element->value() ) );
493  ++element;
494  const size_t i2( element->index() );
495  const IntrinsicType v2( set( element->value() ) );
496  ++element;
497  const size_t i3( element->index() );
498  const IntrinsicType v3( set( element->value() ) );
499  ++element;
500  const size_t i4( element->index() );
501  const IntrinsicType v4( set( element->value() ) );
502  ++element;
503 
504  for( size_t j=0UL; j<N; j+=IT::size ) {
505  store( &y[j], v1 * A.get(i1,j) + v2 * A.get(i2,j) + v3 * A.get(i3,j) + v4 * A.get(i4,j) );
506  }
507  }
508  else
509  {
510  const size_t i1( element->index() );
511  const IntrinsicType v1( set( element->value() ) );
512  ++element;
513 
514  for( size_t j=0UL; j<N; j+=IT::size ) {
515  store( &y[j], v1 * A.get(i1,j) );
516  }
517  }
518 
519  for( size_t i=(iend>3UL)?(4UL):(1UL); (i+4UL)<=iend; i+=4UL )
520  {
521  const size_t i1( element->index() );
522  const IntrinsicType v1( set( element->value() ) );
523  ++element;
524  const size_t i2( element->index() );
525  const IntrinsicType v2( set( element->value() ) );
526  ++element;
527  const size_t i3( element->index() );
528  const IntrinsicType v3( set( element->value() ) );
529  ++element;
530  const size_t i4( element->index() );
531  const IntrinsicType v4( set( element->value() ) );
532  ++element;
533 
534  for( size_t j=0UL; j<N; j+=IT::size ) {
535  store( &y[j], load( &y[j] ) + v1 * A.get(i1,j) + v2 * A.get(i2,j) + v3 * A.get(i3,j) + v4 * A.get(i4,j) );
536  }
537  }
538  for( ; element!=end; ++element )
539  {
540  const size_t i1( element->index() );
541  const IntrinsicType v1( set( element->value() ) );
542 
543  for( size_t j=0UL; j<N; j+=IT::size ) {
544  store( &y[j], load( &y[j] ) + v1 * A.get(i1,j) );
545  }
546  }
547  }
549  //**********************************************************************************************
550 
551  //**Assignment to sparse vectors****************************************************************
563  template< typename VT2 > // Type of the target sparse vector
564  friend inline void assign( SparseVector<VT2,true>& lhs, const TSVecDMatMultExpr& rhs )
565  {
567 
570  BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( typename ResultType::CompositeType );
571 
572  BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
573 
574  const ResultType tmp( rhs );
575  assign( ~lhs, tmp );
576  }
578  //**********************************************************************************************
579 
580  //**Addition assignment to dense vectors********************************************************
591  template< typename VT2 > // Type of the target dense vector
592  friend inline void addAssign( DenseVector<VT2,true>& lhs, const TSVecDMatMultExpr& rhs )
593  {
595 
596  BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
597 
598  // Evaluation of the left-hand side sparse vector operand
599  LT x( rhs.vec_ );
600  if( x.nonZeros() == 0UL ) return;
601 
602  // Evaluation of the right-hand side dense matrix operand
603  RT A( rhs.mat_ );
604 
605  // Checking the evaluated operands
606  BLAZE_INTERNAL_ASSERT( x.size() == rhs.vec_.size() , "Invalid vector size" );
607  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.mat_.rows() , "Invalid number of rows" );
608  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.mat_.columns(), "Invalid number of columns" );
609  BLAZE_INTERNAL_ASSERT( A.columns() == (~lhs).size() , "Invalid vector size" );
610 
611  // Performing the sparse vector-dense matrix multiplication
612  TSVecDMatMultExpr::selectAddAssignKernel( ~lhs, x, A );
613  }
614  //**********************************************************************************************
615 
616  //**Default addition assignment to dense vectors************************************************
630  template< typename VT1 // Type of the left-hand side target vector
631  , typename VT2 // Type of the left-hand side vector operand
632  , typename MT1 > // Type of the right-hand side matrix operand
633  static inline typename EnableIf< UseDefaultKernel<VT1,VT2,MT1> >::Type
634  selectAddAssignKernel( VT1& y, const VT2& x, const MT1& A )
635  {
636  typedef typename RemoveReference<LT>::Type::ConstIterator ConstIterator;
637 
638  BLAZE_INTERNAL_ASSERT( x.nonZeros() != 0UL, "Invalid number of non-zero elements" );
639 
640  const size_t N( A.columns() );
641 
642  ConstIterator element( x.begin() );
643  const ConstIterator end( x.end() );
644 
645  for( ; element!=end; ++element ) {
646  for( size_t j=0UL; j<N; ++j ) {
647  y[j] += element->value() * A(element->index(),j);
648  }
649  }
650  }
652  //**********************************************************************************************
653 
654  //**Optimized addition assignment to dense vectors**********************************************
668  template< typename VT1 // Type of the left-hand side target vector
669  , typename VT2 // Type of the left-hand side vector operand
670  , typename MT1 > // Type of the right-hand side matrix operand
671  static inline typename EnableIf< UseOptimizedKernel<VT1,VT2,MT1> >::Type
672  selectAddAssignKernel( VT1& y, const VT2& x, const MT1& A )
673  {
674  typedef typename RemoveReference<LT>::Type::ConstIterator ConstIterator;
675 
676  BLAZE_INTERNAL_ASSERT( x.nonZeros() != 0UL, "Invalid number of non-zero elements" );
677 
678  const size_t N( A.columns() );
679 
680  ConstIterator element( x.begin() );
681  const ConstIterator end( x.end() );
682 
683  const size_t iend( x.nonZeros() & size_t(-4) );
684  BLAZE_INTERNAL_ASSERT( ( x.nonZeros() - ( x.nonZeros() % 4UL ) ) == iend, "Invalid end calculation" );
685 
686  for( size_t i=0UL; (i+4UL)<=iend; i+=4UL )
687  {
688  const size_t i1( element->index() );
689  const VET v1( element->value() );
690  ++element;
691  const size_t i2( element->index() );
692  const VET v2( element->value() );
693  ++element;
694  const size_t i3( element->index() );
695  const VET v3( element->value() );
696  ++element;
697  const size_t i4( element->index() );
698  const VET v4( element->value() );
699  ++element;
700 
701  for( size_t j=0UL; j<N; ++j ) {
702  y[j] += v1 * A(i1,j) + v2 * A(i2,j) + v3 * A(i3,j) + v4 * A(i4,j);
703  }
704  }
705  for( ; element!=end; ++element )
706  {
707  const size_t i1( element->index() );
708  const VET v1( element->value() );
709 
710  for( size_t j=0UL; j<N; ++j ) {
711  y[j] += v1 * A(i1,j);
712  }
713  }
714  }
716  //**********************************************************************************************
717 
718  //**Vectorized addition assignment to dense vectors*********************************************
732  template< typename VT1 // Type of the left-hand side target vector
733  , typename VT2 // Type of the left-hand side vector operand
734  , typename MT1 > // Type of the right-hand side matrix operand
735  static inline typename EnableIf< UseVectorizedKernel<VT1,VT2,MT1> >::Type
736  selectAddAssignKernel( VT1& y, const VT2& x, const MT1& A )
737  {
738  typedef IntrinsicTrait<ElementType> IT;
739  typedef typename RemoveReference<LT>::Type::ConstIterator ConstIterator;
740 
741  BLAZE_INTERNAL_ASSERT( x.nonZeros() != 0UL, "Invalid number of non-zero elements" );
742 
743  const size_t N( A.columns() );
744 
745  ConstIterator element( x.begin() );
746  const ConstIterator end( x.end() );
747 
748  const size_t iend( x.nonZeros() & size_t(-4) );
749  BLAZE_INTERNAL_ASSERT( ( x.nonZeros() - ( x.nonZeros() % 4UL ) ) == iend, "Invalid end calculation" );
750 
751  for( size_t i=0UL; (i+4UL)<=iend; i+=4UL )
752  {
753  const size_t i1( element->index() );
754  const IntrinsicType v1( set( element->value() ) );
755  ++element;
756  const size_t i2( element->index() );
757  const IntrinsicType v2( set( element->value() ) );
758  ++element;
759  const size_t i3( element->index() );
760  const IntrinsicType v3( set( element->value() ) );
761  ++element;
762  const size_t i4( element->index() );
763  const IntrinsicType v4( set( element->value() ) );
764  ++element;
765 
766  for( size_t j=0UL; j<N; j+=IT::size ) {
767  store( &y[j], load( &y[j] ) + v1 * A.get(i1,j) + v2 * A.get(i2,j) + v3 * A.get(i3,j) + v4 * A.get(i4,j) );
768  }
769  }
770  for( ; element!=end; ++element )
771  {
772  const size_t i1( element->index() );
773  const IntrinsicType v1( set( element->value() ) );
774 
775  for( size_t j=0UL; j<N; j+=IT::size ) {
776  store( &y[j], load( &y[j] ) + v1 * A.get(i1,j) );
777  }
778  }
779  }
781  //**********************************************************************************************
782 
783  //**Addition assignment to sparse vectors*******************************************************
784  // No special implementation for the addition assignment to sparse vectors.
785  //**********************************************************************************************
786 
787  //**Subtraction assignment to dense vectors*****************************************************
798  template< typename VT2 > // Type of the target dense vector
799  friend inline void subAssign( DenseVector<VT2,true>& lhs, const TSVecDMatMultExpr& rhs )
800  {
802 
803  BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
804 
805  typedef typename RemoveReference<LT>::Type::ConstIterator ConstIterator;
806 
807  // Evaluation of the left-hand side sparse vector operand
808  LT x( rhs.vec_ );
809  if( x.nonZeros() == 0UL ) return;
810 
811  // Evaluation of the right-hand side dense matrix operand
812  RT A( rhs.mat_ );
813 
814  // Checking the evaluated operands
815  BLAZE_INTERNAL_ASSERT( x.size() == rhs.vec_.size() , "Invalid vector size" );
816  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.mat_.rows() , "Invalid number of rows" );
817  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.mat_.columns(), "Invalid number of columns" );
818  BLAZE_INTERNAL_ASSERT( A.columns() == (~lhs).size() , "Invalid vector size" );
819 
820  // Performing the sparse vector-dense matrix multiplication
821  TSVecDMatMultExpr::selectSubAssignKernel( ~lhs, x, A );
822  }
823  //**********************************************************************************************
824 
825  //**Default subtraction assignment to dense vectors*********************************************
839  template< typename VT1 // Type of the left-hand side target vector
840  , typename VT2 // Type of the left-hand side vector operand
841  , typename MT1 > // Type of the right-hand side matrix operand
842  static inline typename EnableIf< UseDefaultKernel<VT1,VT2,MT1> >::Type
843  selectSubAssignKernel( VT1& y, const VT2& x, const MT1& A )
844  {
845  typedef typename RemoveReference<LT>::Type::ConstIterator ConstIterator;
846 
847  BLAZE_INTERNAL_ASSERT( x.nonZeros() != 0UL, "Invalid number of non-zero elements" );
848 
849  const size_t N( A.columns() );
850 
851  ConstIterator element( x.begin() );
852  const ConstIterator end( x.end() );
853 
854  for( ; element!=end; ++element ) {
855  for( size_t j=0UL; j<N; ++j ) {
856  y[j] -= element->value() * A(element->index(),j);
857  }
858  }
859  }
861  //**********************************************************************************************
862 
863  //**Optimized subtraction assignment to dense vectors*******************************************
877  template< typename VT1 // Type of the left-hand side target vector
878  , typename VT2 // Type of the left-hand side vector operand
879  , typename MT1 > // Type of the right-hand side matrix operand
880  static inline typename EnableIf< UseOptimizedKernel<VT1,VT2,MT1> >::Type
881  selectSubAssignKernel( VT1& y, const VT2& x, const MT1& A )
882  {
883  typedef typename RemoveReference<LT>::Type::ConstIterator ConstIterator;
884 
885  BLAZE_INTERNAL_ASSERT( x.nonZeros() != 0UL, "Invalid number of non-zero elements" );
886 
887  const size_t N( A.columns() );
888 
889  ConstIterator element( x.begin() );
890  const ConstIterator end( x.end() );
891 
892  const size_t iend( x.nonZeros() & size_t(-4) );
893  BLAZE_INTERNAL_ASSERT( ( x.nonZeros() - ( x.nonZeros() % 4UL ) ) == iend, "Invalid end calculation" );
894 
895  for( size_t i=0UL; (i+4UL)<=iend; i+=4UL )
896  {
897  const size_t i1( element->index() );
898  const VET v1( element->value() );
899  ++element;
900  const size_t i2( element->index() );
901  const VET v2( element->value() );
902  ++element;
903  const size_t i3( element->index() );
904  const VET v3( element->value() );
905  ++element;
906  const size_t i4( element->index() );
907  const VET v4( element->value() );
908  ++element;
909 
910  for( size_t j=0UL; j<N; ++j ) {
911  y[j] -= v1 * A(i1,j) + v2 * A(i2,j) + v3 * A(i3,j) + v4 * A(i4,j);
912  }
913  }
914  for( ; element!=end; ++element )
915  {
916  const size_t i1( element->index() );
917  const VET v1( element->value() );
918 
919  for( size_t j=0UL; j<N; ++j ) {
920  y[j] -= v1 * A(i1,j);
921  }
922  }
923  }
925  //**********************************************************************************************
926 
927  //**Vectorized subtraction assignment to dense vectors******************************************
941  template< typename VT1 // Type of the left-hand side target vector
942  , typename VT2 // Type of the left-hand side vector operand
943  , typename MT1 > // Type of the right-hand side matrix operand
944  static inline typename EnableIf< UseVectorizedKernel<VT1,VT2,MT1> >::Type
945  selectSubAssignKernel( VT1& y, const VT2& x, const MT1& A )
946  {
947  typedef IntrinsicTrait<ElementType> IT;
948  typedef typename RemoveReference<LT>::Type::ConstIterator ConstIterator;
949 
950  BLAZE_INTERNAL_ASSERT( x.nonZeros() != 0UL, "Invalid number of non-zero elements" );
951 
952  const size_t N( A.columns() );
953 
954  ConstIterator element( x.begin() );
955  const ConstIterator end( x.end() );
956 
957  const size_t iend( x.nonZeros() & size_t(-4) );
958  BLAZE_INTERNAL_ASSERT( ( x.nonZeros() - ( x.nonZeros() % 4UL ) ) == iend, "Invalid end calculation" );
959 
960  for( size_t i=0UL; (i+4UL)<=iend; i+=4UL )
961  {
962  const size_t i1( element->index() );
963  const IntrinsicType v1( set( element->value() ) );
964  ++element;
965  const size_t i2( element->index() );
966  const IntrinsicType v2( set( element->value() ) );
967  ++element;
968  const size_t i3( element->index() );
969  const IntrinsicType v3( set( element->value() ) );
970  ++element;
971  const size_t i4( element->index() );
972  const IntrinsicType v4( set( element->value() ) );
973  ++element;
974 
975  for( size_t j=0UL; j<N; j+=IT::size ) {
976  store( &y[j], load( &y[j] ) - v1 * A.get(i1,j) - v2 * A.get(i2,j) - v3 * A.get(i3,j) - v4 * A.get(i4,j) );
977  }
978  }
979  for( ; element!=x.end(); ++element )
980  {
981  const size_t i1( element->index() );
982  const IntrinsicType v1( set( element->value() ) );
983 
984  for( size_t j=0UL; j<N; j+=IT::size ) {
985  store( &y[j], load( &y[j] ) - v1 * A.get(i1,j) );
986  }
987  }
988  }
990  //**********************************************************************************************
991 
992  //**Subtraction assignment to sparse vectors****************************************************
993  // No special implementation for the subtraction assignment to sparse vectors.
994  //**********************************************************************************************
995 
996  //**Multiplication assignment to dense vectors**************************************************
1007  template< typename VT2 > // Type of the target dense vector
1008  friend inline void multAssign( DenseVector<VT2,true>& lhs, const TSVecDMatMultExpr& rhs )
1009  {
1011 
1014  BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( typename ResultType::CompositeType );
1015 
1016  BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
1017 
1018  const ResultType tmp( rhs );
1019  multAssign( ~lhs, tmp );
1020  }
1021  //**********************************************************************************************
1022 
1023  //**Multiplication assignment to sparse vectors*************************************************
1024  // No special implementation for the multiplication assignment to sparse vectors.
1025  //**********************************************************************************************
1026 
1027  //**Compile time checks*************************************************************************
1034  //**********************************************************************************************
1035 };
1036 //*************************************************************************************************
1037 
1038 
1039 
1040 
1041 //=================================================================================================
1042 //
1043 // GLOBAL BINARY ARITHMETIC OPERATORS
1044 //
1045 //=================================================================================================
1046 
1047 //*************************************************************************************************
1078 template< typename T1, typename T2 >
1079 inline const typename DisableIf< IsMatMatMultExpr<T2>, TSVecDMatMultExpr<T1,T2> >::Type
1081 {
1083 
1084  if( (~vec).size() != (~mat).rows() )
1085  throw std::invalid_argument( "Vector and matrix sizes do not match" );
1086 
1087  return TSVecDMatMultExpr<T1,T2>( ~vec, ~mat );
1088 }
1089 //*************************************************************************************************
1090 
1091 
1092 
1093 
1094 //=================================================================================================
1095 //
1096 // GLOBAL RESTRUCTURING BINARY ARITHMETIC OPERATORS
1097 //
1098 //=================================================================================================
1099 
1100 //*************************************************************************************************
1113 template< typename T1 // Type of the left-hand side sparse vector
1114  , typename T2 // Type of the right-hand side dense matrix
1115  , bool SO > // Storage order of the right-hand side dense matrix
1116 inline const typename EnableIf< IsMatMatMultExpr<T2>, MultExprTrait<T1,T2> >::Type::Type
1118 {
1120 
1121  return ( vec * (~mat).leftOperand() ) * (~mat).rightOperand();
1122 }
1123 //*************************************************************************************************
1124 
1125 } // namespace blaze
1126 
1127 #endif