SMatSVecMultExpr.h
Go to the documentation of this file.
1 //=================================================================================================
33 //=================================================================================================
34 
35 #ifndef _BLAZE_MATH_EXPRESSIONS_SMATSVECMULTEXPR_H_
36 #define _BLAZE_MATH_EXPRESSIONS_SMATSVECMULTEXPR_H_
37 
38 
39 //*************************************************************************************************
40 // Includes
41 //*************************************************************************************************
42 
55 #include <blaze/math/shims/Reset.h>
68 #include <blaze/util/Assert.h>
70 #include <blaze/util/DisableIf.h>
71 #include <blaze/util/EnableIf.h>
72 #include <blaze/util/Exception.h>
74 #include <blaze/util/mpl/Or.h>
75 #include <blaze/util/SelectType.h>
76 #include <blaze/util/Types.h>
78 
79 
80 namespace blaze {
81 
82 //=================================================================================================
83 //
84 // CLASS SMATDVECMULTEXPR
85 //
86 //=================================================================================================
87 
88 //*************************************************************************************************
95 template< typename MT // Type of the left-hand side sparse matrix
96  , typename VT > // Type of the right-hand side sparse vector
97 class SMatSVecMultExpr : public SparseVector< SMatSVecMultExpr<MT,VT>, false >
98  , private MatVecMultExpr
99  , private Computation
100 {
101  private:
102  //**Type definitions****************************************************************************
103  typedef typename MT::ResultType MRT;
104  typedef typename VT::ResultType VRT;
105  typedef typename MT::CompositeType MCT;
106  typedef typename VT::CompositeType VCT;
107  //**********************************************************************************************
108 
109  //**********************************************************************************************
111  enum { evaluateMatrix = RequiresEvaluation<MT>::value };
112  //**********************************************************************************************
113 
114  //**********************************************************************************************
116  enum { evaluateVector = RequiresEvaluation<VT>::value || IsComputation<VT>::value };
117  //**********************************************************************************************
118 
119  //**********************************************************************************************
121 
125  template< typename T1 >
126  struct UseSMPAssign {
127  enum { value = ( evaluateMatrix || evaluateVector ) };
128  };
130  //**********************************************************************************************
131 
132  public:
133  //**Type definitions****************************************************************************
138  typedef const ElementType ReturnType;
139 
141  typedef const ResultType CompositeType;
142 
144  typedef typename SelectType< IsExpression<MT>::value, const MT, const MT& >::Type LeftOperand;
145 
147  typedef typename SelectType< IsExpression<VT>::value, const VT, const VT& >::Type RightOperand;
148 
151 
154  //**********************************************************************************************
155 
156  //**Compilation flags***************************************************************************
158  enum { smpAssignable = !evaluateMatrix && MT::smpAssignable &&
159  !evaluateVector && VT::smpAssignable };
160  //**********************************************************************************************
161 
162  //**Constructor*********************************************************************************
168  explicit inline SMatSVecMultExpr( const MT& mat, const VT& vec )
169  : mat_( mat ) // Left-hand side sparse matrix of the multiplication expression
170  , vec_( vec ) // Right-hand side sparse vector of the multiplication expression
171  {
172  BLAZE_INTERNAL_ASSERT( mat_.columns() == vec_.size(), "Invalid matrix and vector sizes" );
173  }
174  //**********************************************************************************************
175 
176  //**Subscript operator**************************************************************************
182  inline ReturnType operator[]( size_t index ) const {
183  BLAZE_INTERNAL_ASSERT( index < mat_.rows(), "Invalid vector access index" );
184 
185  typedef typename RemoveReference<MCT>::Type::ConstIterator MatrixIterator;
186  typedef typename RemoveReference<VCT>::Type::ConstIterator VectorIterator;
187 
188  ElementType res = ElementType();
189 
190  // Early exit
191  if( vec_.size() == 0UL )
192  return res;
193 
194  // Fast computation in case both the left-hand side matrix operand and the right-hand
195  // side vector operand directly provide iterators
197  {
198  MCT A( mat_ ); // Evaluation of the left-hand side sparse matrix operand
199  VCT x( vec_ ); // Evaluation of the right-hand side sparse vector operand
200 
201  MatrixIterator melem( A.begin(index) );
202  const MatrixIterator mend( A.end(index) );
203  if( melem == mend ) {
204  return res;
205  }
206 
207  VectorIterator velem( x.begin() );
208  const VectorIterator vend( x.end() );
209  if( velem == vend ) {
210  return res;
211  }
212 
213  while( true ) {
214  if( melem->index() < velem->index() ) {
215  ++melem;
216  if( melem == mend ) break;
217  }
218  else if( velem->index() < melem->index() ) {
219  ++velem;
220  if( velem == vend ) break;
221  }
222  else {
223  res = melem->value() * velem->value();
224  ++melem;
225  ++velem;
226  break;
227  }
228  }
229 
230  if( melem != mend && velem != vend )
231  {
232  while( true ) {
233  if( melem->index() < velem->index() ) {
234  ++melem;
235  if( melem == mend ) break;
236  }
237  else if( velem->index() < melem->index() ) {
238  ++velem;
239  if( velem == vend ) break;
240  }
241  else {
242  res += melem->value() * velem->value();
243  ++melem;
244  if( melem == mend ) break;
245  ++velem;
246  if( velem == vend ) break;
247  }
248  }
249  }
250  }
251 
252  // Optimized computation in case the left-hand side matrix operand directly provides iterators
254  {
255  MCT A( mat_ ); // Evaluation of the left-hand side sparse matrix operand
256 
257  MatrixIterator melem( A.begin(index) );
258  const MatrixIterator mend( A.end(index) );
259 
260  if( melem == mend )
261  return res;
262 
263  res = melem->value() * vec_[melem->index()];
264  ++melem;
265  for( ; melem!=mend; ++melem ) {
266  res += melem->value() * vec_[melem->index()];
267  }
268  }
269 
270  // Optimized computation in case the right-hand side vector operand directly provides iterators
272  {
273  VCT x( vec_ ); // Evaluation of the right-hand side sparse vector operand
274 
275  VectorIterator velem( x.begin() );
276  const VectorIterator vend( x.end() );
277 
278  if( velem == vend )
279  return res;
280 
281  res = mat_(index,velem->index()) * velem->value();
282  ++velem;
283  for( ; velem!=vend; ++velem ) {
284  res += mat_(index,velem->index()) * velem->value();
285  }
286  }
287 
288  // Default computation in case both operands don't provide iterators
289  else {
290  res = mat_(index,0UL) * vec_[0UL];
291  for( size_t j=1UL; j<vec_.size(); ++j ) {
292  res += mat_(index,j) * vec_[j];
293  }
294  }
295 
296  return res;
297  }
298  //**********************************************************************************************
299 
300  //**At function*********************************************************************************
307  inline ReturnType at( size_t index ) const {
308  if( index >= mat_.rows() ) {
309  BLAZE_THROW_OUT_OF_RANGE( "Invalid vector access index" );
310  }
311  return (*this)[index];
312  }
313  //**********************************************************************************************
314 
315  //**Size function*******************************************************************************
320  inline size_t size() const {
321  return mat_.rows();
322  }
323  //**********************************************************************************************
324 
325  //**NonZeros function***************************************************************************
330  inline size_t nonZeros() const {
331  return mat_.rows();
332  }
333  //**********************************************************************************************
334 
335  //**Left operand access*************************************************************************
340  inline LeftOperand leftOperand() const {
341  return mat_;
342  }
343  //**********************************************************************************************
344 
345  //**Right operand access************************************************************************
350  inline RightOperand rightOperand() const {
351  return vec_;
352  }
353  //**********************************************************************************************
354 
355  //**********************************************************************************************
361  template< typename T >
362  inline bool canAlias( const T* alias ) const {
363  return ( mat_.isAliased( alias ) || vec_.isAliased( alias ) );
364  }
365  //**********************************************************************************************
366 
367  //**********************************************************************************************
373  template< typename T >
374  inline bool isAliased( const T* alias ) const {
375  return ( mat_.isAliased( alias ) || vec_.isAliased( alias ) );
376  }
377  //**********************************************************************************************
378 
379  //**********************************************************************************************
384  inline bool canSMPAssign() const {
385  return ( size() > SMP_SMATSVECMULT_THRESHOLD );
386  }
387  //**********************************************************************************************
388 
389  private:
390  //**Member variables****************************************************************************
391  LeftOperand mat_;
392  RightOperand vec_;
393  //**********************************************************************************************
394 
395  //**Assignment to dense vectors*****************************************************************
407  template< typename VT1 > // Type of the target dense vector
408  friend inline void assign( DenseVector<VT1,false>& lhs, const SMatSVecMultExpr& rhs )
409  {
411 
412  BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
413 
414  // Resetting the left-hand side target dense vector
415  reset( ~lhs );
416 
417  // Evaluation of the right-hand side sparse vector operand
418  RT x( serial( rhs.vec_ ) );
419  if( x.nonZeros() == 0UL ) return;
420 
421  // Evaluation of the left-hand side sparse matrix operand
422  LT A( serial( rhs.mat_ ) );
423 
424  // Checking the evaluated operators
425  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.mat_.rows() , "Invalid number of rows" );
426  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.mat_.columns(), "Invalid number of columns" );
427  BLAZE_INTERNAL_ASSERT( x.size() == rhs.vec_.size() , "Invalid vector size" );
428  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).size() , "Invalid vector size" );
429 
430  // Performing the sparse matrix-sparse vector multiplication
431  SMatSVecMultExpr::selectAssignKernel( ~lhs, A, x );
432  }
434  //**********************************************************************************************
435 
436  //**Default assignment to dense vectors*********************************************************
450  template< typename VT1 // Type of the left-hand side target vector
451  , typename MT1 // Type of the left-hand side matrix operand
452  , typename VT2 > // Type of the right-hand side vector operand
453  static inline void selectAssignKernel( VT1& y, const MT1& A, const VT2& x )
454  {
455  typedef typename RemoveReference<LT>::Type::ConstIterator MatrixIterator;
456  typedef typename RemoveReference<RT>::Type::ConstIterator VectorIterator;
457 
458  const VectorIterator vend( x.end() );
459 
460  for( size_t i=0UL; i<y.size(); ++i )
461  {
462  const MatrixIterator mend ( A.end(i) );
463  MatrixIterator melem( A.begin(i) );
464 
465  if( melem == mend ) continue;
466 
467  VectorIterator velem( x.begin() );
468 
469  while( true ) {
470  if( melem->index() < velem->index() ) {
471  ++melem;
472  if( melem == mend ) break;
473  }
474  else if( velem->index() < melem->index() ) {
475  ++velem;
476  if( velem == vend ) break;
477  }
478  else {
479  y[i] = melem->value() * velem->value();
480  ++melem;
481  ++velem;
482  break;
483  }
484  }
485 
486  if( melem != mend && velem != vend )
487  {
488  while( true ) {
489  if( melem->index() < velem->index() ) {
490  ++melem;
491  if( melem == mend ) break;
492  }
493  else if( velem->index() < melem->index() ) {
494  ++velem;
495  if( velem == vend ) break;
496  }
497  else {
498  y[i] += melem->value() * velem->value();
499  ++melem;
500  if( melem == mend ) break;
501  ++velem;
502  if( velem == vend ) break;
503  }
504  }
505  }
506  }
507  }
509  //**********************************************************************************************
510 
511  //**Assignment to sparse vectors****************************************************************
523  template< typename VT1 > // Type of the target sparse vector
524  friend inline void assign( SparseVector<VT1,false>& lhs, const SMatSVecMultExpr& rhs )
525  {
527 
528  BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
529 
530  typedef typename RemoveReference<LT>::Type::ConstIterator MatrixIterator;
531  typedef typename RemoveReference<RT>::Type::ConstIterator VectorIterator;
532 
533  RT x( rhs.vec_ ); // Evaluation of the right-hand side sparse vector operand
534  if( x.nonZeros() == 0UL ) return;
535 
536  LT A( rhs.mat_ ); // Evaluation of the left-hand side sparse matrix operand
537 
538  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.mat_.rows() , "Invalid number of rows" );
539  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.mat_.columns(), "Invalid number of columns" );
540  BLAZE_INTERNAL_ASSERT( x.size() == rhs.vec_.size() , "Invalid vector size" );
541  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).size() , "Invalid vector size" );
542 
543  ElementType accu;
544  const VectorIterator vend( x.end() );
545 
546  for( size_t i=0UL; i<(~lhs).size(); ++i )
547  {
548  const MatrixIterator mend ( A.end(i) );
549  MatrixIterator melem( A.begin(i) );
550 
551  if( melem == mend ) continue;
552 
553  VectorIterator velem( x.begin() );
554 
555  reset( accu );
556 
557  while( true ) {
558  if( melem->index() < velem->index() ) {
559  ++melem;
560  if( melem == mend ) break;
561  }
562  else if( velem->index() < melem->index() ) {
563  ++velem;
564  if( velem == vend ) break;
565  }
566  else {
567  accu = melem->value() * velem->value();
568  ++melem;
569  ++velem;
570  break;
571  }
572  }
573 
574  if( melem != mend && velem != vend )
575  {
576  while( true ) {
577  if( melem->index() < velem->index() ) {
578  ++melem;
579  if( melem == mend ) break;
580  }
581  else if( velem->index() < melem->index() ) {
582  ++velem;
583  if( velem == vend ) break;
584  }
585  else {
586  accu += melem->value() * velem->value();
587  ++melem;
588  if( melem == mend ) break;
589  ++velem;
590  if( velem == vend ) break;
591  }
592  }
593  }
594 
595  if( !isDefault( accu ) )
596  (~lhs).insert( i, accu );
597  }
598  }
600  //**********************************************************************************************
601 
602  //**Addition assignment to dense vectors********************************************************
614  template< typename VT1 > // Type of the target dense vector
615  friend inline void addAssign( DenseVector<VT1,false>& lhs, const SMatSVecMultExpr& rhs )
616  {
618 
619  BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
620 
621  // Evaluation of the right-hand side sparse vector operand
622  RT x( serial( rhs.vec_ ) );
623  if( x.nonZeros() == 0UL ) return;
624 
625  // Evaluation of the left-hand side sparse matrix operand
626  LT A( serial( rhs.mat_ ) );
627 
628  // Checking the evaluated operators
629  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.mat_.rows() , "Invalid number of rows" );
630  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.mat_.columns(), "Invalid number of columns" );
631  BLAZE_INTERNAL_ASSERT( x.size() == rhs.vec_.size() , "Invalid vector size" );
632  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).size() , "Invalid vector size" );
633 
634  // Performing the sparse matrix-sparse vector multiplication
635  SMatSVecMultExpr::selectAddAssignKernel( ~lhs, A, x );
636  }
638  //**********************************************************************************************
639 
640  //**Default addition assignment to dense vectors************************************************
654  template< typename VT1 // Type of the left-hand side target vector
655  , typename MT1 // Type of the left-hand side matrix operand
656  , typename VT2 > // Type of the right-hand side vector operand
657  static inline void selectAddAssignKernel( VT1& y, const MT1& A, const VT2& x )
658  {
659  typedef typename RemoveReference<LT>::Type::ConstIterator MatrixIterator;
660  typedef typename RemoveReference<RT>::Type::ConstIterator VectorIterator;
661 
662  const VectorIterator vend( x.end() );
663 
664  for( size_t i=0UL; i<y.size(); ++i )
665  {
666  const MatrixIterator mend ( A.end(i) );
667  MatrixIterator melem( A.begin(i) );
668 
669  if( melem == mend ) continue;
670 
671  VectorIterator velem( x.begin() );
672 
673  while( true ) {
674  if( melem->index() < velem->index() ) {
675  ++melem;
676  if( melem == mend ) break;
677  }
678  else if( velem->index() < melem->index() ) {
679  ++velem;
680  if( velem == vend ) break;
681  }
682  else {
683  y[i] += melem->value() * velem->value();
684  ++melem;
685  if( melem == mend ) break;
686  ++velem;
687  if( velem == vend ) break;
688  }
689  }
690  }
691  }
693  //**********************************************************************************************
694 
695  //**Addition assignment to sparse vectors*******************************************************
696  // No special implementation for the addition assignment to sparse vectors.
697  //**********************************************************************************************
698 
699  //**Subtraction assignment to dense vectors*****************************************************
711  template< typename VT1 > // Type of the target dense vector
712  friend inline void subAssign( DenseVector<VT1,false>& lhs, const SMatSVecMultExpr& rhs )
713  {
715 
716  BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
717 
718  typedef typename RemoveReference<LT>::Type::ConstIterator MatrixIterator;
719  typedef typename RemoveReference<RT>::Type::ConstIterator VectorIterator;
720 
721  // Evaluation of the right-hand side sparse vector operand
722  RT x( serial( rhs.vec_ ) );
723  if( x.nonZeros() == 0UL ) return;
724 
725  // Evaluation of the left-hand side sparse matrix operand
726  LT A( serial( rhs.mat_ ) );
727 
728  // Checking the evaluated operators
729  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.mat_.rows() , "Invalid number of rows" );
730  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.mat_.columns(), "Invalid number of columns" );
731  BLAZE_INTERNAL_ASSERT( x.size() == rhs.vec_.size() , "Invalid vector size" );
732  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).size() , "Invalid vector size" );
733 
734  // Performing the sparse matrix-sparse vector multiplication
735  SMatSVecMultExpr::selectSubAssignKernel( ~lhs, A, x );
736  }
738  //**********************************************************************************************
739 
740  //**Default subtraction assignment to dense vectors*********************************************
754  template< typename VT1 // Type of the left-hand side target vector
755  , typename MT1 // Type of the left-hand side matrix operand
756  , typename VT2 > // Type of the right-hand side vector operand
757  static inline void selectSubAssignKernel( VT1& y, const MT1& A, const VT2& x )
758  {
759  typedef typename RemoveReference<LT>::Type::ConstIterator MatrixIterator;
760  typedef typename RemoveReference<RT>::Type::ConstIterator VectorIterator;
761 
762  const VectorIterator vend( x.end() );
763 
764  for( size_t i=0UL; i<y.size(); ++i )
765  {
766  const MatrixIterator mend ( A.end(i) );
767  MatrixIterator melem( A.begin(i) );
768 
769  if( melem == mend ) continue;
770 
771  VectorIterator velem( x.begin() );
772 
773  while( true ) {
774  if( melem->index() < velem->index() ) {
775  ++melem;
776  if( melem == mend ) break;
777  }
778  else if( velem->index() < melem->index() ) {
779  ++velem;
780  if( velem == vend ) break;
781  }
782  else {
783  y[i] -= melem->value() * velem->value();
784  ++melem;
785  if( melem == mend ) break;
786  ++velem;
787  if( velem == vend ) break;
788  }
789  }
790  }
791  }
793  //**********************************************************************************************
794 
795  //**Subtraction assignment to sparse vectors****************************************************
796  // No special implementation for the subtraction assignment to sparse vectors.
797  //**********************************************************************************************
798 
799  //**Multiplication assignment to dense vectors**************************************************
811  template< typename VT1 > // Type of the target dense vector
812  friend inline void multAssign( DenseVector<VT1,false>& lhs, const SMatSVecMultExpr& rhs )
813  {
815 
819 
820  BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
821 
822  const ResultType tmp( serial( rhs ) );
823  multAssign( ~lhs, tmp );
824  }
826  //**********************************************************************************************
827 
828  //**Multiplication assignment to sparse vectors*************************************************
829  // No special implementation for the multiplication assignment to sparse vectors.
830  //**********************************************************************************************
831 
832  //**SMP assignment to dense vectors*************************************************************
846  template< typename VT1 > // Type of the target dense vector
847  friend inline typename EnableIf< UseSMPAssign<VT1> >::Type
848  smpAssign( DenseVector<VT1,false>& lhs, const SMatSVecMultExpr& rhs )
849  {
851 
852  BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
853 
854  // Resetting the left-hand side target dense vector
855  reset( ~lhs );
856 
857  // Evaluation of the right-hand side sparse vector operand
858  RT x( rhs.vec_ );
859  if( x.nonZeros() == 0UL ) return;
860 
861  // Evaluation of the left-hand side sparse matrix operand
862  LT A( rhs.mat_ );
863 
864  // Checking the evaluated operators
865  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.mat_.rows() , "Invalid number of rows" );
866  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.mat_.columns(), "Invalid number of columns" );
867  BLAZE_INTERNAL_ASSERT( x.size() == rhs.vec_.size() , "Invalid vector size" );
868  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).size() , "Invalid vector size" );
869 
870  // Performing the sparse matrix-sparse vector multiplication
871  smpAssign( ~lhs, A * x );
872  }
874  //**********************************************************************************************
875 
876  //**SMP assignment to sparse vectors************************************************************
877  // No special implementation for the SMP assignment to sparse vectors.
878  //**********************************************************************************************
879 
880  //**SMP addition assignment to dense vectors****************************************************
895  template< typename VT1 > // Type of the target dense vector
896  friend inline typename EnableIf< UseSMPAssign<VT1> >::Type
897  smpAddAssign( DenseVector<VT1,false>& lhs, const SMatSVecMultExpr& rhs )
898  {
900 
901  BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
902 
903  // Evaluation of the right-hand side sparse vector operand
904  RT x( rhs.vec_ );
905  if( x.nonZeros() == 0UL ) return;
906 
907  // Evaluation of the left-hand side sparse matrix operand
908  LT A( rhs.mat_ );
909 
910  // Checking the evaluated operators
911  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.mat_.rows() , "Invalid number of rows" );
912  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.mat_.columns(), "Invalid number of columns" );
913  BLAZE_INTERNAL_ASSERT( x.size() == rhs.vec_.size() , "Invalid vector size" );
914  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).size() , "Invalid vector size" );
915 
916  // Performing the sparse matrix-sparse vector multiplication
917  smpAddAssign( ~lhs, A * x );
918  }
920  //**********************************************************************************************
921 
922  //**SMP addition assignment to sparse vectors***************************************************
923  // No special implementation for the SMP addition assignment to sparse vectors.
924  //**********************************************************************************************
925 
926  //**SMP subtraction assignment to dense vectors*************************************************
941  template< typename VT1 > // Type of the target dense vector
942  friend inline typename EnableIf< UseSMPAssign<VT1> >::Type
943  smpSubAssign( DenseVector<VT1,false>& lhs, const SMatSVecMultExpr& rhs )
944  {
946 
947  BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
948 
949  typedef typename RemoveReference<LT>::Type::ConstIterator MatrixIterator;
950  typedef typename RemoveReference<RT>::Type::ConstIterator VectorIterator;
951 
952  // Evaluation of the right-hand side sparse vector operand
953  RT x( rhs.vec_ );
954  if( x.nonZeros() == 0UL ) return;
955 
956  // Evaluation of the left-hand side sparse matrix operand
957  LT A( rhs.mat_ );
958 
959  // Checking the evaluated operators
960  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.mat_.rows() , "Invalid number of rows" );
961  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.mat_.columns(), "Invalid number of columns" );
962  BLAZE_INTERNAL_ASSERT( x.size() == rhs.vec_.size() , "Invalid vector size" );
963  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).size() , "Invalid vector size" );
964 
965  // Performing the sparse matrix-sparse vector multiplication
966  smpSubAssign( ~lhs, A * x );
967  }
969  //**********************************************************************************************
970 
971  //**SMP subtraction assignment to sparse vectors************************************************
972  // No special implementation for the SMP subtraction assignment to sparse vectors.
973  //**********************************************************************************************
974 
975  //**SMP multiplication assignment to dense vectors**********************************************
990  template< typename VT1 > // Type of the target dense vector
991  friend inline typename EnableIf< UseSMPAssign<VT1> >::Type
992  smpMultAssign( DenseVector<VT1,false>& lhs, const SMatSVecMultExpr& rhs )
993  {
995 
999 
1000  BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
1001 
1002  const ResultType tmp( rhs );
1003  smpMultAssign( ~lhs, tmp );
1004  }
1006  //**********************************************************************************************
1007 
1008  //**SMP multiplication assignment to sparse vectors*********************************************
1009  // No special implementation for the SMP multiplication assignment to sparse vectors.
1010  //**********************************************************************************************
1011 
1012  //**Compile time checks*************************************************************************
1021  //**********************************************************************************************
1022 };
1023 //*************************************************************************************************
1024 
1025 
1026 
1027 
1028 //=================================================================================================
1029 //
1030 // GLOBAL BINARY ARITHMETIC OPERATORS
1031 //
1032 //=================================================================================================
1033 
1034 //*************************************************************************************************
1065 template< typename T1 // Type of the left-hand side sparse matrix
1066  , typename T2 > // Type of the right-hand side sparse vector
1067 inline const typename DisableIf< Or< IsSymmetric<T1>, IsMatMatMultExpr<T1> >
1068  , SMatSVecMultExpr<T1,T2> >::Type
1070 {
1072 
1073  if( (~mat).columns() != (~vec).size() ) {
1074  BLAZE_THROW_INVALID_ARGUMENT( "Matrix and vector sizes do not match" );
1075  }
1076 
1077  return SMatSVecMultExpr<T1,T2>( ~mat, ~vec );
1078 }
1079 //*************************************************************************************************
1080 
1081 
1082 
1083 
1084 //=================================================================================================
1085 //
1086 // GLOBAL RESTRUCTURING BINARY ARITHMETIC OPERATORS
1087 //
1088 //=================================================================================================
1089 
1090 //*************************************************************************************************
1105 template< typename T1 // Type of the left-hand side sparse matrix
1106  , typename T2 > // Type of the right-hand side sparse vector
1107 inline const typename EnableIf< IsSymmetric<T1>, typename MultExprTrait<T1,T2>::Type >::Type
1108  operator*( const SparseMatrix<T1,false>& mat, const SparseVector<T2,false>& vec )
1109 {
1111 
1113 
1114  if( (~mat).columns() != (~vec).size() ) {
1115  BLAZE_THROW_INVALID_ARGUMENT( "Matrix and vector sizes do not match" );
1116  }
1117 
1118  return trans( ~mat ) * (~vec);
1119 }
1121 //*************************************************************************************************
1122 
1123 
1124 //*************************************************************************************************
1138 template< typename T1 // Type of the left-hand side sparse matrix
1139  , bool SO // Storage order of the left-hand side sparse matrix
1140  , typename T2 > // Type of the right-hand side sparse vector
1141 inline const typename EnableIf< IsMatMatMultExpr<T1>, typename MultExprTrait<T1,T2>::Type >::Type
1142  operator*( const SparseMatrix<T1,SO>& mat, const SparseVector<T2,false>& vec )
1143 {
1145 
1147 
1148  return (~mat).leftOperand() * ( (~mat).rightOperand() * vec );
1149 }
1151 //*************************************************************************************************
1152 
1153 
1154 
1155 
1156 //=================================================================================================
1157 //
1158 // SIZE SPECIALIZATIONS
1159 //
1160 //=================================================================================================
1161 
1162 //*************************************************************************************************
1164 template< typename MT, typename VT >
1165 struct Size< SMatSVecMultExpr<MT,VT> > : public Rows<MT>
1166 {};
1168 //*************************************************************************************************
1169 
1170 
1171 
1172 
1173 //=================================================================================================
1174 //
1175 // EXPRESSION TRAIT SPECIALIZATIONS
1176 //
1177 //=================================================================================================
1178 
1179 //*************************************************************************************************
1181 template< typename MT, typename VT, bool AF >
1182 struct SubvectorExprTrait< SMatSVecMultExpr<MT,VT>, AF >
1183 {
1184  public:
1185  //**********************************************************************************************
1186  typedef typename MultExprTrait< typename SubmatrixExprTrait<const MT,AF>::Type
1187  , typename SubvectorExprTrait<const VT,AF>::Type >::Type Type;
1188  //**********************************************************************************************
1189 };
1191 //*************************************************************************************************
1192 
1193 } // namespace blaze
1194 
1195 #endif
SelectType< IsExpression< VT >::value, const VT, const VT & >::Type RightOperand
Composite type of the right-hand side sparse vector expression.
Definition: SMatSVecMultExpr.h:147
#define BLAZE_THROW_INVALID_ARGUMENT(MESSAGE)
Macro for the emission of a std::invalid_argument exceptionThis macro encapsulates the default way of...
Definition: Exception.h:187
ReturnType at(size_t index) const
Checked access to the vector elements.
Definition: SMatSVecMultExpr.h:307
Compile time check whether the given type is a computational expression template.This type trait clas...
Definition: IsComputation.h:89
LeftOperand mat_
Left-hand side sparse matrix of the multiplication expression.
Definition: SMatSVecMultExpr.h:391
Header file for the Rows type trait.
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:7820
Header file for basic type definitions.
Header file for the SparseVector base class.
VT::CompositeType VCT
Composite type of the right-hand side sparse vector expression.
Definition: SMatSVecMultExpr.h:106
ResultType::ElementType ElementType
Resulting element type.
Definition: SMatSVecMultExpr.h:137
#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: ColumnVector.h:79
const ElementType ReturnType
Return type for expression template evaluations.
Definition: SMatSVecMultExpr.h:138
VT::ResultType VRT
Result type of the right-hand side sparse vector expression.
Definition: SMatSVecMultExpr.h:104
Efficient implementation of a compressed matrix.The CompressedMatrix class template is the represent...
Definition: CompressedMatrix.h:207
MultTrait< MRT, VRT >::Type ResultType
Result type for expression template evaluations.
Definition: SMatSVecMultExpr.h:135
void reset(const DiagonalProxy< MT > &proxy)
Resetting the represented element to the default initial values.
Definition: DiagonalProxy.h:507
const This & CompositeType
Data type for composite expression templates.
Definition: CompressedMatrix.h:2588
Type ElementType
Type of the sparse matrix elements.
Definition: CompressedMatrix.h:259
const DMatSerialExpr< MT, SO > serial(const DenseMatrix< MT, SO > &dm)
Forces the serial evaluation of the given dense matrix expression dm.
Definition: DMatSerialExpr.h:721
Header file for the Computation base class.
Constraints on the storage order of matrix types.
Header file for the RequiresEvaluation type trait.
bool canAlias(const T *alias) const
Returns whether the expression can alias with the given address alias.
Definition: SMatSVecMultExpr.h:362
SelectType< evaluateVector, const VRT, VCT >::Type RT
Type for the assignment of the right-hand side sparse vector operand.
Definition: SMatSVecMultExpr.h:153
Base class for sparse matrices.The SparseMatrix class is a base class for all sparse matrix classes...
Definition: Forward.h:117
bool isDefault(const DiagonalProxy< MT > &proxy)
Returns whether the represented element is in default state.
Definition: DiagonalProxy.h:547
size_t size() const
Returns the current size/dimension of the vector.
Definition: SMatSVecMultExpr.h:320
Constraint on the data type.
Constraint on the transpose flag of vector types.
Constraint on the data type.
size_t nonZeros() const
Returns an estimation for the number of non-zero elements in the sparse vector.
Definition: SMatSVecMultExpr.h:330
Header file for the MultExprTrait class template.
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:261
SelectType< evaluateMatrix, const MRT, MCT >::Type LT
Type for the assignment of the left-hand side sparse matrix operand.
Definition: SMatSVecMultExpr.h:150
Compile time type selection.The SelectType class template selects one of the two given types T1 and T...
Definition: SelectType.h:59
Header file for the DisableIf class template.
Header file for the multiplication trait.
Header file for the IsSymmetric type trait.
Namespace of the Blaze C++ math library.
Definition: Blaze.h:57
Expression object for sparse matrix-sparse vector multiplications.The SMatSVecMultExpr class represen...
Definition: Forward.h:109
const Element * ConstIterator
Iterator over constant elements.
Definition: CompressedMatrix.h:2592
Header file for the Or class template.
Header file for the IsMatMatMultExpr type trait class.
#define BLAZE_THROW_OUT_OF_RANGE(MESSAGE)
Macro for the emission of a std::out_of_range exceptionThis macro encapsulates the default way of Bla...
Definition: Exception.h:331
Base class for N-dimensional dense vectors.The DenseVector class is a base class for all arbitrarily ...
Definition: DenseVector.h:70
#define BLAZE_CONSTRAINT_MUST_BE_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
ReturnType operator[](size_t index) const
Subscript operator for the direct access to the vector elements.
Definition: SMatSVecMultExpr.h:182
#define BLAZE_CONSTRAINT_MUST_NOT_BE_MATMATMULTEXPR_TYPE(T)
Constraint on the data type.In case the given data type T is a matrix/matrix multiplication expressio...
Definition: MatMatMultExpr.h:126
#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
RightOperand rightOperand() const
Returns the right-hand side sparse vector operand.
Definition: SMatSVecMultExpr.h:350
#define BLAZE_CONSTRAINT_MUST_FORM_VALID_MATVECMULTEXPR(T1, T2)
Constraint on the data type.In case the given data types T1 and T2 do not form a valid matrix/vector ...
Definition: MatVecMultExpr.h:166
Header file for the SelectType class template.
Header file for all forward declarations for expression class templates.
Constraint on the data type.
SMatSVecMultExpr< MT, VT > This
Type of this SMatSVecMultExpr instance.
Definition: SMatSVecMultExpr.h:134
SMatSVecMultExpr(const MT &mat, const VT &vec)
Constructor for the SMatSVecMultExpr class.
Definition: SMatSVecMultExpr.h:168
Header file for the EnableIf class template.
MT::CompositeType MCT
Composite type of the left-hand side sparse matrix expression.
Definition: SMatSVecMultExpr.h:105
Header file for the serial shim.
ResultType::TransposeType TransposeType
Transpose type for expression template evaluations.
Definition: SMatSVecMultExpr.h:136
EnableIf< IsDenseMatrix< MT1 > >::Type smpSubAssign(Matrix< MT1, SO1 > &lhs, const Matrix< MT2, SO2 > &rhs)
Default implementation of the SMP subtraction assignment of a matrix to dense matrix.
Definition: DenseMatrix.h:160
RightOperand vec_
Right-hand side sparse vector of the multiplication expression.
Definition: SMatSVecMultExpr.h:392
#define BLAZE_CONSTRAINT_MUST_NOT_BE_SYMMETRIC_MATRIX_TYPE(T)
Constraint on the data type.In case the given data type T is a symmetric matrix type, a compilation error is created.
Definition: Symmetric.h:116
#define BLAZE_CONSTRAINT_MUST_BE_ROW_MAJOR_MATRIX_TYPE(T)
Constraint on the data type.In case the given data type T is not a row-major dense or sparse matrix t...
Definition: RowMajorMatrix.h:79
Removal of reference modifiers.The RemoveCV type trait removes any reference modifiers from the given...
Definition: RemoveReference.h:69
Header file for run time assertion macros.
EnableIf< IsDenseMatrix< MT1 > >::Type smpAssign(Matrix< MT1, SO1 > &lhs, const Matrix< MT2, SO2 > &rhs)
Default implementation of the SMP assignment of a matrix to a dense matrix.
Definition: DenseMatrix.h:98
Base template for the MultTrait class.
Definition: MultTrait.h:138
bool canSMPAssign() const
Returns whether the expression can be used in SMP assignments.
Definition: SMatSVecMultExpr.h:384
Header file for the reset shim.
Header file for the isDefault shim.
Constraint on the data type.
const ResultType CompositeType
Data type for composite expression templates.
Definition: SMatSVecMultExpr.h:141
Header file for the RemoveReference type trait.
LeftOperand leftOperand() const
Returns the left-hand side sparse matrix operand.
Definition: SMatSVecMultExpr.h:340
const DMatTransExpr< MT,!SO > trans(const DenseMatrix< MT, SO > &dm)
Calculation of the transpose of the given dense matrix.
Definition: DMatTransExpr.h:944
Header file for the IsComputation type trait class.
EnableIf< IsDenseMatrix< MT1 > >::Type smpAddAssign(Matrix< 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:129
MT::ResultType MRT
Result type of the left-hand side sparse matrix expression.
Definition: SMatSVecMultExpr.h:103
Base class for sparse vectors.The SparseVector class is a base class for all arbitrarily sized (N-dim...
Definition: Forward.h:118
#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:2583
BLAZE_ALWAYS_INLINE size_t columns(const Matrix< MT, SO > &matrix)
Returns the current number of columns of the matrix.
Definition: Matrix.h:324
Header file for the SubvectorExprTrait class template.
bool isAliased(const T *alias) const
Returns whether the expression is aliased with the given address alias.
Definition: SMatSVecMultExpr.h:374
Constraint on the data type.
Header file for exception macros.
Header file for the MatVecMultExpr base class.
Constraint on the data type.
EnableIf< IsDenseVector< VT1 > >::Type smpMultAssign(Vector< 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:189
Header file for the Size 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
#define BLAZE_CONSTRAINT_MUST_BE_SPARSE_MATRIX_TYPE(T)
Constraint on the data type.In case the given data type T is not a sparse, N-dimensional matrix type...
Definition: SparseMatrix.h:79
Header file for the IsExpression type trait class.
Header file for the FunctionTrace class.
SelectType< IsExpression< MT >::value, const MT, const MT & >::Type LeftOperand
Composite type of the left-hand side sparse matrix expression.
Definition: SMatSVecMultExpr.h:144