TSVecDMatMultExpr.h
Go to the documentation of this file.
1 //=================================================================================================
33 //=================================================================================================
34 
35 #ifndef _BLAZE_MATH_EXPRESSIONS_TSVECDMATMULTEXPR_H_
36 #define _BLAZE_MATH_EXPRESSIONS_TSVECDMATMULTEXPR_H_
37 
38 
39 //*************************************************************************************************
40 // Includes
41 //*************************************************************************************************
42 
43 #include <stdexcept>
55 #include <blaze/math/Intrinsics.h>
56 #include <blaze/math/shims/Reset.h>
75 #include <blaze/util/Assert.h>
77 #include <blaze/util/DisableIf.h>
78 #include <blaze/util/EnableIf.h>
80 #include <blaze/util/SelectType.h>
81 #include <blaze/util/Types.h>
84 
85 
86 namespace blaze {
87 
88 //=================================================================================================
89 //
90 // CLASS TSVECDMATMULTEXPR
91 //
92 //=================================================================================================
93 
94 //*************************************************************************************************
101 template< typename VT // Type of the left-hand side sparse vector
102  , typename MT > // Type of the right-hand side dense matrix
103 class TSVecDMatMultExpr : public DenseVector< TSVecDMatMultExpr<VT,MT>, true >
104  , private TVecMatMultExpr
105  , private Computation
106 {
107  private:
108  //**Type definitions****************************************************************************
109  typedef typename VT::ResultType VRT;
110  typedef typename MT::ResultType MRT;
111  typedef typename VRT::ElementType VET;
112  typedef typename MRT::ElementType MET;
113  typedef typename VT::CompositeType VCT;
114  typedef typename MT::CompositeType MCT;
115  //**********************************************************************************************
116 
117  //**********************************************************************************************
119  enum { evaluateVector = IsComputation<VT>::value || RequiresEvaluation<VT>::value };
120  //**********************************************************************************************
121 
122  //**********************************************************************************************
124  enum { evaluateMatrix = ( IsComputation<MT>::value && IsSame<MET,VET>::value &&
126  //**********************************************************************************************
127 
128  //**********************************************************************************************
130 
134  template< typename T1 >
135  struct UseSMPAssign {
136  enum { value = ( evaluateVector || evaluateMatrix ) };
137  };
139  //**********************************************************************************************
140 
141  //**********************************************************************************************
143 
147  template< typename T1, typename T2, typename T3 >
148  struct UseVectorizedKernel {
149  enum { value = !IsDiagonal<T3>::value &&
150  T1::vectorizable && T3::vectorizable &&
151  IsSame<typename T1::ElementType,typename T2::ElementType>::value &&
152  IsSame<typename T1::ElementType,typename T3::ElementType>::value &&
153  IntrinsicTrait<typename T1::ElementType>::addition &&
154  IntrinsicTrait<typename T1::ElementType>::multiplication };
155  };
157  //**********************************************************************************************
158 
159  //**********************************************************************************************
161 
165  template< typename T1, typename T2, typename T3 >
166  struct UseOptimizedKernel {
167  enum { value = !UseVectorizedKernel<T1,T2,T3>::value &&
168  !IsDiagonal<T3>::value &&
169  !IsResizable<typename T1::ElementType>::value &&
170  !IsResizable<VET>::value };
171  };
173  //**********************************************************************************************
174 
175  //**********************************************************************************************
177 
180  template< typename T1, typename T2, typename T3 >
181  struct UseDefaultKernel {
182  enum { value = !UseVectorizedKernel<T1,T2,T3>::value &&
183  !UseOptimizedKernel<T1,T2,T3>::value };
184  };
186  //**********************************************************************************************
187 
188  public:
189  //**Type definitions****************************************************************************
195  typedef const ElementType ReturnType;
196  typedef const ResultType CompositeType;
197 
199  typedef typename SelectType< IsExpression<VT>::value, const VT, const VT& >::Type LeftOperand;
200 
202  typedef typename SelectType< IsExpression<MT>::value, const MT, const MT& >::Type RightOperand;
203 
206 
209  //**********************************************************************************************
210 
211  //**Compilation flags***************************************************************************
213  enum { vectorizable = !IsDiagonal<MT>::value &&
214  MT::vectorizable &&
218 
220  enum { smpAssignable = !evaluateVector && VT::smpAssignable &&
221  !evaluateMatrix && MT::smpAssignable };
222  //**********************************************************************************************
223 
224  //**Constructor*********************************************************************************
230  explicit inline TSVecDMatMultExpr( const VT& vec, const MT& mat )
231  : vec_( vec ) // Left-hand side sparse vector of the multiplication expression
232  , mat_( mat ) // Right-hand side dense matrix of the multiplication expression
233  {
234  BLAZE_INTERNAL_ASSERT( vec_.size() == mat_.rows(), "Invalid vector and matrix sizes" );
235  }
236  //**********************************************************************************************
237 
238  //**Subscript operator**************************************************************************
244  inline ReturnType operator[]( size_t index ) const {
245  BLAZE_INTERNAL_ASSERT( index < mat_.columns(), "Invalid vector access index" );
246 
248 
249  LT x( vec_ ); // Evaluation of the left-hand side sparse vector operand
250 
251  BLAZE_INTERNAL_ASSERT( x.size() == vec_.size(), "Invalid vector size" );
252 
253  const ConstIterator end( ( IsUpper<MT>::value )
254  ?( IsStrictlyUpper<MT>::value ? x.lowerBound( index ) : x.upperBound( index ) )
255  :( x.end() ) );
256  ConstIterator element( ( IsLower<MT>::value )
257  ?( IsStrictlyLower<MT>::value ? x.upperBound( index ) : x.lowerBound( index ) )
258  :( x.begin() ) );
259 
260  ElementType res = ElementType();
261 
262  if( element != end ) {
263  res = element->value() * mat_( element->index(), index );
264  ++element;
265  for( ; element!=end; ++element ) {
266  res += element->value() * mat_( element->index(), index );
267  }
268  }
269 
270  return res;
271  }
272  //**********************************************************************************************
273 
274  //**Size function*******************************************************************************
279  inline size_t size() const {
280  return mat_.columns();
281  }
282  //**********************************************************************************************
283 
284  //**Left operand access*************************************************************************
289  inline LeftOperand leftOperand() const {
290  return vec_;
291  }
292  //**********************************************************************************************
293 
294  //**Right operand access************************************************************************
299  inline RightOperand rightOperand() const {
300  return mat_;
301  }
302  //**********************************************************************************************
303 
304  //**********************************************************************************************
310  template< typename T >
311  inline bool canAlias( const T* alias ) const {
312  return vec_.isAliased( alias ) || mat_.isAliased( alias );
313  }
314  //**********************************************************************************************
315 
316  //**********************************************************************************************
322  template< typename T >
323  inline bool isAliased( const T* alias ) const {
324  return vec_.isAliased( alias ) || mat_.isAliased( alias );
325  }
326  //**********************************************************************************************
327 
328  //**********************************************************************************************
333  inline bool isAligned() const {
334  return mat_.isAligned();
335  }
336  //**********************************************************************************************
337 
338  //**********************************************************************************************
343  inline bool canSMPAssign() const {
344  return ( size() > SMP_TSVECDMATMULT_THRESHOLD );
345  }
346  //**********************************************************************************************
347 
348  private:
349  //**Member variables****************************************************************************
350  LeftOperand vec_;
351  RightOperand mat_;
352  //**********************************************************************************************
353 
354  //**Assignment to dense vectors*****************************************************************
367  template< typename VT2 > // Type of the target dense vector
368  friend inline void assign( DenseVector<VT2,true>& lhs, const TSVecDMatMultExpr& rhs )
369  {
371 
372  BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
373 
374  // Evaluation of the left-hand side sparse vector operand
375  LT x( serial( rhs.vec_ ) );
376  if( x.nonZeros() == 0UL ) {
377  reset( ~lhs );
378  return;
379  }
380 
381  // Evaluation of the right-hand side dense matrix operand
382  RT A( serial( rhs.mat_ ) );
383 
384  // Checking the evaluated operands
385  BLAZE_INTERNAL_ASSERT( x.size() == rhs.vec_.size() , "Invalid vector size" );
386  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.mat_.rows() , "Invalid number of rows" );
387  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.mat_.columns(), "Invalid number of columns" );
388  BLAZE_INTERNAL_ASSERT( A.columns() == (~lhs).size() , "Invalid vector size" );
389 
390  // Performing the sparse vector-dense matrix multiplication
391  TSVecDMatMultExpr::selectAssignKernel( ~lhs, x, A );
392  }
394  //**********************************************************************************************
395 
396  //**Default assignment to dense vectors*********************************************************
410  template< typename VT1 // Type of the left-hand side target vector
411  , typename VT2 // Type of the left-hand side vector operand
412  , typename MT1 > // Type of the right-hand side matrix operand
413  static inline typename EnableIf< UseDefaultKernel<VT1,VT2,MT1> >::Type
414  selectAssignKernel( VT1& y, const VT2& x, const MT1& A )
415  {
417 
418  BLAZE_INTERNAL_ASSERT( x.nonZeros() != 0UL, "Invalid number of non-zero elements" );
419 
420  const size_t N( A.columns() );
421 
422  ConstIterator element( x.begin() );
423  const ConstIterator end( x.end() );
424 
425  size_t last( 0UL );
426 
427  if( IsUpper<MT1>::value ) {
428  const size_t jend( IsStrictlyUpper<MT1>::value ? element->index()+1UL : element->index() );
429  for( size_t j=0UL; j<jend; ++j )
430  reset( y[j] );
431  }
432 
433  for( ; element!=end; ++element )
434  {
435  const size_t index( element->index() );
436 
437  if( IsDiagonal<MT1>::value )
438  {
439 
440 
441  for( size_t j=last; j<index; ++j )
442  reset( y[j] );
443 
444  y[index] = element->value() * A(index,index);
445  last = index + 1UL;
446  }
447  else
448  {
449  const size_t jbegin( ( IsUpper<MT1>::value )
450  ?( IsStrictlyUpper<MT1>::value ? index+1UL : index )
451  :( 0UL ) );
452  const size_t jend( ( IsLower<MT1>::value )
453  ?( IsStrictlyLower<MT1>::value ? index : index+1UL )
454  :( N ) );
455  BLAZE_INTERNAL_ASSERT( jbegin <= jend, "Invalid loop indices detected" );
456 
457  for( size_t j=jbegin; j<last; ++j ) {
458  y[j] += element->value() * A(index,j);
459  }
460  for( size_t j=last; j<jend; ++j ) {
461  y[j] = element->value() * A(index,j);
462  }
463 
464  last = jend;
465  }
466  }
467 
468  if( IsLower<MT1>::value ) {
469  for( size_t j=last; j<N; ++j )
470  reset( y[j] );
471  }
472  }
474  //**********************************************************************************************
475 
476  //**Optimized assignment to dense vectors*******************************************************
490  template< typename VT1 // Type of the left-hand side target vector
491  , typename VT2 // Type of the left-hand side vector operand
492  , typename MT1 > // Type of the right-hand side matrix operand
493  static inline typename EnableIf< UseOptimizedKernel<VT1,VT2,MT1> >::Type
494  selectAssignKernel( VT1& y, const VT2& x, const MT1& A )
495  {
497 
498  BLAZE_INTERNAL_ASSERT( x.nonZeros() != 0UL, "Invalid number of non-zero elements" );
499 
500  const size_t N( A.columns() );
501 
502  ConstIterator element( x.begin() );
503  const ConstIterator end( x.end() );
504 
505  const size_t ipos( x.nonZeros() & size_t(-4) );
506  BLAZE_INTERNAL_ASSERT( ( x.nonZeros() - ( x.nonZeros() % 4UL ) ) == ipos, "Invalid end calculation" );
507 
508  if( ipos > 3UL )
509  {
510  const size_t i1( element->index() );
511  const VET v1( element->value() );
512  ++element;
513  const size_t i2( element->index() );
514  const VET v2( element->value() );
515  ++element;
516  const size_t i3( element->index() );
517  const VET v3( element->value() );
518  ++element;
519  const size_t i4( element->index() );
520  const VET v4( element->value() );
521  ++element;
522 
523  BLAZE_INTERNAL_ASSERT( i1 < i2 && i2 < i3 && i3 < i4, "Invalid sparse vector index detected" );
524 
525  for( size_t j=0UL; j<N; ++j ) {
526  y[j] = v1 * A(i1,j) + v2 * A(i2,j) + v3 * A(i3,j) + v4 * A(i4,j);
527  }
528  }
529  else
530  {
531  const size_t i1( element->index() );
532  const VET v1( element->value() );
533  ++element;
534 
535  for( size_t j=0UL; j<N; ++j ) {
536  y[j] = v1 * A(i1,j);
537  }
538  }
539 
540  for( size_t i=(ipos>3UL)?(4UL):(1UL); (i+4UL)<=ipos; i+=4UL )
541  {
542  const size_t i1( element->index() );
543  const VET v1( element->value() );
544  ++element;
545  const size_t i2( element->index() );
546  const VET v2( element->value() );
547  ++element;
548  const size_t i3( element->index() );
549  const VET v3( element->value() );
550  ++element;
551  const size_t i4( element->index() );
552  const VET v4( element->value() );
553  ++element;
554 
555  BLAZE_INTERNAL_ASSERT( i1 < i2 && i2 < i3 && i3 < i4, "Invalid sparse vector index detected" );
556 
557  const size_t jbegin( ( IsUpper<MT1>::value )
558  ?( IsStrictlyUpper<MT1>::value ? i1+1UL : i1 )
559  :( 0UL ) );
560  const size_t jend( ( IsLower<MT1>::value )
561  ?( IsStrictlyLower<MT1>::value ? i4 : i4+1UL )
562  :( N ) );
563  BLAZE_INTERNAL_ASSERT( jbegin <= jend, "Invalid loop indices detected" );
564 
565  for( size_t j=jbegin; j<jend; ++j ) {
566  y[j] += v1 * A(i1,j) + v2 * A(i2,j) + v3 * A(i3,j) + v4 * A(i4,j);
567  }
568  }
569  for( ; element!=end; ++element )
570  {
571  const size_t i1( element->index() );
572  const VET v1( element->value() );
573 
574  const size_t jbegin( ( IsUpper<MT1>::value )
575  ?( IsStrictlyUpper<MT1>::value ? i1+1UL : i1 )
576  :( 0UL ) );
577  const size_t jend( ( IsLower<MT1>::value )
578  ?( IsStrictlyLower<MT1>::value ? i1 : i1+1UL )
579  :( N ) );
580  BLAZE_INTERNAL_ASSERT( jbegin <= jend, "Invalid loop indices detected" );
581 
582  for( size_t j=jbegin; j<jend; ++j ) {
583  y[j] += v1 * A(i1,j);
584  }
585  }
586  }
588  //**********************************************************************************************
589 
590  //**Vectorized assignment to dense vectors******************************************************
604  template< typename VT1 // Type of the left-hand side target vector
605  , typename VT2 // Type of the left-hand side vector operand
606  , typename MT1 > // Type of the right-hand side matrix operand
607  static inline typename EnableIf< UseVectorizedKernel<VT1,VT2,MT1> >::Type
608  selectAssignKernel( VT1& y, const VT2& x, const MT1& A )
609  {
610  typedef IntrinsicTrait<ElementType> IT;
612 
613  BLAZE_INTERNAL_ASSERT( x.nonZeros() != 0UL, "Invalid number of non-zero elements" );
614 
615  const size_t N( A.columns() );
616 
617  ConstIterator element( x.begin() );
618  const ConstIterator end( x.end() );
619 
620  const size_t ipos( x.nonZeros() & size_t(-4) );
621  BLAZE_INTERNAL_ASSERT( ( x.nonZeros() - ( x.nonZeros() % 4UL ) ) == ipos, "Invalid end calculation" );
622 
623  if( ipos > 3UL )
624  {
625  const size_t i1( element->index() );
626  const IntrinsicType v1( set( element->value() ) );
627  ++element;
628  const size_t i2( element->index() );
629  const IntrinsicType v2( set( element->value() ) );
630  ++element;
631  const size_t i3( element->index() );
632  const IntrinsicType v3( set( element->value() ) );
633  ++element;
634  const size_t i4( element->index() );
635  const IntrinsicType v4( set( element->value() ) );
636  ++element;
637 
638  BLAZE_INTERNAL_ASSERT( i1 < i2 && i2 < i3 && i3 < i4, "Invalid sparse vector index detected" );
639 
640  for( size_t j=0UL; j<N; j+=IT::size ) {
641  y.store( j, v1 * A.load(i1,j) + v2 * A.load(i2,j) + v3 * A.load(i3,j) + v4 * A.load(i4,j) );
642  }
643  }
644  else
645  {
646  const size_t i1( element->index() );
647  const IntrinsicType v1( set( element->value() ) );
648  ++element;
649 
650  for( size_t j=0UL; j<N; j+=IT::size ) {
651  y.store( j, v1 * A.load(i1,j) );
652  }
653  }
654 
655  for( size_t i=(ipos>3UL)?(4UL):(1UL); (i+4UL)<=ipos; i+=4UL )
656  {
657  const size_t i1( element->index() );
658  const IntrinsicType v1( set( element->value() ) );
659  ++element;
660  const size_t i2( element->index() );
661  const IntrinsicType v2( set( element->value() ) );
662  ++element;
663  const size_t i3( element->index() );
664  const IntrinsicType v3( set( element->value() ) );
665  ++element;
666  const size_t i4( element->index() );
667  const IntrinsicType v4( set( element->value() ) );
668  ++element;
669 
670  BLAZE_INTERNAL_ASSERT( i1 < i2 && i2 < i3 && i3 < i4, "Invalid sparse vector index detected" );
671 
672  const size_t jbegin( ( IsUpper<MT1>::value )
673  ?( ( IsStrictlyUpper<MT1>::value ? i1+1UL : i1 ) & size_t(-IT::size) )
674  :( 0UL ) );
675  const size_t jend( ( IsLower<MT1>::value )
676  ?( IsStrictlyLower<MT1>::value ? i4 : i4+1UL )
677  :( N ) );
678  BLAZE_INTERNAL_ASSERT( jbegin <= jend, "Invalid loop indices detected" );
679 
680  for( size_t j=jbegin; j<jend; j+=IT::size ) {
681  y.store( j, y.load(j) + v1 * A.load(i1,j) + v2 * A.load(i2,j) + v3 * A.load(i3,j) + v4 * A.load(i4,j) );
682  }
683  }
684  for( ; element!=end; ++element )
685  {
686  const size_t i1( element->index() );
687  const IntrinsicType v1( set( element->value() ) );
688 
689  const size_t jbegin( ( IsUpper<MT1>::value )
690  ?( ( IsStrictlyUpper<MT1>::value ? i1+1UL : i1 ) & size_t(-IT::size) )
691  :( 0UL ) );
692  const size_t jend( ( IsLower<MT1>::value )
693  ?( IsStrictlyLower<MT1>::value ? i1 : i1+1UL )
694  :( N ) );
695  BLAZE_INTERNAL_ASSERT( jbegin <= jend, "Invalid loop indices detected" );
696 
697  for( size_t j=jbegin; j<jend; j+=IT::size ) {
698  y.store( j, y.load(j) + v1 * A.load(i1,j) );
699  }
700  }
701  }
703  //**********************************************************************************************
704 
705  //**Assignment to sparse vectors****************************************************************
718  template< typename VT2 > // Type of the target sparse vector
719  friend inline void assign( SparseVector<VT2,true>& lhs, const TSVecDMatMultExpr& rhs )
720  {
722 
726 
727  BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
728 
729  const ResultType tmp( serial( rhs ) );
730  assign( ~lhs, tmp );
731  }
733  //**********************************************************************************************
734 
735  //**Addition assignment to dense vectors********************************************************
747  template< typename VT2 > // Type of the target dense vector
748  friend inline void addAssign( DenseVector<VT2,true>& lhs, const TSVecDMatMultExpr& rhs )
749  {
751 
752  BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
753 
754  // Evaluation of the left-hand side sparse vector operand
755  LT x( serial( rhs.vec_ ) );
756  if( x.nonZeros() == 0UL ) return;
757 
758  // Evaluation of the right-hand side dense matrix operand
759  RT A( serial( rhs.mat_ ) );
760 
761  // Checking the evaluated operands
762  BLAZE_INTERNAL_ASSERT( x.size() == rhs.vec_.size() , "Invalid vector size" );
763  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.mat_.rows() , "Invalid number of rows" );
764  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.mat_.columns(), "Invalid number of columns" );
765  BLAZE_INTERNAL_ASSERT( A.columns() == (~lhs).size() , "Invalid vector size" );
766 
767  // Performing the sparse vector-dense matrix multiplication
768  TSVecDMatMultExpr::selectAddAssignKernel( ~lhs, x, A );
769  }
770  //**********************************************************************************************
771 
772  //**Default addition assignment to dense vectors************************************************
786  template< typename VT1 // Type of the left-hand side target vector
787  , typename VT2 // Type of the left-hand side vector operand
788  , typename MT1 > // Type of the right-hand side matrix operand
789  static inline typename EnableIf< UseDefaultKernel<VT1,VT2,MT1> >::Type
790  selectAddAssignKernel( VT1& y, const VT2& x, const MT1& A )
791  {
793 
794  BLAZE_INTERNAL_ASSERT( x.nonZeros() != 0UL, "Invalid number of non-zero elements" );
795 
796  const size_t N( A.columns() );
797 
798  ConstIterator element( x.begin() );
799  const ConstIterator end( x.end() );
800 
801  for( ; element!=end; ++element )
802  {
803  const size_t index( element->index() );
804 
806  {
807  y[index] += A(index,index) * element->value();
808  }
809  else
810  {
811  const size_t jbegin( ( IsUpper<MT1>::value )
812  ?( IsStrictlyUpper<MT1>::value ? index+1UL : index )
813  :( 0UL ) );
814  const size_t jend( ( IsLower<MT1>::value )
815  ?( IsStrictlyLower<MT1>::value ? index : index+1UL )
816  :( N ) );
817  BLAZE_INTERNAL_ASSERT( jbegin <= jend, "Invalid loop indices detected" );
818 
819  for( size_t j=jbegin; j<jend; ++j ) {
820  y[j] += element->value() * A(index,j);
821  }
822  }
823  }
824  }
826  //**********************************************************************************************
827 
828  //**Optimized addition assignment to dense vectors**********************************************
842  template< typename VT1 // Type of the left-hand side target vector
843  , typename VT2 // Type of the left-hand side vector operand
844  , typename MT1 > // Type of the right-hand side matrix operand
845  static inline typename EnableIf< UseOptimizedKernel<VT1,VT2,MT1> >::Type
846  selectAddAssignKernel( VT1& y, const VT2& x, const MT1& A )
847  {
849 
850  BLAZE_INTERNAL_ASSERT( x.nonZeros() != 0UL, "Invalid number of non-zero elements" );
851 
852  const size_t N( A.columns() );
853 
854  ConstIterator element( x.begin() );
855  const ConstIterator end( x.end() );
856 
857  const size_t ipos( x.nonZeros() & size_t(-4) );
858  BLAZE_INTERNAL_ASSERT( ( x.nonZeros() - ( x.nonZeros() % 4UL ) ) == ipos, "Invalid end calculation" );
859 
860  for( size_t i=0UL; (i+4UL)<=ipos; i+=4UL )
861  {
862  const size_t i1( element->index() );
863  const VET v1( element->value() );
864  ++element;
865  const size_t i2( element->index() );
866  const VET v2( element->value() );
867  ++element;
868  const size_t i3( element->index() );
869  const VET v3( element->value() );
870  ++element;
871  const size_t i4( element->index() );
872  const VET v4( element->value() );
873  ++element;
874 
875  BLAZE_INTERNAL_ASSERT( i1 < i2 && i2 < i3 && i3 < i4, "Invalid sparse vector index detected" );
876 
877  const size_t jbegin( ( IsUpper<MT1>::value )
878  ?( IsStrictlyUpper<MT1>::value ? i+1UL : i1 )
879  :( 0UL ) );
880  const size_t jend( ( IsLower<MT1>::value )
881  ?( IsStrictlyLower<MT1>::value ? i4 : i4+1UL )
882  :( N ) );
883  BLAZE_INTERNAL_ASSERT( jbegin <= jend, "Invalid loop indices detected" );
884 
885  for( size_t j=jbegin; j<jend; ++j ) {
886  y[j] += v1 * A(i1,j) + v2 * A(i2,j) + v3 * A(i3,j) + v4 * A(i4,j);
887  }
888  }
889  for( ; element!=end; ++element )
890  {
891  const size_t i1( element->index() );
892  const VET v1( element->value() );
893 
894  const size_t jbegin( ( IsUpper<MT1>::value )
895  ?( IsStrictlyUpper<MT1>::value ? i1+1UL : i1 )
896  :( 0UL ) );
897  const size_t jend( ( IsLower<MT1>::value )
898  ?( IsStrictlyLower<MT1>::value ? i1 : i1+1UL )
899  :( N ) );
900  BLAZE_INTERNAL_ASSERT( jbegin <= jend, "Invalid loop indices detected" );
901 
902  for( size_t j=jbegin; j<jend; ++j ) {
903  y[j] += v1 * A(i1,j);
904  }
905  }
906  }
908  //**********************************************************************************************
909 
910  //**Vectorized addition assignment to dense vectors*********************************************
924  template< typename VT1 // Type of the left-hand side target vector
925  , typename VT2 // Type of the left-hand side vector operand
926  , typename MT1 > // Type of the right-hand side matrix operand
927  static inline typename EnableIf< UseVectorizedKernel<VT1,VT2,MT1> >::Type
928  selectAddAssignKernel( VT1& y, const VT2& x, const MT1& A )
929  {
930  typedef IntrinsicTrait<ElementType> IT;
932 
933  BLAZE_INTERNAL_ASSERT( x.nonZeros() != 0UL, "Invalid number of non-zero elements" );
934 
935  const size_t N( A.columns() );
936 
937  ConstIterator element( x.begin() );
938  const ConstIterator end( x.end() );
939 
940  const size_t ipos( x.nonZeros() & size_t(-4) );
941  BLAZE_INTERNAL_ASSERT( ( x.nonZeros() - ( x.nonZeros() % 4UL ) ) == ipos, "Invalid end calculation" );
942 
943  for( size_t i=0UL; (i+4UL)<=ipos; i+=4UL )
944  {
945  const size_t i1( element->index() );
946  const IntrinsicType v1( set( element->value() ) );
947  ++element;
948  const size_t i2( element->index() );
949  const IntrinsicType v2( set( element->value() ) );
950  ++element;
951  const size_t i3( element->index() );
952  const IntrinsicType v3( set( element->value() ) );
953  ++element;
954  const size_t i4( element->index() );
955  const IntrinsicType v4( set( element->value() ) );
956  ++element;
957 
958  BLAZE_INTERNAL_ASSERT( i1 < i2 && i2 < i3 && i3 < i4, "Invalid sparse vector index detected" );
959 
960  const size_t jbegin( ( IsUpper<MT1>::value )
961  ?( ( IsStrictlyUpper<MT1>::value ? i1+1UL : i1 ) & size_t(-IT::size) )
962  :( 0UL ) );
963  const size_t jend( ( IsLower<MT1>::value )
964  ?( IsStrictlyLower<MT1>::value ? i4 : i4+1UL )
965  :( N ) );
966  BLAZE_INTERNAL_ASSERT( jbegin <= jend, "Invalid loop indices detected" );
967 
968  for( size_t j=jbegin; j<jend; j+=IT::size ) {
969  y.store( j, y.load(j) + v1 * A.load(i1,j) + v2 * A.load(i2,j) + v3 * A.load(i3,j) + v4 * A.load(i4,j) );
970  }
971  }
972  for( ; element!=end; ++element )
973  {
974  const size_t i1( element->index() );
975  const IntrinsicType v1( set( element->value() ) );
976 
977  const size_t jbegin( ( IsUpper<MT1>::value )
978  ?( ( IsStrictlyUpper<MT1>::value ? i1+1UL : i1 ) & size_t(-IT::size) )
979  :( 0UL ) );
980  const size_t jend( ( IsLower<MT1>::value )
981  ?( IsStrictlyLower<MT1>::value ? i1 : i1+1UL )
982  :( N ) );
983  BLAZE_INTERNAL_ASSERT( jbegin <= jend, "Invalid loop indices detected" );
984 
985  for( size_t j=jbegin; j<jend; j+=IT::size ) {
986  y.store( j, y.load(j) + v1 * A.load(i1,j) );
987  }
988  }
989  }
991  //**********************************************************************************************
992 
993  //**Addition assignment to sparse vectors*******************************************************
994  // No special implementation for the addition assignment to sparse vectors.
995  //**********************************************************************************************
996 
997  //**Subtraction assignment to dense vectors*****************************************************
1009  template< typename VT2 > // Type of the target dense vector
1010  friend inline void subAssign( DenseVector<VT2,true>& lhs, const TSVecDMatMultExpr& rhs )
1011  {
1013 
1014  BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
1015 
1017 
1018  // Evaluation of the left-hand side sparse vector operand
1019  LT x( serial( rhs.vec_ ) );
1020  if( x.nonZeros() == 0UL ) return;
1021 
1022  // Evaluation of the right-hand side dense matrix operand
1023  RT A( serial( rhs.mat_ ) );
1024 
1025  // Checking the evaluated operands
1026  BLAZE_INTERNAL_ASSERT( x.size() == rhs.vec_.size() , "Invalid vector size" );
1027  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.mat_.rows() , "Invalid number of rows" );
1028  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.mat_.columns(), "Invalid number of columns" );
1029  BLAZE_INTERNAL_ASSERT( A.columns() == (~lhs).size() , "Invalid vector size" );
1030 
1031  // Performing the sparse vector-dense matrix multiplication
1032  TSVecDMatMultExpr::selectSubAssignKernel( ~lhs, x, A );
1033  }
1034  //**********************************************************************************************
1035 
1036  //**Default subtraction assignment to dense vectors*********************************************
1050  template< typename VT1 // Type of the left-hand side target vector
1051  , typename VT2 // Type of the left-hand side vector operand
1052  , typename MT1 > // Type of the right-hand side matrix operand
1053  static inline typename EnableIf< UseDefaultKernel<VT1,VT2,MT1> >::Type
1054  selectSubAssignKernel( VT1& y, const VT2& x, const MT1& A )
1055  {
1057 
1058  BLAZE_INTERNAL_ASSERT( x.nonZeros() != 0UL, "Invalid number of non-zero elements" );
1059 
1060  const size_t N( A.columns() );
1061 
1062  ConstIterator element( x.begin() );
1063  const ConstIterator end( x.end() );
1064 
1065  for( ; element!=end; ++element )
1066  {
1067  const size_t index( element->index() );
1068 
1070  {
1071  y[index] -= A(index,index) * element->value();
1072  }
1073  else
1074  {
1075  const size_t jbegin( ( IsUpper<MT1>::value )
1076  ?( IsStrictlyUpper<MT1>::value ? index+1UL : index )
1077  :( 0UL ) );
1078  const size_t jend( ( IsLower<MT1>::value )
1079  ?( IsStrictlyLower<MT1>::value ? index : index+1UL )
1080  :( N ) );
1081  BLAZE_INTERNAL_ASSERT( jbegin <= jend, "Invalid loop indices detected" );
1082 
1083  for( size_t j=jbegin; j<jend; ++j ) {
1084  y[j] -= element->value() * A(index,j);
1085  }
1086  }
1087  }
1088  }
1090  //**********************************************************************************************
1091 
1092  //**Optimized subtraction assignment to dense vectors*******************************************
1106  template< typename VT1 // Type of the left-hand side target vector
1107  , typename VT2 // Type of the left-hand side vector operand
1108  , typename MT1 > // Type of the right-hand side matrix operand
1109  static inline typename EnableIf< UseOptimizedKernel<VT1,VT2,MT1> >::Type
1110  selectSubAssignKernel( VT1& y, const VT2& x, const MT1& A )
1111  {
1113 
1114  BLAZE_INTERNAL_ASSERT( x.nonZeros() != 0UL, "Invalid number of non-zero elements" );
1115 
1116  const size_t N( A.columns() );
1117 
1118  ConstIterator element( x.begin() );
1119  const ConstIterator end( x.end() );
1120 
1121  const size_t ipos( x.nonZeros() & size_t(-4) );
1122  BLAZE_INTERNAL_ASSERT( ( x.nonZeros() - ( x.nonZeros() % 4UL ) ) == ipos, "Invalid end calculation" );
1123 
1124  for( size_t i=0UL; (i+4UL)<=ipos; i+=4UL )
1125  {
1126  const size_t i1( element->index() );
1127  const VET v1( element->value() );
1128  ++element;
1129  const size_t i2( element->index() );
1130  const VET v2( element->value() );
1131  ++element;
1132  const size_t i3( element->index() );
1133  const VET v3( element->value() );
1134  ++element;
1135  const size_t i4( element->index() );
1136  const VET v4( element->value() );
1137  ++element;
1138 
1139  BLAZE_INTERNAL_ASSERT( i1 < i2 && i2 < i3 && i3 < i4, "Invalid sparse vector index detected" );
1140 
1141  const size_t jbegin( ( IsUpper<MT1>::value )
1142  ?( IsStrictlyUpper<MT1>::value ? i+1UL : i1 )
1143  :( 0UL ) );
1144  const size_t jend( ( IsLower<MT1>::value )
1145  ?( IsStrictlyLower<MT1>::value ? i4 : i4+1UL )
1146  :( N ) );
1147  BLAZE_INTERNAL_ASSERT( jbegin <= jend, "Invalid loop indices detected" );
1148 
1149  for( size_t j=jbegin; j<jend; ++j ) {
1150  y[j] -= v1 * A(i1,j) + v2 * A(i2,j) + v3 * A(i3,j) + v4 * A(i4,j);
1151  }
1152  }
1153  for( ; element!=end; ++element )
1154  {
1155  const size_t i1( element->index() );
1156  const VET v1( element->value() );
1157 
1158  const size_t jbegin( ( IsUpper<MT1>::value )
1159  ?( IsStrictlyUpper<MT1>::value ? i1+1UL : i1 )
1160  :( 0UL ) );
1161  const size_t jend( ( IsLower<MT1>::value )
1162  ?( IsStrictlyLower<MT1>::value ? i1 : i1+1UL )
1163  :( N ) );
1164  BLAZE_INTERNAL_ASSERT( jbegin <= jend, "Invalid loop indices detected" );
1165 
1166  for( size_t j=jbegin; j<jend; ++j ) {
1167  y[j] -= v1 * A(i1,j);
1168  }
1169  }
1170  }
1172  //**********************************************************************************************
1173 
1174  //**Vectorized subtraction assignment to dense vectors******************************************
1188  template< typename VT1 // Type of the left-hand side target vector
1189  , typename VT2 // Type of the left-hand side vector operand
1190  , typename MT1 > // Type of the right-hand side matrix operand
1191  static inline typename EnableIf< UseVectorizedKernel<VT1,VT2,MT1> >::Type
1192  selectSubAssignKernel( VT1& y, const VT2& x, const MT1& A )
1193  {
1194  typedef IntrinsicTrait<ElementType> IT;
1196 
1197  BLAZE_INTERNAL_ASSERT( x.nonZeros() != 0UL, "Invalid number of non-zero elements" );
1198 
1199  const size_t N( A.columns() );
1200 
1201  ConstIterator element( x.begin() );
1202  const ConstIterator end( x.end() );
1203 
1204  const size_t ipos( x.nonZeros() & size_t(-4) );
1205  BLAZE_INTERNAL_ASSERT( ( x.nonZeros() - ( x.nonZeros() % 4UL ) ) == ipos, "Invalid end calculation" );
1206 
1207  for( size_t i=0UL; (i+4UL)<=ipos; i+=4UL )
1208  {
1209  const size_t i1( element->index() );
1210  const IntrinsicType v1( set( element->value() ) );
1211  ++element;
1212  const size_t i2( element->index() );
1213  const IntrinsicType v2( set( element->value() ) );
1214  ++element;
1215  const size_t i3( element->index() );
1216  const IntrinsicType v3( set( element->value() ) );
1217  ++element;
1218  const size_t i4( element->index() );
1219  const IntrinsicType v4( set( element->value() ) );
1220  ++element;
1221 
1222  BLAZE_INTERNAL_ASSERT( i1 < i2 && i2 < i3 && i3 < i4, "Invalid sparse vector index detected" );
1223 
1224  const size_t jbegin( ( IsUpper<MT1>::value )
1225  ?( ( IsStrictlyUpper<MT1>::value ? i1+1UL : i1 ) & size_t(-IT::size) )
1226  :( 0UL ) );
1227  const size_t jend( ( IsLower<MT1>::value )
1228  ?( IsStrictlyLower<MT1>::value ? i4 : i4+1UL )
1229  :( N ) );
1230  BLAZE_INTERNAL_ASSERT( jbegin <= jend, "Invalid loop indices detected" );
1231 
1232  for( size_t j=jbegin; j<jend; j+=IT::size ) {
1233  y.store( j, y.load(j) - v1 * A.load(i1,j) - v2 * A.load(i2,j) - v3 * A.load(i3,j) - v4 * A.load(i4,j) );
1234  }
1235  }
1236  for( ; element!=x.end(); ++element )
1237  {
1238  const size_t i1( element->index() );
1239  const IntrinsicType v1( set( element->value() ) );
1240 
1241  const size_t jbegin( ( IsUpper<MT1>::value )
1242  ?( ( IsStrictlyUpper<MT1>::value ? i1+1UL : i1 ) & size_t(-IT::size) )
1243  :( 0UL ) );
1244  const size_t jend( ( IsLower<MT1>::value )
1245  ?( IsStrictlyLower<MT1>::value ? i1 : i1+1UL )
1246  :( N ) );
1247  BLAZE_INTERNAL_ASSERT( jbegin <= jend, "Invalid loop indices detected" );
1248 
1249  for( size_t j=jbegin; j<jend; j+=IT::size ) {
1250  y.store( j, y.load(j) - v1 * A.load(i1,j) );
1251  }
1252  }
1253  }
1255  //**********************************************************************************************
1256 
1257  //**Subtraction assignment to sparse vectors****************************************************
1258  // No special implementation for the subtraction assignment to sparse vectors.
1259  //**********************************************************************************************
1260 
1261  //**Multiplication assignment to dense vectors**************************************************
1273  template< typename VT2 > // Type of the target dense vector
1274  friend inline void multAssign( DenseVector<VT2,true>& lhs, const TSVecDMatMultExpr& rhs )
1275  {
1277 
1281 
1282  BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
1283 
1284  const ResultType tmp( serial( rhs ) );
1285  multAssign( ~lhs, tmp );
1286  }
1287  //**********************************************************************************************
1288 
1289  //**Multiplication assignment to sparse vectors*************************************************
1290  // No special implementation for the multiplication assignment to sparse vectors.
1291  //**********************************************************************************************
1292 
1293  //**SMP assignment to dense vectors*************************************************************
1308  template< typename VT2 > // Type of the target dense vector
1309  friend inline typename EnableIf< UseSMPAssign<VT2> >::Type
1311  {
1313 
1314  BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
1315 
1316  // Evaluation of the left-hand side sparse vector operand
1317  LT x( rhs.vec_ );
1318  if( x.nonZeros() == 0UL ) {
1319  reset( ~lhs );
1320  return;
1321  }
1322 
1323  // Evaluation of the right-hand side dense matrix operand
1324  RT A( rhs.mat_ );
1325 
1326  // Checking the evaluated operands
1327  BLAZE_INTERNAL_ASSERT( x.size() == rhs.vec_.size() , "Invalid vector size" );
1328  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.mat_.rows() , "Invalid number of rows" );
1329  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.mat_.columns(), "Invalid number of columns" );
1330  BLAZE_INTERNAL_ASSERT( A.columns() == (~lhs).size() , "Invalid vector size" );
1331 
1332  // Performing the sparse vector-dense matrix multiplication
1333  smpAssign( ~lhs, x * A );
1334  }
1336  //**********************************************************************************************
1337 
1338  //**SMP assignment to sparse vectors************************************************************
1353  template< typename VT2 > // Type of the target sparse vector
1354  friend inline typename EnableIf< UseSMPAssign<VT2> >::Type
1355  smpAssign( SparseVector<VT2,true>& lhs, const TSVecDMatMultExpr& rhs )
1356  {
1358 
1362 
1363  BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
1364 
1365  const ResultType tmp( rhs );
1366  smpAssign( ~lhs, tmp );
1367  }
1369  //**********************************************************************************************
1370 
1371  //**SMP addition assignment to dense vectors****************************************************
1385  template< typename VT2 > // Type of the target dense vector
1386  friend inline typename EnableIf< UseSMPAssign<VT2> >::Type
1388  {
1390 
1391  BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
1392 
1393  // Evaluation of the left-hand side sparse vector operand
1394  LT x( rhs.vec_ );
1395  if( x.nonZeros() == 0UL ) return;
1396 
1397  // Evaluation of the right-hand side dense matrix operand
1398  RT A( rhs.mat_ );
1399 
1400  // Checking the evaluated operands
1401  BLAZE_INTERNAL_ASSERT( x.size() == rhs.vec_.size() , "Invalid vector size" );
1402  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.mat_.rows() , "Invalid number of rows" );
1403  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.mat_.columns(), "Invalid number of columns" );
1404  BLAZE_INTERNAL_ASSERT( A.columns() == (~lhs).size() , "Invalid vector size" );
1405 
1406  // Performing the sparse vector-dense matrix multiplication
1407  smpAddAssign( ~lhs, x * A );
1408  }
1409  //**********************************************************************************************
1410 
1411  //**SMP addition assignment to sparse vectors***************************************************
1412  // No special implementation for the SMP addition assignment to sparse vectors.
1413  //**********************************************************************************************
1414 
1415  //**SMP subtraction assignment to dense vectors*************************************************
1429  template< typename VT2 > // Type of the target dense vector
1430  friend inline typename EnableIf< UseSMPAssign<VT2> >::Type
1432  {
1434 
1435  BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
1436 
1438 
1439  // Evaluation of the left-hand side sparse vector operand
1440  LT x( rhs.vec_ );
1441  if( x.nonZeros() == 0UL ) return;
1442 
1443  // Evaluation of the right-hand side dense matrix operand
1444  RT A( rhs.mat_ );
1445 
1446  // Checking the evaluated operands
1447  BLAZE_INTERNAL_ASSERT( x.size() == rhs.vec_.size() , "Invalid vector size" );
1448  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.mat_.rows() , "Invalid number of rows" );
1449  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.mat_.columns(), "Invalid number of columns" );
1450  BLAZE_INTERNAL_ASSERT( A.columns() == (~lhs).size() , "Invalid vector size" );
1451 
1452  // Performing the sparse vector-dense matrix multiplication
1453  smpSubAssign( ~lhs, x * A );
1454  }
1455  //**********************************************************************************************
1456 
1457  //**SMP subtraction assignment to sparse vectors************************************************
1458  // No special implementation for the SMP subtraction assignment to sparse vectors.
1459  //**********************************************************************************************
1460 
1461  //**SMP multiplication assignment to dense vectors**********************************************
1475  template< typename VT2 > // Type of the target dense vector
1476  friend inline typename EnableIf< UseSMPAssign<VT2> >::Type
1478  {
1480 
1484 
1485  BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
1486 
1487  const ResultType tmp( rhs );
1488  smpMultAssign( ~lhs, tmp );
1489  }
1490  //**********************************************************************************************
1491 
1492  //**SMP multiplication assignment to sparse vectors*********************************************
1493  // No special implementation for the SMP multiplication assignment to sparse vectors.
1494  //**********************************************************************************************
1495 
1496  //**Compile time checks*************************************************************************
1504  //**********************************************************************************************
1505 };
1506 //*************************************************************************************************
1507 
1508 
1509 
1510 
1511 //=================================================================================================
1512 //
1513 // GLOBAL BINARY ARITHMETIC OPERATORS
1514 //
1515 //=================================================================================================
1516 
1517 //*************************************************************************************************
1548 template< typename T1, typename T2 >
1549 inline const typename DisableIf< IsMatMatMultExpr<T2>, TSVecDMatMultExpr<T1,T2> >::Type
1551 {
1553 
1554  if( (~vec).size() != (~mat).rows() )
1555  throw std::invalid_argument( "Vector and matrix sizes do not match" );
1556 
1557  return TSVecDMatMultExpr<T1,T2>( ~vec, ~mat );
1558 }
1559 //*************************************************************************************************
1560 
1561 
1562 
1563 
1564 //=================================================================================================
1565 //
1566 // GLOBAL RESTRUCTURING BINARY ARITHMETIC OPERATORS
1567 //
1568 //=================================================================================================
1569 
1570 //*************************************************************************************************
1583 template< typename T1 // Type of the left-hand side sparse vector
1584  , typename T2 // Type of the right-hand side dense matrix
1585  , bool SO > // Storage order of the right-hand side dense matrix
1586 inline const typename EnableIf< IsMatMatMultExpr<T2>, typename MultExprTrait<T1,T2>::Type >::Type
1588 {
1590 
1592 
1593  return ( vec * (~mat).leftOperand() ) * (~mat).rightOperand();
1594 }
1595 //*************************************************************************************************
1596 
1597 
1598 
1599 
1600 //=================================================================================================
1601 //
1602 // SIZE SPECIALIZATIONS
1603 //
1604 //=================================================================================================
1605 
1606 //*************************************************************************************************
1608 template< typename MT, typename VT >
1609 struct Size< TSVecDMatMultExpr<MT,VT> >
1610  : public Columns<MT>
1611 {};
1613 //*************************************************************************************************
1614 
1615 
1616 
1617 
1618 //=================================================================================================
1619 //
1620 // EXPRESSION TRAIT SPECIALIZATIONS
1621 //
1622 //=================================================================================================
1623 
1624 //*************************************************************************************************
1626 template< typename VT, typename MT, bool AF >
1627 struct SubvectorExprTrait< TSVecDMatMultExpr<VT,MT>, AF >
1628 {
1629  public:
1630  //**********************************************************************************************
1631  typedef typename MultExprTrait< typename SubvectorExprTrait<const VT,AF>::Type
1632  , typename SubmatrixExprTrait<const MT,AF>::Type >::Type Type;
1633  //**********************************************************************************************
1634 };
1636 //*************************************************************************************************
1637 
1638 } // namespace blaze
1639 
1640 #endif
IntrinsicTrait< ElementType >::Type IntrinsicType
Resulting intrinsic element type.
Definition: TSVecDMatMultExpr.h:194
bool isAliased(const T *alias) const
Returns whether the expression is aliased with the given address alias.
Definition: TSVecDMatMultExpr.h:323
Compile time check whether the given type is a computational expression template.This type trait clas...
Definition: IsComputation.h:89
friend void multAssign(DenseVector< VT2, true > &lhs, const TSVecDMatMultExpr &rhs)
Multiplication assignment of a transpose sparse vector-dense matrix multiplication to a dense vector ...
Definition: TSVecDMatMultExpr.h:1274
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:8247
Header file for basic type definitions.
TSVecDMatMultExpr< VT, MT > This
Type of this TSVecDMatMultExpr instance.
Definition: TSVecDMatMultExpr.h:190
Expression object for transpose sparse vector-dense matrix multiplications.The TSVecDMatMultExpr clas...
Definition: Forward.h:147
SelectType< IsExpression< VT >::value, const VT, const VT & >::Type LeftOperand
Composite type of the left-hand side sparse vector expression.
Definition: TSVecDMatMultExpr.h:199
BLAZE_ALWAYS_INLINE size_t size(const Vector< VT, TF > &vector)
Returns the current size/dimension of the vector.
Definition: Vector.h:264
SelectType< IsExpression< MT >::value, const MT, const MT & >::Type RightOperand
Composite type of the right-hand side sparse matrix expression.
Definition: TSVecDMatMultExpr.h:202
BLAZE_ALWAYS_INLINE MT::Iterator end(Matrix< MT, SO > &matrix, size_t i)
Returns an iterator just past the last element of row/column i.
Definition: Matrix.h:258
Efficient implementation of a compressed matrix.The CompressedMatrix class template is the represent...
Definition: CompressedMatrix.h:209
Header file for the IsDiagonal type trait.
#define BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE(T)
Constraint on the data type.In case the given data type T is not a dense, N-dimensional matrix type...
Definition: DenseMatrix.h:79
Header file for the IsSame and IsStrictlySame type traits.
LeftOperand vec_
Left-hand side sparse vector of the multiplication expression.
Definition: TSVecDMatMultExpr.h:350
void reset(const DiagonalProxy< MT > &proxy)
Resetting the represented element to the default initial values.
Definition: DiagonalProxy.h:821
const This & CompositeType
Data type for composite expression templates.
Definition: CompressedMatrix.h:2507
Type ElementType
Type of the sparse matrix elements.
Definition: CompressedMatrix.h:261
BLAZE_ALWAYS_INLINE size_t rows(const Matrix< MT, SO > &matrix)
Returns the current number of rows of the matrix.
Definition: Matrix.h:316
Header file for the DenseVector base class.
Compile time check for lower triangular matrices.This type trait tests whether or not the given templ...
Definition: IsLower.h:90
const DMatSerialExpr< MT, SO > serial(const DenseMatrix< MT, SO > &dm)
Forces the serial evaluation of the given dense matrix expression dm.
Definition: DMatSerialExpr.h:699
Header file for the Computation base class.
Type relationship analysis.This class tests if the two data types A and B are equal. For this type comparison, the cv-qualifiers of both data types are ignored. If A and B are the same data type (ignoring the cv-qualifiers), then the value member enumeration is set to 1, the nested type definition Type is TrueType, and the class derives from TrueType. Otherwise value is set to 0, Type is FalseType, and the class derives from FalseType.
Definition: IsSame.h:158
Compile time check for upper triangular matrices.This type trait tests whether or not the given templ...
Definition: IsUpper.h:90
Header file for the RequiresEvaluation type trait.
MRT::ElementType MET
Element type of the right-hand side dense matrix expression.
Definition: TSVecDMatMultExpr.h:112
Base class for dense matrices.The DenseMatrix class is a base class for all dense matrix classes...
Definition: DenseMatrix.h:70
VRT::ElementType VET
Element type of the left-hand side sparse vector expression.
Definition: TSVecDMatMultExpr.h:111
Constraint on the data type.
bool isAligned() const
Returns whether the operands of the expression are properly aligned in memory.
Definition: TSVecDMatMultExpr.h:333
bool canSMPAssign() const
Returns whether the expression can be used in SMP assignments.
Definition: TSVecDMatMultExpr.h:343
ResultType::TransposeType TransposeType
Transpose type for expression template evaluations.
Definition: TSVecDMatMultExpr.h:192
Constraint on the data type.
Header file for the MultExprTrait class template.
RightOperand mat_
Right-hand side dense matrix of the multiplication expression.
Definition: TSVecDMatMultExpr.h:351
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:263
VT::CompositeType VCT
Composite type of the left-hand side sparse vector expression.
Definition: TSVecDMatMultExpr.h:113
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.
friend void addAssign(DenseVector< VT2, true > &lhs, const TSVecDMatMultExpr &rhs)
Addition assignment of a transpose sparse vector-dense matrix multiplication to a dense vector ( )...
Definition: TSVecDMatMultExpr.h:748
Header file for the multiplication trait.
Header file for the IsStrictlyUpper type trait.
MT::CompositeType MCT
Composite type of the right-hand side dense matrix expression.
Definition: TSVecDMatMultExpr.h:114
Namespace of the Blaze C++ math library.
Definition: Blaze.h:57
const Element * ConstIterator
Iterator over constant elements.
Definition: CompressedMatrix.h:2511
Header file for the IsMatMatMultExpr type trait class.
BLAZE_ALWAYS_INLINE 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:635
Header file for the Columns type trait.
Base class for N-dimensional dense vectors.The DenseVector class is a base class for all arbitrarily ...
Definition: DenseVector.h:70
Header file for the IsLower type trait.
#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
Compile time check for diagonal matrices.This type trait tests whether or not the given template para...
Definition: IsDiagonal.h:92
SelectType< evaluateVector, const VRT, VCT >::Type LT
Type for the assignment of the left-hand side sparse vector operand.
Definition: TSVecDMatMultExpr.h:205
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
bool canAlias(const T *alias) const
Returns whether the expression can alias with the given address alias.
Definition: TSVecDMatMultExpr.h:311
Constraints on the storage order of matrix types.
Constraint on the data type.
Compile time check for strictly upper triangular matrices.This type trait tests whether or not the gi...
Definition: IsStrictlyUpper.h:86
Type ElementType
Type of the sparse matrix elements.
Definition: CompressedMatrix.h:2505
Header file for the SelectType class template.
Header file for all forward declarations for expression class templates.
Constraint on the data type.
TSVecDMatMultExpr(const VT &vec, const MT &mat)
Constructor for the TSVecDMatMultExpr class.
Definition: TSVecDMatMultExpr.h:230
Header file for the EnableIf class template.
Header file for the IsStrictlyLower type trait.
Header file for the serial shim.
SelectType< evaluateMatrix, const MRT, MCT >::Type RT
Type for the assignment of the right-hand side dense matrix operand.
Definition: TSVecDMatMultExpr.h:208
friend EnableIf< UseSMPAssign< VT2 > >::Type smpMultAssign(DenseVector< VT2, true > &lhs, const TSVecDMatMultExpr &rhs)
SMP multiplication assignment of a transpose sparse vector-dense matrix multiplication to a dense vec...
Definition: TSVecDMatMultExpr.h:1477
#define BLAZE_CONSTRAINT_MUST_NOT_BE_SYMMETRIC_MATRIX_TYPE(T)
Constraint on the data type.In case the given data type T is a symmetric matrix type, a compilation error is created.
Definition: Symmetric.h:116
Header file for the SubmatrixExprTrait class template.
#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
ResultType::ElementType ElementType
Resulting element type.
Definition: TSVecDMatMultExpr.h:193
Intrinsic characteristics of data types.The IntrinsicTrait class template provides the intrinsic char...
Definition: IntrinsicTrait.h:749
Header file for run time assertion macros.
EnableIf< IsDenseMatrix< MT1 > >::Type smpAssign(Matrix< MT1, SO1 > &lhs, const Matrix< MT2, SO2 > &rhs)
Default implementation of the SMP assignment of a matrix to a dense matrix.
Definition: DenseMatrix.h:98
const ElementType ReturnType
Return type for expression template evaluations.
Definition: TSVecDMatMultExpr.h:195
Base template for the MultTrait class.
Definition: MultTrait.h:150
friend EnableIf< UseSMPAssign< VT2 > >::Type smpAddAssign(DenseVector< VT2, true > &lhs, const TSVecDMatMultExpr &rhs)
SMP addition assignment of a transpose sparse vector-dense matrix multiplication to a dense vector ( ...
Definition: TSVecDMatMultExpr.h:1387
LeftOperand leftOperand() const
Returns the left-hand side sparse vector operand.
Definition: TSVecDMatMultExpr.h:289
Substitution Failure Is Not An Error (SFINAE) class.The EnableIf class template is an auxiliary tool ...
Definition: EnableIf.h:184
Header file for the reset shim.
Constraint on the data type.
size_t size() const
Returns the current size/dimension of the vector.
Definition: TSVecDMatMultExpr.h:279
Compile time check for data types.This type trait tests whether or not the given template parameter i...
Definition: IsBlasCompatible.h:99
ReturnType operator[](size_t index) const
Subscript operator for the direct access to the vector elements.
Definition: TSVecDMatMultExpr.h:244
Header file for the TVecMatMultExpr base class.
Constraint on the data type.
MultTrait< VRT, MRT >::Type ResultType
Result type for expression template evaluations.
Definition: TSVecDMatMultExpr.h:191
Header file for the RemoveReference type trait.
BLAZE_ALWAYS_INLINE EnableIf< And< IsIntegral< T >, HasSize< T, 2UL > >, sse_int16_t >::Type set(T value)
Sets all values in the vector to the given 2-byte integral value.
Definition: Set.h:73
Header file for all intrinsic functionality.
Compile time check for strictly lower triangular matrices.This type trait tests whether or not the gi...
Definition: IsStrictlyLower.h:86
#define BLAZE_CONSTRAINT_MUST_BE_DENSE_VECTOR_TYPE(T)
Constraint on the data type.In case the given data type T is not a dense, N-dimensional vector type...
Definition: DenseVector.h:79
#define BLAZE_CONSTRAINT_MUST_FORM_VALID_TVECMATMULTEXPR(T1, T2)
Constraint on the data type.In case the given data types T1 and T2 do not form a valid vector/matrix ...
Definition: TVecMatMultExpr.h:166
const size_t SMP_TSVECDMATMULT_THRESHOLD
SMP sparse vector/row-major dense matrix multiplication threshold.This threshold specifies when a spa...
Definition: Thresholds.h:460
Header file for the IsComputation type trait class.
friend EnableIf< UseSMPAssign< VT2 > >::Type smpSubAssign(DenseVector< VT2, true > &lhs, const TSVecDMatMultExpr &rhs)
SMP subtraction assignment of a transpose sparse vector-dense matrix multiplication to a dense vector...
Definition: TSVecDMatMultExpr.h:1431
RightOperand rightOperand() const
Returns the right-hand side dense matrix operand.
Definition: TSVecDMatMultExpr.h:299
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:2502
#define BLAZE_CONSTRAINT_MUST_BE_ROW_VECTOR_TYPE(T)
Constraint on the data type.In case the given data type T is not a row dense or sparse vector type (i...
Definition: TransposeFlag.h:81
Header file for the SubvectorExprTrait class template.
friend void subAssign(DenseVector< VT2, true > &lhs, const TSVecDMatMultExpr &rhs)
Subtraction assignment of a transpose sparse vector-dense matrix multiplication to a dense vector ( )...
Definition: TSVecDMatMultExpr.h:1010
Header file for the IsUpper type trait.
Header file for the IsResizable type trait.
const ResultType CompositeType
Data type for composite expression templates.
Definition: TSVecDMatMultExpr.h:196
Header file for the Size type trait.
Header file for the thresholds for matrix/vector and matrix/matrix multiplications.
#define BLAZE_INTERNAL_ASSERT(expr, msg)
Run time assertion macro for internal checks.In case of an invalid run time expression, the program execution is terminated. The BLAZE_INTERNAL_ASSERT macro can be disabled by setting the BLAZE_USER_ASSERTION flag to zero or by defining NDEBUG during the compilation.
Definition: Assert.h:101
VT::ResultType VRT
Result type of the left-hand side sparse vector expression.
Definition: TSVecDMatMultExpr.h:109
MT::ResultType MRT
Result type of the right-hand side dense matrix expression.
Definition: TSVecDMatMultExpr.h:110
Header file for the IsExpression type trait class.
Header file for the FunctionTrace class.