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>
81 #include <blaze/util/EnableIf.h>
82 #include <blaze/util/FalseType.h>
83 #include <blaze/util/mpl/If.h>
84 #include <blaze/util/TrueType.h>
85 #include <blaze/util/Types.h>
90 
91 
92 namespace blaze {
93 
94 //=================================================================================================
95 //
96 // GLOBAL OPERATORS
97 //
98 //=================================================================================================
99 
100 //*************************************************************************************************
103 template< typename MT, bool SO, typename ST >
104 auto operator*=( SparseMatrix<MT,SO>& mat, ST scalar )
105  -> EnableIf_t< IsNumeric_v<ST>, MT& >;
106 
107 template< typename MT, bool SO, typename ST >
108 auto operator*=( SparseMatrix<MT,SO>&& mat, ST scalar )
109  -> EnableIf_t< IsNumeric_v<ST>, MT& >;
110 
111 template< typename MT, bool SO, typename ST >
112 auto operator/=( SparseMatrix<MT,SO>& mat, ST scalar )
113  -> EnableIf_t< IsNumeric_v<ST>, MT& >;
114 
115 template< typename MT, bool SO, typename ST >
116 auto operator/=( SparseMatrix<MT,SO>&& mat, ST scalar )
117  -> EnableIf_t< IsNumeric_v<ST>, MT& >;
119 //*************************************************************************************************
120 
121 
122 //*************************************************************************************************
135 template< typename MT // Type of the left-hand side sparse matrix
136  , bool SO // Storage order
137  , typename ST > // Data type of the right-hand side scalar
138 inline auto operator*=( SparseMatrix<MT,SO>& mat, ST scalar )
140 {
142 
143  if( IsRestricted_v<MT> ) {
144  if( !tryMult( ~mat, 0UL, 0UL, (~mat).rows(), (~mat).columns(), scalar ) ) {
145  BLAZE_THROW_INVALID_ARGUMENT( "Invalid scaling of restricted matrix" );
146  }
147  }
148 
149  if( !IsResizable_v< ElementType_t<MT> > && isZero( scalar ) )
150  {
151  reset( ~mat );
152  }
153  else
154  {
155  BLAZE_DECLTYPE_AUTO( left, derestrict( ~mat ) );
156 
157  const size_t iend( SO == rowMajor ? (~mat).rows() : (~mat).columns() );
158  for( size_t i=0UL; i<iend; ++i ) {
159  const auto last( left.end(i) );
160  for( auto element=left.begin(i); element!=last; ++element ) {
161  element->value() *= scalar;
162  }
163  }
164  }
165 
166  BLAZE_INTERNAL_ASSERT( isIntact( ~mat ), "Invariant violation detected" );
167 
168  return ~mat;
169 }
170 //*************************************************************************************************
171 
172 
173 //*************************************************************************************************
186 template< typename MT // Type of the left-hand side sparse matrix
187  , bool SO // Storage order
188  , typename ST > // Data type of the right-hand side scalar
189 inline auto operator*=( SparseMatrix<MT,SO>&& mat, ST scalar )
191 {
192  return operator*=( ~mat, scalar );
193 }
194 //*************************************************************************************************
195 
196 
197 //*************************************************************************************************
212 template< typename MT // Type of the left-hand side sparse matrix
213  , bool SO // Storage order
214  , typename ST > // Data type of the right-hand side scalar
215 inline auto operator/=( SparseMatrix<MT,SO>& mat, ST scalar )
217 {
219 
220  BLAZE_USER_ASSERT( !isZero( scalar ), "Division by zero detected" );
221 
222  if( IsRestricted_v<MT> ) {
223  if( !tryDiv( ~mat, 0UL, 0UL, (~mat).rows(), (~mat).columns(), scalar ) ) {
224  BLAZE_THROW_INVALID_ARGUMENT( "Invalid scaling of restricted matrix" );
225  }
226  }
227 
229  IsFloatingPoint_v< UnderlyingBuiltin_t<ST> >
230  , If_t< IsComplex_v< UnderlyingNumeric_t<MT> > && IsBuiltin_v<ST>
233  , ST >;
234 
235  BLAZE_DECLTYPE_AUTO( left, derestrict( ~mat ) );
236 
237  if( IsInvertible_v<ScalarType> ) {
238  const ScalarType tmp( ScalarType(1)/static_cast<ScalarType>( scalar ) );
239  const size_t iend( SO == rowMajor ? (~mat).rows() : (~mat).columns() );
240  for( size_t i=0UL; i<iend; ++i ) {
241  const auto last( left.end(i) );
242  for( auto element=left.begin(i); element!=last; ++element ) {
243  element->value() *= tmp;
244  }
245  }
246  }
247  else {
248  const size_t iend( SO == rowMajor ? (~mat).rows() : (~mat).columns() );
249  for( size_t i=0UL; i<iend; ++i ) {
250  const auto last( left.end(i) );
251  for( auto element=left.begin(i); element!=last; ++element ) {
252  element->value() /= scalar;
253  }
254  }
255  }
256 
257  BLAZE_INTERNAL_ASSERT( isIntact( ~mat ), "Invariant violation detected" );
258 
259  return ~mat;
260 }
261 //*************************************************************************************************
262 
263 
264 //*************************************************************************************************
279 template< typename MT // Type of the left-hand side sparse matrix
280  , bool SO // Storage order
281  , typename ST > // Data type of the right-hand side scalar
282 inline auto operator/=( SparseMatrix<MT,SO>&& mat, ST scalar )
284 {
285  return operator/=( ~mat, scalar );
286 }
287 //*************************************************************************************************
288 
289 
290 
291 
292 //=================================================================================================
293 //
294 // GLOBAL FUNCTIONS
295 //
296 //=================================================================================================
297 
298 //*************************************************************************************************
301 template< typename MT, bool SO >
302 bool isnan( const SparseMatrix<MT,SO>& sm );
303 
304 template< bool RF, typename MT, bool SO >
305 bool isSymmetric( const SparseMatrix<MT,SO>& sm );
306 
307 template< bool RF, typename MT, bool SO >
308 bool isHermitian( const SparseMatrix<MT,SO>& sm );
309 
310 template< bool RF, typename MT, bool SO >
311 bool isUniform( const SparseMatrix<MT,SO>& sm );
312 
313 template< bool RF, typename MT, bool SO >
314 bool isZero( const SparseMatrix<MT,SO>& sm );
315 
316 template< bool RF, typename MT, bool SO >
317 bool isLower( const SparseMatrix<MT,SO>& sm );
318 
319 template< bool RF, typename MT, bool SO >
320 bool isUniLower( const SparseMatrix<MT,SO>& sm );
321 
322 template< bool RF, typename MT, bool SO >
323 bool isStrictlyLower( const SparseMatrix<MT,SO>& sm );
324 
325 template< bool RF, typename MT, bool SO >
326 bool isUpper( const SparseMatrix<MT,SO>& sm );
327 
328 template< bool RF, typename MT, bool SO >
329 bool isUniUpper( const SparseMatrix<MT,SO>& sm );
330 
331 template< bool RF, typename MT, bool SO >
332 bool isStrictlyUpper( const SparseMatrix<MT,SO>& sm );
333 
334 template< bool RF, typename MT, bool SO >
335 bool isDiagonal( const SparseMatrix<MT,SO>& sm );
336 
337 template< bool RF, typename MT, bool SO >
338 bool isIdentity( const SparseMatrix<MT,SO>& sm );
340 //*************************************************************************************************
341 
342 
343 //*************************************************************************************************
363 template< typename MT // Type of the sparse matrix
364  , bool SO > // Storage order
365 bool isnan( const SparseMatrix<MT,SO>& sm )
366 {
367  CompositeType_t<MT> A( ~sm ); // Evaluation of the sparse matrix operand
368 
369  if( SO == rowMajor ) {
370  for( size_t i=0UL; i<A.rows(); ++i ) {
371  for( auto element=A.begin(i); element!=A.end(i); ++element )
372  if( isnan( element->value() ) ) return true;
373  }
374  }
375  else {
376  for( size_t j=0UL; j<A.columns(); ++j ) {
377  for( auto element=A.begin(j); element!=A.end(j); ++element )
378  if( isnan( element->value() ) ) return true;
379  }
380  }
381 
382  return false;
383 }
384 //*************************************************************************************************
385 
386 
387 //*************************************************************************************************
420 template< bool RF // Relaxation flag
421  , typename MT // Type of the sparse matrix
422  , bool SO > // Storage order
424 {
425  using RT = ResultType_t<MT>;
426  using RN = ReturnType_t<MT>;
427  using CT = CompositeType_t<MT>;
428  using Tmp = If_t< IsExpression_v<RN>, const RT, CT >;
429 
430  if( IsSymmetric_v<MT> )
431  return true;
432 
433  if( !isSquare( ~sm ) )
434  return false;
435 
436  if( IsUniform_v<MT> || (~sm).rows() < 2UL )
437  return true;
438 
439  Tmp A( ~sm ); // Evaluation of the sparse matrix operand
440 
441  if( SO == rowMajor ) {
442  for( size_t i=0UL; i<A.rows(); ++i ) {
443  for( auto element=A.begin(i); element!=A.end(i); ++element )
444  {
445  const size_t j( element->index() );
446 
447  if( i == j || isDefault<RF>( element->value() ) )
448  continue;
449 
450  const auto pos( A.find( j, i ) );
451  if( pos == A.end(j) || !equal<RF>( pos->value(), element->value() ) )
452  return false;
453  }
454  }
455  }
456  else {
457  for( size_t j=0UL; j<A.columns(); ++j ) {
458  for( auto element=A.begin(j); element!=A.end(j); ++element )
459  {
460  const size_t i( element->index() );
461 
462  if( j == i || isDefault<RF>( element->value() ) )
463  continue;
464 
465  const auto pos( A.find( j, i ) );
466  if( pos == A.end(i) || !equal<RF>( pos->value(), element->value() ) )
467  return false;
468  }
469  }
470  }
471 
472  return true;
473 }
474 //*************************************************************************************************
475 
476 
477 //*************************************************************************************************
512 template< bool RF // Relaxation flag
513  , typename MT // Type of the sparse matrix
514  , bool SO > // Storage order
516 {
517  using RT = ResultType_t<MT>;
518  using ET = ElementType_t<MT>;
519  using RN = ReturnType_t<MT>;
520  using CT = CompositeType_t<MT>;
521  using Tmp = If_t< IsExpression_v<RN>, const RT, CT >;
522 
523  if( IsHermitian_v<MT> )
524  return true;
525 
526  if( !IsNumeric_v<ET> || !isSquare( ~sm ) )
527  return false;
528 
529  if( IsBuiltin_v<ET> && IsUniform_v<MT> )
530  return true;
531 
532  Tmp A( ~sm ); // Evaluation of the sparse matrix operand
533 
534  if( SO == rowMajor ) {
535  for( size_t i=0UL; i<A.rows(); ++i ) {
536  for( auto element=A.begin(i); element!=A.end(i); ++element )
537  {
538  const size_t j( element->index() );
539 
540  if( isDefault<RF>( element->value() ) )
541  continue;
542 
543  if( i == j && !isReal<RF>( element->value() ) )
544  return false;
545 
546  const auto pos( A.find( j, i ) );
547  if( pos == A.end(j) || !equal<RF>( pos->value(), conj( element->value() ) ) )
548  return false;
549  }
550  }
551  }
552  else {
553  for( size_t j=0UL; j<A.columns(); ++j ) {
554  for( auto element=A.begin(j); element!=A.end(j); ++element )
555  {
556  const size_t i( element->index() );
557 
558  if( isDefault<RF>( element->value() ) )
559  continue;
560 
561  if( j == i && !isReal<RF>( element->value() ) )
562  return false;
563 
564  const auto pos( A.find( j, i ) );
565  if( pos == A.end(i) || !equal<RF>( pos->value(), conj( element->value() ) ) )
566  return false;
567  }
568  }
569  }
570 
571  return true;
572 }
573 //*************************************************************************************************
574 
575 
576 //*************************************************************************************************
584 template< bool RF // Relaxation flag
585  , typename MT > // Type of the sparse matrix
586 bool isUniform_backend( const SparseMatrix<MT,false>& sm, TrueType )
587 {
590 
591  BLAZE_INTERNAL_ASSERT( (~sm).rows() != 0UL, "Invalid number of rows detected" );
592  BLAZE_INTERNAL_ASSERT( (~sm).columns() != 0UL, "Invalid number of columns detected" );
593 
594  const size_t ibegin( ( IsStrictlyLower_v<MT> )?( 1UL ):( 0UL ) );
595  const size_t iend ( ( IsStrictlyUpper_v<MT> )?( (~sm).rows()-1UL ):( (~sm).rows() ) );
596 
597  for( size_t i=ibegin; i<iend; ++i ) {
598  for( auto element=(~sm).begin(i); element!=(~sm).end(i); ++element ) {
599  if( !isDefault<RF>( element->value() ) )
600  return false;
601  }
602  }
603 
604  return true;
605 }
607 //*************************************************************************************************
608 
609 
610 //*************************************************************************************************
618 template< bool RF // Relaxation flag
619  , typename MT > // Type of the sparse matrix
620 bool isUniform_backend( const SparseMatrix<MT,true>& sm, TrueType )
621 {
624 
625  BLAZE_INTERNAL_ASSERT( (~sm).rows() != 0UL, "Invalid number of rows detected" );
626  BLAZE_INTERNAL_ASSERT( (~sm).columns() != 0UL, "Invalid number of columns detected" );
627 
628  const size_t jbegin( ( IsStrictlyUpper_v<MT> )?( 1UL ):( 0UL ) );
629  const size_t jend ( ( IsStrictlyLower_v<MT> )?( (~sm).columns()-1UL ):( (~sm).columns() ) );
630 
631  for( size_t j=jbegin; j<jend; ++j ) {
632  for( auto element=(~sm).begin(j); element!=(~sm).end(j); ++element ) {
633  if( !isDefault<RF>( element->value() ) )
634  return false;
635  }
636  }
637 
638  return true;
639 }
641 //*************************************************************************************************
642 
643 
644 //*************************************************************************************************
652 template< bool RF // Relaxation flag
653  , typename MT > // Type of the sparse matrix
654 bool isUniform_backend( const SparseMatrix<MT,false>& sm, FalseType )
655 {
658 
659  BLAZE_INTERNAL_ASSERT( (~sm).rows() != 0UL, "Invalid number of rows detected" );
660  BLAZE_INTERNAL_ASSERT( (~sm).columns() != 0UL, "Invalid number of columns detected" );
661 
662  const size_t maxElements( (~sm).rows() * (~sm).columns() );
663 
664  if( (~sm).nonZeros() != maxElements )
665  {
666  for( size_t i=0UL; i<(~sm).rows(); ++i ) {
667  for( auto element=(~sm).begin(i); element!=(~sm).end(i); ++element ) {
668  if( !isDefault<RF>( element->value() ) )
669  return false;
670  }
671  }
672  }
673  else
674  {
675  BLAZE_INTERNAL_ASSERT( (~sm).find(0UL,0UL) != (~sm).end(0UL), "Missing element detected" );
676 
677  const auto& cmp( (~sm)(0UL,0UL) );
678 
679  for( size_t i=0UL; i<(~sm).rows(); ++i ) {
680  for( auto element=(~sm).begin(i); element!=(~sm).end(i); ++element ) {
681  if( !equal<RF>( element->value(), cmp ) )
682  return false;
683  }
684  }
685  }
686 
687  return true;
688 }
690 //*************************************************************************************************
691 
692 
693 //*************************************************************************************************
701 template< bool RF // Relaxation flag
702  , typename MT > // Type of the sparse matrix
703 bool isUniform_backend( const SparseMatrix<MT,true>& sm, FalseType )
704 {
707 
708  BLAZE_INTERNAL_ASSERT( (~sm).rows() != 0UL, "Invalid number of rows detected" );
709  BLAZE_INTERNAL_ASSERT( (~sm).columns() != 0UL, "Invalid number of columns detected" );
710 
711  const size_t maxElements( (~sm).rows() * (~sm).columns() );
712 
713  if( (~sm).nonZeros() != maxElements )
714  {
715  for( size_t j=0UL; j<(~sm).columns(); ++j ) {
716  for( auto element=(~sm).begin(j); element!=(~sm).end(j); ++element ) {
717  if( !isDefault<RF>( element->value() ) )
718  return false;
719  }
720  }
721  }
722  else
723  {
724  BLAZE_INTERNAL_ASSERT( (~sm).find(0UL,0UL) != (~sm).end(0UL), "Missing element detected" );
725 
726  const auto& cmp( (~sm)(0UL,0UL) );
727 
728  for( size_t j=0UL; j<(~sm).columns(); ++j ) {
729  for( auto element=(~sm).begin(j); element!=(~sm).end(j); ++element ) {
730  if( !equal<RF>( element->value(), cmp ) )
731  return false;
732  }
733  }
734  }
735 
736  return true;
737 }
739 //*************************************************************************************************
740 
741 
742 //*************************************************************************************************
775 template< bool RF // Relaxation flag
776  , typename MT // Type of the sparse matrix
777  , bool SO > // Storage order
779 {
780  if( IsUniform_v<MT> ||
781  (~sm).rows() == 0UL || (~sm).columns() == 0UL ||
782  ( (~sm).rows() == 1UL && (~sm).columns() == 1UL ) )
783  return true;
784 
785  if( IsUniTriangular_v<MT> )
786  return false;
787 
788  CompositeType_t<MT> A( ~sm ); // Evaluation of the sparse matrix operand
789 
790  return isUniform_backend<RF>( A, typename IsTriangular<MT>::Type() );
791 }
792 //*************************************************************************************************
793 
794 
795 //*************************************************************************************************
828 template< bool RF // Relaxation flag
829  , typename MT // Type of the sparse matrix
830  , bool SO > // Storage order
831 bool isZero( const SparseMatrix<MT,SO>& sm )
832 {
833  const size_t M( (~sm).rows() );
834  const size_t N( (~sm).columns() );
835 
836  if( IsZero_v<MT> || M == 0UL || N == 0UL )
837  return true;
838 
839  if( IsUniTriangular_v<MT> )
840  return false;
841 
842  CompositeType_t<MT> A( ~sm ); // Evaluation of the sparse matrix operand
843 
844  const size_t iend( SO == rowMajor ? A.rows() : A.columns() );
845 
846  for( size_t i=0UL; i<iend; ++i ) {
847  for( auto element=A.begin(i); element!=A.end(i); ++element ) {
848  if( !isZero<RF>( element->value() ) ) {
849  return false;
850  }
851  }
852  }
853 
854  return true;
855 }
856 //*************************************************************************************************
857 
858 
859 //*************************************************************************************************
902 template< bool RF // Relaxation flag
903  , typename MT // Type of the sparse matrix
904  , bool SO > // Storage order
905 bool isLower( const SparseMatrix<MT,SO>& sm )
906 {
907  using RT = ResultType_t<MT>;
908  using RN = ReturnType_t<MT>;
909  using CT = CompositeType_t<MT>;
910  using Tmp = If_t< IsExpression_v<RN>, const RT, CT >;
911 
912  if( IsLower_v<MT> )
913  return true;
914 
915  if( !isSquare( ~sm ) )
916  return false;
917 
918  if( IsZero_v<MT> || (~sm).rows() < 2UL )
919  return true;
920 
921  Tmp A( ~sm ); // Evaluation of the sparse matrix operand
922 
923  if( SO == rowMajor ) {
924  for( size_t i=0UL; i<A.rows()-1UL; ++i ) {
925  for( auto element=A.lowerBound(i,i+1UL); element!=A.end(i); ++element )
926  {
927  if( !isDefault<RF>( element->value() ) )
928  return false;
929  }
930  }
931  }
932  else {
933  for( size_t j=1UL; j<A.columns(); ++j ) {
934  for( auto element=A.begin(j); element!=A.end(j); ++element )
935  {
936  if( element->index() >= j )
937  break;
938 
939  if( !isDefault<RF>( element->value() ) )
940  return false;
941  }
942  }
943  }
944 
945  return true;
946 }
947 //*************************************************************************************************
948 
949 
950 //*************************************************************************************************
992 template< bool RF // Relaxation flag
993  , typename MT // Type of the sparse matrix
994  , bool SO > // Storage order
996 {
997  using RT = ResultType_t<MT>;
998  using RN = ReturnType_t<MT>;
999  using CT = CompositeType_t<MT>;
1000  using Tmp = If_t< IsExpression_v<RN>, const RT, CT >;
1001 
1002  if( IsUniLower_v<MT> )
1003  return true;
1004 
1005  if( !isSquare( ~sm ) )
1006  return false;
1007 
1008  Tmp A( ~sm ); // Evaluation of the sparse matrix operand
1009 
1010  if( SO == rowMajor ) {
1011  for( size_t i=0UL; i<A.rows(); ++i )
1012  {
1013  auto element( A.lowerBound(i,i) );
1014 
1015  if( element == A.end(i) || element->index() != i || !isOne<RF>( element->value() ) )
1016  return false;
1017 
1018  ++element;
1019 
1020  for( ; element!=A.end(i); ++element ) {
1021  if( !isZero<RF>( element->value() ) )
1022  return false;
1023  }
1024  }
1025  }
1026  else {
1027  for( size_t j=0UL; j<A.columns(); ++j )
1028  {
1029  bool hasDiagonalElement( false );
1030 
1031  for( auto element=A.begin(j); element!=A.end(j); ++element )
1032  {
1033  if( element->index() >= j ) {
1034  if( element->index() != j || !isOne<RF>( element->value() ) )
1035  return false;
1036  hasDiagonalElement = true;
1037  break;
1038  }
1039 
1040  if( !isZero<RF>( element->value() ) )
1041  return false;
1042  }
1043 
1044  if( !hasDiagonalElement ) {
1045  return false;
1046  }
1047  }
1048  }
1049 
1050  return true;
1051 }
1052 //*************************************************************************************************
1053 
1054 
1055 //*************************************************************************************************
1098 template< bool RF // Relaxation flag
1099  , typename MT // Type of the sparse matrix
1100  , bool SO > // Storage order
1102 {
1103  using RT = ResultType_t<MT>;
1104  using RN = ReturnType_t<MT>;
1105  using CT = CompositeType_t<MT>;
1106  using Tmp = If_t< IsExpression_v<RN>, const RT, CT >;
1107 
1108  if( IsStrictlyLower_v<MT> )
1109  return true;
1110 
1111  if( !isSquare( ~sm ) )
1112  return false;
1113 
1114  if( IsZero_v<MT> || (~sm).rows() < 2UL )
1115  return true;
1116 
1117  if( IsUniLower_v<MT> || IsUniUpper_v<MT> )
1118  return false;
1119 
1120  Tmp A( ~sm ); // Evaluation of the sparse matrix operand
1121 
1122  if( SO == rowMajor ) {
1123  for( size_t i=0UL; i<A.rows(); ++i ) {
1124  for( auto element=A.lowerBound(i,i); element!=A.end(i); ++element )
1125  {
1126  if( !isDefault<RF>( element->value() ) )
1127  return false;
1128  }
1129  }
1130  }
1131  else {
1132  for( size_t j=0UL; j<A.columns(); ++j ) {
1133  for( auto element=A.begin(j); element!=A.end(j); ++element )
1134  {
1135  if( element->index() > j )
1136  break;
1137 
1138  if( !isDefault<RF>( element->value() ) )
1139  return false;
1140  }
1141  }
1142  }
1143 
1144  return true;
1145 }
1146 //*************************************************************************************************
1147 
1148 
1149 //*************************************************************************************************
1192 template< bool RF // Relaxation flag
1193  , typename MT // Type of the sparse matrix
1194  , bool SO > // Storage order
1195 bool isUpper( const SparseMatrix<MT,SO>& sm )
1196 {
1197  using RT = ResultType_t<MT>;
1198  using RN = ReturnType_t<MT>;
1199  using CT = CompositeType_t<MT>;
1200  using Tmp = If_t< IsExpression_v<RN>, const RT, CT >;
1201 
1202  if( IsUpper_v<MT> )
1203  return true;
1204 
1205  if( !isSquare( ~sm ) )
1206  return false;
1207 
1208  if( IsZero_v<MT> || (~sm).rows() < 2UL )
1209  return true;
1210 
1211  Tmp A( ~sm ); // Evaluation of the sparse matrix operand
1212 
1213  if( SO == rowMajor ) {
1214  for( size_t i=1UL; i<A.rows(); ++i ) {
1215  for( auto element=A.begin(i); element!=A.end(i); ++element )
1216  {
1217  if( element->index() >= i )
1218  break;
1219 
1220  if( !isDefault<RF>( element->value() ) )
1221  return false;
1222  }
1223  }
1224  }
1225  else {
1226  for( size_t j=0UL; j<A.columns()-1UL; ++j ) {
1227  for( auto element=A.lowerBound(j+1UL,j); element!=A.end(j); ++element )
1228  {
1229  if( !isDefault<RF>( element->value() ) )
1230  return false;
1231  }
1232  }
1233  }
1234 
1235  return true;
1236 }
1237 //*************************************************************************************************
1238 
1239 
1240 //*************************************************************************************************
1282 template< bool RF // Relaxation flag
1283  , typename MT // Type of the sparse matrix
1284  , bool SO > // Storage order
1286 {
1287  using RT = ResultType_t<MT>;
1288  using RN = ReturnType_t<MT>;
1289  using CT = CompositeType_t<MT>;
1290  using Tmp = If_t< IsExpression_v<RN>, const RT, CT >;
1291 
1292  if( IsUniUpper_v<MT> )
1293  return true;
1294 
1295  if( !isSquare( ~sm ) )
1296  return false;
1297 
1298  Tmp A( ~sm ); // Evaluation of the sparse matrix operand
1299 
1300  if( SO == rowMajor ) {
1301  for( size_t i=0UL; i<A.rows(); ++i )
1302  {
1303  bool hasDiagonalElement( false );
1304 
1305  for( auto element=A.begin(i); element!=A.end(i); ++element )
1306  {
1307  if( element->index() >= i ) {
1308  if( element->index() != i || !isOne<RF>( element->value() ) )
1309  return false;
1310  hasDiagonalElement = true;
1311  break;
1312  }
1313  else if( !isZero<RF>( element->value() ) ) {
1314  return false;
1315  }
1316  }
1317 
1318  if( !hasDiagonalElement ) {
1319  return false;
1320  }
1321  }
1322  }
1323  else {
1324  for( size_t j=0UL; j<A.columns(); ++j )
1325  {
1326  auto element( A.lowerBound(j,j) );
1327 
1328  if( element == A.end(j) || element->index() != j || !isOne<RF>( element->value() ) )
1329  return false;
1330 
1331  ++element;
1332 
1333  for( ; element!=A.end(j); ++element ) {
1334  if( !isZero<RF>( element->value() ) )
1335  return false;
1336  }
1337  }
1338  }
1339 
1340  return true;
1341 }
1342 //*************************************************************************************************
1343 
1344 
1345 //*************************************************************************************************
1388 template< bool RF // Relaxation flag
1389  , typename MT // Type of the sparse matrix
1390  , bool SO > // Storage order
1392 {
1393  using RT = ResultType_t<MT>;
1394  using RN = ReturnType_t<MT>;
1395  using CT = CompositeType_t<MT>;
1396  using Tmp = If_t< IsExpression_v<RN>, const RT, CT >;
1397 
1398  if( IsStrictlyUpper_v<MT> )
1399  return true;
1400 
1401  if( !isSquare( ~sm ) )
1402  return false;
1403 
1404  if( IsZero_v<MT> || (~sm).rows() < 2UL )
1405  return true;
1406 
1407  if( IsUniLower_v<MT> || IsUniUpper_v<MT> )
1408  return false;
1409 
1410  Tmp A( ~sm ); // Evaluation of the sparse matrix operand
1411 
1412  if( SO == rowMajor ) {
1413  for( size_t i=0UL; i<A.rows(); ++i ) {
1414  for( auto element=A.begin(i); element!=A.end(i); ++element )
1415  {
1416  if( element->index() > i )
1417  break;
1418 
1419  if( !isDefault<RF>( element->value() ) )
1420  return false;
1421  }
1422  }
1423  }
1424  else {
1425  for( size_t j=0UL; j<A.columns(); ++j ) {
1426  for( auto element=A.lowerBound(j,j); element!=A.end(j); ++element )
1427  {
1428  if( !isDefault<RF>( element->value() ) )
1429  return false;
1430  }
1431  }
1432  }
1433 
1434  return true;
1435 }
1436 //*************************************************************************************************
1437 
1438 
1439 //*************************************************************************************************
1482 template< bool RF // Relaxation flag
1483  , typename MT // Type of the sparse matrix
1484  , bool SO > // Storage order
1486 {
1487  using RT = ResultType_t<MT>;
1488  using RN = ReturnType_t<MT>;
1489  using CT = CompositeType_t<MT>;
1490  using Tmp = If_t< IsExpression_v<RN>, const RT, CT >;
1491 
1492  if( IsDiagonal_v<MT> )
1493  return true;
1494 
1495  if( !isSquare( ~sm ) )
1496  return false;
1497 
1498  if( IsZero_v<MT> || (~sm).rows() < 2UL )
1499  return true;
1500 
1501  Tmp A( ~sm ); // Evaluation of the sparse matrix operand
1502 
1503  if( SO == rowMajor ) {
1504  for( size_t i=0UL; i<A.rows(); ++i ) {
1505  for( auto element=A.begin(i); element!=A.end(i); ++element )
1506  if( element->index() != i && !isDefault<RF>( element->value() ) )
1507  return false;
1508  }
1509  }
1510  else {
1511  for( size_t j=0UL; j<A.columns(); ++j ) {
1512  for( auto element=A.begin(j); element!=A.end(j); ++element )
1513  if( element->index() != j && !isDefault<RF>( element->value() ) )
1514  return false;
1515  }
1516  }
1517 
1518  return true;
1519 }
1520 //*************************************************************************************************
1521 
1522 
1523 //*************************************************************************************************
1566 template< bool RF // Relaxation flag
1567  , typename MT // Type of the sparse matrix
1568  , bool SO > // Storage order
1570 {
1571  using RT = ResultType_t<MT>;
1572  using RN = ReturnType_t<MT>;
1573  using CT = CompositeType_t<MT>;
1574  using Tmp = If_t< IsExpression_v<RN>, const RT, CT >;
1575 
1576  if( IsIdentity_v<MT> )
1577  return true;
1578 
1579  if( !isSquare( ~sm ) )
1580  return false;
1581 
1582  Tmp A( ~sm ); // Evaluation of the sparse matrix operand
1583 
1584  if( SO == rowMajor ) {
1585  for( size_t i=0UL; i<A.rows(); ++i )
1586  {
1587  bool hasDiagonalElement( false );
1588 
1589  for( auto element=A.begin(i); element!=A.end(i); ++element )
1590  {
1591  if( element->index() == i ) {
1592  if( !isOne<RF>( element->value() ) )
1593  return false;
1594  hasDiagonalElement = true;
1595  }
1596  else if( !isZero<RF>( element->value() ) ) {
1597  return false;
1598  }
1599  }
1600 
1601  if( !hasDiagonalElement ) {
1602  return false;
1603  }
1604  }
1605  }
1606  else {
1607  for( size_t j=0UL; j<A.columns(); ++j )
1608  {
1609  bool hasDiagonalElement( false );
1610 
1611  for( auto element=A.begin(j); element!=A.end(j); ++element )
1612  {
1613  if( element->index() == j ) {
1614  if( !isOne<RF>( element->value() ) )
1615  return false;
1616  hasDiagonalElement = true;
1617  }
1618  else if( !isZero<RF>( element->value() ) ) {
1619  return false;
1620  }
1621  }
1622 
1623  if( !hasDiagonalElement ) {
1624  return false;
1625  }
1626  }
1627  }
1628 
1629  return true;
1630 }
1631 //*************************************************************************************************
1632 
1633 
1634 //*************************************************************************************************
1648 template< typename MT // Type of the sparse matrix
1649  , bool SO // Storage order
1650  , typename... Args > // Type of the erase arguments
1651 auto erase( SparseMatrix<MT,SO>& sm, Args&&... args )
1652  -> decltype( (~sm).erase( std::forward<Args>( args )... ) )
1653 {
1654  return (~sm).erase( std::forward<Args>( args )... );
1655 }
1657 //*************************************************************************************************
1658 
1659 } // namespace blaze
1660 
1661 #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: FalseType.h:61
#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:1004
bool isUpper(const DenseMatrix< MT, SO > &dm)
Checks if the given dense matrix is an upper triangular matrix.
Definition: DenseMatrix.h:1271
bool isStrictlyLower(const DenseMatrix< MT, SO > &dm)
Checks if the given dense matrix is a strictly lower triangular matrix.
Definition: DenseMatrix.h:1179
#define BLAZE_USER_ASSERT(expr, msg)
Run time assertion macro for user checks.In case of an invalid run time expression, the program execution is terminated. The BLAZE_USER_ASSERT macro can be disabled by setting the BLAZE_USER_ASSERT flag to zero or by defining NDEBUG during the compilation.
Definition: Assert.h:117
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:354
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 declaration for the If class template.The If_t alias declaration provides a convenien...
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 FalseType type/value trait base class.
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:591
bool isUniLower(const DenseMatrix< MT, SO > &dm)
Checks if the given dense matrix is a lower unitriangular matrix.
Definition: DenseMatrix.h:1092
#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:1539
size_t nonZeros(const Matrix< MT, SO > &matrix)
Returns the total number of non-zero elements in the matrix.
Definition: Matrix.h:584
Header file for the decltype(auto) workaround.
BoolConstant< true > TrueType
Type traits base class.The TrueType class is used as base class for type traits and value traits that...
Definition: TrueType.h:61
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:137
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:1644
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:673
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.
Header file for the IsUniform type trait.
Header file for the IsStrictlyUpper type trait.
Header file for the IsSymmetric type trait.
constexpr bool IsResizable_v
Auxiliary variable template for the IsResizable type trait.The IsResizable_v variable template provid...
Definition: IsResizable.h:134
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:713
bool isUniform(const DenseMatrix< MT, SO > &dm)
Checks if the given dense matrix is a uniform matrix.
Definition: DenseMatrix.h:849
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.
bool isStrictlyUpper(const DenseMatrix< MT, SO > &dm)
Checks if the given dense matrix is a strictly upper triangular matrix.
Definition: DenseMatrix.h:1446
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:617
Header file for the isDefault shim.
bool isSymmetric(const DenseMatrix< MT, SO > &dm)
Checks if the given dense matrix is symmetric.
Definition: DenseMatrix.h:539
#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.
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:290
bool isUniUpper(const DenseMatrix< MT, SO > &dm)
Checks if the given dense matrix is an upper unitriangular matrix.
Definition: DenseMatrix.h:1359
bool isIntact(const DiagonalMatrix< MT, SO, DF > &m)
Returns whether the invariants of the given diagonal matrix are intact.
Definition: DiagonalMatrix.h:263
Header file for the IsComplex type trait.
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:1326
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, 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
Header file for the TrueType type/value trait base class.
Header file for the IsExpression type trait class.