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 <blaze/math/Aliases.h>
48 #include <blaze/math/shims/Equal.h>
50 #include <blaze/math/shims/IsNaN.h>
51 #include <blaze/math/shims/IsOne.h>
71 #include <blaze/util/Assert.h>
72 #include <blaze/util/FalseType.h>
73 #include <blaze/util/mpl/If.h>
74 #include <blaze/util/TrueType.h>
75 #include <blaze/util/Types.h>
79 
80 
81 namespace blaze {
82 
83 //=================================================================================================
84 //
85 // GLOBAL OPERATORS
86 //
87 //=================================================================================================
88 
89 //*************************************************************************************************
92 template< typename T1, typename T2, bool SO >
93 inline bool operator==( const SparseMatrix<T1,false>& lhs, const SparseMatrix<T2,false>& rhs );
94 
95 template< typename T1, typename T2, bool SO >
96 inline bool operator==( const SparseMatrix<T1,true>& lhs, const SparseMatrix<T2,true>& rhs );
97 
98 template< typename T1, typename T2, bool SO >
99 inline bool operator==( const SparseMatrix<T1,SO>& lhs, const SparseMatrix<T2,!SO>& rhs );
100 
101 template< typename T1, bool SO1, typename T2, bool SO2 >
102 inline bool operator!=( const SparseMatrix<T1,SO1>& lhs, const SparseMatrix<T2,SO2>& rhs );
104 //*************************************************************************************************
105 
106 
107 //*************************************************************************************************
115 template< typename T1 // Type of the left-hand side sparse matrix
116  , typename T2 > // Type of the right-hand side sparse matrix
117 inline bool operator==( const SparseMatrix<T1,false>& lhs, const SparseMatrix<T2,false>& rhs )
118 {
119  using CT1 = CompositeType_<T1>;
120  using CT2 = CompositeType_<T2>;
121  using LhsConstIterator = ConstIterator_< RemoveReference_<CT1> >;
122  using RhsConstIterator = ConstIterator_< RemoveReference_<CT2> >;
123 
124  // Early exit in case the matrix sizes don't match
125  if( (~lhs).rows() != (~rhs).rows() || (~lhs).columns() != (~rhs).columns() )
126  return false;
127 
128  // Evaluation of the two sparse matrix operands
129  CT1 A( ~lhs );
130  CT2 B( ~rhs );
131 
132  // In order to compare the two matrices, the data values of the lower-order data
133  // type are converted to the higher-order data type within the equal function.
134  for( size_t i=0UL; i<A.rows(); ++i )
135  {
136  const LhsConstIterator lend( A.end(i) );
137  const RhsConstIterator rend( B.end(i) );
138 
139  LhsConstIterator lelem( A.begin(i) );
140  RhsConstIterator relem( B.begin(i) );
141 
142  while( lelem != lend && relem != rend )
143  {
144  if( lelem->index() < relem->index() ) {
145  if( !isDefault( lelem->value() ) )
146  return false;
147  ++lelem;
148  }
149  else if( lelem->index() > relem->index() ) {
150  if( !isDefault( relem->value() ) )
151  return false;
152  ++relem;
153  }
154  else if( !equal( lelem->value(), relem->value() ) ) {
155  return false;
156  }
157  else {
158  ++lelem;
159  ++relem;
160  }
161  }
162 
163  while( lelem != lend ) {
164  if( !isDefault( lelem->value() ) )
165  return false;
166  ++lelem;
167  }
168 
169  while( relem != rend ) {
170  if( !isDefault( relem->value() ) )
171  return false;
172  ++relem;
173  }
174  }
175 
176  return true;
177 }
178 //*************************************************************************************************
179 
180 
181 //*************************************************************************************************
189 template< typename T1 // Type of the left-hand side sparse matrix
190  , typename T2 > // Type of the right-hand side sparse matrix
191 inline bool operator==( const SparseMatrix<T1,true>& lhs, const SparseMatrix<T2,true>& rhs )
192 {
193  using CT1 = CompositeType_<T1>;
194  using CT2 = CompositeType_<T2>;
195  using LhsConstIterator = ConstIterator_< RemoveReference_<CT1> >;
196  using RhsConstIterator = ConstIterator_< RemoveReference_<CT2> >;
197 
198  // Early exit in case the matrix sizes don't match
199  if( (~lhs).rows() != (~rhs).rows() || (~lhs).columns() != (~rhs).columns() )
200  return false;
201 
202  // Evaluation of the two sparse matrix operands
203  CT1 A( ~lhs );
204  CT2 B( ~rhs );
205 
206  // In order to compare the two matrices, the data values of the lower-order data
207  // type are converted to the higher-order data type within the equal function.
208  for( size_t j=0UL; j<A.columns(); ++j )
209  {
210  const LhsConstIterator lend( A.end(j) );
211  const RhsConstIterator rend( B.end(j) );
212 
213  LhsConstIterator lelem( A.begin(j) );
214  RhsConstIterator relem( B.begin(j) );
215 
216  while( lelem != lend && relem != rend )
217  {
218  if( lelem->index() < relem->index() ) {
219  if( !isDefault( lelem->value() ) )
220  return false;
221  ++lelem;
222  }
223  else if( lelem->index() > relem->index() ) {
224  if( !isDefault( relem->value() ) )
225  return false;
226  ++relem;
227  }
228  else if( !equal( lelem->value(), relem->value() ) ) {
229  return false;
230  }
231  else {
232  ++lelem;
233  ++relem;
234  }
235  }
236 
237  while( lelem != lend ) {
238  if( !isDefault( lelem->value() ) )
239  return false;
240  ++lelem;
241  }
242 
243  while( relem != rend ) {
244  if( !isDefault( relem->value() ) )
245  return false;
246  ++relem;
247  }
248  }
249 
250  return true;
251 }
252 //*************************************************************************************************
253 
254 
255 //*************************************************************************************************
263 template< typename T1 // Type of the left-hand side sparse matrix
264  , typename T2 // Type of the right-hand side sparse matrix
265  , bool SO > // Storage order
266 inline bool operator==( const SparseMatrix<T1,SO>& lhs, const SparseMatrix<T2,!SO>& rhs )
267 {
268  const OppositeType_<T2> tmp( ~rhs );
269  return ( ~lhs == tmp );
270 }
271 //*************************************************************************************************
272 
273 
274 //*************************************************************************************************
282 template< typename T1 // Type of the left-hand side sparse matrix
283  , bool SO1 // Storage order of the left-hand side sparse matrix
284  , typename T2 // Type of the right-hand side sparse matrix
285  , bool SO2 > // Storage order of the right-hand side sparse matrix
286 inline bool operator!=( const SparseMatrix<T1,SO1>& lhs, const SparseMatrix<T2,SO2>& rhs )
287 {
288  return !( lhs == rhs );
289 }
290 //*************************************************************************************************
291 
292 
293 
294 
295 //=================================================================================================
296 //
297 // GLOBAL FUNCTIONS
298 //
299 //=================================================================================================
300 
301 //*************************************************************************************************
304 template< typename MT, bool SO >
305 bool isnan( const SparseMatrix<MT,SO>& sm );
306 
307 template< bool RF, typename MT, bool SO >
308 bool isSymmetric( const SparseMatrix<MT,SO>& sm );
309 
310 template< bool RF, typename MT, bool SO >
311 bool isHermitian( const SparseMatrix<MT,SO>& sm );
312 
313 template< bool RF, typename MT, bool SO >
314 bool isUniform( 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 );
339 
340 template< typename MT, bool SO >
341 const ElementType_<MT> min( const SparseMatrix<MT,SO>& sm );
342 
343 template< typename MT, bool SO >
344 const ElementType_<MT> max( const SparseMatrix<MT,SO>& sm );
346 //*************************************************************************************************
347 
348 
349 //*************************************************************************************************
369 template< typename MT // Type of the sparse matrix
370  , bool SO > // Storage order
371 bool isnan( const SparseMatrix<MT,SO>& sm )
372 {
373  using CT = CompositeType_<MT>;
375 
376  CT A( ~sm ); // Evaluation of the sparse matrix operand
377 
378  if( SO == rowMajor ) {
379  for( size_t i=0UL; i<A.rows(); ++i ) {
380  for( ConstIterator element=A.begin(i); element!=A.end(i); ++element )
381  if( isnan( element->value() ) ) return true;
382  }
383  }
384  else {
385  for( size_t j=0UL; j<A.columns(); ++j ) {
386  for( ConstIterator element=A.begin(j); element!=A.end(j); ++element )
387  if( isnan( element->value() ) ) return true;
388  }
389  }
390 
391  return false;
392 }
393 //*************************************************************************************************
394 
395 
396 //*************************************************************************************************
429 template< bool RF // Relaxation flag
430  , typename MT // Type of the sparse matrix
431  , bool SO > // Storage order
433 {
434  using RT = ResultType_<MT>;
435  using RN = ReturnType_<MT>;
436  using CT = CompositeType_<MT>;
437  using Tmp = If_< IsExpression<RN>, const RT, CT >;
439 
441  return true;
442 
443  if( !isSquare( ~sm ) )
444  return false;
445 
446  if( IsUniform<MT>::value || (~sm).rows() < 2UL )
447  return true;
448 
449  Tmp A( ~sm ); // Evaluation of the sparse matrix operand
450 
451  if( SO == rowMajor ) {
452  for( size_t i=0UL; i<A.rows(); ++i ) {
453  for( ConstIterator element=A.begin(i); element!=A.end(i); ++element )
454  {
455  const size_t j( element->index() );
456 
457  if( i == j || isDefault<RF>( element->value() ) )
458  continue;
459 
460  const ConstIterator pos( A.find( j, i ) );
461  if( pos == A.end(j) || !equal<RF>( pos->value(), element->value() ) )
462  return false;
463  }
464  }
465  }
466  else {
467  for( size_t j=0UL; j<A.columns(); ++j ) {
468  for( ConstIterator element=A.begin(j); element!=A.end(j); ++element )
469  {
470  const size_t i( element->index() );
471 
472  if( j == i || isDefault<RF>( element->value() ) )
473  continue;
474 
475  const ConstIterator pos( A.find( j, i ) );
476  if( pos == A.end(i) || !equal<RF>( pos->value(), element->value() ) )
477  return false;
478  }
479  }
480  }
481 
482  return true;
483 }
484 //*************************************************************************************************
485 
486 
487 //*************************************************************************************************
522 template< bool RF // Relaxation flag
523  , typename MT // Type of the sparse matrix
524  , bool SO > // Storage order
526 {
527  using RT = ResultType_<MT>;
528  using ET = ElementType_<MT>;
529  using RN = ReturnType_<MT>;
530  using CT = CompositeType_<MT>;
531  using Tmp = If_< IsExpression<RN>, const RT, CT >;
533 
535  return true;
536 
537  if( !IsNumeric<ET>::value || !isSquare( ~sm ) )
538  return false;
539 
541  return true;
542 
543  Tmp A( ~sm ); // Evaluation of the sparse matrix operand
544 
545  if( SO == rowMajor ) {
546  for( size_t i=0UL; i<A.rows(); ++i ) {
547  for( ConstIterator element=A.begin(i); element!=A.end(i); ++element )
548  {
549  const size_t j( element->index() );
550 
551  if( isDefault<RF>( element->value() ) )
552  continue;
553 
554  if( i == j && !isReal<RF>( element->value() ) )
555  return false;
556 
557  const ConstIterator pos( A.find( j, i ) );
558  if( pos == A.end(j) || !equal<RF>( pos->value(), conj( element->value() ) ) )
559  return false;
560  }
561  }
562  }
563  else {
564  for( size_t j=0UL; j<A.columns(); ++j ) {
565  for( ConstIterator element=A.begin(j); element!=A.end(j); ++element )
566  {
567  const size_t i( element->index() );
568 
569  if( isDefault<RF>( element->value() ) )
570  continue;
571 
572  if( j == i && !isReal<RF>( element->value() ) )
573  return false;
574 
575  const ConstIterator pos( A.find( j, i ) );
576  if( pos == A.end(i) || !equal<RF>( pos->value(), conj( element->value() ) ) )
577  return false;
578  }
579  }
580  }
581 
582  return true;
583 }
584 //*************************************************************************************************
585 
586 
587 //*************************************************************************************************
595 template< bool RF // Relaxation flag
596  , typename MT > // Type of the sparse matrix
597 bool isUniform_backend( const SparseMatrix<MT,false>& sm, TrueType )
598 {
601 
602  BLAZE_INTERNAL_ASSERT( (~sm).rows() != 0UL, "Invalid number of rows detected" );
603  BLAZE_INTERNAL_ASSERT( (~sm).columns() != 0UL, "Invalid number of columns detected" );
604 
606 
607  const size_t ibegin( ( IsStrictlyLower<MT>::value )?( 1UL ):( 0UL ) );
608  const size_t iend ( ( IsStrictlyUpper<MT>::value )?( (~sm).rows()-1UL ):( (~sm).rows() ) );
609 
610  for( size_t i=ibegin; i<iend; ++i ) {
611  for( ConstIterator element=(~sm).begin(i); element!=(~sm).end(i); ++element ) {
612  if( !isDefault<RF>( element->value() ) )
613  return false;
614  }
615  }
616 
617  return true;
618 }
620 //*************************************************************************************************
621 
622 
623 //*************************************************************************************************
631 template< bool RF // Relaxation flag
632  , typename MT > // Type of the sparse matrix
633 bool isUniform_backend( const SparseMatrix<MT,true>& sm, TrueType )
634 {
637 
638  BLAZE_INTERNAL_ASSERT( (~sm).rows() != 0UL, "Invalid number of rows detected" );
639  BLAZE_INTERNAL_ASSERT( (~sm).columns() != 0UL, "Invalid number of columns detected" );
640 
642 
643  const size_t jbegin( ( IsStrictlyUpper<MT>::value )?( 1UL ):( 0UL ) );
644  const size_t jend ( ( IsStrictlyLower<MT>::value )?( (~sm).columns()-1UL ):( (~sm).columns() ) );
645 
646  for( size_t j=jbegin; j<jend; ++j ) {
647  for( ConstIterator element=(~sm).begin(j); element!=(~sm).end(j); ++element ) {
648  if( !isDefault<RF>( element->value() ) )
649  return false;
650  }
651  }
652 
653  return true;
654 }
656 //*************************************************************************************************
657 
658 
659 //*************************************************************************************************
667 template< bool RF // Relaxation flag
668  , typename MT > // Type of the sparse matrix
669 bool isUniform_backend( const SparseMatrix<MT,false>& sm, FalseType )
670 {
673 
674  BLAZE_INTERNAL_ASSERT( (~sm).rows() != 0UL, "Invalid number of rows detected" );
675  BLAZE_INTERNAL_ASSERT( (~sm).columns() != 0UL, "Invalid number of columns detected" );
676 
679 
680  const size_t maxElements( (~sm).rows() * (~sm).columns() );
681 
682  if( (~sm).nonZeros() != maxElements )
683  {
684  for( size_t i=0UL; i<(~sm).rows(); ++i ) {
685  for( ConstIterator element=(~sm).begin(i); element!=(~sm).end(i); ++element ) {
686  if( !isDefault<RF>( element->value() ) )
687  return false;
688  }
689  }
690  }
691  else
692  {
693  BLAZE_INTERNAL_ASSERT( (~sm).find(0UL,0UL) != (~sm).end(0UL), "Missing element detected" );
694 
695  ConstReference cmp( (~sm)(0UL,0UL) );
696 
697  for( size_t i=0UL; i<(~sm).rows(); ++i ) {
698  for( ConstIterator element=(~sm).begin(i); element!=(~sm).end(i); ++element ) {
699  if( element->value() != cmp )
700  return false;
701  }
702  }
703  }
704 
705  return true;
706 }
708 //*************************************************************************************************
709 
710 
711 //*************************************************************************************************
719 template< bool RF // Relaxation flag
720  , typename MT > // Type of the sparse matrix
721 bool isUniform_backend( const SparseMatrix<MT,true>& sm, FalseType )
722 {
725 
726  BLAZE_INTERNAL_ASSERT( (~sm).rows() != 0UL, "Invalid number of rows detected" );
727  BLAZE_INTERNAL_ASSERT( (~sm).columns() != 0UL, "Invalid number of columns detected" );
728 
731 
732  const size_t maxElements( (~sm).rows() * (~sm).columns() );
733 
734  if( (~sm).nonZeros() != maxElements )
735  {
736  for( size_t j=0UL; j<(~sm).columns(); ++j ) {
737  for( ConstIterator element=(~sm).begin(j); element!=(~sm).end(j); ++element ) {
738  if( !isDefault<RF>( element->value() ) )
739  return false;
740  }
741  }
742  }
743  else
744  {
745  BLAZE_INTERNAL_ASSERT( (~sm).find(0UL,0UL) != (~sm).end(0UL), "Missing element detected" );
746 
747  ConstReference cmp( (~sm)(0UL,0UL) );
748 
749  for( size_t j=0UL; j<(~sm).columns(); ++j ) {
750  for( ConstIterator element=(~sm).begin(j); element!=(~sm).end(j); ++element ) {
751  if( element->value() != cmp )
752  return false;
753  }
754  }
755  }
756 
757  return true;
758 }
760 //*************************************************************************************************
761 
762 
763 //*************************************************************************************************
796 template< bool RF // Relaxation flag
797  , typename MT // Type of the sparse matrix
798  , bool SO > // Storage order
800 {
802  return false;
803 
804  if( IsUniform<MT>::value ||
805  (~sm).rows() == 0UL || (~sm).columns() == 0UL ||
806  ( (~sm).rows() == 1UL && (~sm).columns() == 1UL ) )
807  return true;
808 
809  CompositeType_<MT> A( ~sm ); // Evaluation of the sparse matrix operand
810 
811  return isUniform_backend<RF>( A, typename IsTriangular<MT>::Type() );
812 }
813 //*************************************************************************************************
814 
815 
816 //*************************************************************************************************
859 template< bool RF // Relaxation flag
860  , typename MT // Type of the sparse matrix
861  , bool SO > // Storage order
862 bool isLower( const SparseMatrix<MT,SO>& sm )
863 {
864  using RT = ResultType_<MT>;
865  using RN = ReturnType_<MT>;
866  using CT = CompositeType_<MT>;
867  using Tmp = If_< IsExpression<RN>, const RT, CT >;
869 
870  if( IsLower<MT>::value )
871  return true;
872 
873  if( !isSquare( ~sm ) )
874  return false;
875 
876  if( (~sm).rows() < 2UL )
877  return true;
878 
879  Tmp A( ~sm ); // Evaluation of the sparse matrix operand
880 
881  if( SO == rowMajor ) {
882  for( size_t i=0UL; i<A.rows()-1UL; ++i ) {
883  for( ConstIterator element=A.lowerBound(i,i+1UL); element!=A.end(i); ++element )
884  {
885  if( !isDefault<RF>( element->value() ) )
886  return false;
887  }
888  }
889  }
890  else {
891  for( size_t j=1UL; j<A.columns(); ++j ) {
892  for( ConstIterator element=A.begin(j); element!=A.end(j); ++element )
893  {
894  if( element->index() >= j )
895  break;
896 
897  if( !isDefault<RF>( element->value() ) )
898  return false;
899  }
900  }
901  }
902 
903  return true;
904 }
905 //*************************************************************************************************
906 
907 
908 //*************************************************************************************************
950 template< bool RF // Relaxation flag
951  , typename MT // Type of the sparse matrix
952  , bool SO > // Storage order
954 {
955  using RT = ResultType_<MT>;
956  using RN = ReturnType_<MT>;
957  using CT = CompositeType_<MT>;
958  using Tmp = If_< IsExpression<RN>, const RT, CT >;
960 
962  return true;
963 
964  if( !isSquare( ~sm ) )
965  return false;
966 
967  Tmp A( ~sm ); // Evaluation of the sparse matrix operand
968 
969  if( SO == rowMajor ) {
970  for( size_t i=0UL; i<A.rows(); ++i )
971  {
972  ConstIterator element( A.lowerBound(i,i) );
973 
974  if( element == A.end(i) || element->index() != i || !isOne<RF>( element->value() ) )
975  return false;
976 
977  ++element;
978 
979  for( ; element!=A.end(i); ++element ) {
980  if( !isZero<RF>( element->value() ) )
981  return false;
982  }
983  }
984  }
985  else {
986  for( size_t j=0UL; j<A.columns(); ++j )
987  {
988  bool hasDiagonalElement( false );
989 
990  for( ConstIterator element=A.begin(j); element!=A.end(j); ++element )
991  {
992  if( element->index() >= j ) {
993  if( element->index() != j || !isOne<RF>( element->value() ) )
994  return false;
995  hasDiagonalElement = true;
996  break;
997  }
998 
999  if( !isZero<RF>( element->value() ) )
1000  return false;
1001  }
1002 
1003  if( !hasDiagonalElement ) {
1004  return false;
1005  }
1006  }
1007  }
1008 
1009  return true;
1010 }
1011 //*************************************************************************************************
1012 
1013 
1014 //*************************************************************************************************
1057 template< bool RF // Relaxation flag
1058  , typename MT // Type of the sparse matrix
1059  , bool SO > // Storage order
1061 {
1062  using RT = ResultType_<MT>;
1063  using RN = ReturnType_<MT>;
1064  using CT = CompositeType_<MT>;
1065  using Tmp = If_< IsExpression<RN>, const RT, CT >;
1067 
1069  return true;
1070 
1072  return false;
1073 
1074  Tmp A( ~sm ); // Evaluation of the sparse matrix operand
1075 
1076  if( SO == rowMajor ) {
1077  for( size_t i=0UL; i<A.rows(); ++i ) {
1078  for( ConstIterator element=A.lowerBound(i,i); element!=A.end(i); ++element )
1079  {
1080  if( !isDefault<RF>( element->value() ) )
1081  return false;
1082  }
1083  }
1084  }
1085  else {
1086  for( size_t j=0UL; j<A.columns(); ++j ) {
1087  for( ConstIterator element=A.begin(j); element!=A.end(j); ++element )
1088  {
1089  if( element->index() > j )
1090  break;
1091 
1092  if( !isDefault<RF>( element->value() ) )
1093  return false;
1094  }
1095  }
1096  }
1097 
1098  return true;
1099 }
1100 //*************************************************************************************************
1101 
1102 
1103 //*************************************************************************************************
1146 template< bool RF // Relaxation flag
1147  , typename MT // Type of the sparse matrix
1148  , bool SO > // Storage order
1149 bool isUpper( const SparseMatrix<MT,SO>& sm )
1150 {
1151  using RT = ResultType_<MT>;
1152  using RN = ReturnType_<MT>;
1153  using CT = CompositeType_<MT>;
1154  using Tmp = If_< IsExpression<RN>, const RT, CT >;
1156 
1157  if( IsUpper<MT>::value )
1158  return true;
1159 
1160  if( !isSquare( ~sm ) )
1161  return false;
1162 
1163  if( (~sm).rows() < 2UL )
1164  return true;
1165 
1166  Tmp A( ~sm ); // Evaluation of the sparse matrix operand
1167 
1168  if( SO == rowMajor ) {
1169  for( size_t i=1UL; i<A.rows(); ++i ) {
1170  for( ConstIterator element=A.begin(i); element!=A.end(i); ++element )
1171  {
1172  if( element->index() >= i )
1173  break;
1174 
1175  if( !isDefault<RF>( element->value() ) )
1176  return false;
1177  }
1178  }
1179  }
1180  else {
1181  for( size_t j=0UL; j<A.columns()-1UL; ++j ) {
1182  for( ConstIterator element=A.lowerBound(j+1UL,j); element!=A.end(j); ++element )
1183  {
1184  if( !isDefault<RF>( element->value() ) )
1185  return false;
1186  }
1187  }
1188  }
1189 
1190  return true;
1191 }
1192 //*************************************************************************************************
1193 
1194 
1195 //*************************************************************************************************
1237 template< bool RF // Relaxation flag
1238  , typename MT // Type of the sparse matrix
1239  , bool SO > // Storage order
1241 {
1242  using RT = ResultType_<MT>;
1243  using RN = ReturnType_<MT>;
1244  using CT = CompositeType_<MT>;
1245  using Tmp = If_< IsExpression<RN>, const RT, CT >;
1247 
1248  if( IsUniUpper<MT>::value )
1249  return true;
1250 
1251  if( !isSquare( ~sm ) )
1252  return false;
1253 
1254  Tmp A( ~sm ); // Evaluation of the sparse matrix operand
1255 
1256  if( SO == rowMajor ) {
1257  for( size_t i=0UL; i<A.rows(); ++i )
1258  {
1259  bool hasDiagonalElement( false );
1260 
1261  for( ConstIterator element=A.begin(i); element!=A.end(i); ++element )
1262  {
1263  if( element->index() >= i ) {
1264  if( element->index() != i || !isOne<RF>( element->value() ) )
1265  return false;
1266  hasDiagonalElement = true;
1267  break;
1268  }
1269  else if( !isZero<RF>( element->value() ) ) {
1270  return false;
1271  }
1272  }
1273 
1274  if( !hasDiagonalElement ) {
1275  return false;
1276  }
1277  }
1278  }
1279  else {
1280  for( size_t j=0UL; j<A.columns(); ++j )
1281  {
1282  ConstIterator element( A.lowerBound(j,j) );
1283 
1284  if( element == A.end(j) || element->index() != j || !isOne<RF>( element->value() ) )
1285  return false;
1286 
1287  ++element;
1288 
1289  for( ; element!=A.end(j); ++element ) {
1290  if( !isZero<RF>( element->value() ) )
1291  return false;
1292  }
1293  }
1294  }
1295 
1296  return true;
1297 }
1298 //*************************************************************************************************
1299 
1300 
1301 //*************************************************************************************************
1344 template< bool RF // Relaxation flag
1345  , typename MT // Type of the sparse matrix
1346  , bool SO > // Storage order
1348 {
1349  using RT = ResultType_<MT>;
1350  using RN = ReturnType_<MT>;
1351  using CT = CompositeType_<MT>;
1352  using Tmp = If_< IsExpression<RN>, const RT, CT >;
1354 
1356  return true;
1357 
1359  return false;
1360 
1361  Tmp A( ~sm ); // Evaluation of the sparse matrix operand
1362 
1363  if( SO == rowMajor ) {
1364  for( size_t i=0UL; i<A.rows(); ++i ) {
1365  for( ConstIterator element=A.begin(i); element!=A.end(i); ++element )
1366  {
1367  if( element->index() > i )
1368  break;
1369 
1370  if( !isDefault<RF>( element->value() ) )
1371  return false;
1372  }
1373  }
1374  }
1375  else {
1376  for( size_t j=0UL; j<A.columns(); ++j ) {
1377  for( ConstIterator element=A.lowerBound(j,j); element!=A.end(j); ++element )
1378  {
1379  if( !isDefault<RF>( element->value() ) )
1380  return false;
1381  }
1382  }
1383  }
1384 
1385  return true;
1386 }
1387 //*************************************************************************************************
1388 
1389 
1390 //*************************************************************************************************
1433 template< bool RF // Relaxation flag
1434  , typename MT // Type of the sparse matrix
1435  , bool SO > // Storage order
1437 {
1438  using RT = ResultType_<MT>;
1439  using RN = ReturnType_<MT>;
1440  using CT = CompositeType_<MT>;
1441  using Tmp = If_< IsExpression<RN>, const RT, CT >;
1443 
1444  if( IsDiagonal<MT>::value )
1445  return true;
1446 
1447  if( !isSquare( ~sm ) )
1448  return false;
1449 
1450  if( (~sm).rows() < 2UL )
1451  return true;
1452 
1453  Tmp A( ~sm ); // Evaluation of the sparse matrix operand
1454 
1455  if( SO == rowMajor ) {
1456  for( size_t i=0UL; i<A.rows(); ++i ) {
1457  for( ConstIterator element=A.begin(i); element!=A.end(i); ++element )
1458  if( element->index() != i && !isDefault<RF>( element->value() ) )
1459  return false;
1460  }
1461  }
1462  else {
1463  for( size_t j=0UL; j<A.columns(); ++j ) {
1464  for( ConstIterator element=A.begin(j); element!=A.end(j); ++element )
1465  if( element->index() != j && !isDefault<RF>( element->value() ) )
1466  return false;
1467  }
1468  }
1469 
1470  return true;
1471 }
1472 //*************************************************************************************************
1473 
1474 
1475 //*************************************************************************************************
1518 template< bool RF // Relaxation flag
1519  , typename MT // Type of the sparse matrix
1520  , bool SO > // Storage order
1522 {
1523  using RT = ResultType_<MT>;
1524  using RN = ReturnType_<MT>;
1525  using CT = CompositeType_<MT>;
1526  using Tmp = If_< IsExpression<RN>, const RT, CT >;
1528 
1529  if( IsIdentity<MT>::value )
1530  return true;
1531 
1532  if( !isSquare( ~sm ) )
1533  return false;
1534 
1535  Tmp A( ~sm ); // Evaluation of the sparse matrix operand
1536 
1537  if( SO == rowMajor ) {
1538  for( size_t i=0UL; i<A.rows(); ++i )
1539  {
1540  bool hasDiagonalElement( false );
1541 
1542  for( ConstIterator element=A.begin(i); element!=A.end(i); ++element )
1543  {
1544  if( element->index() == i ) {
1545  if( !isOne<RF>( element->value() ) )
1546  return false;
1547  hasDiagonalElement = true;
1548  }
1549  else if( !isZero<RF>( element->value() ) ) {
1550  return false;
1551  }
1552  }
1553 
1554  if( !hasDiagonalElement ) {
1555  return false;
1556  }
1557  }
1558  }
1559  else {
1560  for( size_t j=0UL; j<A.columns(); ++j )
1561  {
1562  bool hasDiagonalElement( false );
1563 
1564  for( ConstIterator element=A.begin(j); element!=A.end(j); ++element )
1565  {
1566  if( element->index() == j ) {
1567  if( !isOne<RF>( element->value() ) )
1568  return false;
1569  hasDiagonalElement = true;
1570  }
1571  else if( !isZero<RF>( element->value() ) ) {
1572  return false;
1573  }
1574  }
1575 
1576  if( !hasDiagonalElement ) {
1577  return false;
1578  }
1579  }
1580  }
1581 
1582  return true;
1583 }
1584 //*************************************************************************************************
1585 
1586 
1587 //*************************************************************************************************
1599 template< typename MT // Type of the sparse matrix
1600  , bool SO > // Storage order
1602 {
1603  using blaze::min;
1604 
1605  using ET = ElementType_<MT>;
1606  using CT = CompositeType_<MT>;
1608 
1609  CT A( ~sm ); // Evaluation of the sparse matrix operand
1610 
1611  const size_t nonzeros( A.nonZeros() );
1612 
1613  if( nonzeros == 0UL ) {
1614  return ET();
1615  }
1616 
1617  ET minimum = ET();
1618  if( nonzeros == A.rows() * A.columns() ) {
1619  minimum = A.begin( 0UL )->value();
1620  }
1621 
1622  const size_t index( ( SO == rowMajor )?( A.rows() ):( A.columns() ) );
1623 
1624  for( size_t i=0UL; i<index; ++i ) {
1625  const ConstIterator end( A.end( i ) );
1626  ConstIterator element( A.begin( i ) );
1627  for( ; element!=end; ++element )
1628  minimum = min( minimum, element->value() );
1629  }
1630 
1631  return minimum;
1632 }
1633 //*************************************************************************************************
1634 
1635 
1636 //*************************************************************************************************
1648 template< typename MT // Type of the sparse matrix
1649  , bool SO > // Storage order
1651 {
1652  using blaze::max;
1653 
1654  using ET = ElementType_<MT>;
1655  using CT = CompositeType_<MT>;
1657 
1658  CT A( ~sm ); // Evaluation of the sparse matrix operand
1659 
1660  const size_t nonzeros( A.nonZeros() );
1661 
1662  if( nonzeros == 0UL ) {
1663  return ET();
1664  }
1665 
1666  ET maximum = ET();
1667  if( nonzeros == A.rows() * A.columns() ) {
1668  maximum = A.begin( 0UL )->value();
1669  }
1670 
1671  const size_t index( ( SO == rowMajor )?( A.rows() ):( A.columns() ) );
1672 
1673  for( size_t i=0UL; i<index; ++i ) {
1674  const ConstIterator end( A.end( i ) );
1675  ConstIterator element( A.begin( i ) );
1676  for( ; element!=end; ++element )
1677  maximum = max( maximum, element->value() );
1678  }
1679 
1680  return maximum;
1681 }
1682 //*************************************************************************************************
1683 
1684 } // namespace blaze
1685 
1686 #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 auxiliary alias declarations.
Headerfile for the generic min algorithm.
Compile time check for numeric types.This type trait tests whether or not the given template paramete...
Definition: IsNumeric.h:79
bool isLower(const DenseMatrix< MT, SO > &dm)
Checks if the given dense matrix is a lower triangular matrix.
Definition: DenseMatrix.h:1073
bool isUpper(const DenseMatrix< MT, SO > &dm)
Checks if the given dense matrix is an upper triangular matrix.
Definition: DenseMatrix.h:1328
bool isStrictlyLower(const DenseMatrix< MT, SO > &dm)
Checks if the given dense matrix is a strictly lower triangular matrix.
Definition: DenseMatrix.h:1245
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:87
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
constexpr bool equal(const T1 &a, const T2 &b)
Generic equality check.
Definition: Equal.h:76
Header file for the FalseType type/value trait base class.
Header file for the IsDiagonal type trait.
Generic wrapper for a compile time constant integral value.The IntegralConstant class template repres...
Definition: IntegralConstant.h:71
BLAZE_ALWAYS_INLINE MT::Iterator begin(Matrix< MT, SO > &matrix, size_t i)
Returns an iterator to the first element of row/column i.
Definition: Matrix.h:198
Compile time check for uniform vectors and matrices.This type trait tests whether or not the given te...
Definition: IsUniform.h:67
bool isUniLower(const DenseMatrix< MT, SO > &dm)
Checks if the given dense matrix is a lower unitriangular matrix.
Definition: DenseMatrix.h:1158
const ElementType_< MT > min(const DenseMatrix< MT, SO > &dm)
Returns the smallest element of the dense matrix.
Definition: DenseMatrix.h:1762
Compile time check for lower triangular matrices.This type trait tests whether or not the given templ...
Definition: IsLower.h:88
Header file for the IsIdentity type trait.
const Type & ConstReference
Reference to a constant matrix value.
Definition: CompressedMatrix.h:3085
bool isDiagonal(const DenseMatrix< MT, SO > &dm)
Checks if the give dense matrix is diagonal.
Definition: DenseMatrix.h:1584
BLAZE_ALWAYS_INLINE size_t nonZeros(const Matrix< MT, SO > &matrix)
Returns the total number of non-zero elements in the matrix.
Definition: Matrix.h:394
Compile time check for upper triangular matrices.This type trait tests whether or not the given templ...
Definition: IsUpper.h:88
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
const ElementType_< MT > max(const DenseMatrix< MT, SO > &dm)
Returns the largest element of the dense matrix.
Definition: DenseMatrix.h:1809
Base class for sparse matrices.The SparseMatrix class is a base class for all sparse matrix classes...
Definition: Forward.h:129
bool isIdentity(const DenseMatrix< MT, SO > &dm)
Checks if the give dense matrix is an identity matrix.
Definition: DenseMatrix.h:1686
typename T::ReturnType ReturnType_
Alias declaration for nested ReturnType type definitions.The ReturnType_ alias declaration provides a...
Definition: Aliases.h:363
Header file for the SparseMatrix base class.
Header file for the IsSquare type trait.
Header file for the matrix storage order types.
Constraint on the data type.
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
Headerfile for the generic max algorithm.
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:57
Header file for the If class template.
const Element * ConstIterator
Iterator over constant elements.
Definition: CompressedMatrix.h:3087
constexpr bool operator==(const NegativeAccuracy< A > &lhs, const T &rhs)
Equality comparison between a NegativeAccuracy object and a floating point value. ...
Definition: Accuracy.h:250
typename T::ElementType ElementType_
Alias declaration for nested ElementType type definitions.The ElementType_ alias declaration provides...
Definition: Aliases.h:163
Header file for the IsLower type trait.
Compile time check for diagonal matrices.This type trait tests whether or not the given template para...
Definition: IsDiagonal.h:90
BLAZE_ALWAYS_INLINE size_t columns(const Matrix< MT, SO > &matrix) noexcept
Returns the current number of columns of the matrix.
Definition: Matrix.h:340
Header file for the equal shim.
Header file for the IsUniTriangular type trait.
Header file for the IsTriangular type trait.
Compile time check for symmetric matrices.This type trait tests whether or not the given template par...
Definition: IsSymmetric.h:85
bool isnan(const DiagonalProxy< MT > &proxy)
Returns whether the represented element is not a number.
Definition: DiagonalProxy.h:682
Compile time check for strictly upper triangular matrices.This type trait tests whether or not the gi...
Definition: IsStrictlyUpper.h:86
bool isUniform(const DenseMatrix< MT, SO > &dm)
Checks if the given dense matrix is a uniform matrix.
Definition: DenseMatrix.h:1010
BLAZE_ALWAYS_INLINE 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:264
constexpr bool operator!=(const NegativeAccuracy< A > &lhs, const T &rhs)
Inequality comparison between a NegativeAccuracy object and a floating point value.
Definition: Accuracy.h:290
Constraint on the data type.
Header file for the IsStrictlyLower type trait.
Header file for the isOne shim.
Compile time check for lower unitriangular matrices.This type trait tests whether or not the given te...
Definition: IsUniLower.h:86
Header file for the conjugate shim.
Header file for the IsNumeric type trait.
Compile time check for identity matrices.This type trait tests whether or not the given template para...
Definition: IsIdentity.h:90
bool isStrictlyUpper(const DenseMatrix< MT, SO > &dm)
Checks if the given dense matrix is a strictly upper triangular matrix.
Definition: DenseMatrix.h:1500
Header file for run time assertion macros.
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
bool isHermitian(const DenseMatrix< MT, SO > &dm)
Checks if the given dense matrix is Hermitian.
Definition: DenseMatrix.h:778
Header file for the isDefault shim.
Compile time check for Hermitian matrices.This type trait tests whether or not the given template par...
Definition: IsHermitian.h:85
Compile time check for built-in data types.This type trait tests whether or not the given template pa...
Definition: IsBuiltin.h:75
bool isSymmetric(const DenseMatrix< MT, SO > &dm)
Checks if the given dense matrix is symmetric.
Definition: DenseMatrix.h:700
#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
Header file for the RemoveReference type trait.
typename T::OppositeType OppositeType_
Alias declaration for nested OppositeType type definitions.The OppositeType_ alias declaration provid...
Definition: Aliases.h:263
Compile time check for strictly lower triangular matrices.This type trait tests whether or not the gi...
Definition: IsStrictlyLower.h:86
typename T::ConstReference ConstReference_
Alias declaration for nested ConstReference type definitions.The ConstReference_ alias declaration pr...
Definition: Aliases.h:143
BLAZE_ALWAYS_INLINE size_t rows(const Matrix< MT, SO > &matrix) noexcept
Returns the current number of rows of the matrix.
Definition: Matrix.h:324
typename T::ConstIterator ConstIterator_
Alias declaration for nested ConstIterator type definitions.The ConstIterator_ alias declaration prov...
Definition: Aliases.h:103
const bool rowMajor
Storage order flag for row-major matrices.
Definition: StorageOrder.h:71
Header file for the IsBuiltin type trait.
bool isUniUpper(const DenseMatrix< MT, SO > &dm)
Checks if the given dense matrix is an upper unitriangular matrix.
Definition: DenseMatrix.h:1413
bool isDefault(const DiagonalProxy< MT > &proxy)
Returns whether the represented element is in default state.
Definition: DiagonalProxy.h:600
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:1321
Header file for the IsHermitian type trait.
BLAZE_ALWAYS_INLINE bool isSquare(const Matrix< MT, SO > &matrix) noexcept
Checks if the given matrix is a square matrix.
Definition: Matrix.h:742
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.
Compile time check for unitriangular matrix types.This type trait tests whether or not the given temp...
Definition: IsUniTriangular.h:87
Header file for the IsExpression type trait class.