Mercurial > hg > octave-nkf
comparison liboctave/MatrixType.cc @ 7798:42c42c640108
improved matrix_type check
author | Jaroslav Hajek <highegg@gmail.com> |
---|---|
date | Wed, 21 May 2008 17:14:08 +0200 |
parents | 82be108cc558 |
children | 25bc2d31e1bf |
comparison
equal
deleted
inserted
replaced
7797:f42c6f8d6d8e | 7798:42c42c640108 |
---|---|
53 for (octave_idx_type i = 0; i < nperm; i++) | 53 for (octave_idx_type i = 0; i < nperm; i++) |
54 perm[i] = a.perm[i]; | 54 perm[i] = a.perm[i]; |
55 } | 55 } |
56 } | 56 } |
57 | 57 |
58 MatrixType::MatrixType (const Matrix &a) | 58 template<class T> |
59 : typ (MatrixType::Unknown), | 59 MatrixType::matrix_type |
60 sp_bandden (0), bandden (0), upper_band (0), lower_band (0), | 60 matrix_real_probe (const MArray2<T>& a) |
61 dense (false), full (true), nperm (0), perm (0) | 61 { |
62 { | 62 MatrixType::matrix_type typ; |
63 octave_idx_type nrows = a.rows (); | 63 octave_idx_type nrows = a.rows (); |
64 octave_idx_type ncols = a.cols (); | 64 octave_idx_type ncols = a.cols (); |
65 | |
66 const T zero = 0; | |
65 | 67 |
66 if (ncols == nrows) | 68 if (ncols == nrows) |
67 { | 69 { |
68 bool upper = true; | 70 bool upper = true; |
69 bool lower = true; | 71 bool lower = true; |
70 bool hermitian = true; | 72 bool hermitian = true; |
71 | 73 |
72 for (octave_idx_type j = 0; j < ncols; j++) | 74 // do the checks for lower/upper/hermitian all in one pass. |
73 { | 75 ColumnVector diag(ncols); |
74 if (j < nrows) | 76 |
75 { | 77 for (octave_idx_type j = 0; |
76 if (a.elem (j,j) == 0.) | 78 j < ncols && upper; j++) |
77 { | 79 { |
78 upper = false; | 80 T d = a.elem (j,j); |
79 lower = false; | 81 upper = upper && (d != zero); |
80 hermitian = false; | 82 lower = lower && (d != zero); |
81 break; | 83 hermitian = hermitian && (d > zero); |
82 } | 84 diag(j) = d; |
83 if (a.elem (j,j) < 0.) | 85 } |
84 hermitian = false; | 86 |
85 } | 87 for (octave_idx_type j = 0; |
86 for (octave_idx_type i = 0; i < j; i++) | 88 j < ncols && (upper || lower || hermitian); j++) |
87 if (lower && a.elem (i,j) != 0.) | 89 { |
88 { | 90 for (octave_idx_type i = 0; i < j; i++) |
89 lower = false; | 91 { |
90 break; | 92 double aij = a.elem (i,j), aji = a.elem (j,i); |
91 } | 93 lower = lower && (aij == zero); |
92 for (octave_idx_type i = j+1; i < nrows; i++) | 94 upper = upper && (aji == zero); |
93 { | 95 hermitian = hermitian && (aij == aji |
94 if (hermitian && a.elem (i, j) != a.elem (j, i)) | 96 && aij*aij < diag(i)*diag(j)); |
95 hermitian = false; | 97 } |
96 if (upper && a.elem (i,j) != 0) | 98 } |
97 upper = false; | 99 |
98 } | 100 if (upper) |
99 if (!upper && !lower && !hermitian) | 101 typ = MatrixType::Upper; |
100 break; | 102 else if (lower) |
101 } | 103 typ = MatrixType::Lower; |
104 else if (hermitian) | |
105 typ = MatrixType::Hermitian; | |
106 else | |
107 typ = MatrixType::Full; | |
108 } | |
109 else | |
110 typ = MatrixType::Rectangular; | |
111 | |
112 return typ; | |
113 } | |
114 | |
115 template<class T> | |
116 MatrixType::matrix_type | |
117 matrix_complex_probe (const MArray2<T>& a) | |
118 { | |
119 MatrixType::matrix_type typ; | |
120 octave_idx_type nrows = a.rows (); | |
121 octave_idx_type ncols = a.cols (); | |
122 | |
123 const typename T::value_type zero = 0; | |
124 | |
125 if (ncols == nrows) | |
126 { | |
127 bool upper = true; | |
128 bool lower = true; | |
129 bool hermitian = true; | |
130 | |
131 // do the checks for lower/upper/hermitian all in one pass. | |
132 ColumnVector diag(ncols); | |
133 | |
134 for (octave_idx_type j = 0; | |
135 j < ncols && upper; j++) | |
136 { | |
137 T d = a.elem (j,j); | |
138 upper = upper && (d != zero); | |
139 lower = lower && (d != zero); | |
140 hermitian = hermitian && (d.real() > zero && d.imag() == zero); | |
141 diag (j) = d.real(); | |
142 } | |
143 | |
144 for (octave_idx_type j = 0; | |
145 j < ncols && (upper || lower || hermitian); j++) | |
146 { | |
147 for (octave_idx_type i = 0; i < j; i++) | |
148 { | |
149 T aij = a.elem (i,j), aji = a.elem (j,i); | |
150 lower = lower && (aij == zero); | |
151 upper = upper && (aji == zero); | |
152 hermitian = hermitian && (aij == std::conj (aji) | |
153 && std::norm (aij) < diag(i)*diag(j)); | |
154 } | |
155 } | |
156 | |
102 | 157 |
103 if (upper) | 158 if (upper) |
104 typ = MatrixType::Upper; | 159 typ = MatrixType::Upper; |
105 else if (lower) | 160 else if (lower) |
106 typ = MatrixType::Lower; | 161 typ = MatrixType::Lower; |
109 else if (ncols == nrows) | 164 else if (ncols == nrows) |
110 typ = MatrixType::Full; | 165 typ = MatrixType::Full; |
111 } | 166 } |
112 else | 167 else |
113 typ = MatrixType::Rectangular; | 168 typ = MatrixType::Rectangular; |
169 | |
170 return typ; | |
171 } | |
172 | |
173 MatrixType::MatrixType (const Matrix &a) | |
174 : typ (MatrixType::Unknown), | |
175 sp_bandden (0), bandden (0), upper_band (0), lower_band (0), | |
176 dense (false), full (true), nperm (0), perm (0) | |
177 { | |
178 typ = matrix_real_probe (a); | |
114 } | 179 } |
115 | 180 |
116 MatrixType::MatrixType (const ComplexMatrix &a) | 181 MatrixType::MatrixType (const ComplexMatrix &a) |
117 : typ (MatrixType::Unknown), | 182 : typ (MatrixType::Unknown), |
118 sp_bandden (0), bandden (0), upper_band (0), lower_band (0), | 183 sp_bandden (0), bandden (0), upper_band (0), lower_band (0), |
119 dense (false), full (true), nperm (0), perm (0) | 184 dense (false), full (true), nperm (0), perm (0) |
120 { | 185 { |
121 octave_idx_type nrows = a.rows (); | 186 typ = matrix_complex_probe (a); |
122 octave_idx_type ncols = a.cols (); | |
123 | |
124 if (ncols == nrows) | |
125 { | |
126 bool upper = true; | |
127 bool lower = true; | |
128 bool hermitian = true; | |
129 | |
130 for (octave_idx_type j = 0; j < ncols; j++) | |
131 { | |
132 if (j < ncols) | |
133 { | |
134 if (imag(a.elem (j,j)) == 0. && | |
135 real(a.elem (j,j)) == 0.) | |
136 { | |
137 upper = false; | |
138 lower = false; | |
139 hermitian = false; | |
140 break; | |
141 } | |
142 | |
143 if (imag(a.elem (j,j)) != 0. || | |
144 real(a.elem (j,j)) < 0.) | |
145 hermitian = false; | |
146 } | |
147 for (octave_idx_type i = 0; i < j; i++) | |
148 if (lower && (real(a.elem (i,j)) != 0 || imag(a.elem (i,j)) != 0)) | |
149 { | |
150 lower = false; | |
151 break; | |
152 } | |
153 for (octave_idx_type i = j+1; i < nrows; i++) | |
154 { | |
155 if (hermitian && a.elem (i, j) != conj(a.elem (j, i))) | |
156 hermitian = false; | |
157 if (upper && (real(a.elem (i,j)) != 0 || | |
158 imag(a.elem (i,j)) != 0)) | |
159 upper = false; | |
160 } | |
161 if (!upper && !lower && !hermitian) | |
162 break; | |
163 } | |
164 | |
165 if (upper) | |
166 typ = MatrixType::Upper; | |
167 else if (lower) | |
168 typ = MatrixType::Lower; | |
169 else if (hermitian) | |
170 typ = MatrixType::Hermitian; | |
171 else if (ncols == nrows) | |
172 typ = MatrixType::Full; | |
173 } | |
174 else | |
175 typ = MatrixType::Rectangular; | |
176 } | 187 } |
177 | 188 |
178 | 189 |
179 MatrixType::MatrixType (const FloatMatrix &a) | 190 MatrixType::MatrixType (const FloatMatrix &a) |
180 : typ (MatrixType::Unknown), | 191 : typ (MatrixType::Unknown), |
181 sp_bandden (0), bandden (0), upper_band (0), lower_band (0), | 192 sp_bandden (0), bandden (0), upper_band (0), lower_band (0), |
182 dense (false), full (true), nperm (0), perm (0) | 193 dense (false), full (true), nperm (0), perm (0) |
183 { | 194 { |
184 octave_idx_type nrows = a.rows (); | 195 typ = matrix_real_probe (a); |
185 octave_idx_type ncols = a.cols (); | |
186 | |
187 if (ncols == nrows) | |
188 { | |
189 bool upper = true; | |
190 bool lower = true; | |
191 bool hermitian = true; | |
192 | |
193 for (octave_idx_type j = 0; j < ncols; j++) | |
194 { | |
195 if (j < nrows) | |
196 { | |
197 if (a.elem (j,j) == 0.) | |
198 { | |
199 upper = false; | |
200 lower = false; | |
201 hermitian = false; | |
202 break; | |
203 } | |
204 if (a.elem (j,j) < 0.) | |
205 hermitian = false; | |
206 } | |
207 for (octave_idx_type i = 0; i < j; i++) | |
208 if (lower && a.elem (i,j) != 0.) | |
209 { | |
210 lower = false; | |
211 break; | |
212 } | |
213 for (octave_idx_type i = j+1; i < nrows; i++) | |
214 { | |
215 if (hermitian && a.elem (i, j) != a.elem (j, i)) | |
216 hermitian = false; | |
217 if (upper && a.elem (i,j) != 0) | |
218 upper = false; | |
219 } | |
220 if (!upper && !lower && !hermitian) | |
221 break; | |
222 } | |
223 | |
224 if (upper) | |
225 typ = MatrixType::Upper; | |
226 else if (lower) | |
227 typ = MatrixType::Lower; | |
228 else if (hermitian) | |
229 typ = MatrixType::Hermitian; | |
230 else if (ncols == nrows) | |
231 typ = MatrixType::Full; | |
232 } | |
233 else | |
234 typ = MatrixType::Rectangular; | |
235 } | 196 } |
236 | 197 |
237 MatrixType::MatrixType (const FloatComplexMatrix &a) | 198 MatrixType::MatrixType (const FloatComplexMatrix &a) |
238 : typ (MatrixType::Unknown), | 199 : typ (MatrixType::Unknown), |
239 sp_bandden (0), bandden (0), upper_band (0), lower_band (0), | 200 sp_bandden (0), bandden (0), upper_band (0), lower_band (0), |
240 dense (false), full (true), nperm (0), perm (0) | 201 dense (false), full (true), nperm (0), perm (0) |
241 { | 202 { |
242 octave_idx_type nrows = a.rows (); | 203 typ = matrix_complex_probe (a); |
243 octave_idx_type ncols = a.cols (); | |
244 | |
245 if (ncols == nrows) | |
246 { | |
247 bool upper = true; | |
248 bool lower = true; | |
249 bool hermitian = true; | |
250 | |
251 for (octave_idx_type j = 0; j < ncols; j++) | |
252 { | |
253 if (j < ncols) | |
254 { | |
255 if (imag(a.elem (j,j)) == 0. && | |
256 real(a.elem (j,j)) == 0.) | |
257 { | |
258 upper = false; | |
259 lower = false; | |
260 hermitian = false; | |
261 break; | |
262 } | |
263 | |
264 if (imag(a.elem (j,j)) != 0. || | |
265 real(a.elem (j,j)) < 0.) | |
266 hermitian = false; | |
267 } | |
268 for (octave_idx_type i = 0; i < j; i++) | |
269 if (lower && (real(a.elem (i,j)) != 0 || imag(a.elem (i,j)) != 0)) | |
270 { | |
271 lower = false; | |
272 break; | |
273 } | |
274 for (octave_idx_type i = j+1; i < nrows; i++) | |
275 { | |
276 if (hermitian && a.elem (i, j) != conj(a.elem (j, i))) | |
277 hermitian = false; | |
278 if (upper && (real(a.elem (i,j)) != 0 || | |
279 imag(a.elem (i,j)) != 0)) | |
280 upper = false; | |
281 } | |
282 if (!upper && !lower && !hermitian) | |
283 break; | |
284 } | |
285 | |
286 if (upper) | |
287 typ = MatrixType::Upper; | |
288 else if (lower) | |
289 typ = MatrixType::Lower; | |
290 else if (hermitian) | |
291 typ = MatrixType::Hermitian; | |
292 else if (ncols == nrows) | |
293 typ = MatrixType::Full; | |
294 } | |
295 else | |
296 typ = MatrixType::Rectangular; | |
297 } | 204 } |
298 | 205 |
299 MatrixType::MatrixType (const SparseMatrix &a) | 206 MatrixType::MatrixType (const SparseMatrix &a) |
300 : typ (MatrixType::Unknown), | 207 : typ (MatrixType::Unknown), |
301 sp_bandden (0), bandden (0), upper_band (0), lower_band (0), | 208 sp_bandden (0), bandden (0), upper_band (0), lower_band (0), |
558 | 465 |
559 if (maybe_hermitian && (typ == MatrixType::Full || | 466 if (maybe_hermitian && (typ == MatrixType::Full || |
560 typ == MatrixType::Tridiagonal || | 467 typ == MatrixType::Tridiagonal || |
561 typ == MatrixType::Banded)) | 468 typ == MatrixType::Banded)) |
562 { | 469 { |
563 // Check for symmetry, with positive real diagonal, which | |
564 // has a very good chance of being symmetric positive | |
565 // definite.. | |
566 bool is_herm = true; | 470 bool is_herm = true; |
567 | 471 |
568 for (octave_idx_type j = 0; j < ncols; j++) | 472 // first, check whether the diagonal is positive & extract it |
569 { | 473 ColumnVector diag (ncols); |
570 bool diag_positive = false; | 474 |
571 | 475 for (octave_idx_type j = 0; is_herm && j < ncols; j++) |
572 for (octave_idx_type i = a.cidx(j); i < a.cidx(j+1); i++) | 476 { |
573 { | 477 is_herm = false; |
574 octave_idx_type ri = a.ridx(i); | 478 for (octave_idx_type i = a.cidx(j); i < a.cidx(j+1); i++) |
575 | 479 { |
576 if (ri == j) | 480 if (a.ridx(i) == j) |
577 { | 481 { |
578 if (a.data(i) == std::abs(a.data(i))) | 482 double d = a.data(i); |
579 diag_positive = true; | 483 is_herm = d > 0.; |
580 else | 484 diag(j) = d; |
581 break; | 485 break; |
582 } | 486 } |
583 else | 487 } |
584 { | 488 } |
585 bool found = false; | 489 |
586 | 490 |
587 for (octave_idx_type k = a.cidx(ri); k < a.cidx(ri+1); k++) | 491 // next, check symmetry and 2x2 positiveness |
588 { | 492 |
589 if (a.ridx(k) == j) | 493 for (octave_idx_type j = 0; is_herm && j < ncols; j++) |
590 { | 494 for (octave_idx_type i = a.cidx(j); is_herm && i < a.cidx(j+1); i++) |
591 if (a.data(i) == a.data(k)) | 495 { |
592 found = true; | 496 octave_idx_type k = a.ridx(i); |
593 break; | 497 is_herm = k == j; |
594 } | 498 if (is_herm) |
595 } | 499 continue; |
596 | 500 double d = a.data(i); |
597 if (! found) | 501 if (d*d < diag(j)*diag(k)) |
598 { | 502 { |
599 is_herm = false; | 503 for (octave_idx_type l = a.cidx(k); l < a.cidx(k+1); l++) |
600 break; | 504 { |
601 } | 505 if (a.ridx(l) == j) |
602 } | 506 { |
603 } | 507 is_herm = a.data(l) == d; |
604 | 508 break; |
605 if (! diag_positive || ! is_herm) | 509 } |
606 { | 510 } |
607 is_herm = false; | 511 } |
608 break; | 512 } |
609 } | |
610 } | |
611 | 513 |
612 if (is_herm) | 514 if (is_herm) |
613 { | 515 { |
614 if (typ == MatrixType::Full) | 516 if (typ == MatrixType::Full) |
615 typ = MatrixType::Hermitian; | 517 typ = MatrixType::Hermitian; |
884 | 786 |
885 if (maybe_hermitian && (typ == MatrixType::Full || | 787 if (maybe_hermitian && (typ == MatrixType::Full || |
886 typ == MatrixType::Tridiagonal || | 788 typ == MatrixType::Tridiagonal || |
887 typ == MatrixType::Banded)) | 789 typ == MatrixType::Banded)) |
888 { | 790 { |
889 // Check for symmetry, with positive real diagonal, which | |
890 // has a very good chance of being symmetric positive | |
891 // definite.. | |
892 bool is_herm = true; | 791 bool is_herm = true; |
893 | 792 |
894 for (octave_idx_type j = 0; j < ncols; j++) | 793 // first, check whether the diagonal is positive & extract it |
895 { | 794 ColumnVector diag (ncols); |
896 bool diag_positive = false; | 795 |
897 | 796 for (octave_idx_type j = 0; is_herm && j < ncols; j++) |
898 for (octave_idx_type i = a.cidx(j); i < a.cidx(j+1); i++) | 797 { |
899 { | 798 is_herm = false; |
900 octave_idx_type ri = a.ridx(i); | 799 for (octave_idx_type i = a.cidx(j); i < a.cidx(j+1); i++) |
901 | 800 { |
902 if (ri == j) | 801 if (a.ridx(i) == j) |
903 { | 802 { |
904 if (a.data(i) == std::abs(a.data(i))) | 803 Complex d = a.data(i); |
905 diag_positive = true; | 804 is_herm = d.real() > 0. && d.imag() == 0.; |
906 else | 805 diag(j) = d.real(); |
907 break; | 806 break; |
908 } | 807 } |
909 else | 808 } |
910 { | 809 } |
911 bool found = false; | 810 |
912 | 811 // next, check symmetry and 2x2 positiveness |
913 for (octave_idx_type k = a.cidx(ri); k < a.cidx(ri+1); k++) | 812 |
914 { | 813 for (octave_idx_type j = 0; is_herm && j < ncols; j++) |
915 if (a.ridx(k) == j) | 814 for (octave_idx_type i = a.cidx(j); is_herm && i < a.cidx(j+1); i++) |
916 { | 815 { |
917 if (a.data(i) == conj(a.data(k))) | 816 octave_idx_type k = a.ridx(i); |
918 found = true; | 817 is_herm = k == j; |
919 break; | 818 if (is_herm) |
920 } | 819 continue; |
921 } | 820 Complex d = a.data(i); |
922 | 821 if (std::norm (d) < diag(j)*diag(k)) |
923 if (! found) | 822 { |
924 { | 823 d = std::conj (d); |
925 is_herm = false; | 824 for (octave_idx_type l = a.cidx(k); l < a.cidx(k+1); l++) |
926 break; | 825 { |
927 } | 826 if (a.ridx(l) == j) |
928 } | 827 { |
929 } | 828 is_herm = a.data(l) == d; |
930 | 829 break; |
931 if (! diag_positive || ! is_herm) | 830 } |
932 { | 831 } |
933 is_herm = false; | 832 } |
934 break; | 833 } |
935 } | 834 |
936 } | |
937 | 835 |
938 if (is_herm) | 836 if (is_herm) |
939 { | 837 { |
940 if (typ == MatrixType::Full) | 838 if (typ == MatrixType::Full) |
941 typ = MatrixType::Hermitian; | 839 typ = MatrixType::Hermitian; |
951 : typ (MatrixType::Unknown), | 849 : typ (MatrixType::Unknown), |
952 sp_bandden (octave_sparse_params::get_bandden()), | 850 sp_bandden (octave_sparse_params::get_bandden()), |
953 bandden (0), upper_band (0), lower_band (0), | 851 bandden (0), upper_band (0), lower_band (0), |
954 dense (false), full (_full), nperm (0), perm (0) | 852 dense (false), full (_full), nperm (0), perm (0) |
955 { | 853 { |
956 if (t == MatrixType::Full || t == MatrixType::Diagonal || | 854 if (t == MatrixType::Unknown || t == MatrixType::Full |
957 t == MatrixType::Permuted_Diagonal || t == MatrixType::Upper || | 855 || t == MatrixType::Diagonal || t == MatrixType::Permuted_Diagonal |
958 t == MatrixType::Lower || t == MatrixType::Tridiagonal || | 856 || t == MatrixType::Upper || t == MatrixType::Lower |
959 t == MatrixType::Tridiagonal_Hermitian || t == MatrixType::Rectangular) | 857 || t == MatrixType::Tridiagonal || t == MatrixType::Tridiagonal_Hermitian |
858 || t == MatrixType::Rectangular) | |
960 typ = t; | 859 typ = t; |
961 else | 860 else |
962 (*current_liboctave_warning_handler) ("Invalid matrix type"); | 861 (*current_liboctave_warning_handler) ("Invalid matrix type"); |
963 } | 862 } |
964 | 863 |