Blaze 3.9
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>
66#include <blaze/util/Assert.h>
67#include <blaze/util/EnableIf.h>
69#include <blaze/util/mpl/If.h>
70#include <blaze/util/Types.h>
71
72
73namespace blaze {
74
75//=================================================================================================
76//
77// CLASS DMATSMATKRONEXPR
78//
79//=================================================================================================
80
81//*************************************************************************************************
88template< typename MT1 // Type of the left-hand side dense matrix
89 , typename MT2 // Type of the right-hand side sparse matrix
90 , bool SO > // Storage order
92 : public MatMatKronExpr< SparseMatrix< DMatSMatKronExpr<MT1,MT2,SO>, SO > >
93 , private Computation
94{
95 private:
96 //**Type definitions****************************************************************************
103 //**********************************************************************************************
104
105 //**Return type evaluation**********************************************************************
107
112 static constexpr bool returnExpr = ( !IsTemporary_v<RN1> && !IsTemporary_v<RN2> );
113
115 using ExprReturnType = decltype( std::declval<RN1>() * std::declval<RN2>() );
116 //**********************************************************************************************
117
118 public:
119 //**Type definitions****************************************************************************
122
125
130
133
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 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<strict>( 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<strict>( 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<strict>( 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<strict>( 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<strict>( 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<strict>( 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<strict>( 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<strict>( 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<strict>( 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<strict>( 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<strict>( 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<strict>( 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//*************************************************************************************************
914template< 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 >
919inline 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//*************************************************************************************************
943template< 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 >
948inline 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//*************************************************************************************************
986template< 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
990inline decltype(auto)
992{
994
995 return dmatsmatkron( *lhs, *rhs );
996}
997//*************************************************************************************************
998
999} // namespace blaze
1000
1001#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 isDefault shim.
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.
Expression object for dense matrix-sparse matrix Kronecker product.
Definition: DMatSMatKronExpr.h:94
LeftOperand leftOperand() const noexcept
Returns the left-hand side dense matrix operand.
Definition: DMatSMatKronExpr.h:243
RightOperand rhs_
Right-hand side sparse matrix of the Kronecker product expression.
Definition: DMatSMatKronExpr.h:285
ReturnType at(size_t i, size_t j) const
Checked access to the matrix elements.
Definition: DMatSMatKronExpr.h:183
ReturnType operator()(size_t i, size_t j) const
2D-access to the matrix elements.
Definition: DMatSMatKronExpr.h:168
LeftOperand lhs_
Left-hand side dense matrix of the Kronecker product expression.
Definition: DMatSMatKronExpr.h:284
size_t rows() const noexcept
Returns the current number of rows of the matrix.
Definition: DMatSMatKronExpr.h:199
DMatSMatKronExpr(const MT1 &lhs, const MT2 &rhs) noexcept
Constructor for the DMatSMatKronExpr class.
Definition: DMatSMatKronExpr.h:155
size_t columns() const noexcept
Returns the current number of columns of the matrix.
Definition: DMatSMatKronExpr.h:209
If_t< IsExpression_v< MT1 >, const MT1, const MT1 & > LeftOperand
Composite type of the left-hand side dense matrix expression.
Definition: DMatSMatKronExpr.h:138
If_t< IsExpression_v< MT2 >, const MT2, const MT2 & > RightOperand
Composite type of the right-hand side sparse matrix expression.
Definition: DMatSMatKronExpr.h:141
size_t nonZeros(size_t i) const
Returns the number of non-zero elements in the specified row.
Definition: DMatSMatKronExpr.h:230
TransposeType_t< ResultType > TransposeType
Transpose type for expression template evaluations.
Definition: DMatSMatKronExpr.h:128
CompositeType_t< MT1 > CT1
Composite type of the left-hand side dense matrix expression.
Definition: DMatSMatKronExpr.h:101
KronTrait_t< RT1, RT2 > ResultType
Result type for expression template evaluations.
Definition: DMatSMatKronExpr.h:126
ElementType_t< ResultType > ElementType
Resulting element type.
Definition: DMatSMatKronExpr.h:129
ResultType_t< MT1 > RT1
Result type of the left-hand side dense matrix expression.
Definition: DMatSMatKronExpr.h:97
RightOperand rightOperand() const noexcept
Returns the right-hand side sparse matrix operand.
Definition: DMatSMatKronExpr.h:253
bool isAliased(const T *alias) const noexcept
Returns whether the expression is aliased with the given address alias.
Definition: DMatSMatKronExpr.h:277
static constexpr bool returnExpr
Compilation switch for the selection of the subscript operator return type.
Definition: DMatSMatKronExpr.h:112
size_t nonZeros() const
Returns the number of non-zero elements in the sparse matrix.
Definition: DMatSMatKronExpr.h:219
bool canAlias(const T *alias) const noexcept
Returns whether the expression can alias with the given address alias.
Definition: DMatSMatKronExpr.h:265
OppositeType_t< ResultType > OppositeType
Result type with opposite storage order for expression template evaluations.
Definition: DMatSMatKronExpr.h:127
const If_t< returnExpr, ExprReturnType, ElementType > ReturnType
Return type for expression template evaluations.
Definition: DMatSMatKronExpr.h:132
const ResultType CompositeType
Data type for composite expression templates.
Definition: DMatSMatKronExpr.h:135
ReturnType_t< MT1 > RN1
Return type of the left-hand side dense matrix expression.
Definition: DMatSMatKronExpr.h:99
CompositeType_t< MT2 > CT2
Composite type of the right-hand side sparse matrix expression.
Definition: DMatSMatKronExpr.h:102
ReturnType_t< MT2 > RN2
Return type of the right-hand side sparse matrix expression.
Definition: DMatSMatKronExpr.h:100
decltype(std::declval< RN1 >() *std::declval< RN2 >()) ExprReturnType
Expression return type for the subscript operator.
Definition: DMatSMatKronExpr.h:115
ResultType_t< MT2 > RT2
Result type of the right-hand side sparse matrix expression.
Definition: DMatSMatKronExpr.h:98
static constexpr bool smpAssignable
Compilation switch for the expression template assignment strategy.
Definition: DMatSMatKronExpr.h:146
Base class for dense matrices.
Definition: DenseMatrix.h:82
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
#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
decltype(auto) kron(const DenseMatrix< MT1, SO1 > &lhs, const SparseMatrix< MT2, SO2 > &rhs)
Computes the Kronecker product of a dense matrix and a sparse matrix ( ).
Definition: DMatSMatKronExpr.h:991
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.