All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
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 
43 #include <stdexcept>
53 #include <blaze/math/shims/Reset.h>
63 #include <blaze/util/Assert.h>
65 #include <blaze/util/DisableIf.h>
66 #include <blaze/util/EnableIf.h>
68 #include <blaze/util/SelectType.h>
69 #include <blaze/util/Types.h>
71 
72 
73 namespace blaze {
74 
75 //=================================================================================================
76 //
77 // CLASS SMATDVECMULTEXPR
78 //
79 //=================================================================================================
80 
81 //*************************************************************************************************
88 template< typename MT // Type of the left-hand side sparse matrix
89  , typename VT > // Type of the right-hand side sparse vector
90 class SMatSVecMultExpr : public SparseVector< SMatSVecMultExpr<MT,VT>, false >
91  , private MatVecMultExpr
92  , private Computation
93 {
94  private:
95  //**Type definitions****************************************************************************
96  typedef typename MT::ResultType MRT;
97  typedef typename VT::ResultType VRT;
98  typedef typename MT::CompositeType MCT;
99  typedef typename VT::CompositeType VCT;
100  //**********************************************************************************************
101 
102  //**********************************************************************************************
104  enum { evaluateMatrix = RequiresEvaluation<MT>::value };
105  //**********************************************************************************************
106 
107  //**********************************************************************************************
109  enum { evaluateVector = RequiresEvaluation<VT>::value || IsComputation<VT>::value };
110  //**********************************************************************************************
111 
112  //**********************************************************************************************
114 
118  template< typename T1 >
119  struct UseSMPAssign {
120  enum { value = ( evaluateMatrix || evaluateVector ) };
121  };
123  //**********************************************************************************************
124 
125  public:
126  //**Type definitions****************************************************************************
131  typedef const ElementType ReturnType;
132 
134  typedef const ResultType CompositeType;
135 
137  typedef typename SelectType< IsExpression<MT>::value, const MT, const MT& >::Type LeftOperand;
138 
140  typedef typename SelectType< IsExpression<VT>::value, const VT, const VT& >::Type RightOperand;
141 
144 
147  //**********************************************************************************************
148 
149  //**Compilation flags***************************************************************************
151  enum { smpAssignable = !evaluateMatrix && MT::smpAssignable &&
152  !evaluateVector && VT::smpAssignable };
153  //**********************************************************************************************
154 
155  //**Constructor*********************************************************************************
161  explicit inline SMatSVecMultExpr( const MT& mat, const VT& vec )
162  : mat_( mat ) // Left-hand side sparse matrix of the multiplication expression
163  , vec_( vec ) // Right-hand side sparse vector of the multiplication expression
164  {
165  BLAZE_INTERNAL_ASSERT( mat_.columns() == vec_.size(), "Invalid matrix and vector sizes" );
166  }
167  //**********************************************************************************************
168 
169  //**Subscript operator**************************************************************************
175  inline ReturnType operator[]( size_t index ) const {
176  BLAZE_INTERNAL_ASSERT( index < mat_.rows(), "Invalid vector access index" );
177 
178  typedef typename RemoveReference<MCT>::Type::ConstIterator MatrixIterator;
179  typedef typename RemoveReference<VCT>::Type::ConstIterator VectorIterator;
180 
181  ElementType res = ElementType();
182 
183  // Early exit
184  if( vec_.size() == 0UL )
185  return res;
186 
187  // Fast computation in case both the left-hand side matrix operand and the right-hand
188  // side vector operand directly provide iterators
190  {
191  MCT A( mat_ ); // Evaluation of the left-hand side sparse matrix operand
192  VCT x( vec_ ); // Evaluation of the right-hand side sparse vector operand
193 
194  MatrixIterator melem( A.begin(index) );
195  const MatrixIterator mend( A.end(index) );
196  if( melem == mend ) {
197  return res;
198  }
199 
200  VectorIterator velem( x.begin() );
201  const VectorIterator vend( x.end() );
202  if( velem == vend ) {
203  return res;
204  }
205 
206  while( true ) {
207  if( melem->index() < velem->index() ) {
208  ++melem;
209  if( melem == mend ) break;
210  }
211  else if( velem->index() < melem->index() ) {
212  ++velem;
213  if( velem == vend ) break;
214  }
215  else {
216  res = melem->value() * velem->value();
217  ++melem;
218  ++velem;
219  break;
220  }
221  }
222 
223  if( melem != mend && velem != vend )
224  {
225  while( true ) {
226  if( melem->index() < velem->index() ) {
227  ++melem;
228  if( melem == mend ) break;
229  }
230  else if( velem->index() < melem->index() ) {
231  ++velem;
232  if( velem == vend ) break;
233  }
234  else {
235  res += melem->value() * velem->value();
236  ++melem;
237  if( melem == mend ) break;
238  ++velem;
239  if( velem == vend ) break;
240  }
241  }
242  }
243  }
244 
245  // Optimized computation in case the left-hand side matrix operand directly provides iterators
247  {
248  MCT A( mat_ ); // Evaluation of the left-hand side sparse matrix operand
249 
250  MatrixIterator melem( A.begin(index) );
251  const MatrixIterator mend( A.end(index) );
252 
253  if( melem == mend )
254  return res;
255 
256  res = melem->value() * vec_[melem->index()];
257  ++melem;
258  for( ; melem!=mend; ++melem ) {
259  res += melem->value() * vec_[melem->index()];
260  }
261  }
262 
263  // Optimized computation in case the right-hand side vector operand directly provides iterators
265  {
266  VCT x( vec_ ); // Evaluation of the right-hand side sparse vector operand
267 
268  VectorIterator velem( x.begin() );
269  const VectorIterator vend( x.end() );
270 
271  if( velem == vend )
272  return res;
273 
274  res = mat_(index,velem->index()) * velem->value();
275  ++velem;
276  for( ; velem!=vend; ++velem ) {
277  res += mat_(index,velem->index()) * velem->value();
278  }
279  }
280 
281  // Default computation in case both operands don't provide iterators
282  else {
283  res = mat_(index,0UL) * vec_[0UL];
284  for( size_t j=1UL; j<vec_.size(); ++j ) {
285  res += mat_(index,j) * vec_[j];
286  }
287  }
288 
289  return res;
290  }
291  //**********************************************************************************************
292 
293  //**Size function*******************************************************************************
298  inline size_t size() const {
299  return mat_.rows();
300  }
301  //**********************************************************************************************
302 
303  //**NonZeros function***************************************************************************
308  inline size_t nonZeros() const {
309  return mat_.rows();
310  }
311  //**********************************************************************************************
312 
313  //**Left operand access*************************************************************************
318  inline LeftOperand leftOperand() const {
319  return mat_;
320  }
321  //**********************************************************************************************
322 
323  //**Right operand access************************************************************************
328  inline RightOperand rightOperand() const {
329  return vec_;
330  }
331  //**********************************************************************************************
332 
333  //**********************************************************************************************
339  template< typename T >
340  inline bool canAlias( const T* alias ) const {
341  return ( mat_.isAliased( alias ) || vec_.isAliased( alias ) );
342  }
343  //**********************************************************************************************
344 
345  //**********************************************************************************************
351  template< typename T >
352  inline bool isAliased( const T* alias ) const {
353  return ( mat_.isAliased( alias ) || vec_.isAliased( alias ) );
354  }
355  //**********************************************************************************************
356 
357  //**********************************************************************************************
362  inline bool canSMPAssign() const {
363  return ( size() > SMP_SMATSVECMULT_THRESHOLD );
364  }
365  //**********************************************************************************************
366 
367  private:
368  //**Member variables****************************************************************************
371  //**********************************************************************************************
372 
373  //**Assignment to dense vectors*****************************************************************
385  template< typename VT1 > // Type of the target dense vector
386  friend inline void assign( DenseVector<VT1,false>& lhs, const SMatSVecMultExpr& rhs )
387  {
389 
390  BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
391 
392  // Resetting the left-hand side target dense vector
393  reset( ~lhs );
394 
395  // Evaluation of the right-hand side sparse vector operand
396  RT x( serial( rhs.vec_ ) );
397  if( x.nonZeros() == 0UL ) return;
398 
399  // Evaluation of the left-hand side sparse matrix operand
400  LT A( serial( rhs.mat_ ) );
401 
402  // Checking the evaluated operators
403  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.mat_.rows() , "Invalid number of rows" );
404  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.mat_.columns(), "Invalid number of columns" );
405  BLAZE_INTERNAL_ASSERT( x.size() == rhs.vec_.size() , "Invalid vector size" );
406  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).size() , "Invalid vector size" );
407 
408  // Performing the sparse matrix-sparse vector multiplication
409  SMatSVecMultExpr::selectAssignKernel( ~lhs, A, x );
410  }
412  //**********************************************************************************************
413 
414  //**Default assignment to dense vectors*********************************************************
428  template< typename VT1 // Type of the left-hand side target vector
429  , typename MT1 // Type of the left-hand side matrix operand
430  , typename VT2 > // Type of the right-hand side vector operand
431  static inline void selectAssignKernel( VT1& y, const MT1& A, const VT2& x )
432  {
433  typedef typename RemoveReference<LT>::Type::ConstIterator MatrixIterator;
434  typedef typename RemoveReference<RT>::Type::ConstIterator VectorIterator;
435 
436  const VectorIterator vend( x.end() );
437 
438  for( size_t i=0UL; i<y.size(); ++i )
439  {
440  const MatrixIterator mend ( A.end(i) );
441  MatrixIterator melem( A.begin(i) );
442 
443  if( melem == mend ) continue;
444 
445  VectorIterator velem( x.begin() );
446 
447  while( true ) {
448  if( melem->index() < velem->index() ) {
449  ++melem;
450  if( melem == mend ) break;
451  }
452  else if( velem->index() < melem->index() ) {
453  ++velem;
454  if( velem == vend ) break;
455  }
456  else {
457  y[i] = melem->value() * velem->value();
458  ++melem;
459  ++velem;
460  break;
461  }
462  }
463 
464  if( melem != mend && velem != vend )
465  {
466  while( true ) {
467  if( melem->index() < velem->index() ) {
468  ++melem;
469  if( melem == mend ) break;
470  }
471  else if( velem->index() < melem->index() ) {
472  ++velem;
473  if( velem == vend ) break;
474  }
475  else {
476  y[i] += melem->value() * velem->value();
477  ++melem;
478  if( melem == mend ) break;
479  ++velem;
480  if( velem == vend ) break;
481  }
482  }
483  }
484  }
485  }
487  //**********************************************************************************************
488 
489  //**Assignment to sparse vectors****************************************************************
501  template< typename VT1 > // Type of the target sparse vector
502  friend inline void assign( SparseVector<VT1,false>& lhs, const SMatSVecMultExpr& rhs )
503  {
505 
506  BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
507 
508  typedef typename RemoveReference<LT>::Type::ConstIterator MatrixIterator;
509  typedef typename RemoveReference<RT>::Type::ConstIterator VectorIterator;
510 
511  RT x( rhs.vec_ ); // Evaluation of the right-hand side sparse vector operand
512  if( x.nonZeros() == 0UL ) return;
513 
514  LT A( rhs.mat_ ); // Evaluation of the left-hand side sparse matrix operand
515 
516  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.mat_.rows() , "Invalid number of rows" );
517  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.mat_.columns(), "Invalid number of columns" );
518  BLAZE_INTERNAL_ASSERT( x.size() == rhs.vec_.size() , "Invalid vector size" );
519  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).size() , "Invalid vector size" );
520 
521  ElementType accu;
522  const VectorIterator vend( x.end() );
523 
524  for( size_t i=0UL; i<(~lhs).size(); ++i )
525  {
526  const MatrixIterator mend ( A.end(i) );
527  MatrixIterator melem( A.begin(i) );
528 
529  if( melem == mend ) continue;
530 
531  VectorIterator velem( x.begin() );
532 
533  reset( accu );
534 
535  while( true ) {
536  if( melem->index() < velem->index() ) {
537  ++melem;
538  if( melem == mend ) break;
539  }
540  else if( velem->index() < melem->index() ) {
541  ++velem;
542  if( velem == vend ) break;
543  }
544  else {
545  accu = melem->value() * velem->value();
546  ++melem;
547  ++velem;
548  break;
549  }
550  }
551 
552  if( melem != mend && velem != vend )
553  {
554  while( true ) {
555  if( melem->index() < velem->index() ) {
556  ++melem;
557  if( melem == mend ) break;
558  }
559  else if( velem->index() < melem->index() ) {
560  ++velem;
561  if( velem == vend ) break;
562  }
563  else {
564  accu += melem->value() * velem->value();
565  ++melem;
566  if( melem == mend ) break;
567  ++velem;
568  if( velem == vend ) break;
569  }
570  }
571  }
572 
573  if( !isDefault( accu ) )
574  (~lhs).insert( i, accu );
575  }
576  }
578  //**********************************************************************************************
579 
580  //**Addition assignment to dense vectors********************************************************
592  template< typename VT1 > // Type of the target dense vector
593  friend inline void addAssign( DenseVector<VT1,false>& lhs, const SMatSVecMultExpr& rhs )
594  {
596 
597  BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
598 
599  // Evaluation of the right-hand side sparse vector operand
600  RT x( serial( rhs.vec_ ) );
601  if( x.nonZeros() == 0UL ) return;
602 
603  // Evaluation of the left-hand side sparse matrix operand
604  LT A( serial( rhs.mat_ ) );
605 
606  // Checking the evaluated operators
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( x.size() == rhs.vec_.size() , "Invalid vector size" );
610  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).size() , "Invalid vector size" );
611 
612  // Performing the sparse matrix-sparse vector multiplication
613  SMatSVecMultExpr::selectAddAssignKernel( ~lhs, A, x );
614  }
616  //**********************************************************************************************
617 
618  //**Default addition assignment to dense vectors************************************************
632  template< typename VT1 // Type of the left-hand side target vector
633  , typename MT1 // Type of the left-hand side matrix operand
634  , typename VT2 > // Type of the right-hand side vector operand
635  static inline void selectAddAssignKernel( VT1& y, const MT1& A, const VT2& x )
636  {
637  typedef typename RemoveReference<LT>::Type::ConstIterator MatrixIterator;
638  typedef typename RemoveReference<RT>::Type::ConstIterator VectorIterator;
639 
640  const VectorIterator vend( x.end() );
641 
642  for( size_t i=0UL; i<y.size(); ++i )
643  {
644  const MatrixIterator mend ( A.end(i) );
645  MatrixIterator melem( A.begin(i) );
646 
647  if( melem == mend ) continue;
648 
649  VectorIterator velem( x.begin() );
650 
651  while( true ) {
652  if( melem->index() < velem->index() ) {
653  ++melem;
654  if( melem == mend ) break;
655  }
656  else if( velem->index() < melem->index() ) {
657  ++velem;
658  if( velem == vend ) break;
659  }
660  else {
661  y[i] += melem->value() * velem->value();
662  ++melem;
663  if( melem == mend ) break;
664  ++velem;
665  if( velem == vend ) break;
666  }
667  }
668  }
669  }
671  //**********************************************************************************************
672 
673  //**Addition assignment to sparse vectors*******************************************************
674  // No special implementation for the addition assignment to sparse vectors.
675  //**********************************************************************************************
676 
677  //**Subtraction assignment to dense vectors*****************************************************
689  template< typename VT1 > // Type of the target dense vector
690  friend inline void subAssign( DenseVector<VT1,false>& lhs, const SMatSVecMultExpr& rhs )
691  {
693 
694  BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
695 
696  typedef typename RemoveReference<LT>::Type::ConstIterator MatrixIterator;
697  typedef typename RemoveReference<RT>::Type::ConstIterator VectorIterator;
698 
699  // Evaluation of the right-hand side sparse vector operand
700  RT x( serial( rhs.vec_ ) );
701  if( x.nonZeros() == 0UL ) return;
702 
703  // Evaluation of the left-hand side sparse matrix operand
704  LT A( serial( rhs.mat_ ) );
705 
706  // Checking the evaluated operators
707  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.mat_.rows() , "Invalid number of rows" );
708  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.mat_.columns(), "Invalid number of columns" );
709  BLAZE_INTERNAL_ASSERT( x.size() == rhs.vec_.size() , "Invalid vector size" );
710  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).size() , "Invalid vector size" );
711 
712  // Performing the sparse matrix-sparse vector multiplication
713  SMatSVecMultExpr::selectSubAssignKernel( ~lhs, A, x );
714  }
716  //**********************************************************************************************
717 
718  //**Default subtraction assignment to dense vectors*********************************************
732  template< typename VT1 // Type of the left-hand side target vector
733  , typename MT1 // Type of the left-hand side matrix operand
734  , typename VT2 > // Type of the right-hand side vector operand
735  static inline void selectSubAssignKernel( VT1& y, const MT1& A, const VT2& x )
736  {
737  typedef typename RemoveReference<LT>::Type::ConstIterator MatrixIterator;
738  typedef typename RemoveReference<RT>::Type::ConstIterator VectorIterator;
739 
740  const VectorIterator vend( x.end() );
741 
742  for( size_t i=0UL; i<y.size(); ++i )
743  {
744  const MatrixIterator mend ( A.end(i) );
745  MatrixIterator melem( A.begin(i) );
746 
747  if( melem == mend ) continue;
748 
749  VectorIterator velem( x.begin() );
750 
751  while( true ) {
752  if( melem->index() < velem->index() ) {
753  ++melem;
754  if( melem == mend ) break;
755  }
756  else if( velem->index() < melem->index() ) {
757  ++velem;
758  if( velem == vend ) break;
759  }
760  else {
761  y[i] -= melem->value() * velem->value();
762  ++melem;
763  if( melem == mend ) break;
764  ++velem;
765  if( velem == vend ) break;
766  }
767  }
768  }
769  }
771  //**********************************************************************************************
772 
773  //**Subtraction assignment to sparse vectors****************************************************
774  // No special implementation for the subtraction assignment to sparse vectors.
775  //**********************************************************************************************
776 
777  //**Multiplication assignment to dense vectors**************************************************
789  template< typename VT1 > // Type of the target dense vector
790  friend inline void multAssign( DenseVector<VT1,false>& lhs, const SMatSVecMultExpr& rhs )
791  {
793 
797 
798  BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
799 
800  const ResultType tmp( serial( rhs ) );
801  multAssign( ~lhs, tmp );
802  }
804  //**********************************************************************************************
805 
806  //**Multiplication assignment to sparse vectors*************************************************
807  // No special implementation for the multiplication assignment to sparse vectors.
808  //**********************************************************************************************
809 
810  //**SMP assignment to dense vectors*************************************************************
824  template< typename VT1 > // Type of the target dense vector
825  friend inline typename EnableIf< UseSMPAssign<VT1> >::Type
826  smpAssign( DenseVector<VT1,false>& lhs, const SMatSVecMultExpr& rhs )
827  {
829 
830  BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
831 
832  // Resetting the left-hand side target dense vector
833  reset( ~lhs );
834 
835  // Evaluation of the right-hand side sparse vector operand
836  RT x( rhs.vec_ );
837  if( x.nonZeros() == 0UL ) return;
838 
839  // Evaluation of the left-hand side sparse matrix operand
840  LT A( rhs.mat_ );
841 
842  // Checking the evaluated operators
843  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.mat_.rows() , "Invalid number of rows" );
844  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.mat_.columns(), "Invalid number of columns" );
845  BLAZE_INTERNAL_ASSERT( x.size() == rhs.vec_.size() , "Invalid vector size" );
846  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).size() , "Invalid vector size" );
847 
848  // Performing the sparse matrix-sparse vector multiplication
849  smpAssign( ~lhs, A * x );
850  }
852  //**********************************************************************************************
853 
854  //**SMP assignment to sparse vectors************************************************************
855  // No special implementation for the SMP assignment to sparse vectors.
856  //**********************************************************************************************
857 
858  //**SMP addition assignment to dense vectors****************************************************
873  template< typename VT1 > // Type of the target dense vector
874  friend inline typename EnableIf< UseSMPAssign<VT1> >::Type
875  smpAddAssign( DenseVector<VT1,false>& lhs, const SMatSVecMultExpr& rhs )
876  {
878 
879  BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
880 
881  // Evaluation of the right-hand side sparse vector operand
882  RT x( rhs.vec_ );
883  if( x.nonZeros() == 0UL ) return;
884 
885  // Evaluation of the left-hand side sparse matrix operand
886  LT A( rhs.mat_ );
887 
888  // Checking the evaluated operators
889  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.mat_.rows() , "Invalid number of rows" );
890  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.mat_.columns(), "Invalid number of columns" );
891  BLAZE_INTERNAL_ASSERT( x.size() == rhs.vec_.size() , "Invalid vector size" );
892  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).size() , "Invalid vector size" );
893 
894  // Performing the sparse matrix-sparse vector multiplication
895  smpAddAssign( ~lhs, A * x );
896  }
898  //**********************************************************************************************
899 
900  //**SMP addition assignment to sparse vectors***************************************************
901  // No special implementation for the SMP addition assignment to sparse vectors.
902  //**********************************************************************************************
903 
904  //**SMP subtraction assignment to dense vectors*************************************************
919  template< typename VT1 > // Type of the target dense vector
920  friend inline typename EnableIf< UseSMPAssign<VT1> >::Type
921  smpSubAssign( DenseVector<VT1,false>& lhs, const SMatSVecMultExpr& rhs )
922  {
924 
925  BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
926 
927  typedef typename RemoveReference<LT>::Type::ConstIterator MatrixIterator;
928  typedef typename RemoveReference<RT>::Type::ConstIterator VectorIterator;
929 
930  // Evaluation of the right-hand side sparse vector operand
931  RT x( rhs.vec_ );
932  if( x.nonZeros() == 0UL ) return;
933 
934  // Evaluation of the left-hand side sparse matrix operand
935  LT A( rhs.mat_ );
936 
937  // Checking the evaluated operators
938  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.mat_.rows() , "Invalid number of rows" );
939  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.mat_.columns(), "Invalid number of columns" );
940  BLAZE_INTERNAL_ASSERT( x.size() == rhs.vec_.size() , "Invalid vector size" );
941  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).size() , "Invalid vector size" );
942 
943  // Performing the sparse matrix-sparse vector multiplication
944  smpSubAssign( ~lhs, A * x );
945  }
947  //**********************************************************************************************
948 
949  //**SMP subtraction assignment to sparse vectors************************************************
950  // No special implementation for the SMP subtraction assignment to sparse vectors.
951  //**********************************************************************************************
952 
953  //**SMP multiplication assignment to dense vectors**********************************************
968  template< typename VT1 > // Type of the target dense vector
969  friend inline typename EnableIf< UseSMPAssign<VT1> >::Type
970  smpMultAssign( DenseVector<VT1,false>& lhs, const SMatSVecMultExpr& rhs )
971  {
973 
977 
978  BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
979 
980  const ResultType tmp( rhs );
981  smpMultAssign( ~lhs, tmp );
982  }
984  //**********************************************************************************************
985 
986  //**SMP multiplication assignment to sparse vectors*********************************************
987  // No special implementation for the SMP multiplication assignment to sparse vectors.
988  //**********************************************************************************************
989 
990  //**Compile time checks*************************************************************************
997  //**********************************************************************************************
998 };
999 //*************************************************************************************************
1000 
1001 
1002 
1003 
1004 //=================================================================================================
1005 //
1006 // GLOBAL BINARY ARITHMETIC OPERATORS
1007 //
1008 //=================================================================================================
1009 
1010 //*************************************************************************************************
1041 template< typename T1 // Type of the left-hand side sparse matrix
1042  , typename T2 > // Type of the right-hand side sparse vector
1043 inline const typename DisableIf< IsMatMatMultExpr<T1>, SMatSVecMultExpr<T1,T2> >::Type
1045 {
1047 
1048  if( (~mat).columns() != (~vec).size() )
1049  throw std::invalid_argument( "Matrix and vector sizes do not match" );
1050 
1051  return SMatSVecMultExpr<T1,T2>( ~mat, ~vec );
1052 }
1053 //*************************************************************************************************
1054 
1055 
1056 
1057 
1058 //=================================================================================================
1059 //
1060 // GLOBAL RESTRUCTURING BINARY ARITHMETIC OPERATORS
1061 //
1062 //=================================================================================================
1063 
1064 //*************************************************************************************************
1077 template< typename T1 // Type of the left-hand side sparse matrix
1078  , bool SO // Storage order of the left-hand side sparse matrix
1079  , typename T2 > // Type of the right-hand side sparse vector
1080 inline const typename EnableIf< IsMatMatMultExpr<T1>, MultExprTrait<T1,T2> >::Type::Type
1082 {
1084 
1085  return (~mat).leftOperand() * ( (~mat).rightOperand() * vec );
1086 }
1087 //*************************************************************************************************
1088 
1089 
1090 
1091 
1092 //=================================================================================================
1093 //
1094 // EXPRESSION TRAIT SPECIALIZATIONS
1095 //
1096 //=================================================================================================
1097 
1098 //*************************************************************************************************
1100 template< typename MT, typename VT, bool AF >
1101 struct SubvectorExprTrait< SMatSVecMultExpr<MT,VT>, AF >
1102 {
1103  public:
1104  //**********************************************************************************************
1105  typedef typename MultExprTrait< typename SubmatrixExprTrait<const MT,AF>::Type, VT >::Type Type;
1106  //**********************************************************************************************
1107 };
1109 //*************************************************************************************************
1110 
1111 } // namespace blaze
1112 
1113 #endif
RightOperand vec_
Right-hand side sparse vector of the multiplication expression.
Definition: SMatSVecMultExpr.h:370
SelectType< evaluateMatrix, const MRT, MCT >::Type LT
Type for the assignment of the left-hand side sparse matrix operand.
Definition: SMatSVecMultExpr.h:143
const size_t SMP_SMATSVECMULT_THRESHOLD
SMP row-major sparse matrix/sparse vector multiplication threshold.This threshold specifies when a ro...
Definition: Thresholds.h:598
Compile time check whether the given type is a computational expression template.This type trait clas...
Definition: IsComputation.h:89
SMatSVecMultExpr(const MT &mat, const VT &vec)
Constructor for the SMatSVecMultExpr class.
Definition: SMatSVecMultExpr.h:161
void reset(DynamicMatrix< Type, SO > &m)
Resetting the given dense matrix.
Definition: DynamicMatrix.h:4599
const DMatDMatMultExpr< T1, T2 > operator*(const DenseMatrix< T1, false > &lhs, const DenseMatrix< T2, false > &rhs)
Multiplication operator for the multiplication of two row-major dense matrices ( ).
Definition: DMatDMatMultExpr.h:4329
Header file for the SparseVector base class.
ReturnType operator[](size_t index) const
Subscript operator for the direct access to the vector elements.
Definition: SMatSVecMultExpr.h:175
bool canAlias(const T *alias) const
Returns whether the expression can alias with the given address alias.
Definition: SMatSVecMultExpr.h:340
void smpSubAssign(DenseMatrix< MT1, SO1 > &lhs, const Matrix< MT2, SO2 > &rhs)
Default implementation of the SMP subtraction assignment of a matrix to dense matrix.
Definition: DenseMatrix.h:152
#define BLAZE_CONSTRAINT_MUST_BE_COLUMN_VECTOR_TYPE(T)
Constraint on the data type.In case the given data type T is not a column dense or sparse vector type...
Definition: TransposeFlag.h:159
bool isDefault(const DynamicMatrix< Type, SO > &m)
Returns whether the given dense matrix is in default state.
Definition: DynamicMatrix.h:4642
Efficient implementation of a compressed matrix.The CompressedMatrix class template is the represent...
Definition: CompressedMatrix.h:199
void smpMultAssign(DenseVector< VT1, TF1 > &lhs, const Vector< VT2, TF2 > &rhs)
Default implementation of the SMP multiplication assignment of a vector to a dense vector...
Definition: DenseVector.h:179
const This & CompositeType
Data type for composite expression templates.
Definition: CompressedMatrix.h:2408
Type ElementType
Type of the sparse matrix elements.
Definition: CompressedMatrix.h:251
SelectType< IsExpression< VT >::value, const VT, const VT & >::Type RightOperand
Composite type of the right-hand side sparse vector expression.
Definition: SMatSVecMultExpr.h:140
const ResultType CompositeType
Data type for composite expression templates.
Definition: SMatSVecMultExpr.h:134
ResultType::TransposeType TransposeType
Transpose type for expression template evaluations.
Definition: SMatSVecMultExpr.h:129
const DMatSerialExpr< MT, SO > serial(const DenseMatrix< MT, SO > &dm)
Forces the serial evaluation of the given dense matrix expression dm.
Definition: DMatSerialExpr.h:690
Header file for the Computation base class.
Header file for the RequiresEvaluation type trait.
Base class for sparse matrices.The SparseMatrix class is a base class for all sparse matrix classes...
Definition: Forward.h:107
Constraint on the data type.
size_t size() const
Returns the current size/dimension of the vector.
Definition: SMatSVecMultExpr.h:298
const ElementType ReturnType
Return type for expression template evaluations.
Definition: SMatSVecMultExpr.h:131
Constraint on the data type.
Header file for the MultExprTrait class template.
void smpAddAssign(DenseMatrix< MT1, SO1 > &lhs, const Matrix< MT2, SO2 > &rhs)
Default implementation of the SMP addition assignment of a matrix to a dense matrix.
Definition: DenseMatrix.h:122
Compile time check to query the requirement to evaluate an expression.Via this type trait it is possi...
Definition: RequiresEvaluation.h:90
const This & CompositeType
Data type for composite expression templates.
Definition: CompressedMatrix.h:253
Compile time type selection.The SelectType class template selects one of the two given types T1 and T...
Definition: SelectType.h:59
Header file for the DisableIf class template.
Header file for the multiplication trait.
Expression object for sparse matrix-sparse vector multiplications.The SMatSVecMultExpr class represen...
Definition: Forward.h:99
const Element * ConstIterator
Iterator over constant elements.
Definition: CompressedMatrix.h:2412
Header file for the IsMatMatMultExpr type trait class.
SelectType< IsExpression< MT >::value, const MT, const MT & >::Type LeftOperand
Composite type of the left-hand side sparse matrix expression.
Definition: SMatSVecMultExpr.h:137
MultTrait< MRT, VRT >::Type ResultType
Result type for expression template evaluations.
Definition: SMatSVecMultExpr.h:128
void assign(Matrix< MT1, SO1 > &lhs, const Matrix< MT2, SO2 > &rhs)
Default implementation of the assignment of a matrix to a matrix.
Definition: Matrix.h:271
MT::CompositeType MCT
Composite type of the left-hand side sparse matrix expression.
Definition: SMatSVecMultExpr.h:98
VT::CompositeType VCT
Composite type of the right-hand side sparse vector expression.
Definition: SMatSVecMultExpr.h:99
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
Constraint on the data type.
#define BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE(T)
Constraint on the data type.In case the given data type T is not a reference type, a compilation error is created.
Definition: Reference.h:78
Constraints on the storage order of matrix types.
void multAssign(Matrix< MT1, SO1 > &lhs, const Matrix< MT2, SO2 > &rhs)
Default implementation of the multiplication assignment of a matrix to a matrix.
Definition: Matrix.h:361
Header file for the SelectType class template.
Header file for all forward declarations for expression class templates.
Constraint on the data type.
ResultType::ElementType ElementType
Resulting element type.
Definition: SMatSVecMultExpr.h:130
Header file for the EnableIf class template.
Header file for the serial shim.
bool isAliased(const T *alias) const
Returns whether the expression is aliased with the given address alias.
Definition: SMatSVecMultExpr.h:352
void smpAssign(DenseMatrix< MT1, SO1 > &lhs, const Matrix< MT2, SO2 > &rhs)
Default implementation of the SMP assignment of a matrix to a dense matrix.
Definition: DenseMatrix.h:92
SMatSVecMultExpr< MT, VT > This
Type of this SMatSVecMultExpr instance.
Definition: SMatSVecMultExpr.h:127
#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: StorageOrder.h:81
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.
Base template for the MultTrait class.
Definition: MultTrait.h:141
void addAssign(Matrix< MT1, SO1 > &lhs, const Matrix< MT2, SO2 > &rhs)
Default implementation of the addition assignment of a matrix to a matrix.
Definition: Matrix.h:301
RightOperand rightOperand() const
Returns the right-hand side sparse vector operand.
Definition: SMatSVecMultExpr.h:328
Header file for the reset shim.
void subAssign(Matrix< MT1, SO1 > &lhs, const Matrix< MT2, SO2 > &rhs)
Default implementation of the subtraction assignment of a matrix to matrix.
Definition: Matrix.h:331
Header file for the isDefault shim.
MT::ResultType MRT
Result type of the left-hand side sparse matrix expression.
Definition: SMatSVecMultExpr.h:96
Header file for the RemoveReference type trait.
size_t nonZeros() const
Returns an estimation for the number of non-zero elements in the sparse vector.
Definition: SMatSVecMultExpr.h:308
Header file for the IsComputation type trait class.
VT::ResultType VRT
Result type of the right-hand side sparse vector expression.
Definition: SMatSVecMultExpr.h:97
Base class for sparse vectors.The SparseVector class is a base class for all arbitrarily sized (N-dim...
Definition: Forward.h:108
#define BLAZE_FUNCTION_TRACE
Function trace macro.This macro can be used to reliably trace function calls. In case function tracin...
Definition: FunctionTrace.h:157
This ResultType
Result type for expression template evaluations.
Definition: CompressedMatrix.h:2403
size_t columns(const Matrix< MT, SO > &m)
Returns the current number of columns of the matrix.
Definition: Matrix.h:170
bool canSMPAssign() const
Returns whether the expression can be used in SMP assignments.
Definition: SMatSVecMultExpr.h:362
Header file for basic type definitions.
Header file for the SubvectorExprTrait class template.
LeftOperand mat_
Left-hand side sparse matrix of the multiplication expression.
Definition: SMatSVecMultExpr.h:369
Header file for the MatVecMultExpr base class.
SelectType< evaluateVector, const VRT, VCT >::Type RT
Type for the assignment of the right-hand side sparse vector operand.
Definition: SMatSVecMultExpr.h:146
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.
LeftOperand leftOperand() const
Returns the left-hand side sparse matrix operand.
Definition: SMatSVecMultExpr.h:318
Header file for the FunctionTrace class.