All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
TSVecTSMatMultExpr.h
Go to the documentation of this file.
1 //=================================================================================================
20 //=================================================================================================
21 
22 #ifndef _BLAZE_MATH_EXPRESSIONS_TSVECTSMATMULTEXPR_H_
23 #define _BLAZE_MATH_EXPRESSIONS_TSVECTSMATMULTEXPR_H_
24 
25 
26 //*************************************************************************************************
27 // Includes
28 //*************************************************************************************************
29 
30 #include <stdexcept>
31 #include <boost/type_traits/remove_reference.hpp>
40 #include <blaze/math/shims/Reset.h>
47 #include <blaze/util/Assert.h>
49 #include <blaze/util/DisableIf.h>
50 #include <blaze/util/SelectType.h>
51 #include <blaze/util/Types.h>
52 
53 
54 namespace blaze {
55 
56 //=================================================================================================
57 //
58 // CLASS TSVECTSMATMULTEXPR
59 //
60 //=================================================================================================
61 
62 //*************************************************************************************************
69 template< typename VT // Type of the left-hand side sparse vector
70  , typename MT > // Type of the right-hand side sparse matrix
71 class TSVecTSMatMultExpr : public SparseVector< TSVecTSMatMultExpr<VT,MT>, true >
72  , private Expression
73  , private Computation
74 {
75  private:
76  //**Type definitions****************************************************************************
77  typedef typename VT::ResultType VRT;
78  typedef typename MT::ResultType MRT;
79  typedef typename VT::CompositeType VCT;
80  typedef typename MT::CompositeType MCT;
81  //**********************************************************************************************
82 
83  public:
84  //**Type definitions****************************************************************************
87  typedef typename ResultType::TransposeType TransposeType;
88  typedef typename ResultType::ElementType ElementType;
89  typedef const ElementType ReturnType;
90  typedef const ResultType CompositeType;
91 
93  typedef typename SelectType< IsExpression<VT>::value, const VT, const VT& >::Type LeftOperand;
94 
96  typedef typename SelectType< IsExpression<MT>::value, const MT, const MT& >::Type RightOperand;
97 
99  typedef typename SelectType< IsComputation<VT>::value, const VRT, VCT >::Type LT;
100 
102  typedef MCT RT;
103  //**********************************************************************************************
104 
105  //**Compilation flags***************************************************************************
107  enum { canAlias = ( !IsComputation<VT>::value ) ||
109  //**********************************************************************************************
110 
111  //**Constructor*********************************************************************************
117  explicit inline TSVecTSMatMultExpr( const VT& vec, const MT& mat )
118  : vec_( vec ) // Left-hand side sparse vector of the multiplication expression
119  , mat_( mat ) // Right-hand side sparse matrix of the multiplication expression
120  {
121  BLAZE_INTERNAL_ASSERT( vec_.size() == mat_.rows(), "Invalid vector and matrix sizes" );
122  }
123  //**********************************************************************************************
124 
125  //**Subscript operator**************************************************************************
131  inline ReturnType operator[]( size_t index ) const {
132  BLAZE_INTERNAL_ASSERT( index < mat_.columns(), "Invalid vector access index" );
133 
134  typedef typename boost::remove_reference<VCT>::type::ConstIterator VectorIterator;
135  typedef typename boost::remove_reference<MCT>::type::ConstIterator MatrixIterator;
136 
137  VCT x( vec_ ); // Evaluation of the left-hand side sparse vector operand
138  MCT A( mat_ ); // Evaluation of the right-hand side sparse matrix operand
139 
140  BLAZE_INTERNAL_ASSERT( x.size() == vec_.size() , "Invalid vector size" );
141  BLAZE_INTERNAL_ASSERT( A.rows() == mat_.rows() , "Invalid number of rows" );
142  BLAZE_INTERNAL_ASSERT( A.columns() == mat_.columns(), "Invalid number of columns" );
143 
144  ElementType res = ElementType();
145 
146  VectorIterator velem( x.begin() );
147  const VectorIterator vend( x.end() );
148  if( velem == vend ) {
149  reset( res );
150  return res;
151  }
152 
153  MatrixIterator melem( A.begin(index) );
154  const MatrixIterator mend( A.end(index) );
155  if( melem == mend ) {
156  reset( res );
157  return res;
158  }
159 
160  while( true ) {
161  if( velem->index() < melem->index() ) {
162  ++velem;
163  if( velem == vend ) break;
164  }
165  else if( melem->index() < velem->index() ) {
166  ++melem;
167  if( melem == mend ) break;
168  }
169  else {
170  res = velem->value() * melem->value();
171  ++velem;
172  ++melem;
173  break;
174  }
175  }
176 
177  if( melem != mend && velem != vend )
178  {
179  while( true ) {
180  if( velem->index() < melem->index() ) {
181  ++velem;
182  if( velem == vend ) break;
183  }
184  else if( melem->index() < velem->index() ) {
185  ++melem;
186  if( melem == mend ) break;
187  }
188  else {
189  res += velem->value() * melem->value();
190  ++velem;
191  if( velem == vend ) break;
192  ++melem;
193  if( melem == mend ) break;
194  }
195  }
196  }
197 
198  return res;
199  }
200  //**********************************************************************************************
201 
202  //**Size function*******************************************************************************
207  inline size_t size() const {
208  return mat_.columns();
209  }
210  //**********************************************************************************************
211 
212  //**NonZeros function***************************************************************************
217  inline size_t nonZeros() const {
218  return mat_.columns();
219  }
220  //**********************************************************************************************
221 
222  //**Left operand access*************************************************************************
227  inline LeftOperand leftOperand() const {
228  return vec_;
229  }
230  //**********************************************************************************************
231 
232  //**Right operand access************************************************************************
237  inline RightOperand rightOperand() const {
238  return mat_;
239  }
240  //**********************************************************************************************
241 
242  //**********************************************************************************************
248  template< typename T >
249  inline bool isAliased( const T* alias ) const {
250  return ( !IsComputation<VT>::value && vec_.isAliased( alias ) ) ||
252  CanAlias<MT>::value && mat_.isAliased( alias ) );
253  }
254  //**********************************************************************************************
255 
256  private:
257  //**Member variables****************************************************************************
260  //**********************************************************************************************
261 
262  //**Assignment to dense vectors*****************************************************************
275  template< typename VT1 > // Type of the target dense vector
276  friend inline void assign( DenseVector<VT1,true>& lhs, const TSVecTSMatMultExpr& rhs )
277  {
278  BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
279 
280  typedef typename boost::remove_reference<LT>::type::ConstIterator VectorIterator;
281  typedef typename boost::remove_reference<RT>::type::ConstIterator MatrixIterator;
282 
283  // Resetting the left-hand side target dense vector
284  reset( ~lhs );
285 
286  // Evaluation of the left-hand side sparse vector operand
287  LT x( rhs.vec_ );
288  if( x.nonZeros() == 0UL ) return;
289 
290  // Evaluation of the right-hand side sparse matrix operand
291  RT A( rhs.mat_ );
292 
293  // Checking the evaluated operands
294  BLAZE_INTERNAL_ASSERT( x.size() == rhs.vec_.size() , "Invalid vector size" );
295  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.mat_.rows() , "Invalid number of rows" );
296  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.mat_.columns(), "Invalid number of columns" );
297  BLAZE_INTERNAL_ASSERT( A.columns() == (~lhs).size() , "Invalid vector size" );
298 
299  // Performing the sparse vector-sparse matrix multiplication
300  const VectorIterator vend( x.end() );
301 
302  for( size_t j=0UL; j<A.columns(); ++j )
303  {
304  const MatrixIterator mend ( A.end(j) );
305  MatrixIterator melem( A.begin(j) );
306 
307  if( melem == mend ) continue;
308 
309  VectorIterator velem( x.begin() );
310 
311  while( true ) {
312  if( velem->index() < melem->index() ) {
313  ++velem;
314  if( velem == vend ) break;
315  }
316  else if( melem->index() < velem->index() ) {
317  ++melem;
318  if( melem == mend ) break;
319  }
320  else {
321  (~lhs)[j] = velem->value() * melem->value();
322  ++velem;
323  ++melem;
324  break;
325  }
326  }
327 
328  if( velem != vend && melem != mend )
329  {
330  while( true ) {
331  if( velem->index() < melem->index() ) {
332  ++velem;
333  if( velem == vend ) break;
334  }
335  else if( melem->index() < velem->index() ) {
336  ++melem;
337  if( melem == mend ) break;
338  }
339  else {
340  (~lhs)[j] += velem->value() * melem->value();
341  ++velem;
342  if( velem == vend ) break;
343  ++melem;
344  if( melem == mend ) break;
345  }
346  }
347  }
348  }
349  }
351  //**********************************************************************************************
352 
353  //**Assignment to sparse vectors****************************************************************
366  template< typename VT1 > // Type of the target sparse vector
367  friend inline void assign( SparseVector<VT1,true>& lhs, const TSVecTSMatMultExpr& rhs )
368  {
369  BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
370 
371  typedef typename boost::remove_reference<LT>::type::ConstIterator VectorIterator;
372  typedef typename boost::remove_reference<RT>::type::ConstIterator MatrixIterator;
373 
374  // Evaluation of the left-hand side sparse vector operand
375  LT x( rhs.vec_ );
376  if( x.nonZeros() == 0UL ) return;
377 
378  // Evaluation of the right-hand side sparse matrix operand
379  RT A( rhs.mat_ );
380 
381  // Checking the evaluated operands
382  BLAZE_INTERNAL_ASSERT( x.size() == rhs.vec_.size() , "Invalid vector size" );
383  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.mat_.rows() , "Invalid number of rows" );
384  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.mat_.columns(), "Invalid number of columns" );
385  BLAZE_INTERNAL_ASSERT( A.columns() == (~lhs).size() , "Invalid vector size" );
386 
387  // Performing the sparse vector-sparse matrix multiplication
388  ElementType accu;
389  const VectorIterator vend( x.end() );
390 
391  for( size_t j=0UL; j<A.columns(); ++j )
392  {
393  const MatrixIterator mend ( A.end(j) );
394  MatrixIterator melem( A.begin(j) );
395 
396  if( melem == mend ) continue;
397 
398  VectorIterator velem( x.begin() );
399 
400  reset( accu );
401 
402  while( true ) {
403  if( velem->index() < melem->index() ) {
404  ++velem;
405  if( velem == vend ) break;
406  }
407  else if( melem->index() < velem->index() ) {
408  ++melem;
409  if( melem == mend ) break;
410  }
411  else {
412  accu = velem->value() * melem->value();
413  ++velem;
414  ++melem;
415  break;
416  }
417  }
418 
419  if( velem != vend && melem != mend )
420  {
421  while( true ) {
422  if( velem->index() < melem->index() ) {
423  ++velem;
424  if( velem == vend ) break;
425  }
426  else if( melem->index() < velem->index() ) {
427  ++melem;
428  if( melem == mend ) break;
429  }
430  else {
431  accu += velem->value() * melem->value();
432  ++velem;
433  if( velem == vend ) break;
434  ++melem;
435  if( melem == mend ) break;
436  }
437  }
438  }
439 
440  if( !isDefault( accu ) )
441  (~lhs).insert( j, accu );
442  }
443  }
445  //**********************************************************************************************
446 
447  //**Addition assignment to dense vectors********************************************************
460  template< typename VT1 > // Type of the target dense vector
461  friend inline void addAssign( DenseVector<VT1,true>& lhs, const TSVecTSMatMultExpr& rhs )
462  {
463  BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
464 
465  typedef typename boost::remove_reference<LT>::type::ConstIterator VectorIterator;
466  typedef typename boost::remove_reference<RT>::type::ConstIterator MatrixIterator;
467 
468  // Evaluation of the left-hand side sparse vector operand
469  LT x( rhs.vec_ );
470  if( x.nonZeros() == 0UL ) return;
471 
472  // Evaluation of the right-hand side sparse matrix operand
473  RT A( rhs.mat_ );
474 
475  // Checking the evaluated operands
476  BLAZE_INTERNAL_ASSERT( x.size() == rhs.vec_.size() , "Invalid vector size" );
477  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.mat_.rows() , "Invalid number of rows" );
478  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.mat_.columns(), "Invalid number of columns" );
479  BLAZE_INTERNAL_ASSERT( A.columns() == (~lhs).size() , "Invalid vector size" );
480 
481  // Performing the sparse matrix-sparse vector multiplication
482  const VectorIterator vend( x.end() );
483 
484  for( size_t j=0UL; j<A.columns(); ++j )
485  {
486  const MatrixIterator mend ( A.end(j) );
487  MatrixIterator melem( A.begin(j) );
488 
489  if( melem == mend ) continue;
490 
491  VectorIterator velem( x.begin() );
492 
493  while( true ) {
494  if( velem->index() < melem->index() ) {
495  ++velem;
496  if( velem == vend ) break;
497  }
498  else if( melem->index() < velem->index() ) {
499  ++melem;
500  if( melem == mend ) break;
501  }
502  else {
503  (~lhs)[j] += velem->value() * melem->value();
504  ++velem;
505  if( velem == vend ) break;
506  ++melem;
507  if( melem == mend ) break;
508  }
509  }
510  }
511  }
513  //**********************************************************************************************
514 
515  //**Addition assignment to sparse vectors*******************************************************
516  // No special implementation for the addition assignment to sparse vectors.
517  //**********************************************************************************************
518 
519  //**Subtraction assignment to dense vectors*****************************************************
532  template< typename VT1 > // Type of the target dense vector
533  friend inline void subAssign( DenseVector<VT1,true>& lhs, const TSVecTSMatMultExpr& rhs )
534  {
535  BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
536 
537  typedef typename boost::remove_reference<LT>::type::ConstIterator VectorIterator;
538  typedef typename boost::remove_reference<RT>::type::ConstIterator MatrixIterator;
539 
540  // Evaluation of the left-hand side sparse vector operand
541  LT x( rhs.vec_ );
542  if( x.nonZeros() == 0UL ) return;
543 
544  // Evaluation of the right-hand side sparse matrix operand
545  RT A( rhs.mat_ );
546 
547  // Checking the evaluated operands
548  BLAZE_INTERNAL_ASSERT( x.size() == rhs.vec_.size() , "Invalid vector size" );
549  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.mat_.rows() , "Invalid number of rows" );
550  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.mat_.columns(), "Invalid number of columns" );
551  BLAZE_INTERNAL_ASSERT( A.columns() == (~lhs).size() , "Invalid vector size" );
552 
553  // Performing the sparse matrix-sparse vector multiplication
554  const VectorIterator vend( x.end() );
555 
556  for( size_t j=0UL; j<A.columns(); ++j )
557  {
558  const MatrixIterator mend ( A.end(j) );
559  MatrixIterator melem( A.begin(j) );
560 
561  if( melem == mend ) continue;
562 
563  VectorIterator velem( x.begin() );
564 
565  while( true ) {
566  if( velem->index() < melem->index() ) {
567  ++velem;
568  if( velem == vend ) break;
569  }
570  else if( melem->index() < velem->index() ) {
571  ++melem;
572  if( melem == mend ) break;
573  }
574  else {
575  (~lhs)[j] -= velem->value() * melem->value();
576  ++velem;
577  if( velem == vend ) break;
578  ++melem;
579  if( melem == mend ) break;
580  }
581  }
582  }
583  }
585  //**********************************************************************************************
586 
587  //**Subtraction assignment to sparse vectors****************************************************
588  // No special implementation for the subtraction assignment to sparse vectors.
589  //**********************************************************************************************
590 
591  //**Multiplication assignment to dense vectors**************************************************
604  template< typename VT1 > // Type of the target dense vector
605  friend inline void multAssign( DenseVector<VT1,true>& lhs, const TSVecTSMatMultExpr& rhs )
606  {
609  BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( typename ResultType::CompositeType );
610 
611  BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
612 
613  const ResultType tmp( rhs );
614  multAssign( ~lhs, tmp );
615  }
617  //**********************************************************************************************
618 
619  //**Multiplication assignment to sparse vectors*************************************************
620  // No special implementation for the multiplication assignment to sparse vectors.
621  //**********************************************************************************************
622 
623  //**Compile time checks*************************************************************************
630  //**********************************************************************************************
631 };
632 //*************************************************************************************************
633 
634 
635 
636 
637 //=================================================================================================
638 //
639 // GLOBAL BINARY ARITHMETIC OPERATORS
640 //
641 //=================================================================================================
642 
643 //*************************************************************************************************
674 template< typename T1 // Type of the left-hand side sparse vector
675  , typename T2 > // Type of the right-hand side sparse matrix
676 inline const typename DisableIf< IsMatMatMultExpr<T2>, TSVecTSMatMultExpr<T1,T2> >::Type
678 {
679  if( (~vec).size() != (~mat).rows() )
680  throw std::invalid_argument( "Vector and matrix sizes do not match" );
681 
682  return TSVecTSMatMultExpr<T1,T2>( ~vec, ~mat );
683 }
684 //*************************************************************************************************
685 
686 } // namespace blaze
687 
688 #endif