Blaze 3.9
TSMatDMatMultExpr.h
Go to the documentation of this file.
1//=================================================================================================
33//=================================================================================================
34
35#ifndef _BLAZE_MATH_EXPRESSIONS_TSMATDMATMULTEXPR_H_
36#define _BLAZE_MATH_EXPRESSIONS_TSMATDMATMULTEXPR_H_
37
38
39//*************************************************************************************************
40// Includes
41//*************************************************************************************************
42
43#include <blaze/math/Aliases.h>
97#include <blaze/util/Assert.h>
98#include <blaze/util/EnableIf.h>
102#include <blaze/util/mpl/If.h>
103#include <blaze/util/Types.h>
105
106
107namespace blaze {
108
109//=================================================================================================
110//
111// CLASS SMATDMATMULTEXPR
112//
113//=================================================================================================
114
115//*************************************************************************************************
122template< typename MT1 // Type of the left-hand side dense matrix
123 , typename MT2 // Type of the right-hand side sparse matrix
124 , bool SF // Symmetry flag
125 , bool HF // Hermitian flag
126 , bool LF // Lower flag
127 , bool UF > // Upper flag
129 : public MatMatMultExpr< DenseMatrix< TSMatDMatMultExpr<MT1,MT2,SF,HF,LF,UF>, false > >
130 , private Computation
131{
132 private:
133 //**Type definitions****************************************************************************
140 //**********************************************************************************************
141
142 //**********************************************************************************************
144 static constexpr bool evaluateLeft = ( IsComputation_v<MT1> || RequiresEvaluation_v<MT1> );
145 //**********************************************************************************************
146
147 //**********************************************************************************************
149 static constexpr bool evaluateRight = ( IsComputation_v<MT2> || RequiresEvaluation_v<MT2> );
150 //**********************************************************************************************
151
152 //**********************************************************************************************
153 static constexpr bool SYM = ( SF && !( HF || LF || UF ) );
154 static constexpr bool HERM = ( HF && !( LF || UF ) );
155 static constexpr bool LOW = ( LF || ( ( SF || HF ) && UF ) );
156 static constexpr bool UPP = ( UF || ( ( SF || HF ) && LF ) );
157 //**********************************************************************************************
158
159 //**********************************************************************************************
161
166 template< typename T1, typename T2, typename T3 >
167 static constexpr bool CanExploitSymmetry_v = IsSymmetric_v<T2>;
169 //**********************************************************************************************
170
171 //**********************************************************************************************
173
177 template< typename T1, typename T2, typename T3 >
178 static constexpr bool IsEvaluationRequired_v =
179 ( ( evaluateLeft || evaluateRight ) && !CanExploitSymmetry_v<T1,T2,T3> );
181 //**********************************************************************************************
182
183 //**********************************************************************************************
185
188 template< typename T1, typename T2, typename T3 >
189 static constexpr bool UseOptimizedKernel_v =
190 ( useOptimizedKernels &&
191 !IsDiagonal_v<T3> &&
192 !IsResizable_v< ElementType_t<T1> > &&
193 !IsResizable_v<ET1> );
195 //**********************************************************************************************
196
197 //**********************************************************************************************
199
202 template< typename T1, typename T2, typename T3 >
203 static constexpr bool UseDefaultKernel_v = !UseOptimizedKernel_v<T1,T2,T3>;
205 //**********************************************************************************************
206
207 //**********************************************************************************************
209
212 using ForwardFunctor = If_t< HERM
213 , DeclHerm
214 , If_t< SYM
215 , DeclSym
216 , If_t< LOW
217 , If_t< UPP
218 , DeclDiag
219 , DeclLow >
220 , If_t< UPP
221 , DeclUpp
222 , Noop > > > >;
224 //**********************************************************************************************
225
226 public:
227 //**Type definitions****************************************************************************
230
233
235 using ResultType = typename If_t< HERM
237 , If_t< SYM
239 , If_t< LOW
240 , If_t< UPP
243 , If_t< UPP
245 , MultTrait<RT1,RT2> > > > >::Type;
246
250 using ReturnType = const ElementType;
251 using CompositeType = const ResultType;
252
254 using LeftOperand = If_t< IsExpression_v<MT1>, const MT1, const MT1& >;
255
257 using RightOperand = If_t< IsExpression_v<MT2>, const MT2, const MT2& >;
258
261
264 //**********************************************************************************************
265
266 //**Compilation flags***************************************************************************
268 static constexpr bool simdEnabled = false;
269
271 static constexpr bool smpAssignable =
272 ( !evaluateLeft && MT1::smpAssignable && !evaluateRight && MT2::smpAssignable );
273 //**********************************************************************************************
274
275 //**Constructor*********************************************************************************
281 inline TSMatDMatMultExpr( const MT1& lhs, const MT2& rhs ) noexcept
282 : lhs_( lhs ) // Left-hand side sparse matrix of the multiplication expression
283 , rhs_( rhs ) // Right-hand side dense matrix of the multiplication expression
284 {
285 BLAZE_INTERNAL_ASSERT( lhs.columns() == rhs.rows(), "Invalid matrix sizes" );
286 }
287 //**********************************************************************************************
288
289 //**Access operator*****************************************************************************
296 inline ReturnType operator()( size_t i, size_t j ) const {
297 BLAZE_INTERNAL_ASSERT( i < lhs_.rows() , "Invalid row access index" );
298 BLAZE_INTERNAL_ASSERT( j < rhs_.columns(), "Invalid column access index" );
299
300 if( IsDiagonal_v<MT1> ) {
301 return lhs_(i,i) * rhs_(i,j);
302 }
303 else if( IsDiagonal_v<MT2> ) {
304 return lhs_(i,j) * rhs_(j,j);
305 }
306 else if( IsTriangular_v<MT1> || IsTriangular_v<MT2> ) {
307 const size_t begin( ( IsUpper_v<MT1> )
308 ?( ( IsLower_v<MT2> )
309 ?( max( ( IsStrictlyUpper_v<MT1> ? i+1UL : i )
310 , ( IsStrictlyLower_v<MT2> ? j+1UL : j ) ) )
311 :( IsStrictlyUpper_v<MT1> ? i+1UL : i ) )
312 :( ( IsLower_v<MT2> )
313 ?( IsStrictlyLower_v<MT2> ? j+1UL : j )
314 :( 0UL ) ) );
315 const size_t end( ( IsLower_v<MT1> )
316 ?( ( IsUpper_v<MT2> )
317 ?( min( ( IsStrictlyLower_v<MT1> ? i : i+1UL )
318 , ( IsStrictlyUpper_v<MT2> ? j : j+1UL ) ) )
319 :( IsStrictlyLower_v<MT1> ? i : i+1UL ) )
320 :( ( IsUpper_v<MT2> )
321 ?( IsStrictlyUpper_v<MT2> ? j : j+1UL )
322 :( lhs_.columns() ) ) );
323
324 if( begin >= end ) return ElementType();
325
326 const size_t n( end - begin );
327
328 return subvector( row( lhs_, i, unchecked ), begin, n, unchecked ) *
330 }
331 else {
332 return row( lhs_, i, unchecked ) * column( rhs_, j, unchecked );
333 }
334 }
335 //**********************************************************************************************
336
337 //**At function*********************************************************************************
345 inline ReturnType at( size_t i, size_t j ) const {
346 if( i >= lhs_.rows() ) {
347 BLAZE_THROW_OUT_OF_RANGE( "Invalid row access index" );
348 }
349 if( j >= rhs_.columns() ) {
350 BLAZE_THROW_OUT_OF_RANGE( "Invalid column access index" );
351 }
352 return (*this)(i,j);
353 }
354 //**********************************************************************************************
355
356 //**Rows function*******************************************************************************
361 inline size_t rows() const noexcept {
362 return lhs_.rows();
363 }
364 //**********************************************************************************************
365
366 //**Columns function****************************************************************************
371 inline size_t columns() const noexcept {
372 return rhs_.columns();
373 }
374 //**********************************************************************************************
375
376 //**Left operand access*************************************************************************
381 inline LeftOperand leftOperand() const noexcept {
382 return lhs_;
383 }
384 //**********************************************************************************************
385
386 //**Right operand access************************************************************************
391 inline RightOperand rightOperand() const noexcept {
392 return rhs_;
393 }
394 //**********************************************************************************************
395
396 //**********************************************************************************************
402 template< typename T >
403 inline bool canAlias( const T* alias ) const noexcept {
404 return ( lhs_.isAliased( alias ) || rhs_.isAliased( alias ) );
405 }
406 //**********************************************************************************************
407
408 //**********************************************************************************************
414 template< typename T >
415 inline bool isAliased( const T* alias ) const noexcept {
416 return ( lhs_.isAliased( alias ) || rhs_.isAliased( alias ) );
417 }
418 //**********************************************************************************************
419
420 //**********************************************************************************************
425 inline bool isAligned() const noexcept {
426 return rhs_.isAligned();
427 }
428 //**********************************************************************************************
429
430 //**********************************************************************************************
435 inline bool canSMPAssign() const noexcept {
436 return ( rows() * columns() >= SMP_TSMATDMATMULT_THRESHOLD ) && !IsDiagonal_v<MT2>;
437 }
438 //**********************************************************************************************
439
440 private:
441 //**Member variables****************************************************************************
444 //**********************************************************************************************
445
446 //**Assignment to dense matrices****************************************************************
459 template< typename MT // Type of the target dense matrix
460 , bool SO > // Storage order of the target dense matrix
461 friend inline auto assign( DenseMatrix<MT,SO>& lhs, const TSMatDMatMultExpr& rhs )
463 {
465
466 BLAZE_INTERNAL_ASSERT( (*lhs).rows() == rhs.rows() , "Invalid number of rows" );
467 BLAZE_INTERNAL_ASSERT( (*lhs).columns() == rhs.columns(), "Invalid number of columns" );
468
469 LT A( serial( rhs.lhs_ ) ); // Evaluation of the right-hand side sparse matrix operand
470 RT B( serial( rhs.rhs_ ) ); // Evaluation of the left-hand side dense matrix operand
471
472 BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
473 BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
474 BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
475 BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
476 BLAZE_INTERNAL_ASSERT( A.rows() == (*lhs).rows() , "Invalid number of rows" );
477 BLAZE_INTERNAL_ASSERT( B.columns() == (*lhs).columns() , "Invalid number of columns" );
478
479 TSMatDMatMultExpr::selectAssignKernel( *lhs, A, B );
480 }
482 //**********************************************************************************************
483
484 //**Assignment to dense matrices (kernel selection)*********************************************
495 template< typename MT3 // Type of the left-hand side target matrix
496 , typename MT4 // Type of the left-hand side matrix operand
497 , typename MT5 > // Type of the right-hand side matrix operand
498 static inline void selectAssignKernel( MT3& C, const MT4& A, const MT5& B )
499 {
500 const size_t size( C.rows() * C.columns() );
501
502 if( ( IsRowMajorMatrix_v<MT3> && size < TSMATDMATMULT_THRESHOLD ) ||
503 ( IsColumnMajorMatrix_v<MT3> && size < 625UL ) )
504 selectSmallAssignKernel( C, A, B );
505 else
506 selectLargeAssignKernel( C, A, B );
507 }
509 //**********************************************************************************************
510
511 //**Default assignment to dense matrices********************************************************
526 template< typename MT3 // Type of the left-hand side target matrix
527 , typename MT4 // Type of the left-hand side matrix operand
528 , typename MT5 > // Type of the right-hand side matrix operand
529 static inline void selectDefaultAssignKernel( MT3& C, const MT4& A, const MT5& B )
530 {
531 reset( C );
532
533 if( IsDiagonal_v<MT5> )
534 {
535 for( size_t i=0UL; i<A.columns(); ++i )
536 {
537 const auto end( A.end(i) );
538 auto element( A.begin(i) );
539
540 for( ; element!=end; ++element ) {
541 C(element->index(),i) = element->value() * B(i,i);
542 }
543 }
544 }
545 else
546 {
547 const size_t block( IsRowMajorMatrix_v<MT3> ? 256UL : 8UL );
548
549 for( size_t jj=0UL; jj<B.columns(); jj+=block )
550 {
551 const size_t jpos( ( jj+block > B.columns() )?( B.columns() ):( jj+block ) );
552
553 for( size_t i=0UL; i<A.columns(); ++i )
554 {
555 const auto end( A.end(i) );
556 auto element( A.begin(i) );
557
558 for( ; element!=end; ++element )
559 {
560 const size_t i1( element->index() );
561
562 const size_t jbegin( ( IsUpper_v<MT5> )
563 ?( ( SYM || HERM || UPP )
564 ?( max( i1, IsStrictlyUpper_v<MT5> ? i+1UL : i, jj ) )
565 :( max( IsStrictlyUpper_v<MT5> ? i+1UL : i, jj ) ) )
566 :( SYM || HERM || UPP ? max(i1,jj) : jj ) );
567 const size_t jend( ( IsLower_v<MT5> )
568 ?( ( LOW )
569 ?( min( i1+1UL, IsStrictlyLower_v<MT5> ? i : i+1UL, jpos ) )
570 :( min( IsStrictlyLower_v<MT5> ? i : i+1UL, jpos ) ) )
571 :( LOW ? min(i1+1UL,jpos) : jpos ) );
572
573 if( jbegin >= jend )
574 continue;
575
576 for( size_t j=jbegin; j<jend; ++j ) {
577 if( isDefault( C(i1,j) ) )
578 C(i1,j) = element->value() * B(i,j);
579 else
580 C(i1,j) += element->value() * B(i,j);
581 }
582 }
583 }
584 }
585 }
586
587 if( SYM || HERM ) {
588 for( size_t j=0UL; j<B.columns(); ++j ) {
589 for( size_t i=j+1UL; i<A.rows(); ++i ) {
590 C(i,j) = HERM ? conj( C(j,i) ) : C(j,i);
591 }
592 }
593 }
594 }
596 //**********************************************************************************************
597
598 //**Default assignment to dense matrices (small matrices)***************************************
612 template< typename MT3 // Type of the left-hand side target matrix
613 , typename MT4 // Type of the left-hand side matrix operand
614 , typename MT5 > // Type of the right-hand side matrix operand
615 static inline auto selectSmallAssignKernel( MT3& C, const MT4& A, const MT5& B )
616 -> EnableIf_t< UseDefaultKernel_v<MT3,MT4,MT5> >
617 {
618 selectDefaultAssignKernel( C, A, B );
619 }
621 //**********************************************************************************************
622
623 //**Optimized assignment to dense matrices (small matrices)*************************************
638 template< typename MT3 // Type of the left-hand side target matrix
639 , typename MT4 // Type of the left-hand side matrix operand
640 , typename MT5 > // Type of the right-hand side matrix operand
641 static inline auto selectSmallAssignKernel( MT3& C, const MT4& A, const MT5& B )
642 -> EnableIf_t< UseOptimizedKernel_v<MT3,MT4,MT5> >
643 {
644 const size_t block( ( IsRowMajorMatrix_v<MT3> )?( 256UL ):( 8UL ) );
645
646 reset( C );
647
648 for( size_t jj=0UL; jj<B.columns(); jj+=block )
649 {
650 const size_t jpos( ( jj+block > B.columns() )?( B.columns() ):( jj+block ) );
651
652 for( size_t i=0UL; i<A.columns(); ++i )
653 {
654 const auto end( A.end(i) );
655 auto element( A.begin(i) );
656
657 const size_t nonzeros( A.nonZeros(i) );
658 const size_t kpos( prevMultiple( nonzeros, 4UL ) );
659 BLAZE_INTERNAL_ASSERT( kpos <= nonzeros, "Invalid end calculation" );
660
661 for( size_t k=0UL; k<kpos; k+=4UL )
662 {
663 const size_t i1( element->index() );
664 const ET1 v1( element->value() );
665 ++element;
666 const size_t i2( element->index() );
667 const ET1 v2( element->value() );
668 ++element;
669 const size_t i3( element->index() );
670 const ET1 v3( element->value() );
671 ++element;
672 const size_t i4( element->index() );
673 const ET1 v4( element->value() );
674 ++element;
675
676 BLAZE_INTERNAL_ASSERT( i1 < i2 && i2 < i3 && i3 < i4, "Invalid sparse matrix index detected" );
677
678 const size_t jbegin( ( IsUpper_v<MT5> )
679 ?( ( SYM || HERM || UPP )
680 ?( max( i1, IsStrictlyUpper_v<MT5> ? i+1UL : i, jj ) )
681 :( max( IsStrictlyUpper_v<MT5> ? i+1UL : i, jj ) ) )
682 :( SYM || HERM || UPP ? max(i1,jj) : jj ) );
683 const size_t jend( ( IsLower_v<MT5> )
684 ?( ( LOW )
685 ?( min( i4+1UL, IsStrictlyLower_v<MT5> ? i : i+1UL, jpos ) )
686 :( min( IsStrictlyLower_v<MT5> ? i : i+1UL, jpos ) ) )
687 :( LOW ? min(i4+1UL,jpos) : jpos ) );
688
689 if( jbegin >= jend )
690 continue;
691
692 for( size_t j=jbegin; j<jend; ++j ) {
693 C(i1,j) += v1 * B(i,j);
694 C(i2,j) += v2 * B(i,j);
695 C(i3,j) += v3 * B(i,j);
696 C(i4,j) += v4 * B(i,j);
697 }
698 }
699
700 for( ; element!=end; ++element )
701 {
702 const size_t i1( element->index() );
703
704 const size_t jbegin( ( IsUpper_v<MT5> )
705 ?( ( SYM || HERM || UPP )
706 ?( max( i1, IsStrictlyUpper_v<MT5> ? i+1UL : i, jj ) )
707 :( max( IsStrictlyUpper_v<MT5> ? i+1UL : i, jj ) ) )
708 :( SYM || HERM || UPP ? max(i1,jj) : jj ) );
709 const size_t jend( ( IsLower_v<MT5> )
710 ?( ( LOW )
711 ?( min( i1+1UL, IsStrictlyLower_v<MT5> ? i : i+1UL, jpos ) )
712 :( min( IsStrictlyLower_v<MT5> ? i : i+1UL, jpos ) ) )
713 :( LOW ? min(i1+1UL,jpos) : jpos ) );
714
715 if( jbegin >= jend )
716 continue;
717
718 for( size_t j=jbegin; j<jend; ++j ) {
719 C(i1,j) += element->value() * B(i,j);
720 }
721 }
722 }
723 }
724
725 if( SYM || HERM ) {
726 for( size_t j=0UL; j<B.columns(); ++j ) {
727 for( size_t i=j+1UL; i<A.rows(); ++i ) {
728 C(i,j) = HERM ? conj( C(j,i) ) : C(j,i);
729 }
730 }
731 }
732 }
734 //**********************************************************************************************
735
736 //**Default assignment to dense matrices (large matrices)***************************************
750 template< typename MT3 // Type of the left-hand side target matrix
751 , typename MT4 // Type of the left-hand side matrix operand
752 , typename MT5 > // Type of the right-hand side matrix operand
753 static inline auto selectLargeAssignKernel( MT3& C, const MT4& A, const MT5& B )
754 -> EnableIf_t< UseDefaultKernel_v<MT3,MT4,MT5> >
755 {
756 selectDefaultAssignKernel( C, A, B );
757 }
759 //**********************************************************************************************
760
761 //**Optimized assignment to dense matrices (large matrices)*************************************
776 template< typename MT3 // Type of the left-hand side target matrix
777 , typename MT4 // Type of the left-hand side matrix operand
778 , typename MT5 > // Type of the right-hand side matrix operand
779 static inline auto selectLargeAssignKernel( MT3& C, const MT4& A, const MT5& B )
780 -> EnableIf_t< UseOptimizedKernel_v<MT3,MT4,MT5> >
781 {
783
784 const ForwardFunctor fwd;
785
786 const OppositeType_t<MT4> tmp( serial( A ) );
787 assign( C, fwd( tmp * B ) );
788 }
790 //**********************************************************************************************
791
792 //**Assignment to sparse matrices***************************************************************
805 template< typename MT // Type of the target sparse matrix
806 , bool SO > // Storage order of the target sparse matrix
807 friend inline auto assign( SparseMatrix<MT,SO>& lhs, const TSMatDMatMultExpr& rhs )
808 -> DisableIf_t< CanExploitSymmetry_v<MT,MT1,MT2> >
809 {
811
812 using TmpType = If_t< SO, OppositeType, ResultType >;
813
820
821 BLAZE_INTERNAL_ASSERT( (*lhs).rows() == rhs.rows() , "Invalid number of rows" );
822 BLAZE_INTERNAL_ASSERT( (*lhs).columns() == rhs.columns(), "Invalid number of columns" );
823
824 const ForwardFunctor fwd;
825
826 const TmpType tmp( serial( rhs ) );
827 assign( *lhs, fwd( tmp ) );
828 }
830 //**********************************************************************************************
831
832 //**Restructuring assignment to row-major matrices**********************************************
847 template< typename MT // Type of the target matrix
848 , bool SO > // Storage order of the target matrix
849 friend inline auto assign( Matrix<MT,SO>& lhs, const TSMatDMatMultExpr& rhs )
850 -> EnableIf_t< CanExploitSymmetry_v<MT,MT1,MT2> >
851 {
853
855
856 BLAZE_INTERNAL_ASSERT( (*lhs).rows() == rhs.rows() , "Invalid number of rows" );
857 BLAZE_INTERNAL_ASSERT( (*lhs).columns() == rhs.columns(), "Invalid number of columns" );
858
859 const ForwardFunctor fwd;
860
861 assign( *lhs, fwd( trans( rhs.lhs_ ) * rhs.rhs_ ) );
862 }
864 //**********************************************************************************************
865
866 //**Addition assignment to dense matrices*******************************************************
879 template< typename MT // Type of the target dense matrix
880 , bool SO > // Storage order of the target dense matrix
881 friend inline auto addAssign( DenseMatrix<MT,SO>& lhs, const TSMatDMatMultExpr& rhs )
882 -> DisableIf_t< CanExploitSymmetry_v<MT,MT1,MT2> >
883 {
885
886 BLAZE_INTERNAL_ASSERT( (*lhs).rows() == rhs.rows() , "Invalid number of rows" );
887 BLAZE_INTERNAL_ASSERT( (*lhs).columns() == rhs.columns(), "Invalid number of columns" );
888
889 LT A( serial( rhs.lhs_ ) ); // Evaluation of the right-hand side sparse matrix operand
890 RT B( serial( rhs.rhs_ ) ); // Evaluation of the left-hand side dense matrix operand
891
892 BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
893 BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
894 BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
895 BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
896 BLAZE_INTERNAL_ASSERT( A.rows() == (*lhs).rows() , "Invalid number of rows" );
897 BLAZE_INTERNAL_ASSERT( B.columns() == (*lhs).columns() , "Invalid number of columns" );
898
899 TSMatDMatMultExpr::selectAddAssignKernel( *lhs, A, B );
900 }
902 //**********************************************************************************************
903
904 //**Addition assignment to dense matrices (kernel selection)************************************
915 template< typename MT3 // Type of the left-hand side target matrix
916 , typename MT4 // Type of the left-hand side matrix operand
917 , typename MT5 > // Type of the right-hand side matrix operand
918 static inline void selectAddAssignKernel( MT3& C, const MT4& A, const MT5& B )
919 {
920 const size_t size( C.rows() * C.columns() );
921
922 if( ( IsRowMajorMatrix_v<MT3> && size < TSMATDMATMULT_THRESHOLD ) ||
923 ( IsColumnMajorMatrix_v<MT3> && size < 625UL ) )
924 selectSmallAddAssignKernel( C, A, B );
925 else
926 selectLargeAddAssignKernel( C, A, B );
927 }
929 //**********************************************************************************************
930
931 //**Default addition assignment to dense matrices***********************************************
946 template< typename MT3 // Type of the left-hand side target matrix
947 , typename MT4 // Type of the left-hand side matrix operand
948 , typename MT5 > // Type of the right-hand side matrix operand
949 static inline void selectDefaultAddAssignKernel( MT3& C, const MT4& A, const MT5& B )
950 {
951 if( IsDiagonal_v<MT5> )
952 {
953 for( size_t i=0UL; i<A.columns(); ++i )
954 {
955 const auto end( A.end(i) );
956 auto element( A.begin(i) );
957
958 for( ; element!=end; ++element ) {
959 C(element->index(),i) += element->value() * B(i,i);
960 }
961 }
962 }
963 else
964 {
965 const size_t block( IsRowMajorMatrix_v<MT3> ? 256UL : 8UL );
966
967 for( size_t jj=0UL; jj<B.columns(); jj+=block )
968 {
969 const size_t jpos( ( jj+block > B.columns() )?( B.columns() ):( jj+block ) );
970
971 for( size_t i=0UL; i<A.columns(); ++i )
972 {
973 const auto end( A.end(i) );
974 auto element( A.begin(i) );
975
976 for( ; element!=end; ++element )
977 {
978 const size_t i1( element->index() );
979
980 const size_t jbegin( ( IsUpper_v<MT5> )
981 ?( ( UPP )
982 ?( max( i1, IsStrictlyUpper_v<MT5> ? i+1UL : i, jj ) )
983 :( max( IsStrictlyUpper_v<MT5> ? i+1UL : i, jj ) ) )
984 :( UPP ? max(i1,jj) : jj ) );
985 const size_t jend( ( IsLower_v<MT5> )
986 ?( ( LOW )
987 ?( min( i1+1UL, IsStrictlyLower_v<MT5> ? i : i+1UL, jpos ) )
988 :( min( IsStrictlyLower_v<MT5> ? i : i+1UL, jpos ) ) )
989 :( LOW ? min(i1+1UL,jpos) : jpos ) );
990
991 if( jbegin >= jend )
992 continue;
993
994 for( size_t j=jbegin; j<jend; ++j ) {
995 C(i1,j) += element->value() * B(i,j);
996 }
997 }
998 }
999 }
1000 }
1001 }
1003 //**********************************************************************************************
1004
1005 //**Default addition assignment to dense matrices (small matrices)******************************
1019 template< typename MT3 // Type of the left-hand side target matrix
1020 , typename MT4 // Type of the left-hand side matrix operand
1021 , typename MT5 > // Type of the right-hand side matrix operand
1022 static inline auto selectSmallAddAssignKernel( MT3& C, const MT4& A, const MT5& B )
1023 -> EnableIf_t< UseDefaultKernel_v<MT3,MT4,MT5> >
1024 {
1025 selectDefaultAddAssignKernel( C, A, B );
1026 }
1028 //**********************************************************************************************
1029
1030 //**Optimized addition assignment to dense matrices (small matrices)****************************
1045 template< typename MT3 // Type of the left-hand side target matrix
1046 , typename MT4 // Type of the left-hand side matrix operand
1047 , typename MT5 > // Type of the right-hand side matrix operand
1048 static inline auto selectSmallAddAssignKernel( MT3& C, const MT4& A, const MT5& B )
1049 -> EnableIf_t< UseOptimizedKernel_v<MT3,MT4,MT5> >
1050 {
1051 const size_t block( ( IsRowMajorMatrix_v<MT3> )?( 256UL ):( 8UL ) );
1052
1053 for( size_t jj=0UL; jj<B.columns(); jj+=block )
1054 {
1055 const size_t jpos( ( jj+block > B.columns() )?( B.columns() ):( jj+block ) );
1056
1057 for( size_t i=0UL; i<A.columns(); ++i )
1058 {
1059 const auto end( A.end(i) );
1060 auto element( A.begin(i) );
1061
1062 const size_t nonzeros( A.nonZeros(i) );
1063 const size_t kpos( prevMultiple( nonzeros, 4UL ) );
1064 BLAZE_INTERNAL_ASSERT( kpos <= nonzeros, "Invalid end calculation" );
1065
1066 for( size_t k=0UL; k<kpos; k+=4UL )
1067 {
1068 const size_t i1( element->index() );
1069 const ET1 v1( element->value() );
1070 ++element;
1071 const size_t i2( element->index() );
1072 const ET1 v2( element->value() );
1073 ++element;
1074 const size_t i3( element->index() );
1075 const ET1 v3( element->value() );
1076 ++element;
1077 const size_t i4( element->index() );
1078 const ET1 v4( element->value() );
1079 ++element;
1080
1081 BLAZE_INTERNAL_ASSERT( i1 < i2 && i2 < i3 && i3 < i4, "Invalid sparse matrix index detected" );
1082
1083 const size_t jbegin( ( IsUpper_v<MT5> )
1084 ?( ( UPP )
1085 ?( max( i1, IsStrictlyUpper_v<MT5> ? i+1UL : i, jj ) )
1086 :( max( IsStrictlyUpper_v<MT5> ? i+1UL : i, jj ) ) )
1087 :( UPP ? max(i1,jj) : jj ) );
1088 const size_t jend( ( IsLower_v<MT5> )
1089 ?( ( LOW )
1090 ?( min( i4+1UL, IsStrictlyLower_v<MT5> ? i : i+1UL, jpos ) )
1091 :( min( IsStrictlyLower_v<MT5> ? i : i+1UL, jpos ) ) )
1092 :( LOW ? min(i4+1UL,jpos) : jpos ) );
1093
1094 if( jbegin >= jend )
1095 continue;
1096
1097 for( size_t j=jbegin; j<jend; ++j ) {
1098 C(i1,j) += v1 * B(i,j);
1099 C(i2,j) += v2 * B(i,j);
1100 C(i3,j) += v3 * B(i,j);
1101 C(i4,j) += v4 * B(i,j);
1102 }
1103 }
1104
1105 for( ; element!=end; ++element )
1106 {
1107 const size_t i1( element->index() );
1108
1109 const size_t jbegin( ( IsUpper_v<MT5> )
1110 ?( ( UPP )
1111 ?( max( i1, IsStrictlyUpper_v<MT5> ? i+1UL : i, jj ) )
1112 :( max( IsStrictlyUpper_v<MT5> ? i+1UL : i, jj ) ) )
1113 :( UPP ? max(i1,jj) : jj ) );
1114 const size_t jend( ( IsLower_v<MT5> )
1115 ?( ( LOW )
1116 ?( min( i1+1UL, IsStrictlyLower_v<MT5> ? i : i+1UL, jpos ) )
1117 :( min( IsStrictlyLower_v<MT5> ? i : i+1UL, jpos ) ) )
1118 :( LOW ? min(i1+1UL,jpos) : jpos ) );
1119
1120 if( jbegin >= jend )
1121 continue;
1122
1123 for( size_t j=jbegin; j<jend; ++j ) {
1124 C(i1,j) += element->value() * B(i,j);
1125 }
1126 }
1127 }
1128 }
1129 }
1131 //**********************************************************************************************
1132
1133 //**Default addition assignment to dense matrices (large matrices)******************************
1147 template< typename MT3 // Type of the left-hand side target matrix
1148 , typename MT4 // Type of the left-hand side matrix operand
1149 , typename MT5 > // Type of the right-hand side matrix operand
1150 static inline auto selectLargeAddAssignKernel( MT3& C, const MT4& A, const MT5& B )
1151 -> EnableIf_t< UseDefaultKernel_v<MT3,MT4,MT5> >
1152 {
1153 selectDefaultAddAssignKernel( C, A, B );
1154 }
1156 //**********************************************************************************************
1157
1158 //**Optimized addition assignment to dense matrices (large matrices)****************************
1173 template< typename MT3 // Type of the left-hand side target matrix
1174 , typename MT4 // Type of the left-hand side matrix operand
1175 , typename MT5 > // Type of the right-hand side matrix operand
1176 static inline auto selectLargeAddAssignKernel( MT3& C, const MT4& A, const MT5& B )
1177 -> EnableIf_t< UseOptimizedKernel_v<MT3,MT4,MT5> >
1178 {
1180
1181 const ForwardFunctor fwd;
1182
1183 const OppositeType_t<MT4> tmp( serial( A ) );
1184 addAssign( C, fwd( tmp * B ) );
1185 }
1187 //**********************************************************************************************
1188
1189 //**Restructuring addition assignment to row-major matrices*************************************
1204 template< typename MT // Type of the target matrix
1205 , bool SO > // Storage order of the target matrix
1206 friend inline auto addAssign( Matrix<MT,SO>& lhs, const TSMatDMatMultExpr& rhs )
1207 -> EnableIf_t< CanExploitSymmetry_v<MT,MT1,MT2> >
1208 {
1210
1212
1213 BLAZE_INTERNAL_ASSERT( (*lhs).rows() == rhs.rows() , "Invalid number of rows" );
1214 BLAZE_INTERNAL_ASSERT( (*lhs).columns() == rhs.columns(), "Invalid number of columns" );
1215
1216 const ForwardFunctor fwd;
1217
1218 addAssign( *lhs, fwd( trans( rhs.lhs_ ) * rhs.rhs_ ) );
1219 }
1221 //**********************************************************************************************
1222
1223 //**Addition assignment to sparse matrices******************************************************
1224 // No special implementation for the addition assignment to sparse matrices.
1225 //**********************************************************************************************
1226
1227 //**Subtraction assignment to dense matrices****************************************************
1240 template< typename MT // Type of the target dense matrix
1241 , bool SO > // Storage order of the target dense matrix
1242 friend inline auto subAssign( DenseMatrix<MT,SO>& lhs, const TSMatDMatMultExpr& rhs )
1243 -> DisableIf_t< CanExploitSymmetry_v<MT,MT1,MT2> >
1244 {
1246
1247 BLAZE_INTERNAL_ASSERT( (*lhs).rows() == rhs.rows() , "Invalid number of rows" );
1248 BLAZE_INTERNAL_ASSERT( (*lhs).columns() == rhs.columns(), "Invalid number of columns" );
1249
1250 LT A( serial( rhs.lhs_ ) ); // Evaluation of the right-hand side sparse matrix operand
1251 RT B( serial( rhs.rhs_ ) ); // Evaluation of the left-hand side dense matrix operand
1252
1253 BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
1254 BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
1255 BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
1256 BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
1257 BLAZE_INTERNAL_ASSERT( A.rows() == (*lhs).rows() , "Invalid number of rows" );
1258 BLAZE_INTERNAL_ASSERT( B.columns() == (*lhs).columns() , "Invalid number of columns" );
1259
1260 TSMatDMatMultExpr::selectSubAssignKernel( *lhs, A, B );
1261 }
1263 //**********************************************************************************************
1264
1265 //**Subtraction assignment to dense matrices (kernel selection)*********************************
1276 template< typename MT3 // Type of the left-hand side target matrix
1277 , typename MT4 // Type of the left-hand side matrix operand
1278 , typename MT5 > // Type of the right-hand side matrix operand
1279 static inline void selectSubAssignKernel( MT3& C, const MT4& A, const MT5& B )
1280 {
1281 const size_t size( C.rows() * C.columns() );
1282
1283 if( ( IsRowMajorMatrix_v<MT3> && size < TSMATDMATMULT_THRESHOLD ) ||
1284 ( IsColumnMajorMatrix_v<MT3> && size < 625UL ) )
1285 selectSmallSubAssignKernel( C, A, B );
1286 else
1287 selectLargeSubAssignKernel( C, A, B );
1288 }
1290 //**********************************************************************************************
1291
1292 //**Default subtraction assignment to dense matrices********************************************
1307 template< typename MT3 // Type of the left-hand side target matrix
1308 , typename MT4 // Type of the left-hand side matrix operand
1309 , typename MT5 > // Type of the right-hand side matrix operand
1310 static inline void selectDefaultSubAssignKernel( MT3& C, const MT4& A, const MT5& B )
1311 {
1312 if( IsDiagonal_v<MT5> )
1313 {
1314 for( size_t i=0UL; i<A.columns(); ++i )
1315 {
1316 const auto end( A.end(i) );
1317 auto element( A.begin(i) );
1318
1319 for( ; element!=end; ++element ) {
1320 C(element->index(),i) -= element->value() * B(i,i);
1321 }
1322 }
1323 }
1324 else
1325 {
1326 const size_t block( IsRowMajorMatrix_v<MT3> ? 256UL : 8UL );
1327
1328 for( size_t jj=0UL; jj<B.columns(); jj+=block )
1329 {
1330 const size_t jpos( ( jj+block > B.columns() )?( B.columns() ):( jj+block ) );
1331
1332 for( size_t i=0UL; i<A.columns(); ++i )
1333 {
1334 const auto end( A.end(i) );
1335 auto element( A.begin(i) );
1336
1337 for( ; element!=end; ++element )
1338 {
1339 const size_t i1( element->index() );
1340
1341 const size_t jbegin( ( IsUpper_v<MT5> )
1342 ?( ( UPP )
1343 ?( max( i1, IsStrictlyUpper_v<MT5> ? i+1UL : i, jj ) )
1344 :( max( IsStrictlyUpper_v<MT5> ? i+1UL : i, jj ) ) )
1345 :( UPP ? max(i1,jj) : jj ) );
1346 const size_t jend( ( IsLower_v<MT5> )
1347 ?( ( LOW )
1348 ?( min( i1+1UL, IsStrictlyLower_v<MT5> ? i : i+1UL, jpos ) )
1349 :( min( IsStrictlyLower_v<MT5> ? i : i+1UL, jpos ) ) )
1350 :( LOW ? min(i1+1UL,jpos) : jpos ) );
1351
1352 if( jbegin >= jend )
1353 continue;
1354
1355 for( size_t j=jbegin; j<jend; ++j ) {
1356 C(i1,j) -= element->value() * B(i,j);
1357 }
1358 }
1359 }
1360 }
1361 }
1362 }
1364 //**********************************************************************************************
1365
1366 //**Default subtraction assignment to dense matrices (small matrices)***************************
1380 template< typename MT3 // Type of the left-hand side target matrix
1381 , typename MT4 // Type of the left-hand side matrix operand
1382 , typename MT5 > // Type of the right-hand side matrix operand
1383 static inline auto selectSmallSubAssignKernel( MT3& C, const MT4& A, const MT5& B )
1384 -> EnableIf_t< UseDefaultKernel_v<MT3,MT4,MT5> >
1385 {
1386 selectDefaultSubAssignKernel( C, A, B );
1387 }
1389 //**********************************************************************************************
1390
1391 //**Optimized subtraction assignment to dense matrices (small matrices)*************************
1406 template< typename MT3 // Type of the left-hand side target matrix
1407 , typename MT4 // Type of the left-hand side matrix operand
1408 , typename MT5 > // Type of the right-hand side matrix operand
1409 static inline auto selectSmallSubAssignKernel( MT3& C, const MT4& A, const MT5& B )
1410 -> EnableIf_t< UseOptimizedKernel_v<MT3,MT4,MT5> >
1411 {
1412 const size_t block( ( IsRowMajorMatrix_v<MT3> )?( 256UL ):( 8UL ) );
1413
1414 for( size_t jj=0UL; jj<B.columns(); jj+=block )
1415 {
1416 const size_t jpos( ( jj+block > B.columns() )?( B.columns() ):( jj+block ) );
1417
1418 for( size_t i=0UL; i<A.columns(); ++i )
1419 {
1420 const auto end( A.end(i) );
1421 auto element( A.begin(i) );
1422
1423 const size_t nonzeros( A.nonZeros(i) );
1424 const size_t kpos( prevMultiple( nonzeros, 4UL ) );
1425 BLAZE_INTERNAL_ASSERT( kpos <= nonzeros, "Invalid end calculation" );
1426
1427 for( size_t k=0UL; k<kpos; k+=4UL )
1428 {
1429 const size_t i1( element->index() );
1430 const ET1 v1( element->value() );
1431 ++element;
1432 const size_t i2( element->index() );
1433 const ET1 v2( element->value() );
1434 ++element;
1435 const size_t i3( element->index() );
1436 const ET1 v3( element->value() );
1437 ++element;
1438 const size_t i4( element->index() );
1439 const ET1 v4( element->value() );
1440 ++element;
1441
1442 BLAZE_INTERNAL_ASSERT( i1 < i2 && i2 < i3 && i3 < i4, "Invalid sparse matrix index detected" );
1443
1444 const size_t jbegin( ( IsUpper_v<MT5> )
1445 ?( ( UPP )
1446 ?( max( i1, IsStrictlyUpper_v<MT5> ? i+1UL : i, jj ) )
1447 :( max( IsStrictlyUpper_v<MT5> ? i+1UL : i, jj ) ) )
1448 :( UPP ? max(i1,jj) : jj ) );
1449 const size_t jend( ( IsLower_v<MT5> )
1450 ?( ( LOW )
1451 ?( min( i4+1UL, IsStrictlyLower_v<MT5> ? i : i+1UL, jpos ) )
1452 :( min( IsStrictlyLower_v<MT5> ? i : i+1UL, jpos ) ) )
1453 :( LOW ? min(i4+1UL,jpos) : jpos ) );
1454
1455 if( jbegin >= jend )
1456 continue;
1457
1458 for( size_t j=jbegin; j<jend; ++j ) {
1459 C(i1,j) -= v1 * B(i,j);
1460 C(i2,j) -= v2 * B(i,j);
1461 C(i3,j) -= v3 * B(i,j);
1462 C(i4,j) -= v4 * B(i,j);
1463 }
1464 }
1465
1466 for( ; element!=end; ++element )
1467 {
1468 const size_t i1( element->index() );
1469
1470 const size_t jbegin( ( IsUpper_v<MT5> )
1471 ?( ( UPP )
1472 ?( max( i1, IsStrictlyUpper_v<MT5> ? i+1UL : i, jj ) )
1473 :( max( IsStrictlyUpper_v<MT5> ? i+1UL : i, jj ) ) )
1474 :( UPP ? max(i1,jj) : jj ) );
1475 const size_t jend( ( IsLower_v<MT5> )
1476 ?( ( LOW )
1477 ?( min( i1+1UL, IsStrictlyLower_v<MT5> ? i : i+1UL, jpos ) )
1478 :( min( IsStrictlyLower_v<MT5> ? i : i+1UL, jpos ) ) )
1479 :( LOW ? min(i1+1UL,jpos) : jpos ) );
1480
1481 if( jbegin >= jend )
1482 continue;
1483
1484 for( size_t j=jbegin; j<jend; ++j ) {
1485 C(i1,j) -= element->value() * B(i,j);
1486 }
1487 }
1488 }
1489 }
1490 }
1492 //**********************************************************************************************
1493
1494 //**Default subtraction assignment to dense matrices (large matrices)***************************
1508 template< typename MT3 // Type of the left-hand side target matrix
1509 , typename MT4 // Type of the left-hand side matrix operand
1510 , typename MT5 > // Type of the right-hand side matrix operand
1511 static inline auto selectLargeSubAssignKernel( MT3& C, const MT4& A, const MT5& B )
1512 -> EnableIf_t< UseDefaultKernel_v<MT3,MT4,MT5> >
1513 {
1514 selectDefaultSubAssignKernel( C, A, B );
1515 }
1517 //**********************************************************************************************
1518
1519 //**Optimized subtraction assignment to dense matrices (large matrices)*************************
1534 template< typename MT3 // Type of the left-hand side target matrix
1535 , typename MT4 // Type of the left-hand side matrix operand
1536 , typename MT5 > // Type of the right-hand side matrix operand
1537 static inline auto selectLargeSubAssignKernel( MT3& C, const MT4& A, const MT5& B )
1538 -> EnableIf_t< UseOptimizedKernel_v<MT3,MT4,MT5> >
1539 {
1541
1542 const ForwardFunctor fwd;
1543
1544 const OppositeType_t<MT4> tmp( serial( A ) );
1545 subAssign( C, fwd( tmp * B ) );
1546 }
1548 //**********************************************************************************************
1549
1550 //**Restructuring subtraction assignment to row-major matrices**********************************
1565 template< typename MT // Type of the target matrix
1566 , bool SO > // Storage order of the target matrix
1567 friend inline auto subAssign( Matrix<MT,SO>& lhs, const TSMatDMatMultExpr& rhs )
1568 -> EnableIf_t< CanExploitSymmetry_v<MT,MT1,MT2> >
1569 {
1571
1573
1574 BLAZE_INTERNAL_ASSERT( (*lhs).rows() == rhs.rows() , "Invalid number of rows" );
1575 BLAZE_INTERNAL_ASSERT( (*lhs).columns() == rhs.columns(), "Invalid number of columns" );
1576
1577 const ForwardFunctor fwd;
1578
1579 subAssign( *lhs, fwd( trans( rhs.lhs_ ) * rhs.rhs_ ) );
1580 }
1582 //**********************************************************************************************
1583
1584 //**Subtraction assignment to sparse matrices***************************************************
1585 // No special implementation for the subtraction assignment to sparse matrices.
1586 //**********************************************************************************************
1587
1588 //**Schur product assignment to dense matrices**************************************************
1601 template< typename MT // Type of the target dense matrix
1602 , bool SO > // Storage order of the target dense matrix
1603 friend inline void schurAssign( DenseMatrix<MT,SO>& lhs, const TSMatDMatMultExpr& rhs )
1604 {
1606
1610
1611 BLAZE_INTERNAL_ASSERT( (*lhs).rows() == rhs.rows() , "Invalid number of rows" );
1612 BLAZE_INTERNAL_ASSERT( (*lhs).columns() == rhs.columns(), "Invalid number of columns" );
1613
1614 const ResultType tmp( serial( rhs ) );
1615 schurAssign( *lhs, tmp );
1616 }
1618 //**********************************************************************************************
1619
1620 //**Schur product assignment to sparse matrices*************************************************
1621 // No special implementation for the Schur product assignment to sparse matrices.
1622 //**********************************************************************************************
1623
1624 //**Multiplication assignment to dense matrices*************************************************
1625 // No special implementation for the multiplication assignment to dense matrices.
1626 //**********************************************************************************************
1627
1628 //**Multiplication assignment to sparse matrices************************************************
1629 // No special implementation for the multiplication assignment to sparse matrices.
1630 //**********************************************************************************************
1631
1632 //**SMP assignment to dense matrices************************************************************
1648 template< typename MT // Type of the target dense matrix
1649 , bool SO > // Storage order of the target dense matrix
1650 friend inline auto smpAssign( DenseMatrix<MT,SO>& lhs, const TSMatDMatMultExpr& rhs )
1651 -> EnableIf_t< IsEvaluationRequired_v<MT,MT1,MT2> >
1652 {
1654
1655 BLAZE_INTERNAL_ASSERT( (*lhs).rows() == rhs.rows() , "Invalid number of rows" );
1656 BLAZE_INTERNAL_ASSERT( (*lhs).columns() == rhs.columns(), "Invalid number of columns" );
1657
1658 LT A( rhs.lhs_ ); // Evaluation of the right-hand side sparse matrix operand
1659 RT B( rhs.rhs_ ); // Evaluation of the left-hand side dense matrix operand
1660
1661 BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
1662 BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
1663 BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
1664 BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
1665 BLAZE_INTERNAL_ASSERT( A.rows() == (*lhs).rows() , "Invalid number of rows" );
1666 BLAZE_INTERNAL_ASSERT( B.columns() == (*lhs).columns() , "Invalid number of columns" );
1667
1668 smpAssign( *lhs, A * B );
1669 }
1671 //**********************************************************************************************
1672
1673 //**SMP assignment to sparse matrices***********************************************************
1689 template< typename MT // Type of the target sparse matrix
1690 , bool SO > // Storage order of the target sparse matrix
1691 friend inline auto smpAssign( SparseMatrix<MT,SO>& lhs, const TSMatDMatMultExpr& rhs )
1692 -> EnableIf_t< IsEvaluationRequired_v<MT,MT1,MT2> >
1693 {
1695
1696 using TmpType = If_t< SO, OppositeType, ResultType >;
1697
1704
1705 BLAZE_INTERNAL_ASSERT( (*lhs).rows() == rhs.rows() , "Invalid number of rows" );
1706 BLAZE_INTERNAL_ASSERT( (*lhs).columns() == rhs.columns(), "Invalid number of columns" );
1707
1708 const ForwardFunctor fwd;
1709
1710 const TmpType tmp( rhs );
1711 smpAssign( *lhs, fwd( tmp ) );
1712 }
1714 //**********************************************************************************************
1715
1716 //**Restructuring SMP assignment to row-major matrices******************************************
1731 template< typename MT // Type of the target matrix
1732 , bool SO > // Storage order of the target matrix
1733 friend inline auto smpAssign( Matrix<MT,SO>& lhs, const TSMatDMatMultExpr& rhs )
1734 -> EnableIf_t< CanExploitSymmetry_v<MT,MT1,MT2> >
1735 {
1737
1738 BLAZE_INTERNAL_ASSERT( (*lhs).rows() == rhs.rows() , "Invalid number of rows" );
1739 BLAZE_INTERNAL_ASSERT( (*lhs).columns() == rhs.columns(), "Invalid number of columns" );
1740
1741 const ForwardFunctor fwd;
1742
1743 smpAssign( *lhs, fwd( trans( rhs.lhs_ ) * rhs.rhs_ ) );
1744 }
1746 //**********************************************************************************************
1747
1748 //**SMP addition assignment to dense matrices***************************************************
1764 template< typename MT // Type of the target dense matrix
1765 , bool SO > // Storage order of the target dense matrix
1766 friend inline auto smpAddAssign( DenseMatrix<MT,SO>& lhs, const TSMatDMatMultExpr& rhs )
1767 -> EnableIf_t< IsEvaluationRequired_v<MT,MT1,MT2> >
1768 {
1770
1771 BLAZE_INTERNAL_ASSERT( (*lhs).rows() == rhs.rows() , "Invalid number of rows" );
1772 BLAZE_INTERNAL_ASSERT( (*lhs).columns() == rhs.columns(), "Invalid number of columns" );
1773
1774 LT A( rhs.lhs_ ); // Evaluation of the right-hand side sparse matrix operand
1775 RT B( rhs.rhs_ ); // Evaluation of the left-hand side dense matrix operand
1776
1777 BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
1778 BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
1779 BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
1780 BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
1781 BLAZE_INTERNAL_ASSERT( A.rows() == (*lhs).rows() , "Invalid number of rows" );
1782 BLAZE_INTERNAL_ASSERT( B.columns() == (*lhs).columns() , "Invalid number of columns" );
1783
1784 smpAddAssign( *lhs, A * B );
1785 }
1787 //**********************************************************************************************
1788
1789 //**Restructuring SMP addition assignment to row-major matrices*********************************
1804 template< typename MT // Type of the target matrix
1805 , bool SO > // Storage order of the target matrix
1806 friend inline auto smpAddAssign( Matrix<MT,SO>& lhs, const TSMatDMatMultExpr& rhs )
1807 -> EnableIf_t< CanExploitSymmetry_v<MT,MT1,MT2> >
1808 {
1810
1811 BLAZE_INTERNAL_ASSERT( (*lhs).rows() == rhs.rows() , "Invalid number of rows" );
1812 BLAZE_INTERNAL_ASSERT( (*lhs).columns() == rhs.columns(), "Invalid number of columns" );
1813
1814 const ForwardFunctor fwd;
1815
1816 smpAddAssign( *lhs, fwd( trans( rhs.lhs_ ) * rhs.rhs_ ) );
1817 }
1819 //**********************************************************************************************
1820
1821 //**SMP addition assignment to sparse matrices**************************************************
1822 // No special implementation for the SMP addition assignment to sparse matrices.
1823 //**********************************************************************************************
1824
1825 //**SMP subtraction assignment to dense matrices************************************************
1841 template< typename MT // Type of the target dense matrix
1842 , bool SO > // Storage order of the target dense matrix
1843 friend inline auto smpSubAssign( DenseMatrix<MT,SO>& lhs, const TSMatDMatMultExpr& rhs )
1844 -> EnableIf_t< IsEvaluationRequired_v<MT,MT1,MT2> >
1845 {
1847
1848 BLAZE_INTERNAL_ASSERT( (*lhs).rows() == rhs.rows() , "Invalid number of rows" );
1849 BLAZE_INTERNAL_ASSERT( (*lhs).columns() == rhs.columns(), "Invalid number of columns" );
1850
1851 LT A( rhs.lhs_ ); // Evaluation of the right-hand side sparse matrix operand
1852 RT B( rhs.rhs_ ); // Evaluation of the left-hand side dense matrix operand
1853
1854 BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
1855 BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
1856 BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
1857 BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
1858 BLAZE_INTERNAL_ASSERT( A.rows() == (*lhs).rows() , "Invalid number of rows" );
1859 BLAZE_INTERNAL_ASSERT( B.columns() == (*lhs).columns() , "Invalid number of columns" );
1860
1861 smpSubAssign( *lhs, A * B );
1862 }
1864 //**********************************************************************************************
1865
1866 //**Restructuring SMP subtraction assignment to row-major matrices******************************
1881 template< typename MT // Type of the target matrix
1882 , bool SO > // Storage order of the target matrix
1883 friend inline auto smpSubAssign( Matrix<MT,SO>& lhs, const TSMatDMatMultExpr& rhs )
1884 -> EnableIf_t< CanExploitSymmetry_v<MT,MT1,MT2> >
1885 {
1887
1888 BLAZE_INTERNAL_ASSERT( (*lhs).rows() == rhs.rows() , "Invalid number of rows" );
1889 BLAZE_INTERNAL_ASSERT( (*lhs).columns() == rhs.columns(), "Invalid number of columns" );
1890
1891 const ForwardFunctor fwd;
1892
1893 smpSubAssign( *lhs, fwd( trans( rhs.lhs_ ) * rhs.rhs_ ) );
1894 }
1896 //**********************************************************************************************
1897
1898 //**SMP subtraction assignment to sparse matrices***********************************************
1899 // No special implementation for the SMP subtraction assignment to sparse matrices.
1900 //**********************************************************************************************
1901
1902 //**SMP Schur product assignment to dense matrices**********************************************
1915 template< typename MT // Type of the target dense matrix
1916 , bool SO > // Storage order of the target dense matrix
1917 friend inline void smpSchurAssign( DenseMatrix<MT,SO>& lhs, const TSMatDMatMultExpr& rhs )
1918 {
1920
1924
1925 BLAZE_INTERNAL_ASSERT( (*lhs).rows() == rhs.rows() , "Invalid number of rows" );
1926 BLAZE_INTERNAL_ASSERT( (*lhs).columns() == rhs.columns(), "Invalid number of columns" );
1927
1928 const ResultType tmp( rhs );
1929 smpSchurAssign( *lhs, tmp );
1930 }
1932 //**********************************************************************************************
1933
1934 //**SMP Schur product assignment to sparse matrices*********************************************
1935 // No special implementation for the SMP Schur product assignment to sparse matrices.
1936 //**********************************************************************************************
1937
1938 //**SMP multiplication assignment to dense matrices*********************************************
1939 // No special implementation for the SMP multiplication assignment to dense matrices.
1940 //**********************************************************************************************
1941
1942 //**SMP multiplication assignment to sparse matrices********************************************
1943 // No special implementation for the SMP multiplication assignment to sparse matrices.
1944 //**********************************************************************************************
1945
1946 //**Compile time checks*************************************************************************
1955 //**********************************************************************************************
1956};
1957//*************************************************************************************************
1958
1959
1960
1961
1962//=================================================================================================
1963//
1964// GLOBAL BINARY ARITHMETIC OPERATORS
1965//
1966//=================================================================================================
1967
1968//*************************************************************************************************
1981template< typename MT1 // Type of the left-hand side dense matrix
1982 , typename MT2 // Type of the right-hand side sparse matrix
1983 , DisableIf_t< ( IsIdentity_v<MT1> &&
1984 IsSame_v< ElementType_t<MT1>, ElementType_t<MT2> > ) ||
1985 IsZero_v<MT1> >* = nullptr >
1986inline const TSMatDMatMultExpr<MT1,MT2,false,false,false,false>
1987 tsmatdmatmult( const SparseMatrix<MT1,true>& lhs, const DenseMatrix<MT2,false>& rhs )
1988{
1990
1991 BLAZE_INTERNAL_ASSERT( (*lhs).columns() == (*rhs).rows(), "Invalid matrix sizes" );
1992
1993 return TSMatDMatMultExpr<MT1,MT2,false,false,false,false>( *lhs, *rhs );
1994}
1996//*************************************************************************************************
1997
1998
1999//*************************************************************************************************
2013template< typename MT1 // Type of the left-hand side sparse matrix
2014 , typename MT2 // Type of the right-hand side dense matrix
2015 , EnableIf_t< IsIdentity_v<MT1> &&
2016 IsSame_v< ElementType_t<MT1>, ElementType_t<MT2> > >* = nullptr >
2017inline const MT2&
2018 tsmatdmatmult( const SparseMatrix<MT1,true>& lhs, const DenseMatrix<MT2,false>& rhs )
2019{
2021
2022 MAYBE_UNUSED( lhs );
2023
2024 BLAZE_INTERNAL_ASSERT( (*lhs).columns() == (*rhs).rows(), "Invalid matrix sizes" );
2025
2026 return (*rhs);
2027}
2029//*************************************************************************************************
2030
2031
2032//*************************************************************************************************
2045template< typename MT1 // Type of the left-hand side dense matrix
2046 , typename MT2 // Type of the right-hand side sparse matrix
2047 , EnableIf_t< IsZero_v<MT1> >* = nullptr >
2048inline decltype(auto)
2049 tsmatdmatmult( const SparseMatrix<MT1,true>& lhs, const DenseMatrix<MT2,false>& rhs )
2050{
2052
2053 BLAZE_INTERNAL_ASSERT( (*lhs).columns() == (*rhs).rows(), "Invalid matrix sizes" );
2054
2055 using ReturnType = const MultTrait_t< ResultType_t<MT1>, ResultType_t<MT2> >;
2056
2059
2060 return ReturnType( (*lhs).rows(), (*rhs).columns() );
2061}
2063//*************************************************************************************************
2064
2065
2066//*************************************************************************************************
2097template< typename MT1 // Type of the left-hand side sparse matrix
2098 , typename MT2 > // Type of the right-hand side dense matrix
2099inline decltype(auto)
2100 operator*( const SparseMatrix<MT1,true>& lhs, const DenseMatrix<MT2,false>& rhs )
2101{
2103
2104 if( (*lhs).columns() != (*rhs).rows() ) {
2105 BLAZE_THROW_INVALID_ARGUMENT( "Matrix sizes do not match" );
2106 }
2107
2108 return tsmatdmatmult( *lhs, *rhs );
2109}
2110//*************************************************************************************************
2111
2112
2113
2114
2115//=================================================================================================
2116//
2117// GLOBAL FUNCTIONS
2118//
2119//=================================================================================================
2120
2121//*************************************************************************************************
2147template< typename MT1 // Type of the left-hand side dense matrix
2148 , typename MT2 // Type of the right-hand side dense matrix
2149 , bool SF // Symmetry flag
2150 , bool HF // Hermitian flag
2151 , bool LF // Lower flag
2152 , bool UF > // Upper flag
2153inline decltype(auto) declsym( const TSMatDMatMultExpr<MT1,MT2,SF,HF,LF,UF>& dm )
2154{
2156
2157 if( !isSquare( dm ) ) {
2158 BLAZE_THROW_INVALID_ARGUMENT( "Invalid symmetric matrix specification" );
2159 }
2160
2161 using ReturnType = const TSMatDMatMultExpr<MT1,MT2,true,HF,LF,UF>;
2162 return ReturnType( dm.leftOperand(), dm.rightOperand() );
2163}
2165//*************************************************************************************************
2166
2167
2168//*************************************************************************************************
2194template< typename MT1 // Type of the left-hand side dense matrix
2195 , typename MT2 // Type of the right-hand side dense matrix
2196 , bool SF // Symmetry flag
2197 , bool HF // Hermitian flag
2198 , bool LF // Lower flag
2199 , bool UF > // Upper flag
2200inline decltype(auto) declherm( const TSMatDMatMultExpr<MT1,MT2,SF,HF,LF,UF>& dm )
2201{
2203
2204 if( !isSquare( dm ) ) {
2205 BLAZE_THROW_INVALID_ARGUMENT( "Invalid Hermitian matrix specification" );
2206 }
2207
2208 using ReturnType = const TSMatDMatMultExpr<MT1,MT2,SF,true,LF,UF>;
2209 return ReturnType( dm.leftOperand(), dm.rightOperand() );
2210}
2212//*************************************************************************************************
2213
2214
2215//*************************************************************************************************
2241template< typename MT1 // Type of the left-hand side dense matrix
2242 , typename MT2 // Type of the right-hand side dense matrix
2243 , bool SF // Symmetry flag
2244 , bool HF // Hermitian flag
2245 , bool LF // Lower flag
2246 , bool UF > // Upper flag
2247inline decltype(auto) decllow( const TSMatDMatMultExpr<MT1,MT2,SF,HF,LF,UF>& dm )
2248{
2250
2251 if( !isSquare( dm ) ) {
2252 BLAZE_THROW_INVALID_ARGUMENT( "Invalid lower matrix specification" );
2253 }
2254
2255 using ReturnType = const TSMatDMatMultExpr<MT1,MT2,SF,HF,true,UF>;
2256 return ReturnType( dm.leftOperand(), dm.rightOperand() );
2257}
2259//*************************************************************************************************
2260
2261
2262//*************************************************************************************************
2288template< typename MT1 // Type of the left-hand side dense matrix
2289 , typename MT2 // Type of the right-hand side dense matrix
2290 , bool SF // Symmetry flag
2291 , bool HF // Hermitian flag
2292 , bool UF > // Upper flag
2293inline decltype(auto) declunilow( const TSMatDMatMultExpr<MT1,MT2,SF,HF,false,UF>& dm )
2294{
2296
2297 if( !isSquare( dm ) ) {
2298 BLAZE_THROW_INVALID_ARGUMENT( "Invalid unilower matrix specification" );
2299 }
2300
2301 return declunilow( decllow( *dm ) );
2302}
2304//*************************************************************************************************
2305
2306
2307//*************************************************************************************************
2333template< typename MT1 // Type of the left-hand side dense matrix
2334 , typename MT2 // Type of the right-hand side dense matrix
2335 , bool SF // Symmetry flag
2336 , bool HF // Hermitian flag
2337 , bool UF > // Upper flag
2338inline decltype(auto) declstrlow( const TSMatDMatMultExpr<MT1,MT2,SF,HF,false,UF>& dm )
2339{
2341
2342 if( !isSquare( dm ) ) {
2343 BLAZE_THROW_INVALID_ARGUMENT( "Invalid strictly lower matrix specification" );
2344 }
2345
2346 return declstrlow( decllow( *dm ) );
2347}
2349//*************************************************************************************************
2350
2351
2352//*************************************************************************************************
2378template< typename MT1 // Type of the left-hand side dense matrix
2379 , typename MT2 // Type of the right-hand side dense matrix
2380 , bool SF // Symmetry flag
2381 , bool HF // Hermitian flag
2382 , bool LF // Lower flag
2383 , bool UF > // Upper flag
2384inline decltype(auto) declupp( const TSMatDMatMultExpr<MT1,MT2,SF,HF,LF,UF>& dm )
2385{
2387
2388 if( !isSquare( dm ) ) {
2389 BLAZE_THROW_INVALID_ARGUMENT( "Invalid upper matrix specification" );
2390 }
2391
2392 using ReturnType = const TSMatDMatMultExpr<MT1,MT2,SF,HF,LF,true>;
2393 return ReturnType( dm.leftOperand(), dm.rightOperand() );
2394}
2396//*************************************************************************************************
2397
2398
2399//*************************************************************************************************
2425template< typename MT1 // Type of the left-hand side dense matrix
2426 , typename MT2 // Type of the right-hand side dense matrix
2427 , bool SF // Symmetry flag
2428 , bool HF // Hermitian flag
2429 , bool LF > // Lower flag
2430inline decltype(auto) decluniupp( const TSMatDMatMultExpr<MT1,MT2,SF,HF,LF,false>& dm )
2431{
2433
2434 if( !isSquare( dm ) ) {
2435 BLAZE_THROW_INVALID_ARGUMENT( "Invalid uniupper matrix specification" );
2436 }
2437
2438 return decluniupp( declupp( *dm ) );
2439}
2441//*************************************************************************************************
2442
2443
2444//*************************************************************************************************
2470template< typename MT1 // Type of the left-hand side dense matrix
2471 , typename MT2 // Type of the right-hand side dense matrix
2472 , bool SF // Symmetry flag
2473 , bool HF // Hermitian flag
2474 , bool LF > // Lower flag
2475inline decltype(auto) declstrupp( const TSMatDMatMultExpr<MT1,MT2,SF,HF,LF,false>& dm )
2476{
2478
2479 if( !isSquare( dm ) ) {
2480 BLAZE_THROW_INVALID_ARGUMENT( "Invalid strictly upper matrix specification" );
2481 }
2482
2483 return declstrupp( declupp( *dm ) );
2484}
2486//*************************************************************************************************
2487
2488
2489//*************************************************************************************************
2515template< typename MT1 // Type of the left-hand side dense matrix
2516 , typename MT2 // Type of the right-hand side dense matrix
2517 , bool SF // Symmetry flag
2518 , bool HF // Hermitian flag
2519 , bool LF // Lower flag
2520 , bool UF > // Upper flag
2521inline decltype(auto) decldiag( const TSMatDMatMultExpr<MT1,MT2,SF,HF,LF,UF>& dm )
2522{
2524
2525 if( !isSquare( dm ) ) {
2526 BLAZE_THROW_INVALID_ARGUMENT( "Invalid diagonal matrix specification" );
2527 }
2528
2529 using ReturnType = const TSMatDMatMultExpr<MT1,MT2,SF,HF,true,true>;
2530 return ReturnType( dm.leftOperand(), dm.rightOperand() );
2531}
2533//*************************************************************************************************
2534
2535
2536
2537
2538//=================================================================================================
2539//
2540// SIZE SPECIALIZATIONS
2541//
2542//=================================================================================================
2543
2544//*************************************************************************************************
2546template< typename MT1, typename MT2, bool SF, bool HF, bool LF, bool UF >
2547struct Size< TSMatDMatMultExpr<MT1,MT2,SF,HF,LF,UF>, 0UL >
2548 : public Size<MT1,0UL>
2549{};
2550
2551template< typename MT1, typename MT2, bool SF, bool HF, bool LF, bool UF >
2552struct Size< TSMatDMatMultExpr<MT1,MT2,SF,HF,LF,UF>, 1UL >
2553 : public Size<MT2,1UL>
2554{};
2556//*************************************************************************************************
2557
2558
2559
2560
2561//=================================================================================================
2562//
2563// ISALIGNED SPECIALIZATIONS
2564//
2565//=================================================================================================
2566
2567//*************************************************************************************************
2569template< typename MT1, typename MT2, bool SF, bool HF, bool LF, bool UF >
2570struct IsAligned< TSMatDMatMultExpr<MT1,MT2,SF,HF,LF,UF> >
2571 : public IsAligned<MT2>
2572{};
2574//*************************************************************************************************
2575
2576} // namespace blaze
2577
2578#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 IsColumnMajorMatrix 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 IsRowMajorMatrix 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 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.
Header file for the prevMultiple shim.
Constraints on the storage order of matrix types.
Constraint on the data type.
Constraint on the data type.
Base class for dense matrices.
Definition: DenseMatrix.h:82
Base class for sparse matrices.
Definition: SparseMatrix.h:77
Expression object for transpose sparse matrix-dense matrix multiplications.
Definition: TSMatDMatMultExpr.h:131
CompositeType_t< MT1 > CT1
Composite type of the left-hand side sparse matrix expression.
Definition: TSMatDMatMultExpr.h:138
bool isAligned() const noexcept
Returns whether the operands of the expression are properly aligned in memory.
Definition: TSMatDMatMultExpr.h:425
TSMatDMatMultExpr(const MT1 &lhs, const MT2 &rhs) noexcept
Constructor for the TSMatDMatMultExpr class.
Definition: TSMatDMatMultExpr.h:281
const ResultType CompositeType
Data type for composite expression templates.
Definition: TSMatDMatMultExpr.h:251
static constexpr bool HERM
Flag for Hermitian matrices.
Definition: TSMatDMatMultExpr.h:154
static constexpr bool UPP
Flag for upper matrices.
Definition: TSMatDMatMultExpr.h:156
ResultType_t< MT2 > RT2
Result type of the right-hand side dense matrix expression.
Definition: TSMatDMatMultExpr.h:135
bool isAliased(const T *alias) const noexcept
Returns whether the expression is aliased with the given address alias.
Definition: TSMatDMatMultExpr.h:415
ReturnType at(size_t i, size_t j) const
Checked access to the matrix elements.
Definition: TSMatDMatMultExpr.h:345
ResultType_t< MT1 > RT1
Result type of the left-hand side sparse matrix expression.
Definition: TSMatDMatMultExpr.h:134
RightOperand rightOperand() const noexcept
Returns the right-hand side dense matrix operand.
Definition: TSMatDMatMultExpr.h:391
CompositeType_t< MT2 > CT2
Composite type of the right-hand side dense matrix expression.
Definition: TSMatDMatMultExpr.h:139
ElementType_t< ResultType > ElementType
Resulting element type.
Definition: TSMatDMatMultExpr.h:249
TransposeType_t< ResultType > TransposeType
Transpose type for expression template evaluations.
Definition: TSMatDMatMultExpr.h:248
static constexpr bool simdEnabled
Compilation switch for the expression template evaluation strategy.
Definition: TSMatDMatMultExpr.h:268
static constexpr bool evaluateLeft
Compilation switch for the composite type of the left-hand side sparse matrix expression.
Definition: TSMatDMatMultExpr.h:144
bool canAlias(const T *alias) const noexcept
Returns whether the expression can alias with the given address alias.
Definition: TSMatDMatMultExpr.h:403
ElementType_t< RT1 > ET1
Element type of the left-hand side dense matrix expression.
Definition: TSMatDMatMultExpr.h:136
RightOperand rhs_
Right-hand side dense matrix of the multiplication expression.
Definition: TSMatDMatMultExpr.h:443
If_t< IsExpression_v< MT2 >, const MT2, const MT2 & > RightOperand
Composite type of the right-hand side dense matrix expression.
Definition: TSMatDMatMultExpr.h:257
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: TSMatDMatMultExpr.h:245
size_t rows() const noexcept
Returns the current number of rows of the matrix.
Definition: TSMatDMatMultExpr.h:361
If_t< evaluateLeft, const RT1, CT1 > LT
Type for the assignment of the left-hand side sparse matrix operand.
Definition: TSMatDMatMultExpr.h:260
static constexpr bool smpAssignable
Compilation switch for the expression template assignment strategy.
Definition: TSMatDMatMultExpr.h:271
ReturnType operator()(size_t i, size_t j) const
2D-access to the matrix elements.
Definition: TSMatDMatMultExpr.h:296
static constexpr bool evaluateRight
Compilation switch for the composite type of the right-hand side dense matrix expression.
Definition: TSMatDMatMultExpr.h:149
static constexpr bool SYM
Flag for symmetric matrices.
Definition: TSMatDMatMultExpr.h:153
size_t columns() const noexcept
Returns the current number of columns of the matrix.
Definition: TSMatDMatMultExpr.h:371
OppositeType_t< ResultType > OppositeType
Result type with opposite storage order for expression template evaluations.
Definition: TSMatDMatMultExpr.h:247
If_t< evaluateRight, const RT2, CT2 > RT
Type for the assignment of the right-hand side dense matrix operand.
Definition: TSMatDMatMultExpr.h:263
LeftOperand leftOperand() const noexcept
Returns the left-hand side transpose sparse matrix operand.
Definition: TSMatDMatMultExpr.h:381
static constexpr bool LOW
Flag for lower matrices.
Definition: TSMatDMatMultExpr.h:155
ElementType_t< RT2 > ET2
Element type of the right-hand side sparse matrix expression.
Definition: TSMatDMatMultExpr.h:137
bool canSMPAssign() const noexcept
Returns whether the expression can be used in SMP assignments.
Definition: TSMatDMatMultExpr.h:435
If_t< IsExpression_v< MT1 >, const MT1, const MT1 & > LeftOperand
Composite type of the left-hand side sparse matrix expression.
Definition: TSMatDMatMultExpr.h:254
LeftOperand lhs_
Left-hand side sparse matrix of the multiplication expression.
Definition: TSMatDMatMultExpr.h:442
const ElementType ReturnType
Return type for expression template evaluations.
Definition: TSMatDMatMultExpr.h:250
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) 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) trans(const DenseMatrix< MT, SO > &dm)
Calculation of the transpose of the given dense matrix.
Definition: DMatTransExpr.h:766
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
BLAZE_ALWAYS_INLINE constexpr auto prevMultiple(T1 value, T2 factor) noexcept
Rounds down an integral value to the previous multiple of a given factor.
Definition: PrevMultiple.h:68
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
constexpr size_t size(const Matrix< MT, SO > &matrix) noexcept
Returns the total number of elements of the matrix.
Definition: Matrix.h:676
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.