All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
TDMatTSMatMultExpr.h
Go to the documentation of this file.
1 //=================================================================================================
20 //=================================================================================================
21 
22 #ifndef _BLAZE_MATH_EXPRESSIONS_TDMATTSMATMULTEXPR_H_
23 #define _BLAZE_MATH_EXPRESSIONS_TDMATTSMATMULTEXPR_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>
59 #include <blaze/util/Assert.h>
61 #include <blaze/util/DisableIf.h>
62 #include <blaze/util/EnableIf.h>
63 #include <blaze/util/InvalidType.h>
64 #include <blaze/util/SelectType.h>
65 #include <blaze/util/Types.h>
66 
67 
68 namespace blaze {
69 
70 //=================================================================================================
71 //
72 // CLASS TDMATTSMATMULTEXPR
73 //
74 //=================================================================================================
75 
76 //*************************************************************************************************
83 template< typename MT1 // Type of the left-hand side dense matrix
84  , typename MT2 > // Type of the right-hand side sparse matrix
85 class TDMatTSMatMultExpr : public DenseMatrix< TDMatTSMatMultExpr<MT1,MT2>, true >
86  , private Expression
87  , private Computation
88 {
89  private:
90  //**Type definitions****************************************************************************
91  typedef typename MT1::ResultType RT1;
92  typedef typename MT2::ResultType RT2;
93  typedef typename MT1::ElementType ET1;
94  typedef typename MT2::ElementType ET2;
95  typedef typename MT1::CompositeType CT1;
96  typedef typename MT2::CompositeType CT2;
97  //**********************************************************************************************
98 
99  public:
100  //**Type definitions****************************************************************************
103  typedef typename ResultType::OppositeType OppositeType;
104  typedef typename ResultType::TransposeType TransposeType;
105  typedef typename ResultType::ElementType ElementType;
106  typedef const ElementType ReturnType;
107  typedef const ResultType CompositeType;
108 
110  typedef typename SelectType< IsExpression<MT1>::value, const MT1, const MT1& >::Type LeftOperand;
111 
113  typedef typename SelectType< IsExpression<MT2>::value, const MT2, const MT2& >::Type RightOperand;
114 
116  typedef typename SelectType< IsComputation<MT1>::value, const RT1, CT1 >::Type LT;
117 
119  typedef typename SelectType< IsComputation<MT2>::value, const RT2, CT2 >::Type RT;
120  //**********************************************************************************************
121 
122  //**Compilation flags***************************************************************************
124  enum { vectorizable = 0 };
125 
127  enum { canAlias = !IsComputation<MT1>::value };
128  //**********************************************************************************************
129 
130  //**Constructor*********************************************************************************
136  explicit inline TDMatTSMatMultExpr( const MT1& lhs, const MT2& rhs )
137  : lhs_( lhs ) // Left-hand side dense matrix of the multiplication expression
138  , rhs_( rhs ) // Right-hand side sparse matrix of the multiplication expression
139  {
140  BLAZE_INTERNAL_ASSERT( lhs.columns() == rhs.rows(), "Invalid matrix sizes" );
141  }
142  //**********************************************************************************************
143 
144  //**Access operator*****************************************************************************
151  inline ReturnType operator()( size_t i, size_t j ) const {
152  BLAZE_INTERNAL_ASSERT( i < lhs_.rows() , "Invalid row access index" );
153  BLAZE_INTERNAL_ASSERT( j < rhs_.columns(), "Invalid column access index" );
154 
155  typedef typename boost::remove_reference<CT2>::type::ConstIterator ConstIterator;
156 
157  ElementType tmp = ElementType();
158 
159  // Early exit
160  if( lhs_.columns() == 0UL )
161  return tmp;
162 
163  // Fast computation in case the right-hand side sparse matrix directly provides iterators
165  {
166  CT2 B( rhs_ ); // Evaluation of the right-hand side sparse matrix operand
167 
168  const ConstIterator end( B.end(j) );
169  ConstIterator element( B.begin(j) );
170 
171  // Early exit in case column j is empty
172  if( element == end )
173  return tmp;
174 
175  // Calculating element (i,j)
176  tmp = lhs_(i,element->index()) * element->value();
177  ++element;
178  for( ; element!=end; ++element )
179  tmp += lhs_(i,element->index()) * element->value();
180  }
181 
182  // Default computation in case the right-hand side sparse matrix doesn't provide iterators
183  else {
184  tmp = lhs_(i,0UL) * rhs_(0UL,j);
185  for( size_t k=1UL; k<lhs_.columns(); ++k ) {
186  tmp += lhs_(i,k) * rhs_(k,j);
187  }
188  }
189 
190  return tmp;
191  }
192  //**********************************************************************************************
193 
194  //**Rows function*******************************************************************************
199  inline size_t rows() const {
200  return lhs_.rows();
201  }
202  //**********************************************************************************************
203 
204  //**Columns function****************************************************************************
209  inline size_t columns() const {
210  return rhs_.columns();
211  }
212  //**********************************************************************************************
213 
214  //**Left operand access*************************************************************************
219  inline LeftOperand leftOperand() const {
220  return lhs_;
221  }
222  //**********************************************************************************************
223 
224  //**Right operand access************************************************************************
229  inline RightOperand rightOperand() const {
230  return rhs_;
231  }
232  //**********************************************************************************************
233 
234  //**********************************************************************************************
240  template< typename T >
241  inline bool isAliased( const T* alias ) const {
242  return ( !IsComputation<MT1>::value && lhs_.isAliased( alias ) );
243  }
244  //**********************************************************************************************
245 
246  private:
247  //**Member variables****************************************************************************
250  //**********************************************************************************************
251 
252  //**Default assignment to row-major dense matrices**********************************************
266  template< typename MT > // Type of the target dense matrix
267  friend inline typename EnableIf< IsResizable<typename MT::ElementType> >::Type
269  {
270  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
271  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
272 
273  typedef typename boost::remove_reference<RT>::type::ConstIterator ConstIterator;
274 
275  LT A( rhs.lhs_ ); // Evaluation of the left-hand side dense matrix operand
276  RT B( rhs.rhs_ ); // Evaluation of the right-hand side sparse matrix operand
277 
278  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
279  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
280  BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
281  BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
282  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
283  BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
284 
285  for( size_t i=0UL; i<A.rows(); ++i ) {
286  for( size_t j=0UL; j<B.columns(); ++j )
287  {
288  ConstIterator element( B.begin(j) );
289  const ConstIterator end( B.end(j) );
290 
291  if( element == end ) {
292  reset( (~lhs)(i,j) );
293  continue;
294  }
295 
296  (~lhs)(i,j) = A(i,element->index()) * element->value();
297  ++element;
298  for( ; element!=end; ++element )
299  (~lhs)(i,j) += A(i,element->index()) * element->value();
300  }
301  }
302  }
304  //**********************************************************************************************
305 
306  //**Default assignment to column-major dense matrices*******************************************
320  template< typename MT > // Type of the target dense matrix
321  friend inline typename EnableIf< IsResizable<typename MT::ElementType> >::Type
323  {
324  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
325  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
326 
327  typedef typename boost::remove_reference<RT>::type::ConstIterator ConstIterator;
328 
329  LT A( rhs.lhs_ ); // Evaluation of the left-hand side dense matrix operand
330  RT B( rhs.rhs_ ); // Evaluation of the right-hand side sparse matrix operand
331 
332  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
333  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
334  BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
335  BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
336  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
337  BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
338 
339  for( size_t j=0UL; j<B.columns(); ++j ) {
340  for( size_t i=0UL; i<(~lhs).rows(); ++i ) {
341  reset( (~lhs)(i,j) );
342  }
343  ConstIterator element( B.begin(j) );
344  const ConstIterator end( B.end(j) );
345  for( ; element!=end; ++element ) {
346  for( size_t i=0UL; i<A.rows(); ++i ) {
347  if( isDefault( (~lhs)(element->index(),j) ) )
348  (~lhs)(i,j) = A(i,element->index()) * element->value();
349  else
350  (~lhs)(i,j) += A(i,element->index()) * element->value();
351  }
352  }
353  }
354  }
356  //**********************************************************************************************
357 
358  //**Optimized assignment to row-major dense matrices********************************************
372  template< typename MT > // Type of the target dense matrix
373  friend inline typename DisableIf< IsResizable<typename MT::ElementType> >::Type
374  assign( DenseMatrix<MT,false>& lhs, const TDMatTSMatMultExpr& rhs )
375  {
376  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
377  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
378 
379  typedef typename boost::remove_reference<RT>::type::ConstIterator ConstIterator;
380 
381  LT A( rhs.lhs_ ); // Evaluation of the left-hand side dense matrix operand
382  RT B( rhs.rhs_ ); // Evaluation of the right-hand side sparse matrix operand
383 
384  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
385  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
386  BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
387  BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
388  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
389  BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
390 
391  BLAZE_INTERNAL_ASSERT( ( A.rows() - ( A.rows() % 4UL ) ) == ( A.rows() & size_t(-4) ), "Invalid end calculation" );
392  const size_t iend( A.rows() & size_t(-4) );
393 
394  for( size_t i=0UL; i<iend; i+=4UL ) {
395  for( size_t j=0UL; j<B.columns(); ++j )
396  {
397  ConstIterator element( B.begin(j) );
398  const ConstIterator end( B.end(j) );
399 
400  if( element == end ) {
401  reset( (~lhs)(i ,j) );
402  reset( (~lhs)(i+1UL,j) );
403  reset( (~lhs)(i+2UL,j) );
404  reset( (~lhs)(i+3UL,j) );
405  continue;
406  }
407 
408  (~lhs)(i ,j) = A(i ,element->index()) * element->value();
409  (~lhs)(i+1UL,j) = A(i+1UL,element->index()) * element->value();
410  (~lhs)(i+2UL,j) = A(i+2UL,element->index()) * element->value();
411  (~lhs)(i+3UL,j) = A(i+3UL,element->index()) * element->value();
412  ++element;
413  for( ; element!=end; ++element ) {
414  (~lhs)(i ,j) += A(i ,element->index()) * element->value();
415  (~lhs)(i+1UL,j) += A(i+1UL,element->index()) * element->value();
416  (~lhs)(i+2UL,j) += A(i+2UL,element->index()) * element->value();
417  (~lhs)(i+3UL,j) += A(i+3UL,element->index()) * element->value();
418  }
419  }
420  }
421 
422  for( size_t i=iend; i<A.rows(); ++i ) {
423  for( size_t j=0UL; j<B.columns(); ++j )
424  {
425  ConstIterator element( B.begin(j) );
426  const ConstIterator end( B.end(j) );
427 
428  if( element == end ) {
429  reset( (~lhs)(i,j) );
430  continue;
431  }
432 
433  (~lhs)(i,j) = A(i,element->index()) * element->value();
434  ++element;
435  for( ; element!=end; ++element )
436  (~lhs)(i,j) += A(i,element->index()) * element->value();
437  }
438  }
439  }
441  //**********************************************************************************************
442 
443  //**Optimized assignment to column-major dense matrices*****************************************
457  template< typename MT > // Type of the target dense matrix
458  friend inline typename DisableIf< IsResizable<typename MT::ElementType> >::Type
459  assign( DenseMatrix<MT,true>& lhs, const TDMatTSMatMultExpr& rhs )
460  {
461  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
462  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
463 
464  typedef typename boost::remove_reference<RT>::type::ConstIterator ConstIterator;
465 
466  LT A( rhs.lhs_ ); // Evaluation of the left-hand side dense matrix operand
467  RT B( rhs.rhs_ ); // Evaluation of the right-hand side sparse matrix operand
468 
469  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
470  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
471  BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
472  BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
473  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
474  BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
475 
476  BLAZE_INTERNAL_ASSERT( ( A.rows() - ( A.rows() % 4UL ) ) == ( A.rows() & size_t(-4) ), "Invalid end calculation" );
477  const size_t iend( A.rows() & size_t(-4) );
478 
479  for( size_t j=0UL; j<B.columns(); ++j ) {
480  for( size_t i=0UL; i<iend; i+=4UL ) {
481  reset( (~lhs)(i ,j) );
482  reset( (~lhs)(i+1UL,j) );
483  reset( (~lhs)(i+2UL,j) );
484  reset( (~lhs)(i+3UL,j) );
485  }
486  for( size_t i=iend; i<(~lhs).rows(); ++i ) {
487  reset( (~lhs)(i,j) );
488  }
489  ConstIterator element( B.begin(j) );
490  const ConstIterator end( B.end(j) );
491 
492  while( element!=end )
493  {
494  const ET2 v1( element->value() );
495  const size_t i1( element->index() );
496  ++element;
497 
498  if( element != end ) {
499  const ET2 v2( element->value() );
500  const size_t i2( element->index() );
501  ++element;
502 
503  if( element != end ) {
504  const ET2 v3( element->value() );
505  const size_t i3( element->index() );
506  ++element;
507 
508  if( element != end ) {
509  const ET2 v4( element->value() );
510  const size_t i4( element->index() );
511  ++element;
512 
513  for( size_t i=0UL; i<iend; i+=4UL ) {
514  (~lhs)(i ,j) += A(i ,i1) * v1 + A(i ,i2) * v2 + A(i ,i3) * v3 + A(i ,i4) * v4;
515  (~lhs)(i+1UL,j) += A(i+1UL,i1) * v1 + A(i+1UL,i2) * v2 + A(i+1UL,i3) * v3 + A(i+1UL,i4) * v4;
516  (~lhs)(i+2UL,j) += A(i+2UL,i1) * v1 + A(i+2UL,i2) * v2 + A(i+2UL,i3) * v3 + A(i+2UL,i4) * v4;
517  (~lhs)(i+3UL,j) += A(i+3UL,i1) * v1 + A(i+3UL,i2) * v2 + A(i+3UL,i3) * v3 + A(i+3UL,i4) * v4;
518  }
519  for( size_t i=iend; i<A.rows(); ++i ) {
520  (~lhs)(i,j) += A(i,i1) * v1 + A(i,i2) * v2 + A(i,i3) * v3 + A(i,i4) * v4;
521  }
522  }
523  else {
524  for( size_t i=0UL; i<iend; i+=4UL ) {
525  (~lhs)(i ,j) += A(i ,i1) * v1 + A(i ,i2) * v2 + A(i ,i3) * v3;
526  (~lhs)(i+1UL,j) += A(i+1UL,i1) * v1 + A(i+1UL,i2) * v2 + A(i+1UL,i3) * v3;
527  (~lhs)(i+2UL,j) += A(i+2UL,i1) * v1 + A(i+2UL,i2) * v2 + A(i+2UL,i3) * v3;
528  (~lhs)(i+3UL,j) += A(i+3UL,i1) * v1 + A(i+3UL,i2) * v2 + A(i+3UL,i3) * v3;
529  }
530  for( size_t i=iend; i<A.rows(); ++i ) {
531  (~lhs)(i,j) += A(i,i1) * v1 + A(i,i2) * v2 + A(i,i3) * v3;
532  }
533  }
534  }
535  else {
536  for( size_t i=0UL; i<iend; i+=4UL ) {
537  (~lhs)(i ,j) += A(i ,i1) * v1 + A(i ,i2) * v2;
538  (~lhs)(i+1UL,j) += A(i+1UL,i1) * v1 + A(i+1UL,i2) * v2;
539  (~lhs)(i+2UL,j) += A(i+2UL,i1) * v1 + A(i+2UL,i2) * v2;
540  (~lhs)(i+3UL,j) += A(i+3UL,i1) * v1 + A(i+3UL,i2) * v2;
541  }
542  for( size_t i=iend; i<A.rows(); ++i ) {
543  (~lhs)(i,j) += A(i,i1) * v1 + A(i,i2) * v2;
544  }
545  }
546  }
547  else {
548  for( size_t i=0UL; i<iend; i+=4UL ) {
549  (~lhs)(i ,j) += A(i ,i1) * v1;
550  (~lhs)(i+1UL,j) += A(i+1UL,i1) * v1;
551  (~lhs)(i+2UL,j) += A(i+2UL,i1) * v1;
552  (~lhs)(i+3UL,j) += A(i+3UL,i1) * v1;
553  }
554  for( size_t i=iend; i<A.rows(); ++i ) {
555  (~lhs)(i,j) += A(i,i1) * v1;
556  }
557  }
558  }
559  }
560  }
562  //**********************************************************************************************
563 
564  //**Assignment to sparse matrices***************************************************************
576  template< typename MT // Type of the target sparse matrix
577  , bool SO > // Storage order of the target sparse matrix
578  friend inline void assign( SparseMatrix<MT,SO>& lhs, const TDMatTSMatMultExpr& rhs )
579  {
580  typedef typename SelectType< SO, ResultType, OppositeType >::Type TmpType;
581 
587  BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( typename TmpType::CompositeType );
588 
589  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
590  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
591 
592  const TmpType tmp( rhs );
593  assign( ~lhs, tmp );
594  }
596  //**********************************************************************************************
597 
598  //**Addition assignment to row-major dense matrices*********************************************
611  template< typename MT > // Type of the target dense matrix
612  friend inline void addAssign( DenseMatrix<MT,false>& lhs, const TDMatTSMatMultExpr& rhs )
613  {
614  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
615  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
616 
617  typedef typename boost::remove_reference<RT>::type::ConstIterator ConstIterator;
618 
619  LT A( rhs.lhs_ ); // Evaluation of the left-hand side dense matrix operand
620  RT B( rhs.rhs_ ); // Evaluation of the right-hand side sparse matrix operand
621 
622  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
623  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
624  BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
625  BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
626  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
627  BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
628 
629  BLAZE_INTERNAL_ASSERT( ( A.rows() - ( A.rows() % 4UL ) ) == ( A.rows() & size_t(-4) ), "Invalid end calculation" );
630  const size_t iend( A.rows() & size_t(-4) );
631 
632  for( size_t i=0UL; i<iend; i+=4UL ) {
633  for( size_t j=0UL; j<B.columns(); ++j )
634  {
635  ConstIterator element( B.begin(j) );
636  const ConstIterator end( B.end(j) );
637 
638  for( ; element!=end; ++element ) {
639  (~lhs)(i ,j) += A(i ,element->index()) * element->value();
640  (~lhs)(i+1UL,j) += A(i+1UL,element->index()) * element->value();
641  (~lhs)(i+2UL,j) += A(i+2UL,element->index()) * element->value();
642  (~lhs)(i+3UL,j) += A(i+3UL,element->index()) * element->value();
643  }
644  }
645  }
646 
647  for( size_t i=iend; i<A.rows(); ++i ) {
648  for( size_t j=0UL; j<B.columns(); ++j )
649  {
650  ConstIterator element( B.begin(j) );
651  const ConstIterator end( B.end(j) );
652 
653  for( ; element!=end; ++element )
654  (~lhs)(i,j) += A(i,element->index()) * element->value();
655  }
656  }
657  }
659  //**********************************************************************************************
660 
661  //**Addition assignment to column-major dense matrices******************************************
674  template< typename MT > // Type of the target dense matrix
675  friend inline void addAssign( DenseMatrix<MT,true>& lhs, const TDMatTSMatMultExpr& rhs )
676  {
677  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
678  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
679 
680  typedef typename boost::remove_reference<RT>::type::ConstIterator ConstIterator;
681 
682  LT A( rhs.lhs_ ); // Evaluation of the left-hand side dense matrix operand
683  RT B( rhs.rhs_ ); // Evaluation of the right-hand side sparse matrix operand
684 
685  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
686  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
687  BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
688  BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
689  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
690  BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
691 
692  BLAZE_INTERNAL_ASSERT( ( A.rows() - ( A.rows() % 4UL ) ) == ( A.rows() & size_t(-4) ), "Invalid end calculation" );
693  const size_t iend( A.rows() & size_t(-4) );
694 
695  for( size_t j=0UL; j<B.columns(); ++j )
696  {
697  ConstIterator element( B.begin(j) );
698  const ConstIterator end( B.end(j) );
699 
700  while( element!=end )
701  {
702  const ET2 v1( element->value() );
703  const size_t i1( element->index() );
704  ++element;
705 
706  if( element != end ) {
707  const ET2 v2( element->value() );
708  const size_t i2( element->index() );
709  ++element;
710 
711  if( element != end ) {
712  const ET2 v3( element->value() );
713  const size_t i3( element->index() );
714  ++element;
715 
716  if( element != end ) {
717  const ET2 v4( element->value() );
718  const size_t i4( element->index() );
719  ++element;
720 
721  for( size_t i=0UL; i<iend; i+=4UL ) {
722  (~lhs)(i ,j) += A(i ,i1) * v1 + A(i ,i2) * v2 + A(i ,i3) * v3 + A(i ,i4) * v4;
723  (~lhs)(i+1UL,j) += A(i+1UL,i1) * v1 + A(i+1UL,i2) * v2 + A(i+1UL,i3) * v3 + A(i+1UL,i4) * v4;
724  (~lhs)(i+2UL,j) += A(i+2UL,i1) * v1 + A(i+2UL,i2) * v2 + A(i+2UL,i3) * v3 + A(i+2UL,i4) * v4;
725  (~lhs)(i+3UL,j) += A(i+3UL,i1) * v1 + A(i+3UL,i2) * v2 + A(i+3UL,i3) * v3 + A(i+3UL,i4) * v4;
726  }
727  for( size_t i=iend; i<A.rows(); ++i ) {
728  (~lhs)(i,j) += A(i,i1) * v1 + A(i,i2) * v2 + A(i,i3) * v3 + A(i,i4) * v4;
729  }
730  }
731  else {
732  for( size_t i=0UL; i<iend; i+=4UL ) {
733  (~lhs)(i ,j) += A(i ,i1) * v1 + A(i ,i2) * v2 + A(i ,i3) * v3;
734  (~lhs)(i+1UL,j) += A(i+1UL,i1) * v1 + A(i+1UL,i2) * v2 + A(i+1UL,i3) * v3;
735  (~lhs)(i+2UL,j) += A(i+2UL,i1) * v1 + A(i+2UL,i2) * v2 + A(i+2UL,i3) * v3;
736  (~lhs)(i+3UL,j) += A(i+3UL,i1) * v1 + A(i+3UL,i2) * v2 + A(i+3UL,i3) * v3;
737  }
738  for( size_t i=iend; i<A.rows(); ++i ) {
739  (~lhs)(i,j) += A(i,i1) * v1 + A(i,i2) * v2 + A(i,i3) * v3;
740  }
741  }
742  }
743  else {
744  for( size_t i=0UL; i<iend; i+=4UL ) {
745  (~lhs)(i ,j) += A(i ,i1) * v1 + A(i ,i2) * v2;
746  (~lhs)(i+1UL,j) += A(i+1UL,i1) * v1 + A(i+1UL,i2) * v2;
747  (~lhs)(i+2UL,j) += A(i+2UL,i1) * v1 + A(i+2UL,i2) * v2;
748  (~lhs)(i+3UL,j) += A(i+3UL,i1) * v1 + A(i+3UL,i2) * v2;
749  }
750  for( size_t i=iend; i<A.rows(); ++i ) {
751  (~lhs)(i,j) += A(i,i1) * v1 + A(i,i2) * v2;
752  }
753  }
754  }
755  else {
756  for( size_t i=0UL; i<iend; i+=4UL ) {
757  (~lhs)(i ,j) += A(i ,i1) * v1;
758  (~lhs)(i+1UL,j) += A(i+1UL,i1) * v1;
759  (~lhs)(i+2UL,j) += A(i+2UL,i1) * v1;
760  (~lhs)(i+3UL,j) += A(i+3UL,i1) * v1;
761  }
762  for( size_t i=iend; i<A.rows(); ++i ) {
763  (~lhs)(i,j) += A(i,i1) * v1;
764  }
765  }
766  }
767  }
768  }
770  //**********************************************************************************************
771 
772  //**Addition assignment to sparse matrices******************************************************
773  // No special implementation for the addition assignment to sparse matrices.
774  //**********************************************************************************************
775 
776  //**Subtraction assignment to row-major dense matrices******************************************
789  template< typename MT > // Type of the target dense matrix
790  friend inline void subAssign( DenseMatrix<MT,false>& lhs, const TDMatTSMatMultExpr& rhs )
791  {
792  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
793  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
794 
795  typedef typename boost::remove_reference<RT>::type::ConstIterator ConstIterator;
796 
797  LT A( rhs.lhs_ ); // Evaluation of the left-hand side dense matrix operand
798  RT B( rhs.rhs_ ); // Evaluation of the right-hand side sparse matrix operand
799 
800  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
801  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
802  BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
803  BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
804  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
805  BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
806 
807  BLAZE_INTERNAL_ASSERT( ( A.rows() - ( A.rows() % 4UL ) ) == ( A.rows() & size_t(-4) ), "Invalid end calculation" );
808  const size_t iend( A.rows() & size_t(-4) );
809 
810  for( size_t i=0UL; i<iend; i+=4 ) {
811  for( size_t j=0UL; j<B.columns(); ++j )
812  {
813  ConstIterator element( B.begin(j) );
814  const ConstIterator end( B.end(j) );
815 
816  for( ; element!=end; ++element ) {
817  (~lhs)(i ,j) -= A(i ,element->index()) * element->value();
818  (~lhs)(i+1UL,j) -= A(i+1UL,element->index()) * element->value();
819  (~lhs)(i+2UL,j) -= A(i+2UL,element->index()) * element->value();
820  (~lhs)(i+3UL,j) -= A(i+3UL,element->index()) * element->value();
821  }
822  }
823  }
824 
825  for( size_t i=iend; i<A.rows(); ++i ) {
826  for( size_t j=0UL; j<B.columns(); ++j )
827  {
828  ConstIterator element( B.begin(j) );
829  const ConstIterator end( B.end(j) );
830 
831  for( ; element!=end; ++element )
832  (~lhs)(i,j) -= A(i,element->index()) * element->value();
833  }
834  }
835  }
837  //**********************************************************************************************
838 
839  //**Subtraction assignment to column-major dense matrices***************************************
852  template< typename MT > // Type of the target dense matrix
853  friend inline void subAssign( DenseMatrix<MT,true>& lhs, const TDMatTSMatMultExpr& rhs )
854  {
855  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
856  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
857 
858  typedef typename boost::remove_reference<RT>::type::ConstIterator ConstIterator;
859 
860  LT A( rhs.lhs_ ); // Evaluation of the left-hand side dense matrix operand
861  RT B( rhs.rhs_ ); // Evaluation of the right-hand side sparse matrix operand
862 
863  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
864  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
865  BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
866  BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
867  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
868  BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
869 
870  BLAZE_INTERNAL_ASSERT( ( A.rows() - ( A.rows() % 4UL ) ) == ( A.rows() & size_t(-4) ), "Invalid end calculation" );
871  const size_t iend( A.rows() & size_t(-4) );
872 
873  for( size_t j=0UL; j<B.columns(); ++j )
874  {
875  ConstIterator element( B.begin(j) );
876  const ConstIterator end( B.end(j) );
877 
878  while( element!=end )
879  {
880  const ET2 v1( element->value() );
881  const size_t i1( element->index() );
882  ++element;
883 
884  if( element != end ) {
885  const ET2 v2( element->value() );
886  const size_t i2( element->index() );
887  ++element;
888 
889  if( element != end ) {
890  const ET2 v3( element->value() );
891  const size_t i3( element->index() );
892  ++element;
893 
894  if( element != end ) {
895  const ET2 v4( element->value() );
896  const size_t i4( element->index() );
897  ++element;
898 
899  for( size_t i=0UL; i<iend; i+=4UL ) {
900  (~lhs)(i ,j) -= A(i ,i1) * v1 + A(i ,i2) * v2 + A(i ,i3) * v3 + A(i ,i4) * v4;
901  (~lhs)(i+1UL,j) -= A(i+1UL,i1) * v1 + A(i+1UL,i2) * v2 + A(i+1UL,i3) * v3 + A(i+1UL,i4) * v4;
902  (~lhs)(i+2UL,j) -= A(i+2UL,i1) * v1 + A(i+2UL,i2) * v2 + A(i+2UL,i3) * v3 + A(i+2UL,i4) * v4;
903  (~lhs)(i+3UL,j) -= A(i+3UL,i1) * v1 + A(i+3UL,i2) * v2 + A(i+3UL,i3) * v3 + A(i+3UL,i4) * v4;
904  }
905  for( size_t i=iend; i<A.rows(); ++i ) {
906  (~lhs)(i,j) -= A(i,i1) * v1 + A(i,i2) * v2 + A(i,i3) * v3 + A(i,i4) * v4;
907  }
908  }
909  else {
910  for( size_t i=0UL; i<iend; i+=4UL ) {
911  (~lhs)(i ,j) -= A(i ,i1) * v1 + A(i ,i2) * v2 + A(i ,i3) * v3;
912  (~lhs)(i+1UL,j) -= A(i+1UL,i1) * v1 + A(i+1UL,i2) * v2 + A(i+1UL,i3) * v3;
913  (~lhs)(i+2UL,j) -= A(i+2UL,i1) * v1 + A(i+2UL,i2) * v2 + A(i+2UL,i3) * v3;
914  (~lhs)(i+3UL,j) -= A(i+3UL,i1) * v1 + A(i+3UL,i2) * v2 + A(i+3UL,i3) * v3;
915  }
916  for( size_t i=iend; i<A.rows(); ++i ) {
917  (~lhs)(i,j) -= A(i,i1) * v1 + A(i,i2) * v2 + A(i,i3) * v3;
918  }
919  }
920  }
921  else {
922  for( size_t i=0UL; i<iend; i+=4UL ) {
923  (~lhs)(i ,j) -= A(i ,i1) * v1 + A(i ,i2) * v2;
924  (~lhs)(i+1UL,j) -= A(i+1UL,i1) * v1 + A(i+1UL,i2) * v2;
925  (~lhs)(i+2UL,j) -= A(i+2UL,i1) * v1 + A(i+2UL,i2) * v2;
926  (~lhs)(i+3UL,j) -= A(i+3UL,i1) * v1 + A(i+3UL,i2) * v2;
927  }
928  for( size_t i=iend; i<A.rows(); ++i ) {
929  (~lhs)(i,j) -= A(i,i1) * v1 + A(i,i2) * v2;
930  }
931  }
932  }
933  else {
934  for( size_t i=0UL; i<iend; i+=4UL ) {
935  (~lhs)(i ,j) -= A(i ,i1) * v1;
936  (~lhs)(i+1UL,j) -= A(i+1UL,i1) * v1;
937  (~lhs)(i+2UL,j) -= A(i+2UL,i1) * v1;
938  (~lhs)(i+3UL,j) -= A(i+3UL,i1) * v1;
939  }
940  for( size_t i=iend; i<A.rows(); ++i ) {
941  (~lhs)(i,j) -= A(i,i1) * v1;
942  }
943  }
944  }
945  }
946  }
948  //**********************************************************************************************
949 
950  //**Subtraction assignment to sparse matrices***************************************************
951  // No special implementation for the subtraction assignment to sparse matrices.
952  //**********************************************************************************************
953 
954  //**Multiplication assignment to dense matrices*************************************************
955  // No special implementation for the multiplication assignment to dense matrices.
956  //**********************************************************************************************
957 
958  //**Multiplication assignment to sparse matrices************************************************
959  // No special implementation for the multiplication assignment to sparse matrices.
960  //**********************************************************************************************
961 
962  //**Compile time checks*************************************************************************
969  //**********************************************************************************************
970 };
971 //*************************************************************************************************
972 
973 
974 
975 
976 //=================================================================================================
977 //
978 // GLOBAL BINARY ARITHMETIC OPERATORS
979 //
980 //=================================================================================================
981 
982 //*************************************************************************************************
1011 template< typename T1 // Type of the left-hand side dense matrix
1012  , typename T2 > // Type of the right-hand side sparse matrix
1013 inline const TDMatTSMatMultExpr<T1,T2>
1015 {
1016  if( (~lhs).columns() != (~rhs).rows() )
1017  throw std::invalid_argument( "Matrix sizes do not match" );
1018 
1019  return TDMatTSMatMultExpr<T1,T2>( ~lhs, ~rhs );
1020 }
1021 //*************************************************************************************************
1022 
1023 
1024 
1025 
1026 //=================================================================================================
1027 //
1028 // EXPRESSION TRAIT SPECIALIZATIONS
1029 //
1030 //=================================================================================================
1031 
1032 //*************************************************************************************************
1034 template< typename MT1, typename MT2, typename VT >
1035 struct TDMatDVecMultExprTrait< TDMatTSMatMultExpr<MT1,MT2>, VT >
1036 {
1037  public:
1038  //**********************************************************************************************
1039  typedef typename SelectType< IsDenseMatrix<MT1>::value && IsColumnMajorMatrix<MT1>::value &&
1040  IsSparseMatrix<MT2>::value && IsColumnMajorMatrix<MT2>::value &&
1041  IsDenseVector<VT>::value && !IsTransposeVector<VT>::value
1042  , typename TDMatDVecMultExprTrait< MT1, typename TSMatDVecMultExprTrait<MT2,VT>::Type >::Type
1043  , INVALID_TYPE >::Type Type;
1044  //**********************************************************************************************
1045 };
1047 //*************************************************************************************************
1048 
1049 
1050 //*************************************************************************************************
1052 template< typename MT1, typename MT2, typename VT >
1053 struct TDMatSVecMultExprTrait< TDMatTSMatMultExpr<MT1,MT2>, VT >
1054 {
1055  public:
1056  //**********************************************************************************************
1057  typedef typename SelectType< IsDenseMatrix<MT1>::value && IsColumnMajorMatrix<MT1>::value &&
1058  IsSparseMatrix<MT2>::value && IsColumnMajorMatrix<MT2>::value &&
1059  IsSparseVector<VT>::value && !IsTransposeVector<VT>::value
1060  , typename TDMatDVecMultExprTrait< MT1, typename TSMatDVecMultExprTrait<MT2,VT>::Type >::Type
1061  , INVALID_TYPE >::Type Type;
1062  //**********************************************************************************************
1063 };
1065 //*************************************************************************************************
1066 
1067 
1068 //*************************************************************************************************
1070 template< typename VT, typename MT1, typename MT2 >
1071 struct TDVecTDMatMultExprTrait< VT, TDMatTSMatMultExpr<MT1,MT2> >
1072 {
1073  public:
1074  //**********************************************************************************************
1075  typedef typename SelectType< IsDenseVector<VT>::value && IsTransposeVector<VT>::value &&
1076  IsDenseMatrix<MT1>::value && IsColumnMajorMatrix<MT1>::value &&
1077  IsSparseMatrix<MT2>::value && IsColumnMajorMatrix<MT2>::value
1078  , typename TDVecTSMatMultExprTrait< typename TDVecTDMatMultExprTrait<VT,MT1>::Type, MT2 >::Type
1079  , INVALID_TYPE >::Type Type;
1080  //**********************************************************************************************
1081 };
1083 //*************************************************************************************************
1084 
1085 
1086 //*************************************************************************************************
1088 template< typename VT, typename MT1, typename MT2 >
1089 struct TSVecTDMatMultExprTrait< VT, TDMatTSMatMultExpr<MT1,MT2> >
1090 {
1091  public:
1092  //**********************************************************************************************
1093  typedef typename SelectType< IsSparseVector<VT>::value && IsTransposeVector<VT>::value &&
1094  IsDenseMatrix<MT1>::value && IsColumnMajorMatrix<MT1>::value &&
1095  IsSparseMatrix<MT2>::value && IsColumnMajorMatrix<MT2>::value
1096  , typename TDVecTSMatMultExprTrait< typename TSVecTDMatMultExprTrait<VT,MT1>::Type, MT2 >::Type
1097  , INVALID_TYPE >::Type Type;
1098  //**********************************************************************************************
1099 };
1101 //*************************************************************************************************
1102 
1103 } // namespace blaze
1104 
1105 #endif