Blaze  3.6
SMatDMatKronExpr.h
Go to the documentation of this file.
1 //=================================================================================================
33 //=================================================================================================
34 
35 #ifndef _BLAZE_MATH_EXPRESSIONS_SMATDMATKRONEXPR_H_
36 #define _BLAZE_MATH_EXPRESSIONS_SMATDMATKRONEXPR_H_
37 
38 
39 //*************************************************************************************************
40 // Includes
41 //*************************************************************************************************
42 
43 #include <utility>
44 #include <blaze/math/Aliases.h>
50 #include <blaze/math/Exception.h>
55 #include <blaze/math/shims/Reset.h>
67 #include <blaze/util/Assert.h>
68 #include <blaze/util/DisableIf.h>
69 #include <blaze/util/EnableIf.h>
71 #include <blaze/util/mpl/If.h>
72 #include <blaze/util/Types.h>
73 
74 
75 namespace blaze {
76 
77 //=================================================================================================
78 //
79 // CLASS SMATDMATKRONEXPR
80 //
81 //=================================================================================================
82 
83 //*************************************************************************************************
90 template< typename MT1 // Type of the left-hand side sparse matrix
91  , typename MT2 // Type of the right-hand side dense matrix
92  , bool SO > // Storage order
93 class SMatDMatKronExpr
94  : public MatMatKronExpr< SparseMatrix< SMatDMatKronExpr<MT1,MT2,SO>, SO > >
95  , private Computation
96 {
97  private:
98  //**Type definitions****************************************************************************
105  //**********************************************************************************************
106 
107  //**Return type evaluation**********************************************************************
109 
114  static constexpr bool returnExpr = ( !IsTemporary_v<RN1> && !IsTemporary_v<RN2> );
115 
117  using ExprReturnType = decltype( std::declval<RN1>() * std::declval<RN2>() );
118  //**********************************************************************************************
119 
120  public:
121  //**Type definitions****************************************************************************
128 
131 
133  using CompositeType = const ResultType;
134 
136  using LeftOperand = If_t< IsExpression_v<MT1>, const MT1, const MT1& >;
137 
139  using RightOperand = If_t< IsExpression_v<MT2>, const MT2, const MT2& >;
140  //**********************************************************************************************
141 
142  //**Compilation flags***************************************************************************
144  static constexpr bool smpAssignable = false;
145  //**********************************************************************************************
146 
147  //**Constructor*********************************************************************************
153  explicit inline SMatDMatKronExpr( const MT1& lhs, const MT2& rhs ) noexcept
154  : lhs_( lhs ) // Left-hand side sparse matrix of the Kronecker product expression
155  , rhs_( rhs ) // Right-hand side dense matrix of the Kronecker product expression
156  {}
157  //**********************************************************************************************
158 
159  //**Access operator*****************************************************************************
166  inline ReturnType operator()( size_t i, size_t j ) const {
167  BLAZE_INTERNAL_ASSERT( i < rows() , "Invalid row access index" );
168  BLAZE_INTERNAL_ASSERT( j < columns(), "Invalid column access index" );
169  return lhs_( i/rhs_.rows(), j/rhs_.columns() ) * rhs_( i%rhs_.rows(), j%rhs_.columns() );
170  }
171  //**********************************************************************************************
172 
173  //**At function*********************************************************************************
181  inline ReturnType at( size_t i, size_t j ) const {
182  if( i >= rows() ) {
183  BLAZE_THROW_OUT_OF_RANGE( "Invalid row access index" );
184  }
185  if( j >= columns() ) {
186  BLAZE_THROW_OUT_OF_RANGE( "Invalid column access index" );
187  }
188  return (*this)(i,j);
189  }
190  //**********************************************************************************************
191 
192  //**Rows function*******************************************************************************
197  inline size_t rows() const noexcept {
198  return lhs_.rows() * rhs_.rows();
199  }
200  //**********************************************************************************************
201 
202  //**Columns function****************************************************************************
207  inline size_t columns() const noexcept {
208  return lhs_.columns() * rhs_.columns();
209  }
210  //**********************************************************************************************
211 
212  //**NonZeros function***************************************************************************
217  inline size_t nonZeros() const {
218  return lhs_.nonZeros() * rhs_.rows() * rhs_.columns();
219  }
220  //**********************************************************************************************
221 
222  //**NonZeros function***************************************************************************
228  inline size_t nonZeros( size_t i ) const {
229  if( SO )
230  return lhs_.nonZeros( i/rhs_.columns() ) * rhs_.rows();
231  else
232  return lhs_.nonZeros( i/rhs_.rows() ) * rhs_.columns();
233  }
234  //**********************************************************************************************
235 
236  //**Left operand access*************************************************************************
241  inline LeftOperand leftOperand() const noexcept {
242  return lhs_;
243  }
244  //**********************************************************************************************
245 
246  //**Right operand access************************************************************************
251  inline RightOperand rightOperand() const noexcept {
252  return rhs_;
253  }
254  //**********************************************************************************************
255 
256  //**********************************************************************************************
262  template< typename T >
263  inline bool canAlias( const T* alias ) const noexcept {
264  return ( lhs_.canAlias( alias ) || rhs_.canAlias( alias ) );
265  }
266  //**********************************************************************************************
267 
268  //**********************************************************************************************
274  template< typename T >
275  inline bool isAliased( const T* alias ) const noexcept {
276  return ( lhs_.isAliased( alias ) || rhs_.isAliased( alias ) );
277  }
278  //**********************************************************************************************
279 
280  private:
281  //**Member variables****************************************************************************
284  //**********************************************************************************************
285 
286  //**Assignment to dense matrices****************************************************************
298  template< typename MT // Type of the target dense matrix
299  , bool SO2 > // Storage order of the target dense matrix
300  friend inline void assign( DenseMatrix<MT,SO2>& lhs, const SMatDMatKronExpr& rhs )
301  {
303 
304  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
305  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
306 
307  if( rhs.rows() == 0UL || rhs.columns() == 0UL ) {
308  return;
309  }
310 
311  CT1 A( serial( rhs.lhs_ ) ); // Evaluation of the left-hand side sparse matrix operand
312  CT2 B( serial( rhs.rhs_ ) ); // Evaluation of the right-hand side dense matrix operand
313 
314  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
315  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
316  BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
317  BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
318 
319  const size_t M( B.rows() );
320  const size_t N( B.columns() );
321 
322  if( SO )
323  {
324  for( size_t j=0UL; j<A.columns(); ++j ) {
325  const auto aend( A.end(j) );
326  for( auto aelem=A.begin(j); aelem!=aend; ++aelem ) {
327  for( size_t l=0UL; l<N; ++l )
328  {
329  const size_t kbegin( ( IsLower_v<MT2> )
330  ?( ( IsStrictlyLower_v<MT2> ? l+1UL : l ) )
331  :( 0UL ) );
332  const size_t kend( ( IsUpper_v<MT2> )
333  ?( IsStrictlyUpper_v<MT2> ? l : l+1UL )
334  :( M ) );
335  BLAZE_INTERNAL_ASSERT( kbegin <= kend, "Invalid loop indices detected" );
336 
337  for( size_t k=kbegin; k<kend; ++k ) {
338  (~lhs)(aelem->index()*M+k,j*N+l) = aelem->value() * B(k,l);
339  }
340  }
341  }
342  }
343  }
344  else
345  {
346  for( size_t i=0UL; i<A.rows(); ++i ) {
347  const auto aend( A.end(i) );
348  for( auto aelem=A.begin(i); aelem!=aend; ++aelem ) {
349  for( size_t k=0UL; k<M; ++k )
350  {
351  const size_t lbegin( ( IsUpper_v<MT2> )
352  ?( ( IsStrictlyUpper_v<MT2> ? k+1UL : k ) )
353  :( 0UL ) );
354  const size_t lend( ( IsLower_v<MT2> )
355  ?( IsStrictlyLower_v<MT2> ? k : k+1UL )
356  :( N ) );
357  BLAZE_INTERNAL_ASSERT( lbegin <= lend, "Invalid loop indices detected" );
358 
359  for( size_t l=lbegin; l<lend; ++l )
360  (~lhs)(i*M+k,aelem->index()*N+l) = aelem->value() * B(k,l);
361  }
362  }
363  }
364  }
365  }
367  //**********************************************************************************************
368 
369  //**Assignment to row-major sparse matrices*****************************************************
382  template< typename MT > // Type of the target sparse matrix
383  friend inline void assign( SparseMatrix<MT,false>& lhs, const SMatDMatKronExpr& rhs )
384  {
386 
387  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
388  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
389 
390  if( rhs.rows() == 0UL || rhs.columns() == 0UL ) {
391  return;
392  }
393 
394  CT1 A( serial( rhs.lhs_ ) ); // Evaluation of the left-hand side sparse matrix operand
395  CT2 B( serial( rhs.rhs_ ) ); // Evaluation of the right-hand side dense matrix operand
396 
397  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
398  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
399  BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
400  BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
401 
402  const size_t M( B.rows() );
403  const size_t N( B.columns() );
404 
405  if( SO )
406  {
407  // Counting the number of elements per row
408  std::vector<size_t> nonzeros( A.rows(), 0UL );
409  for( size_t j=0UL; j<A.columns(); ++j ) {
410  const auto end( A.end(j) );
411  for( auto aelem=A.begin(j); aelem!=end; ++aelem ) {
412  ++nonzeros[aelem->index()];
413  }
414  }
415 
416  // Resizing the left-hand side sparse matrix
417  for( size_t i=0UL; i<A.rows(); ++i ) {
418  for( size_t j=0UL; j<M; ++j ) {
419  (~lhs).reserve( i*M+j, nonzeros[i]*B.columns() );
420  }
421  }
422 
423  // Performing the Kronecker product
424  for( size_t j=0UL; j<A.columns(); ++j ) {
425  const auto aend( A.end(j) );
426  for( size_t l=0UL; l<N; ++l )
427  {
428  const size_t kbegin( ( IsLower_v<MT2> )
429  ?( ( IsStrictlyLower_v<MT2> ? l+1UL : l ) )
430  :( 0UL ) );
431  const size_t kend( ( IsUpper_v<MT2> )
432  ?( IsStrictlyUpper_v<MT2> ? l : l+1UL )
433  :( M ) );
434  BLAZE_INTERNAL_ASSERT( kbegin <= kend, "Invalid loop indices detected" );
435 
436  for( auto aelem=A.begin(j); aelem!=aend; ++aelem ) {
437  for( size_t k=kbegin; k<kend; ++k ) {
438  (~lhs).append( aelem->index()*M+k, j*N+l, aelem->value() * B(k,l), true );
439  }
440  }
441  }
442  }
443  }
444  else
445  {
446  for( size_t i=0UL; i<A.rows(); ++i ) {
447  const auto aend( A.end(i) );
448  for( size_t k=0UL; k<M; ++k )
449  {
450  const size_t lbegin( ( IsUpper_v<MT2> )
451  ?( ( IsStrictlyUpper_v<MT2> ? k+1UL : k ) )
452  :( 0UL ) );
453  const size_t lend( ( IsLower_v<MT2> )
454  ?( IsStrictlyLower_v<MT2> ? k : k+1UL )
455  :( N ) );
456  BLAZE_INTERNAL_ASSERT( lbegin <= lend, "Invalid loop indices detected" );
457 
458  for( auto aelem=A.begin(i); aelem!=aend; ++aelem ) {
459  for( size_t l=lbegin; l<lend; ++l ) {
460  (~lhs).append( i*M+k, aelem->index()*N+l, aelem->value() * B(k,l), true );
461  }
462  }
463  (~lhs).finalize( i*M+k );
464  }
465  }
466  }
467  }
469  //**********************************************************************************************
470 
471  //**Assignment to column-major sparse matrices**************************************************
484  template< typename MT > // Type of the target sparse matrix
485  friend inline void assign( SparseMatrix<MT,true>& lhs, const SMatDMatKronExpr& rhs )
486  {
488 
489  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
490  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
491 
492  if( rhs.rows() == 0UL || rhs.columns() == 0UL ) {
493  return;
494  }
495 
496  CT1 A( serial( rhs.lhs_ ) ); // Evaluation of the left-hand side sparse matrix operand
497  CT2 B( serial( rhs.rhs_ ) ); // Evaluation of the right-hand side dense matrix operand
498 
499  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
500  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
501  BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
502  BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
503 
504  const size_t M( B.rows() );
505  const size_t N( B.columns() );
506 
507  if( SO )
508  {
509  for( size_t j=0UL; j<A.columns(); ++j ) {
510  const auto aend( A.end(j) );
511  for( size_t l=0UL; l<N; ++l )
512  {
513  const size_t kbegin( ( IsLower_v<MT2> )
514  ?( ( IsStrictlyLower_v<MT2> ? l+1UL : l ) )
515  :( 0UL ) );
516  const size_t kend( ( IsUpper_v<MT2> )
517  ?( IsStrictlyUpper_v<MT2> ? l : l+1UL )
518  :( M ) );
519  BLAZE_INTERNAL_ASSERT( kbegin <= kend, "Invalid loop indices detected" );
520 
521  for( auto aelem=A.begin(j); aelem!=aend; ++aelem ) {
522  for( size_t k=kbegin; k<kend; ++k ) {
523  (~lhs).append( aelem->index()*M+k, j*N+l, aelem->value() * B(k,l), true );
524  }
525  }
526  (~lhs).finalize( j*N+l );
527  }
528  }
529  }
530  else
531  {
532  // Counting the number of elements per column
533  std::vector<size_t> nonzeros( A.columns(), 0UL );
534  for( size_t i=0UL; i<A.rows(); ++i ) {
535  const auto end( A.end(i) );
536  for( auto aelem=A.begin(i); aelem!=end; ++aelem ) {
537  ++nonzeros[aelem->index()];
538  }
539  }
540 
541  // Resizing the left-hand side sparse matrix
542  for( size_t i=0UL; i<A.columns(); ++i ) {
543  for( size_t j=0UL; j<N; ++j ) {
544  (~lhs).reserve( i*N+j, nonzeros[i]*B.rows() );
545  }
546  }
547 
548  // Performing the Kronecker product
549  for( size_t i=0UL; i<A.rows(); ++i ) {
550  const auto aend( A.end(i) );
551  for( size_t k=0UL; k<M; ++k )
552  {
553  const size_t lbegin( ( IsUpper_v<MT2> )
554  ?( ( IsStrictlyUpper_v<MT2> ? k+1UL : k ) )
555  :( 0UL ) );
556  const size_t lend( ( IsLower_v<MT2> )
557  ?( IsStrictlyLower_v<MT2> ? k : k+1UL )
558  :( N ) );
559  BLAZE_INTERNAL_ASSERT( lbegin <= lend, "Invalid loop indices detected" );
560 
561  for( auto aelem=A.begin(i); aelem!=aend; ++aelem ) {
562  for( size_t l=lbegin; l<lend; ++l ) {
563  (~lhs).append( i*M+k, aelem->index()*N+l, aelem->value() * B(k,l), true );
564  }
565  }
566  }
567  }
568  }
569  }
571  //**********************************************************************************************
572 
573  //**Addition assignment to dense matrices*******************************************************
586  template< typename MT // Type of the target dense matrix
587  , bool SO2 > // Storage order of the target dense matrix
588  friend inline void addAssign( DenseMatrix<MT,SO2>& lhs, const SMatDMatKronExpr& 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  if( rhs.rows() == 0UL || rhs.columns() == 0UL ) {
596  return;
597  }
598 
599  CT1 A( serial( rhs.lhs_ ) ); // Evaluation of the left-hand side sparse matrix operand
600  CT2 B( serial( rhs.rhs_ ) ); // Evaluation of the right-hand side dense matrix operand
601 
602  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
603  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
604  BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
605  BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
606 
607  const size_t M( B.rows() );
608  const size_t N( B.columns() );
609 
610  if( SO )
611  {
612  for( size_t j=0UL; j<A.columns(); ++j ) {
613  const auto aend( A.end(j) );
614  for( auto aelem=A.begin(j); aelem!=aend; ++aelem ) {
615  for( size_t l=0UL; l<N; ++l )
616  {
617  const size_t kbegin( ( IsLower_v<MT2> )
618  ?( ( IsStrictlyLower_v<MT2> ? l+1UL : l ) )
619  :( 0UL ) );
620  const size_t kend( ( IsUpper_v<MT2> )
621  ?( IsStrictlyUpper_v<MT2> ? l : l+1UL )
622  :( M ) );
623  BLAZE_INTERNAL_ASSERT( kbegin <= kend, "Invalid loop indices detected" );
624 
625  for( size_t k=kbegin; k<kend; ++k ) {
626  (~lhs)(aelem->index()*M+k,j*N+l) += aelem->value() * B(k,l);
627  }
628  }
629  }
630  }
631  }
632  else
633  {
634  for( size_t i=0UL; i<A.rows(); ++i ) {
635  const auto aend( A.end(i) );
636  for( auto aelem=A.begin(i); aelem!=aend; ++aelem ) {
637  for( size_t k=0UL; k<M; ++k )
638  {
639  const size_t lbegin( ( IsUpper_v<MT2> )
640  ?( ( IsStrictlyUpper_v<MT2> ? k+1UL : k ) )
641  :( 0UL ) );
642  const size_t lend( ( IsLower_v<MT2> )
643  ?( IsStrictlyLower_v<MT2> ? k : k+1UL )
644  :( N ) );
645  BLAZE_INTERNAL_ASSERT( lbegin <= lend, "Invalid loop indices detected" );
646 
647  for( size_t l=lbegin; l<lend; ++l ) {
648  (~lhs)(i*M+k,aelem->index()*N+l) += aelem->value() * B(k,l);
649  }
650  }
651  }
652  }
653  }
654  }
656  //**********************************************************************************************
657 
658  //**Addition assignment to sparse matrices******************************************************
659  // No special implementation for the addition assignment to sparse matrices.
660  //**********************************************************************************************
661 
662  //**Subtraction assignment to dense matrices****************************************************
675  template< typename MT // Type of the target dense matrix
676  , bool SO2 > // Storage order of the target dense matrix
677  friend inline void subAssign( DenseMatrix<MT,SO2>& lhs, const SMatDMatKronExpr& rhs )
678  {
680 
681  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
682  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
683 
684  if( rhs.rows() == 0UL || rhs.columns() == 0UL ) {
685  return;
686  }
687 
688  CT1 A( serial( rhs.lhs_ ) ); // Evaluation of the left-hand side sparse matrix operand
689  CT2 B( serial( rhs.rhs_ ) ); // Evaluation of the right-hand side dense matrix operand
690 
691  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
692  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
693  BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
694  BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
695 
696  const size_t M( B.rows() );
697  const size_t N( B.columns() );
698 
699  if( SO )
700  {
701  for( size_t j=0UL; j<A.columns(); ++j ) {
702  const auto aend( A.end(j) );
703  for( auto aelem=A.begin(j); aelem!=aend; ++aelem ) {
704  for( size_t l=0UL; l<N; ++l )
705  {
706  const size_t kbegin( ( IsLower_v<MT2> )
707  ?( ( IsStrictlyLower_v<MT2> ? l+1UL : l ) )
708  :( 0UL ) );
709  const size_t kend( ( IsUpper_v<MT2> )
710  ?( IsStrictlyUpper_v<MT2> ? l : l+1UL )
711  :( M ) );
712  BLAZE_INTERNAL_ASSERT( kbegin <= kend, "Invalid loop indices detected" );
713 
714  for( size_t k=kbegin; k<kend; ++k ) {
715  (~lhs)(aelem->index()*M+k,j*N+l) -= aelem->value() * B(k,l);
716  }
717  }
718  }
719  }
720  }
721  else
722  {
723  for( size_t i=0UL; i<A.rows(); ++i ) {
724  const auto aend( A.end(i) );
725  for( auto aelem=A.begin(i); aelem!=aend; ++aelem ) {
726  for( size_t k=0UL; k<M; ++k )
727  {
728  const size_t lbegin( ( IsUpper_v<MT2> )
729  ?( ( IsStrictlyUpper_v<MT2> ? k+1UL : k ) )
730  :( 0UL ) );
731  const size_t lend( ( IsLower_v<MT2> )
732  ?( IsStrictlyLower_v<MT2> ? k : k+1UL )
733  :( N ) );
734  BLAZE_INTERNAL_ASSERT( lbegin <= lend, "Invalid loop indices detected" );
735 
736  for( size_t l=lbegin; l<lend; ++l ) {
737  (~lhs)(i*M+k,aelem->index()*N+l) -= aelem->value() * B(k,l);
738  }
739  }
740  }
741  }
742  }
743  }
745  //**********************************************************************************************
746 
747  //**Subtraction assignment to sparse matrices***************************************************
748  // No special implementation for the subtraction assignment to sparse matrices.
749  //**********************************************************************************************
750 
751  //**Schur product assignment to dense matrices**************************************************
764  template< typename MT // Type of the target dense matrix
765  , bool SO2 > // Storage order of the target dense matrix
766  friend inline void schurAssign( DenseMatrix<MT,SO2>& lhs, const SMatDMatKronExpr& rhs )
767  {
769 
770  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
771  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
772 
773  if( rhs.rows() == 0UL || rhs.columns() == 0UL ) {
774  return;
775  }
776 
777  CT1 A( serial( rhs.lhs_ ) ); // Evaluation of the left-hand side sparse matrix operand
778  CT2 B( serial( rhs.rhs_ ) ); // Evaluation of the right-hand side dense matrix operand
779 
780  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
781  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
782  BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
783  BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
784 
785  const size_t M( B.rows() );
786  const size_t N( B.columns() );
787 
788  if( SO )
789  {
790  for( size_t j=0UL; j<A.columns(); ++j )
791  {
792  size_t index( 0UL );
793  const auto aend( A.end(j) );
794 
795  for( auto aelem=A.begin(j); aelem!=aend; ++aelem, ++index )
796  {
797  for( ; index<aelem->index(); ++index )
798  for( size_t l=0UL; l<N; ++l )
799  for( size_t k=0UL; k<M; ++k )
800  reset( (~lhs)(index*M+k,j*N+l) );
801 
802  for( size_t l=0UL; l<N; ++l )
803  for( size_t k=0UL; k<M; ++k )
804  (~lhs)(index*M+k,j*N+l) *= aelem->value() * B(k,l);
805  }
806 
807  for( ; index<A.rows(); ++index )
808  for( size_t l=0UL; l<N; ++l )
809  for( size_t k=0UL; k<M; ++k )
810  reset( (~lhs)(index*M+k,j*N+l) );
811  }
812  }
813  else
814  {
815  for( size_t i=0UL; i<A.rows(); ++i )
816  {
817  size_t index( 0UL );
818  const auto aend( A.end(i) );
819 
820  for( auto aelem=A.begin(i); aelem!=aend; ++aelem, ++index )
821  {
822  for( ; index<aelem->index(); ++index )
823  for( size_t k=0UL; k<M; ++k )
824  for( size_t l=0UL; l<N; ++l )
825  reset( (~lhs)(i*M+k,index*N+l) );
826 
827  for( size_t k=0UL; k<M; ++k )
828  for( size_t l=0UL; l<N; ++l )
829  (~lhs)(i*M+k,index*N+l) *= aelem->value() * B(k,l);
830  }
831 
832  for( ; index<A.columns(); ++index )
833  for( size_t k=0UL; k<M; ++k )
834  for( size_t l=0UL; l<N; ++l )
835  reset( (~lhs)(i*M+k,index*N+l) );
836  }
837  }
838  }
840  //**********************************************************************************************
841 
842  //**Schur product assignment to sparse matrices***************************************************
843  // No special implementation for the Schur product assignment to sparse matrices.
844  //**********************************************************************************************
845 
846  //**Multiplication assignment to dense matrices*************************************************
847  // No special implementation for the multiplication assignment to dense matrices.
848  //**********************************************************************************************
849 
850  //**Multiplication assignment to sparse matrices************************************************
851  // No special implementation for the multiplication assignment to sparse matrices.
852  //**********************************************************************************************
853 
854  //**Compile time checks*************************************************************************
862  //**********************************************************************************************
863 };
864 //*************************************************************************************************
865 
866 
867 
868 
869 //=================================================================================================
870 //
871 // GLOBAL FUNCTIONS
872 //
873 //=================================================================================================
874 
875 //*************************************************************************************************
888 template< typename MT1 // Type of the left-hand side sparse matrix
889  , bool SO1 // Storage order of the left-hand side sparse matrix
890  , typename MT2 // Type of the right-hand side dense matrix
891  , bool SO2 // Storage order of the right-hand side dense matrix
892  , DisableIf_t< IsZero_v<MT1> >* = nullptr >
893 inline const SMatDMatKronExpr<MT1,MT2,SO1>
894  smatdmatkron( const SparseMatrix<MT1,SO1>& lhs, const DenseMatrix<MT2,SO2>& rhs )
895 {
897 
898  return SMatDMatKronExpr<MT1,MT2,SO1>( ~lhs, ~rhs );
899 }
901 //*************************************************************************************************
902 
903 
904 //*************************************************************************************************
917 template< typename MT1 // Type of the left-hand side sparse matrix
918  , bool SO1 // Storage order of the left-hand side sparse matrix
919  , typename MT2 // Type of the right-hand side dense matrix
920  , bool SO2 // Storage order of the right-hand side dense matrix
921  , EnableIf_t< IsZero_v<MT1> >* = nullptr >
922 inline decltype(auto)
923  smatdmatkron( const SparseMatrix<MT1,SO1>& lhs, const DenseMatrix<MT2,SO2>& rhs )
924 {
926 
927  using ReturnType = const KronTrait_t< ResultType_t<MT1>, ResultType_t<MT2> >;
928 
931 
932  return ReturnType( (~lhs).rows()*(~rhs).rows(), (~lhs).columns()*(~rhs).columns() );
933 }
935 //*************************************************************************************************
936 
937 
938 //*************************************************************************************************
960 template< typename MT1 // Type of the left-hand side sparse matrix
961  , bool SO1 // Storage order of the left-hand side sparse matrix
962  , typename MT2 // Type of the right-hand side dense matrix
963  , bool SO2 > // Storage order of the right-hand side dense matrix
964 inline decltype(auto)
965  kron( const SparseMatrix<MT1,SO1>& lhs, const DenseMatrix<MT2,SO2>& rhs )
966 {
968 
969  return smatdmatkron( ~lhs, ~rhs );
970 }
971 //*************************************************************************************************
972 
973 } // namespace blaze
974 
975 #endif
CompositeType_t< MT1 > CT1
Composite type of the left-hand side sparse matrix expression.
Definition: SMatDMatKronExpr.h:103
Header file for auxiliary alias declarations.
ElementType_t< ResultType > ElementType
Resulting element type.
Definition: SMatDMatKronExpr.h:127
bool isAliased(const T *alias) const noexcept
Returns whether the expression is aliased with the given address alias.
Definition: SMatDMatKronExpr.h:275
ReturnType at(size_t i, size_t j) const
Checked access to the matrix elements.
Definition: SMatDMatKronExpr.h:181
TransposeType_t< ResultType > TransposeType
Transpose type for expression template evaluations.
Definition: SMatDMatKronExpr.h:126
Header file for basic type definitions.
size_t rows() const noexcept
Returns the current number of rows of the matrix.
Definition: SMatDMatKronExpr.h:197
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
Header file for the serial shim.
#define BLAZE_CONSTRAINT_MUST_BE_MATRIX_WITH_STORAGE_ORDER(T, SO)
Constraint on the data type.In case the given data type T is not a dense or sparse matrix type and in...
Definition: StorageOrder.h:63
#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:61
size_t nonZeros(size_t i) const
Returns the number of non-zero elements in the specified row.
Definition: SMatDMatKronExpr.h:228
Header file for the IsColumnMajorMatrix type trait.
void reset(const DiagonalProxy< MT > &proxy)
Resetting the represented element to the default initial values.
Definition: DiagonalProxy.h:595
Constraint on the data type.
If_t< IsExpression_v< MT1 >, const MT1, const MT1 & > LeftOperand
Composite type of the left-hand side sparse matrix expression.
Definition: SMatDMatKronExpr.h:136
Header file for the Computation base class.
Header file for the reset shim.
ResultType_t< MT2 > RT2
Result type of the right-hand side dense matrix expression.
Definition: SMatDMatKronExpr.h:100
typename T::ReturnType ReturnType_t
Alias declaration for nested ReturnType type definitions.The ReturnType_t alias declaration provides ...
Definition: Aliases.h:410
decltype(auto) kron(const DenseMatrix< MT1, SO1 > &lhs, const DenseMatrix< MT2, SO2 > &rhs)
Computes the Kronecker product of two dense matrices ( ).
Definition: DMatDMatKronExpr.h:954
constexpr size_t columns(const Matrix< MT, SO > &matrix) noexcept
Returns the current number of columns of the matrix.
Definition: Matrix.h:514
static constexpr bool returnExpr
Compilation switch for the selection of the subscript operator return type.
Definition: SMatDMatKronExpr.h:114
Header file for the MatMatKronExpr base class.
KronTrait_t< RT1, RT2 > ResultType
Result type for expression template evaluations.
Definition: SMatDMatKronExpr.h:124
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
Header file for the SparseMatrix base class.
static constexpr bool smpAssignable
Compilation switch for the expression template assignment strategy.
Definition: SMatDMatKronExpr.h:144
Constraint on the data type.
Constraint on the data type.
Header file for the DisableIf class template.
Header file for the IsTemporary type trait class.
Header file for the IsStrictlyUpper type trait.
Namespace of the Blaze C++ math library.
Definition: Blaze.h:58
Header file for the If class template.
decltype(std::declval< RN1 >() *std::declval< RN2 >()) ExprReturnType
Expression return type for the subscript operator.
Definition: SMatDMatKronExpr.h:117
#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
size_t nonZeros() const
Returns the number of non-zero elements in the sparse matrix.
Definition: SMatDMatKronExpr.h:217
OppositeType_t< ResultType > OppositeType
Result type with opposite storage order for expression template evaluations.
Definition: SMatDMatKronExpr.h:125
typename KronTrait< T1, T2 >::Type KronTrait_t
Auxiliary alias declaration for the KronTrait class template.The KronTrait_t alias declaration provid...
Definition: KronTrait.h:163
#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
Header file for the DenseMatrix base class.
bool canAlias(const T *alias) const noexcept
Returns whether the expression can alias with the given address alias.
Definition: SMatDMatKronExpr.h:263
Header file for the IsLower type trait.
Header file for the Kron product trait.
Constraints on the storage order of matrix types.
Header file for the exception macros of the math module.
Constraint on the data type.
const If_t< returnExpr, ExprReturnType, ElementType > ReturnType
Return type for expression template evaluations.
Definition: SMatDMatKronExpr.h:130
ReturnType operator()(size_t i, size_t j) const
2D-access to the matrix elements.
Definition: SMatDMatKronExpr.h:166
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:438
RightOperand rightOperand() const noexcept
Returns the right-hand side dense matrix operand.
Definition: SMatDMatKronExpr.h:251
Header file for the EnableIf class template.
Header file for the IsStrictlyLower type trait.
typename T::OppositeType OppositeType_t
Alias declaration for nested OppositeType type definitions.The OppositeType_t alias declaration provi...
Definition: Aliases.h:270
RightOperand rhs_
Right-hand side dense matrix of the Kronecker product expression.
Definition: SMatDMatKronExpr.h:283
typename T::TransposeType TransposeType_t
Alias declaration for nested TransposeType type definitions.The TransposeType_t alias declaration pro...
Definition: Aliases.h:470
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
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
size_t columns() const noexcept
Returns the current number of columns of the matrix.
Definition: SMatDMatKronExpr.h:207
const ResultType CompositeType
Data type for composite expression templates.
Definition: SMatDMatKronExpr.h:133
decltype(auto) serial(const DenseMatrix< MT, SO > &dm)
Forces the serial evaluation of the given dense matrix expression dm.
Definition: DMatSerialExpr.h:808
ReturnType_t< MT1 > RN1
Return type of the left-hand side sparse matrix expression.
Definition: SMatDMatKronExpr.h:101
constexpr size_t rows(const Matrix< MT, SO > &matrix) noexcept
Returns the current number of rows of the matrix.
Definition: Matrix.h:498
CompositeType_t< MT2 > CT2
Composite type of the right-hand side dense matrix expression.
Definition: SMatDMatKronExpr.h:104
Header file for the IsRowMajorMatrix type trait.
#define BLAZE_CONSTRAINT_MUST_FORM_VALID_MATMATKRONEXPR(T1, T2)
Constraint on the data type.In case the given data types T1 and T2 do not form a valid matrix/matrix ...
Definition: MatMatKronExpr.h:102
ReturnType_t< MT2 > RN2
Return type of the right-hand side dense matrix expression.
Definition: SMatDMatKronExpr.h:102
LeftOperand lhs_
Left-hand side sparse matrix of the Kronecker product expression.
Definition: SMatDMatKronExpr.h:282
ResultType_t< MT1 > RT1
Result type of the left-hand side sparse matrix expression.
Definition: SMatDMatKronExpr.h:99
SMatDMatKronExpr(const MT1 &lhs, const MT2 &rhs) noexcept
Constructor for the SMatDMatKronExpr class.
Definition: SMatDMatKronExpr.h:153
LeftOperand leftOperand() const noexcept
Returns the left-hand side sparse matrix operand.
Definition: SMatDMatKronExpr.h:241
Header file for the IsUpper type trait.
If_t< IsExpression_v< MT2 >, const MT2, const MT2 & > RightOperand
Composite type of the right-hand side dense matrix expression.
Definition: SMatDMatKronExpr.h:139
#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
#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
#define BLAZE_CONSTRAINT_MUST_BE_SPARSE_MATRIX_TYPE(T)
Constraint on the data type.In case the given data type T is not a sparse, N-dimensional matrix type,...
Definition: SparseMatrix.h:61
Expression object for sparse matrix-dense matrix Kronecker product.The SMatDMatKronExpr class represe...
Definition: Forward.h:120
Header file for the IsExpression type trait class.
Header file for the function trace functionality.