Blaze 3.9
SMatSMatSchurExpr.h
Go to the documentation of this file.
1//=================================================================================================
33//=================================================================================================
34
35#ifndef _BLAZE_MATH_EXPRESSIONS_SMATSMATSCHUREXPR_H_
36#define _BLAZE_MATH_EXPRESSIONS_SMATSMATSCHUREXPR_H_
37
38
39//*************************************************************************************************
40// Includes
41//*************************************************************************************************
42
43#include <utility>
44#include <blaze/math/Aliases.h>
72#include <blaze/util/Assert.h>
73#include <blaze/util/EnableIf.h>
77#include <blaze/util/mpl/If.h>
78#include <blaze/util/Types.h>
79
80
81namespace blaze {
82
83//=================================================================================================
84//
85// CLASS SMATSMATSCHUREXPR
86//
87//=================================================================================================
88
89//*************************************************************************************************
96template< typename MT1 // Type of the left-hand side sparse matrix
97 , typename MT2 > // Type of the right-hand side sparse matrix
99 : public SchurExpr< SparseMatrix< SMatSMatSchurExpr<MT1,MT2>, false > >
100 , private Computation
101{
102 private:
103 //**Type definitions****************************************************************************
110 //**********************************************************************************************
111
112 //**Return type evaluation**********************************************************************
114
119 static constexpr bool returnExpr = ( !IsTemporary_v<RN1> && !IsTemporary_v<RN2> );
120
122 using ExprReturnType = decltype( std::declval<RN1>() * std::declval<RN2>() );
123 //**********************************************************************************************
124
125 //**Serial evaluation strategy******************************************************************
127
132 template< typename T1, typename T2, typename T3 >
133 static constexpr bool UseSymmetricKernel_v =
134 ( IsColumnMajorMatrix_v<T1> && IsSymmetric_v<T2> && IsSymmetric_v<T3> );
136 //**********************************************************************************************
137
138 public:
139 //**Type definitions****************************************************************************
142
145
150
153
156
158 using LeftOperand = If_t< IsExpression_v<MT1>, const MT1, const MT1& >;
159
161 using RightOperand = If_t< IsExpression_v<MT2>, const MT2, const MT2& >;
162 //**********************************************************************************************
163
164 //**Compilation flags***************************************************************************
166 static constexpr bool smpAssignable = false;
167 //**********************************************************************************************
168
169 //**Constructor*********************************************************************************
175 inline SMatSMatSchurExpr( const MT1& lhs, const MT2& rhs ) noexcept
176 : lhs_( lhs ) // Left-hand side sparse matrix of the Schur product expression
177 , rhs_( rhs ) // Right-hand side sparse matrix of the Schur product expression
178 {
179 BLAZE_INTERNAL_ASSERT( lhs.rows() == rhs.rows() , "Invalid number of rows" );
180 BLAZE_INTERNAL_ASSERT( lhs.columns() == rhs.columns(), "Invalid number of columns" );
181 }
182 //**********************************************************************************************
183
184 //**Access operator*****************************************************************************
191 inline ReturnType operator()( size_t i, size_t j ) const {
192 BLAZE_INTERNAL_ASSERT( i < lhs_.rows() , "Invalid row access index" );
193 BLAZE_INTERNAL_ASSERT( j < lhs_.columns(), "Invalid column access index" );
194 return lhs_(i,j) * rhs_(i,j);
195 }
196 //**********************************************************************************************
197
198 //**At function*********************************************************************************
206 inline ReturnType at( size_t i, size_t j ) const {
207 if( i >= lhs_.rows() ) {
208 BLAZE_THROW_OUT_OF_RANGE( "Invalid row access index" );
209 }
210 if( j >= lhs_.columns() ) {
211 BLAZE_THROW_OUT_OF_RANGE( "Invalid column access index" );
212 }
213 return (*this)(i,j);
214 }
215 //**********************************************************************************************
216
217 //**Rows function*******************************************************************************
222 inline size_t rows() const noexcept {
223 return lhs_.rows();
224 }
225 //**********************************************************************************************
226
227 //**Columns function****************************************************************************
232 inline size_t columns() const noexcept {
233 return lhs_.columns();
234 }
235 //**********************************************************************************************
236
237 //**NonZeros function***************************************************************************
242 inline size_t nonZeros() const {
243 return min( lhs_.nonZeros(), rhs_.nonZeros() );
244 }
245 //**********************************************************************************************
246
247 //**NonZeros function***************************************************************************
253 inline size_t nonZeros( size_t i ) const {
254 return min( lhs_.nonZeros(i), rhs_.nonZeros(i) );
255 }
256 //**********************************************************************************************
257
258 //**Left operand access*************************************************************************
263 inline LeftOperand leftOperand() const noexcept {
264 return lhs_;
265 }
266 //**********************************************************************************************
267
268 //**Right operand access************************************************************************
273 inline RightOperand rightOperand() const noexcept {
274 return rhs_;
275 }
276 //**********************************************************************************************
277
278 //**********************************************************************************************
284 template< typename T >
285 inline bool canAlias( const T* alias ) const noexcept {
286 return ( lhs_.canAlias( alias ) || rhs_.canAlias( alias ) );
287 }
288 //**********************************************************************************************
289
290 //**********************************************************************************************
296 template< typename T >
297 inline bool isAliased( const T* alias ) const noexcept {
298 return ( lhs_.isAliased( alias ) || rhs_.isAliased( alias ) );
299 }
300 //**********************************************************************************************
301
302 private:
303 //**Member variables****************************************************************************
306 //**********************************************************************************************
307
308 //**Assignment to dense matrices****************************************************************
320 template< typename MT // Type of the target dense matrix
321 , bool SO > // Storage order of the target dense matrix
322 friend inline auto assign( DenseMatrix<MT,SO>& lhs, const SMatSMatSchurExpr& rhs )
324 {
326
327 BLAZE_INTERNAL_ASSERT( (*lhs).rows() == rhs.rows() , "Invalid number of rows" );
328 BLAZE_INTERNAL_ASSERT( (*lhs).columns() == rhs.columns(), "Invalid number of columns" );
329
330 CT1 A( serial( rhs.lhs_ ) ); // Evaluation of the left-hand side sparse matrix operand
331 CT2 B( serial( rhs.rhs_ ) ); // Evaluation of the right-hand side sparse matrix operand
332
333 BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
334 BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
335 BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
336 BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
337 BLAZE_INTERNAL_ASSERT( A.rows() == (*lhs).rows() , "Invalid number of rows" );
338 BLAZE_INTERNAL_ASSERT( A.columns() == (*lhs).columns() , "Invalid number of columns" );
339
340 for( size_t i=0UL; i<(*lhs).rows(); ++i )
341 {
342 const auto lend( A.end(i) );
343 const auto rend( B.end(i) );
344
345 auto l( A.begin(i) );
346 auto r( B.begin(i) );
347
348 for( ; l!=lend; ++l ) {
349 while( r!=rend && r->index() < l->index() ) ++r;
350 if( r==rend ) break;
351 if( l->index() == r->index() ) {
352 (*lhs)(i,l->index()) = l->value() * r->value();
353 ++r;
354 }
355 }
356 }
357 }
359 //**********************************************************************************************
360
361 //**Assignment to row-major sparse matrices*****************************************************
373 template< typename MT > // Type of the target sparse matrix
374 friend inline void assign( SparseMatrix<MT,false>& lhs, const SMatSMatSchurExpr& rhs )
375 {
377
378 BLAZE_INTERNAL_ASSERT( (*lhs).rows() == rhs.rows() , "Invalid number of rows" );
379 BLAZE_INTERNAL_ASSERT( (*lhs).columns() == rhs.columns(), "Invalid number of columns" );
380
381 CT1 A( serial( rhs.lhs_ ) ); // Evaluation of the left-hand side sparse matrix operand
382 CT2 B( serial( rhs.rhs_ ) ); // Evaluation of the right-hand side sparse matrix operand
383
384 BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
385 BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
386 BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
387 BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
388 BLAZE_INTERNAL_ASSERT( A.rows() == (*lhs).rows() , "Invalid number of rows" );
389 BLAZE_INTERNAL_ASSERT( A.columns() == (*lhs).columns() , "Invalid number of columns" );
390
391 // Final memory allocation (based on the evaluated operands)
392 (*lhs).reserve( min( A.nonZeros(), B.nonZeros() ) );
393
394 // Performing the Schur product
395 for( size_t i=0UL; i<(*lhs).rows(); ++i )
396 {
397 const auto lend( A.end(i) );
398 const auto rend( B.end(i) );
399
400 auto l( A.begin(i) );
401 auto r( B.begin(i) );
402
403 for( ; l!=lend; ++l ) {
404 while( r!=rend && r->index() < l->index() ) ++r;
405 if( r==rend ) break;
406 if( l->index() == r->index() ) {
407 (*lhs).append( i, l->index(), l->value() * r->value() );
408 ++r;
409 }
410 }
411
412 (*lhs).finalize( i );
413 }
414 }
416 //**********************************************************************************************
417
418 //**Assignment to column-major sparse matrices**************************************************
431 template< typename MT > // Type of the target sparse matrix
432 friend inline auto assign( SparseMatrix<MT,true>& lhs, const SMatSMatSchurExpr& rhs )
433 -> DisableIf_t< UseSymmetricKernel_v<MT,MT1,MT2> >
434 {
436
438
439 BLAZE_INTERNAL_ASSERT( (*lhs).rows() == rhs.rows() , "Invalid number of rows" );
440 BLAZE_INTERNAL_ASSERT( (*lhs).columns() == rhs.columns(), "Invalid number of columns" );
441
442 CT1 A( serial( rhs.lhs_ ) ); // Evaluation of the left-hand side sparse matrix operand
443 CT2 B( serial( rhs.rhs_ ) ); // Evaluation of the right-hand side sparse matrix operand
444
445 BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
446 BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
447 BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
448 BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
449 BLAZE_INTERNAL_ASSERT( A.rows() == (*lhs).rows() , "Invalid number of rows" );
450 BLAZE_INTERNAL_ASSERT( A.columns() == (*lhs).columns() , "Invalid number of columns" );
451
452 const size_t m( rhs.rows() );
453 const size_t n( rhs.columns() );
454
455 // Counting the number of elements per column
456 std::vector<size_t> nonzeros( n, 0UL );
457 for( size_t i=0UL; i<m; ++i )
458 {
459 const auto lend( A.end(i) );
460 const auto rend( B.end(i) );
461
462 auto l( A.begin(i) );
463 auto r( B.begin(i) );
464
465 for( ; l!=lend; ++l ) {
466 while( r!=rend && r->index() < l->index() ) ++r;
467 if( r==rend ) break;
468 if( l->index() == r->index() ) {
469 ++nonzeros[l->index()];
470 ++r;
471 }
472 }
473 }
474
475 // Resizing the left-hand side sparse matrix
476 for( size_t j=0UL; j<n; ++j ) {
477 (*lhs).reserve( j, nonzeros[j] );
478 }
479
480 // Performing the Schur product
481 for( size_t i=0UL; i<m; ++i )
482 {
483 const auto lend( A.end(i) );
484 const auto rend( B.end(i) );
485
486 auto l( A.begin(i) );
487 auto r( B.begin(i) );
488
489 for( ; l!=lend; ++l ) {
490 while( r!=rend && r->index() < l->index() ) ++r;
491 if( r==rend ) break;
492 if( l->index() == r->index() ) {
493 (*lhs).append( i, l->index(), l->value() * r->value() );
494 ++r;
495 }
496 }
497 }
498 }
500 //**********************************************************************************************
501
502 //**Restructuring assignment to column-major matrices*******************************************
515 template< typename MT > // Type of the target matrix
516 friend inline auto assign( Matrix<MT,true>& lhs, const SMatSMatSchurExpr& rhs )
517 -> EnableIf_t< UseSymmetricKernel_v<MT,MT1,MT2> >
518 {
520
522
523 BLAZE_INTERNAL_ASSERT( (*lhs).rows() == rhs.rows() , "Invalid number of rows" );
524 BLAZE_INTERNAL_ASSERT( (*lhs).columns() == rhs.columns(), "Invalid number of columns" );
525
526 assign( *lhs, trans( rhs.lhs_ ) % trans( rhs.rhs_ ) );
527 }
529 //**********************************************************************************************
530
531 //**Addition assignment to dense matrices*******************************************************
543 template< typename MT // Type of the target dense matrix
544 , bool SO > // Storage order of the target dense matrix
545 friend inline auto addAssign( DenseMatrix<MT,SO>& lhs, const SMatSMatSchurExpr& rhs )
546 -> DisableIf_t< UseSymmetricKernel_v<MT,MT1,MT2> >
547 {
549
550 BLAZE_INTERNAL_ASSERT( (*lhs).rows() == rhs.rows() , "Invalid number of rows" );
551 BLAZE_INTERNAL_ASSERT( (*lhs).columns() == rhs.columns(), "Invalid number of columns" );
552
553 CT1 A( serial( rhs.lhs_ ) ); // Evaluation of the left-hand side sparse matrix operand
554 CT2 B( serial( rhs.rhs_ ) ); // Evaluation of the right-hand side sparse matrix operand
555
556 BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
557 BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
558 BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
559 BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
560 BLAZE_INTERNAL_ASSERT( A.rows() == (*lhs).rows() , "Invalid number of rows" );
561 BLAZE_INTERNAL_ASSERT( A.columns() == (*lhs).columns() , "Invalid number of columns" );
562
563 for( size_t i=0UL; i<(*lhs).rows(); ++i )
564 {
565 const auto lend( A.end(i) );
566 const auto rend( B.end(i) );
567
568 auto l( A.begin(i) );
569 auto r( B.begin(i) );
570
571 for( ; l!=lend; ++l ) {
572 while( r!=rend && r->index() < l->index() ) ++r;
573 if( r==rend ) break;
574 if( l->index() == r->index() ) {
575 (*lhs)(i,l->index()) += l->value() * r->value();
576 ++r;
577 }
578 }
579 }
580 }
582 //**********************************************************************************************
583
584 //**Restructuring addition assignment to column-major matrices**********************************
597 template< typename MT > // Type of the target matrix
598 friend inline auto addAssign( Matrix<MT,true>& lhs, const SMatSMatSchurExpr& rhs )
599 -> EnableIf_t< UseSymmetricKernel_v<MT,MT1,MT2> >
600 {
602
604
605 BLAZE_INTERNAL_ASSERT( (*lhs).rows() == rhs.rows() , "Invalid number of rows" );
606 BLAZE_INTERNAL_ASSERT( (*lhs).columns() == rhs.columns(), "Invalid number of columns" );
607
608 addAssign( *lhs, trans( rhs.lhs_ ) % trans( rhs.rhs_ ) );
609 }
611 //**********************************************************************************************
612
613 //**Addition assignment to sparse matrices******************************************************
614 // No special implementation for the addition assignment to sparse matrices.
615 //**********************************************************************************************
616
617 //**Subtraction assignment to dense matrices****************************************************
630 template< typename MT // Type of the target dense matrix
631 , bool SO > // Storage order of the target dense matrix
632 friend inline auto subAssign( DenseMatrix<MT,SO>& lhs, const SMatSMatSchurExpr& rhs )
633 -> DisableIf_t< UseSymmetricKernel_v<MT,MT1,MT2> >
634 {
636
637 BLAZE_INTERNAL_ASSERT( (*lhs).rows() == rhs.rows() , "Invalid number of rows" );
638 BLAZE_INTERNAL_ASSERT( (*lhs).columns() == rhs.columns(), "Invalid number of columns" );
639
640 CT1 A( serial( rhs.lhs_ ) ); // Evaluation of the left-hand side sparse matrix operand
641 CT2 B( serial( rhs.rhs_ ) ); // Evaluation of the right-hand side sparse matrix operand
642
643 BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
644 BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
645 BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
646 BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
647 BLAZE_INTERNAL_ASSERT( A.rows() == (*lhs).rows() , "Invalid number of rows" );
648 BLAZE_INTERNAL_ASSERT( A.columns() == (*lhs).columns() , "Invalid number of columns" );
649
650 for( size_t i=0UL; i<(*lhs).rows(); ++i )
651 {
652 const auto lend( A.end(i) );
653 const auto rend( B.end(i) );
654
655 auto l( A.begin(i) );
656 auto r( B.begin(i) );
657
658 for( ; l!=lend; ++l ) {
659 while( r!=rend && r->index() < l->index() ) ++r;
660 if( r==rend ) break;
661 if( l->index() == r->index() ) {
662 (*lhs)(i,l->index()) -= l->value() * r->value();
663 ++r;
664 }
665 }
666 }
667 }
669 //**********************************************************************************************
670
671 //**Restructuring subtraction assignment to column-major matrices*******************************
684 template< typename MT > // Type of the target matrix
685 friend inline auto subAssign( Matrix<MT,true>& lhs, const SMatSMatSchurExpr& rhs )
686 -> EnableIf_t< UseSymmetricKernel_v<MT,MT1,MT2> >
687 {
689
691
692 BLAZE_INTERNAL_ASSERT( (*lhs).rows() == rhs.rows() , "Invalid number of rows" );
693 BLAZE_INTERNAL_ASSERT( (*lhs).columns() == rhs.columns(), "Invalid number of columns" );
694
695 subAssign( *lhs, trans( rhs.lhs_ ) % trans( rhs.rhs_ ) );
696 }
698 //**********************************************************************************************
699
700 //**Subtraction assignment to sparse matrices***************************************************
701 // No special implementation for the subtraction assignment to sparse matrices.
702 //**********************************************************************************************
703
704 //**Schur product assignment to dense matrices**************************************************
717 template< typename MT // Type of the target dense matrix
718 , bool SO > // Storage order of the target dense matrix
719 friend inline auto schurAssign( DenseMatrix<MT,SO>& lhs, const SMatSMatSchurExpr& rhs )
720 -> DisableIf_t< UseSymmetricKernel_v<MT,MT1,MT2> >
721 {
723
724 BLAZE_INTERNAL_ASSERT( (*lhs).rows() == rhs.rows() , "Invalid number of rows" );
725 BLAZE_INTERNAL_ASSERT( (*lhs).columns() == rhs.columns(), "Invalid number of columns" );
726
727 CT1 A( serial( rhs.lhs_ ) ); // Evaluation of the left-hand side sparse matrix operand
728 CT2 B( serial( rhs.rhs_ ) ); // Evaluation of the right-hand side sparse matrix operand
729
730 BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
731 BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
732 BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
733 BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
734 BLAZE_INTERNAL_ASSERT( A.rows() == (*lhs).rows() , "Invalid number of rows" );
735 BLAZE_INTERNAL_ASSERT( A.columns() == (*lhs).columns() , "Invalid number of columns" );
736
737 for( size_t i=0UL; i<(*lhs).rows(); ++i )
738 {
739 const auto lend( A.end(i) );
740 const auto rend( B.end(i) );
741
742 auto l( A.begin(i) );
743 auto r( B.begin(i) );
744
745 size_t j( 0UL );
746
747 for( ; l!=lend; ++l ) {
748 while( r!=rend && r->index() < l->index() ) ++r;
749 if( r==rend ) break;
750 if( l->index() == r->index() ) {
751 for( ; j<l->index(); ++j )
752 reset( (*lhs)(i,j) );
753 (*lhs)(i,l->index()) *= l->value() * r->value();
754 ++r;
755 ++j;
756 }
757 }
758
759 for( ; j<(*lhs).columns(); ++j )
760 reset( (*lhs)(i,j) );
761 }
762 }
764 //**********************************************************************************************
765
766 //**Restructuring Schur product assignment to column-major matrices*****************************
779 template< typename MT > // Type of the target matrix
780 friend inline auto schurAssign( Matrix<MT,true>& lhs, const SMatSMatSchurExpr& rhs )
781 -> EnableIf_t< UseSymmetricKernel_v<MT,MT1,MT2> >
782 {
784
786
787 BLAZE_INTERNAL_ASSERT( (*lhs).rows() == rhs.rows() , "Invalid number of rows" );
788 BLAZE_INTERNAL_ASSERT( (*lhs).columns() == rhs.columns(), "Invalid number of columns" );
789
790 schurAssign( *lhs, trans( rhs.lhs_ ) % trans( rhs.rhs_ ) );
791 }
793 //**********************************************************************************************
794
795 //**Schur product assignment to sparse matrices*************************************************
796 // No special implementation for the Schur product assignment to sparse matrices.
797 //**********************************************************************************************
798
799 //**Multiplication assignment to dense matrices*************************************************
800 // No special implementation for the multiplication assignment to dense matrices.
801 //**********************************************************************************************
802
803 //**Multiplication assignment to sparse matrices************************************************
804 // No special implementation for the multiplication assignment to sparse matrices.
805 //**********************************************************************************************
806
807 //**SMP assignment to dense matrices************************************************************
808 // No special implementation for the SMP assignment to dense matrices.
809 //**********************************************************************************************
810
811 //**SMP assignment to sparse matrices***********************************************************
812 // No special implementation for the SMP assignment to sparse matrices.
813 //**********************************************************************************************
814
815 //**SMP addition assignment to dense matrices***************************************************
816 // No special implementation for the SMP addition assignment to dense matrices.
817 //**********************************************************************************************
818
819 //**SMP addition assignment to sparse matrices**************************************************
820 // No special implementation for the SMP addition assignment to sparse matrices.
821 //**********************************************************************************************
822
823 //**SMP subtraction assignment to dense matrices************************************************
824 // No special implementation for the SMP subtraction assignment to dense matrices.
825 //**********************************************************************************************
826
827 //**SMP subtraction assignment to sparse matrices***********************************************
828 // No special implementation for the SMP subtraction assignment to sparse matrices.
829 //**********************************************************************************************
830
831 //**SMP Schur product assignment to dense matrices**********************************************
844 template< typename MT // Type of the target dense matrix
845 , bool SO > // Storage order of the target dense matrix
846 friend inline void smpSchurAssign( DenseMatrix<MT,SO>& lhs, const SMatSMatSchurExpr& rhs )
847 {
849
850 BLAZE_INTERNAL_ASSERT( (*lhs).rows() == rhs.rows() , "Invalid number of rows" );
851 BLAZE_INTERNAL_ASSERT( (*lhs).columns() == rhs.columns(), "Invalid number of columns" );
852
853 smpSchurAssign( *lhs, rhs.lhs_ );
854 smpSchurAssign( *lhs, rhs.rhs_ );
855 }
857 //**********************************************************************************************
858
859 //**SMP Schur product assignment to sparse matrices*********************************************
860 // No special implementation for the SMP Schur product assignment to sparse matrices.
861 //**********************************************************************************************
862
863 //**SMP multiplication assignment to dense matrices*********************************************
864 // No special implementation for the SMP multiplication assignment to dense matrices.
865 //**********************************************************************************************
866
867 //**SMP multiplication assignment to sparse matrices********************************************
868 // No special implementation for the SMP multiplication assignment to sparse matrices.
869 //**********************************************************************************************
870
871 //**Compile time checks*************************************************************************
881 //**********************************************************************************************
882};
883//*************************************************************************************************
884
885
886
887
888//=================================================================================================
889//
890// GLOBAL BINARY ARITHMETIC OPERATORS
891//
892//=================================================================================================
893
894//*************************************************************************************************
907template< typename MT1 // Type of the left-hand side sparse matrix
908 , typename MT2 // Type of the right-hand side sparse matrix
909 , DisableIf_t< ( IsUniLower_v<MT1> && IsUniUpper_v<MT2> ) ||
910 ( IsUniUpper_v<MT1> && IsUniLower_v<MT2> ) ||
911 ( IsStrictlyLower_v<MT1> && IsUpper_v<MT2> ) ||
912 ( IsStrictlyUpper_v<MT1> && IsLower_v<MT2> ) ||
913 ( IsLower_v<MT1> && IsStrictlyUpper_v<MT2> ) ||
914 ( IsUpper_v<MT1> && IsStrictlyLower_v<MT2> ) ||
915 ( IsZero_v<MT1> || IsZero_v<MT2> ) >* = nullptr >
916inline const SMatSMatSchurExpr<MT1,MT2>
917 smatsmatschur( const SparseMatrix<MT1,false>& lhs, const SparseMatrix<MT2,false>& rhs )
918{
920
921 BLAZE_INTERNAL_ASSERT( (*lhs).rows() == (*rhs).rows() , "Invalid number of rows" );
922 BLAZE_INTERNAL_ASSERT( (*lhs).columns() == (*rhs).columns(), "Invalid number of columns" );
923
924 return SMatSMatSchurExpr<MT1,MT2>( *lhs, *rhs );
925}
927//*************************************************************************************************
928
929
930//*************************************************************************************************
943template< typename MT1 // Type of the left-hand side sparse matrix
944 , typename MT2 // Type of the right-hand side sparse matrix
945 , EnableIf_t< ( IsUniLower_v<MT1> && IsUniUpper_v<MT2> ) ||
946 ( IsUniUpper_v<MT1> && IsUniLower_v<MT2> ) >* = nullptr >
947inline decltype(auto)
948 smatsmatschur( const SparseMatrix<MT1,false>& lhs, const SparseMatrix<MT2,false>& rhs )
949{
951
952 MAYBE_UNUSED( rhs );
953
954 BLAZE_INTERNAL_ASSERT( (*lhs).rows() == (*rhs).rows() , "Invalid number of rows" );
955 BLAZE_INTERNAL_ASSERT( (*lhs).columns() == (*rhs).columns(), "Invalid number of columns" );
956
957 using ReturnType = const SchurTrait_t< ResultType_t<MT1>, ResultType_t<MT2> >;
958
961
962 return ReturnType( (*lhs).rows() );
963}
965//*************************************************************************************************
966
967
968//*************************************************************************************************
981template< typename MT1 // Type of the left-hand side sparse matrix
982 , typename MT2 // Type of the right-hand side sparse matrix
983 , EnableIf_t< ( IsStrictlyLower_v<MT1> && IsUpper_v<MT2> ) ||
984 ( IsStrictlyUpper_v<MT1> && IsLower_v<MT2> ) ||
985 ( IsLower_v<MT1> && IsStrictlyUpper_v<MT2> ) ||
986 ( IsUpper_v<MT1> && IsStrictlyLower_v<MT2> ) ||
987 ( IsZero_v<MT1> || IsZero_v<MT2> ) >* = nullptr >
988inline decltype(auto)
989 smatsmatschur( const SparseMatrix<MT1,false>& lhs, const SparseMatrix<MT2,false>& rhs )
990{
992
993 MAYBE_UNUSED( rhs );
994
995 BLAZE_INTERNAL_ASSERT( (*lhs).rows() == (*rhs).rows() , "Invalid number of rows" );
996 BLAZE_INTERNAL_ASSERT( (*lhs).columns() == (*rhs).columns(), "Invalid number of columns" );
997
998 using ReturnType = const SchurTrait_t< ResultType_t<MT1>, ResultType_t<MT2> >;
999
1002
1003 return ReturnType( (*lhs).rows(), (*lhs).columns() );
1004}
1006//*************************************************************************************************
1007
1008
1009//*************************************************************************************************
1035template< typename MT1 // Type of the left-hand side sparse matrix
1036 , typename MT2 > // Type of the right-hand side sparse matrix
1037inline decltype(auto)
1038 operator%( const SparseMatrix<MT1,false>& lhs, const SparseMatrix<MT2,false>& rhs )
1039{
1041
1042 if( (*lhs).rows() != (*rhs).rows() || (*lhs).columns() != (*rhs).columns() ) {
1043 BLAZE_THROW_INVALID_ARGUMENT( "Matrix sizes do not match" );
1044 }
1045
1046 return smatsmatschur( *lhs, *rhs );
1047}
1048//*************************************************************************************************
1049
1050} // namespace blaze
1051
1052#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.
Constraint on the data type.
Header file for the If class template.
Header file for the IntegralConstant class template.
Header file for the IsColumnMajorMatrix type trait.
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 IsSymmetric type trait.
Header file for the IsTemporary type trait class.
Header file for the IsUniLower type trait.
Header file for the IsUniUpper type trait.
Header file for the IsUpper type trait.
Header file for the MAYBE_UNUSED function template.
Constraints on the storage order of matrix types.
Header file for the Schur product trait.
Constraint on the data type.
Constraint on the data type.
Base class for dense matrices.
Definition: DenseMatrix.h:82
Expression object for sparse matrix-sparse matrix Schur product.
Definition: SMatSMatSchurExpr.h:101
ResultType_t< MT1 > RT1
Result type of the left-hand side sparse matrix expression.
Definition: SMatSMatSchurExpr.h:104
ReturnType at(size_t i, size_t j) const
Checked access to the matrix elements.
Definition: SMatSMatSchurExpr.h:206
ReturnType operator()(size_t i, size_t j) const
2D-access to the matrix elements.
Definition: SMatSMatSchurExpr.h:191
LeftOperand lhs_
Left-hand side sparse matrix of the Schur product expression.
Definition: SMatSMatSchurExpr.h:304
CompositeType_t< MT2 > CT2
Composite type of the right-hand side sparse matrix expression.
Definition: SMatSMatSchurExpr.h:109
static constexpr bool smpAssignable
Compilation switch for the expression template assignment strategy.
Definition: SMatSMatSchurExpr.h:166
If_t< IsExpression_v< MT2 >, const MT2, const MT2 & > RightOperand
Composite type of the right-hand side sparse matrix expression.
Definition: SMatSMatSchurExpr.h:161
RightOperand rhs_
Right-hand side sparse matrix of the Schur product expression.
Definition: SMatSMatSchurExpr.h:305
ElementType_t< ResultType > ElementType
Resulting element type.
Definition: SMatSMatSchurExpr.h:149
LeftOperand leftOperand() const noexcept
Returns the left-hand side sparse matrix operand.
Definition: SMatSMatSchurExpr.h:263
size_t nonZeros(size_t i) const
Returns the number of non-zero elements in the specified row.
Definition: SMatSMatSchurExpr.h:253
static constexpr bool returnExpr
Compilation switch for the selection of the subscript operator return type.
Definition: SMatSMatSchurExpr.h:119
ReturnType_t< MT2 > RN2
ReturnType type of the right-hand side sparse matrix expression.
Definition: SMatSMatSchurExpr.h:107
ReturnType_t< MT1 > RN1
ReturnType type of the left-hand side sparse matrix expression.
Definition: SMatSMatSchurExpr.h:106
CompositeType_t< MT1 > CT1
Composite type of the left-hand side sparse matrix expression.
Definition: SMatSMatSchurExpr.h:108
ResultType_t< MT2 > RT2
Result type of the right-hand side sparse matrix expression.
Definition: SMatSMatSchurExpr.h:105
If_t< IsExpression_v< MT1 >, const MT1, const MT1 & > LeftOperand
Composite type of the left-hand side sparse matrix expression.
Definition: SMatSMatSchurExpr.h:158
RightOperand rightOperand() const noexcept
Returns the right-hand side sparse matrix operand.
Definition: SMatSMatSchurExpr.h:273
size_t columns() const noexcept
Returns the current number of columns of the matrix.
Definition: SMatSMatSchurExpr.h:232
SMatSMatSchurExpr(const MT1 &lhs, const MT2 &rhs) noexcept
Constructor for the SMatSMatSchurExpr class.
Definition: SMatSMatSchurExpr.h:175
const If_t< returnExpr, ExprReturnType, ElementType > ReturnType
Return type for expression template evaluations.
Definition: SMatSMatSchurExpr.h:152
size_t nonZeros() const
Returns the number of non-zero elements in the sparse matrix.
Definition: SMatSMatSchurExpr.h:242
bool isAliased(const T *alias) const noexcept
Returns whether the expression is aliased with the given address alias.
Definition: SMatSMatSchurExpr.h:297
OppositeType_t< ResultType > OppositeType
Result type with opposite storage order for expression template evaluations.
Definition: SMatSMatSchurExpr.h:147
decltype(std::declval< RN1 >() *std::declval< RN2 >()) ExprReturnType
Expression return type for the subscript operator.
Definition: SMatSMatSchurExpr.h:122
TransposeType_t< ResultType > TransposeType
Transpose type for expression template evaluations.
Definition: SMatSMatSchurExpr.h:148
const ResultType CompositeType
Data type for composite expression templates.
Definition: SMatSMatSchurExpr.h:155
SchurTrait_t< RT1, RT2 > ResultType
Result type for expression template evaluations.
Definition: SMatSMatSchurExpr.h:146
bool canAlias(const T *alias) const noexcept
Returns whether the expression can alias with the given address alias.
Definition: SMatSMatSchurExpr.h:285
size_t rows() const noexcept
Returns the current number of rows of the matrix.
Definition: SMatSMatSchurExpr.h:222
Base class for sparse matrices.
Definition: SparseMatrix.h:77
Constraint on the data type.
Constraint on the data type.
Header file for the Computation base class.
Header file for the SchurExpr base class.
Header file for the SparseMatrix base class.
decltype(auto) min(const DenseMatrix< MT1, SO1 > &lhs, const DenseMatrix< MT2, SO2 > &rhs)
Computes the componentwise minimum of the dense matrices lhs and rhs.
Definition: DMatDMatMapExpr.h:1339
decltype(auto) trans(const DenseMatrix< MT, SO > &dm)
Calculation of the transpose of the given dense matrix.
Definition: DMatTransExpr.h:766
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_SYMMETRIC_MATRIX_TYPE(T)
Constraint on the data type.
Definition: Symmetric.h:79
#define BLAZE_CONSTRAINT_MUST_BE_ROW_MAJOR_MATRIX_TYPE(T)
Constraint on the data type.
Definition: RowMajorMatrix.h:61
#define BLAZE_CONSTRAINT_MUST_NOT_BE_ZERO_TYPE(T)
Constraint on the data type.
Definition: Zero.h:81
#define BLAZE_CONSTRAINT_MUST_BE_SPARSE_MATRIX_TYPE(T)
Constraint on the data type.
Definition: SparseMatrix.h:61
#define BLAZE_CONSTRAINT_MUST_BE_IDENTITY_MATRIX_TYPE(T)
Constraint on the data type.
Definition: Identity.h:60
#define BLAZE_CONSTRAINT_MUST_FORM_VALID_SCHUREXPR(T1, T2)
Constraint on the data type.
Definition: SchurExpr.h:103
#define BLAZE_CONSTRAINT_MUST_BE_ZERO_TYPE(T)
Constraint on the data type.
Definition: Zero.h:61
typename SchurTrait< T1, T2 >::Type SchurTrait_t
Auxiliary alias declaration for the SchurTrait class template.
Definition: SchurTrait.h:137
constexpr void reset(Matrix< MT, SO > &matrix)
Resetting the given matrix.
Definition: Matrix.h:806
#define BLAZE_INTERNAL_ASSERT(expr, msg)
Run time assertion macro for internal checks.
Definition: Assert.h:101
auto smpSchurAssign(Matrix< MT1, SO1 > &lhs, const Matrix< MT2, SO2 > &rhs) -> EnableIf_t< IsDenseMatrix_v< MT1 > >
Default implementation of the SMP Schur product assignment of a matrix to dense matrix.
Definition: DenseMatrix.h:194
typename EnableIf< Condition, T >::Type EnableIf_t
Auxiliary type for the EnableIf class template.
Definition: EnableIf.h:138
constexpr void MAYBE_UNUSED(const Args &...)
Suppression of unused parameter warnings.
Definition: MaybeUnused.h:81
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_THROW_INVALID_ARGUMENT(MESSAGE)
Macro for the emission of a std::invalid_argument exception.
Definition: Exception.h:235
typename EnableIf<!Condition, T >::Type DisableIf_t
Auxiliary type for the EnableIf class template.
Definition: EnableIf.h:175
#define BLAZE_FUNCTION_TRACE
Function trace macro.
Definition: FunctionTrace.h:94
Header file for the exception macros of the math module.
Header file for all forward declarations for expression class templates.
Header file for all forward declarations for sparse vectors and matrices.
Header file for the serial shim.
Base class for all compute expression templates.
Definition: Computation.h:68
Base class for all Schur product expression templates.
Definition: SchurExpr.h:68
Header file for the IsZero type trait.
Header file for basic type definitions.
Header file for the generic max algorithm.
Header file for the generic min algorithm.