Blaze 3.9
SMatSMatMultExpr.h
Go to the documentation of this file.
1//=================================================================================================
33//=================================================================================================
34
35#ifndef _BLAZE_MATH_EXPRESSIONS_SMATSMATMULTEXPR_H_
36#define _BLAZE_MATH_EXPRESSIONS_SMATSMATMULTEXPR_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>
87
88
89namespace blaze {
90
91//=================================================================================================
92//
93// CLASS SMATSMATMULTEXPR
94//
95//=================================================================================================
96
97//*************************************************************************************************
104template< typename MT1 // Type of the left-hand side sparse matrix
105 , typename MT2 > // Type of the right-hand side sparse matrix
107 : public MatMatMultExpr< SparseMatrix< SMatSMatMultExpr<MT1,MT2>, false > >
108 , private Computation
109{
110 private:
111 //**Type definitions****************************************************************************
116 //**********************************************************************************************
117
118 //**********************************************************************************************
120 static constexpr bool evaluateLeft = RequiresEvaluation_v<MT1>;
121 //**********************************************************************************************
122
123 //**********************************************************************************************
125 static constexpr bool evaluateRight = RequiresEvaluation_v<MT2>;
126 //**********************************************************************************************
127
128 //**********************************************************************************************
130
135 template< typename T1, typename T2, typename T3 >
136 static constexpr bool CanExploitSymmetry_v =
137 ( IsColumnMajorMatrix_v<T1> && IsSymmetric_v<T2> && IsSymmetric_v<T3> );
139 //**********************************************************************************************
140
141 //**********************************************************************************************
143
147 template< typename T1, typename T2, typename T3 >
148 static constexpr bool IsEvaluationRequired_v =
149 ( ( evaluateLeft || evaluateRight ) && !CanExploitSymmetry_v<T1,T2,T3> );
151 //**********************************************************************************************
152
153 public:
154 //**Type definitions****************************************************************************
157
160
165 using ReturnType = const ElementType;
166 using CompositeType = const ResultType;
167
169 using LeftOperand = If_t< IsExpression_v<MT1>, const MT1, const MT1& >;
170
172 using RightOperand = If_t< IsExpression_v<MT2>, const MT2, const MT2& >;
173 //**********************************************************************************************
174
175 //**Compilation flags***************************************************************************
177 static constexpr bool smpAssignable =
178 ( !evaluateLeft && MT1::smpAssignable && !evaluateRight && MT2::smpAssignable );
179 //**********************************************************************************************
180
181 //**Constructor*********************************************************************************
187 inline SMatSMatMultExpr( const MT1& lhs, const MT2& rhs ) noexcept
188 : lhs_( lhs ) // Left-hand side sparse matrix of the multiplication expression
189 , rhs_( rhs ) // Right-hand side sparse matrix of the multiplication expression
190 {
191 BLAZE_INTERNAL_ASSERT( lhs.columns() == rhs.rows(), "Invalid matrix sizes" );
192 }
193 //**********************************************************************************************
194
195 //**Access operator*****************************************************************************
202 inline ReturnType operator()( size_t i, size_t j ) const {
203 BLAZE_INTERNAL_ASSERT( i < lhs_.rows() , "Invalid row access index" );
204 BLAZE_INTERNAL_ASSERT( j < rhs_.columns(), "Invalid column access index" );
205
206 if( IsDiagonal_v<MT1> ) {
207 return lhs_(i,i) * rhs_(i,j);
208 }
209 else if( IsDiagonal_v<MT2> ) {
210 return lhs_(i,j) * rhs_(j,j);
211 }
212 else if( IsTriangular_v<MT1> || IsTriangular_v<MT2> ) {
213 const size_t begin( ( IsUpper_v<MT1> )
214 ?( ( IsLower_v<MT2> )
215 ?( max( ( IsStrictlyUpper_v<MT1> ? i+1UL : i )
216 , ( IsStrictlyLower_v<MT2> ? j+1UL : j ) ) )
217 :( IsStrictlyUpper_v<MT1> ? i+1UL : i ) )
218 :( ( IsLower_v<MT2> )
219 ?( IsStrictlyLower_v<MT2> ? j+1UL : j )
220 :( 0UL ) ) );
221 const size_t end( ( IsLower_v<MT1> )
222 ?( ( IsUpper_v<MT2> )
223 ?( min( ( IsStrictlyLower_v<MT1> ? i : i+1UL )
224 , ( IsStrictlyUpper_v<MT2> ? j : j+1UL ) ) )
225 :( IsStrictlyLower_v<MT1> ? i : i+1UL ) )
226 :( ( IsUpper_v<MT2> )
227 ?( IsStrictlyUpper_v<MT2> ? j : j+1UL )
228 :( lhs_.columns() ) ) );
229
230 if( begin >= end ) return ElementType();
231
232 const size_t n( end - begin );
233
234 return subvector( row( lhs_, i, unchecked ), begin, n, unchecked ) *
236 }
237 else {
238 return row( lhs_, i, unchecked ) * column( rhs_, j, unchecked );
239 }
240 }
241 //**********************************************************************************************
242
243 //**At function*********************************************************************************
251 inline ReturnType at( size_t i, size_t j ) const {
252 if( i >= lhs_.rows() ) {
253 BLAZE_THROW_OUT_OF_RANGE( "Invalid row access index" );
254 }
255 if( j >= rhs_.columns() ) {
256 BLAZE_THROW_OUT_OF_RANGE( "Invalid column access index" );
257 }
258 return (*this)(i,j);
259 }
260 //**********************************************************************************************
261
262 //**Rows function*******************************************************************************
267 inline size_t rows() const noexcept {
268 return lhs_.rows();
269 }
270 //**********************************************************************************************
271
272 //**Columns function****************************************************************************
277 inline size_t columns() const noexcept {
278 return rhs_.columns();
279 }
280 //**********************************************************************************************
281
282 //**NonZeros function***************************************************************************
287 constexpr size_t nonZeros() const noexcept {
288 return 0UL;
289 }
290 //**********************************************************************************************
291
292 //**NonZeros function***************************************************************************
298 inline size_t nonZeros( size_t i ) const noexcept {
299 MAYBE_UNUSED( i );
300 return 0UL;
301 }
302 //**********************************************************************************************
303
304 //**Left operand access*************************************************************************
309 inline LeftOperand leftOperand() const noexcept {
310 return lhs_;
311 }
312 //**********************************************************************************************
313
314 //**Right operand access************************************************************************
319 inline RightOperand rightOperand() const noexcept {
320 return rhs_;
321 }
322 //**********************************************************************************************
323
324 //**********************************************************************************************
330 template< typename T >
331 inline bool canAlias( const T* alias ) const noexcept {
332 return ( lhs_.isAliased( alias ) || rhs_.isAliased( alias ) );
333 }
334 //**********************************************************************************************
335
336 //**********************************************************************************************
342 template< typename T >
343 inline bool isAliased( const T* alias ) const noexcept {
344 return ( lhs_.isAliased( alias ) || rhs_.isAliased( alias ) );
345 }
346 //**********************************************************************************************
347
348 //**********************************************************************************************
353 inline bool canSMPAssign() const noexcept {
354 return ( rows() * columns() >= SMP_SMATSMATMULT_THRESHOLD );
355 }
356 //**********************************************************************************************
357
358 private:
359 //**Member variables****************************************************************************
362 //**********************************************************************************************
363
364 //**Assignment to dense matrices****************************************************************
377 template< typename MT // Type of the target dense matrix
378 , bool SO > // Storage order of the target dense matrix
379 friend inline auto assign( DenseMatrix<MT,SO>& lhs, const SMatSMatMultExpr& rhs )
381 {
383
384 BLAZE_INTERNAL_ASSERT( (*lhs).rows() == rhs.rows() , "Invalid number of rows" );
385 BLAZE_INTERNAL_ASSERT( (*lhs).columns() == rhs.columns(), "Invalid number of columns" );
386
387 CT1 A( serial( rhs.lhs_ ) ); // Evaluation of the left-hand side sparse matrix operand
388 CT2 B( serial( rhs.rhs_ ) ); // Evaluation of the right-hand side sparse matrix operand
389
390 BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
391 BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
392 BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
393 BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
394 BLAZE_INTERNAL_ASSERT( A.rows() == (*lhs).rows() , "Invalid number of rows" );
395 BLAZE_INTERNAL_ASSERT( B.columns() == (*lhs).columns() , "Invalid number of columns" );
396
397 SMatSMatMultExpr::selectAssignKernel( *lhs, A, B );
398 }
400 //**********************************************************************************************
401
402 //**Default assignment to dense matrices********************************************************
415 template< typename MT3 // Type of the left-hand side target matrix
416 , typename MT4 // Type of the left-hand side matrix operand
417 , typename MT5 > // Type of the right-hand side matrix operand
418 static inline void selectAssignKernel( MT3& C, const MT4& A, const MT5& B )
419 {
420 for( size_t i=0UL; i<C.rows(); ++i ) {
421 const auto lend( A.end(i) );
422 for( auto lelem=A.begin(i); lelem!=lend; ++lelem ) {
423 const auto rend( B.end( lelem->index() ) );
424 for( auto relem=B.begin( lelem->index() ); relem!=rend; ++relem )
425 {
427 isDefault( C(i,relem->index()) ) ) {
428 C(i,relem->index()) = lelem->value() * relem->value();
429 }
430 else {
431 C(i,relem->index()) += lelem->value() * relem->value();
432 }
433 }
434 }
435 }
436 }
438 //**********************************************************************************************
439
440 //**Assignment to row-major sparse matrices*****************************************************
453 template< typename MT > // Type of the target sparse matrix
454 friend inline void assign( SparseMatrix<MT,false>& lhs, const SMatSMatMultExpr& rhs )
455 {
457
458 BLAZE_INTERNAL_ASSERT( (*lhs).rows() == rhs.rows() , "Invalid number of rows" );
459 BLAZE_INTERNAL_ASSERT( (*lhs).columns() == rhs.columns(), "Invalid number of columns" );
460
461 CT1 A( serial( rhs.lhs_ ) ); // Evaluation of the left-hand side sparse matrix operand
462 CT2 B( serial( rhs.rhs_ ) ); // Evaluation of the right-hand side sparse matrix operand
463
464 BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
465 BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
466 BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
467 BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
468 BLAZE_INTERNAL_ASSERT( A.rows() == (*lhs).rows() , "Invalid number of rows" );
469 BLAZE_INTERNAL_ASSERT( B.columns() == (*lhs).columns() , "Invalid number of columns" );
470
471 // (Over-)Estimating the number of non-zero entries in the resulting matrix
472 size_t nonzeros( 0UL );
473
474 for( size_t i=0UL; i<(*lhs).rows(); ++i ) {
475 const auto lend( A.end(i) );
476 for( auto lelem=A.begin(i); lelem!=lend; ++lelem ) {
477 nonzeros += B.nonZeros( lelem->index() );
478 }
479 }
480
481 if( nonzeros > (*lhs).rows() * (*lhs).columns() ) {
482 nonzeros = (*lhs).rows() * (*lhs).columns();
483 }
484
485 (*lhs).reserve( nonzeros );
486 nonzeros = 0UL;
487
488 // Performing the matrix-matrix multiplication
489 SmallArray<ElementType,128UL> values ( (*lhs).columns(), ElementType() );
490 SmallArray<bool,128UL> valid ( (*lhs).columns(), false );
491 SmallArray<size_t,128UL> indices( (*lhs).columns(), 0UL );
492 size_t minIndex( inf ), maxIndex( 0UL );
493
494 for( size_t i=0UL; i<(*lhs).rows(); ++i )
495 {
496 const auto lend( A.end(i) );
497 for( auto lelem=A.begin(i); lelem!=lend; ++lelem )
498 {
499 const auto rend( B.end( lelem->index() ) );
500 for( auto relem=B.begin( lelem->index() ); relem!=rend; ++relem )
501 {
502 if( !valid[relem->index()] ) {
503 values[relem->index()] = lelem->value() * relem->value();
504 valid [relem->index()] = true;
505 indices[nonzeros] = relem->index();
506 ++nonzeros;
507 if( relem->index() < minIndex ) minIndex = relem->index();
508 if( relem->index() > maxIndex ) maxIndex = relem->index();
509 }
510 else {
511 values[relem->index()] += lelem->value() * relem->value();
512 }
513 }
514 }
515
516 BLAZE_INTERNAL_ASSERT( nonzeros <= (*lhs).columns(), "Invalid number of non-zero elements" );
517
518 if( nonzeros > 0UL )
519 {
520 BLAZE_INTERNAL_ASSERT( minIndex <= maxIndex, "Invalid index detected" );
521
522 if( ( nonzeros + nonzeros ) < ( maxIndex - minIndex ) )
523 {
524 std::sort( indices.begin(), indices.begin() + nonzeros );
525
526 for( size_t j=0UL; j<nonzeros; ++j )
527 {
528 const size_t index( indices[j] );
529 if( !isDefault( values[index] ) ) {
530 (*lhs).append( i, index, values[index] );
531 reset( values[index] );
532 }
533
534 reset( valid[index] );
535 }
536 }
537 else {
538 for( size_t j=minIndex; j<=maxIndex; ++j )
539 {
540 if( !isDefault( values[j] ) ) {
541 (*lhs).append( i, j, values[j] );
542 reset( values[j] );
543 }
544
545 reset( valid[j] );
546 }
547 }
548
549 nonzeros = 0UL;
550 minIndex = inf;
551 maxIndex = 0UL;
552 }
553
554 (*lhs).finalize( i );
555 }
556 }
558 //**********************************************************************************************
559
560 //**Assignment to column-major sparse matrices**************************************************
573 template< typename MT > // Type of the target sparse matrix
574 friend inline auto assign( SparseMatrix<MT,true>& lhs, const SMatSMatMultExpr& rhs )
575 -> DisableIf_t< CanExploitSymmetry_v<MT,MT1,MT2> >
576 {
578
580
581 BLAZE_INTERNAL_ASSERT( (*lhs).rows() == rhs.rows() , "Invalid number of rows" );
582 BLAZE_INTERNAL_ASSERT( (*lhs).columns() == rhs.columns(), "Invalid number of columns" );
583
586
587 const ResultType tmp( serial( rhs ) );
588 (*lhs).reserve( tmp.nonZeros() );
589 assign( *lhs, tmp );
590 }
592 //**********************************************************************************************
593
594 //**Restructuring assignment to column-major matrices*******************************************
609 template< typename MT > // Type of the target matrix
610 friend inline auto assign( Matrix<MT,true>& lhs, const SMatSMatMultExpr& rhs )
611 -> EnableIf_t< CanExploitSymmetry_v<MT,MT1,MT2> >
612 {
614
616
617 BLAZE_INTERNAL_ASSERT( (*lhs).rows() == rhs.rows() , "Invalid number of rows" );
618 BLAZE_INTERNAL_ASSERT( (*lhs).columns() == rhs.columns(), "Invalid number of columns" );
619
620 assign( *lhs, trans( rhs.lhs_ ) * trans( rhs.rhs_ ) );
621 }
623 //**********************************************************************************************
624
625 //**Addition assignment to dense matrices*******************************************************
638 template< typename MT // Type of the target dense matrix
639 , bool SO > // Storage order of the target dense matarix
640 friend inline auto addAssign( DenseMatrix<MT,SO>& lhs, const SMatSMatMultExpr& rhs )
641 -> DisableIf_t< CanExploitSymmetry_v<MT,MT1,MT2> >
642 {
644
645 BLAZE_INTERNAL_ASSERT( (*lhs).rows() == rhs.rows() , "Invalid number of rows" );
646 BLAZE_INTERNAL_ASSERT( (*lhs).columns() == rhs.columns(), "Invalid number of columns" );
647
648 CT1 A( serial( rhs.lhs_ ) ); // Evaluation of the left-hand side sparse matrix operand
649 CT2 B( serial( rhs.rhs_ ) ); // Evaluation of the right-hand side sparse matrix operand
650
651 BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
652 BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
653 BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
654 BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
655 BLAZE_INTERNAL_ASSERT( A.rows() == (*lhs).rows() , "Invalid number of rows" );
656 BLAZE_INTERNAL_ASSERT( B.columns() == (*lhs).columns() , "Invalid number of columns" );
657
658 SMatSMatMultExpr::selectAddAssignKernel( *lhs, A, B );
659 }
661 //**********************************************************************************************
662
663 //**Default addition assignment to dense matrices***********************************************
677 template< typename MT3 // Type of the left-hand side target matrix
678 , typename MT4 // Type of the left-hand side matrix operand
679 , typename MT5 > // Type of the right-hand side matrix operand
680 static inline void selectAddAssignKernel( MT3& C, const MT4& A, const MT5& B )
681 {
682 for( size_t i=0UL; i<C.rows(); ++i ) {
683 const auto lend( A.end(i) );
684 for( auto lelem=A.begin(i); lelem!=lend; ++lelem ) {
685 const auto rend( B.end( lelem->index() ) );
686 for( auto relem=B.begin( lelem->index() ); relem!=rend; ++relem ) {
687 C(i,relem->index()) += lelem->value() * relem->value();
688 }
689 }
690 }
691 }
693 //**********************************************************************************************
694
695 //**Restructuring addition assignment to column-major matrices**********************************
710 template< typename MT > // Type of the target matrix
711 friend inline auto addAssign( Matrix<MT,true>& lhs, const SMatSMatMultExpr& rhs )
712 -> EnableIf_t< CanExploitSymmetry_v<MT,MT1,MT2> >
713 {
715
717
718 BLAZE_INTERNAL_ASSERT( (*lhs).rows() == rhs.rows() , "Invalid number of rows" );
719 BLAZE_INTERNAL_ASSERT( (*lhs).columns() == rhs.columns(), "Invalid number of columns" );
720
721 addAssign( *lhs, trans( rhs.lhs_ ) * trans( rhs.rhs_ ) );
722 }
724 //**********************************************************************************************
725
726 //**Addition assignment to sparse matrices******************************************************
727 // No special implementation for the addition assignment to sparse matrices.
728 //**********************************************************************************************
729
730 //**Subtraction assignment to dense matrices****************************************************
743 template< typename MT // Type of the target dense matrix
744 , bool SO > // Storage order of the target dense matrix
745 friend inline auto subAssign( DenseMatrix<MT,SO>& lhs, const SMatSMatMultExpr& rhs )
746 -> DisableIf_t< CanExploitSymmetry_v<MT,MT1,MT2> >
747 {
749
750 BLAZE_INTERNAL_ASSERT( (*lhs).rows() == rhs.rows() , "Invalid number of rows" );
751 BLAZE_INTERNAL_ASSERT( (*lhs).columns() == rhs.columns(), "Invalid number of columns" );
752
753 CT1 A( serial( rhs.lhs_ ) ); // Evaluation of the left-hand side sparse matrix operand
754 CT2 B( serial( rhs.rhs_ ) ); // Evaluation of the right-hand side sparse matrix operand
755
756 BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
757 BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
758 BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
759 BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
760 BLAZE_INTERNAL_ASSERT( A.rows() == (*lhs).rows() , "Invalid number of rows" );
761 BLAZE_INTERNAL_ASSERT( B.columns() == (*lhs).columns() , "Invalid number of columns" );
762
763 SMatSMatMultExpr::selectSubAssignKernel( *lhs, A, B );
764 }
766 //**********************************************************************************************
767
768 //**Default subtraction assignment to dense matrices********************************************
782 template< typename MT3 // Type of the left-hand side target matrix
783 , typename MT4 // Type of the left-hand side matrix operand
784 , typename MT5 > // Type of the right-hand side matrix operand
785 static inline void selectSubAssignKernel( MT3& C, const MT4& A, const MT5& B )
786 {
787 for( size_t i=0UL; i<C.rows(); ++i ) {
788 const auto lend( A.end(i) );
789 for( auto lelem=A.begin(i); lelem!=lend; ++lelem ) {
790 const auto rend( B.end( lelem->index() ) );
791 for( auto relem=B.begin( lelem->index() ); relem!=rend; ++relem ) {
792 C(i,relem->index()) -= lelem->value() * relem->value();
793 }
794 }
795 }
796 }
798 //**********************************************************************************************
799
800 //**Restructuring subtraction assignment to column-major matrices*******************************
815 template< typename MT > // Type of the target matrix
816 friend inline auto subAssign( Matrix<MT,true>& lhs, const SMatSMatMultExpr& rhs )
817 -> EnableIf_t< CanExploitSymmetry_v<MT,MT1,MT2> >
818 {
820
822
823 BLAZE_INTERNAL_ASSERT( (*lhs).rows() == rhs.rows() , "Invalid number of rows" );
824 BLAZE_INTERNAL_ASSERT( (*lhs).columns() == rhs.columns(), "Invalid number of columns" );
825
826 subAssign( *lhs, trans( rhs.lhs_ ) * trans( rhs.rhs_ ) );
827 }
829 //**********************************************************************************************
830
831 //**Subtraction assignment to sparse matrices***************************************************
832 // No special implementation for the subtraction assignment to sparse matrices.
833 //**********************************************************************************************
834
835 //**Schur product assignment to dense matrices**************************************************
848 template< typename MT // Type of the target dense matrix
849 , bool SO > // Storage order of the target dense matrix
850 friend inline void schurAssign( DenseMatrix<MT,SO>& lhs, const SMatSMatMultExpr& rhs )
851 {
853
857
858 BLAZE_INTERNAL_ASSERT( (*lhs).rows() == rhs.rows() , "Invalid number of rows" );
859 BLAZE_INTERNAL_ASSERT( (*lhs).columns() == rhs.columns(), "Invalid number of columns" );
860
861 const ResultType tmp( serial( rhs ) );
862 schurAssign( *lhs, tmp );
863 }
865 //**********************************************************************************************
866
867 //**Schur product assignment to sparse matrices*************************************************
868 // No special implementation for the Schur product assignment to sparse matrices.
869 //**********************************************************************************************
870
871 //**Multiplication assignment to dense matrices*************************************************
872 // No special implementation for the multiplication assignment to dense matrices.
873 //**********************************************************************************************
874
875 //**Multiplication assignment to sparse matrices************************************************
876 // No special implementation for the multiplication assignment to sparse matrices.
877 //**********************************************************************************************
878
879 //**SMP assignment to matrices******************************************************************
894 template< typename MT // Type of the target matrix
895 , bool SO > // Storage order of the target matrix
896 friend inline auto smpAssign( Matrix<MT,SO>& lhs, const SMatSMatMultExpr& rhs )
897 -> EnableIf_t< IsEvaluationRequired_v<MT,MT1,MT2> >
898 {
900
901 BLAZE_INTERNAL_ASSERT( (*lhs).rows() == rhs.rows() , "Invalid number of rows" );
902 BLAZE_INTERNAL_ASSERT( (*lhs).columns() == rhs.columns(), "Invalid number of columns" );
903
904 CT1 A( rhs.lhs_ ); // Evaluation of the left-hand side sparse matrix operand
905 CT2 B( rhs.rhs_ ); // Evaluation of the right-hand side sparse matrix operand
906
907 BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
908 BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
909 BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
910 BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
911 BLAZE_INTERNAL_ASSERT( A.rows() == (*lhs).rows() , "Invalid number of rows" );
912 BLAZE_INTERNAL_ASSERT( B.columns() == (*lhs).columns() , "Invalid number of columns" );
913
914 smpAssign( *lhs, A * B );
915 }
917 //**********************************************************************************************
918
919 //**Restructuring SMP assignment to column-major matrices***************************************
934 template< typename MT > // Type of the target matrix
935 friend inline auto smpAssign( Matrix<MT,true>& lhs, const SMatSMatMultExpr& rhs )
936 -> EnableIf_t< CanExploitSymmetry_v<MT,MT1,MT2> >
937 {
939
941
942 BLAZE_INTERNAL_ASSERT( (*lhs).rows() == rhs.rows() , "Invalid number of rows" );
943 BLAZE_INTERNAL_ASSERT( (*lhs).columns() == rhs.columns(), "Invalid number of columns" );
944
945 smpAssign( *lhs, trans( rhs.lhs_ ) * trans( rhs.rhs_ ) );
946 }
948 //**********************************************************************************************
949
950 //**SMP addition assignment to dense matrices***************************************************
966 template< typename MT // Type of the target dense matrix
967 , bool SO > // Storage order of the target dense matarix
968 friend inline auto smpAddAssign( DenseMatrix<MT,SO>& lhs, const SMatSMatMultExpr& rhs )
969 -> EnableIf_t< IsEvaluationRequired_v<MT,MT1,MT2> >
970 {
972
973 BLAZE_INTERNAL_ASSERT( (*lhs).rows() == rhs.rows() , "Invalid number of rows" );
974 BLAZE_INTERNAL_ASSERT( (*lhs).columns() == rhs.columns(), "Invalid number of columns" );
975
976 CT1 A( rhs.lhs_ ); // Evaluation of the left-hand side sparse matrix operand
977 CT2 B( rhs.rhs_ ); // Evaluation of the right-hand side sparse matrix operand
978
979 BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
980 BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
981 BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
982 BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
983 BLAZE_INTERNAL_ASSERT( A.rows() == (*lhs).rows() , "Invalid number of rows" );
984 BLAZE_INTERNAL_ASSERT( B.columns() == (*lhs).columns() , "Invalid number of columns" );
985
986 smpAddAssign( *lhs, A * B );
987 }
989 //**********************************************************************************************
990
991 //**Restructuring SMP addition assignment to column-major matrices******************************
1006 template< typename MT > // Type of the target matrix
1007 friend inline auto smpAddAssign( Matrix<MT,true>& lhs, const SMatSMatMultExpr& rhs )
1008 -> EnableIf_t< CanExploitSymmetry_v<MT,MT1,MT2> >
1009 {
1011
1013
1014 BLAZE_INTERNAL_ASSERT( (*lhs).rows() == rhs.rows() , "Invalid number of rows" );
1015 BLAZE_INTERNAL_ASSERT( (*lhs).columns() == rhs.columns(), "Invalid number of columns" );
1016
1017 smpAddAssign( *lhs, trans( rhs.lhs_ ) * trans( rhs.rhs_ ) );
1018 }
1020 //**********************************************************************************************
1021
1022 //**SMP addition assignment to sparse matrices**************************************************
1023 // No special implementation for the SMP addition assignment to sparse matrices.
1024 //**********************************************************************************************
1025
1026 //**SMP subtraction assignment to dense matrices************************************************
1042 template< typename MT // Type of the target dense matrix
1043 , bool SO > // Storage order of the target dense matrix
1044 friend inline auto smpSubAssign( DenseMatrix<MT,SO>& lhs, const SMatSMatMultExpr& rhs )
1045 -> EnableIf_t< IsEvaluationRequired_v<MT,MT1,MT2> >
1046 {
1048
1049 BLAZE_INTERNAL_ASSERT( (*lhs).rows() == rhs.rows() , "Invalid number of rows" );
1050 BLAZE_INTERNAL_ASSERT( (*lhs).columns() == rhs.columns(), "Invalid number of columns" );
1051
1052 CT1 A( rhs.lhs_ ); // Evaluation of the left-hand side sparse matrix operand
1053 CT2 B( rhs.rhs_ ); // Evaluation of the right-hand side sparse matrix operand
1054
1055 BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
1056 BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
1057 BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
1058 BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
1059 BLAZE_INTERNAL_ASSERT( A.rows() == (*lhs).rows() , "Invalid number of rows" );
1060 BLAZE_INTERNAL_ASSERT( B.columns() == (*lhs).columns() , "Invalid number of columns" );
1061
1062 smpSubAssign( *lhs, A * B );
1063 }
1065 //**********************************************************************************************
1066
1067 //**Restructuring SMP subtraction assignment to column-major matrices***************************
1082 template< typename MT > // Type of the target matrix
1083 friend inline auto smpSubAssign( Matrix<MT,true>& lhs, const SMatSMatMultExpr& rhs )
1084 -> EnableIf_t< CanExploitSymmetry_v<MT,MT1,MT2> >
1085 {
1087
1089
1090 BLAZE_INTERNAL_ASSERT( (*lhs).rows() == rhs.rows() , "Invalid number of rows" );
1091 BLAZE_INTERNAL_ASSERT( (*lhs).columns() == rhs.columns(), "Invalid number of columns" );
1092
1093 smpSubAssign( *lhs, trans( rhs.lhs_ ) * trans( rhs.rhs_ ) );
1094 }
1096 //**********************************************************************************************
1097
1098 //**SMP subtraction assignment to sparse matrices***********************************************
1099 // No special implementation for the SMP subtraction assignment to sparse matrices.
1100 //**********************************************************************************************
1101
1102 //**SMP Schur product assignment to dense matrices**********************************************
1115 template< typename MT // Type of the target dense matrix
1116 , bool SO > // Storage order of the target dense matrix
1117 friend inline void
1118 smpSchurAssign( DenseMatrix<MT,SO>& lhs, const SMatSMatMultExpr& rhs )
1119 {
1121
1125
1126 BLAZE_INTERNAL_ASSERT( (*lhs).rows() == rhs.rows() , "Invalid number of rows" );
1127 BLAZE_INTERNAL_ASSERT( (*lhs).columns() == rhs.columns(), "Invalid number of columns" );
1128
1129 const ResultType tmp( rhs );
1130 smpSchurAssign( *lhs, tmp );
1131 }
1133 //**********************************************************************************************
1134
1135 //**SMP Schur product assignment to sparse matrices*********************************************
1136 // No special implementation for the SMP Schur product assignment to sparse matrices.
1137 //**********************************************************************************************
1138
1139 //**SMP multiplication assignment to dense matrices*********************************************
1140 // No special implementation for the SMP multiplication assignment to dense matrices.
1141 //**********************************************************************************************
1142
1143 //**SMP multiplication assignment to sparse matrices********************************************
1144 // No special implementation for the SMP multiplication assignment to sparse matrices.
1145 //**********************************************************************************************
1146
1147 //**Compile time checks*************************************************************************
1157 //**********************************************************************************************
1158};
1159//*************************************************************************************************
1160
1161
1162
1163
1164//=================================================================================================
1165//
1166// GLOBAL BINARY ARITHMETIC OPERATORS
1167//
1168//=================================================================================================
1169
1170//*************************************************************************************************
1183template< typename MT1 // Type of the left-hand side sparse matrix
1184 , typename MT2 // Type of the right-hand side sparse matrix
1185 , DisableIf_t< ( ( IsIdentity_v<MT1> || IsIdentity_v<MT2> ) &&
1186 IsSame_v< ElementType_t<MT1>, ElementType_t<MT2> > ) ||
1187 ( IsIdentity_v<MT1> && IsIdentity_v<MT2> ) ||
1188 ( IsZero_v<MT1> || IsZero_v<MT2> ) >* = nullptr >
1189inline const SMatSMatMultExpr<MT1,MT2>
1190 smatsmatmult( const SparseMatrix<MT1,false>& lhs, const SparseMatrix<MT2,false>& rhs )
1191{
1193
1194 BLAZE_INTERNAL_ASSERT( (*lhs).columns() == (*rhs).rows(), "Invalid matrix sizes" );
1195
1196 return SMatSMatMultExpr<MT1,MT2>( *lhs, *rhs );
1197}
1199//*************************************************************************************************
1200
1201
1202//*************************************************************************************************
1216template< typename MT1 // Type of the left-hand side sparse matrix
1217 , typename MT2 // Type of the right-hand side sparse matrix
1218 , EnableIf_t< !IsIdentity_v<MT1> && IsIdentity_v<MT2> &&
1219 IsSame_v< ElementType_t<MT1>, ElementType_t<MT2> > >* = nullptr >
1220inline const MT1&
1221 smatsmatmult( const SparseMatrix<MT1,false>& lhs, const SparseMatrix<MT2,false>& rhs )
1222{
1224
1225 MAYBE_UNUSED( rhs );
1226
1227 BLAZE_INTERNAL_ASSERT( (*lhs).columns() == (*rhs).rows(), "Invalid matrix sizes" );
1228
1229 return (*lhs);
1230}
1232//*************************************************************************************************
1233
1234
1235//*************************************************************************************************
1249template< typename MT1 // Type of the left-hand side sparse matrix
1250 , typename MT2 // Type of the right-hand side sparse matrix
1251 , EnableIf_t< IsIdentity_v<MT1> && !IsIdentity_v<MT2> &&
1252 IsSame_v< ElementType_t<MT1>, ElementType_t<MT2> > >* = nullptr >
1253inline const MT2&
1254 smatsmatmult( const SparseMatrix<MT1,false>& lhs, const SparseMatrix<MT2,false>& rhs )
1255{
1257
1258 MAYBE_UNUSED( lhs );
1259
1260 BLAZE_INTERNAL_ASSERT( (*lhs).columns() == (*rhs).rows(), "Invalid matrix sizes" );
1261
1262 return (*rhs);
1263}
1265//*************************************************************************************************
1266
1267
1268//*************************************************************************************************
1281template< typename MT1 // Type of the left-hand side sparse matrix
1282 , typename MT2 // Type of the right-hand side sparse matrix
1283 , EnableIf_t< IsIdentity_v<MT1> && IsIdentity_v<MT2> >* = nullptr >
1284inline decltype(auto)
1285 smatsmatmult( const SparseMatrix<MT1,false>& lhs, const SparseMatrix<MT2,false>& rhs )
1286{
1288
1289 MAYBE_UNUSED( rhs );
1290
1291 BLAZE_INTERNAL_ASSERT( (*lhs).columns() == (*rhs).rows(), "Invalid matrix sizes" );
1292
1293 using ReturnType = const MultTrait_t< ResultType_t<MT1>, ResultType_t<MT2> >;
1294
1297
1298 return ReturnType( (*lhs).rows() );
1299}
1301//*************************************************************************************************
1302
1303
1304//*************************************************************************************************
1317template< typename MT1 // Type of the left-hand side sparse matrix
1318 , typename MT2 // Type of the right-hand side sparse matrix
1319 , EnableIf_t< IsZero_v<MT1> || IsZero_v<MT2> >* = nullptr >
1320inline decltype(auto)
1321 smatsmatmult( const SparseMatrix<MT1,false>& lhs, const SparseMatrix<MT2,false>& rhs )
1322{
1324
1325 BLAZE_INTERNAL_ASSERT( (*lhs).columns() == (*rhs).rows(), "Invalid matrix sizes" );
1326
1327 using ReturnType = const MultTrait_t< ResultType_t<MT1>, ResultType_t<MT2> >;
1328
1331
1332 return ReturnType( (*lhs).rows(), (*rhs).columns() );
1333}
1335//*************************************************************************************************
1336
1337
1338//*************************************************************************************************
1365template< typename MT1 // Type of the left-hand side sparse matrix
1366 , typename MT2 > // Type of the right-hand side sparse matrix
1367inline decltype(auto)
1368 operator*( const SparseMatrix<MT1,false>& lhs, const SparseMatrix<MT2,false>& rhs )
1369{
1371
1372 if( (*lhs).columns() != (*rhs).rows() ) {
1373 BLAZE_THROW_INVALID_ARGUMENT( "Matrix sizes do not match" );
1374 }
1375
1376 return smatsmatmult( *lhs, *rhs );
1377}
1378//*************************************************************************************************
1379
1380} // namespace blaze
1381
1382#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.
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 IsColumnMajorMatrix 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 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.
Constraints on the storage order of matrix types.
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
Expression object for sparse matrix-sparse matrix multiplications.
Definition: SMatSMatMultExpr.h:109
const ElementType ReturnType
Return type for expression template evaluations.
Definition: SMatSMatMultExpr.h:165
ResultType_t< MT1 > RT1
Result type of the left-hand side sparse matrix expression.
Definition: SMatSMatMultExpr.h:112
If_t< IsExpression_v< MT2 >, const MT2, const MT2 & > RightOperand
Composite type of the right-hand side sparse matrix expression.
Definition: SMatSMatMultExpr.h:172
bool isAliased(const T *alias) const noexcept
Returns whether the expression is aliased with the given address alias.
Definition: SMatSMatMultExpr.h:343
bool canAlias(const T *alias) const noexcept
Returns whether the expression can alias with the given address alias.
Definition: SMatSMatMultExpr.h:331
static constexpr bool evaluateRight
Compilation switch for the composite type of the right-hand side sparse matrix expression.
Definition: SMatSMatMultExpr.h:125
size_t nonZeros(size_t i) const noexcept
Returns the number of non-zero elements in the specified row.
Definition: SMatSMatMultExpr.h:298
LeftOperand lhs_
Left-hand side sparse matrix of the multiplication expression.
Definition: SMatSMatMultExpr.h:360
MultTrait_t< RT1, RT2 > ResultType
Result type for expression template evaluations.
Definition: SMatSMatMultExpr.h:161
ReturnType at(size_t i, size_t j) const
Checked access to the matrix elements.
Definition: SMatSMatMultExpr.h:251
ResultType_t< MT2 > RT2
Result type of the right-hand side sparse matrix expression.
Definition: SMatSMatMultExpr.h:113
static constexpr bool smpAssignable
Compilation switch for the expression template assignment strategy.
Definition: SMatSMatMultExpr.h:177
bool canSMPAssign() const noexcept
Returns whether the expression can be used in SMP assignments.
Definition: SMatSMatMultExpr.h:353
OppositeType_t< ResultType > OppositeType
Result type with opposite storage order for expression template evaluations.
Definition: SMatSMatMultExpr.h:162
RightOperand rightOperand() const noexcept
Returns the right-hand side sparse matrix operand.
Definition: SMatSMatMultExpr.h:319
LeftOperand leftOperand() const noexcept
Returns the left-hand side sparse matrix operand.
Definition: SMatSMatMultExpr.h:309
ReturnType operator()(size_t i, size_t j) const
2D-access to the matrix elements.
Definition: SMatSMatMultExpr.h:202
If_t< IsExpression_v< MT1 >, const MT1, const MT1 & > LeftOperand
Composite type of the left-hand side sparse matrix expression.
Definition: SMatSMatMultExpr.h:169
CompositeType_t< MT1 > CT1
Composite type of the left-hand side sparse matrix expression.
Definition: SMatSMatMultExpr.h:114
static constexpr bool evaluateLeft
Compilation switch for the composite type of the left-hand side sparse matrix expression.
Definition: SMatSMatMultExpr.h:120
SMatSMatMultExpr(const MT1 &lhs, const MT2 &rhs) noexcept
Constructor for the SMatSMatMultExpr class.
Definition: SMatSMatMultExpr.h:187
TransposeType_t< ResultType > TransposeType
Transpose type for expression template evaluations.
Definition: SMatSMatMultExpr.h:163
CompositeType_t< MT2 > CT2
Composite type of the right-hand side sparse matrix expression.
Definition: SMatSMatMultExpr.h:115
constexpr size_t nonZeros() const noexcept
Returns the number of non-zero elements in the sparse matrix.
Definition: SMatSMatMultExpr.h:287
ElementType_t< ResultType > ElementType
Resulting element type.
Definition: SMatSMatMultExpr.h:164
RightOperand rhs_
Right-hand side sparse matrix of the multiplication expression.
Definition: SMatSMatMultExpr.h:361
size_t columns() const noexcept
Returns the current number of columns of the matrix.
Definition: SMatSMatMultExpr.h:277
size_t rows() const noexcept
Returns the current number of rows of the matrix.
Definition: SMatSMatMultExpr.h:267
const ResultType CompositeType
Data type for composite expression templates.
Definition: SMatSMatMultExpr.h:166
Base class for sparse matrices.
Definition: SparseMatrix.h:77
Constraint on the data type.
Constraint on the data type.
Constraint on the data type.
Header file for the Computation base class.
Header file for the 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_BE_ROW_MAJOR_MATRIX_TYPE(T)
Constraint on the data type.
Definition: RowMajorMatrix.h:61
#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_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.