Blaze  3.6
DMatSMatKronExpr.h
Go to the documentation of this file.
1 //=================================================================================================
33 //=================================================================================================
34 
35 #ifndef _BLAZE_MATH_EXPRESSIONS_DMATSMATKRONEXPR_H_
36 #define _BLAZE_MATH_EXPRESSIONS_DMATSMATKRONEXPR_H_
37 
38 
39 //*************************************************************************************************
40 // Includes
41 //*************************************************************************************************
42 
43 #include <utility>
44 #include <blaze/math/Aliases.h>
50 #include <blaze/math/Exception.h>
56 #include <blaze/math/shims/Reset.h>
68 #include <blaze/util/Assert.h>
69 #include <blaze/util/DisableIf.h>
70 #include <blaze/util/EnableIf.h>
72 #include <blaze/util/MaybeUnused.h>
73 #include <blaze/util/mpl/If.h>
74 #include <blaze/util/Types.h>
75 
76 
77 namespace blaze {
78 
79 //=================================================================================================
80 //
81 // CLASS DMATSMATKRONEXPR
82 //
83 //=================================================================================================
84 
85 //*************************************************************************************************
92 template< typename MT1 // Type of the left-hand side dense matrix
93  , typename MT2 // Type of the right-hand side sparse matrix
94  , bool SO > // Storage order
96  : public MatMatKronExpr< SparseMatrix< DMatSMatKronExpr<MT1,MT2,SO>, SO > >
97  , private Computation
98 {
99  private:
100  //**Type definitions****************************************************************************
107  //**********************************************************************************************
108 
109  //**Return type evaluation**********************************************************************
111 
116  static constexpr bool returnExpr = ( !IsTemporary_v<RN1> && !IsTemporary_v<RN2> );
117 
119  using ExprReturnType = decltype( std::declval<RN1>() * std::declval<RN2>() );
120  //**********************************************************************************************
121 
122  public:
123  //**Type definitions****************************************************************************
130 
133 
135  using CompositeType = const ResultType;
136 
138  using LeftOperand = If_t< IsExpression_v<MT1>, const MT1, const MT1& >;
139 
141  using RightOperand = If_t< IsExpression_v<MT2>, const MT2, const MT2& >;
142  //**********************************************************************************************
143 
144  //**Compilation flags***************************************************************************
146  static constexpr bool smpAssignable = false;
147  //**********************************************************************************************
148 
149  //**Constructor*********************************************************************************
155  explicit inline DMatSMatKronExpr( const MT1& lhs, const MT2& rhs ) noexcept
156  : lhs_( lhs ) // Left-hand side dense matrix of the Kronecker product expression
157  , rhs_( rhs ) // Right-hand side sparse matrix of the Kronecker product expression
158  {}
159  //**********************************************************************************************
160 
161  //**Access operator*****************************************************************************
168  inline ReturnType operator()( size_t i, size_t j ) const {
169  BLAZE_INTERNAL_ASSERT( i < rows() , "Invalid row access index" );
170  BLAZE_INTERNAL_ASSERT( j < columns(), "Invalid column access index" );
171  return lhs_( i/rhs_.rows(), j/rhs_.columns() ) * rhs_( i%rhs_.rows(), j%rhs_.columns() );
172  }
173  //**********************************************************************************************
174 
175  //**At function*********************************************************************************
183  inline ReturnType at( size_t i, size_t j ) const {
184  if( i >= rows() ) {
185  BLAZE_THROW_OUT_OF_RANGE( "Invalid row access index" );
186  }
187  if( j >= columns() ) {
188  BLAZE_THROW_OUT_OF_RANGE( "Invalid column access index" );
189  }
190  return (*this)(i,j);
191  }
192  //**********************************************************************************************
193 
194  //**Rows function*******************************************************************************
199  inline size_t rows() const noexcept {
200  return lhs_.rows() * rhs_.rows();
201  }
202  //**********************************************************************************************
203 
204  //**Columns function****************************************************************************
209  inline size_t columns() const noexcept {
210  return lhs_.columns() * rhs_.columns();
211  }
212  //**********************************************************************************************
213 
214  //**NonZeros function***************************************************************************
219  inline size_t nonZeros() const {
220  return lhs_.rows() * lhs_.columns() * rhs_.nonZeros();
221  }
222  //**********************************************************************************************
223 
224  //**NonZeros function***************************************************************************
230  inline size_t nonZeros( size_t i ) const {
231  if( SO )
232  return lhs_.rows() * rhs_.nonZeros( i%rhs_.columns() );
233  else
234  return lhs_.columns() * rhs_.nonZeros( i%rhs_.rows() );
235  }
236  //**********************************************************************************************
237 
238  //**Left operand access*************************************************************************
243  inline LeftOperand leftOperand() const noexcept {
244  return lhs_;
245  }
246  //**********************************************************************************************
247 
248  //**Right operand access************************************************************************
253  inline RightOperand rightOperand() const noexcept {
254  return rhs_;
255  }
256  //**********************************************************************************************
257 
258  //**********************************************************************************************
264  template< typename T >
265  inline bool canAlias( const T* alias ) const noexcept {
266  return ( lhs_.canAlias( alias ) || rhs_.canAlias( alias ) );
267  }
268  //**********************************************************************************************
269 
270  //**********************************************************************************************
276  template< typename T >
277  inline bool isAliased( const T* alias ) const noexcept {
278  return ( lhs_.isAliased( alias ) || rhs_.isAliased( alias ) );
279  }
280  //**********************************************************************************************
281 
282  private:
283  //**Member variables****************************************************************************
286  //**********************************************************************************************
287 
288  //**Assignment to dense matrices****************************************************************
300  template< typename MT // Type of the target dense matrix
301  , bool SO2 > // Storage order of the target dense matrix
302  friend inline void assign( DenseMatrix<MT,SO2>& lhs, const DMatSMatKronExpr& rhs )
303  {
305 
306  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
307  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
308 
309  if( rhs.rows() == 0UL || rhs.columns() == 0UL ) {
310  return;
311  }
312 
313  CT1 A( serial( rhs.lhs_ ) ); // Evaluation of the left-hand side dense matrix operand
314  CT2 B( serial( rhs.rhs_ ) ); // Evaluation of the right-hand side sparse matrix operand
315 
316  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
317  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
318  BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
319  BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
320 
321  const size_t M( B.rows() );
322  const size_t N( B.columns() );
323 
324  if( SO )
325  {
326  for( size_t j=0UL; j<A.columns(); ++j )
327  {
328  const size_t ibegin( ( IsLower_v<MT1> )
329  ?( ( IsStrictlyLower_v<MT1> ? j+1UL : j ) )
330  :( 0UL ) );
331  const size_t iend( ( IsUpper_v<MT1> )
332  ?( IsStrictlyUpper_v<MT1> ? j : j+1UL )
333  :( A.rows() ) );
334  BLAZE_INTERNAL_ASSERT( ibegin <= iend, "Invalid loop indices detected" );
335 
336  for( size_t l=0UL; l<N; ++l ) {
337  for( size_t i=ibegin; i<iend; ++i ) {
338  if( !isDefault( A(i,j) ) ) {
339  const auto bbegin( B.begin(l) );
340  const auto bend ( B.end(l) );
341  for( auto belem=bbegin; belem!=bend; ++belem ) {
342  (~lhs)(i*M+belem->index(),j*N+l) = A(i,j) * belem->value();
343  }
344  }
345  }
346  }
347  }
348  }
349  else
350  {
351  for( size_t i=0UL; i<A.rows(); ++i )
352  {
353  const size_t jbegin( ( IsUpper_v<MT1> )
354  ?( ( IsStrictlyUpper_v<MT1> ? i+1UL : i ) )
355  :( 0UL ) );
356  const size_t jend( ( IsLower_v<MT1> )
357  ?( IsStrictlyLower_v<MT1> ? i : i+1UL )
358  :( A.columns() ) );
359  BLAZE_INTERNAL_ASSERT( jbegin <= jend, "Invalid loop indices detected" );
360 
361  for( size_t k=0UL; k<M; ++k ) {
362  for( size_t j=jbegin; j<jend; ++j ) {
363  if( !isDefault( A(i,j) ) ) {
364  const auto bbegin( B.begin(k) );
365  const auto bend ( B.end(k) );
366  for( auto belem=bbegin; belem!=bend; ++belem ) {
367  (~lhs)(i*M+k,j*N+belem->index()) = A(i,j) * belem->value();
368  }
369  }
370  }
371  }
372  }
373  }
374  }
376  //**********************************************************************************************
377 
378  //**Assignment to row-major sparse matrices*****************************************************
391  template< typename MT > // Type of the target sparse matrix
392  friend inline void assign( SparseMatrix<MT,false>& lhs, const DMatSMatKronExpr& rhs )
393  {
395 
396  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
397  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
398 
399  if( rhs.rows() == 0UL || rhs.columns() == 0UL ) {
400  return;
401  }
402 
403  CT1 A( serial( rhs.lhs_ ) ); // Evaluation of the left-hand side dense matrix operand
404  CT2 B( serial( rhs.rhs_ ) ); // Evaluation of the right-hand side sparse matrix operand
405 
406  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
407  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
408  BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
409  BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
410 
411  const size_t M( B.rows() );
412  const size_t N( B.columns() );
413 
414  if( SO )
415  {
416  // Counting the number of elements per row
417  std::vector<size_t> nonzeros( M, 0UL );
418  for( size_t j=0UL; j<N; ++j ) {
419  const auto end( B.end(j) );
420  for( auto elem=B.begin(j); elem!=end; ++elem ) {
421  ++nonzeros[elem->index()];
422  }
423  }
424 
425  // Resizing the left-hand side sparse matrix
426  for( size_t i=0UL; i<A.rows(); ++i ) {
427  for( size_t j=0UL; j<M; ++j ) {
428  (~lhs).reserve( i*M+j, A.columns()*nonzeros[j] );
429  }
430  }
431 
432  // Performing the Kronecker product
433  for( size_t j=0UL; j<A.columns(); ++j )
434  {
435  const size_t ibegin( ( IsLower_v<MT1> )
436  ?( ( IsStrictlyLower_v<MT1> ? j+1UL : j ) )
437  :( 0UL ) );
438  const size_t iend( ( IsUpper_v<MT1> )
439  ?( IsStrictlyUpper_v<MT1> ? j : j+1UL )
440  :( A.rows() ) );
441  BLAZE_INTERNAL_ASSERT( ibegin <= iend, "Invalid loop indices detected" );
442 
443  for( size_t l=0UL; l<N; ++l ) {
444  for( size_t i=ibegin; i<iend; ++i ) {
445  if( !isDefault( A(i,j) ) ) {
446  const auto end( B.end(l) );
447  for( auto belem=B.begin(l); belem!=end; ++belem ) {
448  (~lhs).append( i*M+belem->index(), j*N+l, A(i,j) * belem->value(), true );
449  }
450  }
451  }
452  }
453  }
454  }
455  else
456  {
457  for( size_t i=0UL; i<A.rows(); ++i )
458  {
459  const size_t jbegin( ( IsUpper_v<MT1> )
460  ?( ( IsStrictlyUpper_v<MT1> ? i+1UL : i ) )
461  :( 0UL ) );
462  const size_t jend( ( IsLower_v<MT1> )
463  ?( IsStrictlyLower_v<MT1> ? i : i+1UL )
464  :( A.columns() ) );
465  BLAZE_INTERNAL_ASSERT( jbegin <= jend, "Invalid loop indices detected" );
466 
467  for( size_t k=0UL; k<M; ++k ) {
468  for( size_t j=jbegin; j<jend; ++j ) {
469  if( !isDefault( A(i,j) ) ) {
470  const auto bend( B.end(k) );
471  for( auto belem=B.begin(k); belem!=bend; ++belem )
472  (~lhs).append( i*M+k, j*N+belem->index(), A(i,j) * belem->value(), true );
473  }
474  }
475  (~lhs).finalize( i*M+k );
476  }
477  }
478  }
479  }
481  //**********************************************************************************************
482 
483  //**Assignment to column-major sparse matrices**************************************************
496  template< typename MT > // Type of the target sparse matrix
497  friend inline void assign( SparseMatrix<MT,true>& lhs, const DMatSMatKronExpr& rhs )
498  {
500 
501  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
502  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
503 
504  if( rhs.rows() == 0UL || rhs.columns() == 0UL ) {
505  return;
506  }
507 
508  CT1 A( serial( rhs.lhs_ ) ); // Evaluation of the left-hand side dense matrix operand
509  CT2 B( serial( rhs.rhs_ ) ); // Evaluation of the right-hand side sparse matrix operand
510 
511  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
512  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
513  BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
514  BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
515 
516  const size_t M( B.rows() );
517  const size_t N( B.columns() );
518 
519  if( SO )
520  {
521  for( size_t j=0UL; j<A.columns(); ++j )
522  {
523  const size_t ibegin( ( IsLower_v<MT1> )
524  ?( ( IsStrictlyLower_v<MT1> ? j+1UL : j ) )
525  :( 0UL ) );
526  const size_t iend( ( IsUpper_v<MT1> )
527  ?( IsStrictlyUpper_v<MT1> ? j : j+1UL )
528  :( A.rows() ) );
529  BLAZE_INTERNAL_ASSERT( ibegin <= iend, "Invalid loop indices detected" );
530 
531  for( size_t l=0UL; l<N; ++l ) {
532  for( size_t i=ibegin; i<iend; ++i ) {
533  if( !isDefault( A(i,j) ) ) {
534  const auto end( B.end(l) );
535  for( auto belem=B.begin(l); belem!=end; ++belem )
536  (~lhs).append( i*M+belem->index(), j*N+l, A(i,j) * belem->value(), true );
537  }
538  }
539  (~lhs).finalize( j*N+l );
540  }
541  }
542  }
543  else
544  {
545  // Counting the number of elements per column
546  std::vector<size_t> nonzeros( N, 0UL );
547  for( size_t i=0UL; i<M; ++i ) {
548  const auto end( B.end(i) );
549  for( auto elem=B.begin(i); elem!=end; ++elem ) {
550  ++nonzeros[elem->index()];
551  }
552  }
553 
554  // Resizing the left-hand side sparse matrix
555  for( size_t i=0UL; i<A.columns(); ++i ) {
556  for( size_t j=0UL; j<N; ++j ) {
557  (~lhs).reserve( i*N+j, A.rows()*nonzeros[j] );
558  }
559  }
560 
561  // Performing the Kronecker product
562  for( size_t i=0UL; i<A.rows(); ++i )
563  {
564  const size_t jbegin( ( IsUpper_v<MT1> )
565  ?( ( IsStrictlyUpper_v<MT1> ? i+1UL : i ) )
566  :( 0UL ) );
567  const size_t jend( ( IsLower_v<MT1> )
568  ?( IsStrictlyLower_v<MT1> ? i : i+1UL )
569  :( A.columns() ) );
570  BLAZE_INTERNAL_ASSERT( jbegin <= jend, "Invalid loop indices detected" );
571 
572  for( size_t k=0UL; k<M; ++k ) {
573  for( size_t j=jbegin; j<jend; ++j ) {
574  if( !isDefault( A(i,j) ) ) {
575  const auto end( B.end(k) );
576  for( auto belem=B.begin(k); belem!=end; ++belem ) {
577  (~lhs).append( i*M+k, j*N+belem->index(), A(i,j) * belem->value(), true );
578  }
579  }
580  }
581  }
582  }
583  }
584  }
586  //**********************************************************************************************
587 
588  //**Addition assignment to dense matrices*******************************************************
600  template< typename MT // Type of the target dense matrix
601  , bool SO2 > // Storage order of the target dense matrix
602  friend inline void addAssign( DenseMatrix<MT,SO2>& lhs, const DMatSMatKronExpr& rhs )
603  {
605 
606  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
607  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
608 
609  if( rhs.rows() == 0UL || rhs.columns() == 0UL ) {
610  return;
611  }
612 
613  CT1 A( serial( rhs.lhs_ ) ); // Evaluation of the left-hand side dense matrix operand
614  CT2 B( serial( rhs.rhs_ ) ); // Evaluation of the right-hand side sparse matrix operand
615 
616  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
617  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
618  BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
619  BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
620 
621  const size_t M( B.rows() );
622  const size_t N( B.columns() );
623 
624  if( SO )
625  {
626  for( size_t j=0UL; j<A.columns(); ++j )
627  {
628  const size_t ibegin( ( IsLower_v<MT1> )
629  ?( ( IsStrictlyLower_v<MT1> ? j+1UL : j ) )
630  :( 0UL ) );
631  const size_t iend( ( IsUpper_v<MT1> )
632  ?( IsStrictlyUpper_v<MT1> ? j : j+1UL )
633  :( A.rows() ) );
634  BLAZE_INTERNAL_ASSERT( ibegin <= iend, "Invalid loop indices detected" );
635 
636  for( size_t l=0UL; l<N; ++l ) {
637  for( size_t i=ibegin; i<iend; ++i ) {
638  if( !isDefault( A(i,j) ) ) {
639  const auto bbegin( B.begin(l) );
640  const auto bend ( B.end(l) );
641  for( auto belem=bbegin; belem!=bend; ++belem )
642  (~lhs)(i*M+belem->index(),j*N+l) += A(i,j) * belem->value();
643  }
644  }
645  }
646  }
647  }
648  else
649  {
650  for( size_t i=0UL; i<A.rows(); ++i )
651  {
652  const size_t jbegin( ( IsUpper_v<MT1> )
653  ?( ( IsStrictlyUpper_v<MT1> ? i+1UL : i ) )
654  :( 0UL ) );
655  const size_t jend( ( IsLower_v<MT1> )
656  ?( IsStrictlyLower_v<MT1> ? i : i+1UL )
657  :( A.columns() ) );
658  BLAZE_INTERNAL_ASSERT( jbegin <= jend, "Invalid loop indices detected" );
659 
660  for( size_t k=0UL; k<M; ++k ) {
661  for( size_t j=jbegin; j<jend; ++j ) {
662  if( !isDefault( A(i,j) ) ) {
663  const auto bbegin( B.begin(k) );
664  const auto bend ( B.end(k) );
665  for( auto belem=bbegin; belem!=bend; ++belem )
666  (~lhs)(i*M+k,j*N+belem->index()) += A(i,j) * belem->value();
667  }
668  }
669  }
670  }
671  }
672  }
674  //**********************************************************************************************
675 
676  //**Addition assignment to sparse matrices******************************************************
677  // No special implementation for the addition assignment to sparse matrices.
678  //**********************************************************************************************
679 
680  //**Subtraction assignment to dense matrices****************************************************
693  template< typename MT // Type of the target dense matrix
694  , bool SO2 > // Storage order of the target dense matrix
695  friend inline void subAssign( DenseMatrix<MT,SO2>& lhs, const DMatSMatKronExpr& rhs )
696  {
698 
699  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
700  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
701 
702  if( rhs.rows() == 0UL || rhs.columns() == 0UL ) {
703  return;
704  }
705 
706  CT1 A( serial( rhs.lhs_ ) ); // Evaluation of the left-hand side dense matrix operand
707  CT2 B( serial( rhs.rhs_ ) ); // Evaluation of the right-hand side sparse matrix operand
708 
709  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
710  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
711  BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
712  BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
713 
714  const size_t M( B.rows() );
715  const size_t N( B.columns() );
716 
717  if( SO )
718  {
719  for( size_t j=0UL; j<A.columns(); ++j )
720  {
721  const size_t ibegin( ( IsLower_v<MT1> )
722  ?( ( IsStrictlyLower_v<MT1> ? j+1UL : j ) )
723  :( 0UL ) );
724  const size_t iend( ( IsUpper_v<MT1> )
725  ?( IsStrictlyUpper_v<MT1> ? j : j+1UL )
726  :( A.rows() ) );
727  BLAZE_INTERNAL_ASSERT( ibegin <= iend, "Invalid loop indices detected" );
728 
729  for( size_t l=0UL; l<N; ++l ) {
730  for( size_t i=ibegin; i<iend; ++i ) {
731  if( !isDefault( A(i,j) ) ) {
732  const auto bbegin( B.begin(l) );
733  const auto bend ( B.end(l) );
734  for( auto belem=bbegin; belem!=bend; ++belem )
735  (~lhs)(i*M+belem->index(),j*N+l) -= A(i,j) * belem->value();
736  }
737  }
738  }
739  }
740  }
741  else
742  {
743  for( size_t i=0UL; i<A.rows(); ++i )
744  {
745  const size_t jbegin( ( IsUpper_v<MT1> )
746  ?( ( IsStrictlyUpper_v<MT1> ? i+1UL : i ) )
747  :( 0UL ) );
748  const size_t jend( ( IsLower_v<MT1> )
749  ?( IsStrictlyLower_v<MT1> ? i : i+1UL )
750  :( A.columns() ) );
751  BLAZE_INTERNAL_ASSERT( jbegin <= jend, "Invalid loop indices detected" );
752 
753  for( size_t k=0UL; k<M; ++k ) {
754  for( size_t j=jbegin; j<jend; ++j ) {
755  if( !isDefault( A(i,j) ) ) {
756  const auto bbegin( B.begin(k) );
757  const auto bend ( B.end(k) );
758  for( auto belem=bbegin; belem!=bend; ++belem )
759  (~lhs)(i*M+k,j*N+belem->index()) -= A(i,j) * belem->value();
760  }
761  }
762  }
763  }
764  }
765  }
767  //**********************************************************************************************
768 
769  //**Subtraction assignment to sparse matrices***************************************************
770  // No special implementation for the subtraction assignment to sparse matrices.
771  //**********************************************************************************************
772 
773  //**Schur product assignment to dense matrices**************************************************
786  template< typename MT // Type of the target dense matrix
787  , bool SO2 > // Storage order of the target dense matrix
788  friend inline void schurAssign( DenseMatrix<MT,SO2>& lhs, const DMatSMatKronExpr& rhs )
789  {
791 
792  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
793  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
794 
795  if( rhs.rows() == 0UL || rhs.columns() == 0UL ) {
796  return;
797  }
798 
799  CT1 A( serial( rhs.lhs_ ) ); // Evaluation of the left-hand side dense matrix operand
800  CT2 B( serial( rhs.rhs_ ) ); // Evaluation of the right-hand side sparse matrix operand
801 
802  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
803  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
804  BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
805  BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
806 
807  const size_t M( B.rows() );
808  const size_t N( B.columns() );
809 
810  if( SO )
811  {
812  for( size_t j=0UL; j<A.columns(); ++j ) {
813  for( size_t l=0UL; l<N; ++l )
814  {
815  const auto bbegin( B.begin(l) );
816  const auto bend ( B.end(l) );
817 
818  for( size_t i=0UL; i<A.rows(); ++i )
819  {
820  size_t k( 0UL );
821 
822  if( !isDefault( A(i,j) ) ) {
823  for( auto belem=bbegin; belem!=bend; ++belem, ++k ) {
824  for( ; k<belem->index(); ++k )
825  reset( (~lhs)(i*M+k,j*N+l) );
826  (~lhs)(i*M+k,j*N+l) *= A(i,j) * belem->value();
827  }
828  }
829 
830  for( ; k<M; ++k ) {
831  reset( (~lhs)(i*M+k,j*N+l) );
832  }
833  }
834  }
835  }
836  }
837  else
838  {
839  for( size_t i=0UL; i<A.rows(); ++i ) {
840  for( size_t k=0UL; k<M; ++k )
841  {
842  const auto bbegin( B.begin(k) );
843  const auto bend ( B.end(k) );
844 
845  for( size_t j=0UL; j<A.columns(); ++j )
846  {
847  size_t l( 0UL );
848 
849  if( !isDefault( A(i,j) ) ) {
850  for( auto belem=bbegin; belem!=bend; ++belem, ++l ) {
851  for( ; l<belem->index(); ++l )
852  reset( (~lhs)(i*M+k,j*N+l) );
853  (~lhs)(i*M+k,j*N+l) *= A(i,j) * belem->value();
854  }
855  }
856 
857  for( ; l<N; ++l ) {
858  reset( (~lhs)(i*M+k,j*N+l) );
859  }
860  }
861  }
862  }
863  }
864  }
866  //**********************************************************************************************
867 
868  //**Schur product assignment to sparse matrices*************************************************
869  // No special implementation for the Schur product assignment to sparse matrices.
870  //**********************************************************************************************
871 
872  //**Multiplication assignment to dense matrices*************************************************
873  // No special implementation for the multiplication assignment to dense matrices.
874  //**********************************************************************************************
875 
876  //**Multiplication assignment to sparse matrices************************************************
877  // No special implementation for the multiplication assignment to sparse matrices.
878  //**********************************************************************************************
879 
880  //**Compile time checks*************************************************************************
888  //**********************************************************************************************
889 };
890 //*************************************************************************************************
891 
892 
893 
894 
895 //=================================================================================================
896 //
897 // GLOBAL FUNCTIONS
898 //
899 //=================================================================================================
900 
901 //*************************************************************************************************
914 template< typename MT1 // Type of the left-hand side dense matrix
915  , bool SO1 // Storage order of the left-hand side dense matrix
916  , typename MT2 // Type of the right-hand side sparse matrix
917  , bool SO2 // Storage order of the right-hand side sparse matrix
918  , DisableIf_t< IsZero_v<MT2> >* = nullptr >
919 inline const DMatSMatKronExpr<MT1,MT2,SO2>
920  dmatsmatkron( const DenseMatrix<MT1,SO1>& lhs, const SparseMatrix<MT2,SO2>& rhs )
921 {
923 
924  return DMatSMatKronExpr<MT1,MT2,SO2>( ~lhs, ~rhs );
925 }
927 //*************************************************************************************************
928 
929 
930 //*************************************************************************************************
943 template< typename MT1 // Type of the left-hand side dense matrix
944  , bool SO1 // Storage order of the left-hand side dense matrix
945  , typename MT2 // Type of the right-hand side sparse matrix
946  , bool SO2 // Storage order of the right-hand side sparse matrix
947  , EnableIf_t< IsZero_v<MT2> >* = nullptr >
948 inline decltype(auto)
949  dmatsmatkron( const DenseMatrix<MT1,SO1>& lhs, const SparseMatrix<MT2,SO2>& rhs )
950 {
952 
953  using ReturnType = const KronTrait_t< ResultType_t<MT1>, ResultType_t<MT2> >;
954 
957 
958  return ReturnType( (~lhs).rows()*(~rhs).rows(), (~lhs).columns()*(~rhs).columns() );
959 }
961 //*************************************************************************************************
962 
963 
964 //*************************************************************************************************
986 template< typename MT1 // Type of the left-hand side dense matrix
987  , bool SO1 // Storage order of the left-hand side dense matrix
988  , typename MT2 // Type of the right-hand side sparse matrix
989  , bool SO2 > // Storage order of the right-hand side sparse matrix
990 inline decltype(auto)
991  kron( const DenseMatrix<MT1,SO1>& lhs, const SparseMatrix<MT2,SO2>& rhs )
992 {
994 
995  return dmatsmatkron( ~lhs, ~rhs );
996 }
997 //*************************************************************************************************
998 
999 } // namespace blaze
1000 
1001 #endif
Header file for auxiliary alias declarations.
KronTrait_t< RT1, RT2 > ResultType
Result type for expression template evaluations.
Definition: DMatSMatKronExpr.h:126
Header file for basic type definitions.
Expression object for dense matrix-sparse matrix Kronecker product.The DMatSMatKronExpr class represe...
Definition: DMatSMatKronExpr.h:95
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.
size_t nonZeros() const
Returns the number of non-zero elements in the sparse matrix.
Definition: DMatSMatKronExpr.h:219
#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 columns() const noexcept
Returns the current number of columns of the matrix.
Definition: DMatSMatKronExpr.h:209
CompositeType_t< MT2 > CT2
Composite type of the right-hand side sparse matrix expression.
Definition: DMatSMatKronExpr.h:106
Header file for the IsColumnMajorMatrix type trait.
ResultType_t< MT2 > RT2
Result type of the right-hand side sparse matrix expression.
Definition: DMatSMatKronExpr.h:102
void reset(const DiagonalProxy< MT > &proxy)
Resetting the represented element to the default initial values.
Definition: DiagonalProxy.h:595
Constraint on the data type.
Header file for the MAYBE_UNUSED function template.
ReturnType_t< MT2 > RN2
Return type of the right-hand side sparse matrix expression.
Definition: DMatSMatKronExpr.h:104
Header file for the Computation base class.
Header file for the reset shim.
ReturnType_t< MT1 > RN1
Return type of the left-hand side dense matrix expression.
Definition: DMatSMatKronExpr.h:103
ReturnType at(size_t i, size_t j) const
Checked access to the matrix elements.
Definition: DMatSMatKronExpr.h:183
typename T::ReturnType ReturnType_t
Alias declaration for nested ReturnType type definitions.The ReturnType_t alias declaration provides ...
Definition: Aliases.h:410
bool canAlias(const T *alias) const noexcept
Returns whether the expression can alias with the given address alias.
Definition: DMatSMatKronExpr.h:265
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
Header file for the MatMatKronExpr base class.
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.
Constraint on the data type.
Base class for all matrix/matrix Kronecker expression templates.The MatMatKronExpr class serves as a ...
Definition: MatMatKronExpr.h:67
Constraint on the data type.
decltype(std::declval< RN1 >() *std::declval< RN2 >()) ExprReturnType
Expression return type for the subscript operator.
Definition: DMatSMatKronExpr.h:119
Header file for the DisableIf class template.
Header file for the IsTemporary type trait class.
Header file for the IsStrictlyUpper type trait.
size_t nonZeros(size_t i) const
Returns the number of non-zero elements in the specified row.
Definition: DMatSMatKronExpr.h:230
const If_t< returnExpr, ExprReturnType, ElementType > ReturnType
Return type for expression template evaluations.
Definition: DMatSMatKronExpr.h:132
Namespace of the Blaze C++ math library.
Definition: Blaze.h:58
Header file for the If class template.
#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
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
OppositeType_t< ResultType > OppositeType
Result type with opposite storage order for expression template evaluations.
Definition: DMatSMatKronExpr.h:127
#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.
Header file for the IsLower type trait.
ResultType_t< MT1 > RT1
Result type of the left-hand side dense matrix expression.
Definition: DMatSMatKronExpr.h:101
LeftOperand lhs_
Left-hand side dense matrix of the Kronecker product expression.
Definition: DMatSMatKronExpr.h:284
Header file for the Kron product trait.
static constexpr bool returnExpr
Compilation switch for the selection of the subscript operator return type.
Definition: DMatSMatKronExpr.h:116
Constraints on the storage order of matrix types.
Header file for the exception macros of the math module.
Constraint on the data type.
If_t< IsExpression_v< MT2 >, const MT2, const MT2 & > RightOperand
Composite type of the right-hand side sparse matrix expression.
Definition: DMatSMatKronExpr.h:141
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
Header file for the EnableIf class template.
Header file for the IsStrictlyLower type trait.
DMatSMatKronExpr(const MT1 &lhs, const MT2 &rhs) noexcept
Constructor for the DMatSMatKronExpr class.
Definition: DMatSMatKronExpr.h:155
typename T::OppositeType OppositeType_t
Alias declaration for nested OppositeType type definitions.The OppositeType_t alias declaration provi...
Definition: Aliases.h:270
ReturnType operator()(size_t i, size_t j) const
2D-access to the matrix elements.
Definition: DMatSMatKronExpr.h:168
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
TransposeType_t< ResultType > TransposeType
Transpose type for expression template evaluations.
Definition: DMatSMatKronExpr.h:128
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 the isDefault shim.
static constexpr bool smpAssignable
Compilation switch for the expression template assignment strategy.
Definition: DMatSMatKronExpr.h:146
decltype(auto) serial(const DenseMatrix< MT, SO > &dm)
Forces the serial evaluation of the given dense matrix expression dm.
Definition: DMatSerialExpr.h:808
constexpr size_t rows(const Matrix< MT, SO > &matrix) noexcept
Returns the current number of rows of the matrix.
Definition: Matrix.h:498
LeftOperand leftOperand() const noexcept
Returns the left-hand side dense matrix operand.
Definition: DMatSMatKronExpr.h:243
ElementType_t< ResultType > ElementType
Resulting element type.
Definition: DMatSMatKronExpr.h:129
Header file for the IsRowMajorMatrix type trait.
RightOperand rhs_
Right-hand side sparse matrix of the Kronecker product expression.
Definition: DMatSMatKronExpr.h:285
bool isAliased(const T *alias) const noexcept
Returns whether the expression is aliased with the given address alias.
Definition: DMatSMatKronExpr.h:277
#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
Base class for all compute expression templates.The Computation class serves as a tag for all computa...
Definition: Computation.h:66
CompositeType_t< MT1 > CT1
Composite type of the left-hand side dense matrix expression.
Definition: DMatSMatKronExpr.h:105
If_t< IsExpression_v< MT1 >, const MT1, const MT1 & > LeftOperand
Composite type of the left-hand side dense matrix expression.
Definition: DMatSMatKronExpr.h:138
const ResultType CompositeType
Data type for composite expression templates.
Definition: DMatSMatKronExpr.h:135
bool isDefault(const DiagonalProxy< MT > &proxy)
Returns whether the represented element is in default state.
Definition: DiagonalProxy.h:635
Header file for the IsUpper type trait.
size_t rows() const noexcept
Returns the current number of rows of the matrix.
Definition: DMatSMatKronExpr.h:199
#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
RightOperand rightOperand() const noexcept
Returns the right-hand side sparse matrix operand.
Definition: DMatSMatKronExpr.h:253
#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
Header file for the IsExpression type trait class.
Header file for the function trace functionality.