DMatTDMatSchurExpr.h
Go to the documentation of this file.
1 //=================================================================================================
33 //=================================================================================================
34 
35 #ifndef _BLAZE_MATH_EXPRESSIONS_DMATTDMATSCHUREXPR_H_
36 #define _BLAZE_MATH_EXPRESSIONS_DMATTDMATSCHUREXPR_H_
37 
38 
39 //*************************************************************************************************
40 // Includes
41 //*************************************************************************************************
42 
43 #include <blaze/math/Aliases.h>
50 #include <blaze/math/Exception.h>
74 #include <blaze/system/Blocking.h>
76 #include <blaze/util/Assert.h>
77 #include <blaze/util/DisableIf.h>
78 #include <blaze/util/EnableIf.h>
80 #include <blaze/util/mpl/And.h>
81 #include <blaze/util/mpl/If.h>
82 #include <blaze/util/mpl/Maximum.h>
83 #include <blaze/util/mpl/Not.h>
84 #include <blaze/util/mpl/Or.h>
85 #include <blaze/util/Types.h>
86 #include <blaze/util/Unused.h>
87 
88 
89 namespace blaze {
90 
91 //=================================================================================================
92 //
93 // CLASS DMATTDMATSCHUREXPR
94 //
95 //=================================================================================================
96 
97 //*************************************************************************************************
104 template< typename MT1 // Type of the left-hand side dense matrix
105  , typename MT2 > // Type of the right-hand side dense matrix
107  : public SchurExpr< DenseMatrix< DMatTDMatSchurExpr<MT1,MT2>, false > >
108  , private Computation
109 {
110  private:
111  //**Type definitions****************************************************************************
118  //**********************************************************************************************
119 
120  //**Return type evaluation**********************************************************************
122 
127  enum : bool { returnExpr = !IsTemporary<RN1>::value && !IsTemporary<RN2>::value };
128 
131  //**********************************************************************************************
132 
133  //**Serial evaluation strategy******************************************************************
135 
141  enum : bool { useAssign = RequiresEvaluation<MT1>::value || RequiresEvaluation<MT2>::value || !returnExpr };
142 
144  template< typename MT >
146  struct UseAssign {
147  enum : bool { value = useAssign };
148  };
150  //**********************************************************************************************
151 
152  //**Parallel evaluation strategy****************************************************************
154 
160  template< typename MT >
161  struct UseSMPAssign {
162  enum : bool { value = ( !MT1::smpAssignable || !MT2::smpAssignable ) && useAssign };
163  };
165  //**********************************************************************************************
166 
167  public:
168  //**Type definitions****************************************************************************
174 
177 
179  using CompositeType = const ResultType;
180 
182  using LeftOperand = If_< IsExpression<MT1>, const MT1, const MT1& >;
183 
185  using RightOperand = If_< IsExpression<MT2>, const MT2, const MT2& >;
186  //**********************************************************************************************
187 
188  //**Compilation flags***************************************************************************
190  enum : bool { simdEnabled = false };
191 
193  enum : bool { smpAssignable = MT1::smpAssignable && MT2::smpAssignable };
194  //**********************************************************************************************
195 
196  //**Constructor*********************************************************************************
202  explicit inline DMatTDMatSchurExpr( const MT1& lhs, const MT2& rhs ) noexcept
203  : lhs_( lhs ) // Left-hand side dense matrix of the Schur product expression
204  , rhs_( rhs ) // Right-hand side dense matrix of the Schur product expression
205  {
206  BLAZE_INTERNAL_ASSERT( lhs.rows() == rhs.rows() , "Invalid number of rows" );
207  BLAZE_INTERNAL_ASSERT( lhs.columns() == rhs.columns(), "Invalid number of columns" );
208  }
209  //**********************************************************************************************
210 
211  //**Access operator*****************************************************************************
218  inline ReturnType operator()( size_t i, size_t j ) const {
219  BLAZE_INTERNAL_ASSERT( i < lhs_.rows() , "Invalid row access index" );
220  BLAZE_INTERNAL_ASSERT( j < lhs_.columns(), "Invalid column access index" );
221  return lhs_(i,j) * rhs_(i,j);
222  }
223  //**********************************************************************************************
224 
225  //**At function*********************************************************************************
233  inline ReturnType at( size_t i, size_t j ) const {
234  if( i >= lhs_.rows() ) {
235  BLAZE_THROW_OUT_OF_RANGE( "Invalid row access index" );
236  }
237  if( j >= lhs_.columns() ) {
238  BLAZE_THROW_OUT_OF_RANGE( "Invalid column access index" );
239  }
240  return (*this)(i,j);
241  }
242  //**********************************************************************************************
243 
244  //**Rows function*******************************************************************************
249  inline size_t rows() const noexcept {
250  return lhs_.rows();
251  }
252  //**********************************************************************************************
253 
254  //**Columns function****************************************************************************
259  inline size_t columns() const noexcept {
260  return lhs_.columns();
261  }
262  //**********************************************************************************************
263 
264  //**Left operand access*************************************************************************
269  inline LeftOperand leftOperand() const noexcept {
270  return lhs_;
271  }
272  //**********************************************************************************************
273 
274  //**Right operand access************************************************************************
279  inline RightOperand rightOperand() const noexcept {
280  return rhs_;
281  }
282  //**********************************************************************************************
283 
284  //**********************************************************************************************
290  template< typename T >
291  inline bool canAlias( const T* alias ) const noexcept {
292  return ( IsExpression<MT1>::value && ( RequiresEvaluation<MT1>::value ? lhs_.isAliased( alias ) : lhs_.canAlias( alias ) ) ) ||
293  ( IsExpression<MT2>::value && ( RequiresEvaluation<MT2>::value ? rhs_.isAliased( alias ) : rhs_.canAlias( alias ) ) );
294  }
295  //**********************************************************************************************
296 
297  //**********************************************************************************************
303  template< typename T >
304  inline bool isAliased( const T* alias ) const noexcept {
305  return ( lhs_.isAliased( alias ) || rhs_.isAliased( alias ) );
306  }
307  //**********************************************************************************************
308 
309  //**********************************************************************************************
314  inline bool isAligned() const noexcept {
315  return lhs_.isAligned() && rhs_.isAligned();
316  }
317  //**********************************************************************************************
318 
319  //**********************************************************************************************
324  inline bool canSMPAssign() const noexcept {
325  return lhs_.canSMPAssign() || rhs_.canSMPAssign() ||
326  ( rows() * columns() >= SMP_DMATTDMATSCHUR_THRESHOLD );
327  }
328  //**********************************************************************************************
329 
330  private:
331  //**Member variables****************************************************************************
334  //**********************************************************************************************
335 
336  //**Assignment to dense matrices****************************************************************
350  template< typename MT // Type of the target dense matrix
351  , bool SO > // Storage order of the target dense matrix
352  friend inline DisableIf_< UseAssign<MT> >
353  assign( DenseMatrix<MT,SO>& lhs, const DMatTDMatSchurExpr& rhs )
354  {
356 
357  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
358  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
359 
360  constexpr size_t block( BLOCK_SIZE );
361 
362  const size_t m( rhs.rows() );
363  const size_t n( rhs.columns() );
364 
365  for( size_t ii=0UL; ii<m; ii+=block ) {
366  const size_t iend( ( m < ii+block )?( m ):( ii+block ) );
367  for( size_t jj=0UL; jj<n; jj+=block ) {
368  const size_t jend( ( n < jj+block )?( n ):( jj+block ) );
369  for( size_t i=ii; i<iend; ++i ) {
370  for( size_t j=jj; j<jend; ++j ) {
371  (~lhs)(i,j) = rhs.lhs_(i,j) * rhs.rhs_(i,j);
372  }
373  }
374  }
375  }
376  }
378  //**********************************************************************************************
379 
380  //**Assignment to dense matrices****************************************************************
394  template< typename MT // Type of the target dense matrix
395  , bool SO > // Storage order of the target dense matrix
396  friend inline EnableIf_< UseAssign<MT> >
397  assign( DenseMatrix<MT,SO>& lhs, const DMatTDMatSchurExpr& rhs )
398  {
400 
401  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
402  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
403 
404  if( !IsOperation<MT1>::value && isSame( ~lhs, rhs.lhs_ ) ) {
405  schurAssign( ~lhs, rhs.rhs_ );
406  }
407  else {
408  assign ( ~lhs, rhs.lhs_ );
409  schurAssign( ~lhs, rhs.rhs_ );
410  }
411  }
413  //**********************************************************************************************
414 
415  //**Assignment to sparse matrices***************************************************************
427  template< typename MT // Type of the target sparse matrix
428  , bool SO > // Storage order of the target sparse matrix
429  friend inline void assign( SparseMatrix<MT,SO>& lhs, const DMatTDMatSchurExpr& rhs )
430  {
432 
434 
441 
442  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
443  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
444 
445  const TmpType tmp( serial( rhs ) );
446  assign( ~lhs, tmp );
447  }
449  //**********************************************************************************************
450 
451  //**Addition assignment to dense matrices*******************************************************
466  template< typename MT // Type of the target dense matrix
467  , bool SO > // Storage order of the target dense matrix
468  friend inline DisableIf_< UseAssign<MT> >
469  addAssign( DenseMatrix<MT,SO>& lhs, const DMatTDMatSchurExpr& rhs )
470  {
472 
473  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
474  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
475 
476  constexpr size_t block( BLOCK_SIZE );
477 
478  const size_t m( rhs.rows() );
479  const size_t n( rhs.columns() );
480 
481  for( size_t ii=0UL; ii<m; ii+=block ) {
482  const size_t iend( ( m < ii+block )?( m ):( ii+block ) );
483  for( size_t jj=0UL; jj<n; jj+=block ) {
484  const size_t jend( ( n < jj+block )?( n ):( jj+block ) );
485  for( size_t i=ii; i<iend; ++i ) {
486  for( size_t j=jj; j<jend; ++j ) {
487  (~lhs)(i,j) += rhs.lhs_(i,j) * rhs.rhs_(i,j);
488  }
489  }
490  }
491  }
492  }
494  //**********************************************************************************************
495 
496  //**Addition assignment to dense matrices*******************************************************
511  template< typename MT // Type of the target dense matrix
512  , bool SO > // Storage order of the target dense matrix
513  friend inline EnableIf_< UseAssign<MT> >
514  addAssign( DenseMatrix<MT,SO>& lhs, const DMatTDMatSchurExpr& rhs )
515  {
517 
521 
522  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
523  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
524 
525  const ResultType tmp( serial( rhs ) );
526  addAssign( ~lhs, tmp );
527  }
529  //**********************************************************************************************
530 
531  //**Addition assignment to sparse matrices******************************************************
532  // No special implementation for the addition assignment to sparse matrices.
533  //**********************************************************************************************
534 
535  //**Subtraction assignment to dense matrices****************************************************
550  template< typename MT // Type of the target dense matrix
551  , bool SO > // Storage order of the target dense matrix
552  friend inline DisableIf_< UseAssign<MT> >
553  subAssign( DenseMatrix<MT,SO>& lhs, const DMatTDMatSchurExpr& rhs )
554  {
556 
557  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
558  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
559 
560  constexpr size_t block( BLOCK_SIZE );
561 
562  const size_t m( rhs.rows() );
563  const size_t n( rhs.columns() );
564 
565  for( size_t ii=0UL; ii<m; ii+=block ) {
566  const size_t iend( ( m < ii+block )?( m ):( ii+block ) );
567  for( size_t jj=0UL; jj<n; jj+=block ) {
568  const size_t jend( ( n < jj+block )?( n ):( jj+block ) );
569  for( size_t i=ii; i<iend; ++i ) {
570  for( size_t j=jj; j<jend; ++j ) {
571  (~lhs)(i,j) -= rhs.lhs_(i,j) * rhs.rhs_(i,j);
572  }
573  }
574  }
575  }
576  }
578  //**********************************************************************************************
579 
580  //**Subtraction assignment to dense matrices****************************************************
595  template< typename MT // Type of the target dense matrix
596  , bool SO > // Storage order of the target dense matrix
597  friend inline EnableIf_< UseAssign<MT> >
598  subAssign( DenseMatrix<MT,SO>& lhs, const DMatTDMatSchurExpr& rhs )
599  {
601 
605 
606  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
607  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
608 
609  const ResultType tmp( serial( rhs ) );
610  subAssign( ~lhs, tmp );
611  }
613  //**********************************************************************************************
614 
615  //**Subtraction assignment to sparse matrices***************************************************
616  // No special implementation for the subtraction assignment to sparse matrices.
617  //**********************************************************************************************
618 
619  //**Schur product assignment to dense matrices**************************************************
634  template< typename MT // Type of the target dense matrix
635  , bool SO > // Storage order of the target dense matrix
636  friend inline DisableIf_< UseAssign<MT> >
637  schurAssign( DenseMatrix<MT,SO>& lhs, const DMatTDMatSchurExpr& rhs )
638  {
640 
641  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
642  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
643 
644  constexpr size_t block( BLOCK_SIZE );
645 
646  const size_t m( rhs.rows() );
647  const size_t n( rhs.columns() );
648 
649  for( size_t ii=0UL; ii<m; ii+=block ) {
650  const size_t iend( ( m < ii+block )?( m ):( ii+block ) );
651  for( size_t jj=0UL; jj<n; jj+=block ) {
652  const size_t jend( ( n < jj+block )?( n ):( jj+block ) );
653  for( size_t i=ii; i<iend; ++i ) {
654  for( size_t j=jj; j<jend; ++j ) {
655  (~lhs)(i,j) *= rhs.lhs_(i,j) * rhs.rhs_(i,j);
656  }
657  }
658  }
659  }
660  }
662  //**********************************************************************************************
663 
664  //**Schur product assignment to dense matrices**************************************************
679  template< typename MT // Type of the target dense matrix
680  , bool SO > // Storage order of the target dense matrix
681  friend inline EnableIf_< UseAssign<MT> >
682  schurAssign( DenseMatrix<MT,SO>& lhs, const DMatTDMatSchurExpr& rhs )
683  {
685 
686  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
687  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
688 
689  schurAssign( ~lhs, rhs.lhs_ );
690  schurAssign( ~lhs, rhs.rhs_ );
691  }
693  //**********************************************************************************************
694 
695  //**Schur product assignment to sparse matrices*************************************************
696  // No special implementation for the Schur product assignment to sparse matrices.
697  //**********************************************************************************************
698 
699  //**Multiplication assignment to dense matrices*************************************************
700  // No special implementation for the multiplication assignment to dense matrices.
701  //**********************************************************************************************
702 
703  //**Multiplication assignment to sparse matrices************************************************
704  // No special implementation for the multiplication assignment to sparse matrices.
705  //**********************************************************************************************
706 
707  //**SMP assignment to dense matrices************************************************************
722  template< typename MT // Type of the target dense matrix
723  , bool SO > // Storage order of the target dense matrix
724  friend inline EnableIf_< UseSMPAssign<MT> >
726  {
728 
729  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
730  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
731 
732  if( !IsOperation<MT1>::value && isSame( ~lhs, rhs.lhs_ ) ) {
733  smpSchurAssign( ~lhs, rhs.rhs_ );
734  }
735  else {
736  smpAssign ( ~lhs, rhs.lhs_ );
737  smpSchurAssign( ~lhs, rhs.rhs_ );
738  }
739  }
741  //**********************************************************************************************
742 
743  //**SMP assignment to sparse matrices***********************************************************
758  template< typename MT // Type of the target sparse matrix
759  , bool SO > // Storage order of the target sparse matrix
760  friend inline EnableIf_< UseSMPAssign<MT> >
762  {
764 
766 
773 
774  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
775  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
776 
777  const TmpType tmp( rhs );
778  smpAssign( ~lhs, tmp );
779  }
781  //**********************************************************************************************
782 
783  //**SMP addition assignment to dense matrices***************************************************
798  template< typename MT // Type of the target dense matrix
799  , bool SO > // Storage order of the target dense matrix
800  friend inline EnableIf_< UseSMPAssign<MT> >
802  {
804 
808 
809  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
810  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
811 
812  const ResultType tmp( rhs );
813  smpAddAssign( ~lhs, tmp );
814  }
816  //**********************************************************************************************
817 
818  //**SMP addition assignment to sparse matrices**************************************************
819  // No special implementation for the SMP addition assignment to sparse matrices.
820  //**********************************************************************************************
821 
822  //**SMP subtraction assignment to dense matrices************************************************
837  template< typename MT // Type of the target dense matrix
838  , bool SO > // Storage order of the target dense matrix
839  friend inline EnableIf_< UseSMPAssign<MT> >
841  {
843 
847 
848  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
849  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
850 
851  const ResultType tmp( rhs );
852  smpSubAssign( ~lhs, tmp );
853  }
855  //**********************************************************************************************
856 
857  //**SMP subtraction assignment to sparse matrices***********************************************
858  // No special implementation for the SMP subtraction assignment to sparse matrices.
859  //**********************************************************************************************
860 
861  //**SMP Schur product assignment to dense matrices**********************************************
876  template< typename MT // Type of the target dense matrix
877  , bool SO > // Storage order of the target dense matrix
878  friend inline EnableIf_< UseSMPAssign<MT> >
880  {
882 
883  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
884  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
885 
886  smpSchurAssign( ~lhs, rhs.lhs_ );
887  smpSchurAssign( ~lhs, rhs.rhs_ );
888  }
890  //**********************************************************************************************
891 
892  //**SMP Schur product assignment to sparse matrices*********************************************
893  // No special implementation for the SMP Schur product assignment to sparse matrices.
894  //**********************************************************************************************
895 
896  //**SMP multiplication assignment to dense matrices*********************************************
897  // No special implementation for the SMP multiplication assignment to dense matrices.
898  //**********************************************************************************************
899 
900  //**SMP multiplication assignment to sparse matrices********************************************
901  // No special implementation for the SMP multiplication assignment to sparse matrices.
902  //**********************************************************************************************
903 
904  //**Compile time checks*************************************************************************
911  //**********************************************************************************************
912 };
913 //*************************************************************************************************
914 
915 
916 
917 
918 //=================================================================================================
919 //
920 // GLOBAL BINARY ARITHMETIC OPERATORS
921 //
922 //=================================================================================================
923 
924 //*************************************************************************************************
937 template< typename MT1 // Type of the left-hand side dense matrix
938  , typename MT2 > // Type of the right-hand side dense matrix
939 inline const DMatTDMatSchurExpr<MT1,MT2>
940  dmattdmatschur( const DenseMatrix<MT1,false>& lhs, const DenseMatrix<MT2,true>& rhs,
942  , Not< IsSymmetric<MT2> >
944  , Not< And< IsUniUpper<MT1>, IsUniLower<MT2> > > > >* = nullptr )
945 {
947 
948  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == (~rhs).rows() , "Invalid number of rows" );
949  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == (~rhs).columns(), "Invalid number of columns" );
950 
951  return DMatTDMatSchurExpr<MT1,MT2>( ~lhs, ~rhs );
952 }
954 //*************************************************************************************************
955 
956 
957 //*************************************************************************************************
970 template< typename MT1 // Type of the left-hand side dense matrix
971  , typename MT2 > // Type of the right-hand side dense matrix
972 inline decltype(auto)
973  dmattdmatschur( const DenseMatrix<MT1,false>& lhs, const DenseMatrix<MT2,true>& rhs,
975  , Not< IsSymmetric<MT2> >
977  , Not< And< IsUniUpper<MT1>, IsUniLower<MT2> > > > >* = nullptr )
978 {
980 
981  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == (~rhs).rows() , "Invalid number of rows" );
982  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == (~rhs).columns(), "Invalid number of columns" );
983 
984  return trans( ~lhs ) % ~rhs;
985 }
987 //*************************************************************************************************
988 
989 
990 //*************************************************************************************************
1003 template< typename MT1 // Type of the left-hand side dense matrix
1004  , typename MT2 > // Type of the right-hand side dense matrix
1005 inline decltype(auto)
1006  dmattdmatschur( const DenseMatrix<MT1,false>& lhs, const DenseMatrix<MT2,true>& rhs,
1009  , Not< And< IsUniUpper<MT1>, IsUniLower<MT2> > > > >* = nullptr )
1010 {
1012 
1013  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == (~rhs).rows() , "Invalid number of rows" );
1014  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == (~rhs).columns(), "Invalid number of columns" );
1015 
1016  return (~lhs) % trans( ~rhs );
1017 }
1019 //*************************************************************************************************
1020 
1021 
1022 //*************************************************************************************************
1035 template< typename MT1 // Type of the left-hand side dense matrix
1036  , typename MT2 > // Type of the right-hand side dense matrix
1038  dmattdmatschur( const DenseMatrix<MT1,false>& lhs, const SparseMatrix<MT2,true>& rhs,
1040  , And< IsUniUpper<MT1>, IsUniLower<MT2> > > >* = nullptr )
1041 {
1043 
1044  UNUSED_PARAMETER( rhs );
1045 
1046  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == (~rhs).rows() , "Invalid number of rows" );
1047  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == (~rhs).columns(), "Invalid number of columns" );
1048 
1049  return IdentityMatrix< MultTrait_< ElementType_<MT1>, ElementType_<MT2> >, false >( (~lhs).rows() );
1050 }
1052 //*************************************************************************************************
1053 
1054 
1055 //*************************************************************************************************
1084 template< typename MT1 // Type of the left-hand side dense matrix
1085  , typename MT2 > // Type of the right-hand side dense matrix
1086 inline decltype(auto)
1087  operator%( const DenseMatrix<MT1,false>& lhs, const DenseMatrix<MT2,true>& rhs )
1088 {
1090 
1091  if( (~lhs).rows() != (~rhs).rows() || (~lhs).columns() != (~rhs).columns() ) {
1092  BLAZE_THROW_INVALID_ARGUMENT( "Matrix sizes do not match" );
1093  }
1094 
1095  return dmattdmatschur( ~lhs, ~rhs );
1096 }
1097 //*************************************************************************************************
1098 
1099 
1100 //*************************************************************************************************
1113 template< typename MT1 // Type of the left-hand side dense matrix
1114  , typename MT2 > // Type of the right-hand side dense matrix
1115 inline const DMatTDMatSchurExpr<MT1,MT2>
1116  tdmatdmatschur( const DenseMatrix<MT1,true>& lhs, const DenseMatrix<MT2,false>& rhs,
1118  , Not< IsSymmetric<MT2> >
1120  , Not< And< IsUniUpper<MT1>, IsUniLower<MT2> > > > >* = nullptr )
1121 {
1123 
1124  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == (~rhs).rows() , "Invalid number of rows" );
1125  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == (~rhs).columns(), "Invalid number of columns" );
1126 
1127  return DMatTDMatSchurExpr<MT1,MT2>( ~lhs, ~rhs );
1128 }
1130 //*************************************************************************************************
1131 
1132 
1133 //*************************************************************************************************
1146 template< typename MT1 // Type of the left-hand side dense matrix
1147  , typename MT2 > // Type of the right-hand side dense matrix
1148 inline decltype(auto)
1149  tdmatdmatschur( const DenseMatrix<MT1,true>& lhs, const DenseMatrix<MT2,false>& rhs,
1153  , Not< And< IsUniUpper<MT1>, IsUniLower<MT2> > > > >* = nullptr )
1154 {
1156 
1157  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == (~rhs).rows() , "Invalid number of rows" );
1158  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == (~rhs).columns(), "Invalid number of columns" );
1159 
1160  return (~lhs) % trans( ~rhs );
1161 }
1163 //*************************************************************************************************
1164 
1165 
1166 //*************************************************************************************************
1179 template< typename MT1 // Type of the left-hand side dense matrix
1180  , typename MT2 > // Type of the right-hand side dense matrix
1181 inline decltype(auto)
1182  tdmatdmatschur( const DenseMatrix<MT1,true>& lhs, const DenseMatrix<MT2,false>& rhs,
1185  , Not< And< IsUniUpper<MT1>, IsUniLower<MT2> > > > >* = nullptr )
1186 {
1188 
1189  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == (~rhs).rows() , "Invalid number of rows" );
1190  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == (~rhs).columns(), "Invalid number of columns" );
1191 
1192  return trans( ~lhs ) % (~rhs);
1193 }
1195 //*************************************************************************************************
1196 
1197 
1198 //*************************************************************************************************
1211 template< typename MT1 // Type of the left-hand side dense matrix
1212  , typename MT2 > // Type of the right-hand side dense matrix
1214  tdmatdmatschur( const DenseMatrix<MT1,true>& lhs, const SparseMatrix<MT2,false>& rhs,
1216  , And< IsUniUpper<MT1>, IsUniLower<MT2> > > >* = nullptr )
1217 {
1219 
1220  UNUSED_PARAMETER( rhs );
1221 
1222  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == (~rhs).rows() , "Invalid number of rows" );
1223  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == (~rhs).columns(), "Invalid number of columns" );
1224 
1226 }
1228 //*************************************************************************************************
1229 
1230 
1231 //*************************************************************************************************
1260 template< typename MT1 // Type of the left-hand side dense matrix
1261  , typename MT2 > // Type of the right-hand side dense matrix
1262 inline decltype(auto)
1263  operator%( const DenseMatrix<MT1,true>& lhs, const DenseMatrix<MT2,false>& rhs )
1264 {
1266 
1267  if( (~lhs).rows() != (~rhs).rows() || (~lhs).columns() != (~rhs).columns() ) {
1268  BLAZE_THROW_INVALID_ARGUMENT( "Matrix sizes do not match" );
1269  }
1270 
1271  return tdmatdmatschur( ~lhs, ~rhs );
1272 }
1273 //*************************************************************************************************
1274 
1275 
1276 
1277 
1278 //=================================================================================================
1279 //
1280 // SIZE SPECIALIZATIONS
1281 //
1282 //=================================================================================================
1283 
1284 //*************************************************************************************************
1286 template< typename MT1, typename MT2 >
1287 struct Size< DMatTDMatSchurExpr<MT1,MT2>, 0UL >
1288  : public Maximum< Size<MT1,0UL>, Size<MT2,0UL> >
1289 {};
1290 
1291 template< typename MT1, typename MT2 >
1292 struct Size< DMatTDMatSchurExpr<MT1,MT2>, 1UL >
1293  : public Maximum< Size<MT1,1UL>, Size<MT2,1UL> >
1294 {};
1296 //*************************************************************************************************
1297 
1298 
1299 
1300 
1301 //=================================================================================================
1302 //
1303 // ISALIGNED SPECIALIZATIONS
1304 //
1305 //=================================================================================================
1306 
1307 //*************************************************************************************************
1309 template< typename MT1, typename MT2 >
1310 struct IsAligned< DMatTDMatSchurExpr<MT1,MT2> >
1311  : public And< IsAligned<MT1>, IsAligned<MT2> >
1312 {};
1314 //*************************************************************************************************
1315 
1316 
1317 
1318 
1319 //=================================================================================================
1320 //
1321 // ISSYMMETRIC SPECIALIZATIONS
1322 //
1323 //=================================================================================================
1324 
1325 //*************************************************************************************************
1327 template< typename MT1, typename MT2 >
1328 struct IsSymmetric< DMatTDMatSchurExpr<MT1,MT2> >
1329  : public And< IsSymmetric<MT1>, IsSymmetric<MT2> >
1330 {};
1332 //*************************************************************************************************
1333 
1334 
1335 
1336 
1337 //=================================================================================================
1338 //
1339 // ISHERMITIAN SPECIALIZATIONS
1340 //
1341 //=================================================================================================
1342 
1343 //*************************************************************************************************
1345 template< typename MT1, typename MT2 >
1346 struct IsHermitian< DMatTDMatSchurExpr<MT1,MT2> >
1347  : public And< IsHermitian<MT1>, IsHermitian<MT2> >
1348 {};
1350 //*************************************************************************************************
1351 
1352 
1353 
1354 
1355 //=================================================================================================
1356 //
1357 // ISLOWER SPECIALIZATIONS
1358 //
1359 //=================================================================================================
1360 
1361 //*************************************************************************************************
1363 template< typename MT1, typename MT2 >
1364 struct IsLower< DMatTDMatSchurExpr<MT1,MT2> >
1365  : public Or< IsLower<MT1>, IsLower<MT2> >
1366 {};
1368 //*************************************************************************************************
1369 
1370 
1371 
1372 
1373 //=================================================================================================
1374 //
1375 // ISUNILOWER SPECIALIZATIONS
1376 //
1377 //=================================================================================================
1378 
1379 //*************************************************************************************************
1381 template< typename MT1, typename MT2 >
1382 struct IsUniLower< DMatTDMatSchurExpr<MT1,MT2> >
1383  : public And< IsUniLower<MT1>, IsUniLower<MT2> >
1384 {};
1386 //*************************************************************************************************
1387 
1388 
1389 
1390 
1391 //=================================================================================================
1392 //
1393 // ISSTRICTLYLOWER SPECIALIZATIONS
1394 //
1395 //=================================================================================================
1396 
1397 //*************************************************************************************************
1399 template< typename MT1, typename MT2 >
1400 struct IsStrictlyLower< DMatTDMatSchurExpr<MT1,MT2> >
1401  : public Or< IsStrictlyLower<MT1>, IsStrictlyLower<MT2> >
1402 {};
1404 //*************************************************************************************************
1405 
1406 
1407 
1408 
1409 //=================================================================================================
1410 //
1411 // ISUPPER SPECIALIZATIONS
1412 //
1413 //=================================================================================================
1414 
1415 //*************************************************************************************************
1417 template< typename MT1, typename MT2 >
1418 struct IsUpper< DMatTDMatSchurExpr<MT1,MT2> >
1419  : public Or< IsUpper<MT1>, IsUpper<MT2> >
1420 {};
1422 //*************************************************************************************************
1423 
1424 
1425 
1426 
1427 //=================================================================================================
1428 //
1429 // ISUNIUPPER SPECIALIZATIONS
1430 //
1431 //=================================================================================================
1432 
1433 //*************************************************************************************************
1435 template< typename MT1, typename MT2 >
1436 struct IsUniUpper< DMatTDMatSchurExpr<MT1,MT2> >
1437  : public And< IsUniUpper<MT1>, IsUniUpper<MT2> >
1438 {};
1440 //*************************************************************************************************
1441 
1442 
1443 
1444 
1445 //=================================================================================================
1446 //
1447 // ISSTRICTLYUPPER SPECIALIZATIONS
1448 //
1449 //=================================================================================================
1450 
1451 //*************************************************************************************************
1453 template< typename MT1, typename MT2 >
1454 struct IsStrictlyUpper< DMatTDMatSchurExpr<MT1,MT2> >
1455  : public Or< IsStrictlyUpper<MT1>, IsStrictlyUpper<MT2> >
1456 {};
1458 //*************************************************************************************************
1459 
1460 } // namespace blaze
1461 
1462 #endif
#define BLAZE_THROW_INVALID_ARGUMENT(MESSAGE)
Macro for the emission of a std::invalid_argument exception.This macro encapsulates the default way o...
Definition: Exception.h:235
Header file for auxiliary alias declarations.
Header file for kernel specific block sizes.
Header file for the Schur product trait.
Compile time check whether the given type is a temporary vector or matrix type.This type trait class ...
Definition: IsTemporary.h:69
Header file for the UNUSED_PARAMETER function template.
Header file for the IsUniUpper type trait.
EnableIf_< IsDenseMatrix< MT1 > > smpSchurAssign(Matrix< MT1, SO1 > &lhs, const Matrix< MT2, SO2 > &rhs)
Default implementation of the SMP Schur product assignment of a matrix to dense matrix.
Definition: DenseMatrix.h:196
LeftOperand lhs_
Left-hand side dense matrix of the Schur product expression.
Definition: DMatTDMatSchurExpr.h:332
bool isAligned() const noexcept
Returns whether the operands of the expression are properly aligned in memory.
Definition: DMatTDMatSchurExpr.h:314
BLAZE_ALWAYS_INLINE bool isSame(const Matrix< MT1, SO1 > &a, const Matrix< MT2, SO2 > &b) noexcept
Returns whether the two given matrices represent the same observable state.
Definition: Matrix.h:949
Header file for basic type definitions.
Compile time check whether the given type is an operational expression template.This type trait class...
Definition: IsOperation.h:70
EnableIf_< IsDenseMatrix< MT1 > > smpSubAssign(Matrix< MT1, SO1 > &lhs, const Matrix< MT2, SO2 > &rhs)
Default implementation of the SMP subtraction assignment of a matrix to dense matrix.
Definition: DenseMatrix.h:164
Header file for the serial shim.
#define BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE(T)
Constraint on the data type.In case the given data type T is not a dense, N-dimensional matrix type...
Definition: DenseMatrix.h:61
CompositeType_< MT1 > CT1
Composite type of the left-hand side dense matrix expression.
Definition: DMatTDMatSchurExpr.h:116
TransposeType_< ResultType > TransposeType
Transpose type for expression template evaluations.
Definition: DMatTDMatSchurExpr.h:172
LeftOperand leftOperand() const noexcept
Returns the left-hand side dense matrix operand.
Definition: DMatTDMatSchurExpr.h:269
typename DisableIf< Condition, T >::Type DisableIf_
Auxiliary type for the DisableIf class template.The DisableIf_ alias declaration provides a convenien...
Definition: DisableIf.h:224
Header file for the And class template.
Compile time value evaluation.The Maximum alias declaration selects the larger of the two given templ...
Definition: Maximum.h:73
Compile time check for lower triangular matrices.This type trait tests whether or not the given templ...
Definition: IsLower.h:87
RightOperand rightOperand() const noexcept
Returns the right-hand side transpose dense matrix operand.
Definition: DMatTDMatSchurExpr.h:279
const ResultType CompositeType
Data type for composite expression templates.
Definition: DMatTDMatSchurExpr.h:179
Header file for the Computation base class.
Compile time check for upper triangular matrices.This type trait tests whether or not the given templ...
Definition: IsUpper.h:87
Constraints on the storage order of matrix types.
Header file for the RequiresEvaluation type trait.
Header file for the IsUniLower type trait.
typename T::ResultType ResultType_
Alias declaration for nested ResultType type definitions.The ResultType_ alias declaration provides a...
Definition: Aliases.h:343
EnableIf_< IsDenseMatrix< MT1 > > smpAddAssign(Matrix< MT1, SO1 > &lhs, const Matrix< MT2, SO2 > &rhs)
Default implementation of the SMP addition assignment of a matrix to a dense matrix.
Definition: DenseMatrix.h:133
#define BLAZE_CONSTRAINT_MUST_FORM_VALID_SCHUREXPR(T1, T2)
Constraint on the data type.In case the given data types T1 and T2 do not form a valid matrix/matrix ...
Definition: SchurExpr.h:107
Base class for dense matrices.The DenseMatrix class is a base class for all dense matrix classes...
Definition: DenseMatrix.h:80
Base class for sparse matrices.The SparseMatrix class is a base class for all sparse matrix classes...
Definition: Forward.h:129
Header file for all forward declarations for sparse vectors and matrices.
bool canAlias(const T *alias) const noexcept
Returns whether the expression can alias with the given address alias.
Definition: DMatTDMatSchurExpr.h:291
typename IfTrue< Condition, T1, T2 >::Type IfTrue_
Auxiliary alias declaration for the IfTrue class template.The IfTrue_ alias declaration provides a co...
Definition: If.h:109
typename T::ReturnType ReturnType_
Alias declaration for nested ReturnType type definitions.The ReturnType_ alias declaration provides a...
Definition: Aliases.h:363
Compile time check for the alignment of data types.This type trait tests whether the given data type ...
Definition: IsAligned.h:87
Constraint on the data type.
Header file for the Maximum class template.
typename MultExprTrait< T1, T2 >::Type MultExprTrait_
Auxiliary alias declaration for the MultExprTrait class template.The MultExprTrait_ alias declaration...
Definition: MultExprTrait.h:112
Header file for the MultExprTrait class template.
Compile time check to query the requirement to evaluate an expression.Via this type trait it is possi...
Definition: RequiresEvaluation.h:71
typename T::CompositeType CompositeType_
Alias declaration for nested CompositeType type definitions.The CompositeType_ alias declaration prov...
Definition: Aliases.h:83
Compile time check for upper unitriangular matrices.This type trait tests whether or not the given te...
Definition: IsUniUpper.h:86
ResultType_< MT2 > RT2
Result type of the right-hand side dense matrix expression.
Definition: DMatTDMatSchurExpr.h:113
Efficient implementation of an identity matrix.The IdentityMatrix class template is the representati...
Definition: Forward.h:49
Header file for the DisableIf class template.
Header file for the IsTemporary type trait class.
Header file for the multiplication trait.
Header file for the IsStrictlyUpper type trait.
Header file for the IsSymmetric type trait.
Namespace of the Blaze C++ math library.
Definition: Blaze.h:58
Header file for the If class template.
#define BLAZE_CONSTRAINT_MUST_BE_COLUMN_MAJOR_MATRIX_TYPE(T)
Constraint on the data type.In case the given data type T is not a column-major dense or sparse matri...
Definition: ColumnMajorMatrix.h:61
size_t columns() const noexcept
Returns the current number of columns of the matrix.
Definition: DMatTDMatSchurExpr.h:259
EnableIf_< IsDenseMatrix< MT1 > > smpAssign(Matrix< MT1, SO1 > &lhs, const Matrix< MT2, SO2 > &rhs)
Default implementation of the SMP assignment of a matrix to a dense matrix.
Definition: DenseMatrix.h:102
Header file for the Or class template.
#define BLAZE_THROW_OUT_OF_RANGE(MESSAGE)
Macro for the emission of a std::out_of_range exception.This macro encapsulates the default way of Bl...
Definition: Exception.h:331
Header file for the DenseMatrix base class.
Header file for the Not class template.
typename T::ElementType ElementType_
Alias declaration for nested ElementType type definitions.The ElementType_ alias declaration provides...
Definition: Aliases.h:163
Header file for the IsOperation type trait class.
Header file for the IsLower type trait.
typename SchurTrait< T1, T2 >::Type SchurTrait_
Auxiliary alias declaration for the SchurTrait class template.The SchurTrait_ alias declaration provi...
Definition: SchurTrait.h:208
Header file for the IsAligned type trait.
Constraints on the storage order of matrix types.
Compile time check for symmetric matrices.This type trait tests whether or not the given template par...
Definition: IsSymmetric.h:85
Header file for the exception macros of the math module.
Compile time check for strictly upper triangular matrices.This type trait tests whether or not the gi...
Definition: IsStrictlyUpper.h:86
ResultType_< MT1 > RT1
Result type of the left-hand side dense matrix expression.
Definition: DMatTDMatSchurExpr.h:112
const IfTrue_< returnExpr, ExprReturnType, ElementType > ReturnType
Return type for expression template evaluations.
Definition: DMatTDMatSchurExpr.h:176
Constraint on the data type.
Header file for all forward declarations for expression class templates.
Header file for the EnableIf class template.
Header file for the IsStrictlyLower type trait.
If_< IsExpression< MT2 >, const MT2, const MT2 &> RightOperand
Composite type of the right-hand side dense matrix expression.
Definition: DMatTDMatSchurExpr.h:185
#define BLAZE_CONSTRAINT_MATRICES_MUST_HAVE_DIFFERENT_STORAGE_ORDER(T1, T2)
Constraint on the data type.In case either of the two given data types T1 or T2 is not a matrix type ...
Definition: StorageOrder.h:106
Compile time check for lower unitriangular matrices.This type trait tests whether or not the given te...
Definition: IsUniLower.h:86
CompositeType_< MT2 > CT2
Composite type of the right-hand side dense matrix expression.
Definition: DMatTDMatSchurExpr.h:117
ReturnType at(size_t i, size_t j) const
Checked access to the matrix elements.
Definition: DMatTDMatSchurExpr.h:233
#define BLAZE_CONSTRAINT_MUST_BE_ROW_MAJOR_MATRIX_TYPE(T)
Constraint on the data type.In case the given data type T is not a row-major dense or sparse matrix t...
Definition: RowMajorMatrix.h:61
DMatTDMatSchurExpr(const MT1 &lhs, const MT2 &rhs) noexcept
Constructor for the DMatTDMatSchurExpr class.
Definition: DMatTDMatSchurExpr.h:202
Base class for all Schur product expression templates.The SchurExpr class serves as a tag for all exp...
Definition: SchurExpr.h:66
Header file for run time assertion macros.
If_< IsExpression< MT1 >, const MT1, const MT1 &> LeftOperand
Composite type of the left-hand side dense matrix expression.
Definition: DMatTDMatSchurExpr.h:182
Header file for the SchurExpr base class.
typename If< T1, T2, T3 >::Type If_
Auxiliary alias declaration for the If class template.The If_ alias declaration provides a convenient...
Definition: If.h:154
#define BLAZE_FUNCTION_TRACE
Function trace macro.This macro can be used to reliably trace function calls. In case function tracin...
Definition: FunctionTrace.h:94
Compile time type negation.The Not alias declaration negates the given compile time condition...
Definition: Not.h:70
Compile time check for Hermitian matrices.This type trait tests whether or not the given template par...
Definition: IsHermitian.h:85
Expression object for dense matrix-transpose dense matrix Schur product.The DMatTDMatSchurExpr class ...
Definition: DMatTDMatSchurExpr.h:106
Constraints on the storage order of matrix types.
decltype(auto) serial(const DenseMatrix< MT, SO > &dm)
Forces the serial evaluation of the given dense matrix expression dm.
Definition: DMatSerialExpr.h:816
#define BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION(T)
Constraint on the data type.In case the given data type T requires an intermediate evaluation within ...
Definition: RequiresEvaluation.h:81
bool canSMPAssign() const noexcept
Returns whether the expression can be used in SMP assignments.
Definition: DMatTDMatSchurExpr.h:324
RightOperand rhs_
Right-hand side dense matrix of the Schur product expression.
Definition: DMatTDMatSchurExpr.h:333
OppositeType_< ResultType > OppositeType
Result type with opposite storage order for expression template evaluations.
Definition: DMatTDMatSchurExpr.h:171
typename EnableIf< Condition, T >::Type EnableIf_
Auxiliary alias declaration for the EnableIf class template.The EnableIf_ alias declaration provides ...
Definition: EnableIf.h:224
ReturnType_< MT2 > RN2
Return type of the right-hand side dense matrix expression.
Definition: DMatTDMatSchurExpr.h:115
typename T::OppositeType OppositeType_
Alias declaration for nested OppositeType type definitions.The OppositeType_ alias declaration provid...
Definition: Aliases.h:263
#define BLAZE_CONSTRAINT_MATRICES_MUST_HAVE_SAME_STORAGE_ORDER(T1, T2)
Constraint on the data type.In case either of the two given data types T1 or T2 is not a matrix type ...
Definition: StorageOrder.h:84
ElementType_< ResultType > ElementType
Resulting element type.
Definition: DMatTDMatSchurExpr.h:173
Compile time check for strictly lower triangular matrices.This type trait tests whether or not the gi...
Definition: IsStrictlyLower.h:86
decltype(auto) trans(const DenseMatrix< MT, SO > &dm)
Calculation of the transpose of the given dense matrix.
Definition: DMatTransExpr.h:789
MultExprTrait_< RN1, RN2 > ExprReturnType
Expression return type for the subscript operator.
Definition: DMatTDMatSchurExpr.h:130
Base class for all compute expression templates.The Computation class serves as a tag for all computa...
Definition: Computation.h:66
Compile time logical &#39;or&#39; evaluation.The Or alias declaration performs at compile time a logical &#39;or&#39;...
Definition: Or.h:76
Compile time evaluation of the size of vectors and matrices.The Size type trait evaluates the size of...
Definition: Size.h:80
ReturnType_< MT1 > RN1
Return type of the left-hand side dense matrix expression.
Definition: DMatTDMatSchurExpr.h:114
size_t rows() const noexcept
Returns the current number of rows of the matrix.
Definition: DMatTDMatSchurExpr.h:249
Compile time logical &#39;and&#39; evaluation.The And alias declaration performs at compile time a logical &#39;a...
Definition: And.h:76
bool isAliased(const T *alias) const noexcept
Returns whether the expression is aliased with the given address alias.
Definition: DMatTDMatSchurExpr.h:304
SchurTrait_< RT1, RT2 > ResultType
Result type for expression template evaluations.
Definition: DMatTDMatSchurExpr.h:170
typename T::TransposeType TransposeType_
Alias declaration for nested TransposeType type definitions.The TransposeType_ alias declaration prov...
Definition: Aliases.h:423
Header file for the IsUpper type trait.
void UNUSED_PARAMETER(const Args &...)
Suppression of unused parameter warnings.
Definition: Unused.h:81
Header file for the IsHermitian type trait.
Header file for the Size type trait.
Header file for the thresholds for matrix/vector and matrix/matrix multiplications.
#define BLAZE_INTERNAL_ASSERT(expr, msg)
Run time assertion macro for internal checks.In case of an invalid run time expression, the program execution is terminated. The BLAZE_INTERNAL_ASSERT macro can be disabled by setting the BLAZE_USER_ASSERTION flag to zero or by defining NDEBUG during the compilation.
Definition: Assert.h:101
Compile time check whether the given type is an expression template.This type trait class tests wheth...
Definition: IsExpression.h:95
ReturnType operator()(size_t i, size_t j) const
2D-access to the matrix elements.
Definition: DMatTDMatSchurExpr.h:218
Header file for the IsExpression type trait class.
Header file for the function trace functionality.
Constraint on the data type.