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