Blaze 3.9
DMatSMatMultExpr.h
Go to the documentation of this file.
1//=================================================================================================
33//=================================================================================================
34
35#ifndef _BLAZE_MATH_EXPRESSIONS_DMATSMATMULTEXPR_H_
36#define _BLAZE_MATH_EXPRESSIONS_DMATSMATMULTEXPR_H_
37
38
39//*************************************************************************************************
40// Includes
41//*************************************************************************************************
42
43#include <blaze/math/Aliases.h>
94#include <blaze/util/Assert.h>
95#include <blaze/util/EnableIf.h>
99#include <blaze/util/mpl/If.h>
100#include <blaze/util/Types.h>
103
104
105namespace blaze {
106
107//=================================================================================================
108//
109// CLASS DMATSMATMULTEXPR
110//
111//=================================================================================================
112
113//*************************************************************************************************
120template< typename MT1 // Type of the left-hand side dense matrix
121 , typename MT2 // Type of the right-hand side sparse matrix
122 , bool SF // Symmetry flag
123 , bool HF // Hermitian flag
124 , bool LF // Lower flag
125 , bool UF > // Upper flag
127 : public MatMatMultExpr< DenseMatrix< DMatSMatMultExpr<MT1,MT2,SF,HF,LF,UF>, false > >
128 , private Computation
129{
130 private:
131 //**Type definitions****************************************************************************
138 //**********************************************************************************************
139
140 //**********************************************************************************************
142 static constexpr bool evaluateLeft = ( IsComputation_v<MT1> || RequiresEvaluation_v<MT1> );
143 //**********************************************************************************************
144
145 //**********************************************************************************************
147 static constexpr bool evaluateRight = ( IsComputation_v<MT2> || RequiresEvaluation_v<MT2> );
148 //**********************************************************************************************
149
150 //**********************************************************************************************
151 static constexpr bool SYM = ( SF && !( HF || LF || UF ) );
152 static constexpr bool HERM = ( HF && !( LF || UF ) );
153 static constexpr bool LOW = ( LF || ( ( SF || HF ) && UF ) );
154 static constexpr bool UPP = ( UF || ( ( SF || HF ) && LF ) );
155 //**********************************************************************************************
156
157 //**********************************************************************************************
159
164 template< typename T1, typename T2, typename T3 >
165 static constexpr bool CanExploitSymmetry_v = ( IsSymmetric_v<T2> || IsSymmetric_v<T3> );
167 //**********************************************************************************************
168
169 //**********************************************************************************************
171
175 template< typename T1, typename T2, typename T3 >
176 static constexpr bool IsEvaluationRequired_v =
177 ( evaluateLeft || evaluateRight ) && !CanExploitSymmetry_v<T1,T2,T3>;
179 //**********************************************************************************************
180
181 //**********************************************************************************************
183
186 template< typename T1, typename T2, typename T3 >
187 static constexpr bool UseOptimizedKernel_v =
188 useOptimizedKernels && !IsDiagonal_v<T2> && !IsResizable_v< ElementType_t<T1> >;
190 //**********************************************************************************************
191
192 //**********************************************************************************************
194
197 template< typename T1, typename T2, typename T3 >
198 static constexpr bool UseDefaultKernel_v = !UseOptimizedKernel_v<T1,T2,T3>;
200 //**********************************************************************************************
201
202 //**********************************************************************************************
204
207 using ForwardFunctor = If_t< HERM
208 , DeclHerm
209 , If_t< SYM
210 , DeclSym
211 , If_t< LOW
212 , If_t< UPP
213 , DeclDiag
214 , DeclLow >
215 , If_t< UPP
216 , DeclUpp
217 , Noop > > > >;
219 //**********************************************************************************************
220
221 public:
222 //**Type definitions****************************************************************************
225
228
230 using ResultType = typename If_t< HERM
232 , If_t< SYM
234 , If_t< LOW
235 , If_t< UPP
238 , If_t< UPP
240 , MultTrait<RT1,RT2> > > > >::Type;
241
245 using ReturnType = const ElementType;
246 using CompositeType = const ResultType;
247
249 using LeftOperand = If_t< IsExpression_v<MT1>, const MT1, const MT1& >;
250
252 using RightOperand = If_t< IsExpression_v<MT2>, const MT2, const MT2& >;
253
256
259 //**********************************************************************************************
260
261 //**Compilation flags***************************************************************************
263 static constexpr bool simdEnabled = false;
264
266 static constexpr bool smpAssignable =
267 ( !evaluateLeft && MT1::smpAssignable && !evaluateRight && MT2::smpAssignable );
268 //**********************************************************************************************
269
270 //**Constructor*********************************************************************************
276 inline DMatSMatMultExpr( const MT1& lhs, const MT2& rhs ) noexcept
277 : lhs_( lhs ) // Left-hand side dense matrix of the multiplication expression
278 , rhs_( rhs ) // Right-hand side sparse matrix of the multiplication expression
279 {
280 BLAZE_INTERNAL_ASSERT( lhs.columns() == rhs.rows(), "Invalid matrix sizes" );
281 }
282 //**********************************************************************************************
283
284 //**Access operator*****************************************************************************
291 inline ReturnType operator()( size_t i, size_t j ) const {
292 BLAZE_INTERNAL_ASSERT( i < lhs_.rows() , "Invalid row access index" );
293 BLAZE_INTERNAL_ASSERT( j < rhs_.columns(), "Invalid column access index" );
294
295 if( IsDiagonal_v<MT1> ) {
296 return lhs_(i,i) * rhs_(i,j);
297 }
298 else if( IsDiagonal_v<MT2> ) {
299 return lhs_(i,j) * rhs_(j,j);
300 }
301 else if( IsTriangular_v<MT1> || IsTriangular_v<MT2> ) {
302 const size_t begin( ( IsUpper_v<MT1> )
303 ?( ( IsLower_v<MT2> )
304 ?( max( ( IsStrictlyUpper_v<MT1> ? i+1UL : i )
305 , ( IsStrictlyLower_v<MT2> ? j+1UL : j ) ) )
306 :( IsStrictlyUpper_v<MT1> ? i+1UL : i ) )
307 :( ( IsLower_v<MT2> )
308 ?( IsStrictlyLower_v<MT2> ? j+1UL : j )
309 :( 0UL ) ) );
310 const size_t end( ( IsLower_v<MT1> )
311 ?( ( IsUpper_v<MT2> )
312 ?( min( ( IsStrictlyLower_v<MT1> ? i : i+1UL )
313 , ( IsStrictlyUpper_v<MT2> ? j : j+1UL ) ) )
314 :( IsStrictlyLower_v<MT1> ? i : i+1UL ) )
315 :( ( IsUpper_v<MT2> )
316 ?( IsStrictlyUpper_v<MT2> ? j : j+1UL )
317 :( lhs_.columns() ) ) );
318
319 if( begin >= end ) return ElementType();
320
321 const size_t n( end - begin );
322
323 return subvector( row( lhs_, i, unchecked ), begin, n, unchecked ) *
325 }
326 else {
327 return row( lhs_, i, unchecked ) * column( rhs_, j, unchecked );
328 }
329 }
330 //**********************************************************************************************
331
332 //**At function*********************************************************************************
340 inline ReturnType at( size_t i, size_t j ) const {
341 if( i >= lhs_.rows() ) {
342 BLAZE_THROW_OUT_OF_RANGE( "Invalid row access index" );
343 }
344 if( j >= rhs_.columns() ) {
345 BLAZE_THROW_OUT_OF_RANGE( "Invalid column access index" );
346 }
347 return (*this)(i,j);
348 }
349 //**********************************************************************************************
350
351 //**Rows function*******************************************************************************
356 inline size_t rows() const noexcept {
357 return lhs_.rows();
358 }
359 //**********************************************************************************************
360
361 //**Columns function****************************************************************************
366 inline size_t columns() const noexcept {
367 return rhs_.columns();
368 }
369 //**********************************************************************************************
370
371 //**Left operand access*************************************************************************
376 inline LeftOperand leftOperand() const noexcept {
377 return lhs_;
378 }
379 //**********************************************************************************************
380
381 //**Right operand access************************************************************************
386 inline RightOperand rightOperand() const noexcept {
387 return rhs_;
388 }
389 //**********************************************************************************************
390
391 //**********************************************************************************************
397 template< typename T >
398 inline bool canAlias( const T* alias ) const noexcept {
399 return ( lhs_.isAliased( alias ) || rhs_.isAliased( alias ) );
400 }
401 //**********************************************************************************************
402
403 //**********************************************************************************************
409 template< typename T >
410 inline bool isAliased( const T* alias ) const noexcept {
411 return ( lhs_.isAliased( alias ) || rhs_.isAliased( alias ) );
412 }
413 //**********************************************************************************************
414
415 //**********************************************************************************************
420 inline bool isAligned() const noexcept {
421 return lhs_.isAligned();
422 }
423 //**********************************************************************************************
424
425 //**********************************************************************************************
430 inline bool canSMPAssign() const noexcept {
431 return ( rows() * columns() >= SMP_DMATSMATMULT_THRESHOLD ) && !IsDiagonal_v<MT1>;
432 }
433 //**********************************************************************************************
434
435 private:
436 //**Member variables****************************************************************************
439 //**********************************************************************************************
440
441 //**Assignment to dense matrices****************************************************************
454 template< typename MT // Type of the target dense matrix
455 , bool SO > // Storage order of the target dense matrix
456 friend inline auto assign( DenseMatrix<MT,SO>& lhs, const DMatSMatMultExpr& rhs )
458 {
460
461 BLAZE_INTERNAL_ASSERT( (*lhs).rows() == rhs.rows() , "Invalid number of rows" );
462 BLAZE_INTERNAL_ASSERT( (*lhs).columns() == rhs.columns(), "Invalid number of columns" );
463
464 LT A( serial( rhs.lhs_ ) ); // Evaluation of the left-hand side dense matrix operand
465 RT B( serial( rhs.rhs_ ) ); // Evaluation of the right-hand side sparse matrix operand
466
467 BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
468 BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
469 BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
470 BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
471 BLAZE_INTERNAL_ASSERT( A.rows() == (*lhs).rows() , "Invalid number of rows" );
472 BLAZE_INTERNAL_ASSERT( B.columns() == (*lhs).columns() , "Invalid number of columns" );
473
474 DMatSMatMultExpr::selectAssignKernel( *lhs, A, B );
475 }
477 //**********************************************************************************************
478
479 //**Assignment to dense matrices (kernel selection)*********************************************
490 template< typename MT3 // Type of the left-hand side target matrix
491 , typename MT4 // Type of the left-hand side matrix operand
492 , typename MT5 > // Type of the right-hand side matrix operand
493 static inline void selectAssignKernel( MT3& C, const MT4& A, const MT5& B )
494 {
495 if( C.rows() * C.columns() < DMATSMATMULT_THRESHOLD )
496 selectSmallAssignKernel( C, A, B );
497 else
498 selectLargeAssignKernel( C, A, B );
499 }
501 //**********************************************************************************************
502
503 //**Default assignment to dense matrices********************************************************
517 template< typename MT3 // Type of the left-hand side target matrix
518 , typename MT4 // Type of the left-hand side matrix operand
519 , typename MT5 > // Type of the right-hand side matrix operand
520 static inline void selectDefaultAssignKernel( MT3& C, const MT4& A, const MT5& B )
521 {
522 reset( C );
523
524 for( size_t k=0UL; k<B.rows(); ++k )
525 {
526 if( IsDiagonal_v<MT4> )
527 {
528 auto element( B.begin(k) );
529 const auto end( B.end(k) );
530
531 for( ; element!=end; ++element ) {
532 C(k,element->index()) = A(k,k) * element->value();
533 }
534 }
535 else
536 {
537 const size_t iibegin( ( IsLower_v<MT4> )
538 ?( IsStrictlyLower_v<MT4> ? k+1UL : k )
539 :( 0UL ) );
540 const size_t iiend( ( IsUpper_v<MT4> )
541 ?( IsStrictlyUpper_v<MT4> ? k : k+1UL )
542 :( A.rows() ) );
543 BLAZE_INTERNAL_ASSERT( iibegin <= iiend, "Invalid loop indices detected" );
544
545 for( size_t ii=iibegin; ii<iiend; ii+=8UL )
546 {
547 auto element( B.begin(k) );
548 const auto end( B.end(k) );
549 const size_t itmp( ( ii+8UL > iiend )?( iiend ):( ii+8UL ) );
550
551 for( ; element!=end; ++element )
552 {
553 const size_t j1( element->index() );
554 const size_t ibegin( SYM || HERM || LOW ? max(j1,ii) : ii );
555 const size_t iend( UPP ? min(j1+1UL,itmp) : itmp );
556
557 for( size_t i=ibegin; i<iend; ++i ) {
558 if( isDefault( C(i,element->index()) ) )
559 C(i,j1) = A(i,k) * element->value();
560 else
561 C(i,j1) += A(i,k) * element->value();
562 }
563 }
564 }
565 }
566 }
567
568 if( SYM || HERM ) {
569 for( size_t i=0UL; i<A.rows(); ++i ) {
570 for( size_t j=i+1UL; j<B.columns(); ++j ) {
571 C(i,j) = HERM ? conj( C(j,i) ) : C(j,i);
572 }
573 }
574 }
575 }
577 //**********************************************************************************************
578
579 //**Default assignment to dense matrices (small matrices)***************************************
592 template< typename MT3 // Type of the left-hand side target matrix
593 , typename MT4 // Type of the left-hand side matrix operand
594 , typename MT5 > // Type of the right-hand side matrix operand
595 static inline auto selectSmallAssignKernel( MT3& C, const MT4& A, const MT5& B )
596 -> EnableIf_t< UseDefaultKernel_v<MT3,MT4,MT5> >
597 {
598 selectDefaultAssignKernel( C, A, B );
599 }
601 //**********************************************************************************************
602
603 //**Optimized assignment to dense matrices (small matrices)*************************************
618 template< typename MT3 // Type of the left-hand side target matrix
619 , typename MT4 // Type of the left-hand side matrix operand
620 , typename MT5 > // Type of the right-hand side matrix operand
621 static inline auto selectSmallAssignKernel( MT3& C, const MT4& A, const MT5& B )
622 -> EnableIf_t< UseOptimizedKernel_v<MT3,MT4,MT5> >
623 {
624 reset( C );
625
626 for( size_t j=0UL; j<B.rows(); ++j )
627 {
628 const size_t iibegin( ( IsLower_v<MT4> )
629 ?( IsStrictlyLower_v<MT4> ? j+1UL : j )
630 :( 0UL ) );
631 const size_t iiend( ( IsUpper_v<MT4> )
632 ?( IsStrictlyUpper_v<MT4> ? j : j+1UL )
633 :( A.rows() ) );
634 BLAZE_INTERNAL_ASSERT( iibegin <= iiend, "Invalid loop indices detected" );
635
636 for( size_t ii=iibegin; ii<iiend; ii+=8UL )
637 {
638 auto element( B.begin(j) );
639 const auto end( B.end(j) );
640 const size_t itmp( ( ii+8UL > iiend )?( iiend ):( ii+8UL ) );
641
642 for( ; element!=end; ++element )
643 {
644 const size_t j1( element->index() );
645 const size_t ibegin( SYM || HERM || LOW ? max(j1,ii) : ii );
646 const size_t iend( UPP ? min(j1+1UL,itmp) : itmp );
647
648 for( size_t i=ibegin; i<iend; ++i ) {
649 C(i,j1) += A(i,j) * element->value();
650 }
651 }
652 }
653 }
654
655 if( SYM || HERM ) {
656 for( size_t i=0UL; i<A.rows(); ++i ) {
657 for( size_t j=i+1UL; j<B.columns(); ++j ) {
658 C(i,j) = HERM ? conj( C(j,i) ) : C(j,i);
659 }
660 }
661 }
662 }
664 //**********************************************************************************************
665
666 //**Default assignment to dense matrices (large matrices)***************************************
679 template< typename MT3 // Type of the left-hand side target matrix
680 , typename MT4 // Type of the left-hand side matrix operand
681 , typename MT5 > // Type of the right-hand side matrix operand
682 static inline auto selectLargeAssignKernel( MT3& C, const MT4& A, const MT5& B )
683 -> EnableIf_t< UseDefaultKernel_v<MT3,MT4,MT5> >
684 {
685 selectDefaultAssignKernel( C, A, B );
686 }
688 //**********************************************************************************************
689
690 //**Optimized assignment to dense matrices (large matrices)*************************************
705 template< typename MT3 // Type of the left-hand side target matrix
706 , typename MT4 // Type of the left-hand side matrix operand
707 , typename MT5 > // Type of the right-hand side matrix operand
708 static inline auto selectLargeAssignKernel( MT3& C, const MT4& A, const MT5& B )
709 -> EnableIf_t< UseOptimizedKernel_v<MT3,MT4,MT5> >
710 {
712
713 const ForwardFunctor fwd;
714
715 const OppositeType_t<MT5> tmp( serial( B ) );
716 assign( C, fwd( A * tmp ) );
717 }
719 //**********************************************************************************************
720
721 //**Assignment to sparse matrices***************************************************************
734 template< typename MT // Type of the target sparse matrix
735 , bool SO > // Storage order of the target sparse matrix
736 friend inline auto assign( SparseMatrix<MT,SO>& lhs, const DMatSMatMultExpr& rhs )
737 -> DisableIf_t< CanExploitSymmetry_v<MT,MT1,MT2> >
738 {
740
741 using TmpType = If_t< SO, OppositeType, ResultType >;
742
749
750 BLAZE_INTERNAL_ASSERT( (*lhs).rows() == rhs.rows() , "Invalid number of rows" );
751 BLAZE_INTERNAL_ASSERT( (*lhs).columns() == rhs.columns(), "Invalid number of columns" );
752
753 const ForwardFunctor fwd;
754
755 const TmpType tmp( serial( rhs ) );
756 assign( *lhs, fwd( tmp ) );
757 }
759 //**********************************************************************************************
760
761 //**Restructuring assignment********************************************************************
776 template< typename MT // Type of the target matrix
777 , bool SO > // Storage order of the target matrix
778 friend inline auto assign( Matrix<MT,SO>& lhs, const DMatSMatMultExpr& rhs )
779 -> EnableIf_t< CanExploitSymmetry_v<MT,MT1,MT2> >
780 {
782
784
785 BLAZE_INTERNAL_ASSERT( (*lhs).rows() == rhs.rows() , "Invalid number of rows" );
786 BLAZE_INTERNAL_ASSERT( (*lhs).columns() == rhs.columns(), "Invalid number of columns" );
787
788 const ForwardFunctor fwd;
789
790 decltype(auto) A( transIf< IsSymmetric_v<MT1> >( rhs.lhs_ ) );
791 decltype(auto) B( transIf< IsSymmetric_v<MT2> >( rhs.rhs_ ) );
792
793 assign( *lhs, fwd( A * B ) );
794 }
796 //**********************************************************************************************
797
798 //**Addition assignment to dense matrices*******************************************************
811 template< typename MT // Type of the target dense matrix
812 , bool SO > // Storage order of the target dense matrix
813 friend inline auto addAssign( DenseMatrix<MT,SO>& lhs, const DMatSMatMultExpr& rhs )
814 -> DisableIf_t< CanExploitSymmetry_v<MT,MT1,MT2> >
815 {
817
818 BLAZE_INTERNAL_ASSERT( (*lhs).rows() == rhs.rows() , "Invalid number of rows" );
819 BLAZE_INTERNAL_ASSERT( (*lhs).columns() == rhs.columns(), "Invalid number of columns" );
820
821 LT A( serial( rhs.lhs_ ) ); // Evaluation of the left-hand side dense matrix operand
822 RT B( serial( rhs.rhs_ ) ); // Evaluation of the right-hand side sparse matrix operand
823
824 BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
825 BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
826 BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
827 BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
828 BLAZE_INTERNAL_ASSERT( A.rows() == (*lhs).rows() , "Invalid number of rows" );
829 BLAZE_INTERNAL_ASSERT( B.columns() == (*lhs).columns() , "Invalid number of columns" );
830
831 DMatSMatMultExpr::selectAddAssignKernel( *lhs, A, B );
832 }
834 //**********************************************************************************************
835
836 //**Addition assignment to dense matrices (kernel selection)************************************
847 template< typename MT3 // Type of the left-hand side target matrix
848 , typename MT4 // Type of the left-hand side matrix operand
849 , typename MT5 > // Type of the right-hand side matrix operand
850 static inline void selectAddAssignKernel( MT3& C, const MT4& A, const MT5& B )
851 {
852 if( C.rows() * C.columns() < DMATSMATMULT_THRESHOLD )
853 selectSmallAddAssignKernel( C, A, B );
854 else
855 selectLargeAddAssignKernel( C, A, B );
856 }
858 //**********************************************************************************************
859
860 //**Optimized addition assignment to dense matrices (small matrices)****************************
874 template< typename MT3 // Type of the left-hand side target matrix
875 , typename MT4 // Type of the left-hand side matrix operand
876 , typename MT5 > // Type of the right-hand side matrix operand
877 static inline void selectSmallAddAssignKernel( MT3& C, const MT4& A, const MT5& B )
878 {
879 for( size_t j=0UL; j<B.rows(); ++j )
880 {
881 if( IsDiagonal_v<MT4> )
882 {
883 auto element( B.begin(j) );
884 const auto end( B.end(j) );
885
886 for( ; element!=end; ++element ) {
887 C(j,element->index()) += A(j,j) * element->value();
888 }
889 }
890 else
891 {
892 const size_t iibegin( ( IsLower_v<MT4> )
893 ?( IsStrictlyLower_v<MT4> ? j+1UL : j )
894 :( 0UL ) );
895 const size_t iiend( ( IsUpper_v<MT4> )
896 ?( IsStrictlyUpper_v<MT4> ? j : j+1UL )
897 :( A.rows() ) );
898 BLAZE_INTERNAL_ASSERT( iibegin <= iiend, "Invalid loop indices detected" );
899
900 for( size_t ii=iibegin; ii<iiend; ii+=8UL )
901 {
902 auto element( B.begin(j) );
903 const auto end( B.end(j) );
904 const size_t itmp( ( ii+8UL > iiend )?( iiend ):( ii+8UL ) );
905
906 for( ; element!=end; ++element )
907 {
908 const size_t j1( element->index() );
909 const size_t ibegin( LOW ? max(j1,ii) : ii );
910 const size_t iend( UPP ? min(j1+1UL,itmp) : itmp );
911
912 for( size_t i=ibegin; i<iend; ++i ) {
913 C(i,j1) += A(i,j) * element->value();
914 }
915 }
916 }
917 }
918 }
919 }
921 //**********************************************************************************************
922
923 //**Optimized addition assignment to dense matrices (large matrices)****************************
937 template< typename MT3 // Type of the left-hand side target matrix
938 , typename MT4 // Type of the left-hand side matrix operand
939 , typename MT5 > // Type of the right-hand side matrix operand
940 static inline void selectLargeAddAssignKernel( MT3& C, const MT4& A, const MT5& B )
941 {
943
944 const ForwardFunctor fwd;
945
946 const OppositeType_t<MT5> tmp( serial( B ) );
947 addAssign( C, fwd( A * tmp ) );
948 }
950 //**********************************************************************************************
951
952 //**Restructuring addition assignment***********************************************************
967 template< typename MT // Type of the target matrix
968 , bool SO > // Storage order of the target matrix
969 friend inline auto addAssign( Matrix<MT,SO>& lhs, const DMatSMatMultExpr& rhs )
970 -> EnableIf_t< CanExploitSymmetry_v<MT,MT1,MT2> >
971 {
973
975
976 BLAZE_INTERNAL_ASSERT( (*lhs).rows() == rhs.rows() , "Invalid number of rows" );
977 BLAZE_INTERNAL_ASSERT( (*lhs).columns() == rhs.columns(), "Invalid number of columns" );
978
979 const ForwardFunctor fwd;
980
981 decltype(auto) A( transIf< IsSymmetric_v<MT1> >( rhs.lhs_ ) );
982 decltype(auto) B( transIf< IsSymmetric_v<MT2> >( rhs.rhs_ ) );
983
984 addAssign( *lhs, fwd( A * B ) );
985 }
987 //**********************************************************************************************
988
989 //**Addition assignment to sparse matrices******************************************************
990 // No special implementation for the addition assignment to sparse matrices.
991 //**********************************************************************************************
992
993 //**Subtraction assignment to dense matrices****************************************************
1006 template< typename MT // Type of the target dense matrix
1007 , bool SO > // Storage order of the target dense matrix
1008 friend inline auto subAssign( DenseMatrix<MT,SO>& lhs, const DMatSMatMultExpr& rhs )
1009 -> DisableIf_t< CanExploitSymmetry_v<MT,MT1,MT2> >
1010 {
1012
1013 BLAZE_INTERNAL_ASSERT( (*lhs).rows() == rhs.rows() , "Invalid number of rows" );
1014 BLAZE_INTERNAL_ASSERT( (*lhs).columns() == rhs.columns(), "Invalid number of columns" );
1015
1016 LT A( serial( rhs.lhs_ ) ); // Evaluation of the left-hand side dense matrix operand
1017 RT B( serial( rhs.rhs_ ) ); // Evaluation of the right-hand side sparse matrix operand
1018
1019 BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
1020 BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
1021 BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
1022 BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
1023 BLAZE_INTERNAL_ASSERT( A.rows() == (*lhs).rows() , "Invalid number of rows" );
1024 BLAZE_INTERNAL_ASSERT( B.columns() == (*lhs).columns() , "Invalid number of columns" );
1025
1026 DMatSMatMultExpr::selectSubAssignKernel( *lhs, A, B );
1027 }
1029 //**********************************************************************************************
1030
1031 //**Subtraction assignment to dense matrices (kernel selection)*********************************
1042 template< typename MT3 // Type of the left-hand side target matrix
1043 , typename MT4 // Type of the left-hand side matrix operand
1044 , typename MT5 > // Type of the right-hand side matrix operand
1045 static inline void selectSubAssignKernel( MT3& C, const MT4& A, const MT5& B )
1046 {
1047 if( C.rows() * C.columns() < DMATSMATMULT_THRESHOLD )
1048 selectSmallSubAssignKernel( C, A, B );
1049 else
1050 selectLargeSubAssignKernel( C, A, B );
1051 }
1053 //**********************************************************************************************
1054
1055 //**Optimized subtraction assignment to dense matrices (small matrices)*************************
1069 template< typename MT3 // Type of the left-hand side target matrix
1070 , typename MT4 // Type of the left-hand side matrix operand
1071 , typename MT5 > // Type of the right-hand side matrix operand
1072 static inline void selectSmallSubAssignKernel( MT3& C, const MT4& A, const MT5& B )
1073 {
1074 for( size_t j=0UL; j<B.rows(); ++j )
1075 {
1076 if( IsDiagonal_v<MT4> )
1077 {
1078 auto element( B.begin(j) );
1079 const auto end( B.end(j) );
1080
1081 for( ; element!=end; ++element ) {
1082 C(j,element->index()) -= A(j,j) * element->value();
1083 }
1084 }
1085 else
1086 {
1087 const size_t iibegin( ( IsLower_v<MT4> )
1088 ?( IsStrictlyLower_v<MT4> ? j+1UL : j )
1089 :( 0UL ) );
1090 const size_t iiend( ( IsUpper_v<MT4> )
1091 ?( IsStrictlyUpper_v<MT4> ? j : j+1UL )
1092 :( A.rows() ) );
1093 BLAZE_INTERNAL_ASSERT( iibegin <= iiend, "Invalid loop indices detected" );
1094
1095 for( size_t ii=iibegin; ii<iiend; ii+=8UL )
1096 {
1097 auto element( B.begin(j) );
1098 const auto end( B.end(j) );
1099 const size_t itmp( ( ii+8UL > iiend )?( iiend ):( ii+8UL ) );
1100
1101 for( ; element!=end; ++element )
1102 {
1103 const size_t j1( element->index() );
1104 const size_t ibegin( LOW ? max(j1,ii) : ii );
1105 const size_t iend( UPP ? min(j1+1UL,itmp) : itmp );
1106
1107 for( size_t i=ibegin; i<iend; ++i ) {
1108 C(i,j1) -= A(i,j) * element->value();
1109 }
1110 }
1111 }
1112 }
1113 }
1114 }
1116 //**********************************************************************************************
1117
1118 //**Optimized subtraction assignment to dense matrices (large matrices)*************************
1132 template< typename MT3 // Type of the left-hand side target matrix
1133 , typename MT4 // Type of the left-hand side matrix operand
1134 , typename MT5 > // Type of the right-hand side matrix operand
1135 static inline void selectLargeSubAssignKernel( MT3& C, const MT4& A, const MT5& B )
1136 {
1138
1139 const ForwardFunctor fwd;
1140
1141 const OppositeType_t<MT5> tmp( serial( B ) );
1142 subAssign( C, fwd( A * tmp ) );
1143 }
1145 //**********************************************************************************************
1146
1147 //**Restructuring subtraction assignment********************************************************
1162 template< typename MT // Type of the target matrix
1163 , bool SO > // Storage order of the target matrix
1164 friend inline auto subAssign( Matrix<MT,SO>& lhs, const DMatSMatMultExpr& rhs )
1165 -> EnableIf_t< CanExploitSymmetry_v<MT,MT1,MT2> >
1166 {
1168
1170
1171 BLAZE_INTERNAL_ASSERT( (*lhs).rows() == rhs.rows() , "Invalid number of rows" );
1172 BLAZE_INTERNAL_ASSERT( (*lhs).columns() == rhs.columns(), "Invalid number of columns" );
1173
1174 const ForwardFunctor fwd;
1175
1176 decltype(auto) A( transIf< IsSymmetric_v<MT1> >( rhs.lhs_ ) );
1177 decltype(auto) B( transIf< IsSymmetric_v<MT2> >( rhs.rhs_ ) );
1178
1179 subAssign( *lhs, fwd( A * B ) );
1180 }
1182 //**********************************************************************************************
1183
1184 //**Subtraction assignment to sparse matrices***************************************************
1185 // No special implementation for the subtraction assignment to sparse matrices.
1186 //**********************************************************************************************
1187
1188 //**Schur product assignment to dense matrices**************************************************
1201 template< typename MT // Type of the target dense matrix
1202 , bool SO > // Storage order of the target dense matrix
1203 friend inline void schurAssign( DenseMatrix<MT,SO>& lhs, const DMatSMatMultExpr& rhs )
1204 {
1206
1210
1211 BLAZE_INTERNAL_ASSERT( (*lhs).rows() == rhs.rows() , "Invalid number of rows" );
1212 BLAZE_INTERNAL_ASSERT( (*lhs).columns() == rhs.columns(), "Invalid number of columns" );
1213
1214 const ResultType tmp( serial( rhs ) );
1215 schurAssign( *lhs, tmp );
1216 }
1218 //**********************************************************************************************
1219
1220 //**Schur product assignment to sparse matrices*************************************************
1221 // No special implementation for the Schur product assignment to sparse matrices.
1222 //**********************************************************************************************
1223
1224 //**Multiplication assignment to dense matrices*************************************************
1225 // No special implementation for the multiplication assignment to dense matrices.
1226 //**********************************************************************************************
1227
1228 //**Multiplication assignment to sparse matrices************************************************
1229 // No special implementation for the multiplication assignment to sparse matrices.
1230 //**********************************************************************************************
1231
1232 //**SMP assignment to dense matrices************************************************************
1247 template< typename MT // Type of the target dense matrix
1248 , bool SO > // Storage order of the target dense matrix
1249 friend inline auto smpAssign( DenseMatrix<MT,SO>& lhs, const DMatSMatMultExpr& rhs )
1250 -> EnableIf_t< IsEvaluationRequired_v<MT,MT1,MT2> >
1251 {
1253
1254 BLAZE_INTERNAL_ASSERT( (*lhs).rows() == rhs.rows() , "Invalid number of rows" );
1255 BLAZE_INTERNAL_ASSERT( (*lhs).columns() == rhs.columns(), "Invalid number of columns" );
1256
1257 LT A( rhs.lhs_ ); // Evaluation of the left-hand side dense matrix operand
1258 RT B( rhs.rhs_ ); // Evaluation of the right-hand side sparse matrix operand
1259
1260 BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
1261 BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
1262 BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
1263 BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
1264 BLAZE_INTERNAL_ASSERT( A.rows() == (*lhs).rows() , "Invalid number of rows" );
1265 BLAZE_INTERNAL_ASSERT( B.columns() == (*lhs).columns() , "Invalid number of columns" );
1266
1267 smpAssign( *lhs, A * B );
1268 }
1270 //**********************************************************************************************
1271
1272 //**SMP assignment to sparse matrices***********************************************************
1287 template< typename MT // Type of the target sparse matrix
1288 , bool SO > // Storage order of the target sparse matrix
1289 friend inline auto smpAssign( SparseMatrix<MT,SO>& lhs, const DMatSMatMultExpr& rhs )
1290 -> EnableIf_t< IsEvaluationRequired_v<MT,MT1,MT2> >
1291 {
1293
1294 using TmpType = If_t< SO, OppositeType, ResultType >;
1295
1302
1303 BLAZE_INTERNAL_ASSERT( (*lhs).rows() == rhs.rows() , "Invalid number of rows" );
1304 BLAZE_INTERNAL_ASSERT( (*lhs).columns() == rhs.columns(), "Invalid number of columns" );
1305
1306 const ForwardFunctor fwd;
1307
1308 const TmpType tmp( rhs );
1309 smpAssign( *lhs, fwd( tmp ) );
1310 }
1312 //**********************************************************************************************
1313
1314 //**Restructuring SMP assignment****************************************************************
1329 template< typename MT // Type of the target matrix
1330 , bool SO > // Storage order of the target matrix
1331 friend inline auto smpAssign( Matrix<MT,SO>& lhs, const DMatSMatMultExpr& rhs )
1332 -> EnableIf_t< CanExploitSymmetry_v<MT,MT1,MT2> >
1333 {
1335
1337
1338 BLAZE_INTERNAL_ASSERT( (*lhs).rows() == rhs.rows() , "Invalid number of rows" );
1339 BLAZE_INTERNAL_ASSERT( (*lhs).columns() == rhs.columns(), "Invalid number of columns" );
1340
1341 const ForwardFunctor fwd;
1342
1343 decltype(auto) A( transIf< IsSymmetric_v<MT1> >( rhs.lhs_ ) );
1344 decltype(auto) B( transIf< IsSymmetric_v<MT2> >( rhs.rhs_ ) );
1345
1346 smpAssign( *lhs, fwd( A * B ) );
1347 }
1349 //**********************************************************************************************
1350
1351 //**SMP addition assignment to dense matrices***************************************************
1366 template< typename MT // Type of the target dense matrix
1367 , bool SO > // Storage order of the target sparse matrix
1368 friend inline auto smpAddAssign( DenseMatrix<MT,SO>& lhs, const DMatSMatMultExpr& rhs )
1369 -> EnableIf_t< IsEvaluationRequired_v<MT,MT1,MT2> >
1370 {
1372
1373 BLAZE_INTERNAL_ASSERT( (*lhs).rows() == rhs.rows() , "Invalid number of rows" );
1374 BLAZE_INTERNAL_ASSERT( (*lhs).columns() == rhs.columns(), "Invalid number of columns" );
1375
1376 LT A( rhs.lhs_ ); // Evaluation of the left-hand side dense matrix operand
1377 RT B( rhs.rhs_ ); // Evaluation of the right-hand side sparse matrix operand
1378
1379 BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
1380 BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
1381 BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
1382 BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
1383 BLAZE_INTERNAL_ASSERT( A.rows() == (*lhs).rows() , "Invalid number of rows" );
1384 BLAZE_INTERNAL_ASSERT( B.columns() == (*lhs).columns() , "Invalid number of columns" );
1385
1386 smpAddAssign( *lhs, A * B );
1387 }
1389 //**********************************************************************************************
1390
1391 //**Restructuring SMP addition assignment*******************************************************
1406 template< typename MT // Type of the target matrix
1407 , bool SO > // Storage order of the target matrix
1408 friend inline auto smpAddAssign( Matrix<MT,SO>& lhs, const DMatSMatMultExpr& rhs )
1409 -> EnableIf_t< CanExploitSymmetry_v<MT,MT1,MT2> >
1410 {
1412
1414
1415 BLAZE_INTERNAL_ASSERT( (*lhs).rows() == rhs.rows() , "Invalid number of rows" );
1416 BLAZE_INTERNAL_ASSERT( (*lhs).columns() == rhs.columns(), "Invalid number of columns" );
1417
1418 const ForwardFunctor fwd;
1419
1420 decltype(auto) A( transIf< IsSymmetric_v<MT1> >( rhs.lhs_ ) );
1421 decltype(auto) B( transIf< IsSymmetric_v<MT2> >( rhs.rhs_ ) );
1422
1423 smpAddAssign( *lhs, fwd( A * B ) );
1424 }
1426 //**********************************************************************************************
1427
1428 //**SMP addition assignment to sparse matrices**************************************************
1429 // No special implementation for the SMP addition assignment to sparse matrices.
1430 //**********************************************************************************************
1431
1432 //**SMP subtraction assignment to dense matrices************************************************
1448 template< typename MT // Type of the target dense matrix
1449 , bool SO > // Storage order of the target sparse matrix
1450 friend inline auto smpSubAssign( DenseMatrix<MT,SO>& lhs, const DMatSMatMultExpr& rhs )
1451 -> EnableIf_t< IsEvaluationRequired_v<MT,MT1,MT2> >
1452 {
1454
1455 BLAZE_INTERNAL_ASSERT( (*lhs).rows() == rhs.rows() , "Invalid number of rows" );
1456 BLAZE_INTERNAL_ASSERT( (*lhs).columns() == rhs.columns(), "Invalid number of columns" );
1457
1458 LT A( rhs.lhs_ ); // Evaluation of the left-hand side dense matrix operand
1459 RT B( rhs.rhs_ ); // Evaluation of the right-hand side sparse matrix operand
1460
1461 BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
1462 BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
1463 BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
1464 BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
1465 BLAZE_INTERNAL_ASSERT( A.rows() == (*lhs).rows() , "Invalid number of rows" );
1466 BLAZE_INTERNAL_ASSERT( B.columns() == (*lhs).columns() , "Invalid number of columns" );
1467
1468 smpSubAssign( *lhs, A * B );
1469 }
1471 //**********************************************************************************************
1472
1473 //**Restructuring SMP subtraction assignment****************************************************
1488 template< typename MT // Type of the target matrix
1489 , bool SO > // Storage order of the target matrix
1490 friend inline auto smpSubAssign( Matrix<MT,SO>& lhs, const DMatSMatMultExpr& rhs )
1491 -> EnableIf_t< CanExploitSymmetry_v<MT,MT1,MT2> >
1492 {
1494
1496
1497 BLAZE_INTERNAL_ASSERT( (*lhs).rows() == rhs.rows() , "Invalid number of rows" );
1498 BLAZE_INTERNAL_ASSERT( (*lhs).columns() == rhs.columns(), "Invalid number of columns" );
1499
1500 const ForwardFunctor fwd;
1501
1502 decltype(auto) A( transIf< IsSymmetric_v<MT1> >( rhs.lhs_ ) );
1503 decltype(auto) B( transIf< IsSymmetric_v<MT2> >( rhs.rhs_ ) );
1504
1505 smpSubAssign( *lhs, fwd( A * B ) );
1506 }
1508 //**********************************************************************************************
1509
1510 //**SMP subtraction assignment to sparse matrices***********************************************
1511 // No special implementation for the SMP subtraction assignment to sparse matrices.
1512 //**********************************************************************************************
1513
1514 //**SMP Schur product assignment to dense matrices**********************************************
1527 template< typename MT // Type of the target dense matrix
1528 , bool SO > // Storage order of the target sparse matrix
1529 friend inline void smpSchurAssign( DenseMatrix<MT,SO>& lhs, const DMatSMatMultExpr& rhs )
1530 {
1532
1536
1537 BLAZE_INTERNAL_ASSERT( (*lhs).rows() == rhs.rows() , "Invalid number of rows" );
1538 BLAZE_INTERNAL_ASSERT( (*lhs).columns() == rhs.columns(), "Invalid number of columns" );
1539
1540 const ResultType tmp( rhs );
1541 smpSchurAssign( *lhs, tmp );
1542 }
1544 //**********************************************************************************************
1545
1546 //**SMP Schur product assignment to sparse matrices*********************************************
1547 // No special implementation for the SMP Schur product assignment to sparse matrices.
1548 //**********************************************************************************************
1549
1550 //**SMP multiplication assignment to dense matrices*********************************************
1551 // No special implementation for the SMP multiplication assignment to dense matrices.
1552 //**********************************************************************************************
1553
1554 //**SMP multiplication assignment to sparse matrices********************************************
1555 // No special implementation for the SMP multiplication assignment to sparse matrices.
1556 //**********************************************************************************************
1557
1558 //**Compile time checks*************************************************************************
1567 //**********************************************************************************************
1568};
1569//*************************************************************************************************
1570
1571
1572
1573
1574//=================================================================================================
1575//
1576// GLOBAL BINARY ARITHMETIC OPERATORS
1577//
1578//=================================================================================================
1579
1580//*************************************************************************************************
1593template< typename MT1 // Type of the left-hand side dense matrix
1594 , typename MT2 // Type of the right-hand side sparse matrix
1595 , DisableIf_t< ( IsIdentity_v<MT2> &&
1596 IsSame_v< ElementType_t<MT1>, ElementType_t<MT2> > ) ||
1597 IsZero_v<MT2> >* = nullptr >
1598inline const DMatSMatMultExpr<MT1,MT2,false,false,false,false>
1599 dmatsmatmult( const DenseMatrix<MT1,false>& lhs, const SparseMatrix<MT2,false>& rhs )
1600{
1602
1603 BLAZE_INTERNAL_ASSERT( (*lhs).columns() == (*rhs).rows(), "Invalid matrix sizes" );
1604
1605 return DMatSMatMultExpr<MT1,MT2,false,false,false,false>( *lhs, *rhs );
1606}
1608//*************************************************************************************************
1609
1610
1611//*************************************************************************************************
1625template< typename MT1 // Type of the left-hand side dense matrix
1626 , typename MT2 // Type of the right-hand side sparse matrix
1627 , EnableIf_t< IsIdentity_v<MT2> &&
1628 IsSame_v< ElementType_t<MT1>, ElementType_t<MT2> > >* = nullptr >
1629inline const MT1&
1630 dmatsmatmult( const DenseMatrix<MT1,false>& lhs, const SparseMatrix<MT2,false>& rhs )
1631{
1633
1634 MAYBE_UNUSED( rhs );
1635
1636 BLAZE_INTERNAL_ASSERT( (*lhs).columns() == (*rhs).rows(), "Invalid matrix sizes" );
1637
1638 return (*lhs);
1639}
1641//*************************************************************************************************
1642
1643
1644//*************************************************************************************************
1657template< typename MT1 // Type of the left-hand side dense matrix
1658 , typename MT2 // Type of the right-hand side sparse matrix
1659 , EnableIf_t< IsZero_v<MT2> >* = nullptr >
1660inline decltype(auto)
1661 dmatsmatmult( const DenseMatrix<MT1,false>& lhs, const SparseMatrix<MT2,false>& rhs )
1662{
1664
1665 BLAZE_INTERNAL_ASSERT( (*lhs).columns() == (*rhs).rows(), "Invalid matrix sizes" );
1666
1667 using ReturnType = const MultTrait_t< ResultType_t<MT1>, ResultType_t<MT2> >;
1668
1671
1672 return ReturnType( (*lhs).rows(), (*rhs).columns() );
1673}
1675//*************************************************************************************************
1676
1677
1678//*************************************************************************************************
1707template< typename MT1 // Type of the left-hand side dense matrix
1708 , typename MT2 > // Type of the right-hand side sparse matrix
1709inline decltype(auto)
1710 operator*( const DenseMatrix<MT1,false>& lhs, const SparseMatrix<MT2,false>& rhs )
1711{
1713
1714 if( (*lhs).columns() != (*rhs).rows() ) {
1715 BLAZE_THROW_INVALID_ARGUMENT( "Matrix sizes do not match" );
1716 }
1717
1718 return dmatsmatmult( *lhs, *rhs );
1719}
1720//*************************************************************************************************
1721
1722
1723
1724
1725//=================================================================================================
1726//
1727// GLOBAL FUNCTIONS
1728//
1729//=================================================================================================
1730
1731//*************************************************************************************************
1755template< typename MT1 // Type of the left-hand side dense matrix
1756 , typename MT2 // Type of the right-hand side sparse matrix
1757 , bool SF // Symmetry flag
1758 , bool HF // Hermitian flag
1759 , bool LF // Lower flag
1760 , bool UF > // Upper flag
1761inline decltype(auto) declsym( const DMatSMatMultExpr<MT1,MT2,SF,HF,LF,UF>& dm )
1762{
1764
1765 if( !isSquare( dm ) ) {
1766 BLAZE_THROW_INVALID_ARGUMENT( "Invalid symmetric matrix specification" );
1767 }
1768
1769 using ReturnType = const DMatSMatMultExpr<MT1,MT2,true,HF,LF,UF>;
1770 return ReturnType( dm.leftOperand(), dm.rightOperand() );
1771}
1773//*************************************************************************************************
1774
1775
1776//*************************************************************************************************
1800template< typename MT1 // Type of the left-hand side dense matrix
1801 , typename MT2 // Type of the right-hand side sparse matrix
1802 , bool SF // Symmetry flag
1803 , bool HF // Hermitian flag
1804 , bool LF // Lower flag
1805 , bool UF > // Upper flag
1806inline decltype(auto) declherm( const DMatSMatMultExpr<MT1,MT2,SF,HF,LF,UF>& dm )
1807{
1809
1810 if( !isSquare( dm ) ) {
1811 BLAZE_THROW_INVALID_ARGUMENT( "Invalid Hermitian matrix specification" );
1812 }
1813
1814 using ReturnType = const DMatSMatMultExpr<MT1,MT2,SF,true,LF,UF>;
1815 return ReturnType( dm.leftOperand(), dm.rightOperand() );
1816}
1818//*************************************************************************************************
1819
1820
1821//*************************************************************************************************
1845template< typename MT1 // Type of the left-hand side dense matrix
1846 , typename MT2 // Type of the right-hand side sparse matrix
1847 , bool SF // Symmetry flag
1848 , bool HF // Hermitian flag
1849 , bool LF // Lower flag
1850 , bool UF > // Upper flag
1851inline decltype(auto) decllow( const DMatSMatMultExpr<MT1,MT2,SF,HF,LF,UF>& dm )
1852{
1854
1855 if( !isSquare( dm ) ) {
1856 BLAZE_THROW_INVALID_ARGUMENT( "Invalid lower matrix specification" );
1857 }
1858
1859 using ReturnType = const DMatSMatMultExpr<MT1,MT2,SF,HF,true,UF>;
1860 return ReturnType( dm.leftOperand(), dm.rightOperand() );
1861}
1863//*************************************************************************************************
1864
1865
1866//*************************************************************************************************
1890template< typename MT1 // Type of the left-hand side dense matrix
1891 , typename MT2 // Type of the right-hand side sparse matrix
1892 , bool SF // Symmetry flag
1893 , bool HF // Hermitian flag
1894 , bool UF > // Upper flag
1895inline decltype(auto) declunilow( const DMatSMatMultExpr<MT1,MT2,SF,HF,false,UF>& dm )
1896{
1898
1899 if( !isSquare( dm ) ) {
1900 BLAZE_THROW_INVALID_ARGUMENT( "Invalid unilower matrix specification" );
1901 }
1902
1903 return declunilow( decllow( *dm ) );
1904}
1906//*************************************************************************************************
1907
1908
1909//*************************************************************************************************
1933template< typename MT1 // Type of the left-hand side dense matrix
1934 , typename MT2 // Type of the right-hand side sparse matrix
1935 , bool SF // Symmetry flag
1936 , bool HF // Hermitian flag
1937 , bool UF > // Upper flag
1938inline decltype(auto) declstrlow( const DMatSMatMultExpr<MT1,MT2,SF,HF,false,UF>& dm )
1939{
1941
1942 if( !isSquare( dm ) ) {
1943 BLAZE_THROW_INVALID_ARGUMENT( "Invalid strictly lower matrix specification" );
1944 }
1945
1946 return declstrlow( decllow( *dm ) );
1947}
1949//*************************************************************************************************
1950
1951
1952//*************************************************************************************************
1976template< typename MT1 // Type of the left-hand side dense matrix
1977 , typename MT2 // Type of the right-hand side sparse matrix
1978 , bool SF // Symmetry flag
1979 , bool HF // Hermitian flag
1980 , bool LF // Lower flag
1981 , bool UF > // Upper flag
1982inline decltype(auto) declupp( const DMatSMatMultExpr<MT1,MT2,SF,HF,LF,UF>& dm )
1983{
1985
1986 if( !isSquare( dm ) ) {
1987 BLAZE_THROW_INVALID_ARGUMENT( "Invalid upper matrix specification" );
1988 }
1989
1990 using ReturnType = const DMatSMatMultExpr<MT1,MT2,SF,HF,LF,true>;
1991 return ReturnType( dm.leftOperand(), dm.rightOperand() );
1992}
1994//*************************************************************************************************
1995
1996
1997//*************************************************************************************************
2021template< typename MT1 // Type of the left-hand side dense matrix
2022 , typename MT2 // Type of the right-hand side sparse matrix
2023 , bool SF // Symmetry flag
2024 , bool HF // Hermitian flag
2025 , bool LF > // Lower flag
2026inline decltype(auto) decluniupp( const DMatSMatMultExpr<MT1,MT2,SF,HF,LF,false>& dm )
2027{
2029
2030 if( !isSquare( dm ) ) {
2031 BLAZE_THROW_INVALID_ARGUMENT( "Invalid uniupper matrix specification" );
2032 }
2033
2034 return decluniupp( declupp( *dm ) );
2035}
2037//*************************************************************************************************
2038
2039
2040//*************************************************************************************************
2064template< typename MT1 // Type of the left-hand side dense matrix
2065 , typename MT2 // Type of the right-hand side sparse matrix
2066 , bool SF // Symmetry flag
2067 , bool HF // Hermitian flag
2068 , bool LF > // Lower flag
2069inline decltype(auto) declstrupp( const DMatSMatMultExpr<MT1,MT2,SF,HF,LF,false>& dm )
2070{
2072
2073 if( !isSquare( dm ) ) {
2074 BLAZE_THROW_INVALID_ARGUMENT( "Invalid strictly upper matrix specification" );
2075 }
2076
2077 return declstrupp( declupp( *dm ) );
2078}
2080//*************************************************************************************************
2081
2082
2083//*************************************************************************************************
2107template< typename MT1 // Type of the left-hand side dense matrix
2108 , typename MT2 // Type of the right-hand side sparse matrix
2109 , bool SF // Symmetry flag
2110 , bool HF // Hermitian flag
2111 , bool LF // Lower flag
2112 , bool UF > // Upper flag
2113inline decltype(auto) decldiag( const DMatSMatMultExpr<MT1,MT2,SF,HF,LF,UF>& dm )
2114{
2116
2117 if( !isSquare( dm ) ) {
2118 BLAZE_THROW_INVALID_ARGUMENT( "Invalid diagonal matrix specification" );
2119 }
2120
2121 using ReturnType = const DMatSMatMultExpr<MT1,MT2,SF,HF,true,true>;
2122 return ReturnType( dm.leftOperand(), dm.rightOperand() );
2123}
2125//*************************************************************************************************
2126
2127
2128
2129
2130//=================================================================================================
2131//
2132// SIZE SPECIALIZATIONS
2133//
2134//=================================================================================================
2135
2136//*************************************************************************************************
2138template< typename MT1, typename MT2, bool SF, bool HF, bool LF, bool UF >
2139struct Size< DMatSMatMultExpr<MT1,MT2,SF,HF,LF,UF>, 0UL >
2140 : public Size<MT1,0UL>
2141{};
2142
2143template< typename MT1, typename MT2, bool SF, bool HF, bool LF, bool UF >
2144struct Size< DMatSMatMultExpr<MT1,MT2,SF,HF,LF,UF>, 1UL >
2145 : public Size<MT2,1UL>
2146{};
2148//*************************************************************************************************
2149
2150
2151
2152
2153//=================================================================================================
2154//
2155// ISALIGNED SPECIALIZATIONS
2156//
2157//=================================================================================================
2158
2159//*************************************************************************************************
2161template< typename MT1, typename MT2, bool SF, bool HF, bool LF, bool UF >
2162struct IsAligned< DMatSMatMultExpr<MT1,MT2,SF,HF,LF,UF> >
2163 : public IsAligned<MT1>
2164{};
2166//*************************************************************************************************
2167
2168} // namespace blaze
2169
2170#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::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 blaze::checked and blaze::unchecked instances.
Constraints on the storage order of matrix types.
Header file for the conjugate shim.
Header file for the decldiag trait.
Header file for the DeclDiag functor.
Header file for the declherm trait.
Header file for the DeclHerm functor.
Header file for the decllow trait.
Header file for the DeclLow functor.
Header file for the declsym trait.
Header file for the DeclSym functor.
Header file for the declupp trait.
Header file for the DeclUpp functor.
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 IntegralConstant class template.
Header file for the IsAligned type trait.
Header file for the IsBuiltin type trait.
Header file for the IsComputation type trait class.
Header file for the isDefault shim.
Header file for the IsDiagonal type trait.
Header file for the IsExpression type trait class.
Header file for the IsIdentity type trait.
Header file for the IsLower type trait.
Header file for the IsResizable type trait.
Header file for the IsSame and IsStrictlySame type traits.
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 IsTriangular type trait.
Header file for the IsUpper type trait.
Header file for the MAYBE_UNUSED function template.
Header file for the multiplication trait.
Header file for the Noop functor.
Constraints on the storage order of matrix types.
Constraint on the data type.
Constraint on the data type.
Expression object for dense matrix-sparse matrix multiplications.
Definition: DMatSMatMultExpr.h:129
OppositeType_t< ResultType > OppositeType
Result type with opposite storage order for expression template evaluations.
Definition: DMatSMatMultExpr.h:242
typename If_t< HERM, DeclHermTrait< MultTrait_t< RT1, RT2 > >, If_t< SYM, DeclSymTrait< MultTrait_t< RT1, RT2 > >, If_t< LOW, If_t< UPP, DeclDiagTrait< MultTrait_t< RT1, RT2 > >, DeclLowTrait< MultTrait_t< RT1, RT2 > > >, If_t< UPP, DeclUppTrait< MultTrait_t< RT1, RT2 > >, MultTrait< RT1, RT2 > > > > >::Type ResultType
Result type for expression template evaluations.
Definition: DMatSMatMultExpr.h:240
static constexpr bool SYM
Flag for symmetric matrices.
Definition: DMatSMatMultExpr.h:151
If_t< IsExpression_v< MT2 >, const MT2, const MT2 & > RightOperand
Composite type of the right-hand side sparse matrix expression.
Definition: DMatSMatMultExpr.h:252
RightOperand rhs_
Right-hand side sparse matrix of the multiplication expression.
Definition: DMatSMatMultExpr.h:438
ResultType_t< MT2 > RT2
Result type of the right-hand side sparse matrix expression.
Definition: DMatSMatMultExpr.h:133
TransposeType_t< ResultType > TransposeType
Transpose type for expression template evaluations.
Definition: DMatSMatMultExpr.h:243
If_t< evaluateLeft, const RT1, CT1 > LT
Type for the assignment of the left-hand side dense matrix operand.
Definition: DMatSMatMultExpr.h:255
If_t< evaluateRight, const RT2, CT2 > RT
Type for the assignment of the right-hand side sparse matrix operand.
Definition: DMatSMatMultExpr.h:258
static constexpr bool HERM
Flag for Hermitian matrices.
Definition: DMatSMatMultExpr.h:152
LeftOperand leftOperand() const noexcept
Returns the left-hand side dense matrix operand.
Definition: DMatSMatMultExpr.h:376
ReturnType operator()(size_t i, size_t j) const
2D-access to the matrix elements.
Definition: DMatSMatMultExpr.h:291
CompositeType_t< MT2 > CT2
Composite type of the right-hand side sparse matrix expression.
Definition: DMatSMatMultExpr.h:137
static constexpr bool LOW
Flag for lower matrices.
Definition: DMatSMatMultExpr.h:153
CompositeType_t< MT1 > CT1
Composite type of the left-hand side dense matrix expression.
Definition: DMatSMatMultExpr.h:136
ResultType_t< MT1 > RT1
Result type of the left-hand side dense matrix expression.
Definition: DMatSMatMultExpr.h:132
const ElementType ReturnType
Return type for expression template evaluations.
Definition: DMatSMatMultExpr.h:245
ElementType_t< ResultType > ElementType
Resulting element type.
Definition: DMatSMatMultExpr.h:244
ElementType_t< RT2 > ET2
Element type of the right-hand side sparse matrix expression.
Definition: DMatSMatMultExpr.h:135
bool isAligned() const noexcept
Returns whether the operands of the expression are properly aligned in memory.
Definition: DMatSMatMultExpr.h:420
size_t rows() const noexcept
Returns the current number of rows of the matrix.
Definition: DMatSMatMultExpr.h:356
static constexpr bool smpAssignable
Compilation switch for the expression template assignment strategy.
Definition: DMatSMatMultExpr.h:266
RightOperand rightOperand() const noexcept
Returns the right-hand side sparse matrix operand.
Definition: DMatSMatMultExpr.h:386
ElementType_t< RT1 > ET1
Element type of the left-hand side dense matrix expression.
Definition: DMatSMatMultExpr.h:134
bool isAliased(const T *alias) const noexcept
Returns whether the expression is aliased with the given address alias.
Definition: DMatSMatMultExpr.h:410
const ResultType CompositeType
Data type for composite expression templates.
Definition: DMatSMatMultExpr.h:246
static constexpr bool evaluateRight
Compilation switch for the composite type of the right-hand side sparse matrix expression.
Definition: DMatSMatMultExpr.h:147
bool canAlias(const T *alias) const noexcept
Returns whether the expression can alias with the given address alias.
Definition: DMatSMatMultExpr.h:398
LeftOperand lhs_
Left-hand side dense matrix of the multiplication expression.
Definition: DMatSMatMultExpr.h:437
bool canSMPAssign() const noexcept
Returns whether the expression can be used in SMP assignments.
Definition: DMatSMatMultExpr.h:430
static constexpr bool evaluateLeft
Compilation switch for the composite type of the left-hand side dense matrix expression.
Definition: DMatSMatMultExpr.h:142
static constexpr bool UPP
Flag for upper matrices.
Definition: DMatSMatMultExpr.h:154
If_t< IsExpression_v< MT1 >, const MT1, const MT1 & > LeftOperand
Composite type of the left-hand side dense matrix expression.
Definition: DMatSMatMultExpr.h:249
static constexpr bool simdEnabled
Compilation switch for the expression template evaluation strategy.
Definition: DMatSMatMultExpr.h:263
DMatSMatMultExpr(const MT1 &lhs, const MT2 &rhs) noexcept
Constructor for the DMatSMatMultExpr class.
Definition: DMatSMatMultExpr.h:276
size_t columns() const noexcept
Returns the current number of columns of the matrix.
Definition: DMatSMatMultExpr.h:366
ReturnType at(size_t i, size_t j) const
Checked access to the matrix elements.
Definition: DMatSMatMultExpr.h:340
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.
Constraint on the data type.
Header file for the Computation base class.
Header file for the DenseMatrix base class.
Header file for the MatMatMultExpr base class.
decltype(auto) column(Matrix< MT, SO > &matrix, RCAs... args)
Creating a view on a specific column of the given matrix.
Definition: Column.h:137
decltype(auto) transIf(const DenseMatrix< MT, SO > &dm)
Conditional calculation of the transpose of the given dense matrix.
Definition: DMatTransExpr.h:832
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) max(const DenseMatrix< MT1, SO1 > &lhs, const DenseMatrix< MT2, SO2 > &rhs)
Computes the componentwise maximum of the dense matrices lhs and rhs.
Definition: DMatDMatMapExpr.h:1375
decltype(auto) declstrupp(const DenseMatrix< MT, SO > &dm)
Declares the given dense matrix expression dm as strictly upper.
Definition: DMatDeclStrUppExpr.h:1003
decltype(auto) conj(const DenseMatrix< MT, SO > &dm)
Returns a matrix containing the complex conjugate of each single element of dm.
Definition: DMatMapExpr.h:1464
decltype(auto) decldiag(const DenseMatrix< MT, SO > &dm)
Declares the given dense matrix expression dm as diagonal.
Definition: DMatDeclDiagExpr.h:978
decltype(auto) declstrlow(const DenseMatrix< MT, SO > &dm)
Declares the given dense matrix expression dm as strictly lower.
Definition: DMatDeclStrLowExpr.h:1003
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) declupp(const DenseMatrix< MT, SO > &dm)
Declares the given dense matrix expression dm as upper.
Definition: DMatDeclUppExpr.h:1004
decltype(auto) decllow(const DenseMatrix< MT, SO > &dm)
Declares the given dense matrix expression dm as lower.
Definition: DMatDeclLowExpr.h:1004
decltype(auto) decluniupp(const DenseMatrix< MT, SO > &dm)
Declares the given dense matrix expression dm as uniupper.
Definition: DMatDeclUniUppExpr.h:1005
decltype(auto) declherm(const DenseMatrix< MT, SO > &dm)
Declares the given dense matrix expression dm as Hermitian.
Definition: DMatDeclHermExpr.h:1005
decltype(auto) declsym(const DenseMatrix< MT, SO > &dm)
Declares the given dense matrix expression dm as symmetric.
Definition: DMatDeclSymExpr.h:1005
decltype(auto) declunilow(const DenseMatrix< MT, SO > &dm)
Declares the given dense matrix expression dm as unilower.
Definition: DMatDeclUniLowExpr.h:1004
bool isDefault(const DiagonalMatrix< MT, SO, DF > &m)
Returns whether the given diagonal matrix is in default state.
Definition: DiagonalMatrix.h:169
#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_MATRICES_MUST_HAVE_SAME_STORAGE_ORDER(T1, T2)
Constraint on the data type.
Definition: StorageOrder.h:84
#define BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION(T)
Constraint on the data type.
Definition: RequiresEvaluation.h:81
#define BLAZE_CONSTRAINT_MUST_FORM_VALID_MATMATMULTEXPR(T1, T2)
Constraint on the data type.
Definition: MatMatMultExpr.h:103
#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_BE_COLUMN_MAJOR_MATRIX_TYPE(T)
Constraint on the data type.
Definition: ColumnMajorMatrix.h:61
#define BLAZE_CONSTRAINT_MUST_BE_ZERO_TYPE(T)
Constraint on the data type.
Definition: Zero.h:61
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
MT::Iterator begin(Matrix< MT, SO > &matrix, size_t i)
Returns an iterator to the first element of row/column i.
Definition: Matrix.h:518
bool isSquare(const Matrix< MT, SO > &matrix) noexcept
Checks if the given matrix is a square matrix.
Definition: Matrix.h:1383
decltype(auto) row(Matrix< MT, SO > &, RRAs...)
Creating a view on a specific row of the given matrix.
Definition: Row.h:137
#define BLAZE_INTERNAL_ASSERT(expr, msg)
Run time assertion macro for internal checks.
Definition: Assert.h:101
auto smpSubAssign(Matrix< MT1, SO1 > &lhs, const Matrix< MT2, SO2 > &rhs) -> EnableIf_t< IsDenseMatrix_v< MT1 > >
Default implementation of the SMP subtraction assignment of a matrix to dense matrix.
Definition: DenseMatrix.h:162
auto smpAssign(Matrix< MT1, SO1 > &lhs, const Matrix< MT2, SO2 > &rhs) -> EnableIf_t< IsDenseMatrix_v< MT1 > >
Default implementation of the SMP assignment of a matrix to a dense matrix.
Definition: DenseMatrix.h:100
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
auto smpAddAssign(Matrix< MT1, SO1 > &lhs, const Matrix< MT2, SO2 > &rhs) -> EnableIf_t< IsDenseMatrix_v< MT1 > >
Default implementation of the SMP addition assignment of a matrix to a dense matrix.
Definition: DenseMatrix.h:131
decltype(auto) subvector(Vector< VT, TF > &, RSAs...)
Creating a view on a specific subvector of the given vector.
Definition: Subvector.h:158
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
constexpr Unchecked unchecked
Global Unchecked instance.
Definition: Check.h:146
Header file for the exception macros of the math module.
Constraints on the storage order of matrix types.
Header file for all forward declarations for expression class templates.
Header file for the Size type trait.
Header file for the reset shim.
Header file for the serial shim.
Base class for all compute expression templates.
Definition: Computation.h:68
Base template for the DeclDiagTrait class.
Definition: DeclDiagTrait.h:127
Generic wrapper for the decldiag() function.
Definition: DeclDiag.h:61
Base template for the DeclHermTrait class.
Definition: DeclHermTrait.h:126
Generic wrapper for the declherm() function.
Definition: DeclHerm.h:61
Base template for the DeclLowTrait class.
Definition: DeclLowTrait.h:126
Generic wrapper for the decllow() function.
Definition: DeclLow.h:61
Base template for the DeclSymTrait class.
Definition: DeclSymTrait.h:126
Generic wrapper for the declsym() function.
Definition: DeclSym.h:61
Base template for the DeclUppTrait class.
Definition: DeclUppTrait.h:126
Generic wrapper for the declupp() function.
Definition: DeclUpp.h:61
Base class for all matrix/matrix multiplication expression templates.
Definition: MatMatMultExpr.h:71
Base template for the MultTrait class.
Definition: MultTrait.h:130
Generic wrapper for the null function.
Definition: Noop.h:62
System settings for performance optimizations.
Header file for the thresholds for matrix/vector and matrix/matrix multiplications.
Header file for the IsZero type trait.
Header file for the RequiresEvaluation type trait.
Header file for basic type definitions.
Header file for the generic max algorithm.
Header file for the generic min algorithm.