Blaze  3.6
SparseMatrix.h
Go to the documentation of this file.
1 //=================================================================================================
33 //=================================================================================================
34 
35 #ifndef _BLAZE_MATH_SPARSE_SPARSEMATRIX_H_
36 #define _BLAZE_MATH_SPARSE_SPARSEMATRIX_H_
37 
38 
39 //*************************************************************************************************
40 // Includes
41 //*************************************************************************************************
42 
43 #include <utility>
44 #include <blaze/math/Aliases.h>
50 #include <blaze/math/shims/Equal.h>
52 #include <blaze/math/shims/IsNaN.h>
53 #include <blaze/math/shims/IsOne.h>
79 #include <blaze/util/Assert.h>
80 #include <blaze/util/EnableIf.h>
82 #include <blaze/util/mpl/If.h>
83 #include <blaze/util/Types.h>
88 
89 
90 namespace blaze {
91 
92 //=================================================================================================
93 //
94 // GLOBAL OPERATORS
95 //
96 //=================================================================================================
97 
98 //*************************************************************************************************
101 template< typename MT, bool SO, typename ST >
102 auto operator*=( SparseMatrix<MT,SO>& mat, ST scalar )
103  -> EnableIf_t< IsNumeric_v<ST>, MT& >;
104 
105 template< typename MT, bool SO, typename ST >
106 auto operator*=( SparseMatrix<MT,SO>&& mat, ST scalar )
107  -> EnableIf_t< IsNumeric_v<ST>, MT& >;
108 
109 template< typename MT, bool SO, typename ST >
110 auto operator/=( SparseMatrix<MT,SO>& mat, ST scalar )
111  -> EnableIf_t< IsNumeric_v<ST>, MT& >;
112 
113 template< typename MT, bool SO, typename ST >
114 auto operator/=( SparseMatrix<MT,SO>&& mat, ST scalar )
115  -> EnableIf_t< IsNumeric_v<ST>, MT& >;
117 //*************************************************************************************************
118 
119 
120 //*************************************************************************************************
133 template< typename MT // Type of the left-hand side sparse matrix
134  , bool SO // Storage order
135  , typename ST > // Data type of the right-hand side scalar
136 inline auto operator*=( SparseMatrix<MT,SO>& mat, ST scalar )
138 {
140 
141  if( IsRestricted_v<MT> ) {
142  if( !tryMult( ~mat, 0UL, 0UL, (~mat).rows(), (~mat).columns(), scalar ) ) {
143  BLAZE_THROW_INVALID_ARGUMENT( "Invalid scaling of restricted matrix" );
144  }
145  }
146 
147  if( !IsResizable_v< ElementType_t<MT> > && isZero( scalar ) )
148  {
149  reset( ~mat );
150  }
151  else
152  {
153  decltype(auto) left( derestrict( ~mat ) );
154 
155  const size_t iend( SO == rowMajor ? (~mat).rows() : (~mat).columns() );
156  for( size_t i=0UL; i<iend; ++i ) {
157  const auto last( left.end(i) );
158  for( auto element=left.begin(i); element!=last; ++element ) {
159  element->value() *= scalar;
160  }
161  }
162  }
163 
164  BLAZE_INTERNAL_ASSERT( isIntact( ~mat ), "Invariant violation detected" );
165 
166  return ~mat;
167 }
168 //*************************************************************************************************
169 
170 
171 //*************************************************************************************************
184 template< typename MT // Type of the left-hand side sparse matrix
185  , bool SO // Storage order
186  , typename ST > // Data type of the right-hand side scalar
187 inline auto operator*=( SparseMatrix<MT,SO>&& mat, ST scalar )
189 {
190  return operator*=( ~mat, scalar );
191 }
192 //*************************************************************************************************
193 
194 
195 //*************************************************************************************************
210 template< typename MT // Type of the left-hand side sparse matrix
211  , bool SO // Storage order
212  , typename ST > // Data type of the right-hand side scalar
213 inline auto operator/=( SparseMatrix<MT,SO>& mat, ST scalar )
215 {
217 
218  BLAZE_USER_ASSERT( !isZero( scalar ), "Division by zero detected" );
219 
220  if( IsRestricted_v<MT> ) {
221  if( !tryDiv( ~mat, 0UL, 0UL, (~mat).rows(), (~mat).columns(), scalar ) ) {
222  BLAZE_THROW_INVALID_ARGUMENT( "Invalid scaling of restricted matrix" );
223  }
224  }
225 
227  IsFloatingPoint_v< UnderlyingBuiltin_t<ST> >
228  , If_t< IsComplex_v< UnderlyingNumeric_t<MT> > && IsBuiltin_v<ST>
231  , ST >;
232 
233  decltype(auto) left( derestrict( ~mat ) );
234 
235  if( IsInvertible_v<ScalarType> ) {
236  const ScalarType tmp( ScalarType(1)/static_cast<ScalarType>( scalar ) );
237  const size_t iend( SO == rowMajor ? (~mat).rows() : (~mat).columns() );
238  for( size_t i=0UL; i<iend; ++i ) {
239  const auto last( left.end(i) );
240  for( auto element=left.begin(i); element!=last; ++element ) {
241  element->value() *= tmp;
242  }
243  }
244  }
245  else {
246  const size_t iend( SO == rowMajor ? (~mat).rows() : (~mat).columns() );
247  for( size_t i=0UL; i<iend; ++i ) {
248  const auto last( left.end(i) );
249  for( auto element=left.begin(i); element!=last; ++element ) {
250  element->value() /= scalar;
251  }
252  }
253  }
254 
255  BLAZE_INTERNAL_ASSERT( isIntact( ~mat ), "Invariant violation detected" );
256 
257  return ~mat;
258 }
259 //*************************************************************************************************
260 
261 
262 //*************************************************************************************************
277 template< typename MT // Type of the left-hand side sparse matrix
278  , bool SO // Storage order
279  , typename ST > // Data type of the right-hand side scalar
280 inline auto operator/=( SparseMatrix<MT,SO>&& mat, ST scalar )
282 {
283  return operator/=( ~mat, scalar );
284 }
285 //*************************************************************************************************
286 
287 
288 
289 
290 //=================================================================================================
291 //
292 // GLOBAL FUNCTIONS
293 //
294 //=================================================================================================
295 
296 //*************************************************************************************************
299 template< typename MT, bool SO >
300 bool isnan( const SparseMatrix<MT,SO>& sm );
301 
302 template< bool RF, typename MT, bool SO >
303 bool isSymmetric( const SparseMatrix<MT,SO>& sm );
304 
305 template< bool RF, typename MT, bool SO >
306 bool isHermitian( const SparseMatrix<MT,SO>& sm );
307 
308 template< bool RF, typename MT, bool SO >
309 bool isUniform( const SparseMatrix<MT,SO>& sm );
310 
311 template< bool RF, typename MT, bool SO >
312 bool isZero( const SparseMatrix<MT,SO>& sm );
313 
314 template< bool RF, typename MT, bool SO >
315 bool isLower( const SparseMatrix<MT,SO>& sm );
316 
317 template< bool RF, typename MT, bool SO >
318 bool isUniLower( const SparseMatrix<MT,SO>& sm );
319 
320 template< bool RF, typename MT, bool SO >
321 bool isStrictlyLower( const SparseMatrix<MT,SO>& sm );
322 
323 template< bool RF, typename MT, bool SO >
324 bool isUpper( const SparseMatrix<MT,SO>& sm );
325 
326 template< bool RF, typename MT, bool SO >
327 bool isUniUpper( const SparseMatrix<MT,SO>& sm );
328 
329 template< bool RF, typename MT, bool SO >
330 bool isStrictlyUpper( const SparseMatrix<MT,SO>& sm );
331 
332 template< bool RF, typename MT, bool SO >
333 bool isDiagonal( const SparseMatrix<MT,SO>& sm );
334 
335 template< bool RF, typename MT, bool SO >
336 bool isIdentity( const SparseMatrix<MT,SO>& sm );
338 //*************************************************************************************************
339 
340 
341 //*************************************************************************************************
361 template< typename MT // Type of the sparse matrix
362  , bool SO > // Storage order
363 bool isnan( const SparseMatrix<MT,SO>& sm )
364 {
365  CompositeType_t<MT> A( ~sm ); // Evaluation of the sparse matrix operand
366 
367  if( SO == rowMajor ) {
368  for( size_t i=0UL; i<A.rows(); ++i ) {
369  for( auto element=A.begin(i); element!=A.end(i); ++element )
370  if( isnan( element->value() ) ) return true;
371  }
372  }
373  else {
374  for( size_t j=0UL; j<A.columns(); ++j ) {
375  for( auto element=A.begin(j); element!=A.end(j); ++element )
376  if( isnan( element->value() ) ) return true;
377  }
378  }
379 
380  return false;
381 }
382 //*************************************************************************************************
383 
384 
385 //*************************************************************************************************
418 template< bool RF // Relaxation flag
419  , typename MT // Type of the sparse matrix
420  , bool SO > // Storage order
422 {
423  using RT = ResultType_t<MT>;
424  using RN = ReturnType_t<MT>;
425  using CT = CompositeType_t<MT>;
426  using Tmp = If_t< IsExpression_v<RN>, const RT, CT >;
427 
428  if( IsSymmetric_v<MT> )
429  return true;
430 
431  if( !isSquare( ~sm ) )
432  return false;
433 
434  if( IsUniform_v<MT> || (~sm).rows() < 2UL )
435  return true;
436 
437  Tmp A( ~sm ); // Evaluation of the sparse matrix operand
438 
439  if( SO == rowMajor ) {
440  for( size_t i=0UL; i<A.rows(); ++i ) {
441  for( auto element=A.begin(i); element!=A.end(i); ++element )
442  {
443  const size_t j( element->index() );
444 
445  if( i == j || isDefault<RF>( element->value() ) )
446  continue;
447 
448  const auto pos( A.find( j, i ) );
449  if( pos == A.end(j) || !equal<RF>( pos->value(), element->value() ) )
450  return false;
451  }
452  }
453  }
454  else {
455  for( size_t j=0UL; j<A.columns(); ++j ) {
456  for( auto element=A.begin(j); element!=A.end(j); ++element )
457  {
458  const size_t i( element->index() );
459 
460  if( j == i || isDefault<RF>( element->value() ) )
461  continue;
462 
463  const auto pos( A.find( j, i ) );
464  if( pos == A.end(i) || !equal<RF>( pos->value(), element->value() ) )
465  return false;
466  }
467  }
468  }
469 
470  return true;
471 }
472 //*************************************************************************************************
473 
474 
475 //*************************************************************************************************
510 template< bool RF // Relaxation flag
511  , typename MT // Type of the sparse matrix
512  , bool SO > // Storage order
514 {
515  using RT = ResultType_t<MT>;
516  using ET = ElementType_t<MT>;
517  using RN = ReturnType_t<MT>;
518  using CT = CompositeType_t<MT>;
519  using Tmp = If_t< IsExpression_v<RN>, const RT, CT >;
520 
521  if( IsHermitian_v<MT> )
522  return true;
523 
524  if( !IsNumeric_v<ET> || !isSquare( ~sm ) )
525  return false;
526 
527  if( IsBuiltin_v<ET> && IsUniform_v<MT> )
528  return true;
529 
530  Tmp A( ~sm ); // Evaluation of the sparse matrix operand
531 
532  if( SO == rowMajor ) {
533  for( size_t i=0UL; i<A.rows(); ++i ) {
534  for( auto element=A.begin(i); element!=A.end(i); ++element )
535  {
536  const size_t j( element->index() );
537 
538  if( isDefault<RF>( element->value() ) )
539  continue;
540 
541  if( i == j && !isReal<RF>( element->value() ) )
542  return false;
543 
544  const auto pos( A.find( j, i ) );
545  if( pos == A.end(j) || !equal<RF>( pos->value(), conj( element->value() ) ) )
546  return false;
547  }
548  }
549  }
550  else {
551  for( size_t j=0UL; j<A.columns(); ++j ) {
552  for( auto element=A.begin(j); element!=A.end(j); ++element )
553  {
554  const size_t i( element->index() );
555 
556  if( isDefault<RF>( element->value() ) )
557  continue;
558 
559  if( j == i && !isReal<RF>( element->value() ) )
560  return false;
561 
562  const auto pos( A.find( j, i ) );
563  if( pos == A.end(i) || !equal<RF>( pos->value(), conj( element->value() ) ) )
564  return false;
565  }
566  }
567  }
568 
569  return true;
570 }
571 //*************************************************************************************************
572 
573 
574 //*************************************************************************************************
582 template< bool RF // Relaxation flag
583  , typename MT > // Type of the sparse matrix
584 bool isUniform_backend( const SparseMatrix<MT,false>& sm, TrueType )
585 {
588 
589  BLAZE_INTERNAL_ASSERT( (~sm).rows() != 0UL, "Invalid number of rows detected" );
590  BLAZE_INTERNAL_ASSERT( (~sm).columns() != 0UL, "Invalid number of columns detected" );
591 
592  const size_t ibegin( ( IsStrictlyLower_v<MT> )?( 1UL ):( 0UL ) );
593  const size_t iend ( ( IsStrictlyUpper_v<MT> )?( (~sm).rows()-1UL ):( (~sm).rows() ) );
594 
595  for( size_t i=ibegin; i<iend; ++i ) {
596  for( auto element=(~sm).begin(i); element!=(~sm).end(i); ++element ) {
597  if( !isDefault<RF>( element->value() ) )
598  return false;
599  }
600  }
601 
602  return true;
603 }
605 //*************************************************************************************************
606 
607 
608 //*************************************************************************************************
616 template< bool RF // Relaxation flag
617  , typename MT > // Type of the sparse matrix
618 bool isUniform_backend( const SparseMatrix<MT,true>& sm, TrueType )
619 {
622 
623  BLAZE_INTERNAL_ASSERT( (~sm).rows() != 0UL, "Invalid number of rows detected" );
624  BLAZE_INTERNAL_ASSERT( (~sm).columns() != 0UL, "Invalid number of columns detected" );
625 
626  const size_t jbegin( ( IsStrictlyUpper_v<MT> )?( 1UL ):( 0UL ) );
627  const size_t jend ( ( IsStrictlyLower_v<MT> )?( (~sm).columns()-1UL ):( (~sm).columns() ) );
628 
629  for( size_t j=jbegin; j<jend; ++j ) {
630  for( auto element=(~sm).begin(j); element!=(~sm).end(j); ++element ) {
631  if( !isDefault<RF>( element->value() ) )
632  return false;
633  }
634  }
635 
636  return true;
637 }
639 //*************************************************************************************************
640 
641 
642 //*************************************************************************************************
650 template< bool RF // Relaxation flag
651  , typename MT > // Type of the sparse matrix
652 bool isUniform_backend( const SparseMatrix<MT,false>& sm, FalseType )
653 {
656 
657  BLAZE_INTERNAL_ASSERT( (~sm).rows() != 0UL, "Invalid number of rows detected" );
658  BLAZE_INTERNAL_ASSERT( (~sm).columns() != 0UL, "Invalid number of columns detected" );
659 
660  const size_t maxElements( (~sm).rows() * (~sm).columns() );
661 
662  if( (~sm).nonZeros() != maxElements )
663  {
664  for( size_t i=0UL; i<(~sm).rows(); ++i ) {
665  for( auto element=(~sm).begin(i); element!=(~sm).end(i); ++element ) {
666  if( !isDefault<RF>( element->value() ) )
667  return false;
668  }
669  }
670  }
671  else
672  {
673  BLAZE_INTERNAL_ASSERT( (~sm).find(0UL,0UL) != (~sm).end(0UL), "Missing element detected" );
674 
675  const auto& cmp( (~sm)(0UL,0UL) );
676 
677  for( size_t i=0UL; i<(~sm).rows(); ++i ) {
678  for( auto element=(~sm).begin(i); element!=(~sm).end(i); ++element ) {
679  if( !equal<RF>( element->value(), cmp ) )
680  return false;
681  }
682  }
683  }
684 
685  return true;
686 }
688 //*************************************************************************************************
689 
690 
691 //*************************************************************************************************
699 template< bool RF // Relaxation flag
700  , typename MT > // Type of the sparse matrix
701 bool isUniform_backend( const SparseMatrix<MT,true>& sm, FalseType )
702 {
705 
706  BLAZE_INTERNAL_ASSERT( (~sm).rows() != 0UL, "Invalid number of rows detected" );
707  BLAZE_INTERNAL_ASSERT( (~sm).columns() != 0UL, "Invalid number of columns detected" );
708 
709  const size_t maxElements( (~sm).rows() * (~sm).columns() );
710 
711  if( (~sm).nonZeros() != maxElements )
712  {
713  for( size_t j=0UL; j<(~sm).columns(); ++j ) {
714  for( auto element=(~sm).begin(j); element!=(~sm).end(j); ++element ) {
715  if( !isDefault<RF>( element->value() ) )
716  return false;
717  }
718  }
719  }
720  else
721  {
722  BLAZE_INTERNAL_ASSERT( (~sm).find(0UL,0UL) != (~sm).end(0UL), "Missing element detected" );
723 
724  const auto& cmp( (~sm)(0UL,0UL) );
725 
726  for( size_t j=0UL; j<(~sm).columns(); ++j ) {
727  for( auto element=(~sm).begin(j); element!=(~sm).end(j); ++element ) {
728  if( !equal<RF>( element->value(), cmp ) )
729  return false;
730  }
731  }
732  }
733 
734  return true;
735 }
737 //*************************************************************************************************
738 
739 
740 //*************************************************************************************************
773 template< bool RF // Relaxation flag
774  , typename MT // Type of the sparse matrix
775  , bool SO > // Storage order
777 {
778  if( IsUniform_v<MT> ||
779  (~sm).rows() == 0UL || (~sm).columns() == 0UL ||
780  ( (~sm).rows() == 1UL && (~sm).columns() == 1UL ) )
781  return true;
782 
783  if( IsUniTriangular_v<MT> )
784  return false;
785 
786  CompositeType_t<MT> A( ~sm ); // Evaluation of the sparse matrix operand
787 
788  return isUniform_backend<RF>( A, typename IsTriangular<MT>::Type() );
789 }
790 //*************************************************************************************************
791 
792 
793 //*************************************************************************************************
826 template< bool RF // Relaxation flag
827  , typename MT // Type of the sparse matrix
828  , bool SO > // Storage order
829 bool isZero( const SparseMatrix<MT,SO>& sm )
830 {
831  const size_t M( (~sm).rows() );
832  const size_t N( (~sm).columns() );
833 
834  if( IsZero_v<MT> || M == 0UL || N == 0UL )
835  return true;
836 
837  if( IsUniTriangular_v<MT> )
838  return false;
839 
840  CompositeType_t<MT> A( ~sm ); // Evaluation of the sparse matrix operand
841 
842  const size_t iend( SO == rowMajor ? A.rows() : A.columns() );
843 
844  for( size_t i=0UL; i<iend; ++i ) {
845  for( auto element=A.begin(i); element!=A.end(i); ++element ) {
846  if( !isZero<RF>( element->value() ) ) {
847  return false;
848  }
849  }
850  }
851 
852  return true;
853 }
854 //*************************************************************************************************
855 
856 
857 //*************************************************************************************************
900 template< bool RF // Relaxation flag
901  , typename MT // Type of the sparse matrix
902  , bool SO > // Storage order
903 bool isLower( const SparseMatrix<MT,SO>& sm )
904 {
905  using RT = ResultType_t<MT>;
906  using RN = ReturnType_t<MT>;
907  using CT = CompositeType_t<MT>;
908  using Tmp = If_t< IsExpression_v<RN>, const RT, CT >;
909 
910  if( IsLower_v<MT> )
911  return true;
912 
913  if( !isSquare( ~sm ) )
914  return false;
915 
916  if( IsZero_v<MT> || (~sm).rows() < 2UL )
917  return true;
918 
919  Tmp A( ~sm ); // Evaluation of the sparse matrix operand
920 
921  if( SO == rowMajor ) {
922  for( size_t i=0UL; i<A.rows()-1UL; ++i ) {
923  for( auto element=A.lowerBound(i,i+1UL); element!=A.end(i); ++element )
924  {
925  if( !isDefault<RF>( element->value() ) )
926  return false;
927  }
928  }
929  }
930  else {
931  for( size_t j=1UL; j<A.columns(); ++j ) {
932  for( auto element=A.begin(j); element!=A.end(j); ++element )
933  {
934  if( element->index() >= j )
935  break;
936 
937  if( !isDefault<RF>( element->value() ) )
938  return false;
939  }
940  }
941  }
942 
943  return true;
944 }
945 //*************************************************************************************************
946 
947 
948 //*************************************************************************************************
990 template< bool RF // Relaxation flag
991  , typename MT // Type of the sparse matrix
992  , bool SO > // Storage order
994 {
995  using RT = ResultType_t<MT>;
996  using RN = ReturnType_t<MT>;
997  using CT = CompositeType_t<MT>;
998  using Tmp = If_t< IsExpression_v<RN>, const RT, CT >;
999 
1000  if( IsUniLower_v<MT> )
1001  return true;
1002 
1003  if( !isSquare( ~sm ) )
1004  return false;
1005 
1006  Tmp A( ~sm ); // Evaluation of the sparse matrix operand
1007 
1008  if( SO == rowMajor ) {
1009  for( size_t i=0UL; i<A.rows(); ++i )
1010  {
1011  auto element( A.lowerBound(i,i) );
1012 
1013  if( element == A.end(i) || element->index() != i || !isOne<RF>( element->value() ) )
1014  return false;
1015 
1016  ++element;
1017 
1018  for( ; element!=A.end(i); ++element ) {
1019  if( !isZero<RF>( element->value() ) )
1020  return false;
1021  }
1022  }
1023  }
1024  else {
1025  for( size_t j=0UL; j<A.columns(); ++j )
1026  {
1027  bool hasDiagonalElement( false );
1028 
1029  for( auto element=A.begin(j); element!=A.end(j); ++element )
1030  {
1031  if( element->index() >= j ) {
1032  if( element->index() != j || !isOne<RF>( element->value() ) )
1033  return false;
1034  hasDiagonalElement = true;
1035  break;
1036  }
1037 
1038  if( !isZero<RF>( element->value() ) )
1039  return false;
1040  }
1041 
1042  if( !hasDiagonalElement ) {
1043  return false;
1044  }
1045  }
1046  }
1047 
1048  return true;
1049 }
1050 //*************************************************************************************************
1051 
1052 
1053 //*************************************************************************************************
1096 template< bool RF // Relaxation flag
1097  , typename MT // Type of the sparse matrix
1098  , bool SO > // Storage order
1100 {
1101  using RT = ResultType_t<MT>;
1102  using RN = ReturnType_t<MT>;
1103  using CT = CompositeType_t<MT>;
1104  using Tmp = If_t< IsExpression_v<RN>, const RT, CT >;
1105 
1106  if( IsStrictlyLower_v<MT> )
1107  return true;
1108 
1109  if( !isSquare( ~sm ) )
1110  return false;
1111 
1112  if( IsZero_v<MT> || (~sm).rows() < 2UL )
1113  return true;
1114 
1115  if( IsUniLower_v<MT> || IsUniUpper_v<MT> )
1116  return false;
1117 
1118  Tmp A( ~sm ); // Evaluation of the sparse matrix operand
1119 
1120  if( SO == rowMajor ) {
1121  for( size_t i=0UL; i<A.rows(); ++i ) {
1122  for( auto element=A.lowerBound(i,i); element!=A.end(i); ++element )
1123  {
1124  if( !isDefault<RF>( element->value() ) )
1125  return false;
1126  }
1127  }
1128  }
1129  else {
1130  for( size_t j=0UL; j<A.columns(); ++j ) {
1131  for( auto element=A.begin(j); element!=A.end(j); ++element )
1132  {
1133  if( element->index() > j )
1134  break;
1135 
1136  if( !isDefault<RF>( element->value() ) )
1137  return false;
1138  }
1139  }
1140  }
1141 
1142  return true;
1143 }
1144 //*************************************************************************************************
1145 
1146 
1147 //*************************************************************************************************
1190 template< bool RF // Relaxation flag
1191  , typename MT // Type of the sparse matrix
1192  , bool SO > // Storage order
1193 bool isUpper( const SparseMatrix<MT,SO>& sm )
1194 {
1195  using RT = ResultType_t<MT>;
1196  using RN = ReturnType_t<MT>;
1197  using CT = CompositeType_t<MT>;
1198  using Tmp = If_t< IsExpression_v<RN>, const RT, CT >;
1199 
1200  if( IsUpper_v<MT> )
1201  return true;
1202 
1203  if( !isSquare( ~sm ) )
1204  return false;
1205 
1206  if( IsZero_v<MT> || (~sm).rows() < 2UL )
1207  return true;
1208 
1209  Tmp A( ~sm ); // Evaluation of the sparse matrix operand
1210 
1211  if( SO == rowMajor ) {
1212  for( size_t i=1UL; i<A.rows(); ++i ) {
1213  for( auto element=A.begin(i); element!=A.end(i); ++element )
1214  {
1215  if( element->index() >= i )
1216  break;
1217 
1218  if( !isDefault<RF>( element->value() ) )
1219  return false;
1220  }
1221  }
1222  }
1223  else {
1224  for( size_t j=0UL; j<A.columns()-1UL; ++j ) {
1225  for( auto element=A.lowerBound(j+1UL,j); element!=A.end(j); ++element )
1226  {
1227  if( !isDefault<RF>( element->value() ) )
1228  return false;
1229  }
1230  }
1231  }
1232 
1233  return true;
1234 }
1235 //*************************************************************************************************
1236 
1237 
1238 //*************************************************************************************************
1280 template< bool RF // Relaxation flag
1281  , typename MT // Type of the sparse matrix
1282  , bool SO > // Storage order
1284 {
1285  using RT = ResultType_t<MT>;
1286  using RN = ReturnType_t<MT>;
1287  using CT = CompositeType_t<MT>;
1288  using Tmp = If_t< IsExpression_v<RN>, const RT, CT >;
1289 
1290  if( IsUniUpper_v<MT> )
1291  return true;
1292 
1293  if( !isSquare( ~sm ) )
1294  return false;
1295 
1296  Tmp A( ~sm ); // Evaluation of the sparse matrix operand
1297 
1298  if( SO == rowMajor ) {
1299  for( size_t i=0UL; i<A.rows(); ++i )
1300  {
1301  bool hasDiagonalElement( false );
1302 
1303  for( auto element=A.begin(i); element!=A.end(i); ++element )
1304  {
1305  if( element->index() >= i ) {
1306  if( element->index() != i || !isOne<RF>( element->value() ) )
1307  return false;
1308  hasDiagonalElement = true;
1309  break;
1310  }
1311  else if( !isZero<RF>( element->value() ) ) {
1312  return false;
1313  }
1314  }
1315 
1316  if( !hasDiagonalElement ) {
1317  return false;
1318  }
1319  }
1320  }
1321  else {
1322  for( size_t j=0UL; j<A.columns(); ++j )
1323  {
1324  auto element( A.lowerBound(j,j) );
1325 
1326  if( element == A.end(j) || element->index() != j || !isOne<RF>( element->value() ) )
1327  return false;
1328 
1329  ++element;
1330 
1331  for( ; element!=A.end(j); ++element ) {
1332  if( !isZero<RF>( element->value() ) )
1333  return false;
1334  }
1335  }
1336  }
1337 
1338  return true;
1339 }
1340 //*************************************************************************************************
1341 
1342 
1343 //*************************************************************************************************
1386 template< bool RF // Relaxation flag
1387  , typename MT // Type of the sparse matrix
1388  , bool SO > // Storage order
1390 {
1391  using RT = ResultType_t<MT>;
1392  using RN = ReturnType_t<MT>;
1393  using CT = CompositeType_t<MT>;
1394  using Tmp = If_t< IsExpression_v<RN>, const RT, CT >;
1395 
1396  if( IsStrictlyUpper_v<MT> )
1397  return true;
1398 
1399  if( !isSquare( ~sm ) )
1400  return false;
1401 
1402  if( IsZero_v<MT> || (~sm).rows() < 2UL )
1403  return true;
1404 
1405  if( IsUniLower_v<MT> || IsUniUpper_v<MT> )
1406  return false;
1407 
1408  Tmp A( ~sm ); // Evaluation of the sparse matrix operand
1409 
1410  if( SO == rowMajor ) {
1411  for( size_t i=0UL; i<A.rows(); ++i ) {
1412  for( auto element=A.begin(i); element!=A.end(i); ++element )
1413  {
1414  if( element->index() > i )
1415  break;
1416 
1417  if( !isDefault<RF>( element->value() ) )
1418  return false;
1419  }
1420  }
1421  }
1422  else {
1423  for( size_t j=0UL; j<A.columns(); ++j ) {
1424  for( auto element=A.lowerBound(j,j); element!=A.end(j); ++element )
1425  {
1426  if( !isDefault<RF>( element->value() ) )
1427  return false;
1428  }
1429  }
1430  }
1431 
1432  return true;
1433 }
1434 //*************************************************************************************************
1435 
1436 
1437 //*************************************************************************************************
1480 template< bool RF // Relaxation flag
1481  , typename MT // Type of the sparse matrix
1482  , bool SO > // Storage order
1484 {
1485  using RT = ResultType_t<MT>;
1486  using RN = ReturnType_t<MT>;
1487  using CT = CompositeType_t<MT>;
1488  using Tmp = If_t< IsExpression_v<RN>, const RT, CT >;
1489 
1490  if( IsDiagonal_v<MT> )
1491  return true;
1492 
1493  if( !isSquare( ~sm ) )
1494  return false;
1495 
1496  if( IsZero_v<MT> || (~sm).rows() < 2UL )
1497  return true;
1498 
1499  Tmp A( ~sm ); // Evaluation of the sparse matrix operand
1500 
1501  if( SO == rowMajor ) {
1502  for( size_t i=0UL; i<A.rows(); ++i ) {
1503  for( auto element=A.begin(i); element!=A.end(i); ++element )
1504  if( element->index() != i && !isDefault<RF>( element->value() ) )
1505  return false;
1506  }
1507  }
1508  else {
1509  for( size_t j=0UL; j<A.columns(); ++j ) {
1510  for( auto element=A.begin(j); element!=A.end(j); ++element )
1511  if( element->index() != j && !isDefault<RF>( element->value() ) )
1512  return false;
1513  }
1514  }
1515 
1516  return true;
1517 }
1518 //*************************************************************************************************
1519 
1520 
1521 //*************************************************************************************************
1564 template< bool RF // Relaxation flag
1565  , typename MT // Type of the sparse matrix
1566  , bool SO > // Storage order
1568 {
1569  using RT = ResultType_t<MT>;
1570  using RN = ReturnType_t<MT>;
1571  using CT = CompositeType_t<MT>;
1572  using Tmp = If_t< IsExpression_v<RN>, const RT, CT >;
1573 
1574  if( IsIdentity_v<MT> )
1575  return true;
1576 
1577  if( !isSquare( ~sm ) )
1578  return false;
1579 
1580  Tmp A( ~sm ); // Evaluation of the sparse matrix operand
1581 
1582  if( SO == rowMajor ) {
1583  for( size_t i=0UL; i<A.rows(); ++i )
1584  {
1585  bool hasDiagonalElement( false );
1586 
1587  for( auto element=A.begin(i); element!=A.end(i); ++element )
1588  {
1589  if( element->index() == i ) {
1590  if( !isOne<RF>( element->value() ) )
1591  return false;
1592  hasDiagonalElement = true;
1593  }
1594  else if( !isZero<RF>( element->value() ) ) {
1595  return false;
1596  }
1597  }
1598 
1599  if( !hasDiagonalElement ) {
1600  return false;
1601  }
1602  }
1603  }
1604  else {
1605  for( size_t j=0UL; j<A.columns(); ++j )
1606  {
1607  bool hasDiagonalElement( false );
1608 
1609  for( auto element=A.begin(j); element!=A.end(j); ++element )
1610  {
1611  if( element->index() == j ) {
1612  if( !isOne<RF>( element->value() ) )
1613  return false;
1614  hasDiagonalElement = true;
1615  }
1616  else if( !isZero<RF>( element->value() ) ) {
1617  return false;
1618  }
1619  }
1620 
1621  if( !hasDiagonalElement ) {
1622  return false;
1623  }
1624  }
1625  }
1626 
1627  return true;
1628 }
1629 //*************************************************************************************************
1630 
1631 
1632 //*************************************************************************************************
1646 template< typename MT // Type of the sparse matrix
1647  , bool SO // Storage order
1648  , typename... Args > // Type of the erase arguments
1649 auto erase( SparseMatrix<MT,SO>& sm, Args&&... args )
1650  -> decltype( (~sm).erase( std::forward<Args>( args )... ) )
1651 {
1652  return (~sm).erase( std::forward<Args>( args )... );
1653 }
1655 //*************************************************************************************************
1656 
1657 } // namespace blaze
1658 
1659 #endif
#define BLAZE_CONSTRAINT_MUST_BE_TRIANGULAR_MATRIX_TYPE(T)
Constraint on the data type.In case the given data type T is not a lower or upper triangular matrix t...
Definition: Triangular.h:61
Header file for the isnan shim.
Header file for the UnderlyingNumeric type trait.
BoolConstant< false > FalseType
Type/value traits base class.The FalseType class is used as base class for type traits and value trai...
Definition: IntegralConstant.h:121
#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.
bool isLower(const DenseMatrix< MT, SO > &dm)
Checks if the given dense matrix is a lower triangular matrix.
Definition: DenseMatrix.h:1793
bool isUpper(const DenseMatrix< MT, SO > &dm)
Checks if the given dense matrix is an upper triangular matrix.
Definition: DenseMatrix.h:2060
bool isStrictlyLower(const DenseMatrix< MT, SO > &dm)
Checks if the given dense matrix is a strictly lower triangular matrix.
Definition: DenseMatrix.h:1968
#define BLAZE_USER_ASSERT(expr, msg)
Run time assertion macro for user checks.In case of an invalid run time expression,...
Definition: Assert.h:117
Header file for the IsUniUpper type trait.
Compile time check for triangular matrix types.This type trait tests whether or not the given templat...
Definition: IsTriangular.h:86
Header file for basic type definitions.
#define BLAZE_CONSTRAINT_MUST_NOT_BE_TRIANGULAR_MATRIX_TYPE(T)
Constraint on the data type.In case the given data type T is a lower or upper triangular matrix type,...
Definition: Triangular.h:81
typename If< Condition, T1, T2 >::Type If_t
Auxiliary alias template for the If class template.The If_t alias template provides a convenient shor...
Definition: If.h:109
typename T::ResultType ResultType_t
Alias declaration for nested ResultType type definitions.The ResultType_t alias declaration provides ...
Definition: Aliases.h:390
Header file for the isZero shim.
Header file for the IsDiagonal type trait.
typename DivTrait< T1, T2 >::Type DivTrait_t
Auxiliary alias declaration for the DivTrait class template.The DivTrait_t alias declaration provides...
Definition: DivTrait.h:239
MT::Iterator begin(Matrix< MT, SO > &matrix, size_t i)
Returns an iterator to the first element of row/column i.
Definition: Matrix.h:372
void reset(const DiagonalProxy< MT > &proxy)
Resetting the represented element to the default initial values.
Definition: DiagonalProxy.h:595
bool isUniLower(const DenseMatrix< MT, SO > &dm)
Checks if the given dense matrix is a lower unitriangular matrix.
Definition: DenseMatrix.h:1881
#define BLAZE_CONSTRAINT_MUST_NOT_BE_UNITRIANGULAR_MATRIX_TYPE(T)
Constraint on the data type.In case the given data type T is a lower or upper unitriangular matrix ty...
Definition: UniTriangular.h:81
Header file for the IsIdentity type trait.
bool isDiagonal(const DenseMatrix< MT, SO > &dm)
Checks if the give dense matrix is diagonal.
Definition: DenseMatrix.h:2328
size_t nonZeros(const Matrix< MT, SO > &matrix)
Returns the total number of non-zero elements in the matrix.
Definition: Matrix.h:584
BoolConstant< true > TrueType
Type traits base class.The TrueType class is used as base class for type traits and value traits that...
Definition: IntegralConstant.h:132
typename T::ReturnType ReturnType_t
Alias declaration for nested ReturnType type definitions.The ReturnType_t alias declaration provides ...
Definition: Aliases.h:410
Header file for the IsUniLower type trait.
constexpr size_t columns(const Matrix< MT, SO > &matrix) noexcept
Returns the current number of columns of the matrix.
Definition: Matrix.h:514
constexpr bool rowMajor
Storage order flag for row-major matrices.
Definition: StorageOrder.h:71
Base class for sparse matrices.The SparseMatrix class is a base class for all sparse matrix classes....
Definition: Forward.h:145
typename T::ElementType ElementType_t
Alias declaration for nested ElementType type definitions.The ElementType_t alias declaration provide...
Definition: Aliases.h:170
bool isIdentity(const DenseMatrix< MT, SO > &dm)
Checks if the give dense matrix is an identity matrix.
Definition: DenseMatrix.h:2433
Header file for the SparseMatrix base class.
Header file for the IsSquare type trait.
bool isZero(const DiagonalProxy< MT > &proxy)
Returns whether the represented element is 0.
Definition: DiagonalProxy.h:677
Header file for the matrix storage order types.
typename EnableIf< Condition, T >::Type EnableIf_t
Auxiliary type for the EnableIf class template.The EnableIf_t alias declaration provides a convenient...
Definition: EnableIf.h:138
Constraint on the data type.
constexpr bool IsResizable_v
Auxiliary variable template for the IsResizable type trait.The IsResizable_v variable template provid...
Definition: IsResizable.h:133
Header file for the IsUniform type 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.
Header file for the IsFloatingPoint type trait.
Header file for the UnderlyingBuiltin type trait.
Header file for the IsLower type trait.
Header file for the equal shim.
Header file for the IsUniTriangular type trait.
Header file for the IsTriangular type trait.
bool isnan(const DiagonalProxy< MT > &proxy)
Returns whether the represented element is not a number.
Definition: DiagonalProxy.h:717
bool isUniform(const DenseMatrix< MT, SO > &dm)
Checks if the given dense matrix is a uniform matrix.
Definition: DenseMatrix.h:1638
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:438
Constraint on the data type.
Header file for the EnableIf class template.
Header file for the IsStrictlyLower type trait.
Header file for the isOne shim.
Header file for the conjugate shim.
Constraint on the data type.
Header file for the IsNumeric type trait.
auto operator/=(DenseMatrix< MT, SO > &mat, ST scalar) -> EnableIf_t< IsNumeric_v< ST >, MT & >
Division assignment operator for the division of a dense matrix by a scalar value ( ).
Definition: DenseMatrix.h:558
bool isStrictlyUpper(const DenseMatrix< MT, SO > &dm)
Checks if the given dense matrix is a strictly upper triangular matrix.
Definition: DenseMatrix.h:2235
Header file for run time assertion macros.
typename T::CompositeType CompositeType_t
Alias declaration for nested CompositeType type definitions.The CompositeType_t alias declaration pro...
Definition: Aliases.h:90
Header file for the division trait.
Header file for the IsZero type trait.
bool isHermitian(const DenseMatrix< MT, SO > &dm)
Checks if the given dense matrix is Hermitian.
Definition: DenseMatrix.h:1406
Header file for the isDefault shim.
bool isSymmetric(const DenseMatrix< MT, SO > &dm)
Checks if the given dense matrix is symmetric.
Definition: DenseMatrix.h:1328
#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
constexpr size_t rows(const Matrix< MT, SO > &matrix) noexcept
Returns the current number of rows of the matrix.
Definition: Matrix.h:498
Header file for the IsInvertible type trait.
Header file for the IsBuiltin type trait.
Header file for the IntegralConstant class template.
bool isUniUpper(const DenseMatrix< MT, SO > &dm)
Checks if the given dense matrix is an upper unitriangular matrix.
Definition: DenseMatrix.h:2148
bool isIntact(const DiagonalMatrix< MT, SO, DF > &m)
Returns whether the invariants of the given diagonal matrix are intact.
Definition: DiagonalMatrix.h:264
Header file for the IsComplex type trait.
auto operator *=(DenseMatrix< MT, SO > &mat, ST scalar) -> EnableIf_t< IsNumeric_v< ST >, MT & >
Multiplication assignment operator for the multiplication of a dense matrix and a scalar value ( ).
Definition: DenseMatrix.h:494
Header file for the IsUpper type trait.
decltype(auto) conj(const DenseMatrix< MT, SO > &dm)
Returns a matrix containing the complex conjugate of each single element of dm.
Definition: DMatMapExpr.h:1324
Header file for the IsHermitian type trait.
bool isSquare(const Matrix< MT, SO > &matrix) noexcept
Checks if the given matrix is a square matrix.
Definition: Matrix.h:951
Header file for the IsResizable type trait.
Header file for the IsRestricted type trait.
Header file for the isReal shim.
#define BLAZE_INTERNAL_ASSERT(expr, msg)
Run time assertion macro for internal checks.In case of an invalid run time expression,...
Definition: Assert.h:101
Header file for the IsExpression type trait class.