Blaze  3.6
SVecSVecOuterExpr.h
Go to the documentation of this file.
1 //=================================================================================================
33 //=================================================================================================
34 
35 #ifndef _BLAZE_MATH_EXPRESSIONS_SVECSVECOUTEREXPR_H_
36 #define _BLAZE_MATH_EXPRESSIONS_SVECSVECOUTEREXPR_H_
37 
38 
39 //*************************************************************************************************
40 // Includes
41 //*************************************************************************************************
42 
43 #include <utility>
44 #include <blaze/math/Aliases.h>
52 #include <blaze/math/Exception.h>
64 #include <blaze/util/Assert.h>
66 #include <blaze/util/mpl/If.h>
67 #include <blaze/util/Types.h>
68 
69 
70 namespace blaze {
71 
72 //=================================================================================================
73 //
74 // CLASS SVECSVECOUTEREXPR
75 //
76 //=================================================================================================
77 
78 //*************************************************************************************************
85 template< typename VT1 // Type of the left-hand side sparse vector
86  , typename VT2 > // Type of the right-hand side sparse vector
87 class SVecSVecOuterExpr
88  : public VecTVecMultExpr< SparseMatrix< SVecSVecOuterExpr<VT1,VT2>, false > >
89  , private Computation
90 {
91  private:
92  //**Type definitions****************************************************************************
99  //**********************************************************************************************
100 
101  //**Return type evaluation**********************************************************************
103 
108  static constexpr bool returnExpr = ( !IsTemporary_v<RN1> && !IsTemporary_v<RN2> );
109 
111  using ExprReturnType = decltype( std::declval<RN1>() * std::declval<RN2>() );
112  //**********************************************************************************************
113 
114  public:
115  //**Type definitions****************************************************************************
122 
125 
127  using CompositeType = const ResultType;
128 
130  using LeftOperand = If_t< IsExpression_v<VT1>, const VT1, const VT1& >;
131 
133  using RightOperand = If_t< IsExpression_v<VT2>, const VT2, const VT2& >;
134 
137 
140  //**********************************************************************************************
141 
142  //**Compilation flags***************************************************************************
144  static constexpr bool smpAssignable = false;
145  //**********************************************************************************************
146 
147  //**Constructor*********************************************************************************
153  explicit inline SVecSVecOuterExpr( const VT1& lhs, const VT2& rhs ) noexcept
154  : lhs_( lhs ) // Left-hand side sparse vector of the multiplication expression
155  , rhs_( rhs ) // Right-hand side sparse vector of the multiplication expression
156  {}
157  //**********************************************************************************************
158 
159  //**Access operator*****************************************************************************
166  inline ReturnType operator()( size_t i, size_t j ) const {
167  BLAZE_INTERNAL_ASSERT( i < lhs_.size(), "Invalid row access index" );
168  BLAZE_INTERNAL_ASSERT( j < rhs_.size(), "Invalid column access index" );
169 
170  return lhs_[i] * rhs_[j];
171  }
172  //**********************************************************************************************
173 
174  //**At function*********************************************************************************
182  inline ReturnType at( size_t i, size_t j ) const {
183  if( i >= lhs_.size() ) {
184  BLAZE_THROW_OUT_OF_RANGE( "Invalid row access index" );
185  }
186  if( j >= rhs_.size() ) {
187  BLAZE_THROW_OUT_OF_RANGE( "Invalid column access index" );
188  }
189  return (*this)(i,j);
190  }
191  //**********************************************************************************************
192 
193  //**Rows function*******************************************************************************
198  inline size_t rows() const noexcept {
199  return lhs_.size();
200  }
201  //**********************************************************************************************
202 
203  //**Columns function****************************************************************************
208  inline size_t columns() const noexcept {
209  return rhs_.size();
210  }
211  //**********************************************************************************************
212 
213  //**NonZeros function***************************************************************************
218  inline size_t nonZeros() const {
219  return lhs_.nonZeros() * rhs_.nonZeros();
220  }
221  //**********************************************************************************************
222 
223  //**NonZeros function***************************************************************************
229  inline size_t nonZeros( size_t i ) const {
230  return ( isDefault( lhs_[i] ) )?( size_t(0) ):( rhs_.nonZeros(i) );
231  }
232  //**********************************************************************************************
233 
234  //**Left operand access*************************************************************************
239  inline LeftOperand leftOperand() const noexcept {
240  return lhs_;
241  }
242  //**********************************************************************************************
243 
244  //**Right operand access************************************************************************
249  inline RightOperand rightOperand() const noexcept {
250  return rhs_;
251  }
252  //**********************************************************************************************
253 
254  //**********************************************************************************************
260  template< typename T >
261  inline bool canAlias( const T* alias ) const noexcept {
262  return ( lhs_.canAlias( alias ) || rhs_.canAlias( alias ) );
263  }
264  //**********************************************************************************************
265 
266  //**********************************************************************************************
272  template< typename T >
273  inline bool isAliased( const T* alias ) const noexcept {
274  return ( lhs_.isAliased( alias ) || rhs_.isAliased( alias ) );
275  }
276  //**********************************************************************************************
277 
278  private:
279  //**Member variables****************************************************************************
282  //**********************************************************************************************
283 
284  //**Assignment to row-major dense matrices******************************************************
296  template< typename MT > // Type of the target dense matrix
297  friend inline void assign( DenseMatrix<MT,false>& lhs, const SVecSVecOuterExpr& rhs )
298  {
300 
301  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
302  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
303 
304  LT x( serial( rhs.lhs_ ) ); // Evaluation of the left-hand side sparse vector operand
305  RT y( serial( rhs.rhs_ ) ); // Evaluation of the right-hand side sparse vector operand
306 
307  BLAZE_INTERNAL_ASSERT( x.size() == rhs.lhs_.size() , "Invalid vector size" );
308  BLAZE_INTERNAL_ASSERT( y.size() == rhs.rhs_.size() , "Invalid vector size" );
309  BLAZE_INTERNAL_ASSERT( x.size() == (~lhs).rows() , "Invalid vector size" );
310  BLAZE_INTERNAL_ASSERT( y.size() == (~lhs).columns(), "Invalid vector size" );
311 
312  const auto lend( x.end() );
313  const auto rend( y.end() );
314 
315  for( auto lelem=x.begin(); lelem!=lend; ++lelem ) {
316  if( !isDefault( lelem->value() ) ) {
317  for( auto relem=y.begin(); relem!=rend; ++relem ) {
318  (~lhs)(lelem->index(),relem->index()) = lelem->value() * relem->value();
319  }
320  }
321  }
322  }
324  //**********************************************************************************************
325 
326  //**Assignment to column-major dense matrices***************************************************
339  template< typename MT > // Type of the target dense matrix
340  friend inline void assign( DenseMatrix<MT,true>& lhs, const SVecSVecOuterExpr& rhs )
341  {
343 
345 
346  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
347  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
348 
349  LT x( serial( rhs.lhs_ ) ); // Evaluation of the left-hand side sparse vector operand
350  RT y( serial( rhs.rhs_ ) ); // Evaluation of the right-hand side sparse vector operand
351 
352  BLAZE_INTERNAL_ASSERT( x.size() == rhs.lhs_.size() , "Invalid vector size" );
353  BLAZE_INTERNAL_ASSERT( y.size() == rhs.rhs_.size() , "Invalid vector size" );
354  BLAZE_INTERNAL_ASSERT( x.size() == (~lhs).rows() , "Invalid vector size" );
355  BLAZE_INTERNAL_ASSERT( y.size() == (~lhs).columns(), "Invalid vector size" );
356 
357  const auto lend( x.end() );
358  const auto rend( y.end() );
359 
360  for( auto relem=y.begin(); relem!=rend; ++relem ) {
361  if( !isDefault( relem->value() ) ) {
362  for( auto lelem=x.begin(); lelem!=lend; ++lelem ) {
363  (~lhs)(lelem->index(),relem->index()) = lelem->value() * relem->value();
364  }
365  }
366  }
367  }
369  //**********************************************************************************************
370 
371  //**Assignment to row-major sparse matrices*****************************************************
383  template< typename MT > // Type of the target sparse matrix
384  friend inline void assign( SparseMatrix<MT,false>& lhs, const SVecSVecOuterExpr& rhs )
385  {
387 
388  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
389  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns() , "Invalid number of columns" );
390  BLAZE_INTERNAL_ASSERT( (~lhs).capacity() >= rhs.nonZeros(), "Insufficient capacity" );
391 
392  LT x( serial( rhs.lhs_ ) ); // Evaluation of the left-hand side sparse vector operand
393  RT y( serial( rhs.rhs_ ) ); // Evaluation of the right-hand side sparse vector operand
394 
395  BLAZE_INTERNAL_ASSERT( x.size() == rhs.lhs_.size() , "Invalid vector size" );
396  BLAZE_INTERNAL_ASSERT( y.size() == rhs.rhs_.size() , "Invalid vector size" );
397  BLAZE_INTERNAL_ASSERT( x.size() == (~lhs).rows() , "Invalid vector size" );
398  BLAZE_INTERNAL_ASSERT( y.size() == (~lhs).columns(), "Invalid vector size" );
399 
400  // Final memory allocation (based on the evaluated operands)
401  (~lhs).reserve( x.nonZeros() * y.nonZeros() );
402 
403  // Performing the outer product
404  const auto lend( x.end() );
405  const auto rend( y.end() );
406  size_t index( 0UL );
407 
408  for( auto lelem=x.begin(); lelem!=lend; ++lelem ) {
409  if( !isDefault( lelem->value() ) ) {
410  for( ; index < lelem->index(); ++index ) {
411  (~lhs).finalize( index );
412  }
413  for( auto relem=y.begin(); relem!=rend; ++relem ) {
414  (~lhs).append( lelem->index(), relem->index(), lelem->value() * relem->value() );
415  }
416  (~lhs).finalize( index++ );
417  }
418  }
419 
420  for( ; index < x.size(); ++index ) {
421  (~lhs).finalize( index );
422  }
423  }
425  //**********************************************************************************************
426 
427  //**Assignment to column-major sparse matrices**************************************************
440  template< typename MT > // Type of the target sparse matrix
441  friend inline void assign( SparseMatrix<MT,true>& lhs, const SVecSVecOuterExpr& rhs )
442  {
444 
446 
447  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
448  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns() , "Invalid number of columns" );
449  BLAZE_INTERNAL_ASSERT( (~lhs).capacity() >= rhs.nonZeros(), "Insufficient capacity" );
450 
451  LT x( serial( rhs.lhs_ ) ); // Evaluation of the left-hand side sparse vector operand
452  RT y( serial( rhs.rhs_ ) ); // Evaluation of the right-hand side sparse vector operand
453 
454  BLAZE_INTERNAL_ASSERT( x.size() == rhs.lhs_.size() , "Invalid vector size" );
455  BLAZE_INTERNAL_ASSERT( y.size() == rhs.rhs_.size() , "Invalid vector size" );
456  BLAZE_INTERNAL_ASSERT( x.size() == (~lhs).rows() , "Invalid vector size" );
457  BLAZE_INTERNAL_ASSERT( y.size() == (~lhs).columns(), "Invalid vector size" );
458 
459  const auto lend( x.end() );
460  const auto rend( y.end() );
461  size_t index( 0UL );
462 
463  for( auto relem=y.begin(); relem!=rend; ++relem ) {
464  if( !isDefault( relem->value() ) ) {
465  for( ; index < relem->index(); ++index ) {
466  (~lhs).finalize( index );
467  }
468  for( auto lelem=x.begin(); lelem!=lend; ++lelem ) {
469  (~lhs).append( lelem->index(), relem->index(), lelem->value() * relem->value() );
470  }
471  (~lhs).finalize( index++ );
472  }
473  }
474 
475  for( ; index < y.size(); ++index ) {
476  (~lhs).finalize( index );
477  }
478  }
480  //**********************************************************************************************
481 
482  //**Addition assignment to row-major dense matrices*********************************************
495  template< typename MT > // Type of the target dense matrix
496  friend inline void addAssign( DenseMatrix<MT,false>& lhs, const SVecSVecOuterExpr& rhs )
497  {
499 
500  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
501  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
502 
503  LT x( serial( rhs.lhs_ ) ); // Evaluation of the left-hand side sparse vector operand
504  RT y( serial( rhs.rhs_ ) ); // Evaluation of the right-hand side sparse vector operand
505 
506  BLAZE_INTERNAL_ASSERT( x.size() == rhs.lhs_.size() , "Invalid vector size" );
507  BLAZE_INTERNAL_ASSERT( y.size() == rhs.rhs_.size() , "Invalid vector size" );
508  BLAZE_INTERNAL_ASSERT( x.size() == (~lhs).rows() , "Invalid vector size" );
509  BLAZE_INTERNAL_ASSERT( y.size() == (~lhs).columns(), "Invalid vector size" );
510 
511  const auto lend( x.end() );
512  const auto rend( y.end() );
513 
514  for( auto lelem=x.begin(); lelem!=lend; ++lelem ) {
515  if( !isDefault( lelem->value() ) ) {
516  for( auto relem=y.begin(); relem!=rend; ++relem ) {
517  (~lhs)(lelem->index(),relem->index()) += lelem->value() * relem->value();
518  }
519  }
520  }
521  }
523  //**********************************************************************************************
524 
525  //**Addition assignment to column-major dense matrices******************************************
538  template< typename MT > // Type of the target dense matrix
539  friend inline void addAssign( DenseMatrix<MT,true>& lhs, const SVecSVecOuterExpr& rhs )
540  {
542 
544 
545  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
546  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
547 
548  LT x( serial( rhs.lhs_ ) ); // Evaluation of the left-hand side sparse vector operand
549  RT y( serial( rhs.rhs_ ) ); // Evaluation of the right-hand side sparse vector operand
550 
551  BLAZE_INTERNAL_ASSERT( x.size() == rhs.lhs_.size() , "Invalid vector size" );
552  BLAZE_INTERNAL_ASSERT( y.size() == rhs.rhs_.size() , "Invalid vector size" );
553  BLAZE_INTERNAL_ASSERT( x.size() == (~lhs).rows() , "Invalid vector size" );
554  BLAZE_INTERNAL_ASSERT( y.size() == (~lhs).columns(), "Invalid vector size" );
555 
556  const auto lend( x.end() );
557  const auto rend( y.end() );
558 
559  for( auto relem=y.begin(); relem!=rend; ++relem ) {
560  if( !isDefault( relem->value() ) ) {
561  for( auto lelem=x.begin(); lelem!=lend; ++lelem ) {
562  (~lhs)(lelem->index(),relem->index()) += lelem->value() * relem->value();
563  }
564  }
565  }
566  }
568  //**********************************************************************************************
569 
570  //**Addition assignment to sparse matrices******************************************************
571  // No special implementation for the addition assignment to sparse matrices.
572  //**********************************************************************************************
573 
574  //**Subtraction assignment to row-major dense matrices******************************************
587  template< typename MT > // Type of the target dense matrix
588  friend inline void subAssign( DenseMatrix<MT,false>& lhs, const SVecSVecOuterExpr& rhs )
589  {
591 
592  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
593  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
594 
595  LT x( serial( rhs.lhs_ ) ); // Evaluation of the left-hand side sparse vector operand
596  RT y( serial( rhs.rhs_ ) ); // Evaluation of the right-hand side sparse vector operand
597 
598  BLAZE_INTERNAL_ASSERT( x.size() == rhs.lhs_.size() , "Invalid vector size" );
599  BLAZE_INTERNAL_ASSERT( y.size() == rhs.rhs_.size() , "Invalid vector size" );
600  BLAZE_INTERNAL_ASSERT( x.size() == (~lhs).rows() , "Invalid vector size" );
601  BLAZE_INTERNAL_ASSERT( y.size() == (~lhs).columns(), "Invalid vector size" );
602 
603  const auto lend( x.end() );
604  const auto rend( y.end() );
605 
606  for( auto lelem=x.begin(); lelem!=lend; ++lelem ) {
607  if( !isDefault( lelem->value() ) ) {
608  for( auto relem=y.begin(); relem!=rend; ++relem ) {
609  (~lhs)(lelem->index(),relem->index()) -= lelem->value() * relem->value();
610  }
611  }
612  }
613  }
615  //**********************************************************************************************
616 
617  //**Subtraction assignment to column-major dense matrices***************************************
630  template< typename MT > // Type of the target dense matrix
631  friend inline void subAssign( DenseMatrix<MT,true>& lhs, const SVecSVecOuterExpr& rhs )
632  {
634 
636 
637  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
638  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
639 
640  LT x( serial( rhs.lhs_ ) ); // Evaluation of the left-hand side sparse vector operand
641  RT y( serial( rhs.rhs_ ) ); // Evaluation of the right-hand side sparse vector operand
642 
643  BLAZE_INTERNAL_ASSERT( x.size() == rhs.lhs_.size() , "Invalid vector size" );
644  BLAZE_INTERNAL_ASSERT( y.size() == rhs.rhs_.size() , "Invalid vector size" );
645  BLAZE_INTERNAL_ASSERT( x.size() == (~lhs).rows() , "Invalid vector size" );
646  BLAZE_INTERNAL_ASSERT( y.size() == (~lhs).columns(), "Invalid vector size" );
647 
648  const auto lend( x.end() );
649  const auto rend( y.end() );
650 
651  for( auto relem=y.begin(); relem!=rend; ++relem ) {
652  if( !isDefault( relem->value() ) ) {
653  for( auto lelem=x.begin(); lelem!=lend; ++lelem ) {
654  (~lhs)(lelem->index(),relem->index()) -= lelem->value() * relem->value();
655  }
656  }
657  }
658  }
660  //**********************************************************************************************
661 
662  //**Subtraction assignment to sparse matrices***************************************************
663  // No special implementation for the subtraction assignment to sparse matrices.
664  //**********************************************************************************************
665 
666  //**Schur product assignment to row-major dense matrices****************************************
679  template< typename MT > // Type of the target dense matrix
680  friend inline void schurAssign( DenseMatrix<MT,false>& lhs, const SVecSVecOuterExpr& rhs )
681  {
683 
684  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
685  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
686 
687  LT x( serial( rhs.lhs_ ) ); // Evaluation of the left-hand side sparse vector operand
688  RT y( serial( rhs.rhs_ ) ); // Evaluation of the right-hand side sparse vector operand
689 
690  BLAZE_INTERNAL_ASSERT( x.size() == rhs.lhs_.size() , "Invalid vector size" );
691  BLAZE_INTERNAL_ASSERT( y.size() == rhs.rhs_.size() , "Invalid vector size" );
692  BLAZE_INTERNAL_ASSERT( x.size() == (~lhs).rows() , "Invalid vector size" );
693  BLAZE_INTERNAL_ASSERT( y.size() == (~lhs).columns(), "Invalid vector size" );
694 
695  const auto lend( x.end() );
696  const auto rend( y.end() );
697 
698  size_t i( 0UL );
699 
700  for( auto lelem=x.begin(); lelem!=lend; ++lelem )
701  {
702  if( isDefault( lelem->value() ) ) continue;
703 
704  for( ; i<lelem->index(); ++i ) {
705  for( size_t j=0UL; j<y.size(); ++j )
706  reset( (~lhs)(i,j) );
707  }
708 
709  size_t j( 0UL );
710 
711  for( auto relem=y.begin(); relem!=rend; ++relem, ++j ) {
712  for( ; j<relem->index(); ++j )
713  reset( (~lhs)(i,j) );
714  (~lhs)(lelem->index(),relem->index()) *= lelem->value() * relem->value();
715  }
716 
717  for( ; j<y.size(); ++j ) {
718  reset( (~lhs)(i,j) );
719  }
720 
721  ++i;
722  }
723 
724  for( ; i<x.size(); ++i ) {
725  for( size_t j=0UL; j<y.size(); ++j )
726  reset( (~lhs)(i,j) );
727  }
728  }
730  //**********************************************************************************************
731 
732  //**Schur product assignment to column-major dense matrices*************************************
745  template< typename MT > // Type of the target dense matrix
746  friend inline void schurAssign( DenseMatrix<MT,true>& lhs, const SVecSVecOuterExpr& rhs )
747  {
749 
751 
752  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
753  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
754 
755  LT x( serial( rhs.lhs_ ) ); // Evaluation of the left-hand side sparse vector operand
756  RT y( serial( rhs.rhs_ ) ); // Evaluation of the right-hand side sparse vector operand
757 
758  BLAZE_INTERNAL_ASSERT( x.size() == rhs.lhs_.size() , "Invalid vector size" );
759  BLAZE_INTERNAL_ASSERT( y.size() == rhs.rhs_.size() , "Invalid vector size" );
760  BLAZE_INTERNAL_ASSERT( x.size() == (~lhs).rows() , "Invalid vector size" );
761  BLAZE_INTERNAL_ASSERT( y.size() == (~lhs).columns(), "Invalid vector size" );
762 
763  const auto lend( x.end() );
764  const auto rend( y.end() );
765 
766  size_t j( 0UL );
767 
768  for( auto relem=y.begin(); relem!=rend; ++relem )
769  {
770  if( isDefault( relem->value() ) ) continue;
771 
772  for( ; j<relem->index(); ++j ) {
773  for( size_t i=0UL; i<x.size(); ++i )
774  reset( (~lhs)(i,j) );
775  }
776 
777  size_t i( 0UL );
778 
779  for( auto lelem=x.begin(); lelem!=lend; ++lelem, ++i ) {
780  for( ; i<lelem->index(); ++i )
781  reset( (~lhs)(i,j) );
782  (~lhs)(lelem->index(),relem->index()) *= lelem->value() * relem->value();
783  }
784 
785  for( ; i<x.size(); ++i ) {
786  reset( (~lhs)(i,j) );
787  }
788 
789  ++j;
790  }
791 
792  for( ; j<y.size(); ++j ) {
793  for( size_t i=0UL; i<x.size(); ++i )
794  reset( (~lhs)(i,j) );
795  }
796  }
798  //**********************************************************************************************
799 
800  //**Schur product assignment to sparse matrices*************************************************
801  // No special implementation for the Schur product assignment to sparse matrices.
802  //**********************************************************************************************
803 
804  //**Multiplication assignment to dense matrices*************************************************
805  // No special implementation for the multiplication assignment to dense matrices.
806  //**********************************************************************************************
807 
808  //**Multiplication assignment to sparse matrices************************************************
809  // No special implementation for the multiplication assignment to sparse matrices.
810  //**********************************************************************************************
811 
812  //**Compile time checks*************************************************************************
822  //**********************************************************************************************
823 };
824 //*************************************************************************************************
825 
826 
827 
828 
829 //=================================================================================================
830 //
831 // GLOBAL BINARY ARITHMETIC OPERATORS
832 //
833 //=================================================================================================
834 
835 //*************************************************************************************************
848 template< typename VT1 // Type of the left-hand side sparse vector
849  , typename VT2 // Type of the right-hand side sparse vector
850  , DisableIf_t< IsZero_v<VT1> || IsZero_v<VT2> >* = nullptr >
851 inline const SVecSVecOuterExpr<VT1,VT2>
852  svecsvecouter( const SparseVector<VT1,false>& lhs, const SparseVector<VT2,true>& rhs )
853 {
855 
856  return SVecSVecOuterExpr<VT1,VT2>( ~lhs, ~rhs );
857 }
859 //*************************************************************************************************
860 
861 
862 //*************************************************************************************************
875 template< typename VT1 // Type of the left-hand side sparse vector
876  , typename VT2 // Type of the right-hand side sparse vector
877  , EnableIf_t< IsZero_v<VT1> || IsZero_v<VT2> >* = nullptr >
878 inline decltype(auto)
879  svecsvecouter( const SparseVector<VT1,false>& lhs, const SparseVector<VT2,true>& rhs )
880 {
882 
883  using ReturnType = const MultTrait_t< ResultType_t<VT1>, ResultType_t<VT2> >;
884 
887 
888  return ReturnType( (~lhs).size(), (~rhs).size() );
889 }
891 //*************************************************************************************************
892 
893 
894 //*************************************************************************************************
921 template< typename VT1 // Type of the left-hand side sparse vector
922  , typename VT2 > // Type of the right-hand side sparse vector
923 inline decltype(auto)
924  operator*( const SparseVector<VT1,false>& lhs, const SparseVector<VT2,true>& rhs )
925 {
927 
928  return svecsvecouter( ~lhs, ~rhs );
929 }
930 //*************************************************************************************************
931 
932 } // namespace blaze
933 
934 #endif
LeftOperand leftOperand() const noexcept
Returns the left-hand side sparse vector operand.
Definition: SVecSVecOuterExpr.h:239
Header file for auxiliary alias declarations.
ReturnType operator()(size_t i, size_t j) const
2D-access to the matrix elements.
Definition: SVecSVecOuterExpr.h:166
size_t capacity(const Matrix< MT, SO > &matrix) noexcept
Returns the maximum capacity of the matrix.
Definition: Matrix.h:546
static constexpr bool smpAssignable
Compilation switch for the expression template assignment strategy.
Definition: SVecSVecOuterExpr.h:144
Header file for basic type definitions.
Expression object for sparse vector-sparse vector outer products.The SVecSVecOuterExpr class represen...
Definition: Forward.h:163
typename If< Condition, T1, T2 >::Type If_t
Auxiliary alias template for the If class template.The If_t alias template provides a convenient shor...
Definition: If.h:109
typename T::ResultType ResultType_t
Alias declaration for nested ResultType type definitions.The ResultType_t alias declaration provides ...
Definition: Aliases.h:390
#define BLAZE_CONSTRAINT_MUST_BE_COLUMN_VECTOR_TYPE(T)
Constraint on the data type.In case the given data type T is not a column dense or sparse vector type...
Definition: ColumnVector.h:61
Header file for the serial shim.
static constexpr bool returnExpr
Compilation switch for the selection of the subscript operator return type.
Definition: SVecSVecOuterExpr.h:108
If_t< IsComputation_v< VT2 >, const RT2, CT2 > RT
Type for the assignment of the right-hand side sparse vector operand.
Definition: SVecSVecOuterExpr.h:139
void reset(const DiagonalProxy< MT > &proxy)
Resetting the represented element to the default initial values.
Definition: DiagonalProxy.h:595
CompositeType_t< VT2 > CT2
Composite type of the right-hand side sparse vector expression.
Definition: SVecSVecOuterExpr.h:98
Constraint on the data type.
If_t< IsExpression_v< VT2 >, const VT2, const VT2 & > RightOperand
Composite type of the right-hand side sparse vector expression.
Definition: SVecSVecOuterExpr.h:133
size_t rows() const noexcept
Returns the current number of rows of the matrix.
Definition: SVecSVecOuterExpr.h:198
Header file for the Computation base class.
ResultType_t< VT2 > RT2
Result type of the right-hand side sparse vector expression.
Definition: SVecSVecOuterExpr.h:94
RightOperand rightOperand() const noexcept
Returns the right-hand side sparse vector operand.
Definition: SVecSVecOuterExpr.h:249
typename T::ReturnType ReturnType_t
Alias declaration for nested ReturnType type definitions.The ReturnType_t alias declaration provides ...
Definition: Aliases.h:410
Base class for dense matrices.The DenseMatrix class is a base class for all dense matrix classes....
Definition: DenseMatrix.h:81
Base class for sparse matrices.The SparseMatrix class is a base class for all sparse matrix classes....
Definition: Forward.h:145
typename T::ElementType ElementType_t
Alias declaration for nested ElementType type definitions.The ElementType_t alias declaration provide...
Definition: Aliases.h:170
size_t nonZeros(size_t i) const
Returns the number of non-zero elements in the specified row.
Definition: SVecSVecOuterExpr.h:229
size_t nonZeros() const
Returns the number of non-zero elements in the sparse matrix.
Definition: SVecSVecOuterExpr.h:218
Header file for the SparseMatrix base class.
Constraint on the transpose flag of vector types.
RightOperand rhs_
Right-hand side sparse vector of the multiplication expression.
Definition: SVecSVecOuterExpr.h:281
Constraint on the data type.
Header file for the IsTemporary type trait class.
Header file for the multiplication trait.
Namespace of the Blaze C++ math library.
Definition: Blaze.h:58
Header file for the If class template.
ElementType_t< ResultType > ElementType
Resulting element type.
Definition: SVecSVecOuterExpr.h:121
#define BLAZE_CONSTRAINT_MUST_BE_ZERO_TYPE(T)
Constraint on the data type.In case the given data type T is not a zero vector or matrix type,...
Definition: Zero.h:61
CompositeType_t< VT1 > CT1
Composite type of the left-hand side sparse vector expression.
Definition: SVecSVecOuterExpr.h:97
#define BLAZE_CONSTRAINT_MUST_FORM_VALID_VECTVECMULTEXPR(T1, T2)
Constraint on the data type.In case the given data types T1 and T2 do not form a valid vector/vector ...
Definition: VecTVecMultExpr.h:103
#define BLAZE_THROW_OUT_OF_RANGE(MESSAGE)
Macro for the emission of a std::out_of_range exception.This macro encapsulates the default way of Bl...
Definition: Exception.h:331
#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:61
SVecSVecOuterExpr(const VT1 &lhs, const VT2 &rhs) noexcept
Constructor for the SVecSVecOuterExpr class.
Definition: SVecSVecOuterExpr.h:153
Header file for the exception macros of the math module.
TransposeType_t< ResultType > TransposeType
Transpose type for expression template evaluations.
Definition: SVecSVecOuterExpr.h:120
Constraint on the data type.
Header file for the VecTVecMultExpr base class.
typename MultTrait< T1, T2 >::Type MultTrait_t
Auxiliary alias declaration for the MultTrait class template.The MultTrait_t alias declaration provid...
Definition: MultTrait.h:240
typename T::OppositeType OppositeType_t
Alias declaration for nested OppositeType type definitions.The OppositeType_t alias declaration provi...
Definition: Aliases.h:270
ReturnType_t< VT1 > RN1
Return type of the left-hand side sparse vector expression.
Definition: SVecSVecOuterExpr.h:95
#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,...
Definition: Symmetric.h:79
#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: RowMajorMatrix.h:61
typename T::TransposeType TransposeType_t
Alias declaration for nested TransposeType type definitions.The TransposeType_t alias declaration pro...
Definition: Aliases.h:470
OppositeType_t< ResultType > OppositeType
Result type with opposite storage order for expression template evaluations.
Definition: SVecSVecOuterExpr.h:119
Header file for run time assertion macros.
typename T::CompositeType CompositeType_t
Alias declaration for nested CompositeType type definitions.The CompositeType_t alias declaration pro...
Definition: Aliases.h:90
ResultType_t< VT1 > RT1
Result type of the left-hand side sparse vector expression.
Definition: SVecSVecOuterExpr.h:93
Header file for the IsZero type trait.
#define BLAZE_FUNCTION_TRACE
Function trace macro.This macro can be used to reliably trace function calls. In case function tracin...
Definition: FunctionTrace.h:94
Header file for all forward declarations for expression class templates.
Header file for the isDefault shim.
constexpr size_t size(const Matrix< MT, SO > &matrix) noexcept
Returns the total number of elements of the matrix.
Definition: Matrix.h:530
Constraint on the data type.
decltype(auto) serial(const DenseMatrix< MT, SO > &dm)
Forces the serial evaluation of the given dense matrix expression dm.
Definition: DMatSerialExpr.h:808
Constraint on the data type.
size_t columns() const noexcept
Returns the current number of columns of the matrix.
Definition: SVecSVecOuterExpr.h:208
ReturnType at(size_t i, size_t j) const
Checked access to the matrix elements.
Definition: SVecSVecOuterExpr.h:182
ReturnType_t< VT2 > RN2
Return type of the right-hand side sparse vector expression.
Definition: SVecSVecOuterExpr.h:96
const ResultType CompositeType
Data type for composite expression templates.
Definition: SVecSVecOuterExpr.h:127
If_t< IsComputation_v< VT1 >, const RT1, CT1 > LT
Type for the assignment of the left-hand side sparse vector operand.
Definition: SVecSVecOuterExpr.h:136
Header file for the IsComputation type trait class.
bool canAlias(const T *alias) const noexcept
Returns whether the expression can alias with the given address alias.
Definition: SVecSVecOuterExpr.h:261
Base class for sparse vectors.The SparseVector class is a base class for all arbitrarily sized (N-dim...
Definition: Forward.h:146
const If_t< returnExpr, ExprReturnType, ElementType > ReturnType
Return type for expression template evaluations.
Definition: SVecSVecOuterExpr.h:124
#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: RowVector.h:61
bool isDefault(const DiagonalProxy< MT > &proxy)
Returns whether the represented element is in default state.
Definition: DiagonalProxy.h:635
MultTrait_t< RT1, RT2 > ResultType
Result type for expression template evaluations.
Definition: SVecSVecOuterExpr.h:118
bool isAliased(const T *alias) const noexcept
Returns whether the expression is aliased with the given address alias.
Definition: SVecSVecOuterExpr.h:273
If_t< IsExpression_v< VT1 >, const VT1, const VT1 & > LeftOperand
Composite type of the left-hand side sparse vector expression.
Definition: SVecSVecOuterExpr.h:130
#define BLAZE_CONSTRAINT_MUST_NOT_BE_ZERO_TYPE(T)
Constraint on the data type.In case the given data type T is a zero vector or matrix type,...
Definition: Zero.h:81
Size type of the Blaze library.
#define BLAZE_INTERNAL_ASSERT(expr, msg)
Run time assertion macro for internal checks.In case of an invalid run time expression,...
Definition: Assert.h:101
Constraint on the transpose flag of vector types.
Header file for the IsExpression type trait class.
Header file for the function trace functionality.
decltype(std::declval< RN1 >() *std::declval< RN2 >()) ExprReturnType
Expression return type for the subscript operator.
Definition: SVecSVecOuterExpr.h:111
LeftOperand lhs_
Left-hand side sparse vector of the multiplication expression.
Definition: SVecSVecOuterExpr.h:280