Blaze 3.9
TSMatTSMatMultExpr.h
Go to the documentation of this file.
1//=================================================================================================
33//=================================================================================================
34
35#ifndef _BLAZE_MATH_EXPRESSIONS_TSMATTSMATMULTEXPR_H_
36#define _BLAZE_MATH_EXPRESSIONS_TSMATTSMATMULTEXPR_H_
37
38
39//*************************************************************************************************
40// Includes
41//*************************************************************************************************
42
43#include <algorithm>
44#include <blaze/math/Aliases.h>
57#include <blaze/math/Infinity.h>
79#include <blaze/util/Assert.h>
80#include <blaze/util/EnableIf.h>
84#include <blaze/util/mpl/If.h>
86#include <blaze/util/Types.h>
88
89
90namespace blaze {
91
92//=================================================================================================
93//
94// CLASS TSMATTSMATMULTEXPR
95//
96//=================================================================================================
97
98//*************************************************************************************************
105template< typename MT1 // Type of the left-hand side sparse matrix
106 , typename MT2 > // Type of the right-hand side sparse matrix
108 : public MatMatMultExpr< SparseMatrix< TSMatTSMatMultExpr<MT1,MT2>, true > >
109 , private Computation
110{
111 private:
112 //**Type definitions****************************************************************************
117 //**********************************************************************************************
118
119 //**********************************************************************************************
121 static constexpr bool evaluateLeft = RequiresEvaluation_v<MT1>;
122 //**********************************************************************************************
123
124 //**********************************************************************************************
126 static constexpr bool evaluateRight = RequiresEvaluation_v<MT2>;
127 //**********************************************************************************************
128
129 //**********************************************************************************************
131
136 template< typename T1, typename T2, typename T3 >
137 static constexpr bool CanExploitSymmetry_v =
138 ( IsRowMajorMatrix_v<T1> && IsSymmetric_v<T2> && IsSymmetric_v<T3> );
140 //**********************************************************************************************
141
142 //**********************************************************************************************
144
148 template< typename T1, typename T2, typename T3 >
149 static constexpr bool IsEvaluationRequired_v =
150 ( ( evaluateLeft || evaluateRight ) && !CanExploitSymmetry_v<T1,T2,T3> );
152 //**********************************************************************************************
153
154 public:
155 //**Type definitions****************************************************************************
158
161
166 using ReturnType = const ElementType;
167 using CompositeType = const ResultType;
168
170 using LeftOperand = If_t< IsExpression_v<MT1>, const MT1, const MT1& >;
171
173 using RightOperand = If_t< IsExpression_v<MT2>, const MT2, const MT2& >;
174 //**********************************************************************************************
175
176 //**Compilation flags***************************************************************************
178 static constexpr bool smpAssignable =
179 ( !evaluateLeft && MT1::smpAssignable && !evaluateRight && MT2::smpAssignable );
180 //**********************************************************************************************
181
182 //**Constructor*********************************************************************************
188 inline TSMatTSMatMultExpr( const MT1& lhs, const MT2& rhs ) noexcept
189 : lhs_( lhs ) // Left-hand side sparse matrix of the multiplication expression
190 , rhs_( rhs ) // Right-hand side sparse matrix of the multiplication expression
191 {
192 BLAZE_INTERNAL_ASSERT( lhs.columns() == rhs.rows(), "Invalid matrix sizes" );
193 }
194 //**********************************************************************************************
195
196 //**Access operator*****************************************************************************
203 inline ReturnType operator()( size_t i, size_t j ) const {
204 BLAZE_INTERNAL_ASSERT( i < lhs_.rows() , "Invalid row access index" );
205 BLAZE_INTERNAL_ASSERT( j < rhs_.columns(), "Invalid column access index" );
206
207 if( IsDiagonal_v<MT1> ) {
208 return lhs_(i,i) * rhs_(i,j);
209 }
210 else if( IsDiagonal_v<MT2> ) {
211 return lhs_(i,j) * rhs_(j,j);
212 }
213 else if( IsTriangular_v<MT1> || IsTriangular_v<MT2> ) {
214 const size_t begin( ( IsUpper_v<MT1> )
215 ?( ( IsLower_v<MT2> )
216 ?( max( ( IsStrictlyUpper_v<MT1> ? i+1UL : i )
217 , ( IsStrictlyLower_v<MT2> ? j+1UL : j ) ) )
218 :( IsStrictlyUpper_v<MT1> ? i+1UL : i ) )
219 :( ( IsLower_v<MT2> )
220 ?( IsStrictlyLower_v<MT2> ? j+1UL : j )
221 :( 0UL ) ) );
222 const size_t end( ( IsLower_v<MT1> )
223 ?( ( IsUpper_v<MT2> )
224 ?( min( ( IsStrictlyLower_v<MT1> ? i : i+1UL )
225 , ( IsStrictlyUpper_v<MT2> ? j : j+1UL ) ) )
226 :( IsStrictlyLower_v<MT1> ? i : i+1UL ) )
227 :( ( IsUpper_v<MT2> )
228 ?( IsStrictlyUpper_v<MT2> ? j : j+1UL )
229 :( lhs_.columns() ) ) );
230
231 if( begin >= end ) return ElementType();
232
233 const size_t n( end - begin );
234
235 return subvector( row( lhs_, i, unchecked ), begin, n, unchecked ) *
237 }
238 else {
239 return row( lhs_, i, unchecked ) * column( rhs_, j, unchecked );
240 }
241 }
242 //**********************************************************************************************
243
244 //**At function*********************************************************************************
252 inline ReturnType at( size_t i, size_t j ) const {
253 if( i >= lhs_.rows() ) {
254 BLAZE_THROW_OUT_OF_RANGE( "Invalid row access index" );
255 }
256 if( j >= rhs_.columns() ) {
257 BLAZE_THROW_OUT_OF_RANGE( "Invalid column access index" );
258 }
259 return (*this)(i,j);
260 }
261 //**********************************************************************************************
262
263 //**Rows function*******************************************************************************
268 inline size_t rows() const noexcept {
269 return lhs_.rows();
270 }
271 //**********************************************************************************************
272
273 //**Columns function****************************************************************************
278 inline size_t columns() const noexcept {
279 return rhs_.columns();
280 }
281 //**********************************************************************************************
282
283 //**NonZeros function***************************************************************************
288 constexpr size_t nonZeros() const noexcept {
289 return 0UL;
290 }
291 //**********************************************************************************************
292
293 //**NonZeros function***************************************************************************
299 inline size_t nonZeros( size_t i ) const noexcept {
300 MAYBE_UNUSED( i );
301 return 0UL;
302 }
303 //**********************************************************************************************
304
305 //**Left operand access*************************************************************************
310 inline LeftOperand leftOperand() const noexcept {
311 return lhs_;
312 }
313 //**********************************************************************************************
314
315 //**Right operand access************************************************************************
320 inline RightOperand rightOperand() const noexcept {
321 return rhs_;
322 }
323 //**********************************************************************************************
324
325 //**********************************************************************************************
331 template< typename T >
332 inline bool canAlias( const T* alias ) const noexcept {
333 return ( lhs_.isAliased( alias ) || rhs_.isAliased( alias ) );
334 }
335 //**********************************************************************************************
336
337 //**********************************************************************************************
343 template< typename T >
344 inline bool isAliased( const T* alias ) const noexcept {
345 return ( lhs_.isAliased( alias ) || rhs_.isAliased( alias ) );
346 }
347 //**********************************************************************************************
348
349 //**********************************************************************************************
354 inline bool canSMPAssign() const noexcept {
355 return ( rows() * columns() >= SMP_TSMATTSMATMULT_THRESHOLD );
356 }
357 //**********************************************************************************************
358
359 private:
360 //**Member variables****************************************************************************
363 //**********************************************************************************************
364
365 //**Assignment to dense matrices****************************************************************
378 template< typename MT // Type of the target dense matrix
379 , bool SO > // Storage order of the target dense matrix
380 friend inline auto assign( DenseMatrix<MT,SO>& lhs, const TSMatTSMatMultExpr& rhs )
382 {
384
385 BLAZE_INTERNAL_ASSERT( (*lhs).rows() == rhs.rows() , "Invalid number of rows" );
386 BLAZE_INTERNAL_ASSERT( (*lhs).columns() == rhs.columns(), "Invalid number of columns" );
387
388 CT1 A( serial( rhs.lhs_ ) ); // Evaluation of the left-hand side sparse matrix operand
389 CT2 B( serial( rhs.rhs_ ) ); // Evaluation of the right-hand side sparse matrix operand
390
391 BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
392 BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
393 BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
394 BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
395 BLAZE_INTERNAL_ASSERT( A.rows() == (*lhs).rows() , "Invalid number of rows" );
396 BLAZE_INTERNAL_ASSERT( B.columns() == (*lhs).columns() , "Invalid number of columns" );
397
398 TSMatTSMatMultExpr::selectAssignKernel( *lhs, A, B );
399 }
401 //**********************************************************************************************
402
403 //**Default assignment to dense matrices********************************************************
417 template< typename MT3 // Type of the left-hand side target matrix
418 , typename MT4 // Type of the left-hand side matrix operand
419 , typename MT5 > // Type of the right-hand side matrix operand
420 static inline void selectAssignKernel( MT3& C, const MT4& A, const MT5& B )
421 {
422 for( size_t j=0UL; j<C.columns(); ++j ) {
423 const auto rend( B.end(j) );
424 for( auto relem=B.begin(j); relem!=rend; ++relem ) {
425 const auto lend( A.end( relem->index() ) );
426 for( auto lelem=A.begin( relem->index() ); lelem!=lend; ++lelem )
427 {
429 isDefault( C(lelem->index(),j) ) ) {
430 C(lelem->index(),j) = lelem->value() * relem->value();
431 }
432 else {
433 C(lelem->index(),j) += lelem->value() * relem->value();
434 }
435 }
436 }
437 }
438 }
440 //**********************************************************************************************
441
442 //**Assignment to row-major sparse matrices*****************************************************
455 template< typename MT > // Type of the target sparse matrix
456 friend inline auto assign( SparseMatrix<MT,false>& lhs, const TSMatTSMatMultExpr& rhs )
457 -> DisableIf_t< CanExploitSymmetry_v<MT,MT1,MT2> >
458 {
460
462
463 BLAZE_INTERNAL_ASSERT( (*lhs).rows() == rhs.rows() , "Invalid number of rows" );
464 BLAZE_INTERNAL_ASSERT( (*lhs).columns() == rhs.columns(), "Invalid number of columns" );
465
468
469 const ResultType tmp( serial( rhs ) );
470 (*lhs).reserve( tmp.nonZeros() );
471 assign( *lhs, tmp );
472 }
474 //**********************************************************************************************
475
476 //**Assignment to column-major sparse matrices**************************************************
489 template< typename MT > // Type of the target sparse matrix
490 friend inline void assign( SparseMatrix<MT,true>& lhs, const TSMatTSMatMultExpr& rhs )
491 {
493
494 BLAZE_INTERNAL_ASSERT( (*lhs).rows() == rhs.rows() , "Invalid number of rows" );
495 BLAZE_INTERNAL_ASSERT( (*lhs).columns() == rhs.columns(), "Invalid number of columns" );
496
497 CT1 A( serial( rhs.lhs_ ) ); // Evaluation of the left-hand side sparse matrix operand
498 CT2 B( serial( rhs.rhs_ ) ); // Evaluation of the right-hand side sparse matrix operand
499
500 BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
501 BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
502 BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
503 BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
504 BLAZE_INTERNAL_ASSERT( A.rows() == (*lhs).rows() , "Invalid number of rows" );
505 BLAZE_INTERNAL_ASSERT( B.columns() == (*lhs).columns() , "Invalid number of columns" );
506
507 // (Over-)Estimating the number of non-zero entries in the resulting matrix
508 size_t nonzeros( 0UL );
509
510 for( size_t j=0UL; j<(*lhs).columns(); ++j ) {
511 const auto rend( B.end(j) );
512 for( auto relem=B.begin(j); relem!=rend; ++relem ) {
513 nonzeros += A.nonZeros( relem->index() );
514 }
515 }
516
517 if( nonzeros > (*lhs).rows() * (*lhs).columns() ) {
518 nonzeros = (*lhs).rows() * (*lhs).columns();
519 }
520
521 (*lhs).reserve( nonzeros );
522 nonzeros = 0UL;
523
524 // Performing the matrix-matrix multiplication
525 SmallArray<ElementType,128UL> values ( (*lhs).rows(), ElementType() );
526 SmallArray<bool,128UL> valid ( (*lhs).rows(), false );
527 SmallArray<size_t,128UL> indices( (*lhs).rows(), 0UL );
528 size_t minIndex( inf ), maxIndex( 0UL );
529
530 for( size_t j=0UL; j<(*lhs).columns(); ++j )
531 {
532 const auto rend( B.end(j) );
533 for( auto relem=B.begin(j); relem!=rend; ++relem )
534 {
535 const auto lend( A.end( relem->index() ) );
536 for( auto lelem=A.begin( relem->index() ); lelem!=lend; ++lelem )
537 {
538 if( !valid[lelem->index()] ) {
539 values[lelem->index()] = lelem->value() * relem->value();
540 valid [lelem->index()] = true;
541 indices[nonzeros] = lelem->index();
542 ++nonzeros;
543 if( lelem->index() < minIndex ) minIndex = lelem->index();
544 if( lelem->index() > maxIndex ) maxIndex = lelem->index();
545 }
546 else {
547 values[lelem->index()] += lelem->value() * relem->value();
548 }
549 }
550 }
551
552 BLAZE_INTERNAL_ASSERT( nonzeros <= (*lhs).rows(), "Invalid number of non-zero elements" );
553
554 if( nonzeros > 0UL )
555 {
556 BLAZE_INTERNAL_ASSERT( minIndex <= maxIndex, "Invalid index detected" );
557
558 if( ( nonzeros + nonzeros ) < ( maxIndex - minIndex ) )
559 {
560 std::sort( indices.begin(), indices.begin() + nonzeros );
561
562 for( size_t i=0UL; i<nonzeros; ++i )
563 {
564 const size_t index( indices[i] );
565 if( !isDefault( values[index] ) ) {
566 (*lhs).append( index, j, values[index] );
567 reset( values[index] );
568 }
569
570 reset( valid[index] );
571 }
572 }
573 else {
574 for( size_t i=minIndex; i<=maxIndex; ++i )
575 {
576 if( !isDefault( values[i] ) ) {
577 (*lhs).append( i, j, values[i] );
578 reset( values[i] );
579 }
580
581 reset( valid[i] );
582 }
583 }
584
585 nonzeros = 0UL;
586 minIndex = inf;
587 maxIndex = 0UL;
588 }
589
590 (*lhs).finalize( j );
591 }
592 }
594 //**********************************************************************************************
595
596 //**Restructuring assignment to row-major matrices**********************************************
611 template< typename MT > // Type of the target matrix
612 friend inline auto assign( Matrix<MT,false>& lhs, const TSMatTSMatMultExpr& rhs )
613 -> EnableIf_t< CanExploitSymmetry_v<MT,MT1,MT2> >
614 {
616
618
619 BLAZE_INTERNAL_ASSERT( (*lhs).rows() == rhs.rows() , "Invalid number of rows" );
620 BLAZE_INTERNAL_ASSERT( (*lhs).columns() == rhs.columns(), "Invalid number of columns" );
621
622 assign( *lhs, trans( rhs.lhs_ ) * trans( rhs.rhs_ ) );
623 }
625 //**********************************************************************************************
626
627 //**Addition assignment to dense matrices*******************************************************
640 template< typename MT // Type of the target dense matrix
641 , bool SO > // Storage order of the target dense matarix
642 friend inline auto addAssign( DenseMatrix<MT,SO>& lhs, const TSMatTSMatMultExpr& rhs )
643 -> DisableIf_t< CanExploitSymmetry_v<MT,MT1,MT2> >
644 {
646
647 BLAZE_INTERNAL_ASSERT( (*lhs).rows() == rhs.rows() , "Invalid number of rows" );
648 BLAZE_INTERNAL_ASSERT( (*lhs).columns() == rhs.columns(), "Invalid number of columns" );
649
650 CT1 A( serial( rhs.lhs_ ) ); // Evaluation of the left-hand side sparse matrix operand
651 CT2 B( serial( rhs.rhs_ ) ); // Evaluation of the right-hand side sparse matrix operand
652
653 BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
654 BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
655 BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
656 BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
657 BLAZE_INTERNAL_ASSERT( A.rows() == (*lhs).rows() , "Invalid number of rows" );
658 BLAZE_INTERNAL_ASSERT( B.columns() == (*lhs).columns() , "Invalid number of columns" );
659
660 TSMatTSMatMultExpr::selectAddAssignKernel( *lhs, A, B );
661 }
663 //**********************************************************************************************
664
665 //**Default addition assignment to dense 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 void selectAddAssignKernel( MT3& C, const MT4& A, const MT5& B )
683 {
684 for( size_t j=0UL; j<C.columns(); ++j ) {
685 const auto rend( B.end(j) );
686 for( auto relem=B.begin(j); relem!=rend; ++relem ) {
687 const auto lend( A.end( relem->index() ) );
688 for( auto lelem=A.begin( relem->index() ); lelem!=lend; ++lelem ) {
689 C(lelem->index(),j) += lelem->value() * relem->value();
690 }
691 }
692 }
693 }
695 //**********************************************************************************************
696
697 //**Restructuring addition assignment to row-major matrices*************************************
712 template< typename MT > // Type of the target matrix
713 friend inline auto addAssign( Matrix<MT,false>& lhs, const TSMatTSMatMultExpr& rhs )
714 -> EnableIf_t< CanExploitSymmetry_v<MT,MT1,MT2> >
715 {
717
719
720 BLAZE_INTERNAL_ASSERT( (*lhs).rows() == rhs.rows() , "Invalid number of rows" );
721 BLAZE_INTERNAL_ASSERT( (*lhs).columns() == rhs.columns(), "Invalid number of columns" );
722
723 addAssign( *lhs, trans( rhs.lhs_ ) * trans( rhs.rhs_ ) );
724 }
726 //**********************************************************************************************
727
728 //**Addition assignment to sparse matrices******************************************************
729 // No special implementation for the addition assignment to sparse matrices.
730 //**********************************************************************************************
731
732 //**Subtraction assignment to dense matrices****************************************************
745 template< typename MT // Type of the target dense matrix
746 , bool SO > // Storage order of the target dense matarix
747 friend inline auto subAssign( DenseMatrix<MT,SO>& lhs, const TSMatTSMatMultExpr& rhs )
748 -> DisableIf_t< CanExploitSymmetry_v<MT,MT1,MT2> >
749 {
751
752 BLAZE_INTERNAL_ASSERT( (*lhs).rows() == rhs.rows() , "Invalid number of rows" );
753 BLAZE_INTERNAL_ASSERT( (*lhs).columns() == rhs.columns(), "Invalid number of columns" );
754
755 CT1 A( serial( rhs.lhs_ ) ); // Evaluation of the left-hand side sparse matrix operand
756 CT2 B( serial( rhs.rhs_ ) ); // Evaluation of the right-hand side sparse matrix operand
757
758 BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
759 BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
760 BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
761 BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
762 BLAZE_INTERNAL_ASSERT( A.rows() == (*lhs).rows() , "Invalid number of rows" );
763 BLAZE_INTERNAL_ASSERT( B.columns() == (*lhs).columns() , "Invalid number of columns" );
764
765 TSMatTSMatMultExpr::selectSubAssignKernel( *lhs, A, B );
766 }
768 //**********************************************************************************************
769
770 //**Default subtraction assignment to dense matrices********************************************
784 template< typename MT3 // Type of the left-hand side target matrix
785 , typename MT4 // Type of the left-hand side matrix operand
786 , typename MT5 > // Type of the right-hand side matrix operand
787 static inline void selectSubAssignKernel( MT3& C, const MT4& A, const MT5& B )
788 {
789 for( size_t j=0UL; j<C.columns(); ++j ) {
790 const auto rend( B.end(j) );
791 for( auto relem=B.begin(j); relem!=rend; ++relem ) {
792 const auto lend( A.end( relem->index() ) );
793 for( auto lelem=A.begin( relem->index() ); lelem!=lend; ++lelem ) {
794 C(lelem->index(),j) -= lelem->value() * relem->value();
795 }
796 }
797 }
798 }
800 //**********************************************************************************************
801
802 //**Restructuring subtraction assignment to row-major matrices**********************************
818 template< typename MT > // Type of the target matrix
819 friend inline auto subAssign( Matrix<MT,false>& lhs, const TSMatTSMatMultExpr& rhs )
820 -> EnableIf_t< CanExploitSymmetry_v<MT,MT1,MT2> >
821 {
823
825
826 BLAZE_INTERNAL_ASSERT( (*lhs).rows() == rhs.rows() , "Invalid number of rows" );
827 BLAZE_INTERNAL_ASSERT( (*lhs).columns() == rhs.columns(), "Invalid number of columns" );
828
829 subAssign( *lhs, trans( rhs.lhs_ ) * trans( rhs.rhs_ ) );
830 }
832 //**********************************************************************************************
833
834 //**Subtraction assignment to sparse matrices***************************************************
835 // No special implementation for the subtraction assignment to sparse matrices.
836 //**********************************************************************************************
837
838 //**Schur product assignment to dense matrices**************************************************
851 template< typename MT // Type of the target dense matrix
852 , bool SO > // Storage order of the target dense matarix
853 friend inline void schurAssign( DenseMatrix<MT,SO>& lhs, const TSMatTSMatMultExpr& rhs )
854 {
856
860
861 BLAZE_INTERNAL_ASSERT( (*lhs).rows() == rhs.rows() , "Invalid number of rows" );
862 BLAZE_INTERNAL_ASSERT( (*lhs).columns() == rhs.columns(), "Invalid number of columns" );
863
864 const ResultType tmp( serial( rhs ) );
865 schurAssign( *lhs, tmp );
866 }
868 //**********************************************************************************************
869
870 //**Schur product assignment to sparse matrices*************************************************
871 // No special implementation for the Schur product assignment to sparse matrices.
872 //**********************************************************************************************
873
874 //**Multiplication assignment to dense matrices*************************************************
875 // No special implementation for the multiplication assignment to dense matrices.
876 //**********************************************************************************************
877
878 //**Multiplication assignment to sparse matrices************************************************
879 // No special implementation for the multiplication assignment to sparse matrices.
880 //**********************************************************************************************
881
882 //**SMP assignment to matrices******************************************************************
898 template< typename MT // Type of the target matrix
899 , bool SO > // Storage order of the target matrix
900 friend inline auto smpAssign( Matrix<MT,SO>& lhs, const TSMatTSMatMultExpr& rhs )
901 -> EnableIf_t< IsEvaluationRequired_v<MT,MT1,MT2> >
902 {
904
905 BLAZE_INTERNAL_ASSERT( (*lhs).rows() == rhs.rows() , "Invalid number of rows" );
906 BLAZE_INTERNAL_ASSERT( (*lhs).columns() == rhs.columns(), "Invalid number of columns" );
907
908 CT1 A( rhs.lhs_ ); // Evaluation of the left-hand side sparse matrix operand
909 CT2 B( rhs.rhs_ ); // Evaluation of the right-hand side sparse matrix operand
910
911 BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
912 BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
913 BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
914 BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
915 BLAZE_INTERNAL_ASSERT( A.rows() == (*lhs).rows() , "Invalid number of rows" );
916 BLAZE_INTERNAL_ASSERT( B.columns() == (*lhs).columns() , "Invalid number of columns" );
917
918 smpAssign( *lhs, A * B );
919 }
921 //**********************************************************************************************
922
923 //**Restructuring SMP assignment to row-major matrices******************************************
938 template< typename MT > // Type of the target matrix
939 friend inline auto smpAssign( Matrix<MT,false>& lhs, const TSMatTSMatMultExpr& rhs )
940 -> EnableIf_t< CanExploitSymmetry_v<MT,MT1,MT2> >
941 {
943
945
946 BLAZE_INTERNAL_ASSERT( (*lhs).rows() == rhs.rows() , "Invalid number of rows" );
947 BLAZE_INTERNAL_ASSERT( (*lhs).columns() == rhs.columns(), "Invalid number of columns" );
948
949 smpAssign( *lhs, trans( rhs.lhs_ ) * trans( rhs.rhs_ ) );
950 }
952 //**********************************************************************************************
953
954 //**SMP addition assignment to dense matrices***************************************************
970 template< typename MT // Type of the target dense matrix
971 , bool SO > // Storage order of the target dense matarix
972 friend inline auto smpAddAssign( DenseMatrix<MT,SO>& lhs, const TSMatTSMatMultExpr& rhs )
973 -> EnableIf_t< IsEvaluationRequired_v<MT,MT1,MT2> >
974 {
976
977 BLAZE_INTERNAL_ASSERT( (*lhs).rows() == rhs.rows() , "Invalid number of rows" );
978 BLAZE_INTERNAL_ASSERT( (*lhs).columns() == rhs.columns(), "Invalid number of columns" );
979
980 CT1 A( rhs.lhs_ ); // Evaluation of the left-hand side sparse matrix operand
981 CT2 B( rhs.rhs_ ); // Evaluation of the right-hand side sparse matrix operand
982
983 BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
984 BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
985 BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
986 BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
987 BLAZE_INTERNAL_ASSERT( A.rows() == (*lhs).rows() , "Invalid number of rows" );
988 BLAZE_INTERNAL_ASSERT( B.columns() == (*lhs).columns() , "Invalid number of columns" );
989
990 smpAddAssign( *lhs, A * B );
991 }
993 //**********************************************************************************************
994
995 //**Restructuring SMP addition assignment to row-major matrices*********************************
1011 template< typename MT > // Type of the target matrix
1012 friend inline auto smpAddAssign( Matrix<MT,false>& lhs, const TSMatTSMatMultExpr& rhs )
1013 -> EnableIf_t< CanExploitSymmetry_v<MT,MT1,MT2> >
1014 {
1016
1018
1019 BLAZE_INTERNAL_ASSERT( (*lhs).rows() == rhs.rows() , "Invalid number of rows" );
1020 BLAZE_INTERNAL_ASSERT( (*lhs).columns() == rhs.columns(), "Invalid number of columns" );
1021
1022 smpAddAssign( *lhs, trans( rhs.lhs_ ) * trans( rhs.rhs_ ) );
1023 }
1025 //**********************************************************************************************
1026
1027 //**SMP addition assignment to sparse matrices**************************************************
1028 // No special implementation for the SMP addition assignment to sparse matrices.
1029 //**********************************************************************************************
1030
1031 //**SMP subtraction assignment to dense matrices************************************************
1047 template< typename MT // Type of the target dense matrix
1048 , bool SO > // Storage order of the target dense matarix
1049 friend inline auto smpSubAssign( DenseMatrix<MT,SO>& lhs, const TSMatTSMatMultExpr& rhs )
1050 -> EnableIf_t< IsEvaluationRequired_v<MT,MT1,MT2> >
1051 {
1053
1054 BLAZE_INTERNAL_ASSERT( (*lhs).rows() == rhs.rows() , "Invalid number of rows" );
1055 BLAZE_INTERNAL_ASSERT( (*lhs).columns() == rhs.columns(), "Invalid number of columns" );
1056
1057 CT1 A( rhs.lhs_ ); // Evaluation of the left-hand side sparse matrix operand
1058 CT2 B( rhs.rhs_ ); // Evaluation of the right-hand side sparse matrix operand
1059
1060 BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
1061 BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
1062 BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
1063 BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
1064 BLAZE_INTERNAL_ASSERT( A.rows() == (*lhs).rows() , "Invalid number of rows" );
1065 BLAZE_INTERNAL_ASSERT( B.columns() == (*lhs).columns() , "Invalid number of columns" );
1066
1067 smpSubAssign( *lhs, A * B );
1068 }
1070 //**********************************************************************************************
1071
1072 //**Restructuring SMP subtraction assignment to row-major matrices******************************
1088 template< typename MT > // Type of the target matrix
1089 friend inline auto smpSubAssign( Matrix<MT,false>& lhs, const TSMatTSMatMultExpr& rhs )
1090 -> EnableIf_t< CanExploitSymmetry_v<MT,MT1,MT2> >
1091 {
1093
1095
1096 BLAZE_INTERNAL_ASSERT( (*lhs).rows() == rhs.rows() , "Invalid number of rows" );
1097 BLAZE_INTERNAL_ASSERT( (*lhs).columns() == rhs.columns(), "Invalid number of columns" );
1098
1099 smpSubAssign( *lhs, trans( rhs.lhs_ ) * trans( rhs.rhs_ ) );
1100 }
1102 //**********************************************************************************************
1103
1104 //**SMP subtraction assignment to sparse matrices***********************************************
1105 // No special implementation for the SMP subtraction assignment to sparse matrices.
1106 //**********************************************************************************************
1107
1108 //**SMP Schur product assignment to dense matrices**********************************************
1121 template< typename MT // Type of the target dense matrix
1122 , bool SO > // Storage order of the target dense matarix
1123 friend inline void smpSchurAssign( DenseMatrix<MT,SO>& lhs, const TSMatTSMatMultExpr& rhs )
1124 {
1126
1130
1131 BLAZE_INTERNAL_ASSERT( (*lhs).rows() == rhs.rows() , "Invalid number of rows" );
1132 BLAZE_INTERNAL_ASSERT( (*lhs).columns() == rhs.columns(), "Invalid number of columns" );
1133
1134 const ResultType tmp( rhs );
1135 smpSchurAssign( *lhs, tmp );
1136 }
1138 //**********************************************************************************************
1139
1140 //**SMP Schur product assignment to sparse matrices*********************************************
1141 // No special implementation for the SMP Schur product assignment to sparse matrices.
1142 //**********************************************************************************************
1143
1144 //**SMP multiplication assignment to dense matrices*********************************************
1145 // No special implementation for the SMP multiplication assignment to dense matrices.
1146 //**********************************************************************************************
1147
1148 //**SMP multiplication assignment to sparse matrices********************************************
1149 // No special implementation for the SMP multiplication assignment to sparse matrices.
1150 //**********************************************************************************************
1151
1152 //**Compile time checks*************************************************************************
1162 //**********************************************************************************************
1163};
1164//*************************************************************************************************
1165
1166
1167
1168
1169//=================================================================================================
1170//
1171// GLOBAL BINARY ARITHMETIC OPERATORS
1172//
1173//=================================================================================================
1174
1175//*************************************************************************************************
1188template< typename MT1 // Type of the left-hand side sparse matrix
1189 , typename MT2 // Type of the right-hand side sparse matrix
1190 , DisableIf_t< ( ( IsIdentity_v<MT1> || IsIdentity_v<MT2> ) &&
1191 IsSame_v< ElementType_t<MT1>, ElementType_t<MT2> > ) ||
1192 ( IsIdentity_v<MT1> && IsIdentity_v<MT2> ) ||
1193 ( IsZero_v<MT1> || IsZero_v<MT2> ) >* = nullptr >
1194inline const TSMatTSMatMultExpr<MT1,MT2>
1195 tsmattsmatmult( const SparseMatrix<MT1,true>& lhs, const SparseMatrix<MT2,true>& rhs )
1196{
1198
1199 BLAZE_INTERNAL_ASSERT( (*lhs).columns() == (*rhs).rows(), "Invalid matrix sizes" );
1200
1201 return TSMatTSMatMultExpr<MT1,MT2>( *lhs, *rhs );
1202}
1204//*************************************************************************************************
1205
1206
1207//*************************************************************************************************
1221template< typename MT1 // Type of the left-hand side sparse matrix
1222 , typename MT2 // Type of the right-hand side sparse matrix
1223 , EnableIf_t< !IsIdentity_v<MT1> && IsIdentity_v<MT2> &&
1224 IsSame_v< ElementType_t<MT1>, ElementType_t<MT2> > >* = nullptr >
1225inline const MT1&
1226 tsmattsmatmult( const SparseMatrix<MT1,true>& lhs, const SparseMatrix<MT2,true>& rhs )
1227{
1229
1230 MAYBE_UNUSED( rhs );
1231
1232 BLAZE_INTERNAL_ASSERT( (*lhs).columns() == (*rhs).rows(), "Invalid matrix sizes" );
1233
1234 return (*lhs);
1235}
1237//*************************************************************************************************
1238
1239
1240//*************************************************************************************************
1254template< typename MT1 // Type of the left-hand side sparse matrix
1255 , typename MT2 // Type of the right-hand side sparse matrix
1256 , EnableIf_t< IsIdentity_v<MT1> && !IsIdentity_v<MT2> &&
1257 IsSame_v< ElementType_t<MT1>, ElementType_t<MT2> > >* = nullptr >
1258inline const MT2&
1259 tsmattsmatmult( const SparseMatrix<MT1,true>& lhs, const SparseMatrix<MT2,true>& rhs )
1260{
1262
1263 MAYBE_UNUSED( lhs );
1264
1265 BLAZE_INTERNAL_ASSERT( (*lhs).columns() == (*rhs).rows(), "Invalid matrix sizes" );
1266
1267 return (*rhs);
1268}
1270//*************************************************************************************************
1271
1272
1273//*************************************************************************************************
1286template< typename MT1 // Type of the left-hand side sparse matrix
1287 , typename MT2 // Type of the right-hand side sparse matrix
1288 , EnableIf_t< IsIdentity_v<MT1> && IsIdentity_v<MT2> >* = nullptr >
1289inline decltype(auto)
1290 tsmattsmatmult( const SparseMatrix<MT1,true>& lhs, const SparseMatrix<MT2,true>& rhs )
1291{
1293
1294 MAYBE_UNUSED( rhs );
1295
1296 BLAZE_INTERNAL_ASSERT( (*lhs).columns() == (*rhs).rows(), "Invalid matrix sizes" );
1297
1298 using ReturnType = const MultTrait_t< ResultType_t<MT1>, ResultType_t<MT2> >;
1299
1302
1303 return ReturnType( (*lhs).rows() );
1304}
1306//*************************************************************************************************
1307
1308
1309//*************************************************************************************************
1323template< typename MT1 // Type of the left-hand side sparse matrix
1324 , typename MT2 // Type of the right-hand side sparse matrix
1325 , EnableIf_t< IsZero_v<MT1> || IsZero_v<MT2> >* = nullptr >
1326inline decltype(auto)
1327 tsmattsmatmult( const SparseMatrix<MT1,true>& lhs, const SparseMatrix<MT2,true>& rhs )
1328{
1330
1331 BLAZE_INTERNAL_ASSERT( (*lhs).columns() == (*rhs).rows(), "Invalid matrix sizes" );
1332
1333 using ReturnType = const MultTrait_t< ResultType_t<MT1>, ResultType_t<MT2> >;
1334
1337
1338 return ReturnType( (*lhs).rows(), (*rhs).columns() );
1339}
1341//*************************************************************************************************
1342
1343
1344//*************************************************************************************************
1371template< typename MT1 // Type of the left-hand side sparse matrix
1372 , typename MT2 > // Type of the right-hand side sparse matrix
1373inline decltype(auto)
1374 operator*( const SparseMatrix<MT1,true>& lhs, const SparseMatrix<MT2,true>& rhs )
1375{
1377
1378 if( (*lhs).columns() != (*rhs).rows() ) {
1379 BLAZE_THROW_INVALID_ARGUMENT( "Matrix sizes do not match" );
1380 }
1381
1382 return tsmattsmatmult( *lhs, *rhs );
1383}
1384//*************************************************************************************************
1385
1386} // namespace blaze
1387
1388#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 EnableIf class template.
Header file for the function trace functionality.
Constraint on the data type.
Header file for the If class template.
Numerical infinity for built-in data types.
Header file for the IntegralConstant class template.
Header file for the IsBuiltin type trait.
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 SmallArray implementation.
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-transpose sparse matrix multiplications.
Definition: TSMatTSMatMultExpr.h:110
OppositeType_t< ResultType > OppositeType
Result type with opposite storage order for expression template evaluations.
Definition: TSMatTSMatMultExpr.h:163
ReturnType operator()(size_t i, size_t j) const
2D-access to the matrix elements.
Definition: TSMatTSMatMultExpr.h:203
RightOperand rhs_
Right-hand side sparse matrix of the multiplication expression.
Definition: TSMatTSMatMultExpr.h:362
If_t< IsExpression_v< MT2 >, const MT2, const MT2 & > RightOperand
Composite type of the right-hand side sparse matrix expression.
Definition: TSMatTSMatMultExpr.h:173
ElementType_t< ResultType > ElementType
Resulting element type.
Definition: TSMatTSMatMultExpr.h:165
LeftOperand lhs_
Left-hand side sparse matrix of the multiplication expression.
Definition: TSMatTSMatMultExpr.h:361
bool canAlias(const T *alias) const noexcept
Returns whether the expression can alias with the given address alias.
Definition: TSMatTSMatMultExpr.h:332
static constexpr bool smpAssignable
Compilation switch for the expression template assignment strategy.
Definition: TSMatTSMatMultExpr.h:178
bool canSMPAssign() const noexcept
Returns whether the expression can be used in SMP assignments.
Definition: TSMatTSMatMultExpr.h:354
const ResultType CompositeType
Data type for composite expression templates.
Definition: TSMatTSMatMultExpr.h:167
ResultType_t< MT2 > RT2
Result type of the right-hand side sparse matrix expression.
Definition: TSMatTSMatMultExpr.h:114
TSMatTSMatMultExpr(const MT1 &lhs, const MT2 &rhs) noexcept
Constructor for the TSMatTSMatMultExpr class.
Definition: TSMatTSMatMultExpr.h:188
LeftOperand leftOperand() const noexcept
Returns the left-hand side transpose sparse matrix operand.
Definition: TSMatTSMatMultExpr.h:310
constexpr size_t nonZeros() const noexcept
Returns the number of non-zero elements in the sparse matrix.
Definition: TSMatTSMatMultExpr.h:288
MultTrait_t< RT1, RT2 > ResultType
Result type for expression template evaluations.
Definition: TSMatTSMatMultExpr.h:162
CompositeType_t< MT1 > CT1
Composite type of the left-hand side sparse matrix expression.
Definition: TSMatTSMatMultExpr.h:115
TransposeType_t< ResultType > TransposeType
Transpose type for expression template evaluations.
Definition: TSMatTSMatMultExpr.h:164
ReturnType at(size_t i, size_t j) const
Checked access to the matrix elements.
Definition: TSMatTSMatMultExpr.h:252
size_t rows() const noexcept
Returns the current number of rows of the matrix.
Definition: TSMatTSMatMultExpr.h:268
RightOperand rightOperand() const noexcept
Returns the right-hand side transpose sparse matrix operand.
Definition: TSMatTSMatMultExpr.h:320
static constexpr bool evaluateRight
Compilation switch for the composite type of the right-hand side sparse matrix expression.
Definition: TSMatTSMatMultExpr.h:126
const ElementType ReturnType
Return type for expression template evaluations.
Definition: TSMatTSMatMultExpr.h:166
size_t columns() const noexcept
Returns the current number of columns of the matrix.
Definition: TSMatTSMatMultExpr.h:278
If_t< IsExpression_v< MT1 >, const MT1, const MT1 & > LeftOperand
Composite type of the left-hand side sparse matrix expression.
Definition: TSMatTSMatMultExpr.h:170
CompositeType_t< MT2 > CT2
Composite type of the right-hand side sparse matrix expression.
Definition: TSMatTSMatMultExpr.h:116
static constexpr bool evaluateLeft
Compilation switch for the composite type of the left-hand side sparse matrix expression.
Definition: TSMatTSMatMultExpr.h:121
ResultType_t< MT1 > RT1
Result type of the left-hand side sparse matrix expression.
Definition: TSMatTSMatMultExpr.h:113
size_t nonZeros(size_t i) const noexcept
Returns the number of non-zero elements in the specified row.
Definition: TSMatTSMatMultExpr.h:299
bool isAliased(const T *alias) const noexcept
Returns whether the expression is aliased with the given address alias.
Definition: TSMatTSMatMultExpr.h:344
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 MatMatMultExpr base class.
Header file for the SparseMatrix 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) trans(const DenseMatrix< MT, SO > &dm)
Calculation of the transpose of the given dense matrix.
Definition: DMatTransExpr.h:766
decltype(auto) serial(const DenseMatrix< MT, SO > &dm)
Forces the serial evaluation of the given dense matrix expression dm.
Definition: DMatSerialExpr.h:812
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_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_SPARSE_MATRIX_TYPE(T)
Constraint on the data type.
Definition: SparseMatrix.h:61
#define BLAZE_CONSTRAINT_MUST_BE_IDENTITY_MATRIX_TYPE(T)
Constraint on the data type.
Definition: Identity.h:60
#define BLAZE_CONSTRAINT_MUST_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
typename MultTrait< T1, T2 >::Type MultTrait_t
Auxiliary alias declaration for the MultTrait class template.
Definition: MultTrait.h:165
constexpr bool IsResizable_v
Auxiliary variable template for the IsResizable type trait.
Definition: IsResizable.h:136
constexpr Infinity inf
Global Infinity instance.
Definition: Infinity.h:1080
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
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 bool IsSame_v
Auxiliary variable template for the IsSame type trait.
Definition: IsSame.h:159
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.
Header file for all forward declarations for expression class templates.
Header file for the reset shim.
Header file for the serial shim.
Base class for all compute expression templates.
Definition: Computation.h:68
Base class for all matrix/matrix multiplication expression templates.
Definition: MatMatMultExpr.h:71
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.