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>
41 #include <blaze/math/shims/Reset.h>
47 #include <blaze/util/Assert.h>
49 #include <blaze/util/DisableIf.h>
51 #include <blaze/util/SelectType.h>
52 #include <blaze/util/Types.h>
53 
54 
55 namespace blaze {
56 
57 //=================================================================================================
58 //
59 // CLASS TSVECTSMATMULTEXPR
60 //
61 //=================================================================================================
62 
63 //*************************************************************************************************
70 template< typename VT // Type of the left-hand side sparse vector
71  , typename MT > // Type of the right-hand side sparse matrix
72 class TSVecTSMatMultExpr : public SparseVector< TSVecTSMatMultExpr<VT,MT>, true >
73  , private Expression
74  , private Computation
75 {
76  private:
77  //**Type definitions****************************************************************************
78  typedef typename VT::ResultType VRT;
79  typedef typename MT::ResultType MRT;
80  typedef typename VT::CompositeType VCT;
81  typedef typename MT::CompositeType MCT;
82  //**********************************************************************************************
83 
84  public:
85  //**Type definitions****************************************************************************
88  typedef typename ResultType::TransposeType TransposeType;
89  typedef typename ResultType::ElementType ElementType;
90  typedef const ElementType ReturnType;
91  typedef const ResultType CompositeType;
92 
94  typedef typename SelectType< IsExpression<VT>::value, const VT, const VT& >::Type LeftOperand;
95 
97  typedef typename SelectType< IsExpression<MT>::value, const MT, const MT& >::Type RightOperand;
98 
100  typedef typename SelectType< IsComputation<VT>::value, const VRT, VCT >::Type LT;
101 
103  typedef MCT RT;
104  //**********************************************************************************************
105 
106  //**Constructor*********************************************************************************
112  explicit inline TSVecTSMatMultExpr( const VT& vec, const MT& mat )
113  : vec_( vec ) // Left-hand side sparse vector of the multiplication expression
114  , mat_( mat ) // Right-hand side sparse matrix of the multiplication expression
115  {
116  BLAZE_INTERNAL_ASSERT( vec_.size() == mat_.rows(), "Invalid vector and matrix sizes" );
117  }
118  //**********************************************************************************************
119 
120  //**Subscript operator**************************************************************************
126  inline ReturnType operator[]( size_t index ) const {
127  BLAZE_INTERNAL_ASSERT( index < mat_.columns(), "Invalid vector access index" );
128 
129  typedef typename boost::remove_reference<VCT>::type::ConstIterator VectorIterator;
130  typedef typename boost::remove_reference<MCT>::type::ConstIterator MatrixIterator;
131 
132  VCT x( vec_ ); // Evaluation of the left-hand side sparse vector operand
133  MCT A( mat_ ); // Evaluation of the right-hand side sparse matrix operand
134 
135  BLAZE_INTERNAL_ASSERT( x.size() == vec_.size() , "Invalid vector size" );
136  BLAZE_INTERNAL_ASSERT( A.rows() == mat_.rows() , "Invalid number of rows" );
137  BLAZE_INTERNAL_ASSERT( A.columns() == mat_.columns(), "Invalid number of columns" );
138 
139  ElementType res = ElementType();
140 
141  VectorIterator velem( x.begin() );
142  const VectorIterator vend( x.end() );
143  if( velem == vend ) {
144  reset( res );
145  return res;
146  }
147 
148  MatrixIterator melem( A.begin(index) );
149  const MatrixIterator mend( A.end(index) );
150  if( melem == mend ) {
151  reset( res );
152  return res;
153  }
154 
155  while( true ) {
156  if( velem->index() < melem->index() ) {
157  ++velem;
158  if( velem == vend ) break;
159  }
160  else if( melem->index() < velem->index() ) {
161  ++melem;
162  if( melem == mend ) break;
163  }
164  else {
165  res = velem->value() * melem->value();
166  ++velem;
167  ++melem;
168  break;
169  }
170  }
171 
172  if( melem != mend && velem != vend )
173  {
174  while( true ) {
175  if( velem->index() < melem->index() ) {
176  ++velem;
177  if( velem == vend ) break;
178  }
179  else if( melem->index() < velem->index() ) {
180  ++melem;
181  if( melem == mend ) break;
182  }
183  else {
184  res += velem->value() * melem->value();
185  ++velem;
186  if( velem == vend ) break;
187  ++melem;
188  if( melem == mend ) break;
189  }
190  }
191  }
192 
193  return res;
194  }
195  //**********************************************************************************************
196 
197  //**Size function*******************************************************************************
202  inline size_t size() const {
203  return mat_.columns();
204  }
205  //**********************************************************************************************
206 
207  //**NonZeros function***************************************************************************
212  inline size_t nonZeros() const {
213  return mat_.columns();
214  }
215  //**********************************************************************************************
216 
217  //**Left operand access*************************************************************************
222  inline LeftOperand leftOperand() const {
223  return vec_;
224  }
225  //**********************************************************************************************
226 
227  //**Right operand access************************************************************************
232  inline RightOperand rightOperand() const {
233  return mat_;
234  }
235  //**********************************************************************************************
236 
237  //**********************************************************************************************
243  template< typename T >
244  inline bool canAlias( const T* alias ) const {
245  return ( vec_.isAliased( alias ) || mat_.isAliased( alias ) );
246  }
247  //**********************************************************************************************
248 
249  //**********************************************************************************************
255  template< typename T >
256  inline bool isAliased( const T* alias ) const {
257  return ( vec_.isAliased( alias ) || mat_.isAliased( alias ) );
258  }
259  //**********************************************************************************************
260 
261  private:
262  //**Member variables****************************************************************************
265  //**********************************************************************************************
266 
267  //**Assignment to dense vectors*****************************************************************
280  template< typename VT1 > // Type of the target dense vector
281  friend inline void assign( DenseVector<VT1,true>& lhs, const TSVecTSMatMultExpr& rhs )
282  {
284 
285  BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
286 
287  typedef typename boost::remove_reference<LT>::type::ConstIterator VectorIterator;
288  typedef typename boost::remove_reference<RT>::type::ConstIterator MatrixIterator;
289 
290  // Resetting the left-hand side target dense vector
291  reset( ~lhs );
292 
293  // Evaluation of the left-hand side sparse vector operand
294  LT x( rhs.vec_ );
295  if( x.nonZeros() == 0UL ) return;
296 
297  // Evaluation of the right-hand side sparse matrix operand
298  RT A( rhs.mat_ );
299 
300  // Checking the evaluated operands
301  BLAZE_INTERNAL_ASSERT( x.size() == rhs.vec_.size() , "Invalid vector size" );
302  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.mat_.rows() , "Invalid number of rows" );
303  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.mat_.columns(), "Invalid number of columns" );
304  BLAZE_INTERNAL_ASSERT( A.columns() == (~lhs).size() , "Invalid vector size" );
305 
306  // Performing the sparse vector-sparse matrix multiplication
307  const VectorIterator vend( x.end() );
308 
309  for( size_t j=0UL; j<A.columns(); ++j )
310  {
311  const MatrixIterator mend ( A.end(j) );
312  MatrixIterator melem( A.begin(j) );
313 
314  if( melem == mend ) continue;
315 
316  VectorIterator velem( x.begin() );
317 
318  while( true ) {
319  if( velem->index() < melem->index() ) {
320  ++velem;
321  if( velem == vend ) break;
322  }
323  else if( melem->index() < velem->index() ) {
324  ++melem;
325  if( melem == mend ) break;
326  }
327  else {
328  (~lhs)[j] = velem->value() * melem->value();
329  ++velem;
330  ++melem;
331  break;
332  }
333  }
334 
335  if( velem != vend && melem != mend )
336  {
337  while( true ) {
338  if( velem->index() < melem->index() ) {
339  ++velem;
340  if( velem == vend ) break;
341  }
342  else if( melem->index() < velem->index() ) {
343  ++melem;
344  if( melem == mend ) break;
345  }
346  else {
347  (~lhs)[j] += velem->value() * melem->value();
348  ++velem;
349  if( velem == vend ) break;
350  ++melem;
351  if( melem == mend ) break;
352  }
353  }
354  }
355  }
356  }
358  //**********************************************************************************************
359 
360  //**Assignment to sparse vectors****************************************************************
373  template< typename VT1 > // Type of the target sparse vector
374  friend inline void assign( SparseVector<VT1,true>& lhs, const TSVecTSMatMultExpr& rhs )
375  {
377 
378  BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
379 
380  typedef typename boost::remove_reference<LT>::type::ConstIterator VectorIterator;
381  typedef typename boost::remove_reference<RT>::type::ConstIterator MatrixIterator;
382 
383  // Evaluation of the left-hand side sparse vector operand
384  LT x( rhs.vec_ );
385  if( x.nonZeros() == 0UL ) return;
386 
387  // Evaluation of the right-hand side sparse matrix operand
388  RT A( rhs.mat_ );
389 
390  // Checking the evaluated operands
391  BLAZE_INTERNAL_ASSERT( x.size() == rhs.vec_.size() , "Invalid vector size" );
392  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.mat_.rows() , "Invalid number of rows" );
393  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.mat_.columns(), "Invalid number of columns" );
394  BLAZE_INTERNAL_ASSERT( A.columns() == (~lhs).size() , "Invalid vector size" );
395 
396  // Performing the sparse vector-sparse matrix multiplication
397  ElementType accu;
398  const VectorIterator vend( x.end() );
399 
400  for( size_t j=0UL; j<A.columns(); ++j )
401  {
402  const MatrixIterator mend ( A.end(j) );
403  MatrixIterator melem( A.begin(j) );
404 
405  if( melem == mend ) continue;
406 
407  VectorIterator velem( x.begin() );
408 
409  reset( accu );
410 
411  while( true ) {
412  if( velem->index() < melem->index() ) {
413  ++velem;
414  if( velem == vend ) break;
415  }
416  else if( melem->index() < velem->index() ) {
417  ++melem;
418  if( melem == mend ) break;
419  }
420  else {
421  accu = velem->value() * melem->value();
422  ++velem;
423  ++melem;
424  break;
425  }
426  }
427 
428  if( velem != vend && melem != mend )
429  {
430  while( true ) {
431  if( velem->index() < melem->index() ) {
432  ++velem;
433  if( velem == vend ) break;
434  }
435  else if( melem->index() < velem->index() ) {
436  ++melem;
437  if( melem == mend ) break;
438  }
439  else {
440  accu += velem->value() * melem->value();
441  ++velem;
442  if( velem == vend ) break;
443  ++melem;
444  if( melem == mend ) break;
445  }
446  }
447  }
448 
449  if( !isDefault( accu ) )
450  (~lhs).insert( j, accu );
451  }
452  }
454  //**********************************************************************************************
455 
456  //**Addition assignment to dense vectors********************************************************
469  template< typename VT1 > // Type of the target dense vector
470  friend inline void addAssign( DenseVector<VT1,true>& lhs, const TSVecTSMatMultExpr& rhs )
471  {
473 
474  BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
475 
476  typedef typename boost::remove_reference<LT>::type::ConstIterator VectorIterator;
477  typedef typename boost::remove_reference<RT>::type::ConstIterator MatrixIterator;
478 
479  // Evaluation of the left-hand side sparse vector operand
480  LT x( rhs.vec_ );
481  if( x.nonZeros() == 0UL ) return;
482 
483  // Evaluation of the right-hand side sparse matrix operand
484  RT A( rhs.mat_ );
485 
486  // Checking the evaluated operands
487  BLAZE_INTERNAL_ASSERT( x.size() == rhs.vec_.size() , "Invalid vector size" );
488  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.mat_.rows() , "Invalid number of rows" );
489  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.mat_.columns(), "Invalid number of columns" );
490  BLAZE_INTERNAL_ASSERT( A.columns() == (~lhs).size() , "Invalid vector size" );
491 
492  // Performing the sparse matrix-sparse vector multiplication
493  const VectorIterator vend( x.end() );
494 
495  for( size_t j=0UL; j<A.columns(); ++j )
496  {
497  const MatrixIterator mend ( A.end(j) );
498  MatrixIterator melem( A.begin(j) );
499 
500  if( melem == mend ) continue;
501 
502  VectorIterator velem( x.begin() );
503 
504  while( true ) {
505  if( velem->index() < melem->index() ) {
506  ++velem;
507  if( velem == vend ) break;
508  }
509  else if( melem->index() < velem->index() ) {
510  ++melem;
511  if( melem == mend ) break;
512  }
513  else {
514  (~lhs)[j] += velem->value() * melem->value();
515  ++velem;
516  if( velem == vend ) break;
517  ++melem;
518  if( melem == mend ) break;
519  }
520  }
521  }
522  }
524  //**********************************************************************************************
525 
526  //**Addition assignment to sparse vectors*******************************************************
527  // No special implementation for the addition assignment to sparse vectors.
528  //**********************************************************************************************
529 
530  //**Subtraction assignment to dense vectors*****************************************************
543  template< typename VT1 > // Type of the target dense vector
544  friend inline void subAssign( DenseVector<VT1,true>& lhs, const TSVecTSMatMultExpr& rhs )
545  {
547 
548  BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
549 
550  typedef typename boost::remove_reference<LT>::type::ConstIterator VectorIterator;
551  typedef typename boost::remove_reference<RT>::type::ConstIterator MatrixIterator;
552 
553  // Evaluation of the left-hand side sparse vector operand
554  LT x( rhs.vec_ );
555  if( x.nonZeros() == 0UL ) return;
556 
557  // Evaluation of the right-hand side sparse matrix operand
558  RT A( rhs.mat_ );
559 
560  // Checking the evaluated operands
561  BLAZE_INTERNAL_ASSERT( x.size() == rhs.vec_.size() , "Invalid vector size" );
562  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.mat_.rows() , "Invalid number of rows" );
563  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.mat_.columns(), "Invalid number of columns" );
564  BLAZE_INTERNAL_ASSERT( A.columns() == (~lhs).size() , "Invalid vector size" );
565 
566  // Performing the sparse matrix-sparse vector multiplication
567  const VectorIterator vend( x.end() );
568 
569  for( size_t j=0UL; j<A.columns(); ++j )
570  {
571  const MatrixIterator mend ( A.end(j) );
572  MatrixIterator melem( A.begin(j) );
573 
574  if( melem == mend ) continue;
575 
576  VectorIterator velem( x.begin() );
577 
578  while( true ) {
579  if( velem->index() < melem->index() ) {
580  ++velem;
581  if( velem == vend ) break;
582  }
583  else if( melem->index() < velem->index() ) {
584  ++melem;
585  if( melem == mend ) break;
586  }
587  else {
588  (~lhs)[j] -= velem->value() * melem->value();
589  ++velem;
590  if( velem == vend ) break;
591  ++melem;
592  if( melem == mend ) break;
593  }
594  }
595  }
596  }
598  //**********************************************************************************************
599 
600  //**Subtraction assignment to sparse vectors****************************************************
601  // No special implementation for the subtraction assignment to sparse vectors.
602  //**********************************************************************************************
603 
604  //**Multiplication assignment to dense vectors**************************************************
617  template< typename VT1 > // Type of the target dense vector
618  friend inline void multAssign( DenseVector<VT1,true>& lhs, const TSVecTSMatMultExpr& rhs )
619  {
621 
624  BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( typename ResultType::CompositeType );
625 
626  BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
627 
628  const ResultType tmp( rhs );
629  multAssign( ~lhs, tmp );
630  }
632  //**********************************************************************************************
633 
634  //**Multiplication assignment to sparse vectors*************************************************
635  // No special implementation for the multiplication assignment to sparse vectors.
636  //**********************************************************************************************
637 
638  //**Compile time checks*************************************************************************
645  //**********************************************************************************************
646 };
647 //*************************************************************************************************
648 
649 
650 
651 
652 //=================================================================================================
653 //
654 // GLOBAL BINARY ARITHMETIC OPERATORS
655 //
656 //=================================================================================================
657 
658 //*************************************************************************************************
689 template< typename T1 // Type of the left-hand side sparse vector
690  , typename T2 > // Type of the right-hand side sparse matrix
691 inline const typename DisableIf< IsMatMatMultExpr<T2>, TSVecTSMatMultExpr<T1,T2> >::Type
693 {
695 
696  if( (~vec).size() != (~mat).rows() )
697  throw std::invalid_argument( "Vector and matrix sizes do not match" );
698 
699  return TSVecTSMatMultExpr<T1,T2>( ~vec, ~mat );
700 }
701 //*************************************************************************************************
702 
703 } // namespace blaze
704 
705 #endif