Mercurial > hg > octave-lyh
annotate liboctave/dSparse.cc @ 10010:c5e9931c7ba7
Correctly produce postcript output for geometryimages when QHULL library is not present
author | Rik <rdrider0-list@yahoo.com> |
---|---|
date | Sun, 20 Dec 2009 17:02:57 -0800 |
parents | aabf7a8c2e57 |
children | 829e69ec3110 |
rev | line source |
---|---|
5164 | 1 /* |
2 | |
8920 | 3 Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009 David Bateman |
7016 | 4 Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004 Andy Adler |
5 | |
6 This file is part of Octave. | |
5164 | 7 |
8 Octave is free software; you can redistribute it and/or modify it | |
9 under the terms of the GNU General Public License as published by the | |
7016 | 10 Free Software Foundation; either version 3 of the License, or (at your |
11 option) any later version. | |
5164 | 12 |
13 Octave is distributed in the hope that it will be useful, but WITHOUT | |
14 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
15 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
16 for more details. | |
17 | |
18 You should have received a copy of the GNU General Public License | |
7016 | 19 along with Octave; see the file COPYING. If not, see |
20 <http://www.gnu.org/licenses/>. | |
5164 | 21 |
22 */ | |
23 | |
24 #ifdef HAVE_CONFIG_H | |
25 #include <config.h> | |
26 #endif | |
27 | |
28 #include <cfloat> | |
29 | |
30 #include <iostream> | |
31 #include <vector> | |
8964
f4f4d65faaa0
Implement sparse * diagonal and diagonal * sparse operations, double-prec only.
Jason Riedy <jason@acm.org>
parents:
8951
diff
changeset
|
32 #include <functional> |
5164 | 33 |
34 #include "quit.h" | |
35 #include "lo-ieee.h" | |
36 #include "lo-mappers.h" | |
37 #include "f77-fcn.h" | |
38 #include "dRowVector.h" | |
8377
25bc2d31e1bf
improve OCTAVE_LOCAL_BUFFER
Jaroslav Hajek <highegg@gmail.com>
parents:
8366
diff
changeset
|
39 #include "oct-locbuf.h" |
5164 | 40 |
8964
f4f4d65faaa0
Implement sparse * diagonal and diagonal * sparse operations, double-prec only.
Jason Riedy <jason@acm.org>
parents:
8951
diff
changeset
|
41 #include "dDiagMatrix.h" |
5164 | 42 #include "CSparse.h" |
43 #include "boolSparse.h" | |
44 #include "dSparse.h" | |
7602
7bfaa9611558
Rewrite sparse mappers in terms of a functor template function
David Bateman <dbateman@free.fr>
parents:
7520
diff
changeset
|
45 #include "functor.h" |
5164 | 46 #include "oct-spparms.h" |
47 #include "SparsedbleLU.h" | |
5785 | 48 #include "MatrixType.h" |
5451 | 49 #include "oct-sparse.h" |
5506 | 50 #include "sparse-util.h" |
51 #include "SparsedbleCHOL.h" | |
5610 | 52 #include "SparseQR.h" |
5164 | 53 |
8964
f4f4d65faaa0
Implement sparse * diagonal and diagonal * sparse operations, double-prec only.
Jason Riedy <jason@acm.org>
parents:
8951
diff
changeset
|
54 #include "Sparse-diag-op-defs.h" |
f4f4d65faaa0
Implement sparse * diagonal and diagonal * sparse operations, double-prec only.
Jason Riedy <jason@acm.org>
parents:
8951
diff
changeset
|
55 |
8968
91d53dc37f79
Add perm * sparse, perm \ sparse, sparse * perm, and sparse / perm operations.
Jason Riedy <jason@acm.org>
parents:
8967
diff
changeset
|
56 #include "Sparse-perm-op-defs.h" |
91d53dc37f79
Add perm * sparse, perm \ sparse, sparse * perm, and sparse / perm operations.
Jason Riedy <jason@acm.org>
parents:
8967
diff
changeset
|
57 |
5681 | 58 // Define whether to use a basic QR solver or one that uses a Dulmange |
59 // Mendelsohn factorization to seperate the problem into under-determined, | |
60 // well-determined and over-determined parts and solves them seperately | |
61 #ifndef USE_QRSOLVE | |
62 #include "sparse-dmsolve.cc" | |
63 #endif | |
64 | |
5164 | 65 // Fortran functions we call. |
66 extern "C" | |
67 { | |
68 F77_RET_T | |
6242 | 69 F77_FUNC (dgbtrf, DGBTRF) (const octave_idx_type&, const octave_idx_type&, |
70 const octave_idx_type&, const octave_idx_type&, | |
71 double*, const octave_idx_type&, | |
72 octave_idx_type*, octave_idx_type&); | |
5164 | 73 |
74 F77_RET_T | |
5275 | 75 F77_FUNC (dgbtrs, DGBTRS) (F77_CONST_CHAR_ARG_DECL, const octave_idx_type&, |
76 const octave_idx_type&, const octave_idx_type&, const octave_idx_type&, | |
77 const double*, const octave_idx_type&, | |
78 const octave_idx_type*, double*, const octave_idx_type&, octave_idx_type& | |
5164 | 79 F77_CHAR_ARG_LEN_DECL); |
80 | |
81 F77_RET_T | |
5275 | 82 F77_FUNC (dgbcon, DGBCON) (F77_CONST_CHAR_ARG_DECL, const octave_idx_type&, |
83 const octave_idx_type&, const octave_idx_type&, double*, | |
84 const octave_idx_type&, const octave_idx_type*, const double&, | |
85 double&, double*, octave_idx_type*, octave_idx_type& | |
5164 | 86 F77_CHAR_ARG_LEN_DECL); |
87 | |
88 F77_RET_T | |
5275 | 89 F77_FUNC (dpbtrf, DPBTRF) (F77_CONST_CHAR_ARG_DECL, const octave_idx_type&, |
90 const octave_idx_type&, double*, const octave_idx_type&, octave_idx_type& | |
5164 | 91 F77_CHAR_ARG_LEN_DECL); |
92 | |
93 F77_RET_T | |
5275 | 94 F77_FUNC (dpbtrs, DPBTRS) (F77_CONST_CHAR_ARG_DECL, const octave_idx_type&, |
95 const octave_idx_type&, const octave_idx_type&, double*, const octave_idx_type&, | |
96 double*, const octave_idx_type&, octave_idx_type& | |
5164 | 97 F77_CHAR_ARG_LEN_DECL); |
98 | |
99 F77_RET_T | |
5275 | 100 F77_FUNC (dpbcon, DPBCON) (F77_CONST_CHAR_ARG_DECL, const octave_idx_type&, |
101 const octave_idx_type&, double*, const octave_idx_type&, | |
102 const double&, double&, double*, octave_idx_type*, octave_idx_type& | |
5164 | 103 F77_CHAR_ARG_LEN_DECL); |
104 F77_RET_T | |
5275 | 105 F77_FUNC (dptsv, DPTSV) (const octave_idx_type&, const octave_idx_type&, double*, double*, |
106 double*, const octave_idx_type&, octave_idx_type&); | |
5164 | 107 |
108 F77_RET_T | |
5275 | 109 F77_FUNC (dgtsv, DGTSV) (const octave_idx_type&, const octave_idx_type&, double*, double*, |
110 double*, double*, const octave_idx_type&, octave_idx_type&); | |
5164 | 111 |
112 F77_RET_T | |
5275 | 113 F77_FUNC (dgttrf, DGTTRF) (const octave_idx_type&, double*, double*, double*, double*, |
114 octave_idx_type*, octave_idx_type&); | |
5164 | 115 |
116 F77_RET_T | |
5275 | 117 F77_FUNC (dgttrs, DGTTRS) (F77_CONST_CHAR_ARG_DECL, const octave_idx_type&, |
118 const octave_idx_type&, const double*, const double*, | |
119 const double*, const double*, const octave_idx_type*, | |
120 double *, const octave_idx_type&, octave_idx_type& | |
5164 | 121 F77_CHAR_ARG_LEN_DECL); |
122 | |
123 F77_RET_T | |
5322 | 124 F77_FUNC (zptsv, ZPTSV) (const octave_idx_type&, const octave_idx_type&, double*, Complex*, |
5275 | 125 Complex*, const octave_idx_type&, octave_idx_type&); |
5164 | 126 |
127 F77_RET_T | |
5275 | 128 F77_FUNC (zgtsv, ZGTSV) (const octave_idx_type&, const octave_idx_type&, Complex*, Complex*, |
129 Complex*, Complex*, const octave_idx_type&, octave_idx_type&); | |
5164 | 130 |
131 } | |
132 | |
133 SparseMatrix::SparseMatrix (const SparseBoolMatrix &a) | |
5681 | 134 : MSparse<double> (a.rows (), a.cols (), a.nnz ()) |
5164 | 135 { |
5275 | 136 octave_idx_type nc = cols (); |
5681 | 137 octave_idx_type nz = a.nnz (); |
5275 | 138 |
139 for (octave_idx_type i = 0; i < nc + 1; i++) | |
5164 | 140 cidx (i) = a.cidx (i); |
141 | |
5275 | 142 for (octave_idx_type i = 0; i < nz; i++) |
5164 | 143 { |
144 data (i) = a.data (i); | |
145 ridx (i) = a.ridx (i); | |
146 } | |
147 } | |
148 | |
8366
8b1a2555c4e2
implement diagonal matrix objects
Jaroslav Hajek <highegg@gmail.com>
parents:
8335
diff
changeset
|
149 SparseMatrix::SparseMatrix (const DiagMatrix& a) |
8910
6e9f26506804
optimize diag -> sparse and perm -> sparse conversions
Jaroslav Hajek <highegg@gmail.com>
parents:
8377
diff
changeset
|
150 : MSparse<double> (a.rows (), a.cols (), a.length ()) |
6e9f26506804
optimize diag -> sparse and perm -> sparse conversions
Jaroslav Hajek <highegg@gmail.com>
parents:
8377
diff
changeset
|
151 { |
6e9f26506804
optimize diag -> sparse and perm -> sparse conversions
Jaroslav Hajek <highegg@gmail.com>
parents:
8377
diff
changeset
|
152 octave_idx_type j = 0, l = a.length (); |
6e9f26506804
optimize diag -> sparse and perm -> sparse conversions
Jaroslav Hajek <highegg@gmail.com>
parents:
8377
diff
changeset
|
153 for (octave_idx_type i = 0; i < l; i++) |
8366
8b1a2555c4e2
implement diagonal matrix objects
Jaroslav Hajek <highegg@gmail.com>
parents:
8335
diff
changeset
|
154 { |
8910
6e9f26506804
optimize diag -> sparse and perm -> sparse conversions
Jaroslav Hajek <highegg@gmail.com>
parents:
8377
diff
changeset
|
155 cidx (i) = j; |
8366
8b1a2555c4e2
implement diagonal matrix objects
Jaroslav Hajek <highegg@gmail.com>
parents:
8335
diff
changeset
|
156 if (a(i, i) != 0.0) |
8b1a2555c4e2
implement diagonal matrix objects
Jaroslav Hajek <highegg@gmail.com>
parents:
8335
diff
changeset
|
157 { |
8b1a2555c4e2
implement diagonal matrix objects
Jaroslav Hajek <highegg@gmail.com>
parents:
8335
diff
changeset
|
158 data (j) = a(i, i); |
8b1a2555c4e2
implement diagonal matrix objects
Jaroslav Hajek <highegg@gmail.com>
parents:
8335
diff
changeset
|
159 ridx (j) = i; |
8b1a2555c4e2
implement diagonal matrix objects
Jaroslav Hajek <highegg@gmail.com>
parents:
8335
diff
changeset
|
160 j++; |
8b1a2555c4e2
implement diagonal matrix objects
Jaroslav Hajek <highegg@gmail.com>
parents:
8335
diff
changeset
|
161 } |
8b1a2555c4e2
implement diagonal matrix objects
Jaroslav Hajek <highegg@gmail.com>
parents:
8335
diff
changeset
|
162 } |
8910
6e9f26506804
optimize diag -> sparse and perm -> sparse conversions
Jaroslav Hajek <highegg@gmail.com>
parents:
8377
diff
changeset
|
163 for (octave_idx_type i = l; i <= a.cols (); i++) |
6e9f26506804
optimize diag -> sparse and perm -> sparse conversions
Jaroslav Hajek <highegg@gmail.com>
parents:
8377
diff
changeset
|
164 cidx(i) = j; |
6e9f26506804
optimize diag -> sparse and perm -> sparse conversions
Jaroslav Hajek <highegg@gmail.com>
parents:
8377
diff
changeset
|
165 } |
6e9f26506804
optimize diag -> sparse and perm -> sparse conversions
Jaroslav Hajek <highegg@gmail.com>
parents:
8377
diff
changeset
|
166 |
6e9f26506804
optimize diag -> sparse and perm -> sparse conversions
Jaroslav Hajek <highegg@gmail.com>
parents:
8377
diff
changeset
|
167 SparseMatrix::SparseMatrix (const PermMatrix& a) |
6e9f26506804
optimize diag -> sparse and perm -> sparse conversions
Jaroslav Hajek <highegg@gmail.com>
parents:
8377
diff
changeset
|
168 : MSparse<double> (a.rows (), a.cols (), a.rows ()) |
6e9f26506804
optimize diag -> sparse and perm -> sparse conversions
Jaroslav Hajek <highegg@gmail.com>
parents:
8377
diff
changeset
|
169 { |
6e9f26506804
optimize diag -> sparse and perm -> sparse conversions
Jaroslav Hajek <highegg@gmail.com>
parents:
8377
diff
changeset
|
170 octave_idx_type n = a.rows (); |
6e9f26506804
optimize diag -> sparse and perm -> sparse conversions
Jaroslav Hajek <highegg@gmail.com>
parents:
8377
diff
changeset
|
171 for (octave_idx_type i = 0; i <= n; i++) |
6e9f26506804
optimize diag -> sparse and perm -> sparse conversions
Jaroslav Hajek <highegg@gmail.com>
parents:
8377
diff
changeset
|
172 cidx (i) = i; |
6e9f26506804
optimize diag -> sparse and perm -> sparse conversions
Jaroslav Hajek <highegg@gmail.com>
parents:
8377
diff
changeset
|
173 const Array<octave_idx_type> pv = a.pvec (); |
6e9f26506804
optimize diag -> sparse and perm -> sparse conversions
Jaroslav Hajek <highegg@gmail.com>
parents:
8377
diff
changeset
|
174 |
6e9f26506804
optimize diag -> sparse and perm -> sparse conversions
Jaroslav Hajek <highegg@gmail.com>
parents:
8377
diff
changeset
|
175 if (a.is_row_perm ()) |
6e9f26506804
optimize diag -> sparse and perm -> sparse conversions
Jaroslav Hajek <highegg@gmail.com>
parents:
8377
diff
changeset
|
176 { |
6e9f26506804
optimize diag -> sparse and perm -> sparse conversions
Jaroslav Hajek <highegg@gmail.com>
parents:
8377
diff
changeset
|
177 for (octave_idx_type i = 0; i < n; i++) |
8951
5bce1357edd6
Fix conversion from PermMatrix to SparseMatrix.
Jason Riedy <jason@acm.org>
parents:
8920
diff
changeset
|
178 ridx (pv (i)) = i; |
8910
6e9f26506804
optimize diag -> sparse and perm -> sparse conversions
Jaroslav Hajek <highegg@gmail.com>
parents:
8377
diff
changeset
|
179 } |
6e9f26506804
optimize diag -> sparse and perm -> sparse conversions
Jaroslav Hajek <highegg@gmail.com>
parents:
8377
diff
changeset
|
180 else |
6e9f26506804
optimize diag -> sparse and perm -> sparse conversions
Jaroslav Hajek <highegg@gmail.com>
parents:
8377
diff
changeset
|
181 { |
6e9f26506804
optimize diag -> sparse and perm -> sparse conversions
Jaroslav Hajek <highegg@gmail.com>
parents:
8377
diff
changeset
|
182 for (octave_idx_type i = 0; i < n; i++) |
8951
5bce1357edd6
Fix conversion from PermMatrix to SparseMatrix.
Jason Riedy <jason@acm.org>
parents:
8920
diff
changeset
|
183 ridx (i) = pv (i); |
8910
6e9f26506804
optimize diag -> sparse and perm -> sparse conversions
Jaroslav Hajek <highegg@gmail.com>
parents:
8377
diff
changeset
|
184 } |
8951
5bce1357edd6
Fix conversion from PermMatrix to SparseMatrix.
Jason Riedy <jason@acm.org>
parents:
8920
diff
changeset
|
185 |
5bce1357edd6
Fix conversion from PermMatrix to SparseMatrix.
Jason Riedy <jason@acm.org>
parents:
8920
diff
changeset
|
186 for (octave_idx_type i = 0; i < n; i++) |
5bce1357edd6
Fix conversion from PermMatrix to SparseMatrix.
Jason Riedy <jason@acm.org>
parents:
8920
diff
changeset
|
187 data (i) = 1.0; |
8366
8b1a2555c4e2
implement diagonal matrix objects
Jaroslav Hajek <highegg@gmail.com>
parents:
8335
diff
changeset
|
188 } |
8b1a2555c4e2
implement diagonal matrix objects
Jaroslav Hajek <highegg@gmail.com>
parents:
8335
diff
changeset
|
189 |
5164 | 190 bool |
191 SparseMatrix::operator == (const SparseMatrix& a) const | |
192 { | |
5275 | 193 octave_idx_type nr = rows (); |
194 octave_idx_type nc = cols (); | |
5681 | 195 octave_idx_type nz = nnz (); |
5275 | 196 octave_idx_type nr_a = a.rows (); |
197 octave_idx_type nc_a = a.cols (); | |
5681 | 198 octave_idx_type nz_a = a.nnz (); |
5164 | 199 |
200 if (nr != nr_a || nc != nc_a || nz != nz_a) | |
201 return false; | |
202 | |
5275 | 203 for (octave_idx_type i = 0; i < nc + 1; i++) |
5164 | 204 if (cidx(i) != a.cidx(i)) |
205 return false; | |
206 | |
5275 | 207 for (octave_idx_type i = 0; i < nz; i++) |
5164 | 208 if (data(i) != a.data(i) || ridx(i) != a.ridx(i)) |
209 return false; | |
210 | |
211 return true; | |
212 } | |
213 | |
214 bool | |
215 SparseMatrix::operator != (const SparseMatrix& a) const | |
216 { | |
217 return !(*this == a); | |
218 } | |
219 | |
220 bool | |
221 SparseMatrix::is_symmetric (void) const | |
222 { | |
6207 | 223 octave_idx_type nr = rows (); |
224 octave_idx_type nc = cols (); | |
225 | |
226 if (nr == nc && nr > 0) | |
5164 | 227 { |
6207 | 228 for (octave_idx_type j = 0; j < nc; j++) |
229 { | |
230 for (octave_idx_type i = cidx(j); i < cidx(j+1); i++) | |
231 { | |
232 octave_idx_type ri = ridx(i); | |
233 | |
234 if (ri != j) | |
235 { | |
236 bool found = false; | |
237 | |
238 for (octave_idx_type k = cidx(ri); k < cidx(ri+1); k++) | |
239 { | |
240 if (ridx(k) == j) | |
241 { | |
242 if (data(i) == data(k)) | |
243 found = true; | |
244 break; | |
245 } | |
246 } | |
247 | |
248 if (! found) | |
249 return false; | |
250 } | |
251 } | |
252 } | |
5164 | 253 |
254 return true; | |
255 } | |
256 | |
257 return false; | |
258 } | |
259 | |
260 SparseMatrix& | |
5275 | 261 SparseMatrix::insert (const SparseMatrix& a, octave_idx_type r, octave_idx_type c) |
5164 | 262 { |
263 MSparse<double>::insert (a, r, c); | |
264 return *this; | |
265 } | |
266 | |
6823 | 267 SparseMatrix& |
268 SparseMatrix::insert (const SparseMatrix& a, const Array<octave_idx_type>& indx) | |
269 { | |
270 MSparse<double>::insert (a, indx); | |
271 return *this; | |
272 } | |
273 | |
5164 | 274 SparseMatrix |
275 SparseMatrix::max (int dim) const | |
276 { | |
9790
a5035bc7fbfb
rewrite dispatch part & slightly improve min,max,cummin,cummax
Jaroslav Hajek <highegg@gmail.com>
parents:
9469
diff
changeset
|
277 Array<octave_idx_type> dummy_idx; |
5164 | 278 return max (dummy_idx, dim); |
279 } | |
280 | |
281 SparseMatrix | |
9790
a5035bc7fbfb
rewrite dispatch part & slightly improve min,max,cummin,cummax
Jaroslav Hajek <highegg@gmail.com>
parents:
9469
diff
changeset
|
282 SparseMatrix::max (Array<octave_idx_type>& idx_arg, int dim) const |
5164 | 283 { |
284 SparseMatrix result; | |
285 dim_vector dv = dims (); | |
286 | |
9790
a5035bc7fbfb
rewrite dispatch part & slightly improve min,max,cummin,cummax
Jaroslav Hajek <highegg@gmail.com>
parents:
9469
diff
changeset
|
287 if (dv.numel () == 0 || dim >= dv.length ()) |
5164 | 288 return result; |
289 | |
9790
a5035bc7fbfb
rewrite dispatch part & slightly improve min,max,cummin,cummax
Jaroslav Hajek <highegg@gmail.com>
parents:
9469
diff
changeset
|
290 if (dim < 0) |
a5035bc7fbfb
rewrite dispatch part & slightly improve min,max,cummin,cummax
Jaroslav Hajek <highegg@gmail.com>
parents:
9469
diff
changeset
|
291 dim = dv.first_non_singleton (); |
a5035bc7fbfb
rewrite dispatch part & slightly improve min,max,cummin,cummax
Jaroslav Hajek <highegg@gmail.com>
parents:
9469
diff
changeset
|
292 |
5275 | 293 octave_idx_type nr = dv(0); |
294 octave_idx_type nc = dv(1); | |
5164 | 295 |
296 if (dim == 0) | |
297 { | |
9790
a5035bc7fbfb
rewrite dispatch part & slightly improve min,max,cummin,cummax
Jaroslav Hajek <highegg@gmail.com>
parents:
9469
diff
changeset
|
298 idx_arg.clear (1, nc); |
5275 | 299 octave_idx_type nel = 0; |
300 for (octave_idx_type j = 0; j < nc; j++) | |
5164 | 301 { |
302 double tmp_max = octave_NaN; | |
5275 | 303 octave_idx_type idx_j = 0; |
304 for (octave_idx_type i = cidx(j); i < cidx(j+1); i++) | |
5164 | 305 { |
306 if (ridx(i) != idx_j) | |
307 break; | |
308 else | |
309 idx_j++; | |
310 } | |
311 | |
312 if (idx_j != nr) | |
313 tmp_max = 0.; | |
314 | |
5275 | 315 for (octave_idx_type i = cidx(j); i < cidx(j+1); i++) |
5164 | 316 { |
317 double tmp = data (i); | |
318 | |
5389 | 319 if (xisnan (tmp)) |
5164 | 320 continue; |
5389 | 321 else if (xisnan (tmp_max) || tmp > tmp_max) |
5164 | 322 { |
323 idx_j = ridx (i); | |
324 tmp_max = tmp; | |
325 } | |
326 | |
327 } | |
328 | |
5389 | 329 idx_arg.elem (j) = xisnan (tmp_max) ? 0 : idx_j; |
5164 | 330 if (tmp_max != 0.) |
331 nel++; | |
332 } | |
333 | |
334 result = SparseMatrix (1, nc, nel); | |
335 | |
5275 | 336 octave_idx_type ii = 0; |
5164 | 337 result.xcidx (0) = 0; |
5275 | 338 for (octave_idx_type j = 0; j < nc; j++) |
5164 | 339 { |
340 double tmp = elem (idx_arg(j), j); | |
341 if (tmp != 0.) | |
342 { | |
343 result.xdata (ii) = tmp; | |
344 result.xridx (ii++) = 0; | |
345 } | |
346 result.xcidx (j+1) = ii; | |
347 | |
348 } | |
349 } | |
350 else | |
351 { | |
9790
a5035bc7fbfb
rewrite dispatch part & slightly improve min,max,cummin,cummax
Jaroslav Hajek <highegg@gmail.com>
parents:
9469
diff
changeset
|
352 idx_arg.resize_fill (nr, 1, 0); |
5164 | 353 |
5275 | 354 for (octave_idx_type i = cidx(0); i < cidx(1); i++) |
5164 | 355 idx_arg.elem(ridx(i)) = -1; |
356 | |
5275 | 357 for (octave_idx_type j = 0; j < nc; j++) |
358 for (octave_idx_type i = 0; i < nr; i++) | |
5164 | 359 { |
360 if (idx_arg.elem(i) != -1) | |
361 continue; | |
362 bool found = false; | |
5275 | 363 for (octave_idx_type k = cidx(j); k < cidx(j+1); k++) |
5164 | 364 if (ridx(k) == i) |
365 { | |
366 found = true; | |
367 break; | |
368 } | |
369 | |
370 if (!found) | |
371 idx_arg.elem(i) = j; | |
372 | |
373 } | |
374 | |
5275 | 375 for (octave_idx_type j = 0; j < nc; j++) |
5164 | 376 { |
5275 | 377 for (octave_idx_type i = cidx(j); i < cidx(j+1); i++) |
5164 | 378 { |
5275 | 379 octave_idx_type ir = ridx (i); |
380 octave_idx_type ix = idx_arg.elem (ir); | |
5164 | 381 double tmp = data (i); |
382 | |
5389 | 383 if (xisnan (tmp)) |
5164 | 384 continue; |
385 else if (ix == -1 || tmp > elem (ir, ix)) | |
386 idx_arg.elem (ir) = j; | |
387 } | |
388 } | |
389 | |
5275 | 390 octave_idx_type nel = 0; |
391 for (octave_idx_type j = 0; j < nr; j++) | |
5164 | 392 if (idx_arg.elem(j) == -1 || elem (j, idx_arg.elem (j)) != 0.) |
393 nel++; | |
394 | |
395 result = SparseMatrix (nr, 1, nel); | |
396 | |
5275 | 397 octave_idx_type ii = 0; |
5164 | 398 result.xcidx (0) = 0; |
399 result.xcidx (1) = nel; | |
5275 | 400 for (octave_idx_type j = 0; j < nr; j++) |
5164 | 401 { |
402 if (idx_arg(j) == -1) | |
403 { | |
404 idx_arg(j) = 0; | |
405 result.xdata (ii) = octave_NaN; | |
406 result.xridx (ii++) = j; | |
407 } | |
408 else | |
409 { | |
410 double tmp = elem (j, idx_arg(j)); | |
411 if (tmp != 0.) | |
412 { | |
413 result.xdata (ii) = tmp; | |
414 result.xridx (ii++) = j; | |
415 } | |
416 } | |
417 } | |
418 } | |
419 | |
420 return result; | |
421 } | |
422 | |
423 SparseMatrix | |
424 SparseMatrix::min (int dim) const | |
425 { | |
9790
a5035bc7fbfb
rewrite dispatch part & slightly improve min,max,cummin,cummax
Jaroslav Hajek <highegg@gmail.com>
parents:
9469
diff
changeset
|
426 Array<octave_idx_type> dummy_idx; |
5164 | 427 return min (dummy_idx, dim); |
428 } | |
429 | |
430 SparseMatrix | |
9790
a5035bc7fbfb
rewrite dispatch part & slightly improve min,max,cummin,cummax
Jaroslav Hajek <highegg@gmail.com>
parents:
9469
diff
changeset
|
431 SparseMatrix::min (Array<octave_idx_type>& idx_arg, int dim) const |
5164 | 432 { |
433 SparseMatrix result; | |
434 dim_vector dv = dims (); | |
435 | |
9790
a5035bc7fbfb
rewrite dispatch part & slightly improve min,max,cummin,cummax
Jaroslav Hajek <highegg@gmail.com>
parents:
9469
diff
changeset
|
436 if (dv.numel () == 0 || dim >= dv.length ()) |
5164 | 437 return result; |
438 | |
9790
a5035bc7fbfb
rewrite dispatch part & slightly improve min,max,cummin,cummax
Jaroslav Hajek <highegg@gmail.com>
parents:
9469
diff
changeset
|
439 if (dim < 0) |
a5035bc7fbfb
rewrite dispatch part & slightly improve min,max,cummin,cummax
Jaroslav Hajek <highegg@gmail.com>
parents:
9469
diff
changeset
|
440 dim = dv.first_non_singleton (); |
a5035bc7fbfb
rewrite dispatch part & slightly improve min,max,cummin,cummax
Jaroslav Hajek <highegg@gmail.com>
parents:
9469
diff
changeset
|
441 |
5275 | 442 octave_idx_type nr = dv(0); |
443 octave_idx_type nc = dv(1); | |
5164 | 444 |
445 if (dim == 0) | |
446 { | |
9790
a5035bc7fbfb
rewrite dispatch part & slightly improve min,max,cummin,cummax
Jaroslav Hajek <highegg@gmail.com>
parents:
9469
diff
changeset
|
447 idx_arg.clear (1, nc); |
5275 | 448 octave_idx_type nel = 0; |
449 for (octave_idx_type j = 0; j < nc; j++) | |
5164 | 450 { |
451 double tmp_min = octave_NaN; | |
5275 | 452 octave_idx_type idx_j = 0; |
453 for (octave_idx_type i = cidx(j); i < cidx(j+1); i++) | |
5164 | 454 { |
455 if (ridx(i) != idx_j) | |
456 break; | |
457 else | |
458 idx_j++; | |
459 } | |
460 | |
461 if (idx_j != nr) | |
462 tmp_min = 0.; | |
463 | |
5275 | 464 for (octave_idx_type i = cidx(j); i < cidx(j+1); i++) |
5164 | 465 { |
466 double tmp = data (i); | |
467 | |
5389 | 468 if (xisnan (tmp)) |
5164 | 469 continue; |
5389 | 470 else if (xisnan (tmp_min) || tmp < tmp_min) |
5164 | 471 { |
472 idx_j = ridx (i); | |
473 tmp_min = tmp; | |
474 } | |
475 | |
476 } | |
477 | |
5389 | 478 idx_arg.elem (j) = xisnan (tmp_min) ? 0 : idx_j; |
5164 | 479 if (tmp_min != 0.) |
480 nel++; | |
481 } | |
482 | |
483 result = SparseMatrix (1, nc, nel); | |
484 | |
5275 | 485 octave_idx_type ii = 0; |
5164 | 486 result.xcidx (0) = 0; |
5275 | 487 for (octave_idx_type j = 0; j < nc; j++) |
5164 | 488 { |
489 double tmp = elem (idx_arg(j), j); | |
490 if (tmp != 0.) | |
491 { | |
492 result.xdata (ii) = tmp; | |
493 result.xridx (ii++) = 0; | |
494 } | |
495 result.xcidx (j+1) = ii; | |
496 | |
497 } | |
498 } | |
499 else | |
500 { | |
9790
a5035bc7fbfb
rewrite dispatch part & slightly improve min,max,cummin,cummax
Jaroslav Hajek <highegg@gmail.com>
parents:
9469
diff
changeset
|
501 idx_arg.resize_fill (nr, 1, 0); |
5164 | 502 |
5275 | 503 for (octave_idx_type i = cidx(0); i < cidx(1); i++) |
5164 | 504 idx_arg.elem(ridx(i)) = -1; |
505 | |
5275 | 506 for (octave_idx_type j = 0; j < nc; j++) |
507 for (octave_idx_type i = 0; i < nr; i++) | |
5164 | 508 { |
509 if (idx_arg.elem(i) != -1) | |
510 continue; | |
511 bool found = false; | |
5275 | 512 for (octave_idx_type k = cidx(j); k < cidx(j+1); k++) |
5164 | 513 if (ridx(k) == i) |
514 { | |
515 found = true; | |
516 break; | |
517 } | |
518 | |
519 if (!found) | |
520 idx_arg.elem(i) = j; | |
521 | |
522 } | |
523 | |
5275 | 524 for (octave_idx_type j = 0; j < nc; j++) |
5164 | 525 { |
5275 | 526 for (octave_idx_type i = cidx(j); i < cidx(j+1); i++) |
5164 | 527 { |
5275 | 528 octave_idx_type ir = ridx (i); |
529 octave_idx_type ix = idx_arg.elem (ir); | |
5164 | 530 double tmp = data (i); |
531 | |
5389 | 532 if (xisnan (tmp)) |
5164 | 533 continue; |
534 else if (ix == -1 || tmp < elem (ir, ix)) | |
535 idx_arg.elem (ir) = j; | |
536 } | |
537 } | |
538 | |
5275 | 539 octave_idx_type nel = 0; |
540 for (octave_idx_type j = 0; j < nr; j++) | |
5164 | 541 if (idx_arg.elem(j) == -1 || elem (j, idx_arg.elem (j)) != 0.) |
542 nel++; | |
543 | |
544 result = SparseMatrix (nr, 1, nel); | |
545 | |
5275 | 546 octave_idx_type ii = 0; |
5164 | 547 result.xcidx (0) = 0; |
548 result.xcidx (1) = nel; | |
5275 | 549 for (octave_idx_type j = 0; j < nr; j++) |
5164 | 550 { |
551 if (idx_arg(j) == -1) | |
552 { | |
553 idx_arg(j) = 0; | |
554 result.xdata (ii) = octave_NaN; | |
555 result.xridx (ii++) = j; | |
556 } | |
557 else | |
558 { | |
559 double tmp = elem (j, idx_arg(j)); | |
560 if (tmp != 0.) | |
561 { | |
562 result.xdata (ii) = tmp; | |
563 result.xridx (ii++) = j; | |
564 } | |
565 } | |
566 } | |
567 } | |
568 | |
569 return result; | |
570 } | |
571 | |
8303
b11c31849b44
improve norm computation capabilities
Jaroslav Hajek <highegg@gmail.com>
parents:
7922
diff
changeset
|
572 RowVector |
b11c31849b44
improve norm computation capabilities
Jaroslav Hajek <highegg@gmail.com>
parents:
7922
diff
changeset
|
573 SparseMatrix::row (octave_idx_type i) const |
b11c31849b44
improve norm computation capabilities
Jaroslav Hajek <highegg@gmail.com>
parents:
7922
diff
changeset
|
574 { |
b11c31849b44
improve norm computation capabilities
Jaroslav Hajek <highegg@gmail.com>
parents:
7922
diff
changeset
|
575 octave_idx_type nc = columns (); |
b11c31849b44
improve norm computation capabilities
Jaroslav Hajek <highegg@gmail.com>
parents:
7922
diff
changeset
|
576 RowVector retval (nc, 0); |
b11c31849b44
improve norm computation capabilities
Jaroslav Hajek <highegg@gmail.com>
parents:
7922
diff
changeset
|
577 |
b11c31849b44
improve norm computation capabilities
Jaroslav Hajek <highegg@gmail.com>
parents:
7922
diff
changeset
|
578 for (octave_idx_type j = 0; j < nc; j++) |
b11c31849b44
improve norm computation capabilities
Jaroslav Hajek <highegg@gmail.com>
parents:
7922
diff
changeset
|
579 for (octave_idx_type k = cidx (j); k < cidx (j+1); k++) |
b11c31849b44
improve norm computation capabilities
Jaroslav Hajek <highegg@gmail.com>
parents:
7922
diff
changeset
|
580 { |
b11c31849b44
improve norm computation capabilities
Jaroslav Hajek <highegg@gmail.com>
parents:
7922
diff
changeset
|
581 if (ridx (k) == i) |
b11c31849b44
improve norm computation capabilities
Jaroslav Hajek <highegg@gmail.com>
parents:
7922
diff
changeset
|
582 { |
b11c31849b44
improve norm computation capabilities
Jaroslav Hajek <highegg@gmail.com>
parents:
7922
diff
changeset
|
583 retval(j) = data (k); |
b11c31849b44
improve norm computation capabilities
Jaroslav Hajek <highegg@gmail.com>
parents:
7922
diff
changeset
|
584 break; |
b11c31849b44
improve norm computation capabilities
Jaroslav Hajek <highegg@gmail.com>
parents:
7922
diff
changeset
|
585 } |
b11c31849b44
improve norm computation capabilities
Jaroslav Hajek <highegg@gmail.com>
parents:
7922
diff
changeset
|
586 } |
b11c31849b44
improve norm computation capabilities
Jaroslav Hajek <highegg@gmail.com>
parents:
7922
diff
changeset
|
587 |
b11c31849b44
improve norm computation capabilities
Jaroslav Hajek <highegg@gmail.com>
parents:
7922
diff
changeset
|
588 return retval; |
b11c31849b44
improve norm computation capabilities
Jaroslav Hajek <highegg@gmail.com>
parents:
7922
diff
changeset
|
589 } |
b11c31849b44
improve norm computation capabilities
Jaroslav Hajek <highegg@gmail.com>
parents:
7922
diff
changeset
|
590 |
b11c31849b44
improve norm computation capabilities
Jaroslav Hajek <highegg@gmail.com>
parents:
7922
diff
changeset
|
591 ColumnVector |
b11c31849b44
improve norm computation capabilities
Jaroslav Hajek <highegg@gmail.com>
parents:
7922
diff
changeset
|
592 SparseMatrix::column (octave_idx_type i) const |
b11c31849b44
improve norm computation capabilities
Jaroslav Hajek <highegg@gmail.com>
parents:
7922
diff
changeset
|
593 { |
b11c31849b44
improve norm computation capabilities
Jaroslav Hajek <highegg@gmail.com>
parents:
7922
diff
changeset
|
594 octave_idx_type nr = rows (); |
b11c31849b44
improve norm computation capabilities
Jaroslav Hajek <highegg@gmail.com>
parents:
7922
diff
changeset
|
595 ColumnVector retval (nr); |
b11c31849b44
improve norm computation capabilities
Jaroslav Hajek <highegg@gmail.com>
parents:
7922
diff
changeset
|
596 |
b11c31849b44
improve norm computation capabilities
Jaroslav Hajek <highegg@gmail.com>
parents:
7922
diff
changeset
|
597 for (octave_idx_type k = cidx (i); k < cidx (i+1); k++) |
b11c31849b44
improve norm computation capabilities
Jaroslav Hajek <highegg@gmail.com>
parents:
7922
diff
changeset
|
598 retval(ridx (k)) = data (k); |
b11c31849b44
improve norm computation capabilities
Jaroslav Hajek <highegg@gmail.com>
parents:
7922
diff
changeset
|
599 |
b11c31849b44
improve norm computation capabilities
Jaroslav Hajek <highegg@gmail.com>
parents:
7922
diff
changeset
|
600 return retval; |
b11c31849b44
improve norm computation capabilities
Jaroslav Hajek <highegg@gmail.com>
parents:
7922
diff
changeset
|
601 } |
b11c31849b44
improve norm computation capabilities
Jaroslav Hajek <highegg@gmail.com>
parents:
7922
diff
changeset
|
602 |
5164 | 603 SparseMatrix |
5275 | 604 SparseMatrix::concat (const SparseMatrix& rb, const Array<octave_idx_type>& ra_idx) |
5164 | 605 { |
606 // Don't use numel to avoid all possiblity of an overflow | |
607 if (rb.rows () > 0 && rb.cols () > 0) | |
608 insert (rb, ra_idx(0), ra_idx(1)); | |
609 return *this; | |
610 } | |
611 | |
612 SparseComplexMatrix | |
5275 | 613 SparseMatrix::concat (const SparseComplexMatrix& rb, const Array<octave_idx_type>& ra_idx) |
5164 | 614 { |
615 SparseComplexMatrix retval (*this); | |
616 if (rb.rows () > 0 && rb.cols () > 0) | |
617 retval.insert (rb, ra_idx(0), ra_idx(1)); | |
618 return retval; | |
619 } | |
620 | |
621 SparseMatrix | |
622 real (const SparseComplexMatrix& a) | |
623 { | |
5275 | 624 octave_idx_type nr = a.rows (); |
625 octave_idx_type nc = a.cols (); | |
5681 | 626 octave_idx_type nz = a.nnz (); |
5164 | 627 SparseMatrix r (nr, nc, nz); |
628 | |
5275 | 629 for (octave_idx_type i = 0; i < nc +1; i++) |
5164 | 630 r.cidx(i) = a.cidx(i); |
631 | |
5275 | 632 for (octave_idx_type i = 0; i < nz; i++) |
5164 | 633 { |
5261 | 634 r.data(i) = std::real (a.data(i)); |
5164 | 635 r.ridx(i) = a.ridx(i); |
636 } | |
637 | |
638 return r; | |
639 } | |
640 | |
641 SparseMatrix | |
642 imag (const SparseComplexMatrix& a) | |
643 { | |
5275 | 644 octave_idx_type nr = a.rows (); |
645 octave_idx_type nc = a.cols (); | |
5681 | 646 octave_idx_type nz = a.nnz (); |
5164 | 647 SparseMatrix r (nr, nc, nz); |
648 | |
5275 | 649 for (octave_idx_type i = 0; i < nc +1; i++) |
5164 | 650 r.cidx(i) = a.cidx(i); |
651 | |
5275 | 652 for (octave_idx_type i = 0; i < nz; i++) |
5164 | 653 { |
5261 | 654 r.data(i) = std::imag (a.data(i)); |
5164 | 655 r.ridx(i) = a.ridx(i); |
656 } | |
657 | |
658 return r; | |
659 } | |
660 | |
661 SparseMatrix | |
662 atan2 (const double& x, const SparseMatrix& y) | |
663 { | |
5275 | 664 octave_idx_type nr = y.rows (); |
665 octave_idx_type nc = y.cols (); | |
5164 | 666 |
667 if (x == 0.) | |
668 return SparseMatrix (nr, nc); | |
669 else | |
670 { | |
671 // Its going to be basically full, so this is probably the | |
672 // best way to handle it. | |
673 Matrix tmp (nr, nc, atan2 (x, 0.)); | |
674 | |
5275 | 675 for (octave_idx_type j = 0; j < nc; j++) |
676 for (octave_idx_type i = y.cidx (j); i < y.cidx (j+1); i++) | |
5164 | 677 tmp.elem (y.ridx(i), j) = atan2 (x, y.data(i)); |
678 | |
679 return SparseMatrix (tmp); | |
680 } | |
681 } | |
682 | |
683 SparseMatrix | |
684 atan2 (const SparseMatrix& x, const double& y) | |
685 { | |
5275 | 686 octave_idx_type nr = x.rows (); |
687 octave_idx_type nc = x.cols (); | |
5681 | 688 octave_idx_type nz = x.nnz (); |
5164 | 689 |
690 SparseMatrix retval (nr, nc, nz); | |
691 | |
5275 | 692 octave_idx_type ii = 0; |
5164 | 693 retval.xcidx(0) = 0; |
5275 | 694 for (octave_idx_type i = 0; i < nc; i++) |
5164 | 695 { |
5275 | 696 for (octave_idx_type j = x.cidx(i); j < x.cidx(i+1); j++) |
5164 | 697 { |
698 double tmp = atan2 (x.data(j), y); | |
699 if (tmp != 0.) | |
700 { | |
701 retval.xdata (ii) = tmp; | |
702 retval.xridx (ii++) = x.ridx (j); | |
703 } | |
704 } | |
705 retval.xcidx (i+1) = ii; | |
706 } | |
707 | |
708 if (ii != nz) | |
709 { | |
710 SparseMatrix retval2 (nr, nc, ii); | |
5275 | 711 for (octave_idx_type i = 0; i < nc+1; i++) |
5164 | 712 retval2.xcidx (i) = retval.cidx (i); |
5275 | 713 for (octave_idx_type i = 0; i < ii; i++) |
5164 | 714 { |
715 retval2.xdata (i) = retval.data (i); | |
716 retval2.xridx (i) = retval.ridx (i); | |
717 } | |
718 return retval2; | |
719 } | |
720 else | |
721 return retval; | |
722 } | |
723 | |
724 SparseMatrix | |
725 atan2 (const SparseMatrix& x, const SparseMatrix& y) | |
726 { | |
727 SparseMatrix r; | |
728 | |
729 if ((x.rows() == y.rows()) && (x.cols() == y.cols())) | |
730 { | |
5275 | 731 octave_idx_type x_nr = x.rows (); |
732 octave_idx_type x_nc = x.cols (); | |
733 | |
734 octave_idx_type y_nr = y.rows (); | |
735 octave_idx_type y_nc = y.cols (); | |
5164 | 736 |
737 if (x_nr != y_nr || x_nc != y_nc) | |
738 gripe_nonconformant ("atan2", x_nr, x_nc, y_nr, y_nc); | |
739 else | |
740 { | |
5681 | 741 r = SparseMatrix (x_nr, x_nc, (x.nnz () + y.nnz ())); |
5164 | 742 |
5275 | 743 octave_idx_type jx = 0; |
5164 | 744 r.cidx (0) = 0; |
5275 | 745 for (octave_idx_type i = 0 ; i < x_nc ; i++) |
5164 | 746 { |
5275 | 747 octave_idx_type ja = x.cidx(i); |
748 octave_idx_type ja_max = x.cidx(i+1); | |
5164 | 749 bool ja_lt_max= ja < ja_max; |
750 | |
5275 | 751 octave_idx_type jb = y.cidx(i); |
752 octave_idx_type jb_max = y.cidx(i+1); | |
5164 | 753 bool jb_lt_max = jb < jb_max; |
754 | |
755 while (ja_lt_max || jb_lt_max ) | |
756 { | |
757 OCTAVE_QUIT; | |
758 if ((! jb_lt_max) || | |
759 (ja_lt_max && (x.ridx(ja) < y.ridx(jb)))) | |
760 { | |
761 r.ridx(jx) = x.ridx(ja); | |
762 r.data(jx) = atan2 (x.data(ja), 0.); | |
763 jx++; | |
764 ja++; | |
765 ja_lt_max= ja < ja_max; | |
766 } | |
767 else if (( !ja_lt_max ) || | |
768 (jb_lt_max && (y.ridx(jb) < x.ridx(ja)) ) ) | |
769 { | |
770 jb++; | |
771 jb_lt_max= jb < jb_max; | |
772 } | |
773 else | |
774 { | |
775 double tmp = atan2 (x.data(ja), y.data(jb)); | |
776 if (tmp != 0.) | |
777 { | |
778 r.data(jx) = tmp; | |
779 r.ridx(jx) = x.ridx(ja); | |
780 jx++; | |
781 } | |
782 ja++; | |
783 ja_lt_max= ja < ja_max; | |
784 jb++; | |
785 jb_lt_max= jb < jb_max; | |
786 } | |
787 } | |
788 r.cidx(i+1) = jx; | |
789 } | |
790 | |
791 r.maybe_compress (); | |
792 } | |
793 } | |
794 else | |
795 (*current_liboctave_error_handler) ("matrix size mismatch"); | |
796 | |
797 return r; | |
798 } | |
799 | |
800 SparseMatrix | |
801 SparseMatrix::inverse (void) const | |
802 { | |
5275 | 803 octave_idx_type info; |
5164 | 804 double rcond; |
5785 | 805 MatrixType mattype (*this); |
5506 | 806 return inverse (mattype, info, rcond, 0, 0); |
807 } | |
808 | |
809 SparseMatrix | |
5785 | 810 SparseMatrix::inverse (MatrixType& mattype) const |
5506 | 811 { |
812 octave_idx_type info; | |
813 double rcond; | |
814 return inverse (mattype, info, rcond, 0, 0); | |
5164 | 815 } |
816 | |
817 SparseMatrix | |
5785 | 818 SparseMatrix::inverse (MatrixType& mattype, octave_idx_type& info) const |
5164 | 819 { |
820 double rcond; | |
5506 | 821 return inverse (mattype, info, rcond, 0, 0); |
822 } | |
823 | |
824 SparseMatrix | |
5785 | 825 SparseMatrix::dinverse (MatrixType &mattyp, octave_idx_type& info, |
5610 | 826 double& rcond, const bool, |
5506 | 827 const bool calccond) const |
828 { | |
829 SparseMatrix retval; | |
830 | |
831 octave_idx_type nr = rows (); | |
832 octave_idx_type nc = cols (); | |
833 info = 0; | |
834 | |
835 if (nr == 0 || nc == 0 || nr != nc) | |
836 (*current_liboctave_error_handler) ("inverse requires square matrix"); | |
837 else | |
838 { | |
839 // Print spparms("spumoni") info if requested | |
840 int typ = mattyp.type (); | |
841 mattyp.info (); | |
842 | |
5785 | 843 if (typ == MatrixType::Diagonal || |
844 typ == MatrixType::Permuted_Diagonal) | |
5506 | 845 { |
5785 | 846 if (typ == MatrixType::Permuted_Diagonal) |
5506 | 847 retval = transpose(); |
848 else | |
849 retval = *this; | |
850 | |
851 // Force make_unique to be called | |
852 double *v = retval.data(); | |
853 | |
854 if (calccond) | |
855 { | |
856 double dmax = 0., dmin = octave_Inf; | |
857 for (octave_idx_type i = 0; i < nr; i++) | |
858 { | |
859 double tmp = fabs(v[i]); | |
860 if (tmp > dmax) | |
861 dmax = tmp; | |
862 if (tmp < dmin) | |
863 dmin = tmp; | |
864 } | |
865 rcond = dmin / dmax; | |
866 } | |
867 | |
868 for (octave_idx_type i = 0; i < nr; i++) | |
869 v[i] = 1.0 / v[i]; | |
870 } | |
871 else | |
872 (*current_liboctave_error_handler) ("incorrect matrix type"); | |
873 } | |
874 | |
875 return retval; | |
876 } | |
877 | |
878 SparseMatrix | |
5785 | 879 SparseMatrix::tinverse (MatrixType &mattyp, octave_idx_type& info, |
5610 | 880 double& rcond, const bool, |
5506 | 881 const bool calccond) const |
882 { | |
883 SparseMatrix retval; | |
884 | |
885 octave_idx_type nr = rows (); | |
886 octave_idx_type nc = cols (); | |
887 info = 0; | |
888 | |
889 if (nr == 0 || nc == 0 || nr != nc) | |
890 (*current_liboctave_error_handler) ("inverse requires square matrix"); | |
891 else | |
892 { | |
893 // Print spparms("spumoni") info if requested | |
894 int typ = mattyp.type (); | |
895 mattyp.info (); | |
896 | |
5785 | 897 if (typ == MatrixType::Upper || typ == MatrixType::Permuted_Upper || |
898 typ == MatrixType::Lower || typ == MatrixType::Permuted_Lower) | |
5506 | 899 { |
900 double anorm = 0.; | |
901 double ainvnorm = 0.; | |
902 | |
903 if (calccond) | |
904 { | |
905 // Calculate the 1-norm of matrix for rcond calculation | |
906 for (octave_idx_type j = 0; j < nr; j++) | |
907 { | |
908 double atmp = 0.; | |
909 for (octave_idx_type i = cidx(j); i < cidx(j+1); i++) | |
910 atmp += fabs(data(i)); | |
911 if (atmp > anorm) | |
912 anorm = atmp; | |
913 } | |
914 } | |
915 | |
5785 | 916 if (typ == MatrixType::Upper || typ == MatrixType::Lower) |
5506 | 917 { |
5681 | 918 octave_idx_type nz = nnz (); |
5506 | 919 octave_idx_type cx = 0; |
920 octave_idx_type nz2 = nz; | |
921 retval = SparseMatrix (nr, nc, nz2); | |
922 | |
923 for (octave_idx_type i = 0; i < nr; i++) | |
924 { | |
925 OCTAVE_QUIT; | |
926 // place the 1 in the identity position | |
927 octave_idx_type cx_colstart = cx; | |
928 | |
929 if (cx == nz2) | |
930 { | |
931 nz2 *= 2; | |
932 retval.change_capacity (nz2); | |
933 } | |
934 | |
935 retval.xcidx(i) = cx; | |
936 retval.xridx(cx) = i; | |
937 retval.xdata(cx) = 1.0; | |
938 cx++; | |
939 | |
940 // iterate accross columns of input matrix | |
941 for (octave_idx_type j = i+1; j < nr; j++) | |
942 { | |
943 double v = 0.; | |
944 // iterate to calculate sum | |
945 octave_idx_type colXp = retval.xcidx(i); | |
946 octave_idx_type colUp = cidx(j); | |
947 octave_idx_type rpX, rpU; | |
5876 | 948 |
949 if (cidx(j) == cidx(j+1)) | |
950 { | |
951 (*current_liboctave_error_handler) | |
952 ("division by zero"); | |
953 goto inverse_singular; | |
954 } | |
955 | |
5506 | 956 do |
957 { | |
958 OCTAVE_QUIT; | |
959 rpX = retval.xridx(colXp); | |
960 rpU = ridx(colUp); | |
961 | |
962 if (rpX < rpU) | |
963 colXp++; | |
964 else if (rpX > rpU) | |
965 colUp++; | |
966 else | |
967 { | |
968 v -= retval.xdata(colXp) * data(colUp); | |
969 colXp++; | |
970 colUp++; | |
971 } | |
972 } while ((rpX<j) && (rpU<j) && | |
973 (colXp<cx) && (colUp<nz)); | |
974 | |
975 // get A(m,m) | |
5876 | 976 if (typ == MatrixType::Upper) |
977 colUp = cidx(j+1) - 1; | |
978 else | |
5877 | 979 colUp = cidx(j); |
5506 | 980 double pivot = data(colUp); |
5877 | 981 if (pivot == 0. || ridx(colUp) != j) |
5876 | 982 { |
983 (*current_liboctave_error_handler) | |
984 ("division by zero"); | |
985 goto inverse_singular; | |
986 } | |
5506 | 987 |
988 if (v != 0.) | |
989 { | |
990 if (cx == nz2) | |
991 { | |
992 nz2 *= 2; | |
993 retval.change_capacity (nz2); | |
994 } | |
995 | |
996 retval.xridx(cx) = j; | |
997 retval.xdata(cx) = v / pivot; | |
998 cx++; | |
999 } | |
1000 } | |
1001 | |
1002 // get A(m,m) | |
5876 | 1003 octave_idx_type colUp; |
1004 if (typ == MatrixType::Upper) | |
1005 colUp = cidx(i+1) - 1; | |
1006 else | |
5877 | 1007 colUp = cidx(i); |
5506 | 1008 double pivot = data(colUp); |
5877 | 1009 if (pivot == 0. || ridx(colUp) != i) |
5876 | 1010 { |
1011 (*current_liboctave_error_handler) ("division by zero"); | |
1012 goto inverse_singular; | |
1013 } | |
5506 | 1014 |
1015 if (pivot != 1.0) | |
1016 for (octave_idx_type j = cx_colstart; j < cx; j++) | |
1017 retval.xdata(j) /= pivot; | |
1018 } | |
1019 retval.xcidx(nr) = cx; | |
1020 retval.maybe_compress (); | |
1021 } | |
1022 else | |
1023 { | |
5681 | 1024 octave_idx_type nz = nnz (); |
5506 | 1025 octave_idx_type cx = 0; |
1026 octave_idx_type nz2 = nz; | |
1027 retval = SparseMatrix (nr, nc, nz2); | |
1028 | |
1029 OCTAVE_LOCAL_BUFFER (double, work, nr); | |
1030 OCTAVE_LOCAL_BUFFER (octave_idx_type, rperm, nr); | |
1031 | |
1032 octave_idx_type *perm = mattyp.triangular_perm(); | |
5785 | 1033 if (typ == MatrixType::Permuted_Upper) |
5506 | 1034 { |
1035 for (octave_idx_type i = 0; i < nr; i++) | |
1036 rperm[perm[i]] = i; | |
1037 } | |
1038 else | |
1039 { | |
1040 for (octave_idx_type i = 0; i < nr; i++) | |
1041 rperm[i] = perm[i]; | |
1042 for (octave_idx_type i = 0; i < nr; i++) | |
1043 perm[rperm[i]] = i; | |
1044 } | |
1045 | |
1046 for (octave_idx_type i = 0; i < nr; i++) | |
1047 { | |
1048 OCTAVE_QUIT; | |
1049 octave_idx_type iidx = rperm[i]; | |
1050 | |
1051 for (octave_idx_type j = 0; j < nr; j++) | |
1052 work[j] = 0.; | |
1053 | |
1054 // place the 1 in the identity position | |
1055 work[iidx] = 1.0; | |
1056 | |
1057 // iterate accross columns of input matrix | |
1058 for (octave_idx_type j = iidx+1; j < nr; j++) | |
1059 { | |
1060 double v = 0.; | |
1061 octave_idx_type jidx = perm[j]; | |
1062 // iterate to calculate sum | |
1063 for (octave_idx_type k = cidx(jidx); | |
1064 k < cidx(jidx+1); k++) | |
1065 { | |
1066 OCTAVE_QUIT; | |
1067 v -= work[ridx(k)] * data(k); | |
1068 } | |
1069 | |
1070 // get A(m,m) | |
5876 | 1071 double pivot; |
1072 if (typ == MatrixType::Permuted_Upper) | |
1073 pivot = data(cidx(jidx+1) - 1); | |
1074 else | |
5877 | 1075 pivot = data(cidx(jidx)); |
5506 | 1076 if (pivot == 0.) |
5876 | 1077 { |
1078 (*current_liboctave_error_handler) | |
1079 ("division by zero"); | |
1080 goto inverse_singular; | |
1081 } | |
5506 | 1082 |
1083 work[j] = v / pivot; | |
1084 } | |
1085 | |
1086 // get A(m,m) | |
5876 | 1087 octave_idx_type colUp; |
1088 if (typ == MatrixType::Permuted_Upper) | |
1089 colUp = cidx(perm[iidx]+1) - 1; | |
1090 else | |
5877 | 1091 colUp = cidx(perm[iidx]); |
5876 | 1092 |
5506 | 1093 double pivot = data(colUp); |
5876 | 1094 if (pivot == 0.) |
1095 { | |
1096 (*current_liboctave_error_handler) | |
1097 ("division by zero"); | |
1098 goto inverse_singular; | |
1099 } | |
5506 | 1100 |
1101 octave_idx_type new_cx = cx; | |
1102 for (octave_idx_type j = iidx; j < nr; j++) | |
1103 if (work[j] != 0.0) | |
1104 { | |
1105 new_cx++; | |
1106 if (pivot != 1.0) | |
1107 work[j] /= pivot; | |
1108 } | |
1109 | |
1110 if (cx < new_cx) | |
1111 { | |
1112 nz2 = (2*nz2 < new_cx ? new_cx : 2*nz2); | |
1113 retval.change_capacity (nz2); | |
1114 } | |
1115 | |
1116 retval.xcidx(i) = cx; | |
1117 for (octave_idx_type j = iidx; j < nr; j++) | |
1118 if (work[j] != 0.) | |
1119 { | |
1120 retval.xridx(cx) = j; | |
1121 retval.xdata(cx++) = work[j]; | |
1122 } | |
1123 } | |
1124 | |
1125 retval.xcidx(nr) = cx; | |
1126 retval.maybe_compress (); | |
1127 } | |
1128 | |
1129 if (calccond) | |
1130 { | |
1131 // Calculate the 1-norm of inverse matrix for rcond calculation | |
1132 for (octave_idx_type j = 0; j < nr; j++) | |
1133 { | |
1134 double atmp = 0.; | |
1135 for (octave_idx_type i = retval.cidx(j); | |
1136 i < retval.cidx(j+1); i++) | |
1137 atmp += fabs(retval.data(i)); | |
1138 if (atmp > ainvnorm) | |
1139 ainvnorm = atmp; | |
1140 } | |
1141 | |
1142 rcond = 1. / ainvnorm / anorm; | |
1143 } | |
1144 } | |
1145 else | |
1146 (*current_liboctave_error_handler) ("incorrect matrix type"); | |
1147 } | |
1148 | |
1149 return retval; | |
5876 | 1150 |
1151 inverse_singular: | |
1152 return SparseMatrix(); | |
5164 | 1153 } |
1154 | |
1155 SparseMatrix | |
5785 | 1156 SparseMatrix::inverse (MatrixType &mattype, octave_idx_type& info, |
5610 | 1157 double& rcond, int, int calc_cond) const |
5506 | 1158 { |
1159 int typ = mattype.type (false); | |
1160 SparseMatrix ret; | |
1161 | |
5785 | 1162 if (typ == MatrixType::Unknown) |
5506 | 1163 typ = mattype.type (*this); |
1164 | |
5785 | 1165 if (typ == MatrixType::Diagonal || typ == MatrixType::Permuted_Diagonal) |
5506 | 1166 ret = dinverse (mattype, info, rcond, true, calc_cond); |
5785 | 1167 else if (typ == MatrixType::Upper || typ == MatrixType::Permuted_Upper) |
5506 | 1168 ret = tinverse (mattype, info, rcond, true, calc_cond).transpose(); |
5785 | 1169 else if (typ == MatrixType::Lower || typ == MatrixType::Permuted_Lower) |
6185 | 1170 { |
1171 MatrixType newtype = mattype.transpose(); | |
1172 ret = transpose().tinverse (newtype, info, rcond, true, calc_cond); | |
1173 } | |
6840 | 1174 else |
5506 | 1175 { |
1176 if (mattype.is_hermitian()) | |
1177 { | |
5785 | 1178 MatrixType tmp_typ (MatrixType::Upper); |
5506 | 1179 SparseCHOL fact (*this, info, false); |
1180 rcond = fact.rcond(); | |
1181 if (info == 0) | |
1182 { | |
1183 double rcond2; | |
1184 SparseMatrix Q = fact.Q(); | |
1185 SparseMatrix InvL = fact.L().transpose().tinverse(tmp_typ, | |
1186 info, rcond2, true, false); | |
1187 ret = Q * InvL.transpose() * InvL * Q.transpose(); | |
1188 } | |
1189 else | |
1190 { | |
1191 // Matrix is either singular or not positive definite | |
1192 mattype.mark_as_unsymmetric (); | |
5785 | 1193 typ = MatrixType::Full; |
5506 | 1194 } |
1195 } | |
1196 | |
1197 if (!mattype.is_hermitian()) | |
1198 { | |
1199 octave_idx_type n = rows(); | |
1200 ColumnVector Qinit(n); | |
1201 for (octave_idx_type i = 0; i < n; i++) | |
1202 Qinit(i) = i; | |
1203 | |
5785 | 1204 MatrixType tmp_typ (MatrixType::Upper); |
7515
f3c00dc0912b
Eliminate the rest of the dispatched sparse functions
David Bateman <dbateman@free.fr>
parents:
7503
diff
changeset
|
1205 SparseLU fact (*this, Qinit, Matrix(), false, false); |
5506 | 1206 rcond = fact.rcond(); |
1207 double rcond2; | |
1208 SparseMatrix InvL = fact.L().transpose().tinverse(tmp_typ, | |
1209 info, rcond2, true, false); | |
1210 SparseMatrix InvU = fact.U().tinverse(tmp_typ, info, rcond2, | |
1211 true, false).transpose(); | |
1212 ret = fact.Pc().transpose() * InvU * InvL * fact.Pr(); | |
1213 } | |
1214 } | |
1215 | |
1216 return ret; | |
5164 | 1217 } |
1218 | |
1219 DET | |
1220 SparseMatrix::determinant (void) const | |
1221 { | |
5275 | 1222 octave_idx_type info; |
5164 | 1223 double rcond; |
1224 return determinant (info, rcond, 0); | |
1225 } | |
1226 | |
1227 DET | |
5275 | 1228 SparseMatrix::determinant (octave_idx_type& info) const |
5164 | 1229 { |
1230 double rcond; | |
1231 return determinant (info, rcond, 0); | |
1232 } | |
1233 | |
1234 DET | |
5275 | 1235 SparseMatrix::determinant (octave_idx_type& err, double& rcond, int) const |
5164 | 1236 { |
1237 DET retval; | |
1238 | |
5203 | 1239 #ifdef HAVE_UMFPACK |
5275 | 1240 octave_idx_type nr = rows (); |
1241 octave_idx_type nc = cols (); | |
5164 | 1242 |
1243 if (nr == 0 || nc == 0 || nr != nc) | |
1244 { | |
8335 | 1245 retval = DET (1.0); |
5164 | 1246 } |
1247 else | |
1248 { | |
1249 err = 0; | |
1250 | |
1251 // Setup the control parameters | |
1252 Matrix Control (UMFPACK_CONTROL, 1); | |
1253 double *control = Control.fortran_vec (); | |
5322 | 1254 UMFPACK_DNAME (defaults) (control); |
5164 | 1255 |
5893 | 1256 double tmp = octave_sparse_params::get_key ("spumoni"); |
5164 | 1257 if (!xisnan (tmp)) |
1258 Control (UMFPACK_PRL) = tmp; | |
1259 | |
5893 | 1260 tmp = octave_sparse_params::get_key ("piv_tol"); |
5164 | 1261 if (!xisnan (tmp)) |
1262 { | |
1263 Control (UMFPACK_SYM_PIVOT_TOLERANCE) = tmp; | |
1264 Control (UMFPACK_PIVOT_TOLERANCE) = tmp; | |
1265 } | |
1266 | |
1267 // Set whether we are allowed to modify Q or not | |
5893 | 1268 tmp = octave_sparse_params::get_key ("autoamd"); |
5164 | 1269 if (!xisnan (tmp)) |
1270 Control (UMFPACK_FIXQ) = tmp; | |
1271 | |
1272 // Turn-off UMFPACK scaling for LU | |
1273 Control (UMFPACK_SCALE) = UMFPACK_SCALE_NONE; | |
1274 | |
5322 | 1275 UMFPACK_DNAME (report_control) (control); |
5164 | 1276 |
5275 | 1277 const octave_idx_type *Ap = cidx (); |
1278 const octave_idx_type *Ai = ridx (); | |
5164 | 1279 const double *Ax = data (); |
1280 | |
5322 | 1281 UMFPACK_DNAME (report_matrix) (nr, nc, Ap, Ai, Ax, 1, control); |
5164 | 1282 |
1283 void *Symbolic; | |
1284 Matrix Info (1, UMFPACK_INFO); | |
1285 double *info = Info.fortran_vec (); | |
5322 | 1286 int status = UMFPACK_DNAME (qsymbolic) (nr, nc, Ap, Ai, |
7520 | 1287 Ax, 0, &Symbolic, control, info); |
5164 | 1288 |
1289 if (status < 0) | |
1290 { | |
1291 (*current_liboctave_error_handler) | |
1292 ("SparseMatrix::determinant symbolic factorization failed"); | |
1293 | |
5322 | 1294 UMFPACK_DNAME (report_status) (control, status); |
1295 UMFPACK_DNAME (report_info) (control, info); | |
1296 | |
1297 UMFPACK_DNAME (free_symbolic) (&Symbolic) ; | |
5164 | 1298 } |
1299 else | |
1300 { | |
5322 | 1301 UMFPACK_DNAME (report_symbolic) (Symbolic, control); |
5164 | 1302 |
1303 void *Numeric; | |
5322 | 1304 status = UMFPACK_DNAME (numeric) (Ap, Ai, Ax, Symbolic, |
1305 &Numeric, control, info) ; | |
1306 UMFPACK_DNAME (free_symbolic) (&Symbolic) ; | |
5164 | 1307 |
1308 rcond = Info (UMFPACK_RCOND); | |
1309 | |
1310 if (status < 0) | |
1311 { | |
1312 (*current_liboctave_error_handler) | |
1313 ("SparseMatrix::determinant numeric factorization failed"); | |
1314 | |
5322 | 1315 UMFPACK_DNAME (report_status) (control, status); |
1316 UMFPACK_DNAME (report_info) (control, info); | |
1317 | |
1318 UMFPACK_DNAME (free_numeric) (&Numeric); | |
5164 | 1319 } |
1320 else | |
1321 { | |
5322 | 1322 UMFPACK_DNAME (report_numeric) (Numeric, control); |
5164 | 1323 |
8335 | 1324 double c10, e10; |
1325 | |
1326 status = UMFPACK_DNAME (get_determinant) (&c10, &e10, Numeric, info); | |
5164 | 1327 |
1328 if (status < 0) | |
1329 { | |
1330 (*current_liboctave_error_handler) | |
1331 ("SparseMatrix::determinant error calculating determinant"); | |
1332 | |
5322 | 1333 UMFPACK_DNAME (report_status) (control, status); |
1334 UMFPACK_DNAME (report_info) (control, info); | |
5164 | 1335 } |
1336 else | |
8335 | 1337 retval = DET (c10, e10, 10); |
5346 | 1338 |
1339 UMFPACK_DNAME (free_numeric) (&Numeric); | |
5164 | 1340 } |
1341 } | |
1342 } | |
5203 | 1343 #else |
1344 (*current_liboctave_error_handler) ("UMFPACK not installed"); | |
1345 #endif | |
5164 | 1346 |
1347 return retval; | |
1348 } | |
1349 | |
1350 Matrix | |
5785 | 1351 SparseMatrix::dsolve (MatrixType &mattype, const Matrix& b, octave_idx_type& err, |
5681 | 1352 double& rcond, solve_singularity_handler, |
1353 bool calc_cond) const | |
5164 | 1354 { |
1355 Matrix retval; | |
1356 | |
5275 | 1357 octave_idx_type nr = rows (); |
1358 octave_idx_type nc = cols (); | |
5630 | 1359 octave_idx_type nm = (nc < nr ? nc : nr); |
5164 | 1360 err = 0; |
1361 | |
6924 | 1362 if (nr != b.rows ()) |
5164 | 1363 (*current_liboctave_error_handler) |
1364 ("matrix dimension mismatch solution of linear equations"); | |
6924 | 1365 else if (nr == 0 || nc == 0 || b.cols () == 0) |
1366 retval = Matrix (nc, b.cols (), 0.0); | |
5164 | 1367 else |
1368 { | |
1369 // Print spparms("spumoni") info if requested | |
1370 int typ = mattype.type (); | |
1371 mattype.info (); | |
1372 | |
5785 | 1373 if (typ == MatrixType::Diagonal || |
1374 typ == MatrixType::Permuted_Diagonal) | |
5164 | 1375 { |
5630 | 1376 retval.resize (nc, b.cols(), 0.); |
5785 | 1377 if (typ == MatrixType::Diagonal) |
5275 | 1378 for (octave_idx_type j = 0; j < b.cols(); j++) |
5630 | 1379 for (octave_idx_type i = 0; i < nm; i++) |
5164 | 1380 retval(i,j) = b(i,j) / data (i); |
1381 else | |
5275 | 1382 for (octave_idx_type j = 0; j < b.cols(); j++) |
5630 | 1383 for (octave_idx_type k = 0; k < nc; k++) |
1384 for (octave_idx_type i = cidx(k); i < cidx(k+1); i++) | |
1385 retval(k,j) = b(ridx(i),j) / data (i); | |
1386 | |
5681 | 1387 if (calc_cond) |
1388 { | |
1389 double dmax = 0., dmin = octave_Inf; | |
1390 for (octave_idx_type i = 0; i < nm; i++) | |
1391 { | |
1392 double tmp = fabs(data(i)); | |
1393 if (tmp > dmax) | |
1394 dmax = tmp; | |
1395 if (tmp < dmin) | |
1396 dmin = tmp; | |
1397 } | |
1398 rcond = dmin / dmax; | |
1399 } | |
1400 else | |
1401 rcond = 1.; | |
5164 | 1402 } |
1403 else | |
1404 (*current_liboctave_error_handler) ("incorrect matrix type"); | |
1405 } | |
1406 | |
1407 return retval; | |
1408 } | |
1409 | |
1410 SparseMatrix | |
5785 | 1411 SparseMatrix::dsolve (MatrixType &mattype, const SparseMatrix& b, |
5681 | 1412 octave_idx_type& err, double& rcond, |
1413 solve_singularity_handler, bool calc_cond) const | |
5164 | 1414 { |
1415 SparseMatrix retval; | |
1416 | |
5275 | 1417 octave_idx_type nr = rows (); |
1418 octave_idx_type nc = cols (); | |
5630 | 1419 octave_idx_type nm = (nc < nr ? nc : nr); |
5164 | 1420 err = 0; |
1421 | |
6924 | 1422 if (nr != b.rows ()) |
5164 | 1423 (*current_liboctave_error_handler) |
1424 ("matrix dimension mismatch solution of linear equations"); | |
6924 | 1425 else if (nr == 0 || nc == 0 || b.cols () == 0) |
1426 retval = SparseMatrix (nc, b.cols ()); | |
5164 | 1427 else |
1428 { | |
1429 // Print spparms("spumoni") info if requested | |
1430 int typ = mattype.type (); | |
1431 mattype.info (); | |
1432 | |
5785 | 1433 if (typ == MatrixType::Diagonal || |
1434 typ == MatrixType::Permuted_Diagonal) | |
5164 | 1435 { |
5275 | 1436 octave_idx_type b_nc = b.cols (); |
5681 | 1437 octave_idx_type b_nz = b.nnz (); |
5630 | 1438 retval = SparseMatrix (nc, b_nc, b_nz); |
5164 | 1439 |
1440 retval.xcidx(0) = 0; | |
5275 | 1441 octave_idx_type ii = 0; |
5785 | 1442 if (typ == MatrixType::Diagonal) |
5681 | 1443 for (octave_idx_type j = 0; j < b_nc; j++) |
5164 | 1444 { |
5275 | 1445 for (octave_idx_type i = b.cidx(j); i < b.cidx(j+1); i++) |
5164 | 1446 { |
5681 | 1447 if (b.ridx(i) >= nm) |
1448 break; | |
5164 | 1449 retval.xridx (ii) = b.ridx(i); |
1450 retval.xdata (ii++) = b.data(i) / data (b.ridx (i)); | |
1451 } | |
1452 retval.xcidx(j+1) = ii; | |
1453 } | |
1454 else | |
5681 | 1455 for (octave_idx_type j = 0; j < b_nc; j++) |
5164 | 1456 { |
5630 | 1457 for (octave_idx_type l = 0; l < nc; l++) |
1458 for (octave_idx_type i = cidx(l); i < cidx(l+1); i++) | |
1459 { | |
1460 bool found = false; | |
1461 octave_idx_type k; | |
1462 for (k = b.cidx(j); k < b.cidx(j+1); k++) | |
1463 if (ridx(i) == b.ridx(k)) | |
1464 { | |
1465 found = true; | |
1466 break; | |
1467 } | |
1468 if (found) | |
5164 | 1469 { |
5630 | 1470 retval.xridx (ii) = l; |
1471 retval.xdata (ii++) = b.data(k) / data (i); | |
5164 | 1472 } |
5630 | 1473 } |
5164 | 1474 retval.xcidx(j+1) = ii; |
1475 } | |
5630 | 1476 |
5681 | 1477 if (calc_cond) |
1478 { | |
1479 double dmax = 0., dmin = octave_Inf; | |
1480 for (octave_idx_type i = 0; i < nm; i++) | |
1481 { | |
1482 double tmp = fabs(data(i)); | |
1483 if (tmp > dmax) | |
1484 dmax = tmp; | |
1485 if (tmp < dmin) | |
1486 dmin = tmp; | |
1487 } | |
1488 rcond = dmin / dmax; | |
1489 } | |
1490 else | |
1491 rcond = 1.; | |
5164 | 1492 } |
1493 else | |
1494 (*current_liboctave_error_handler) ("incorrect matrix type"); | |
1495 } | |
1496 | |
1497 return retval; | |
1498 } | |
1499 | |
1500 ComplexMatrix | |
5785 | 1501 SparseMatrix::dsolve (MatrixType &mattype, const ComplexMatrix& b, |
5681 | 1502 octave_idx_type& err, double& rcond, |
1503 solve_singularity_handler, bool calc_cond) const | |
5164 | 1504 { |
1505 ComplexMatrix retval; | |
1506 | |
5275 | 1507 octave_idx_type nr = rows (); |
1508 octave_idx_type nc = cols (); | |
5630 | 1509 octave_idx_type nm = (nc < nr ? nc : nr); |
5164 | 1510 err = 0; |
1511 | |
6924 | 1512 if (nr != b.rows ()) |
5164 | 1513 (*current_liboctave_error_handler) |
1514 ("matrix dimension mismatch solution of linear equations"); | |
6924 | 1515 else if (nr == 0 || nc == 0 || b.cols () == 0) |
1516 retval = ComplexMatrix (nc, b.cols (), Complex (0.0, 0.0)); | |
5164 | 1517 else |
1518 { | |
1519 // Print spparms("spumoni") info if requested | |
1520 int typ = mattype.type (); | |
1521 mattype.info (); | |
1522 | |
5785 | 1523 if (typ == MatrixType::Diagonal || |
1524 typ == MatrixType::Permuted_Diagonal) | |
5164 | 1525 { |
5630 | 1526 retval.resize (nc, b.cols(), 0); |
5785 | 1527 if (typ == MatrixType::Diagonal) |
5275 | 1528 for (octave_idx_type j = 0; j < b.cols(); j++) |
5630 | 1529 for (octave_idx_type i = 0; i < nm; i++) |
1530 retval(i,j) = b(i,j) / data (i); | |
5164 | 1531 else |
5275 | 1532 for (octave_idx_type j = 0; j < b.cols(); j++) |
5630 | 1533 for (octave_idx_type k = 0; k < nc; k++) |
1534 for (octave_idx_type i = cidx(k); i < cidx(k+1); i++) | |
1535 retval(k,j) = b(ridx(i),j) / data (i); | |
5164 | 1536 |
5681 | 1537 if (calc_cond) |
1538 { | |
1539 double dmax = 0., dmin = octave_Inf; | |
1540 for (octave_idx_type i = 0; i < nm; i++) | |
1541 { | |
1542 double tmp = fabs(data(i)); | |
1543 if (tmp > dmax) | |
1544 dmax = tmp; | |
1545 if (tmp < dmin) | |
1546 dmin = tmp; | |
1547 } | |
1548 rcond = dmin / dmax; | |
1549 } | |
1550 else | |
1551 rcond = 1.; | |
5164 | 1552 } |
1553 else | |
1554 (*current_liboctave_error_handler) ("incorrect matrix type"); | |
1555 } | |
1556 | |
1557 return retval; | |
1558 } | |
1559 | |
1560 SparseComplexMatrix | |
5785 | 1561 SparseMatrix::dsolve (MatrixType &mattype, const SparseComplexMatrix& b, |
5275 | 1562 octave_idx_type& err, double& rcond, |
5681 | 1563 solve_singularity_handler, bool calc_cond) const |
5164 | 1564 { |
1565 SparseComplexMatrix retval; | |
1566 | |
5275 | 1567 octave_idx_type nr = rows (); |
1568 octave_idx_type nc = cols (); | |
5630 | 1569 octave_idx_type nm = (nc < nr ? nc : nr); |
5164 | 1570 err = 0; |
1571 | |
6924 | 1572 if (nr != b.rows ()) |
5164 | 1573 (*current_liboctave_error_handler) |
1574 ("matrix dimension mismatch solution of linear equations"); | |
6924 | 1575 else if (nr == 0 || nc == 0 || b.cols () == 0) |
1576 retval = SparseComplexMatrix (nc, b.cols ()); | |
5164 | 1577 else |
1578 { | |
1579 // Print spparms("spumoni") info if requested | |
1580 int typ = mattype.type (); | |
1581 mattype.info (); | |
1582 | |
5785 | 1583 if (typ == MatrixType::Diagonal || |
1584 typ == MatrixType::Permuted_Diagonal) | |
5164 | 1585 { |
5275 | 1586 octave_idx_type b_nc = b.cols (); |
5681 | 1587 octave_idx_type b_nz = b.nnz (); |
5630 | 1588 retval = SparseComplexMatrix (nc, b_nc, b_nz); |
5164 | 1589 |
1590 retval.xcidx(0) = 0; | |
5275 | 1591 octave_idx_type ii = 0; |
5785 | 1592 if (typ == MatrixType::Diagonal) |
5275 | 1593 for (octave_idx_type j = 0; j < b.cols(); j++) |
5164 | 1594 { |
5275 | 1595 for (octave_idx_type i = b.cidx(j); i < b.cidx(j+1); i++) |
5164 | 1596 { |
5681 | 1597 if (b.ridx(i) >= nm) |
1598 break; | |
5164 | 1599 retval.xridx (ii) = b.ridx(i); |
1600 retval.xdata (ii++) = b.data(i) / data (b.ridx (i)); | |
1601 } | |
1602 retval.xcidx(j+1) = ii; | |
1603 } | |
1604 else | |
5275 | 1605 for (octave_idx_type j = 0; j < b.cols(); j++) |
5164 | 1606 { |
5630 | 1607 for (octave_idx_type l = 0; l < nc; l++) |
1608 for (octave_idx_type i = cidx(l); i < cidx(l+1); i++) | |
1609 { | |
1610 bool found = false; | |
1611 octave_idx_type k; | |
1612 for (k = b.cidx(j); k < b.cidx(j+1); k++) | |
1613 if (ridx(i) == b.ridx(k)) | |
1614 { | |
1615 found = true; | |
1616 break; | |
1617 } | |
1618 if (found) | |
5164 | 1619 { |
5630 | 1620 retval.xridx (ii) = l; |
1621 retval.xdata (ii++) = b.data(k) / data (i); | |
5164 | 1622 } |
5630 | 1623 } |
5164 | 1624 retval.xcidx(j+1) = ii; |
1625 } | |
1626 | |
5681 | 1627 if (calc_cond) |
1628 { | |
1629 double dmax = 0., dmin = octave_Inf; | |
1630 for (octave_idx_type i = 0; i < nm; i++) | |
1631 { | |
1632 double tmp = fabs(data(i)); | |
1633 if (tmp > dmax) | |
1634 dmax = tmp; | |
1635 if (tmp < dmin) | |
1636 dmin = tmp; | |
1637 } | |
1638 rcond = dmin / dmax; | |
1639 } | |
1640 else | |
1641 rcond = 1.; | |
5164 | 1642 } |
1643 else | |
1644 (*current_liboctave_error_handler) ("incorrect matrix type"); | |
1645 } | |
1646 | |
1647 return retval; | |
1648 } | |
1649 | |
1650 Matrix | |
5785 | 1651 SparseMatrix::utsolve (MatrixType &mattype, const Matrix& b, |
5630 | 1652 octave_idx_type& err, double& rcond, |
5681 | 1653 solve_singularity_handler sing_handler, |
1654 bool calc_cond) const | |
5164 | 1655 { |
1656 Matrix retval; | |
1657 | |
5275 | 1658 octave_idx_type nr = rows (); |
1659 octave_idx_type nc = cols (); | |
5630 | 1660 octave_idx_type nm = (nc > nr ? nc : nr); |
5164 | 1661 err = 0; |
1662 | |
6924 | 1663 if (nr != b.rows ()) |
5164 | 1664 (*current_liboctave_error_handler) |
1665 ("matrix dimension mismatch solution of linear equations"); | |
6924 | 1666 else if (nr == 0 || nc == 0 || b.cols () == 0) |
1667 retval = Matrix (nc, b.cols (), 0.0); | |
5164 | 1668 else |
1669 { | |
1670 // Print spparms("spumoni") info if requested | |
1671 int typ = mattype.type (); | |
1672 mattype.info (); | |
1673 | |
5785 | 1674 if (typ == MatrixType::Permuted_Upper || |
1675 typ == MatrixType::Upper) | |
5164 | 1676 { |
1677 double anorm = 0.; | |
1678 double ainvnorm = 0.; | |
5630 | 1679 octave_idx_type b_nc = b.cols (); |
5681 | 1680 rcond = 1.; |
1681 | |
1682 if (calc_cond) | |
1683 { | |
1684 // Calculate the 1-norm of matrix for rcond calculation | |
1685 for (octave_idx_type j = 0; j < nc; j++) | |
1686 { | |
1687 double atmp = 0.; | |
1688 for (octave_idx_type i = cidx(j); i < cidx(j+1); i++) | |
1689 atmp += fabs(data(i)); | |
1690 if (atmp > anorm) | |
1691 anorm = atmp; | |
1692 } | |
5164 | 1693 } |
1694 | |
5785 | 1695 if (typ == MatrixType::Permuted_Upper) |
5164 | 1696 { |
5630 | 1697 retval.resize (nc, b_nc); |
5322 | 1698 octave_idx_type *perm = mattype.triangular_perm (); |
5630 | 1699 OCTAVE_LOCAL_BUFFER (double, work, nm); |
1700 | |
1701 for (octave_idx_type j = 0; j < b_nc; j++) | |
5164 | 1702 { |
5275 | 1703 for (octave_idx_type i = 0; i < nr; i++) |
5164 | 1704 work[i] = b(i,j); |
5630 | 1705 for (octave_idx_type i = nr; i < nc; i++) |
1706 work[i] = 0.; | |
1707 | |
1708 for (octave_idx_type k = nc-1; k >= 0; k--) | |
5164 | 1709 { |
5322 | 1710 octave_idx_type kidx = perm[k]; |
1711 | |
1712 if (work[k] != 0.) | |
5164 | 1713 { |
5681 | 1714 if (ridx(cidx(kidx+1)-1) != k || |
1715 data(cidx(kidx+1)-1) == 0.) | |
5164 | 1716 { |
1717 err = -2; | |
1718 goto triangular_error; | |
1719 } | |
1720 | |
5322 | 1721 double tmp = work[k] / data(cidx(kidx+1)-1); |
1722 work[k] = tmp; | |
1723 for (octave_idx_type i = cidx(kidx); | |
1724 i < cidx(kidx+1)-1; i++) | |
5164 | 1725 { |
5322 | 1726 octave_idx_type iidx = ridx(i); |
1727 work[iidx] = work[iidx] - tmp * data(i); | |
5164 | 1728 } |
1729 } | |
1730 } | |
1731 | |
5630 | 1732 for (octave_idx_type i = 0; i < nc; i++) |
1733 retval.xelem (perm[i], j) = work[i]; | |
5164 | 1734 } |
1735 | |
5681 | 1736 if (calc_cond) |
1737 { | |
1738 // Calculation of 1-norm of inv(*this) | |
1739 for (octave_idx_type i = 0; i < nm; i++) | |
1740 work[i] = 0.; | |
1741 | |
1742 for (octave_idx_type j = 0; j < nr; j++) | |
5164 | 1743 { |
5681 | 1744 work[j] = 1.; |
1745 | |
1746 for (octave_idx_type k = j; k >= 0; k--) | |
5164 | 1747 { |
5681 | 1748 octave_idx_type iidx = perm[k]; |
1749 | |
1750 if (work[k] != 0.) | |
5164 | 1751 { |
5681 | 1752 double tmp = work[k] / data(cidx(iidx+1)-1); |
1753 work[k] = tmp; | |
1754 for (octave_idx_type i = cidx(iidx); | |
1755 i < cidx(iidx+1)-1; i++) | |
1756 { | |
1757 octave_idx_type idx2 = ridx(i); | |
1758 work[idx2] = work[idx2] - tmp * data(i); | |
1759 } | |
5164 | 1760 } |
1761 } | |
5681 | 1762 double atmp = 0; |
1763 for (octave_idx_type i = 0; i < j+1; i++) | |
1764 { | |
1765 atmp += fabs(work[i]); | |
1766 work[i] = 0.; | |
1767 } | |
1768 if (atmp > ainvnorm) | |
1769 ainvnorm = atmp; | |
5164 | 1770 } |
5681 | 1771 rcond = 1. / ainvnorm / anorm; |
5164 | 1772 } |
1773 } | |
1774 else | |
1775 { | |
5630 | 1776 OCTAVE_LOCAL_BUFFER (double, work, nm); |
1777 retval.resize (nc, b_nc); | |
1778 | |
1779 for (octave_idx_type j = 0; j < b_nc; j++) | |
5164 | 1780 { |
5630 | 1781 for (octave_idx_type i = 0; i < nr; i++) |
1782 work[i] = b(i,j); | |
1783 for (octave_idx_type i = nr; i < nc; i++) | |
1784 work[i] = 0.; | |
1785 | |
1786 for (octave_idx_type k = nc-1; k >= 0; k--) | |
5164 | 1787 { |
5630 | 1788 if (work[k] != 0.) |
5164 | 1789 { |
5681 | 1790 if (ridx(cidx(k+1)-1) != k || |
1791 data(cidx(k+1)-1) == 0.) | |
5164 | 1792 { |
1793 err = -2; | |
1794 goto triangular_error; | |
1795 } | |
1796 | |
5630 | 1797 double tmp = work[k] / data(cidx(k+1)-1); |
1798 work[k] = tmp; | |
5275 | 1799 for (octave_idx_type i = cidx(k); i < cidx(k+1)-1; i++) |
5164 | 1800 { |
5275 | 1801 octave_idx_type iidx = ridx(i); |
5630 | 1802 work[iidx] = work[iidx] - tmp * data(i); |
5164 | 1803 } |
1804 } | |
1805 } | |
5630 | 1806 |
1807 for (octave_idx_type i = 0; i < nc; i++) | |
1808 retval.xelem (i, j) = work[i]; | |
5164 | 1809 } |
1810 | |
5681 | 1811 if (calc_cond) |
1812 { | |
1813 // Calculation of 1-norm of inv(*this) | |
1814 for (octave_idx_type i = 0; i < nm; i++) | |
1815 work[i] = 0.; | |
1816 | |
1817 for (octave_idx_type j = 0; j < nr; j++) | |
5164 | 1818 { |
5681 | 1819 work[j] = 1.; |
1820 | |
1821 for (octave_idx_type k = j; k >= 0; k--) | |
5164 | 1822 { |
5681 | 1823 if (work[k] != 0.) |
5164 | 1824 { |
5681 | 1825 double tmp = work[k] / data(cidx(k+1)-1); |
1826 work[k] = tmp; | |
1827 for (octave_idx_type i = cidx(k); i < cidx(k+1)-1; i++) | |
1828 { | |
1829 octave_idx_type iidx = ridx(i); | |
1830 work[iidx] = work[iidx] - tmp * data(i); | |
1831 } | |
5164 | 1832 } |
1833 } | |
5681 | 1834 double atmp = 0; |
1835 for (octave_idx_type i = 0; i < j+1; i++) | |
1836 { | |
1837 atmp += fabs(work[i]); | |
1838 work[i] = 0.; | |
1839 } | |
1840 if (atmp > ainvnorm) | |
1841 ainvnorm = atmp; | |
5164 | 1842 } |
5681 | 1843 rcond = 1. / ainvnorm / anorm; |
1844 } | |
1845 } | |
5164 | 1846 |
1847 triangular_error: | |
1848 if (err != 0) | |
1849 { | |
1850 if (sing_handler) | |
5681 | 1851 { |
1852 sing_handler (rcond); | |
1853 mattype.mark_as_rectangular (); | |
1854 } | |
5164 | 1855 else |
1856 (*current_liboctave_error_handler) | |
1857 ("SparseMatrix::solve matrix singular to machine precision, rcond = %g", | |
1858 rcond); | |
1859 } | |
1860 | |
1861 volatile double rcond_plus_one = rcond + 1.0; | |
1862 | |
1863 if (rcond_plus_one == 1.0 || xisnan (rcond)) | |
1864 { | |
1865 err = -2; | |
1866 | |
1867 if (sing_handler) | |
5681 | 1868 { |
1869 sing_handler (rcond); | |
1870 mattype.mark_as_rectangular (); | |
1871 } | |
5164 | 1872 else |
1873 (*current_liboctave_error_handler) | |
1874 ("matrix singular to machine precision, rcond = %g", | |
1875 rcond); | |
1876 } | |
1877 } | |
1878 else | |
1879 (*current_liboctave_error_handler) ("incorrect matrix type"); | |
1880 } | |
1881 | |
1882 return retval; | |
1883 } | |
1884 | |
1885 SparseMatrix | |
5785 | 1886 SparseMatrix::utsolve (MatrixType &mattype, const SparseMatrix& b, |
5630 | 1887 octave_idx_type& err, double& rcond, |
5681 | 1888 solve_singularity_handler sing_handler, |
1889 bool calc_cond) const | |
5164 | 1890 { |
1891 SparseMatrix retval; | |
1892 | |
5275 | 1893 octave_idx_type nr = rows (); |
1894 octave_idx_type nc = cols (); | |
5630 | 1895 octave_idx_type nm = (nc > nr ? nc : nr); |
5164 | 1896 err = 0; |
1897 | |
6924 | 1898 if (nr != b.rows ()) |
5164 | 1899 (*current_liboctave_error_handler) |
1900 ("matrix dimension mismatch solution of linear equations"); | |
6924 | 1901 else if (nr == 0 || nc == 0 || b.cols () == 0) |
1902 retval = SparseMatrix (nc, b.cols ()); | |
5164 | 1903 else |
1904 { | |
1905 // Print spparms("spumoni") info if requested | |
1906 int typ = mattype.type (); | |
1907 mattype.info (); | |
1908 | |
5785 | 1909 if (typ == MatrixType::Permuted_Upper || |
1910 typ == MatrixType::Upper) | |
5164 | 1911 { |
1912 double anorm = 0.; | |
1913 double ainvnorm = 0.; | |
5681 | 1914 rcond = 1.; |
1915 | |
1916 if (calc_cond) | |
1917 { | |
1918 // Calculate the 1-norm of matrix for rcond calculation | |
1919 for (octave_idx_type j = 0; j < nc; j++) | |
1920 { | |
1921 double atmp = 0.; | |
1922 for (octave_idx_type i = cidx(j); i < cidx(j+1); i++) | |
1923 atmp += fabs(data(i)); | |
1924 if (atmp > anorm) | |
1925 anorm = atmp; | |
1926 } | |
5164 | 1927 } |
1928 | |
5275 | 1929 octave_idx_type b_nc = b.cols (); |
5681 | 1930 octave_idx_type b_nz = b.nnz (); |
5630 | 1931 retval = SparseMatrix (nc, b_nc, b_nz); |
5164 | 1932 retval.xcidx(0) = 0; |
5275 | 1933 octave_idx_type ii = 0; |
1934 octave_idx_type x_nz = b_nz; | |
5164 | 1935 |
5785 | 1936 if (typ == MatrixType::Permuted_Upper) |
5164 | 1937 { |
5322 | 1938 octave_idx_type *perm = mattype.triangular_perm (); |
5630 | 1939 OCTAVE_LOCAL_BUFFER (double, work, nm); |
1940 | |
1941 OCTAVE_LOCAL_BUFFER (octave_idx_type, rperm, nc); | |
1942 for (octave_idx_type i = 0; i < nc; i++) | |
5322 | 1943 rperm[perm[i]] = i; |
5164 | 1944 |
5275 | 1945 for (octave_idx_type j = 0; j < b_nc; j++) |
5164 | 1946 { |
5630 | 1947 for (octave_idx_type i = 0; i < nm; i++) |
5164 | 1948 work[i] = 0.; |
5275 | 1949 for (octave_idx_type i = b.cidx(j); i < b.cidx(j+1); i++) |
5164 | 1950 work[b.ridx(i)] = b.data(i); |
1951 | |
5630 | 1952 for (octave_idx_type k = nc-1; k >= 0; k--) |
5164 | 1953 { |
5322 | 1954 octave_idx_type kidx = perm[k]; |
1955 | |
1956 if (work[k] != 0.) | |
5164 | 1957 { |
5681 | 1958 if (ridx(cidx(kidx+1)-1) != k || |
1959 data(cidx(kidx+1)-1) == 0.) | |
5164 | 1960 { |
1961 err = -2; | |
1962 goto triangular_error; | |
1963 } | |
1964 | |
5322 | 1965 double tmp = work[k] / data(cidx(kidx+1)-1); |
1966 work[k] = tmp; | |
1967 for (octave_idx_type i = cidx(kidx); | |
1968 i < cidx(kidx+1)-1; i++) | |
5164 | 1969 { |
5322 | 1970 octave_idx_type iidx = ridx(i); |
1971 work[iidx] = work[iidx] - tmp * data(i); | |
5164 | 1972 } |
1973 } | |
1974 } | |
1975 | |
1976 // Count non-zeros in work vector and adjust space in | |
1977 // retval if needed | |
5275 | 1978 octave_idx_type new_nnz = 0; |
5630 | 1979 for (octave_idx_type i = 0; i < nc; i++) |
5164 | 1980 if (work[i] != 0.) |
1981 new_nnz++; | |
1982 | |
1983 if (ii + new_nnz > x_nz) | |
1984 { | |
1985 // Resize the sparse matrix | |
5275 | 1986 octave_idx_type sz = new_nnz * (b_nc - j) + x_nz; |
5164 | 1987 retval.change_capacity (sz); |
1988 x_nz = sz; | |
1989 } | |
1990 | |
5630 | 1991 for (octave_idx_type i = 0; i < nc; i++) |
5322 | 1992 if (work[rperm[i]] != 0.) |
5164 | 1993 { |
1994 retval.xridx(ii) = i; | |
5322 | 1995 retval.xdata(ii++) = work[rperm[i]]; |
5164 | 1996 } |
1997 retval.xcidx(j+1) = ii; | |
1998 } | |
1999 | |
2000 retval.maybe_compress (); | |
2001 | |
5681 | 2002 if (calc_cond) |
2003 { | |
2004 // Calculation of 1-norm of inv(*this) | |
2005 for (octave_idx_type i = 0; i < nm; i++) | |
2006 work[i] = 0.; | |
2007 | |
2008 for (octave_idx_type j = 0; j < nr; j++) | |
5164 | 2009 { |
5681 | 2010 work[j] = 1.; |
2011 | |
2012 for (octave_idx_type k = j; k >= 0; k--) | |
5164 | 2013 { |
5681 | 2014 octave_idx_type iidx = perm[k]; |
2015 | |
2016 if (work[k] != 0.) | |
5164 | 2017 { |
5681 | 2018 double tmp = work[k] / data(cidx(iidx+1)-1); |
2019 work[k] = tmp; | |
2020 for (octave_idx_type i = cidx(iidx); | |
2021 i < cidx(iidx+1)-1; i++) | |
2022 { | |
2023 octave_idx_type idx2 = ridx(i); | |
2024 work[idx2] = work[idx2] - tmp * data(i); | |
2025 } | |
5164 | 2026 } |
2027 } | |
5681 | 2028 double atmp = 0; |
2029 for (octave_idx_type i = 0; i < j+1; i++) | |
2030 { | |
2031 atmp += fabs(work[i]); | |
2032 work[i] = 0.; | |
2033 } | |
2034 if (atmp > ainvnorm) | |
2035 ainvnorm = atmp; | |
5164 | 2036 } |
5681 | 2037 rcond = 1. / ainvnorm / anorm; |
5164 | 2038 } |
2039 } | |
2040 else | |
2041 { | |
5630 | 2042 OCTAVE_LOCAL_BUFFER (double, work, nm); |
5164 | 2043 |
5275 | 2044 for (octave_idx_type j = 0; j < b_nc; j++) |
5164 | 2045 { |
5630 | 2046 for (octave_idx_type i = 0; i < nm; i++) |
5164 | 2047 work[i] = 0.; |
5275 | 2048 for (octave_idx_type i = b.cidx(j); i < b.cidx(j+1); i++) |
5164 | 2049 work[b.ridx(i)] = b.data(i); |
2050 | |
5630 | 2051 for (octave_idx_type k = nc-1; k >= 0; k--) |
5164 | 2052 { |
2053 if (work[k] != 0.) | |
2054 { | |
5681 | 2055 if (ridx(cidx(k+1)-1) != k || |
2056 data(cidx(k+1)-1) == 0.) | |
5164 | 2057 { |
2058 err = -2; | |
2059 goto triangular_error; | |
2060 } | |
2061 | |
2062 double tmp = work[k] / data(cidx(k+1)-1); | |
2063 work[k] = tmp; | |
5275 | 2064 for (octave_idx_type i = cidx(k); i < cidx(k+1)-1; i++) |
5164 | 2065 { |
5275 | 2066 octave_idx_type iidx = ridx(i); |
5164 | 2067 work[iidx] = work[iidx] - tmp * data(i); |
2068 } | |
2069 } | |
2070 } | |
2071 | |
2072 // Count non-zeros in work vector and adjust space in | |
2073 // retval if needed | |
5275 | 2074 octave_idx_type new_nnz = 0; |
5630 | 2075 for (octave_idx_type i = 0; i < nc; i++) |
5164 | 2076 if (work[i] != 0.) |
2077 new_nnz++; | |
2078 | |
2079 if (ii + new_nnz > x_nz) | |
2080 { | |
2081 // Resize the sparse matrix | |
5275 | 2082 octave_idx_type sz = new_nnz * (b_nc - j) + x_nz; |
5164 | 2083 retval.change_capacity (sz); |
2084 x_nz = sz; | |
2085 } | |
2086 | |
5630 | 2087 for (octave_idx_type i = 0; i < nc; i++) |
5164 | 2088 if (work[i] != 0.) |
2089 { | |
2090 retval.xridx(ii) = i; | |
2091 retval.xdata(ii++) = work[i]; | |
2092 } | |
2093 retval.xcidx(j+1) = ii; | |
2094 } | |
2095 | |
2096 retval.maybe_compress (); | |
2097 | |
5681 | 2098 if (calc_cond) |
2099 { | |
2100 // Calculation of 1-norm of inv(*this) | |
2101 for (octave_idx_type i = 0; i < nm; i++) | |
2102 work[i] = 0.; | |
2103 | |
2104 for (octave_idx_type j = 0; j < nr; j++) | |
5164 | 2105 { |
5681 | 2106 work[j] = 1.; |
2107 | |
2108 for (octave_idx_type k = j; k >= 0; k--) | |
5164 | 2109 { |
5681 | 2110 if (work[k] != 0.) |
5164 | 2111 { |
5681 | 2112 double tmp = work[k] / data(cidx(k+1)-1); |
2113 work[k] = tmp; | |
2114 for (octave_idx_type i = cidx(k); | |
2115 i < cidx(k+1)-1; i++) | |
2116 { | |
2117 octave_idx_type iidx = ridx(i); | |
2118 work[iidx] = work[iidx] - tmp * data(i); | |
2119 } | |
5164 | 2120 } |
2121 } | |
5681 | 2122 double atmp = 0; |
2123 for (octave_idx_type i = 0; i < j+1; i++) | |
2124 { | |
2125 atmp += fabs(work[i]); | |
2126 work[i] = 0.; | |
2127 } | |
2128 if (atmp > ainvnorm) | |
2129 ainvnorm = atmp; | |
5164 | 2130 } |
5681 | 2131 rcond = 1. / ainvnorm / anorm; |
2132 } | |
2133 } | |
5164 | 2134 |
2135 triangular_error: | |
2136 if (err != 0) | |
2137 { | |
2138 if (sing_handler) | |
5681 | 2139 { |
2140 sing_handler (rcond); | |
2141 mattype.mark_as_rectangular (); | |
2142 } | |
5164 | 2143 else |
2144 (*current_liboctave_error_handler) | |
2145 ("SparseMatrix::solve matrix singular to machine precision, rcond = %g", | |
2146 rcond); | |
2147 } | |
2148 | |
2149 volatile double rcond_plus_one = rcond + 1.0; | |
2150 | |
2151 if (rcond_plus_one == 1.0 || xisnan (rcond)) | |
2152 { | |
2153 err = -2; | |
2154 | |
2155 if (sing_handler) | |
5681 | 2156 { |
2157 sing_handler (rcond); | |
2158 mattype.mark_as_rectangular (); | |
2159 } | |
5164 | 2160 else |
2161 (*current_liboctave_error_handler) | |
2162 ("matrix singular to machine precision, rcond = %g", | |
2163 rcond); | |
2164 } | |
2165 } | |
2166 else | |
2167 (*current_liboctave_error_handler) ("incorrect matrix type"); | |
2168 } | |
2169 return retval; | |
2170 } | |
2171 | |
2172 ComplexMatrix | |
5785 | 2173 SparseMatrix::utsolve (MatrixType &mattype, const ComplexMatrix& b, |
5630 | 2174 octave_idx_type& err, double& rcond, |
5681 | 2175 solve_singularity_handler sing_handler, |
2176 bool calc_cond) const | |
5164 | 2177 { |
2178 ComplexMatrix retval; | |
2179 | |
5275 | 2180 octave_idx_type nr = rows (); |
2181 octave_idx_type nc = cols (); | |
5630 | 2182 octave_idx_type nm = (nc > nr ? nc : nr); |
5164 | 2183 err = 0; |
2184 | |
6924 | 2185 if (nr != b.rows ()) |
5164 | 2186 (*current_liboctave_error_handler) |
2187 ("matrix dimension mismatch solution of linear equations"); | |
6924 | 2188 else if (nr == 0 || nc == 0 || b.cols () == 0) |
2189 retval = ComplexMatrix (nc, b.cols (), Complex (0.0, 0.0)); | |
5164 | 2190 else |
2191 { | |
2192 // Print spparms("spumoni") info if requested | |
2193 int typ = mattype.type (); | |
2194 mattype.info (); | |
2195 | |
5785 | 2196 if (typ == MatrixType::Permuted_Upper || |
2197 typ == MatrixType::Upper) | |
5164 | 2198 { |
2199 double anorm = 0.; | |
2200 double ainvnorm = 0.; | |
5275 | 2201 octave_idx_type b_nc = b.cols (); |
5681 | 2202 rcond = 1.; |
2203 | |
2204 if (calc_cond) | |
2205 { | |
2206 // Calculate the 1-norm of matrix for rcond calculation | |
2207 for (octave_idx_type j = 0; j < nc; j++) | |
2208 { | |
2209 double atmp = 0.; | |
2210 for (octave_idx_type i = cidx(j); i < cidx(j+1); i++) | |
2211 atmp += fabs(data(i)); | |
2212 if (atmp > anorm) | |
2213 anorm = atmp; | |
2214 } | |
5164 | 2215 } |
2216 | |
5785 | 2217 if (typ == MatrixType::Permuted_Upper) |
5164 | 2218 { |
5630 | 2219 retval.resize (nc, b_nc); |
5322 | 2220 octave_idx_type *perm = mattype.triangular_perm (); |
5630 | 2221 OCTAVE_LOCAL_BUFFER (Complex, cwork, nm); |
5164 | 2222 |
5275 | 2223 for (octave_idx_type j = 0; j < b_nc; j++) |
5164 | 2224 { |
5275 | 2225 for (octave_idx_type i = 0; i < nr; i++) |
5322 | 2226 cwork[i] = b(i,j); |
5630 | 2227 for (octave_idx_type i = nr; i < nc; i++) |
2228 cwork[i] = 0.; | |
2229 | |
2230 for (octave_idx_type k = nc-1; k >= 0; k--) | |
5164 | 2231 { |
5322 | 2232 octave_idx_type kidx = perm[k]; |
2233 | |
2234 if (cwork[k] != 0.) | |
5164 | 2235 { |
5681 | 2236 if (ridx(cidx(kidx+1)-1) != k || |
2237 data(cidx(kidx+1)-1) == 0.) | |
5164 | 2238 { |
2239 err = -2; | |
2240 goto triangular_error; | |
2241 } | |
2242 | |
5322 | 2243 Complex tmp = cwork[k] / data(cidx(kidx+1)-1); |
2244 cwork[k] = tmp; | |
2245 for (octave_idx_type i = cidx(kidx); | |
2246 i < cidx(kidx+1)-1; i++) | |
5164 | 2247 { |
5322 | 2248 octave_idx_type iidx = ridx(i); |
2249 cwork[iidx] = cwork[iidx] - tmp * data(i); | |
5164 | 2250 } |
2251 } | |
2252 } | |
2253 | |
5630 | 2254 for (octave_idx_type i = 0; i < nc; i++) |
2255 retval.xelem (perm[i], j) = cwork[i]; | |
5164 | 2256 } |
2257 | |
5681 | 2258 if (calc_cond) |
2259 { | |
2260 // Calculation of 1-norm of inv(*this) | |
2261 OCTAVE_LOCAL_BUFFER (double, work, nm); | |
2262 for (octave_idx_type i = 0; i < nm; i++) | |
2263 work[i] = 0.; | |
2264 | |
2265 for (octave_idx_type j = 0; j < nr; j++) | |
5164 | 2266 { |
5681 | 2267 work[j] = 1.; |
2268 | |
2269 for (octave_idx_type k = j; k >= 0; k--) | |
5164 | 2270 { |
5681 | 2271 octave_idx_type iidx = perm[k]; |
2272 | |
2273 if (work[k] != 0.) | |
5164 | 2274 { |
5681 | 2275 double tmp = work[k] / data(cidx(iidx+1)-1); |
2276 work[k] = tmp; | |
2277 for (octave_idx_type i = cidx(iidx); | |
2278 i < cidx(iidx+1)-1; i++) | |
2279 { | |
2280 octave_idx_type idx2 = ridx(i); | |
2281 work[idx2] = work[idx2] - tmp * data(i); | |
2282 } | |
5164 | 2283 } |
2284 } | |
5681 | 2285 double atmp = 0; |
2286 for (octave_idx_type i = 0; i < j+1; i++) | |
2287 { | |
2288 atmp += fabs(work[i]); | |
2289 work[i] = 0.; | |
2290 } | |
2291 if (atmp > ainvnorm) | |
2292 ainvnorm = atmp; | |
5164 | 2293 } |
5681 | 2294 rcond = 1. / ainvnorm / anorm; |
5164 | 2295 } |
2296 } | |
2297 else | |
2298 { | |
5630 | 2299 OCTAVE_LOCAL_BUFFER (Complex, cwork, nm); |
2300 retval.resize (nc, b_nc); | |
5164 | 2301 |
5275 | 2302 for (octave_idx_type j = 0; j < b_nc; j++) |
5164 | 2303 { |
5630 | 2304 for (octave_idx_type i = 0; i < nr; i++) |
2305 cwork[i] = b(i,j); | |
2306 for (octave_idx_type i = nr; i < nc; i++) | |
2307 cwork[i] = 0.; | |
2308 | |
2309 for (octave_idx_type k = nc-1; k >= 0; k--) | |
5164 | 2310 { |
5630 | 2311 if (cwork[k] != 0.) |
5164 | 2312 { |
5681 | 2313 if (ridx(cidx(k+1)-1) != k || |
2314 data(cidx(k+1)-1) == 0.) | |
5164 | 2315 { |
2316 err = -2; | |
2317 goto triangular_error; | |
2318 } | |
2319 | |
5630 | 2320 Complex tmp = cwork[k] / data(cidx(k+1)-1); |
2321 cwork[k] = tmp; | |
5275 | 2322 for (octave_idx_type i = cidx(k); i < cidx(k+1)-1; i++) |
5164 | 2323 { |
5275 | 2324 octave_idx_type iidx = ridx(i); |
5630 | 2325 cwork[iidx] = cwork[iidx] - tmp * data(i); |
5164 | 2326 } |
2327 } | |
2328 } | |
5630 | 2329 |
2330 for (octave_idx_type i = 0; i < nc; i++) | |
2331 retval.xelem (i, j) = cwork[i]; | |
5164 | 2332 } |
2333 | |
5681 | 2334 if (calc_cond) |
2335 { | |
2336 // Calculation of 1-norm of inv(*this) | |
2337 OCTAVE_LOCAL_BUFFER (double, work, nm); | |
2338 for (octave_idx_type i = 0; i < nm; i++) | |
2339 work[i] = 0.; | |
2340 | |
2341 for (octave_idx_type j = 0; j < nr; j++) | |
5164 | 2342 { |
5681 | 2343 work[j] = 1.; |
2344 | |
2345 for (octave_idx_type k = j; k >= 0; k--) | |
5164 | 2346 { |
5681 | 2347 if (work[k] != 0.) |
5164 | 2348 { |
5681 | 2349 double tmp = work[k] / data(cidx(k+1)-1); |
2350 work[k] = tmp; | |
2351 for (octave_idx_type i = cidx(k); | |
2352 i < cidx(k+1)-1; i++) | |
2353 { | |
2354 octave_idx_type iidx = ridx(i); | |
2355 work[iidx] = work[iidx] - tmp * data(i); | |
2356 } | |
5164 | 2357 } |
2358 } | |
5681 | 2359 double atmp = 0; |
2360 for (octave_idx_type i = 0; i < j+1; i++) | |
2361 { | |
2362 atmp += fabs(work[i]); | |
2363 work[i] = 0.; | |
2364 } | |
2365 if (atmp > ainvnorm) | |
2366 ainvnorm = atmp; | |
5164 | 2367 } |
5681 | 2368 rcond = 1. / ainvnorm / anorm; |
2369 } | |
2370 } | |
5164 | 2371 |
2372 triangular_error: | |
2373 if (err != 0) | |
2374 { | |
2375 if (sing_handler) | |
5681 | 2376 { |
2377 sing_handler (rcond); | |
2378 mattype.mark_as_rectangular (); | |
2379 } | |
5164 | 2380 else |
2381 (*current_liboctave_error_handler) | |
2382 ("SparseMatrix::solve matrix singular to machine precision, rcond = %g", | |
2383 rcond); | |
2384 } | |
2385 | |
2386 volatile double rcond_plus_one = rcond + 1.0; | |
2387 | |
2388 if (rcond_plus_one == 1.0 || xisnan (rcond)) | |
2389 { | |
2390 err = -2; | |
2391 | |
2392 if (sing_handler) | |
5681 | 2393 { |
2394 sing_handler (rcond); | |
2395 mattype.mark_as_rectangular (); | |
2396 } | |
5164 | 2397 else |
2398 (*current_liboctave_error_handler) | |
2399 ("matrix singular to machine precision, rcond = %g", | |
2400 rcond); | |
2401 } | |
2402 } | |
2403 else | |
2404 (*current_liboctave_error_handler) ("incorrect matrix type"); | |
2405 } | |
2406 | |
2407 return retval; | |
2408 } | |
2409 | |
2410 SparseComplexMatrix | |
5785 | 2411 SparseMatrix::utsolve (MatrixType &mattype, const SparseComplexMatrix& b, |
5630 | 2412 octave_idx_type& err, double& rcond, |
5681 | 2413 solve_singularity_handler sing_handler, |
2414 bool calc_cond) const | |
5164 | 2415 { |
2416 SparseComplexMatrix retval; | |
2417 | |
5275 | 2418 octave_idx_type nr = rows (); |
2419 octave_idx_type nc = cols (); | |
5630 | 2420 octave_idx_type nm = (nc > nr ? nc : nr); |
5164 | 2421 err = 0; |
2422 | |
6924 | 2423 if (nr != b.rows ()) |
5164 | 2424 (*current_liboctave_error_handler) |
2425 ("matrix dimension mismatch solution of linear equations"); | |
6924 | 2426 else if (nr == 0 || nc == 0 || b.cols () == 0) |
2427 retval = SparseComplexMatrix (nc, b.cols ()); | |
5164 | 2428 else |
2429 { | |
2430 // Print spparms("spumoni") info if requested | |
2431 int typ = mattype.type (); | |
2432 mattype.info (); | |
2433 | |
5785 | 2434 if (typ == MatrixType::Permuted_Upper || |
2435 typ == MatrixType::Upper) | |
5164 | 2436 { |
2437 double anorm = 0.; | |
2438 double ainvnorm = 0.; | |
5681 | 2439 rcond = 1.; |
2440 | |
2441 if (calc_cond) | |
2442 { | |
2443 // Calculate the 1-norm of matrix for rcond calculation | |
2444 for (octave_idx_type j = 0; j < nc; j++) | |
2445 { | |
2446 double atmp = 0.; | |
2447 for (octave_idx_type i = cidx(j); i < cidx(j+1); i++) | |
2448 atmp += fabs(data(i)); | |
2449 if (atmp > anorm) | |
2450 anorm = atmp; | |
2451 } | |
5164 | 2452 } |
2453 | |
5275 | 2454 octave_idx_type b_nc = b.cols (); |
5681 | 2455 octave_idx_type b_nz = b.nnz (); |
5630 | 2456 retval = SparseComplexMatrix (nc, b_nc, b_nz); |
5164 | 2457 retval.xcidx(0) = 0; |
5275 | 2458 octave_idx_type ii = 0; |
2459 octave_idx_type x_nz = b_nz; | |
5164 | 2460 |
5785 | 2461 if (typ == MatrixType::Permuted_Upper) |
5164 | 2462 { |
5322 | 2463 octave_idx_type *perm = mattype.triangular_perm (); |
5630 | 2464 OCTAVE_LOCAL_BUFFER (Complex, cwork, nm); |
2465 | |
2466 OCTAVE_LOCAL_BUFFER (octave_idx_type, rperm, nc); | |
2467 for (octave_idx_type i = 0; i < nc; i++) | |
5322 | 2468 rperm[perm[i]] = i; |
5164 | 2469 |
5275 | 2470 for (octave_idx_type j = 0; j < b_nc; j++) |
5164 | 2471 { |
5630 | 2472 for (octave_idx_type i = 0; i < nm; i++) |
5322 | 2473 cwork[i] = 0.; |
5275 | 2474 for (octave_idx_type i = b.cidx(j); i < b.cidx(j+1); i++) |
5322 | 2475 cwork[b.ridx(i)] = b.data(i); |
5164 | 2476 |
5630 | 2477 for (octave_idx_type k = nc-1; k >= 0; k--) |
5164 | 2478 { |
5322 | 2479 octave_idx_type kidx = perm[k]; |
2480 | |
2481 if (cwork[k] != 0.) | |
5164 | 2482 { |
5681 | 2483 if (ridx(cidx(kidx+1)-1) != k || |
2484 data(cidx(kidx+1)-1) == 0.) | |
5164 | 2485 { |
2486 err = -2; | |
2487 goto triangular_error; | |
2488 } | |
2489 | |
5322 | 2490 Complex tmp = cwork[k] / data(cidx(kidx+1)-1); |
2491 cwork[k] = tmp; | |
2492 for (octave_idx_type i = cidx(kidx); | |
2493 i < cidx(kidx+1)-1; i++) | |
5164 | 2494 { |
5322 | 2495 octave_idx_type iidx = ridx(i); |
2496 cwork[iidx] = cwork[iidx] - tmp * data(i); | |
5164 | 2497 } |
2498 } | |
2499 } | |
2500 | |
2501 // Count non-zeros in work vector and adjust space in | |
2502 // retval if needed | |
5275 | 2503 octave_idx_type new_nnz = 0; |
5630 | 2504 for (octave_idx_type i = 0; i < nc; i++) |
5322 | 2505 if (cwork[i] != 0.) |
5164 | 2506 new_nnz++; |
2507 | |
2508 if (ii + new_nnz > x_nz) | |
2509 { | |
2510 // Resize the sparse matrix | |
5275 | 2511 octave_idx_type sz = new_nnz * (b_nc - j) + x_nz; |
5164 | 2512 retval.change_capacity (sz); |
2513 x_nz = sz; | |
2514 } | |
2515 | |
5630 | 2516 for (octave_idx_type i = 0; i < nc; i++) |
5322 | 2517 if (cwork[rperm[i]] != 0.) |
5164 | 2518 { |
2519 retval.xridx(ii) = i; | |
5322 | 2520 retval.xdata(ii++) = cwork[rperm[i]]; |
5164 | 2521 } |
2522 retval.xcidx(j+1) = ii; | |
2523 } | |
2524 | |
2525 retval.maybe_compress (); | |
2526 | |
5681 | 2527 if (calc_cond) |
2528 { | |
2529 // Calculation of 1-norm of inv(*this) | |
2530 OCTAVE_LOCAL_BUFFER (double, work, nm); | |
2531 for (octave_idx_type i = 0; i < nm; i++) | |
2532 work[i] = 0.; | |
2533 | |
2534 for (octave_idx_type j = 0; j < nr; j++) | |
5164 | 2535 { |
5681 | 2536 work[j] = 1.; |
2537 | |
2538 for (octave_idx_type k = j; k >= 0; k--) | |
5164 | 2539 { |
5681 | 2540 octave_idx_type iidx = perm[k]; |
2541 | |
2542 if (work[k] != 0.) | |
5164 | 2543 { |
5681 | 2544 double tmp = work[k] / data(cidx(iidx+1)-1); |
2545 work[k] = tmp; | |
2546 for (octave_idx_type i = cidx(iidx); | |
2547 i < cidx(iidx+1)-1; i++) | |
2548 { | |
2549 octave_idx_type idx2 = ridx(i); | |
2550 work[idx2] = work[idx2] - tmp * data(i); | |
2551 } | |
5164 | 2552 } |
2553 } | |
5681 | 2554 double atmp = 0; |
2555 for (octave_idx_type i = 0; i < j+1; i++) | |
2556 { | |
2557 atmp += fabs(work[i]); | |
2558 work[i] = 0.; | |
2559 } | |
2560 if (atmp > ainvnorm) | |
2561 ainvnorm = atmp; | |
5164 | 2562 } |
5681 | 2563 rcond = 1. / ainvnorm / anorm; |
5164 | 2564 } |
2565 } | |
2566 else | |
2567 { | |
5630 | 2568 OCTAVE_LOCAL_BUFFER (Complex, cwork, nm); |
5164 | 2569 |
5275 | 2570 for (octave_idx_type j = 0; j < b_nc; j++) |
5164 | 2571 { |
5630 | 2572 for (octave_idx_type i = 0; i < nm; i++) |
2573 cwork[i] = 0.; | |
5275 | 2574 for (octave_idx_type i = b.cidx(j); i < b.cidx(j+1); i++) |
5630 | 2575 cwork[b.ridx(i)] = b.data(i); |
2576 | |
2577 for (octave_idx_type k = nc-1; k >= 0; k--) | |
5164 | 2578 { |
5630 | 2579 if (cwork[k] != 0.) |
5164 | 2580 { |
5681 | 2581 if (ridx(cidx(k+1)-1) != k || |
2582 data(cidx(k+1)-1) == 0.) | |
5164 | 2583 { |
2584 err = -2; | |
2585 goto triangular_error; | |
2586 } | |
2587 | |
5630 | 2588 Complex tmp = cwork[k] / data(cidx(k+1)-1); |
2589 cwork[k] = tmp; | |
5275 | 2590 for (octave_idx_type i = cidx(k); i < cidx(k+1)-1; i++) |
5164 | 2591 { |
5275 | 2592 octave_idx_type iidx = ridx(i); |
5630 | 2593 cwork[iidx] = cwork[iidx] - tmp * data(i); |
5164 | 2594 } |
2595 } | |
2596 } | |
2597 | |
2598 // Count non-zeros in work vector and adjust space in | |
2599 // retval if needed | |
5275 | 2600 octave_idx_type new_nnz = 0; |
5630 | 2601 for (octave_idx_type i = 0; i < nc; i++) |
2602 if (cwork[i] != 0.) | |
5164 | 2603 new_nnz++; |
2604 | |
2605 if (ii + new_nnz > x_nz) | |
2606 { | |
2607 // Resize the sparse matrix | |
5275 | 2608 octave_idx_type sz = new_nnz * (b_nc - j) + x_nz; |
5164 | 2609 retval.change_capacity (sz); |
2610 x_nz = sz; | |
2611 } | |
2612 | |
5630 | 2613 for (octave_idx_type i = 0; i < nc; i++) |
2614 if (cwork[i] != 0.) | |
5164 | 2615 { |
2616 retval.xridx(ii) = i; | |
5630 | 2617 retval.xdata(ii++) = cwork[i]; |
5164 | 2618 } |
2619 retval.xcidx(j+1) = ii; | |
2620 } | |
2621 | |
2622 retval.maybe_compress (); | |
2623 | |
5681 | 2624 if (calc_cond) |
2625 { | |
2626 // Calculation of 1-norm of inv(*this) | |
2627 OCTAVE_LOCAL_BUFFER (double, work, nm); | |
2628 for (octave_idx_type i = 0; i < nm; i++) | |
2629 work[i] = 0.; | |
2630 | |
2631 for (octave_idx_type j = 0; j < nr; j++) | |
5164 | 2632 { |
5681 | 2633 work[j] = 1.; |
2634 | |
2635 for (octave_idx_type k = j; k >= 0; k--) | |
5164 | 2636 { |
5681 | 2637 if (work[k] != 0.) |
5164 | 2638 { |
5681 | 2639 double tmp = work[k] / data(cidx(k+1)-1); |
2640 work[k] = tmp; | |
2641 for (octave_idx_type i = cidx(k); | |
2642 i < cidx(k+1)-1; i++) | |
2643 { | |
2644 octave_idx_type iidx = ridx(i); | |
2645 work[iidx] = work[iidx] - tmp * data(i); | |
2646 } | |
5164 | 2647 } |
2648 } | |
5681 | 2649 double atmp = 0; |
2650 for (octave_idx_type i = 0; i < j+1; i++) | |
2651 { | |
2652 atmp += fabs(work[i]); | |
2653 work[i] = 0.; | |
2654 } | |
2655 if (atmp > ainvnorm) | |
2656 ainvnorm = atmp; | |
5164 | 2657 } |
5681 | 2658 rcond = 1. / ainvnorm / anorm; |
2659 } | |
2660 } | |
5164 | 2661 |
2662 triangular_error: | |
2663 if (err != 0) | |
2664 { | |
2665 if (sing_handler) | |
5681 | 2666 { |
2667 sing_handler (rcond); | |
2668 mattype.mark_as_rectangular (); | |
2669 } | |
5164 | 2670 else |
2671 (*current_liboctave_error_handler) | |
2672 ("SparseMatrix::solve matrix singular to machine precision, rcond = %g", | |
2673 rcond); | |
2674 } | |
2675 | |
2676 volatile double rcond_plus_one = rcond + 1.0; | |
2677 | |
2678 if (rcond_plus_one == 1.0 || xisnan (rcond)) | |
2679 { | |
2680 err = -2; | |
2681 | |
2682 if (sing_handler) | |
5681 | 2683 { |
2684 sing_handler (rcond); | |
2685 mattype.mark_as_rectangular (); | |
2686 } | |
5164 | 2687 else |
2688 (*current_liboctave_error_handler) | |
2689 ("matrix singular to machine precision, rcond = %g", | |
2690 rcond); | |
2691 } | |
2692 } | |
2693 else | |
2694 (*current_liboctave_error_handler) ("incorrect matrix type"); | |
2695 } | |
2696 | |
2697 return retval; | |
2698 } | |
2699 | |
2700 Matrix | |
5785 | 2701 SparseMatrix::ltsolve (MatrixType &mattype, const Matrix& b, |
5630 | 2702 octave_idx_type& err, double& rcond, |
5681 | 2703 solve_singularity_handler sing_handler, |
2704 bool calc_cond) const | |
5164 | 2705 { |
2706 Matrix retval; | |
2707 | |
5275 | 2708 octave_idx_type nr = rows (); |
2709 octave_idx_type nc = cols (); | |
5630 | 2710 octave_idx_type nm = (nc > nr ? nc : nr); |
5164 | 2711 err = 0; |
2712 | |
6924 | 2713 if (nr != b.rows ()) |
5164 | 2714 (*current_liboctave_error_handler) |
2715 ("matrix dimension mismatch solution of linear equations"); | |
6924 | 2716 else if (nr == 0 || nc == 0 || b.cols () == 0) |
2717 retval = Matrix (nc, b.cols (), 0.0); | |
5164 | 2718 else |
2719 { | |
2720 // Print spparms("spumoni") info if requested | |
2721 int typ = mattype.type (); | |
2722 mattype.info (); | |
2723 | |
5785 | 2724 if (typ == MatrixType::Permuted_Lower || |
2725 typ == MatrixType::Lower) | |
5164 | 2726 { |
2727 double anorm = 0.; | |
2728 double ainvnorm = 0.; | |
5630 | 2729 octave_idx_type b_nc = b.cols (); |
5681 | 2730 rcond = 1.; |
2731 | |
2732 if (calc_cond) | |
2733 { | |
2734 // Calculate the 1-norm of matrix for rcond calculation | |
2735 for (octave_idx_type j = 0; j < nc; j++) | |
2736 { | |
2737 double atmp = 0.; | |
2738 for (octave_idx_type i = cidx(j); i < cidx(j+1); i++) | |
2739 atmp += fabs(data(i)); | |
2740 if (atmp > anorm) | |
2741 anorm = atmp; | |
2742 } | |
5164 | 2743 } |
2744 | |
5785 | 2745 if (typ == MatrixType::Permuted_Lower) |
5164 | 2746 { |
5630 | 2747 retval.resize (nc, b_nc); |
2748 OCTAVE_LOCAL_BUFFER (double, work, nm); | |
5322 | 2749 octave_idx_type *perm = mattype.triangular_perm (); |
5164 | 2750 |
5630 | 2751 for (octave_idx_type j = 0; j < b_nc; j++) |
5164 | 2752 { |
5630 | 2753 if (nc > nr) |
2754 for (octave_idx_type i = 0; i < nm; i++) | |
2755 work[i] = 0.; | |
5275 | 2756 for (octave_idx_type i = 0; i < nr; i++) |
5322 | 2757 work[perm[i]] = b(i,j); |
5164 | 2758 |
5630 | 2759 for (octave_idx_type k = 0; k < nc; k++) |
5164 | 2760 { |
5322 | 2761 if (work[k] != 0.) |
5164 | 2762 { |
5322 | 2763 octave_idx_type minr = nr; |
2764 octave_idx_type mini = 0; | |
2765 | |
2766 for (octave_idx_type i = cidx(k); i < cidx(k+1); i++) | |
2767 if (perm[ridx(i)] < minr) | |
2768 { | |
2769 minr = perm[ridx(i)]; | |
2770 mini = i; | |
2771 } | |
2772 | |
5681 | 2773 if (minr != k || data(mini) == 0) |
5164 | 2774 { |
2775 err = -2; | |
2776 goto triangular_error; | |
2777 } | |
2778 | |
5322 | 2779 double tmp = work[k] / data(mini); |
2780 work[k] = tmp; | |
2781 for (octave_idx_type i = cidx(k); i < cidx(k+1); i++) | |
5164 | 2782 { |
5322 | 2783 if (i == mini) |
2784 continue; | |
2785 | |
2786 octave_idx_type iidx = perm[ridx(i)]; | |
2787 work[iidx] = work[iidx] - tmp * data(i); | |
5164 | 2788 } |
2789 } | |
2790 } | |
2791 | |
5630 | 2792 for (octave_idx_type i = 0; i < nc; i++) |
5322 | 2793 retval (i, j) = work[i]; |
5164 | 2794 } |
2795 | |
5681 | 2796 if (calc_cond) |
2797 { | |
2798 // Calculation of 1-norm of inv(*this) | |
2799 for (octave_idx_type i = 0; i < nm; i++) | |
2800 work[i] = 0.; | |
2801 | |
2802 for (octave_idx_type j = 0; j < nr; j++) | |
5164 | 2803 { |
5681 | 2804 work[j] = 1.; |
2805 | |
2806 for (octave_idx_type k = 0; k < nc; k++) | |
5164 | 2807 { |
5681 | 2808 if (work[k] != 0.) |
5164 | 2809 { |
5681 | 2810 octave_idx_type minr = nr; |
2811 octave_idx_type mini = 0; | |
2812 | |
2813 for (octave_idx_type i = cidx(k); | |
2814 i < cidx(k+1); i++) | |
2815 if (perm[ridx(i)] < minr) | |
2816 { | |
2817 minr = perm[ridx(i)]; | |
2818 mini = i; | |
2819 } | |
2820 | |
2821 double tmp = work[k] / data(mini); | |
2822 work[k] = tmp; | |
2823 for (octave_idx_type i = cidx(k); | |
2824 i < cidx(k+1); i++) | |
2825 { | |
2826 if (i == mini) | |
2827 continue; | |
2828 | |
2829 octave_idx_type iidx = perm[ridx(i)]; | |
2830 work[iidx] = work[iidx] - tmp * data(i); | |
2831 } | |
5164 | 2832 } |
2833 } | |
5681 | 2834 |
2835 double atmp = 0; | |
2836 for (octave_idx_type i = j; i < nc; i++) | |
2837 { | |
2838 atmp += fabs(work[i]); | |
2839 work[i] = 0.; | |
2840 } | |
2841 if (atmp > ainvnorm) | |
2842 ainvnorm = atmp; | |
5164 | 2843 } |
5681 | 2844 rcond = 1. / ainvnorm / anorm; |
5164 | 2845 } |
2846 } | |
2847 else | |
2848 { | |
5630 | 2849 OCTAVE_LOCAL_BUFFER (double, work, nm); |
2850 retval.resize (nc, b_nc, 0.); | |
2851 | |
2852 for (octave_idx_type j = 0; j < b_nc; j++) | |
5164 | 2853 { |
5630 | 2854 for (octave_idx_type i = 0; i < nr; i++) |
2855 work[i] = b(i,j); | |
2856 for (octave_idx_type i = nr; i < nc; i++) | |
2857 work[i] = 0.; | |
2858 for (octave_idx_type k = 0; k < nc; k++) | |
5164 | 2859 { |
5630 | 2860 if (work[k] != 0.) |
5164 | 2861 { |
5681 | 2862 if (ridx(cidx(k)) != k || |
2863 data(cidx(k)) == 0.) | |
5164 | 2864 { |
2865 err = -2; | |
2866 goto triangular_error; | |
2867 } | |
2868 | |
5630 | 2869 double tmp = work[k] / data(cidx(k)); |
2870 work[k] = tmp; | |
2871 for (octave_idx_type i = cidx(k)+1; | |
2872 i < cidx(k+1); i++) | |
5164 | 2873 { |
5275 | 2874 octave_idx_type iidx = ridx(i); |
5630 | 2875 work[iidx] = work[iidx] - tmp * data(i); |
5164 | 2876 } |
2877 } | |
2878 } | |
5630 | 2879 |
2880 for (octave_idx_type i = 0; i < nc; i++) | |
2881 retval.xelem (i, j) = work[i]; | |
5164 | 2882 } |
2883 | |
5681 | 2884 if (calc_cond) |
2885 { | |
2886 // Calculation of 1-norm of inv(*this) | |
2887 for (octave_idx_type i = 0; i < nm; i++) | |
2888 work[i] = 0.; | |
2889 | |
2890 for (octave_idx_type j = 0; j < nr; j++) | |
5164 | 2891 { |
5681 | 2892 work[j] = 1.; |
2893 | |
2894 for (octave_idx_type k = j; k < nc; k++) | |
5164 | 2895 { |
5681 | 2896 |
2897 if (work[k] != 0.) | |
5164 | 2898 { |
5681 | 2899 double tmp = work[k] / data(cidx(k)); |
2900 work[k] = tmp; | |
2901 for (octave_idx_type i = cidx(k)+1; | |
2902 i < cidx(k+1); i++) | |
2903 { | |
2904 octave_idx_type iidx = ridx(i); | |
2905 work[iidx] = work[iidx] - tmp * data(i); | |
2906 } | |
5164 | 2907 } |
2908 } | |
5681 | 2909 double atmp = 0; |
2910 for (octave_idx_type i = j; i < nc; i++) | |
2911 { | |
2912 atmp += fabs(work[i]); | |
2913 work[i] = 0.; | |
2914 } | |
2915 if (atmp > ainvnorm) | |
2916 ainvnorm = atmp; | |
5164 | 2917 } |
5681 | 2918 rcond = 1. / ainvnorm / anorm; |
2919 } | |
2920 } | |
5164 | 2921 |
2922 triangular_error: | |
2923 if (err != 0) | |
2924 { | |
2925 if (sing_handler) | |
5681 | 2926 { |
2927 sing_handler (rcond); | |
2928 mattype.mark_as_rectangular (); | |
2929 } | |
5164 | 2930 else |
2931 (*current_liboctave_error_handler) | |
2932 ("SparseMatrix::solve matrix singular to machine precision, rcond = %g", | |
2933 rcond); | |
2934 } | |
2935 | |
2936 volatile double rcond_plus_one = rcond + 1.0; | |
2937 | |
2938 if (rcond_plus_one == 1.0 || xisnan (rcond)) | |
2939 { | |
2940 err = -2; | |
2941 | |
2942 if (sing_handler) | |
5681 | 2943 { |
2944 sing_handler (rcond); | |
2945 mattype.mark_as_rectangular (); | |
2946 } | |
5164 | 2947 else |
2948 (*current_liboctave_error_handler) | |
2949 ("matrix singular to machine precision, rcond = %g", | |
2950 rcond); | |
2951 } | |
2952 } | |
2953 else | |
2954 (*current_liboctave_error_handler) ("incorrect matrix type"); | |
2955 } | |
2956 | |
2957 return retval; | |
2958 } | |
2959 | |
2960 SparseMatrix | |
5785 | 2961 SparseMatrix::ltsolve (MatrixType &mattype, const SparseMatrix& b, |
5630 | 2962 octave_idx_type& err, double& rcond, |
5681 | 2963 solve_singularity_handler sing_handler, |
2964 bool calc_cond) const | |
5164 | 2965 { |
2966 SparseMatrix retval; | |
2967 | |
5275 | 2968 octave_idx_type nr = rows (); |
2969 octave_idx_type nc = cols (); | |
5630 | 2970 octave_idx_type nm = (nc > nr ? nc : nr); |
5164 | 2971 err = 0; |
2972 | |
6924 | 2973 if (nr != b.rows ()) |
5164 | 2974 (*current_liboctave_error_handler) |
2975 ("matrix dimension mismatch solution of linear equations"); | |
6924 | 2976 else if (nr == 0 || nc == 0 || b.cols () == 0) |
2977 retval = SparseMatrix (nc, b.cols ()); | |
5164 | 2978 else |
2979 { | |
2980 // Print spparms("spumoni") info if requested | |
2981 int typ = mattype.type (); | |
2982 mattype.info (); | |
2983 | |
5785 | 2984 if (typ == MatrixType::Permuted_Lower || |
2985 typ == MatrixType::Lower) | |
5164 | 2986 { |
2987 double anorm = 0.; | |
2988 double ainvnorm = 0.; | |
5681 | 2989 rcond = 1.; |
2990 | |
2991 if (calc_cond) | |
2992 { | |
2993 // Calculate the 1-norm of matrix for rcond calculation | |
2994 for (octave_idx_type j = 0; j < nc; j++) | |
2995 { | |
2996 double atmp = 0.; | |
2997 for (octave_idx_type i = cidx(j); i < cidx(j+1); i++) | |
2998 atmp += fabs(data(i)); | |
2999 if (atmp > anorm) | |
3000 anorm = atmp; | |
3001 } | |
3002 } | |
3003 | |
5275 | 3004 octave_idx_type b_nc = b.cols (); |
5681 | 3005 octave_idx_type b_nz = b.nnz (); |
3006 retval = SparseMatrix (nc, b_nc, b_nz); | |
5164 | 3007 retval.xcidx(0) = 0; |
5275 | 3008 octave_idx_type ii = 0; |
3009 octave_idx_type x_nz = b_nz; | |
5164 | 3010 |
5785 | 3011 if (typ == MatrixType::Permuted_Lower) |
5164 | 3012 { |
5681 | 3013 OCTAVE_LOCAL_BUFFER (double, work, nm); |
5322 | 3014 octave_idx_type *perm = mattype.triangular_perm (); |
5164 | 3015 |
5275 | 3016 for (octave_idx_type j = 0; j < b_nc; j++) |
5164 | 3017 { |
5630 | 3018 for (octave_idx_type i = 0; i < nm; i++) |
5164 | 3019 work[i] = 0.; |
5275 | 3020 for (octave_idx_type i = b.cidx(j); i < b.cidx(j+1); i++) |
5322 | 3021 work[perm[b.ridx(i)]] = b.data(i); |
5164 | 3022 |
5630 | 3023 for (octave_idx_type k = 0; k < nc; k++) |
5164 | 3024 { |
5322 | 3025 if (work[k] != 0.) |
5164 | 3026 { |
5322 | 3027 octave_idx_type minr = nr; |
3028 octave_idx_type mini = 0; | |
3029 | |
3030 for (octave_idx_type i = cidx(k); i < cidx(k+1); i++) | |
3031 if (perm[ridx(i)] < minr) | |
3032 { | |
3033 minr = perm[ridx(i)]; | |
3034 mini = i; | |
3035 } | |
3036 | |
5681 | 3037 if (minr != k || data(mini) == 0) |
5164 | 3038 { |
3039 err = -2; | |
3040 goto triangular_error; | |
3041 } | |
3042 | |
5322 | 3043 double tmp = work[k] / data(mini); |
3044 work[k] = tmp; | |
3045 for (octave_idx_type i = cidx(k); i < cidx(k+1); i++) | |
5164 | 3046 { |
5322 | 3047 if (i == mini) |
3048 continue; | |
3049 | |
3050 octave_idx_type iidx = perm[ridx(i)]; | |
3051 work[iidx] = work[iidx] - tmp * data(i); | |
5164 | 3052 } |
3053 } | |
3054 } | |
3055 | |
3056 // Count non-zeros in work vector and adjust space in | |
3057 // retval if needed | |
5275 | 3058 octave_idx_type new_nnz = 0; |
5630 | 3059 for (octave_idx_type i = 0; i < nc; i++) |
5164 | 3060 if (work[i] != 0.) |
3061 new_nnz++; | |
3062 | |
3063 if (ii + new_nnz > x_nz) | |
3064 { | |
3065 // Resize the sparse matrix | |
5275 | 3066 octave_idx_type sz = new_nnz * (b_nc - j) + x_nz; |
5164 | 3067 retval.change_capacity (sz); |
3068 x_nz = sz; | |
3069 } | |
3070 | |
5630 | 3071 for (octave_idx_type i = 0; i < nc; i++) |
5322 | 3072 if (work[i] != 0.) |
5164 | 3073 { |
3074 retval.xridx(ii) = i; | |
5322 | 3075 retval.xdata(ii++) = work[i]; |
5164 | 3076 } |
3077 retval.xcidx(j+1) = ii; | |
3078 } | |
3079 | |
3080 retval.maybe_compress (); | |
3081 | |
5681 | 3082 if (calc_cond) |
3083 { | |
3084 // Calculation of 1-norm of inv(*this) | |
3085 for (octave_idx_type i = 0; i < nm; i++) | |
3086 work[i] = 0.; | |
3087 | |
3088 for (octave_idx_type j = 0; j < nr; j++) | |
5164 | 3089 { |
5681 | 3090 work[j] = 1.; |
3091 | |
3092 for (octave_idx_type k = 0; k < nc; k++) | |
5164 | 3093 { |
5681 | 3094 if (work[k] != 0.) |
5164 | 3095 { |
5681 | 3096 octave_idx_type minr = nr; |
3097 octave_idx_type mini = 0; | |
3098 | |
3099 for (octave_idx_type i = cidx(k); | |
3100 i < cidx(k+1); i++) | |
3101 if (perm[ridx(i)] < minr) | |
3102 { | |
3103 minr = perm[ridx(i)]; | |
3104 mini = i; | |
3105 } | |
3106 | |
3107 double tmp = work[k] / data(mini); | |
3108 work[k] = tmp; | |
3109 for (octave_idx_type i = cidx(k); | |
3110 i < cidx(k+1); i++) | |
3111 { | |
3112 if (i == mini) | |
3113 continue; | |
3114 | |
3115 octave_idx_type iidx = perm[ridx(i)]; | |
3116 work[iidx] = work[iidx] - tmp * data(i); | |
3117 } | |
5164 | 3118 } |
3119 } | |
5681 | 3120 |
3121 double atmp = 0; | |
3122 for (octave_idx_type i = j; i < nr; i++) | |
3123 { | |
3124 atmp += fabs(work[i]); | |
3125 work[i] = 0.; | |
3126 } | |
3127 if (atmp > ainvnorm) | |
3128 ainvnorm = atmp; | |
5164 | 3129 } |
5681 | 3130 rcond = 1. / ainvnorm / anorm; |
5164 | 3131 } |
3132 } | |
3133 else | |
3134 { | |
5681 | 3135 OCTAVE_LOCAL_BUFFER (double, work, nm); |
5164 | 3136 |
5275 | 3137 for (octave_idx_type j = 0; j < b_nc; j++) |
5164 | 3138 { |
5630 | 3139 for (octave_idx_type i = 0; i < nm; i++) |
5164 | 3140 work[i] = 0.; |
5275 | 3141 for (octave_idx_type i = b.cidx(j); i < b.cidx(j+1); i++) |
5164 | 3142 work[b.ridx(i)] = b.data(i); |
3143 | |
5630 | 3144 for (octave_idx_type k = 0; k < nc; k++) |
5164 | 3145 { |
3146 if (work[k] != 0.) | |
3147 { | |
5681 | 3148 if (ridx(cidx(k)) != k || |
3149 data(cidx(k)) == 0.) | |
5164 | 3150 { |
3151 err = -2; | |
3152 goto triangular_error; | |
3153 } | |
3154 | |
3155 double tmp = work[k] / data(cidx(k)); | |
3156 work[k] = tmp; | |
5275 | 3157 for (octave_idx_type i = cidx(k)+1; i < cidx(k+1); i++) |
5164 | 3158 { |
5275 | 3159 octave_idx_type iidx = ridx(i); |
5164 | 3160 work[iidx] = work[iidx] - tmp * data(i); |
3161 } | |
3162 } | |
3163 } | |
3164 | |
3165 // Count non-zeros in work vector and adjust space in | |
3166 // retval if needed | |
5275 | 3167 octave_idx_type new_nnz = 0; |
5630 | 3168 for (octave_idx_type i = 0; i < nc; i++) |
5164 | 3169 if (work[i] != 0.) |
3170 new_nnz++; | |
3171 | |
3172 if (ii + new_nnz > x_nz) | |
3173 { | |
3174 // Resize the sparse matrix | |
5275 | 3175 octave_idx_type sz = new_nnz * (b_nc - j) + x_nz; |
5164 | 3176 retval.change_capacity (sz); |
3177 x_nz = sz; | |
3178 } | |
3179 | |
5630 | 3180 for (octave_idx_type i = 0; i < nc; i++) |
5164 | 3181 if (work[i] != 0.) |
3182 { | |
3183 retval.xridx(ii) = i; | |
3184 retval.xdata(ii++) = work[i]; | |
3185 } | |
3186 retval.xcidx(j+1) = ii; | |
3187 } | |
3188 | |
3189 retval.maybe_compress (); | |
3190 | |
5681 | 3191 if (calc_cond) |
3192 { | |
3193 // Calculation of 1-norm of inv(*this) | |
3194 for (octave_idx_type i = 0; i < nm; i++) | |
3195 work[i] = 0.; | |
3196 | |
3197 for (octave_idx_type j = 0; j < nr; j++) | |
5164 | 3198 { |
5681 | 3199 work[j] = 1.; |
3200 | |
3201 for (octave_idx_type k = j; k < nc; k++) | |
5164 | 3202 { |
5681 | 3203 |
3204 if (work[k] != 0.) | |
5164 | 3205 { |
5681 | 3206 double tmp = work[k] / data(cidx(k)); |
3207 work[k] = tmp; | |
3208 for (octave_idx_type i = cidx(k)+1; | |
3209 i < cidx(k+1); i++) | |
3210 { | |
3211 octave_idx_type iidx = ridx(i); | |
3212 work[iidx] = work[iidx] - tmp * data(i); | |
3213 } | |
5164 | 3214 } |
3215 } | |
5681 | 3216 double atmp = 0; |
3217 for (octave_idx_type i = j; i < nc; i++) | |
3218 { | |
3219 atmp += fabs(work[i]); | |
3220 work[i] = 0.; | |
3221 } | |
3222 if (atmp > ainvnorm) | |
3223 ainvnorm = atmp; | |
5164 | 3224 } |
5681 | 3225 rcond = 1. / ainvnorm / anorm; |
3226 } | |
3227 } | |
5164 | 3228 |
3229 triangular_error: | |
3230 if (err != 0) | |
3231 { | |
3232 if (sing_handler) | |
5681 | 3233 { |
3234 sing_handler (rcond); | |
3235 mattype.mark_as_rectangular (); | |
3236 } | |
5164 | 3237 else |
3238 (*current_liboctave_error_handler) | |
3239 ("SparseMatrix::solve matrix singular to machine precision, rcond = %g", | |
3240 rcond); | |
3241 } | |
3242 | |
3243 volatile double rcond_plus_one = rcond + 1.0; | |
3244 | |
3245 if (rcond_plus_one == 1.0 || xisnan (rcond)) | |
3246 { | |
3247 err = -2; | |
3248 | |
3249 if (sing_handler) | |
5681 | 3250 { |
3251 sing_handler (rcond); | |
3252 mattype.mark_as_rectangular (); | |
3253 } | |
5164 | 3254 else |
3255 (*current_liboctave_error_handler) | |
3256 ("matrix singular to machine precision, rcond = %g", | |
3257 rcond); | |
3258 } | |
3259 } | |
3260 else | |
3261 (*current_liboctave_error_handler) ("incorrect matrix type"); | |
3262 } | |
3263 | |
3264 return retval; | |
3265 } | |
3266 | |
3267 ComplexMatrix | |
5785 | 3268 SparseMatrix::ltsolve (MatrixType &mattype, const ComplexMatrix& b, |
5630 | 3269 octave_idx_type& err, double& rcond, |
5681 | 3270 solve_singularity_handler sing_handler, |
3271 bool calc_cond) const | |
5164 | 3272 { |
3273 ComplexMatrix retval; | |
3274 | |
5275 | 3275 octave_idx_type nr = rows (); |
3276 octave_idx_type nc = cols (); | |
5630 | 3277 octave_idx_type nm = (nc > nr ? nc : nr); |
5164 | 3278 err = 0; |
3279 | |
6924 | 3280 if (nr != b.rows ()) |
5164 | 3281 (*current_liboctave_error_handler) |
3282 ("matrix dimension mismatch solution of linear equations"); | |
6924 | 3283 else if (nr == 0 || nc == 0 || b.cols () == 0) |
3284 retval = ComplexMatrix (nc, b.cols (), Complex (0.0, 0.0)); | |
5164 | 3285 else |
3286 { | |
3287 // Print spparms("spumoni") info if requested | |
3288 int typ = mattype.type (); | |
3289 mattype.info (); | |
3290 | |
5785 | 3291 if (typ == MatrixType::Permuted_Lower || |
3292 typ == MatrixType::Lower) | |
5164 | 3293 { |
3294 double anorm = 0.; | |
3295 double ainvnorm = 0.; | |
5275 | 3296 octave_idx_type b_nc = b.cols (); |
5681 | 3297 rcond = 1.; |
3298 | |
3299 if (calc_cond) | |
3300 { | |
3301 // Calculate the 1-norm of matrix for rcond calculation | |
3302 for (octave_idx_type j = 0; j < nc; j++) | |
3303 { | |
3304 double atmp = 0.; | |
3305 for (octave_idx_type i = cidx(j); i < cidx(j+1); i++) | |
3306 atmp += fabs(data(i)); | |
3307 if (atmp > anorm) | |
3308 anorm = atmp; | |
3309 } | |
5164 | 3310 } |
3311 | |
5785 | 3312 if (typ == MatrixType::Permuted_Lower) |
5164 | 3313 { |
5630 | 3314 retval.resize (nc, b_nc); |
5681 | 3315 OCTAVE_LOCAL_BUFFER (Complex, cwork, nm); |
5322 | 3316 octave_idx_type *perm = mattype.triangular_perm (); |
5164 | 3317 |
5275 | 3318 for (octave_idx_type j = 0; j < b_nc; j++) |
5164 | 3319 { |
5630 | 3320 for (octave_idx_type i = 0; i < nm; i++) |
3321 cwork[i] = 0.; | |
5275 | 3322 for (octave_idx_type i = 0; i < nr; i++) |
5322 | 3323 cwork[perm[i]] = b(i,j); |
5164 | 3324 |
5630 | 3325 for (octave_idx_type k = 0; k < nc; k++) |
5164 | 3326 { |
5322 | 3327 if (cwork[k] != 0.) |
5164 | 3328 { |
5322 | 3329 octave_idx_type minr = nr; |
3330 octave_idx_type mini = 0; | |
3331 | |
3332 for (octave_idx_type i = cidx(k); i < cidx(k+1); i++) | |
3333 if (perm[ridx(i)] < minr) | |
3334 { | |
3335 minr = perm[ridx(i)]; | |
3336 mini = i; | |
3337 } | |
3338 | |
5681 | 3339 if (minr != k || data(mini) == 0) |
5164 | 3340 { |
3341 err = -2; | |
3342 goto triangular_error; | |
3343 } | |
3344 | |
5322 | 3345 Complex tmp = cwork[k] / data(mini); |
3346 cwork[k] = tmp; | |
3347 for (octave_idx_type i = cidx(k); i < cidx(k+1); i++) | |
5164 | 3348 { |
5322 | 3349 if (i == mini) |
3350 continue; | |
3351 | |
3352 octave_idx_type iidx = perm[ridx(i)]; | |
3353 cwork[iidx] = cwork[iidx] - tmp * data(i); | |
5164 | 3354 } |
3355 } | |
3356 } | |
3357 | |
5630 | 3358 for (octave_idx_type i = 0; i < nc; i++) |
5322 | 3359 retval (i, j) = cwork[i]; |
5164 | 3360 } |
3361 | |
5681 | 3362 if (calc_cond) |
3363 { | |
3364 // Calculation of 1-norm of inv(*this) | |
3365 OCTAVE_LOCAL_BUFFER (double, work, nm); | |
3366 for (octave_idx_type i = 0; i < nm; i++) | |
3367 work[i] = 0.; | |
3368 | |
3369 for (octave_idx_type j = 0; j < nr; j++) | |
5164 | 3370 { |
5681 | 3371 work[j] = 1.; |
3372 | |
3373 for (octave_idx_type k = 0; k < nc; k++) | |
5164 | 3374 { |
5681 | 3375 if (work[k] != 0.) |
5164 | 3376 { |
5681 | 3377 octave_idx_type minr = nr; |
3378 octave_idx_type mini = 0; | |
3379 | |
3380 for (octave_idx_type i = cidx(k); | |
3381 i < cidx(k+1); i++) | |
3382 if (perm[ridx(i)] < minr) | |
3383 { | |
3384 minr = perm[ridx(i)]; | |
3385 mini = i; | |
3386 } | |
3387 | |
3388 double tmp = work[k] / data(mini); | |
3389 work[k] = tmp; | |
3390 for (octave_idx_type i = cidx(k); | |
3391 i < cidx(k+1); i++) | |
3392 { | |
3393 if (i == mini) | |
3394 continue; | |
3395 | |
3396 octave_idx_type iidx = perm[ridx(i)]; | |
3397 work[iidx] = work[iidx] - tmp * data(i); | |
3398 } | |
5164 | 3399 } |
3400 } | |
5681 | 3401 |
3402 double atmp = 0; | |
3403 for (octave_idx_type i = j; i < nc; i++) | |
3404 { | |
3405 atmp += fabs(work[i]); | |
3406 work[i] = 0.; | |
3407 } | |
3408 if (atmp > ainvnorm) | |
3409 ainvnorm = atmp; | |
5164 | 3410 } |
5681 | 3411 rcond = 1. / ainvnorm / anorm; |
5164 | 3412 } |
3413 } | |
3414 else | |
3415 { | |
5630 | 3416 OCTAVE_LOCAL_BUFFER (Complex, cwork, nm); |
3417 retval.resize (nc, b_nc, 0.); | |
5164 | 3418 |
5275 | 3419 for (octave_idx_type j = 0; j < b_nc; j++) |
5164 | 3420 { |
5630 | 3421 for (octave_idx_type i = 0; i < nr; i++) |
3422 cwork[i] = b(i,j); | |
3423 for (octave_idx_type i = nr; i < nc; i++) | |
3424 cwork[i] = 0.; | |
3425 | |
3426 for (octave_idx_type k = 0; k < nc; k++) | |
5164 | 3427 { |
5630 | 3428 if (cwork[k] != 0.) |
5164 | 3429 { |
5681 | 3430 if (ridx(cidx(k)) != k || |
3431 data(cidx(k)) == 0.) | |
5164 | 3432 { |
3433 err = -2; | |
3434 goto triangular_error; | |
3435 } | |
3436 | |
5630 | 3437 Complex tmp = cwork[k] / data(cidx(k)); |
3438 cwork[k] = tmp; | |
5275 | 3439 for (octave_idx_type i = cidx(k)+1; i < cidx(k+1); i++) |
5164 | 3440 { |
5275 | 3441 octave_idx_type iidx = ridx(i); |
5630 | 3442 cwork[iidx] = cwork[iidx] - tmp * data(i); |
5164 | 3443 } |
3444 } | |
3445 } | |
5630 | 3446 |
3447 for (octave_idx_type i = 0; i < nc; i++) | |
3448 retval.xelem (i, j) = cwork[i]; | |
5164 | 3449 } |
3450 | |
5681 | 3451 if (calc_cond) |
3452 { | |
3453 // Calculation of 1-norm of inv(*this) | |
3454 OCTAVE_LOCAL_BUFFER (double, work, nm); | |
3455 for (octave_idx_type i = 0; i < nm; i++) | |
3456 work[i] = 0.; | |
3457 | |
3458 for (octave_idx_type j = 0; j < nr; j++) | |
5164 | 3459 { |
5681 | 3460 work[j] = 1.; |
3461 | |
3462 for (octave_idx_type k = j; k < nc; k++) | |
5164 | 3463 { |
5681 | 3464 |
3465 if (work[k] != 0.) | |
5164 | 3466 { |
5681 | 3467 double tmp = work[k] / data(cidx(k)); |
3468 work[k] = tmp; | |
3469 for (octave_idx_type i = cidx(k)+1; | |
3470 i < cidx(k+1); i++) | |
3471 { | |
3472 octave_idx_type iidx = ridx(i); | |
3473 work[iidx] = work[iidx] - tmp * data(i); | |
3474 } | |
5164 | 3475 } |
3476 } | |
5681 | 3477 double atmp = 0; |
3478 for (octave_idx_type i = j; i < nc; i++) | |
3479 { | |
3480 atmp += fabs(work[i]); | |
3481 work[i] = 0.; | |
3482 } | |
3483 if (atmp > ainvnorm) | |
3484 ainvnorm = atmp; | |
5164 | 3485 } |
5681 | 3486 rcond = 1. / ainvnorm / anorm; |
3487 } | |
3488 } | |
5164 | 3489 |
3490 triangular_error: | |
3491 if (err != 0) | |
3492 { | |
3493 if (sing_handler) | |
5681 | 3494 { |
3495 sing_handler (rcond); | |
3496 mattype.mark_as_rectangular (); | |
3497 } | |
5164 | 3498 else |
3499 (*current_liboctave_error_handler) | |
3500 ("SparseMatrix::solve matrix singular to machine precision, rcond = %g", | |
3501 rcond); | |
3502 } | |
3503 | |
3504 volatile double rcond_plus_one = rcond + 1.0; | |
3505 | |
3506 if (rcond_plus_one == 1.0 || xisnan (rcond)) | |
3507 { | |
3508 err = -2; | |
3509 | |
3510 if (sing_handler) | |
5681 | 3511 { |
3512 sing_handler (rcond); | |
3513 mattype.mark_as_rectangular (); | |
3514 } | |
5164 | 3515 else |
3516 (*current_liboctave_error_handler) | |
3517 ("matrix singular to machine precision, rcond = %g", | |
3518 rcond); | |
3519 } | |
3520 } | |
3521 else | |
3522 (*current_liboctave_error_handler) ("incorrect matrix type"); | |
3523 } | |
3524 | |
3525 return retval; | |
3526 } | |
3527 | |
3528 SparseComplexMatrix | |
5785 | 3529 SparseMatrix::ltsolve (MatrixType &mattype, const SparseComplexMatrix& b, |
5630 | 3530 octave_idx_type& err, double& rcond, |
5681 | 3531 solve_singularity_handler sing_handler, |
3532 bool calc_cond) const | |
5164 | 3533 { |
3534 SparseComplexMatrix retval; | |
3535 | |
5275 | 3536 octave_idx_type nr = rows (); |
3537 octave_idx_type nc = cols (); | |
5630 | 3538 octave_idx_type nm = (nc > nr ? nc : nr); |
5164 | 3539 err = 0; |
3540 | |
6924 | 3541 if (nr != b.rows ()) |
5164 | 3542 (*current_liboctave_error_handler) |
3543 ("matrix dimension mismatch solution of linear equations"); | |
6924 | 3544 else if (nr == 0 || nc == 0 || b.cols () == 0) |
3545 retval = SparseComplexMatrix (nc, b.cols ()); | |
5164 | 3546 else |
3547 { | |
3548 // Print spparms("spumoni") info if requested | |
3549 int typ = mattype.type (); | |
3550 mattype.info (); | |
3551 | |
5785 | 3552 if (typ == MatrixType::Permuted_Lower || |
3553 typ == MatrixType::Lower) | |
5164 | 3554 { |
3555 double anorm = 0.; | |
3556 double ainvnorm = 0.; | |
5681 | 3557 rcond = 1.; |
3558 | |
3559 if (calc_cond) | |
3560 { | |
3561 // Calculate the 1-norm of matrix for rcond calculation | |
3562 for (octave_idx_type j = 0; j < nc; j++) | |
3563 { | |
3564 double atmp = 0.; | |
3565 for (octave_idx_type i = cidx(j); i < cidx(j+1); i++) | |
3566 atmp += fabs(data(i)); | |
3567 if (atmp > anorm) | |
3568 anorm = atmp; | |
3569 } | |
5164 | 3570 } |
3571 | |
5275 | 3572 octave_idx_type b_nc = b.cols (); |
5681 | 3573 octave_idx_type b_nz = b.nnz (); |
5630 | 3574 retval = SparseComplexMatrix (nc, b_nc, b_nz); |
5164 | 3575 retval.xcidx(0) = 0; |
5275 | 3576 octave_idx_type ii = 0; |
3577 octave_idx_type x_nz = b_nz; | |
5164 | 3578 |
5785 | 3579 if (typ == MatrixType::Permuted_Lower) |
5164 | 3580 { |
5630 | 3581 OCTAVE_LOCAL_BUFFER (Complex, cwork, nm); |
5322 | 3582 octave_idx_type *perm = mattype.triangular_perm (); |
5164 | 3583 |
5275 | 3584 for (octave_idx_type j = 0; j < b_nc; j++) |
5164 | 3585 { |
5630 | 3586 for (octave_idx_type i = 0; i < nm; i++) |
5322 | 3587 cwork[i] = 0.; |
5275 | 3588 for (octave_idx_type i = b.cidx(j); i < b.cidx(j+1); i++) |
5322 | 3589 cwork[perm[b.ridx(i)]] = b.data(i); |
5164 | 3590 |
5630 | 3591 for (octave_idx_type k = 0; k < nc; k++) |
5164 | 3592 { |
5322 | 3593 if (cwork[k] != 0.) |
5164 | 3594 { |
5322 | 3595 octave_idx_type minr = nr; |
3596 octave_idx_type mini = 0; | |
3597 | |
3598 for (octave_idx_type i = cidx(k); i < cidx(k+1); i++) | |
3599 if (perm[ridx(i)] < minr) | |
3600 { | |
3601 minr = perm[ridx(i)]; | |
3602 mini = i; | |
3603 } | |
3604 | |
5681 | 3605 if (minr != k || data(mini) == 0) |
5164 | 3606 { |
3607 err = -2; | |
3608 goto triangular_error; | |
3609 } | |
3610 | |
5322 | 3611 Complex tmp = cwork[k] / data(mini); |
3612 cwork[k] = tmp; | |
3613 for (octave_idx_type i = cidx(k); i < cidx(k+1); i++) | |
5164 | 3614 { |
5322 | 3615 if (i == mini) |
3616 continue; | |
3617 | |
3618 octave_idx_type iidx = perm[ridx(i)]; | |
3619 cwork[iidx] = cwork[iidx] - tmp * data(i); | |
5164 | 3620 } |
3621 } | |
3622 } | |
3623 | |
3624 // Count non-zeros in work vector and adjust space in | |
3625 // retval if needed | |
5275 | 3626 octave_idx_type new_nnz = 0; |
5630 | 3627 for (octave_idx_type i = 0; i < nc; i++) |
5322 | 3628 if (cwork[i] != 0.) |
5164 | 3629 new_nnz++; |
3630 | |
3631 if (ii + new_nnz > x_nz) | |
3632 { | |
3633 // Resize the sparse matrix | |
5275 | 3634 octave_idx_type sz = new_nnz * (b_nc - j) + x_nz; |
5164 | 3635 retval.change_capacity (sz); |
3636 x_nz = sz; | |
3637 } | |
3638 | |
5630 | 3639 for (octave_idx_type i = 0; i < nc; i++) |
5322 | 3640 if (cwork[i] != 0.) |
5164 | 3641 { |
3642 retval.xridx(ii) = i; | |
5322 | 3643 retval.xdata(ii++) = cwork[i]; |
5164 | 3644 } |
3645 retval.xcidx(j+1) = ii; | |
3646 } | |
3647 | |
3648 retval.maybe_compress (); | |
3649 | |
5681 | 3650 if (calc_cond) |
3651 { | |
3652 // Calculation of 1-norm of inv(*this) | |
3653 OCTAVE_LOCAL_BUFFER (double, work, nm); | |
3654 for (octave_idx_type i = 0; i < nm; i++) | |
3655 work[i] = 0.; | |
3656 | |
3657 for (octave_idx_type j = 0; j < nr; j++) | |
5164 | 3658 { |
5681 | 3659 work[j] = 1.; |
3660 | |
3661 for (octave_idx_type k = 0; k < nc; k++) | |
5164 | 3662 { |
5681 | 3663 if (work[k] != 0.) |
5164 | 3664 { |
5681 | 3665 octave_idx_type minr = nr; |
3666 octave_idx_type mini = 0; | |
3667 | |
3668 for (octave_idx_type i = cidx(k); | |
3669 i < cidx(k+1); i++) | |
3670 if (perm[ridx(i)] < minr) | |
3671 { | |
3672 minr = perm[ridx(i)]; | |
3673 mini = i; | |
3674 } | |
3675 | |
3676 double tmp = work[k] / data(mini); | |
3677 work[k] = tmp; | |
3678 for (octave_idx_type i = cidx(k); | |
3679 i < cidx(k+1); i++) | |
3680 { | |
3681 if (i == mini) | |
3682 continue; | |
3683 | |
3684 octave_idx_type iidx = perm[ridx(i)]; | |
3685 work[iidx] = work[iidx] - tmp * data(i); | |
3686 } | |
5164 | 3687 } |
3688 } | |
5681 | 3689 |
3690 double atmp = 0; | |
3691 for (octave_idx_type i = j; i < nc; i++) | |
3692 { | |
3693 atmp += fabs(work[i]); | |
3694 work[i] = 0.; | |
3695 } | |
3696 if (atmp > ainvnorm) | |
3697 ainvnorm = atmp; | |
5164 | 3698 } |
5681 | 3699 rcond = 1. / ainvnorm / anorm; |
5164 | 3700 } |
3701 } | |
3702 else | |
3703 { | |
5630 | 3704 OCTAVE_LOCAL_BUFFER (Complex, cwork, nm); |
5164 | 3705 |
5275 | 3706 for (octave_idx_type j = 0; j < b_nc; j++) |
5164 | 3707 { |
5630 | 3708 for (octave_idx_type i = 0; i < nm; i++) |
3709 cwork[i] = 0.; | |
5275 | 3710 for (octave_idx_type i = b.cidx(j); i < b.cidx(j+1); i++) |
5630 | 3711 cwork[b.ridx(i)] = b.data(i); |
3712 | |
3713 for (octave_idx_type k = 0; k < nc; k++) | |
5164 | 3714 { |
5630 | 3715 if (cwork[k] != 0.) |
5164 | 3716 { |
5681 | 3717 if (ridx(cidx(k)) != k || |
3718 data(cidx(k)) == 0.) | |
5164 | 3719 { |
3720 err = -2; | |
3721 goto triangular_error; | |
3722 } | |
3723 | |
5630 | 3724 Complex tmp = cwork[k] / data(cidx(k)); |
3725 cwork[k] = tmp; | |
5275 | 3726 for (octave_idx_type i = cidx(k)+1; i < cidx(k+1); i++) |
5164 | 3727 { |
5275 | 3728 octave_idx_type iidx = ridx(i); |
5630 | 3729 cwork[iidx] = cwork[iidx] - tmp * data(i); |
5164 | 3730 } |
3731 } | |
3732 } | |
3733 | |
3734 // Count non-zeros in work vector and adjust space in | |
3735 // retval if needed | |
5275 | 3736 octave_idx_type new_nnz = 0; |
5630 | 3737 for (octave_idx_type i = 0; i < nc; i++) |
3738 if (cwork[i] != 0.) | |
5164 | 3739 new_nnz++; |
3740 | |
3741 if (ii + new_nnz > x_nz) | |
3742 { | |
3743 // Resize the sparse matrix | |
5275 | 3744 octave_idx_type sz = new_nnz * (b_nc - j) + x_nz; |
5164 | 3745 retval.change_capacity (sz); |
3746 x_nz = sz; | |
3747 } | |
3748 | |
5630 | 3749 for (octave_idx_type i = 0; i < nc; i++) |
3750 if (cwork[i] != 0.) | |
5164 | 3751 { |
3752 retval.xridx(ii) = i; | |
5630 | 3753 retval.xdata(ii++) = cwork[i]; |
5164 | 3754 } |
3755 retval.xcidx(j+1) = ii; | |
3756 } | |
3757 | |
3758 retval.maybe_compress (); | |
3759 | |
5681 | 3760 if (calc_cond) |
3761 { | |
3762 // Calculation of 1-norm of inv(*this) | |
3763 OCTAVE_LOCAL_BUFFER (double, work, nm); | |
3764 for (octave_idx_type i = 0; i < nm; i++) | |
3765 work[i] = 0.; | |
3766 | |
3767 for (octave_idx_type j = 0; j < nr; j++) | |
5164 | 3768 { |
5681 | 3769 work[j] = 1.; |
3770 | |
3771 for (octave_idx_type k = j; k < nc; k++) | |
5164 | 3772 { |
5681 | 3773 |
3774 if (work[k] != 0.) | |
5164 | 3775 { |
5681 | 3776 double tmp = work[k] / data(cidx(k)); |
3777 work[k] = tmp; | |
3778 for (octave_idx_type i = cidx(k)+1; | |
3779 i < cidx(k+1); i++) | |
3780 { | |
3781 octave_idx_type iidx = ridx(i); | |
3782 work[iidx] = work[iidx] - tmp * data(i); | |
3783 } | |
5164 | 3784 } |
3785 } | |
5681 | 3786 double atmp = 0; |
3787 for (octave_idx_type i = j; i < nc; i++) | |
3788 { | |
3789 atmp += fabs(work[i]); | |
3790 work[i] = 0.; | |
3791 } | |
3792 if (atmp > ainvnorm) | |
3793 ainvnorm = atmp; | |
5164 | 3794 } |
5681 | 3795 rcond = 1. / ainvnorm / anorm; |
3796 } | |
3797 } | |
5164 | 3798 |
3799 triangular_error: | |
3800 if (err != 0) | |
3801 { | |
3802 if (sing_handler) | |
5681 | 3803 { |
3804 sing_handler (rcond); | |
3805 mattype.mark_as_rectangular (); | |
3806 } | |
5164 | 3807 else |
3808 (*current_liboctave_error_handler) | |
3809 ("SparseMatrix::solve matrix singular to machine precision, rcond = %g", | |
3810 rcond); | |
3811 } | |
3812 | |
3813 volatile double rcond_plus_one = rcond + 1.0; | |
3814 | |
3815 if (rcond_plus_one == 1.0 || xisnan (rcond)) | |
3816 { | |
3817 err = -2; | |
3818 | |
3819 if (sing_handler) | |
5681 | 3820 { |
3821 sing_handler (rcond); | |
3822 mattype.mark_as_rectangular (); | |
3823 } | |
5164 | 3824 else |
3825 (*current_liboctave_error_handler) | |
3826 ("matrix singular to machine precision, rcond = %g", | |
3827 rcond); | |
3828 } | |
3829 } | |
3830 else | |
3831 (*current_liboctave_error_handler) ("incorrect matrix type"); | |
3832 } | |
3833 | |
3834 return retval; | |
3835 } | |
3836 | |
3837 Matrix | |
5785 | 3838 SparseMatrix::trisolve (MatrixType &mattype, const Matrix& b, |
5681 | 3839 octave_idx_type& err, double& rcond, |
3840 solve_singularity_handler sing_handler, | |
3841 bool calc_cond) const | |
5164 | 3842 { |
3843 Matrix retval; | |
3844 | |
5275 | 3845 octave_idx_type nr = rows (); |
3846 octave_idx_type nc = cols (); | |
5164 | 3847 err = 0; |
3848 | |
6924 | 3849 if (nr != nc || nr != b.rows ()) |
5164 | 3850 (*current_liboctave_error_handler) |
3851 ("matrix dimension mismatch solution of linear equations"); | |
6924 | 3852 else if (nr == 0 || b.cols () == 0) |
3853 retval = Matrix (nc, b.cols (), 0.0); | |
5681 | 3854 else if (calc_cond) |
3855 (*current_liboctave_error_handler) | |
3856 ("calculation of condition number not implemented"); | |
5164 | 3857 else |
3858 { | |
3859 // Print spparms("spumoni") info if requested | |
3860 volatile int typ = mattype.type (); | |
3861 mattype.info (); | |
3862 | |
5785 | 3863 if (typ == MatrixType::Tridiagonal_Hermitian) |
5164 | 3864 { |
3865 OCTAVE_LOCAL_BUFFER (double, D, nr); | |
3866 OCTAVE_LOCAL_BUFFER (double, DL, nr - 1); | |
3867 | |
3868 if (mattype.is_dense ()) | |
3869 { | |
5275 | 3870 octave_idx_type ii = 0; |
3871 | |
3872 for (octave_idx_type j = 0; j < nc-1; j++) | |
5164 | 3873 { |
3874 D[j] = data(ii++); | |
3875 DL[j] = data(ii); | |
3876 ii += 2; | |
3877 } | |
3878 D[nc-1] = data(ii); | |
3879 } | |
3880 else | |
3881 { | |
3882 D[0] = 0.; | |
5275 | 3883 for (octave_idx_type i = 0; i < nr - 1; i++) |
5164 | 3884 { |
3885 D[i+1] = 0.; | |
3886 DL[i] = 0.; | |
3887 } | |
3888 | |
5275 | 3889 for (octave_idx_type j = 0; j < nc; j++) |
3890 for (octave_idx_type i = cidx(j); i < cidx(j+1); i++) | |
5164 | 3891 { |
3892 if (ridx(i) == j) | |
3893 D[j] = data(i); | |
3894 else if (ridx(i) == j + 1) | |
3895 DL[j] = data(i); | |
3896 } | |
3897 } | |
3898 | |
5275 | 3899 octave_idx_type b_nc = b.cols(); |
5164 | 3900 retval = b; |
3901 double *result = retval.fortran_vec (); | |
3902 | |
3903 F77_XFCN (dptsv, DPTSV, (nr, b_nc, D, DL, result, | |
3904 b.rows(), err)); | |
3905 | |
7482
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
3906 if (err != 0) |
5164 | 3907 { |
3908 err = 0; | |
3909 mattype.mark_as_unsymmetric (); | |
5785 | 3910 typ = MatrixType::Tridiagonal; |
5164 | 3911 } |
3912 else | |
3913 rcond = 1.; | |
3914 } | |
3915 | |
5785 | 3916 if (typ == MatrixType::Tridiagonal) |
5164 | 3917 { |
3918 OCTAVE_LOCAL_BUFFER (double, DU, nr - 1); | |
3919 OCTAVE_LOCAL_BUFFER (double, D, nr); | |
3920 OCTAVE_LOCAL_BUFFER (double, DL, nr - 1); | |
3921 | |
3922 if (mattype.is_dense ()) | |
3923 { | |
5275 | 3924 octave_idx_type ii = 0; |
3925 | |
3926 for (octave_idx_type j = 0; j < nc-1; j++) | |
5164 | 3927 { |
3928 D[j] = data(ii++); | |
3929 DL[j] = data(ii++); | |
3930 DU[j] = data(ii++); | |
3931 } | |
3932 D[nc-1] = data(ii); | |
3933 } | |
3934 else | |
3935 { | |
3936 D[0] = 0.; | |
5275 | 3937 for (octave_idx_type i = 0; i < nr - 1; i++) |
5164 | 3938 { |
3939 D[i+1] = 0.; | |
3940 DL[i] = 0.; | |
3941 DU[i] = 0.; | |
3942 } | |
3943 | |
5275 | 3944 for (octave_idx_type j = 0; j < nc; j++) |
3945 for (octave_idx_type i = cidx(j); i < cidx(j+1); i++) | |
5164 | 3946 { |
3947 if (ridx(i) == j) | |
3948 D[j] = data(i); | |
3949 else if (ridx(i) == j + 1) | |
3950 DL[j] = data(i); | |
3951 else if (ridx(i) == j - 1) | |
5322 | 3952 DU[j-1] = data(i); |
5164 | 3953 } |
3954 } | |
3955 | |
5275 | 3956 octave_idx_type b_nc = b.cols(); |
5164 | 3957 retval = b; |
3958 double *result = retval.fortran_vec (); | |
3959 | |
3960 F77_XFCN (dgtsv, DGTSV, (nr, b_nc, DL, D, DU, result, | |
3961 b.rows(), err)); | |
3962 | |
7482
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
3963 if (err != 0) |
5164 | 3964 { |
3965 rcond = 0.; | |
3966 err = -2; | |
3967 | |
3968 if (sing_handler) | |
5681 | 3969 { |
3970 sing_handler (rcond); | |
3971 mattype.mark_as_rectangular (); | |
3972 } | |
5164 | 3973 else |
3974 (*current_liboctave_error_handler) | |
3975 ("matrix singular to machine precision"); | |
3976 | |
3977 } | |
3978 else | |
3979 rcond = 1.; | |
3980 } | |
5785 | 3981 else if (typ != MatrixType::Tridiagonal_Hermitian) |
5164 | 3982 (*current_liboctave_error_handler) ("incorrect matrix type"); |
3983 } | |
3984 | |
3985 return retval; | |
3986 } | |
3987 | |
3988 SparseMatrix | |
5785 | 3989 SparseMatrix::trisolve (MatrixType &mattype, const SparseMatrix& b, |
5681 | 3990 octave_idx_type& err, double& rcond, |
3991 solve_singularity_handler sing_handler, | |
3992 bool calc_cond) const | |
5164 | 3993 { |
3994 SparseMatrix retval; | |
3995 | |
5275 | 3996 octave_idx_type nr = rows (); |
3997 octave_idx_type nc = cols (); | |
5164 | 3998 err = 0; |
3999 | |
6924 | 4000 if (nr != nc || nr != b.rows ()) |
5164 | 4001 (*current_liboctave_error_handler) |
4002 ("matrix dimension mismatch solution of linear equations"); | |
6924 | 4003 else if (nr == 0 || b.cols () == 0) |
4004 retval = SparseMatrix (nc, b.cols ()); | |
5681 | 4005 else if (calc_cond) |
4006 (*current_liboctave_error_handler) | |
4007 ("calculation of condition number not implemented"); | |
5164 | 4008 else |
4009 { | |
4010 // Print spparms("spumoni") info if requested | |
4011 int typ = mattype.type (); | |
4012 mattype.info (); | |
4013 | |
4014 // Note can't treat symmetric case as there is no dpttrf function | |
5785 | 4015 if (typ == MatrixType::Tridiagonal || |
4016 typ == MatrixType::Tridiagonal_Hermitian) | |
5164 | 4017 { |
4018 OCTAVE_LOCAL_BUFFER (double, DU2, nr - 2); | |
4019 OCTAVE_LOCAL_BUFFER (double, DU, nr - 1); | |
4020 OCTAVE_LOCAL_BUFFER (double, D, nr); | |
4021 OCTAVE_LOCAL_BUFFER (double, DL, nr - 1); | |
5275 | 4022 Array<octave_idx_type> ipvt (nr); |
4023 octave_idx_type *pipvt = ipvt.fortran_vec (); | |
5164 | 4024 |
4025 if (mattype.is_dense ()) | |
4026 { | |
5275 | 4027 octave_idx_type ii = 0; |
4028 | |
4029 for (octave_idx_type j = 0; j < nc-1; j++) | |
5164 | 4030 { |
4031 D[j] = data(ii++); | |
4032 DL[j] = data(ii++); | |
4033 DU[j] = data(ii++); | |
4034 } | |
4035 D[nc-1] = data(ii); | |
4036 } | |
4037 else | |
4038 { | |
4039 D[0] = 0.; | |
5275 | 4040 for (octave_idx_type i = 0; i < nr - 1; i++) |
5164 | 4041 { |
4042 D[i+1] = 0.; | |
4043 DL[i] = 0.; | |
4044 DU[i] = 0.; | |
4045 } | |
4046 | |
5275 | 4047 for (octave_idx_type j = 0; j < nc; j++) |
4048 for (octave_idx_type i = cidx(j); i < cidx(j+1); i++) | |
5164 | 4049 { |
4050 if (ridx(i) == j) | |
4051 D[j] = data(i); | |
4052 else if (ridx(i) == j + 1) | |
4053 DL[j] = data(i); | |
4054 else if (ridx(i) == j - 1) | |
5322 | 4055 DU[j-1] = data(i); |
5164 | 4056 } |
4057 } | |
4058 | |
4059 F77_XFCN (dgttrf, DGTTRF, (nr, DL, D, DU, DU2, pipvt, err)); | |
4060 | |
7482
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4061 if (err != 0) |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4062 { |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4063 rcond = 0.0; |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4064 err = -2; |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4065 |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4066 if (sing_handler) |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4067 { |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4068 sing_handler (rcond); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4069 mattype.mark_as_rectangular (); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4070 } |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4071 else |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4072 (*current_liboctave_error_handler) |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4073 ("matrix singular to machine precision"); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4074 |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4075 } |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4076 else |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4077 { |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4078 rcond = 1.0; |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4079 char job = 'N'; |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4080 volatile octave_idx_type x_nz = b.nnz (); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4081 octave_idx_type b_nc = b.cols (); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4082 retval = SparseMatrix (nr, b_nc, x_nz); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4083 retval.xcidx(0) = 0; |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4084 volatile octave_idx_type ii = 0; |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4085 |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4086 OCTAVE_LOCAL_BUFFER (double, work, nr); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4087 |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4088 for (volatile octave_idx_type j = 0; j < b_nc; j++) |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4089 { |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4090 for (octave_idx_type i = 0; i < nr; i++) |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4091 work[i] = 0.; |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4092 for (octave_idx_type i = b.cidx(j); i < b.cidx(j+1); i++) |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4093 work[b.ridx(i)] = b.data(i); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4094 |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4095 F77_XFCN (dgttrs, DGTTRS, |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4096 (F77_CONST_CHAR_ARG2 (&job, 1), |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4097 nr, 1, DL, D, DU, DU2, pipvt, |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4098 work, b.rows (), err |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4099 F77_CHAR_ARG_LEN (1))); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4100 |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4101 // Count non-zeros in work vector and adjust |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4102 // space in retval if needed |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4103 octave_idx_type new_nnz = 0; |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4104 for (octave_idx_type i = 0; i < nr; i++) |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4105 if (work[i] != 0.) |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4106 new_nnz++; |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4107 |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4108 if (ii + new_nnz > x_nz) |
5164 | 4109 { |
7482
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4110 // Resize the sparse matrix |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4111 octave_idx_type sz = new_nnz * (b_nc - j) + x_nz; |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4112 retval.change_capacity (sz); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4113 x_nz = sz; |
5164 | 4114 } |
4115 | |
7482
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4116 for (octave_idx_type i = 0; i < nr; i++) |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4117 if (work[i] != 0.) |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4118 { |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4119 retval.xridx(ii) = i; |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4120 retval.xdata(ii++) = work[i]; |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4121 } |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4122 retval.xcidx(j+1) = ii; |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4123 } |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4124 |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4125 retval.maybe_compress (); |
5164 | 4126 } |
4127 } | |
5785 | 4128 else if (typ != MatrixType::Tridiagonal_Hermitian) |
5164 | 4129 (*current_liboctave_error_handler) ("incorrect matrix type"); |
4130 } | |
4131 | |
4132 return retval; | |
4133 } | |
4134 | |
4135 ComplexMatrix | |
5785 | 4136 SparseMatrix::trisolve (MatrixType &mattype, const ComplexMatrix& b, |
5681 | 4137 octave_idx_type& err, double& rcond, |
4138 solve_singularity_handler sing_handler, | |
4139 bool calc_cond) const | |
5164 | 4140 { |
4141 ComplexMatrix retval; | |
4142 | |
5275 | 4143 octave_idx_type nr = rows (); |
4144 octave_idx_type nc = cols (); | |
5164 | 4145 err = 0; |
4146 | |
6924 | 4147 if (nr != nc || nr != b.rows ()) |
5164 | 4148 (*current_liboctave_error_handler) |
4149 ("matrix dimension mismatch solution of linear equations"); | |
6924 | 4150 else if (nr == 0 || b.cols () == 0) |
4151 retval = ComplexMatrix (nc, b.cols (), Complex (0.0, 0.0)); | |
5681 | 4152 else if (calc_cond) |
4153 (*current_liboctave_error_handler) | |
4154 ("calculation of condition number not implemented"); | |
5164 | 4155 else |
4156 { | |
4157 // Print spparms("spumoni") info if requested | |
4158 volatile int typ = mattype.type (); | |
4159 mattype.info (); | |
4160 | |
5785 | 4161 if (typ == MatrixType::Tridiagonal_Hermitian) |
5164 | 4162 { |
5322 | 4163 OCTAVE_LOCAL_BUFFER (double, D, nr); |
5164 | 4164 OCTAVE_LOCAL_BUFFER (Complex, DL, nr - 1); |
4165 | |
4166 if (mattype.is_dense ()) | |
4167 { | |
5275 | 4168 octave_idx_type ii = 0; |
4169 | |
4170 for (octave_idx_type j = 0; j < nc-1; j++) | |
5164 | 4171 { |
4172 D[j] = data(ii++); | |
4173 DL[j] = data(ii); | |
4174 ii += 2; | |
4175 } | |
4176 D[nc-1] = data(ii); | |
4177 } | |
4178 else | |
4179 { | |
4180 D[0] = 0.; | |
5275 | 4181 for (octave_idx_type i = 0; i < nr - 1; i++) |
5164 | 4182 { |
4183 D[i+1] = 0.; | |
4184 DL[i] = 0.; | |
4185 } | |
4186 | |
5275 | 4187 for (octave_idx_type j = 0; j < nc; j++) |
4188 for (octave_idx_type i = cidx(j); i < cidx(j+1); i++) | |
5164 | 4189 { |
4190 if (ridx(i) == j) | |
4191 D[j] = data(i); | |
4192 else if (ridx(i) == j + 1) | |
4193 DL[j] = data(i); | |
4194 } | |
4195 } | |
4196 | |
5275 | 4197 octave_idx_type b_nr = b.rows (); |
4198 octave_idx_type b_nc = b.cols(); | |
5164 | 4199 rcond = 1.; |
4200 | |
4201 retval = b; | |
4202 Complex *result = retval.fortran_vec (); | |
4203 | |
4204 F77_XFCN (zptsv, ZPTSV, (nr, b_nc, D, DL, result, | |
4205 b_nr, err)); | |
4206 | |
7482
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4207 if (err != 0) |
5164 | 4208 { |
4209 err = 0; | |
4210 mattype.mark_as_unsymmetric (); | |
5785 | 4211 typ = MatrixType::Tridiagonal; |
5164 | 4212 } |
4213 } | |
4214 | |
5785 | 4215 if (typ == MatrixType::Tridiagonal) |
5164 | 4216 { |
4217 OCTAVE_LOCAL_BUFFER (Complex, DU, nr - 1); | |
4218 OCTAVE_LOCAL_BUFFER (Complex, D, nr); | |
4219 OCTAVE_LOCAL_BUFFER (Complex, DL, nr - 1); | |
4220 | |
4221 if (mattype.is_dense ()) | |
4222 { | |
5275 | 4223 octave_idx_type ii = 0; |
4224 | |
4225 for (octave_idx_type j = 0; j < nc-1; j++) | |
5164 | 4226 { |
4227 D[j] = data(ii++); | |
4228 DL[j] = data(ii++); | |
4229 DU[j] = data(ii++); | |
4230 } | |
4231 D[nc-1] = data(ii); | |
4232 } | |
4233 else | |
4234 { | |
4235 D[0] = 0.; | |
5275 | 4236 for (octave_idx_type i = 0; i < nr - 1; i++) |
5164 | 4237 { |
4238 D[i+1] = 0.; | |
4239 DL[i] = 0.; | |
4240 DU[i] = 0.; | |
4241 } | |
4242 | |
5275 | 4243 for (octave_idx_type j = 0; j < nc; j++) |
4244 for (octave_idx_type i = cidx(j); i < cidx(j+1); i++) | |
5164 | 4245 { |
4246 if (ridx(i) == j) | |
4247 D[j] = data(i); | |
4248 else if (ridx(i) == j + 1) | |
4249 DL[j] = data(i); | |
4250 else if (ridx(i) == j - 1) | |
5322 | 4251 DU[j-1] = data(i); |
5164 | 4252 } |
4253 } | |
4254 | |
5275 | 4255 octave_idx_type b_nr = b.rows(); |
4256 octave_idx_type b_nc = b.cols(); | |
5164 | 4257 rcond = 1.; |
4258 | |
4259 retval = b; | |
4260 Complex *result = retval.fortran_vec (); | |
4261 | |
4262 F77_XFCN (zgtsv, ZGTSV, (nr, b_nc, DL, D, DU, result, | |
4263 b_nr, err)); | |
4264 | |
7482
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4265 if (err != 0) |
5164 | 4266 { |
4267 rcond = 0.; | |
4268 err = -2; | |
4269 | |
4270 if (sing_handler) | |
5681 | 4271 { |
4272 sing_handler (rcond); | |
4273 mattype.mark_as_rectangular (); | |
4274 } | |
5164 | 4275 else |
4276 (*current_liboctave_error_handler) | |
4277 ("matrix singular to machine precision"); | |
4278 } | |
4279 } | |
5785 | 4280 else if (typ != MatrixType::Tridiagonal_Hermitian) |
5164 | 4281 (*current_liboctave_error_handler) ("incorrect matrix type"); |
4282 } | |
4283 | |
4284 return retval; | |
4285 } | |
4286 | |
4287 SparseComplexMatrix | |
5785 | 4288 SparseMatrix::trisolve (MatrixType &mattype, const SparseComplexMatrix& b, |
5681 | 4289 octave_idx_type& err, double& rcond, |
4290 solve_singularity_handler sing_handler, | |
4291 bool calc_cond) const | |
5164 | 4292 { |
4293 SparseComplexMatrix retval; | |
4294 | |
5275 | 4295 octave_idx_type nr = rows (); |
4296 octave_idx_type nc = cols (); | |
5164 | 4297 err = 0; |
4298 | |
6924 | 4299 if (nr != nc || nr != b.rows ()) |
5164 | 4300 (*current_liboctave_error_handler) |
4301 ("matrix dimension mismatch solution of linear equations"); | |
6924 | 4302 else if (nr == 0 || b.cols () == 0) |
4303 retval = SparseComplexMatrix (nc, b.cols ()); | |
5681 | 4304 else if (calc_cond) |
4305 (*current_liboctave_error_handler) | |
4306 ("calculation of condition number not implemented"); | |
5164 | 4307 else |
4308 { | |
4309 // Print spparms("spumoni") info if requested | |
4310 int typ = mattype.type (); | |
4311 mattype.info (); | |
4312 | |
4313 // Note can't treat symmetric case as there is no dpttrf function | |
5785 | 4314 if (typ == MatrixType::Tridiagonal || |
4315 typ == MatrixType::Tridiagonal_Hermitian) | |
5164 | 4316 { |
4317 OCTAVE_LOCAL_BUFFER (double, DU2, nr - 2); | |
4318 OCTAVE_LOCAL_BUFFER (double, DU, nr - 1); | |
4319 OCTAVE_LOCAL_BUFFER (double, D, nr); | |
4320 OCTAVE_LOCAL_BUFFER (double, DL, nr - 1); | |
5275 | 4321 Array<octave_idx_type> ipvt (nr); |
4322 octave_idx_type *pipvt = ipvt.fortran_vec (); | |
5164 | 4323 |
4324 if (mattype.is_dense ()) | |
4325 { | |
5275 | 4326 octave_idx_type ii = 0; |
4327 | |
4328 for (octave_idx_type j = 0; j < nc-1; j++) | |
5164 | 4329 { |
4330 D[j] = data(ii++); | |
4331 DL[j] = data(ii++); | |
4332 DU[j] = data(ii++); | |
4333 } | |
4334 D[nc-1] = data(ii); | |
4335 } | |
4336 else | |
4337 { | |
4338 D[0] = 0.; | |
5275 | 4339 for (octave_idx_type i = 0; i < nr - 1; i++) |
5164 | 4340 { |
4341 D[i+1] = 0.; | |
4342 DL[i] = 0.; | |
4343 DU[i] = 0.; | |
4344 } | |
4345 | |
5275 | 4346 for (octave_idx_type j = 0; j < nc; j++) |
4347 for (octave_idx_type i = cidx(j); i < cidx(j+1); i++) | |
5164 | 4348 { |
4349 if (ridx(i) == j) | |
4350 D[j] = data(i); | |
4351 else if (ridx(i) == j + 1) | |
4352 DL[j] = data(i); | |
4353 else if (ridx(i) == j - 1) | |
5322 | 4354 DU[j-1] = data(i); |
5164 | 4355 } |
4356 } | |
4357 | |
4358 F77_XFCN (dgttrf, DGTTRF, (nr, DL, D, DU, DU2, pipvt, err)); | |
4359 | |
7482
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4360 if (err != 0) |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4361 { |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4362 rcond = 0.0; |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4363 err = -2; |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4364 |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4365 if (sing_handler) |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4366 { |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4367 sing_handler (rcond); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4368 mattype.mark_as_rectangular (); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4369 } |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4370 else |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4371 (*current_liboctave_error_handler) |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4372 ("matrix singular to machine precision"); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4373 } |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4374 else |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4375 { |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4376 rcond = 1.; |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4377 char job = 'N'; |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4378 octave_idx_type b_nr = b.rows (); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4379 octave_idx_type b_nc = b.cols (); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4380 OCTAVE_LOCAL_BUFFER (double, Bx, b_nr); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4381 OCTAVE_LOCAL_BUFFER (double, Bz, b_nr); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4382 |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4383 // Take a first guess that the number of non-zero terms |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4384 // will be as many as in b |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4385 volatile octave_idx_type x_nz = b.nnz (); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4386 volatile octave_idx_type ii = 0; |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4387 retval = SparseComplexMatrix (b_nr, b_nc, x_nz); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4388 |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4389 retval.xcidx(0) = 0; |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4390 for (volatile octave_idx_type j = 0; j < b_nc; j++) |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4391 { |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4392 |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4393 for (octave_idx_type i = 0; i < b_nr; i++) |
5681 | 4394 { |
7482
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4395 Complex c = b (i,j); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4396 Bx[i] = std::real (c); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4397 Bz[i] = std::imag (c); |
5681 | 4398 } |
7482
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4399 |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4400 F77_XFCN (dgttrs, DGTTRS, |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4401 (F77_CONST_CHAR_ARG2 (&job, 1), |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4402 nr, 1, DL, D, DU, DU2, pipvt, |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4403 Bx, b_nr, err |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4404 F77_CHAR_ARG_LEN (1))); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4405 |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4406 if (err != 0) |
5164 | 4407 { |
7482
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4408 (*current_liboctave_error_handler) |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4409 ("SparseMatrix::solve solve failed"); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4410 |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4411 err = -1; |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4412 break; |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4413 } |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4414 |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4415 F77_XFCN (dgttrs, DGTTRS, |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4416 (F77_CONST_CHAR_ARG2 (&job, 1), |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4417 nr, 1, DL, D, DU, DU2, pipvt, |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4418 Bz, b_nr, err |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4419 F77_CHAR_ARG_LEN (1))); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4420 |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4421 if (err != 0) |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4422 { |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4423 (*current_liboctave_error_handler) |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4424 ("SparseMatrix::solve solve failed"); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4425 |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4426 err = -1; |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4427 break; |
5164 | 4428 } |
4429 | |
7482
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4430 // Count non-zeros in work vector and adjust |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4431 // space in retval if needed |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4432 octave_idx_type new_nnz = 0; |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4433 for (octave_idx_type i = 0; i < nr; i++) |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4434 if (Bx[i] != 0. || Bz[i] != 0.) |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4435 new_nnz++; |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4436 |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4437 if (ii + new_nnz > x_nz) |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4438 { |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4439 // Resize the sparse matrix |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4440 octave_idx_type sz = new_nnz * (b_nc - j) + x_nz; |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4441 retval.change_capacity (sz); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4442 x_nz = sz; |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4443 } |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4444 |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4445 for (octave_idx_type i = 0; i < nr; i++) |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4446 if (Bx[i] != 0. || Bz[i] != 0.) |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4447 { |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4448 retval.xridx(ii) = i; |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4449 retval.xdata(ii++) = |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4450 Complex (Bx[i], Bz[i]); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4451 } |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4452 |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4453 retval.xcidx(j+1) = ii; |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4454 } |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4455 |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4456 retval.maybe_compress (); |
5164 | 4457 } |
4458 } | |
5785 | 4459 else if (typ != MatrixType::Tridiagonal_Hermitian) |
5164 | 4460 (*current_liboctave_error_handler) ("incorrect matrix type"); |
4461 } | |
4462 | |
4463 return retval; | |
4464 } | |
4465 | |
4466 Matrix | |
5785 | 4467 SparseMatrix::bsolve (MatrixType &mattype, const Matrix& b, |
5681 | 4468 octave_idx_type& err, double& rcond, |
4469 solve_singularity_handler sing_handler, | |
4470 bool calc_cond) const | |
5164 | 4471 { |
4472 Matrix retval; | |
4473 | |
5275 | 4474 octave_idx_type nr = rows (); |
4475 octave_idx_type nc = cols (); | |
5164 | 4476 err = 0; |
4477 | |
6924 | 4478 if (nr != nc || nr != b.rows ()) |
5164 | 4479 (*current_liboctave_error_handler) |
4480 ("matrix dimension mismatch solution of linear equations"); | |
6924 | 4481 else if (nr == 0 || b.cols () == 0) |
4482 retval = Matrix (nc, b.cols (), 0.0); | |
5164 | 4483 else |
4484 { | |
4485 // Print spparms("spumoni") info if requested | |
4486 volatile int typ = mattype.type (); | |
4487 mattype.info (); | |
4488 | |
5785 | 4489 if (typ == MatrixType::Banded_Hermitian) |
5164 | 4490 { |
5275 | 4491 octave_idx_type n_lower = mattype.nlower (); |
4492 octave_idx_type ldm = n_lower + 1; | |
5164 | 4493 Matrix m_band (ldm, nc); |
4494 double *tmp_data = m_band.fortran_vec (); | |
4495 | |
4496 if (! mattype.is_dense ()) | |
4497 { | |
5275 | 4498 octave_idx_type ii = 0; |
4499 | |
4500 for (octave_idx_type j = 0; j < ldm; j++) | |
4501 for (octave_idx_type i = 0; i < nc; i++) | |
5164 | 4502 tmp_data[ii++] = 0.; |
4503 } | |
4504 | |
5275 | 4505 for (octave_idx_type j = 0; j < nc; j++) |
4506 for (octave_idx_type i = cidx(j); i < cidx(j+1); i++) | |
5164 | 4507 { |
5275 | 4508 octave_idx_type ri = ridx (i); |
5164 | 4509 if (ri >= j) |
4510 m_band(ri - j, j) = data(i); | |
4511 } | |
4512 | |
4513 // Calculate the norm of the matrix, for later use. | |
5681 | 4514 double anorm; |
4515 if (calc_cond) | |
4516 anorm = m_band.abs().sum().row(0).max(); | |
5164 | 4517 |
4518 char job = 'L'; | |
4519 F77_XFCN (dpbtrf, DPBTRF, (F77_CONST_CHAR_ARG2 (&job, 1), | |
4520 nr, n_lower, tmp_data, ldm, err | |
4521 F77_CHAR_ARG_LEN (1))); | |
4522 | |
7482
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4523 if (err != 0) |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4524 { |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4525 // Matrix is not positive definite!! Fall through to |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4526 // unsymmetric banded solver. |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4527 mattype.mark_as_unsymmetric (); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4528 typ = MatrixType::Banded; |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4529 rcond = 0.0; |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4530 err = 0; |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4531 } |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4532 else |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4533 { |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4534 if (calc_cond) |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4535 { |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4536 Array<double> z (3 * nr); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4537 double *pz = z.fortran_vec (); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4538 Array<octave_idx_type> iz (nr); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4539 octave_idx_type *piz = iz.fortran_vec (); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4540 |
7776 | 4541 F77_XFCN (dpbcon, DPBCON, |
7482
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4542 (F77_CONST_CHAR_ARG2 (&job, 1), |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4543 nr, n_lower, tmp_data, ldm, |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4544 anorm, rcond, pz, piz, err |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4545 F77_CHAR_ARG_LEN (1))); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4546 |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4547 if (err != 0) |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4548 err = -2; |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4549 |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4550 volatile double rcond_plus_one = rcond + 1.0; |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4551 |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4552 if (rcond_plus_one == 1.0 || xisnan (rcond)) |
5681 | 4553 { |
7482
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4554 err = -2; |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4555 |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4556 if (sing_handler) |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4557 { |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4558 sing_handler (rcond); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4559 mattype.mark_as_rectangular (); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4560 } |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4561 else |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4562 (*current_liboctave_error_handler) |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4563 ("matrix singular to machine precision, rcond = %g", |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4564 rcond); |
5681 | 4565 } |
7482
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4566 } |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4567 else |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4568 rcond = 1.; |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4569 |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4570 if (err == 0) |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4571 { |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4572 retval = b; |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4573 double *result = retval.fortran_vec (); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4574 |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4575 octave_idx_type b_nc = b.cols (); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4576 |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4577 F77_XFCN (dpbtrs, DPBTRS, |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4578 (F77_CONST_CHAR_ARG2 (&job, 1), |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4579 nr, n_lower, b_nc, tmp_data, |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4580 ldm, result, b.rows(), err |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4581 F77_CHAR_ARG_LEN (1))); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4582 |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4583 if (err != 0) |
5681 | 4584 { |
7482
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4585 (*current_liboctave_error_handler) |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4586 ("SparseMatrix::solve solve failed"); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4587 err = -1; |
5164 | 4588 } |
4589 } | |
4590 } | |
4591 } | |
4592 | |
5785 | 4593 if (typ == MatrixType::Banded) |
5164 | 4594 { |
4595 // Create the storage for the banded form of the sparse matrix | |
6242 | 4596 octave_idx_type n_upper = mattype.nupper (); |
4597 octave_idx_type n_lower = mattype.nlower (); | |
4598 octave_idx_type ldm = n_upper + 2 * n_lower + 1; | |
5164 | 4599 |
4600 Matrix m_band (ldm, nc); | |
4601 double *tmp_data = m_band.fortran_vec (); | |
4602 | |
4603 if (! mattype.is_dense ()) | |
4604 { | |
5275 | 4605 octave_idx_type ii = 0; |
4606 | |
4607 for (octave_idx_type j = 0; j < ldm; j++) | |
4608 for (octave_idx_type i = 0; i < nc; i++) | |
5164 | 4609 tmp_data[ii++] = 0.; |
4610 } | |
4611 | |
5275 | 4612 for (octave_idx_type j = 0; j < nc; j++) |
4613 for (octave_idx_type i = cidx(j); i < cidx(j+1); i++) | |
5164 | 4614 m_band(ridx(i) - j + n_lower + n_upper, j) = data(i); |
4615 | |
5681 | 4616 // Calculate the norm of the matrix, for later use. |
4617 double anorm; | |
4618 if (calc_cond) | |
4619 { | |
4620 for (octave_idx_type j = 0; j < nr; j++) | |
4621 { | |
4622 double atmp = 0.; | |
4623 for (octave_idx_type i = cidx(j); i < cidx(j+1); i++) | |
4624 atmp += fabs(data(i)); | |
4625 if (atmp > anorm) | |
4626 anorm = atmp; | |
4627 } | |
4628 } | |
4629 | |
5275 | 4630 Array<octave_idx_type> ipvt (nr); |
4631 octave_idx_type *pipvt = ipvt.fortran_vec (); | |
5164 | 4632 |
4633 F77_XFCN (dgbtrf, DGBTRF, (nr, nr, n_lower, n_upper, tmp_data, | |
4634 ldm, pipvt, err)); | |
4635 | |
7482
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4636 // Throw-away extra info LAPACK gives so as to not |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4637 // change output. |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4638 if (err != 0) |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4639 { |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4640 err = -2; |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4641 rcond = 0.0; |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4642 |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4643 if (sing_handler) |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4644 { |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4645 sing_handler (rcond); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4646 mattype.mark_as_rectangular (); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4647 } |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4648 else |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4649 (*current_liboctave_error_handler) |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4650 ("matrix singular to machine precision"); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4651 |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4652 } |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4653 else |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4654 { |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4655 if (calc_cond) |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4656 { |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4657 char job = '1'; |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4658 Array<double> z (3 * nr); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4659 double *pz = z.fortran_vec (); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4660 Array<octave_idx_type> iz (nr); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4661 octave_idx_type *piz = iz.fortran_vec (); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4662 |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4663 F77_XFCN (dgbcon, DGBCON, |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4664 (F77_CONST_CHAR_ARG2 (&job, 1), |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4665 nc, n_lower, n_upper, tmp_data, ldm, pipvt, |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4666 anorm, rcond, pz, piz, err |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4667 F77_CHAR_ARG_LEN (1))); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4668 |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4669 if (err != 0) |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4670 err = -2; |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4671 |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4672 volatile double rcond_plus_one = rcond + 1.0; |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4673 |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4674 if (rcond_plus_one == 1.0 || xisnan (rcond)) |
5681 | 4675 { |
7482
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4676 err = -2; |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4677 |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4678 if (sing_handler) |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4679 { |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4680 sing_handler (rcond); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4681 mattype.mark_as_rectangular (); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4682 } |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4683 else |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4684 (*current_liboctave_error_handler) |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4685 ("matrix singular to machine precision, rcond = %g", |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4686 rcond); |
5681 | 4687 } |
7482
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4688 } |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4689 else |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4690 rcond = 1.; |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4691 |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4692 if (err == 0) |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4693 { |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4694 retval = b; |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4695 double *result = retval.fortran_vec (); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4696 |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4697 octave_idx_type b_nc = b.cols (); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4698 |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4699 char job = 'N'; |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4700 F77_XFCN (dgbtrs, DGBTRS, |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4701 (F77_CONST_CHAR_ARG2 (&job, 1), |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4702 nr, n_lower, n_upper, b_nc, tmp_data, |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4703 ldm, pipvt, result, b.rows(), err |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4704 F77_CHAR_ARG_LEN (1))); |
5164 | 4705 } |
4706 } | |
4707 } | |
5785 | 4708 else if (typ != MatrixType::Banded_Hermitian) |
5164 | 4709 (*current_liboctave_error_handler) ("incorrect matrix type"); |
4710 } | |
4711 | |
4712 return retval; | |
4713 } | |
4714 | |
4715 SparseMatrix | |
5785 | 4716 SparseMatrix::bsolve (MatrixType &mattype, const SparseMatrix& b, |
5681 | 4717 octave_idx_type& err, double& rcond, |
4718 solve_singularity_handler sing_handler, | |
4719 bool calc_cond) const | |
5164 | 4720 { |
4721 SparseMatrix retval; | |
4722 | |
5275 | 4723 octave_idx_type nr = rows (); |
4724 octave_idx_type nc = cols (); | |
5164 | 4725 err = 0; |
4726 | |
6924 | 4727 if (nr != nc || nr != b.rows ()) |
5164 | 4728 (*current_liboctave_error_handler) |
4729 ("matrix dimension mismatch solution of linear equations"); | |
6924 | 4730 else if (nr == 0 || b.cols () == 0) |
4731 retval = SparseMatrix (nc, b.cols ()); | |
5164 | 4732 else |
4733 { | |
4734 // Print spparms("spumoni") info if requested | |
4735 volatile int typ = mattype.type (); | |
4736 mattype.info (); | |
4737 | |
5785 | 4738 if (typ == MatrixType::Banded_Hermitian) |
5164 | 4739 { |
6242 | 4740 octave_idx_type n_lower = mattype.nlower (); |
4741 octave_idx_type ldm = n_lower + 1; | |
5164 | 4742 |
4743 Matrix m_band (ldm, nc); | |
4744 double *tmp_data = m_band.fortran_vec (); | |
4745 | |
4746 if (! mattype.is_dense ()) | |
4747 { | |
5275 | 4748 octave_idx_type ii = 0; |
4749 | |
4750 for (octave_idx_type j = 0; j < ldm; j++) | |
4751 for (octave_idx_type i = 0; i < nc; i++) | |
5164 | 4752 tmp_data[ii++] = 0.; |
4753 } | |
4754 | |
5275 | 4755 for (octave_idx_type j = 0; j < nc; j++) |
4756 for (octave_idx_type i = cidx(j); i < cidx(j+1); i++) | |
5164 | 4757 { |
5275 | 4758 octave_idx_type ri = ridx (i); |
5164 | 4759 if (ri >= j) |
4760 m_band(ri - j, j) = data(i); | |
4761 } | |
4762 | |
5681 | 4763 // Calculate the norm of the matrix, for later use. |
4764 double anorm; | |
4765 if (calc_cond) | |
4766 anorm = m_band.abs().sum().row(0).max(); | |
4767 | |
5164 | 4768 char job = 'L'; |
4769 F77_XFCN (dpbtrf, DPBTRF, (F77_CONST_CHAR_ARG2 (&job, 1), | |
4770 nr, n_lower, tmp_data, ldm, err | |
4771 F77_CHAR_ARG_LEN (1))); | |
4772 | |
7482
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4773 if (err != 0) |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4774 { |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4775 mattype.mark_as_unsymmetric (); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4776 typ = MatrixType::Banded; |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4777 rcond = 0.0; |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4778 err = 0; |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4779 } |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4780 else |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4781 { |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4782 if (calc_cond) |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4783 { |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4784 Array<double> z (3 * nr); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4785 double *pz = z.fortran_vec (); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4786 Array<octave_idx_type> iz (nr); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4787 octave_idx_type *piz = iz.fortran_vec (); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4788 |
7776 | 4789 F77_XFCN (dpbcon, DPBCON, |
7482
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4790 (F77_CONST_CHAR_ARG2 (&job, 1), |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4791 nr, n_lower, tmp_data, ldm, |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4792 anorm, rcond, pz, piz, err |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4793 F77_CHAR_ARG_LEN (1))); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4794 |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4795 if (err != 0) |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4796 err = -2; |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4797 |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4798 volatile double rcond_plus_one = rcond + 1.0; |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4799 |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4800 if (rcond_plus_one == 1.0 || xisnan (rcond)) |
5164 | 4801 { |
7482
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4802 err = -2; |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4803 |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4804 if (sing_handler) |
5681 | 4805 { |
7482
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4806 sing_handler (rcond); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4807 mattype.mark_as_rectangular (); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4808 } |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4809 else |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4810 (*current_liboctave_error_handler) |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4811 ("matrix singular to machine precision, rcond = %g", |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4812 rcond); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4813 } |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4814 } |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4815 else |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4816 rcond = 1.; |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4817 |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4818 if (err == 0) |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4819 { |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4820 octave_idx_type b_nr = b.rows (); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4821 octave_idx_type b_nc = b.cols (); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4822 OCTAVE_LOCAL_BUFFER (double, Bx, b_nr); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4823 |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4824 // Take a first guess that the number of non-zero terms |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4825 // will be as many as in b |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4826 volatile octave_idx_type x_nz = b.nnz (); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4827 volatile octave_idx_type ii = 0; |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4828 retval = SparseMatrix (b_nr, b_nc, x_nz); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4829 |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4830 retval.xcidx(0) = 0; |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4831 for (volatile octave_idx_type j = 0; j < b_nc; j++) |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4832 { |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4833 for (octave_idx_type i = 0; i < b_nr; i++) |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4834 Bx[i] = b.elem (i, j); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4835 |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4836 F77_XFCN (dpbtrs, DPBTRS, |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4837 (F77_CONST_CHAR_ARG2 (&job, 1), |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4838 nr, n_lower, 1, tmp_data, |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4839 ldm, Bx, b_nr, err |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4840 F77_CHAR_ARG_LEN (1))); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4841 |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4842 if (err != 0) |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4843 { |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4844 (*current_liboctave_error_handler) |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4845 ("SparseMatrix::solve solve failed"); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4846 err = -1; |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4847 break; |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4848 } |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4849 |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4850 for (octave_idx_type i = 0; i < b_nr; i++) |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4851 { |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4852 double tmp = Bx[i]; |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4853 if (tmp != 0.0) |
5681 | 4854 { |
7482
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4855 if (ii == x_nz) |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4856 { |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4857 // Resize the sparse matrix |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4858 octave_idx_type sz = x_nz * |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4859 (b_nc - j) / b_nc; |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4860 sz = (sz > 10 ? sz : 10) + x_nz; |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4861 retval.change_capacity (sz); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4862 x_nz = sz; |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4863 } |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4864 retval.xdata(ii) = tmp; |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4865 retval.xridx(ii++) = i; |
5681 | 4866 } |
5164 | 4867 } |
7482
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4868 retval.xcidx(j+1) = ii; |
5164 | 4869 } |
7482
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4870 |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4871 retval.maybe_compress (); |
5164 | 4872 } |
4873 } | |
4874 } | |
4875 | |
5785 | 4876 if (typ == MatrixType::Banded) |
5164 | 4877 { |
4878 // Create the storage for the banded form of the sparse matrix | |
5275 | 4879 octave_idx_type n_upper = mattype.nupper (); |
4880 octave_idx_type n_lower = mattype.nlower (); | |
4881 octave_idx_type ldm = n_upper + 2 * n_lower + 1; | |
5164 | 4882 |
4883 Matrix m_band (ldm, nc); | |
4884 double *tmp_data = m_band.fortran_vec (); | |
4885 | |
4886 if (! mattype.is_dense ()) | |
4887 { | |
5275 | 4888 octave_idx_type ii = 0; |
4889 | |
4890 for (octave_idx_type j = 0; j < ldm; j++) | |
4891 for (octave_idx_type i = 0; i < nc; i++) | |
5164 | 4892 tmp_data[ii++] = 0.; |
4893 } | |
4894 | |
5275 | 4895 for (octave_idx_type j = 0; j < nc; j++) |
4896 for (octave_idx_type i = cidx(j); i < cidx(j+1); i++) | |
5164 | 4897 m_band(ridx(i) - j + n_lower + n_upper, j) = data(i); |
4898 | |
5681 | 4899 // Calculate the norm of the matrix, for later use. |
4900 double anorm; | |
4901 if (calc_cond) | |
4902 { | |
4903 for (octave_idx_type j = 0; j < nr; j++) | |
4904 { | |
4905 double atmp = 0.; | |
4906 for (octave_idx_type i = cidx(j); i < cidx(j+1); i++) | |
4907 atmp += fabs(data(i)); | |
4908 if (atmp > anorm) | |
4909 anorm = atmp; | |
4910 } | |
4911 } | |
4912 | |
5275 | 4913 Array<octave_idx_type> ipvt (nr); |
4914 octave_idx_type *pipvt = ipvt.fortran_vec (); | |
5164 | 4915 |
4916 F77_XFCN (dgbtrf, DGBTRF, (nr, nr, n_lower, n_upper, tmp_data, | |
4917 ldm, pipvt, err)); | |
4918 | |
7482
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4919 if (err != 0) |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4920 { |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4921 err = -2; |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4922 rcond = 0.0; |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4923 |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4924 if (sing_handler) |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4925 { |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4926 sing_handler (rcond); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4927 mattype.mark_as_rectangular (); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4928 } |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4929 else |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4930 (*current_liboctave_error_handler) |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4931 ("matrix singular to machine precision"); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4932 |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4933 } |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4934 else |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4935 { |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4936 if (calc_cond) |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4937 { |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4938 char job = '1'; |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4939 Array<double> z (3 * nr); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4940 double *pz = z.fortran_vec (); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4941 Array<octave_idx_type> iz (nr); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4942 octave_idx_type *piz = iz.fortran_vec (); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4943 |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4944 F77_XFCN (dgbcon, DGBCON, |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4945 (F77_CONST_CHAR_ARG2 (&job, 1), |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4946 nc, n_lower, n_upper, tmp_data, ldm, pipvt, |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4947 anorm, rcond, pz, piz, err |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4948 F77_CHAR_ARG_LEN (1))); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4949 |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4950 if (err != 0) |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4951 err = -2; |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4952 |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4953 volatile double rcond_plus_one = rcond + 1.0; |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4954 |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4955 if (rcond_plus_one == 1.0 || xisnan (rcond)) |
5164 | 4956 { |
7482
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4957 err = -2; |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4958 |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4959 if (sing_handler) |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4960 { |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4961 sing_handler (rcond); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4962 mattype.mark_as_rectangular (); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4963 } |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4964 else |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4965 (*current_liboctave_error_handler) |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4966 ("matrix singular to machine precision, rcond = %g", |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4967 rcond); |
5681 | 4968 } |
7482
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4969 } |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4970 else |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4971 rcond = 1.; |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4972 |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4973 if (err == 0) |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4974 { |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4975 char job = 'N'; |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4976 volatile octave_idx_type x_nz = b.nnz (); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4977 octave_idx_type b_nc = b.cols (); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4978 retval = SparseMatrix (nr, b_nc, x_nz); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4979 retval.xcidx(0) = 0; |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4980 volatile octave_idx_type ii = 0; |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4981 |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4982 OCTAVE_LOCAL_BUFFER (double, work, nr); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4983 |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4984 for (volatile octave_idx_type j = 0; j < b_nc; j++) |
5681 | 4985 { |
7482
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4986 for (octave_idx_type i = 0; i < nr; i++) |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4987 work[i] = 0.; |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4988 for (octave_idx_type i = b.cidx(j); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4989 i < b.cidx(j+1); i++) |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4990 work[b.ridx(i)] = b.data(i); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4991 |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4992 F77_XFCN (dgbtrs, DGBTRS, |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4993 (F77_CONST_CHAR_ARG2 (&job, 1), |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4994 nr, n_lower, n_upper, 1, tmp_data, |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4995 ldm, pipvt, work, b.rows (), err |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4996 F77_CHAR_ARG_LEN (1))); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4997 |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4998 // Count non-zeros in work vector and adjust |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4999 // space in retval if needed |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5000 octave_idx_type new_nnz = 0; |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5001 for (octave_idx_type i = 0; i < nr; i++) |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5002 if (work[i] != 0.) |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5003 new_nnz++; |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5004 |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5005 if (ii + new_nnz > x_nz) |
5164 | 5006 { |
7482
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5007 // Resize the sparse matrix |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5008 octave_idx_type sz = new_nnz * (b_nc - j) + x_nz; |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5009 retval.change_capacity (sz); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5010 x_nz = sz; |
5164 | 5011 } |
5012 | |
7482
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5013 for (octave_idx_type i = 0; i < nr; i++) |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5014 if (work[i] != 0.) |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5015 { |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5016 retval.xridx(ii) = i; |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5017 retval.xdata(ii++) = work[i]; |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5018 } |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5019 retval.xcidx(j+1) = ii; |
5164 | 5020 } |
7482
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5021 |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5022 retval.maybe_compress (); |
5164 | 5023 } |
5024 } | |
5025 } | |
5785 | 5026 else if (typ != MatrixType::Banded_Hermitian) |
5164 | 5027 (*current_liboctave_error_handler) ("incorrect matrix type"); |
5028 } | |
5029 | |
5030 return retval; | |
5031 } | |
5032 | |
5033 ComplexMatrix | |
5785 | 5034 SparseMatrix::bsolve (MatrixType &mattype, const ComplexMatrix& b, |
5681 | 5035 octave_idx_type& err, double& rcond, |
5036 solve_singularity_handler sing_handler, | |
5037 bool calc_cond) const | |
5164 | 5038 { |
5039 ComplexMatrix retval; | |
5040 | |
5275 | 5041 octave_idx_type nr = rows (); |
5042 octave_idx_type nc = cols (); | |
5164 | 5043 err = 0; |
5044 | |
6924 | 5045 if (nr != nc || nr != b.rows ()) |
5164 | 5046 (*current_liboctave_error_handler) |
5047 ("matrix dimension mismatch solution of linear equations"); | |
6924 | 5048 else if (nr == 0 || b.cols () == 0) |
5049 retval = ComplexMatrix (nc, b.cols (), Complex (0.0, 0.0)); | |
5164 | 5050 else |
5051 { | |
5052 // Print spparms("spumoni") info if requested | |
5053 volatile int typ = mattype.type (); | |
5054 mattype.info (); | |
5055 | |
5785 | 5056 if (typ == MatrixType::Banded_Hermitian) |
5164 | 5057 { |
5275 | 5058 octave_idx_type n_lower = mattype.nlower (); |
5059 octave_idx_type ldm = n_lower + 1; | |
5164 | 5060 |
5061 Matrix m_band (ldm, nc); | |
5062 double *tmp_data = m_band.fortran_vec (); | |
5063 | |
5064 if (! mattype.is_dense ()) | |
5065 { | |
5275 | 5066 octave_idx_type ii = 0; |
5067 | |
5068 for (octave_idx_type j = 0; j < ldm; j++) | |
5069 for (octave_idx_type i = 0; i < nc; i++) | |
5164 | 5070 tmp_data[ii++] = 0.; |
5071 } | |
5072 | |
5275 | 5073 for (octave_idx_type j = 0; j < nc; j++) |
5074 for (octave_idx_type i = cidx(j); i < cidx(j+1); i++) | |
5164 | 5075 { |
5275 | 5076 octave_idx_type ri = ridx (i); |
5164 | 5077 if (ri >= j) |
5078 m_band(ri - j, j) = data(i); | |
5079 } | |
5080 | |
5681 | 5081 // Calculate the norm of the matrix, for later use. |
5082 double anorm; | |
5083 if (calc_cond) | |
5084 anorm = m_band.abs().sum().row(0).max(); | |
5085 | |
5164 | 5086 char job = 'L'; |
5087 F77_XFCN (dpbtrf, DPBTRF, (F77_CONST_CHAR_ARG2 (&job, 1), | |
5088 nr, n_lower, tmp_data, ldm, err | |
5089 F77_CHAR_ARG_LEN (1))); | |
5090 | |
7482
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5091 if (err != 0) |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5092 { |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5093 // Matrix is not positive definite!! Fall through to |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5094 // unsymmetric banded solver. |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5095 mattype.mark_as_unsymmetric (); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5096 typ = MatrixType::Banded; |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5097 rcond = 0.0; |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5098 err = 0; |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5099 } |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5100 else |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5101 { |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5102 if (calc_cond) |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5103 { |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5104 Array<double> z (3 * nr); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5105 double *pz = z.fortran_vec (); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5106 Array<octave_idx_type> iz (nr); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5107 octave_idx_type *piz = iz.fortran_vec (); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5108 |
7776 | 5109 F77_XFCN (dpbcon, DPBCON, |
7482
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5110 (F77_CONST_CHAR_ARG2 (&job, 1), |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5111 nr, n_lower, tmp_data, ldm, |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5112 anorm, rcond, pz, piz, err |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5113 F77_CHAR_ARG_LEN (1))); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5114 |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5115 if (err != 0) |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5116 err = -2; |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5117 |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5118 volatile double rcond_plus_one = rcond + 1.0; |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5119 |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5120 if (rcond_plus_one == 1.0 || xisnan (rcond)) |
5681 | 5121 { |
7482
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5122 err = -2; |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5123 |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5124 if (sing_handler) |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5125 { |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5126 sing_handler (rcond); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5127 mattype.mark_as_rectangular (); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5128 } |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5129 else |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5130 (*current_liboctave_error_handler) |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5131 ("matrix singular to machine precision, rcond = %g", |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5132 rcond); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5133 } |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5134 } |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5135 else |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5136 rcond = 1.; |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5137 |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5138 if (err == 0) |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5139 { |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5140 octave_idx_type b_nr = b.rows (); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5141 octave_idx_type b_nc = b.cols (); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5142 |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5143 OCTAVE_LOCAL_BUFFER (double, Bx, b_nr); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5144 OCTAVE_LOCAL_BUFFER (double, Bz, b_nr); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5145 |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5146 retval.resize (b_nr, b_nc); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5147 |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5148 for (volatile octave_idx_type j = 0; j < b_nc; j++) |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5149 { |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5150 for (octave_idx_type i = 0; i < b_nr; i++) |
5164 | 5151 { |
7482
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5152 Complex c = b (i,j); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5153 Bx[i] = std::real (c); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5154 Bz[i] = std::imag (c); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5155 } |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5156 |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5157 F77_XFCN (dpbtrs, DPBTRS, |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5158 (F77_CONST_CHAR_ARG2 (&job, 1), |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5159 nr, n_lower, 1, tmp_data, |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5160 ldm, Bx, b_nr, err |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5161 F77_CHAR_ARG_LEN (1))); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5162 |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5163 if (err != 0) |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5164 { |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5165 (*current_liboctave_error_handler) |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5166 ("SparseMatrix::solve solve failed"); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5167 err = -1; |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5168 break; |
5164 | 5169 } |
7482
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5170 |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5171 F77_XFCN (dpbtrs, DPBTRS, |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5172 (F77_CONST_CHAR_ARG2 (&job, 1), |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5173 nr, n_lower, 1, tmp_data, |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5174 ldm, Bz, b.rows(), err |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5175 F77_CHAR_ARG_LEN (1))); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5176 |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5177 if (err != 0) |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5178 { |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5179 (*current_liboctave_error_handler) |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5180 ("SparseMatrix::solve solve failed"); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5181 err = -1; |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5182 break; |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5183 } |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5184 |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5185 for (octave_idx_type i = 0; i < b_nr; i++) |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5186 retval (i, j) = Complex (Bx[i], Bz[i]); |
5164 | 5187 } |
5188 } | |
5189 } | |
5190 } | |
5191 | |
5785 | 5192 if (typ == MatrixType::Banded) |
5164 | 5193 { |
5194 // Create the storage for the banded form of the sparse matrix | |
6242 | 5195 octave_idx_type n_upper = mattype.nupper (); |
5196 octave_idx_type n_lower = mattype.nlower (); | |
5197 octave_idx_type ldm = n_upper + 2 * n_lower + 1; | |
5164 | 5198 |
5199 Matrix m_band (ldm, nc); | |
5200 double *tmp_data = m_band.fortran_vec (); | |
5201 | |
5202 if (! mattype.is_dense ()) | |
5203 { | |
5275 | 5204 octave_idx_type ii = 0; |
5205 | |
5206 for (octave_idx_type j = 0; j < ldm; j++) | |
5207 for (octave_idx_type i = 0; i < nc; i++) | |
5164 | 5208 tmp_data[ii++] = 0.; |
5209 } | |
5210 | |
5275 | 5211 for (octave_idx_type j = 0; j < nc; j++) |
5212 for (octave_idx_type i = cidx(j); i < cidx(j+1); i++) | |
5164 | 5213 m_band(ridx(i) - j + n_lower + n_upper, j) = data(i); |
5214 | |
5681 | 5215 // Calculate the norm of the matrix, for later use. |
5216 double anorm; | |
5217 if (calc_cond) | |
5218 { | |
5219 for (octave_idx_type j = 0; j < nr; j++) | |
5220 { | |
5221 double atmp = 0.; | |
5222 for (octave_idx_type i = cidx(j); i < cidx(j+1); i++) | |
5223 atmp += fabs(data(i)); | |
5224 if (atmp > anorm) | |
5225 anorm = atmp; | |
5226 } | |
5227 } | |
5228 | |
5275 | 5229 Array<octave_idx_type> ipvt (nr); |
5230 octave_idx_type *pipvt = ipvt.fortran_vec (); | |
5164 | 5231 |
5232 F77_XFCN (dgbtrf, DGBTRF, (nr, nr, n_lower, n_upper, tmp_data, | |
5233 ldm, pipvt, err)); | |
5234 | |
7482
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5235 if (err != 0) |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5236 { |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5237 err = -2; |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5238 rcond = 0.0; |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5239 |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5240 if (sing_handler) |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5241 { |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5242 sing_handler (rcond); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5243 mattype.mark_as_rectangular (); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5244 } |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5245 else |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5246 (*current_liboctave_error_handler) |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5247 ("matrix singular to machine precision"); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5248 |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5249 } |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5250 else |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5251 { |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5252 if (calc_cond) |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5253 { |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5254 char job = '1'; |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5255 Array<double> z (3 * nr); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5256 double *pz = z.fortran_vec (); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5257 Array<octave_idx_type> iz (nr); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5258 octave_idx_type *piz = iz.fortran_vec (); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5259 |
7776 | 5260 F77_XFCN (dpbcon, DPBCON, |
7482
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5261 (F77_CONST_CHAR_ARG2 (&job, 1), |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5262 nr, n_lower, tmp_data, ldm, |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5263 anorm, rcond, pz, piz, err |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5264 F77_CHAR_ARG_LEN (1))); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5265 |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5266 if (err != 0) |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5267 err = -2; |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5268 |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5269 volatile double rcond_plus_one = rcond + 1.0; |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5270 |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5271 if (rcond_plus_one == 1.0 || xisnan (rcond)) |
5164 | 5272 { |
7482
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5273 err = -2; |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5274 |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5275 if (sing_handler) |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5276 { |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5277 sing_handler (rcond); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5278 mattype.mark_as_rectangular (); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5279 } |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5280 else |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5281 (*current_liboctave_error_handler) |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5282 ("matrix singular to machine precision, rcond = %g", |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5283 rcond); |
5681 | 5284 } |
7482
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5285 } |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5286 else |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5287 rcond = 1.; |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5288 |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5289 if (err == 0) |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5290 { |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5291 char job = 'N'; |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5292 octave_idx_type b_nc = b.cols (); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5293 retval.resize (nr,b_nc); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5294 |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5295 OCTAVE_LOCAL_BUFFER (double, Bz, nr); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5296 OCTAVE_LOCAL_BUFFER (double, Bx, nr); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5297 |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5298 for (volatile octave_idx_type j = 0; j < b_nc; j++) |
5681 | 5299 { |
7482
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5300 for (octave_idx_type i = 0; i < nr; i++) |
5164 | 5301 { |
7482
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5302 Complex c = b (i, j); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5303 Bx[i] = std::real (c); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5304 Bz[i] = std::imag (c); |
5164 | 5305 } |
7482
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5306 |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5307 F77_XFCN (dgbtrs, DGBTRS, |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5308 (F77_CONST_CHAR_ARG2 (&job, 1), |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5309 nr, n_lower, n_upper, 1, tmp_data, |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5310 ldm, pipvt, Bx, b.rows (), err |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5311 F77_CHAR_ARG_LEN (1))); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5312 |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5313 F77_XFCN (dgbtrs, DGBTRS, |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5314 (F77_CONST_CHAR_ARG2 (&job, 1), |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5315 nr, n_lower, n_upper, 1, tmp_data, |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5316 ldm, pipvt, Bz, b.rows (), err |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5317 F77_CHAR_ARG_LEN (1))); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5318 |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5319 for (octave_idx_type i = 0; i < nr; i++) |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5320 retval (i, j) = Complex (Bx[i], Bz[i]); |
5164 | 5321 } |
5322 } | |
5323 } | |
5324 } | |
5785 | 5325 else if (typ != MatrixType::Banded_Hermitian) |
5164 | 5326 (*current_liboctave_error_handler) ("incorrect matrix type"); |
5327 } | |
5328 | |
5329 return retval; | |
5330 } | |
5331 | |
5332 SparseComplexMatrix | |
5785 | 5333 SparseMatrix::bsolve (MatrixType &mattype, const SparseComplexMatrix& b, |
5681 | 5334 octave_idx_type& err, double& rcond, |
5335 solve_singularity_handler sing_handler, | |
5336 bool calc_cond) const | |
5164 | 5337 { |
5338 SparseComplexMatrix retval; | |
5339 | |
5275 | 5340 octave_idx_type nr = rows (); |
5341 octave_idx_type nc = cols (); | |
5164 | 5342 err = 0; |
5343 | |
6924 | 5344 if (nr != nc || nr != b.rows ()) |
5164 | 5345 (*current_liboctave_error_handler) |
5346 ("matrix dimension mismatch solution of linear equations"); | |
6924 | 5347 else if (nr == 0 || b.cols () == 0) |
5348 retval = SparseComplexMatrix (nc, b.cols ()); | |
5164 | 5349 else |
5350 { | |
5351 // Print spparms("spumoni") info if requested | |
5352 volatile int typ = mattype.type (); | |
5353 mattype.info (); | |
5354 | |
5785 | 5355 if (typ == MatrixType::Banded_Hermitian) |
5164 | 5356 { |
6242 | 5357 octave_idx_type n_lower = mattype.nlower (); |
5358 octave_idx_type ldm = n_lower + 1; | |
5164 | 5359 |
5360 Matrix m_band (ldm, nc); | |
5361 double *tmp_data = m_band.fortran_vec (); | |
5362 | |
5363 if (! mattype.is_dense ()) | |
5364 { | |
5275 | 5365 octave_idx_type ii = 0; |
5366 | |
5367 for (octave_idx_type j = 0; j < ldm; j++) | |
5368 for (octave_idx_type i = 0; i < nc; i++) | |
5164 | 5369 tmp_data[ii++] = 0.; |
5370 } | |
5371 | |
5275 | 5372 for (octave_idx_type j = 0; j < nc; j++) |
5373 for (octave_idx_type i = cidx(j); i < cidx(j+1); i++) | |
5164 | 5374 { |
5275 | 5375 octave_idx_type ri = ridx (i); |
5164 | 5376 if (ri >= j) |
5377 m_band(ri - j, j) = data(i); | |
5378 } | |
5379 | |
5681 | 5380 // Calculate the norm of the matrix, for later use. |
5381 double anorm; | |
5382 if (calc_cond) | |
5383 anorm = m_band.abs().sum().row(0).max(); | |
5384 | |
5164 | 5385 char job = 'L'; |
5386 F77_XFCN (dpbtrf, DPBTRF, (F77_CONST_CHAR_ARG2 (&job, 1), | |
5387 nr, n_lower, tmp_data, ldm, err | |
5388 F77_CHAR_ARG_LEN (1))); | |
5389 | |
7482
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5390 if (err != 0) |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5391 { |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5392 // Matrix is not positive definite!! Fall through to |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5393 // unsymmetric banded solver. |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5394 mattype.mark_as_unsymmetric (); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5395 typ = MatrixType::Banded; |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5396 |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5397 rcond = 0.0; |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5398 err = 0; |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5399 } |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5400 else |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5401 { |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5402 if (calc_cond) |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5403 { |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5404 Array<double> z (3 * nr); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5405 double *pz = z.fortran_vec (); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5406 Array<octave_idx_type> iz (nr); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5407 octave_idx_type *piz = iz.fortran_vec (); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5408 |
7776 | 5409 F77_XFCN (dpbcon, DPBCON, |
7482
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5410 (F77_CONST_CHAR_ARG2 (&job, 1), |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5411 nr, n_lower, tmp_data, ldm, |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5412 anorm, rcond, pz, piz, err |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5413 F77_CHAR_ARG_LEN (1))); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5414 |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5415 if (err != 0) |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5416 err = -2; |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5417 |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5418 volatile double rcond_plus_one = rcond + 1.0; |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5419 |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5420 if (rcond_plus_one == 1.0 || xisnan (rcond)) |
5164 | 5421 { |
7482
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5422 err = -2; |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5423 |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5424 if (sing_handler) |
5164 | 5425 { |
7482
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5426 sing_handler (rcond); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5427 mattype.mark_as_rectangular (); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5428 } |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5429 else |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5430 (*current_liboctave_error_handler) |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5431 ("matrix singular to machine precision, rcond = %g", |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5432 rcond); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5433 } |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5434 } |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5435 else |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5436 rcond = 1.; |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5437 |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5438 if (err == 0) |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5439 { |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5440 octave_idx_type b_nr = b.rows (); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5441 octave_idx_type b_nc = b.cols (); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5442 OCTAVE_LOCAL_BUFFER (double, Bx, b_nr); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5443 OCTAVE_LOCAL_BUFFER (double, Bz, b_nr); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5444 |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5445 // Take a first guess that the number of non-zero terms |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5446 // will be as many as in b |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5447 volatile octave_idx_type x_nz = b.nnz (); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5448 volatile octave_idx_type ii = 0; |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5449 retval = SparseComplexMatrix (b_nr, b_nc, x_nz); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5450 |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5451 retval.xcidx(0) = 0; |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5452 for (volatile octave_idx_type j = 0; j < b_nc; j++) |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5453 { |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5454 |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5455 for (octave_idx_type i = 0; i < b_nr; i++) |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5456 { |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5457 Complex c = b (i,j); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5458 Bx[i] = std::real (c); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5459 Bz[i] = std::imag (c); |
5164 | 5460 } |
5461 | |
7482
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5462 F77_XFCN (dpbtrs, DPBTRS, |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5463 (F77_CONST_CHAR_ARG2 (&job, 1), |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5464 nr, n_lower, 1, tmp_data, |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5465 ldm, Bx, b_nr, err |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5466 F77_CHAR_ARG_LEN (1))); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5467 |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5468 if (err != 0) |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5469 { |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5470 (*current_liboctave_error_handler) |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5471 ("SparseMatrix::solve solve failed"); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5472 err = -1; |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5473 break; |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5474 } |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5475 |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5476 F77_XFCN (dpbtrs, DPBTRS, |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5477 (F77_CONST_CHAR_ARG2 (&job, 1), |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5478 nr, n_lower, 1, tmp_data, |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5479 ldm, Bz, b_nr, err |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5480 F77_CHAR_ARG_LEN (1))); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5481 |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5482 if (err != 0) |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5483 { |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5484 (*current_liboctave_error_handler) |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5485 ("SparseMatrix::solve solve failed"); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5486 |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5487 err = -1; |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5488 break; |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5489 } |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5490 |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5491 // Count non-zeros in work vector and adjust |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5492 // space in retval if needed |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5493 octave_idx_type new_nnz = 0; |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5494 for (octave_idx_type i = 0; i < nr; i++) |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5495 if (Bx[i] != 0. || Bz[i] != 0.) |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5496 new_nnz++; |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5497 |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5498 if (ii + new_nnz > x_nz) |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5499 { |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5500 // Resize the sparse matrix |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5501 octave_idx_type sz = new_nnz * (b_nc - j) + x_nz; |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5502 retval.change_capacity (sz); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5503 x_nz = sz; |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5504 } |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5505 |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5506 for (octave_idx_type i = 0; i < nr; i++) |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5507 if (Bx[i] != 0. || Bz[i] != 0.) |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5508 { |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5509 retval.xridx(ii) = i; |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5510 retval.xdata(ii++) = |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5511 Complex (Bx[i], Bz[i]); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5512 } |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5513 |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5514 retval.xcidx(j+1) = ii; |
5164 | 5515 } |
7482
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5516 |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5517 retval.maybe_compress (); |
5164 | 5518 } |
5519 } | |
5520 } | |
5521 | |
5785 | 5522 if (typ == MatrixType::Banded) |
5164 | 5523 { |
5524 // Create the storage for the banded form of the sparse matrix | |
6242 | 5525 octave_idx_type n_upper = mattype.nupper (); |
5526 octave_idx_type n_lower = mattype.nlower (); | |
5527 octave_idx_type ldm = n_upper + 2 * n_lower + 1; | |
5164 | 5528 |
5529 Matrix m_band (ldm, nc); | |
5530 double *tmp_data = m_band.fortran_vec (); | |
5531 | |
5532 if (! mattype.is_dense ()) | |
5533 { | |
5275 | 5534 octave_idx_type ii = 0; |
5535 | |
5536 for (octave_idx_type j = 0; j < ldm; j++) | |
5537 for (octave_idx_type i = 0; i < nc; i++) | |
5164 | 5538 tmp_data[ii++] = 0.; |
5539 } | |
5540 | |
5275 | 5541 for (octave_idx_type j = 0; j < nc; j++) |
5542 for (octave_idx_type i = cidx(j); i < cidx(j+1); i++) | |
5164 | 5543 m_band(ridx(i) - j + n_lower + n_upper, j) = data(i); |
5544 | |
5681 | 5545 // Calculate the norm of the matrix, for later use. |
5546 double anorm; | |
5547 if (calc_cond) | |
5548 { | |
5549 for (octave_idx_type j = 0; j < nr; j++) | |
5550 { | |
5551 double atmp = 0.; | |
5552 for (octave_idx_type i = cidx(j); i < cidx(j+1); i++) | |
5553 atmp += fabs(data(i)); | |
5554 if (atmp > anorm) | |
5555 anorm = atmp; | |
5556 } | |
5557 } | |
5558 | |
5275 | 5559 Array<octave_idx_type> ipvt (nr); |
5560 octave_idx_type *pipvt = ipvt.fortran_vec (); | |
5164 | 5561 |
5562 F77_XFCN (dgbtrf, DGBTRF, (nr, nr, n_lower, n_upper, tmp_data, | |
5563 ldm, pipvt, err)); | |
5564 | |
7482
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5565 if (err != 0) |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5566 { |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5567 err = -2; |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5568 rcond = 0.0; |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5569 |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5570 if (sing_handler) |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5571 { |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5572 sing_handler (rcond); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5573 mattype.mark_as_rectangular (); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5574 } |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5575 else |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5576 (*current_liboctave_error_handler) |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5577 ("matrix singular to machine precision"); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5578 |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5579 } |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5580 else |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5581 { |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5582 if (calc_cond) |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5583 { |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5584 char job = '1'; |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5585 Array<double> z (3 * nr); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5586 double *pz = z.fortran_vec (); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5587 Array<octave_idx_type> iz (nr); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5588 octave_idx_type *piz = iz.fortran_vec (); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5589 |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5590 F77_XFCN (dgbcon, DGBCON, |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5591 (F77_CONST_CHAR_ARG2 (&job, 1), |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5592 nc, n_lower, n_upper, tmp_data, ldm, pipvt, |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5593 anorm, rcond, pz, piz, err |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5594 F77_CHAR_ARG_LEN (1))); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5595 |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5596 if (err != 0) |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5597 err = -2; |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5598 |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5599 volatile double rcond_plus_one = rcond + 1.0; |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5600 |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5601 if (rcond_plus_one == 1.0 || xisnan (rcond)) |
5681 | 5602 { |
7482
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5603 err = -2; |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5604 |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5605 if (sing_handler) |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5606 { |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5607 sing_handler (rcond); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5608 mattype.mark_as_rectangular (); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5609 } |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5610 else |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5611 (*current_liboctave_error_handler) |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5612 ("matrix singular to machine precision, rcond = %g", |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5613 rcond); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5614 } |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5615 } |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5616 else |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5617 rcond = 1.; |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5618 |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5619 if (err == 0) |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5620 { |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5621 char job = 'N'; |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5622 volatile octave_idx_type x_nz = b.nnz (); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5623 octave_idx_type b_nc = b.cols (); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5624 retval = SparseComplexMatrix (nr, b_nc, x_nz); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5625 retval.xcidx(0) = 0; |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5626 volatile octave_idx_type ii = 0; |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5627 |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5628 OCTAVE_LOCAL_BUFFER (double, Bx, nr); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5629 OCTAVE_LOCAL_BUFFER (double, Bz, nr); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5630 |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5631 for (volatile octave_idx_type j = 0; j < b_nc; j++) |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5632 { |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5633 for (octave_idx_type i = 0; i < nr; i++) |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5634 { |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5635 Bx[i] = 0.; |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5636 Bz[i] = 0.; |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5637 } |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5638 for (octave_idx_type i = b.cidx(j); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5639 i < b.cidx(j+1); i++) |
5164 | 5640 { |
7482
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5641 Complex c = b.data(i); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5642 Bx[b.ridx(i)] = std::real (c); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5643 Bz[b.ridx(i)] = std::imag (c); |
5164 | 5644 } |
5645 | |
7482
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5646 F77_XFCN (dgbtrs, DGBTRS, |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5647 (F77_CONST_CHAR_ARG2 (&job, 1), |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5648 nr, n_lower, n_upper, 1, tmp_data, |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5649 ldm, pipvt, Bx, b.rows (), err |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5650 F77_CHAR_ARG_LEN (1))); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5651 |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5652 F77_XFCN (dgbtrs, DGBTRS, |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5653 (F77_CONST_CHAR_ARG2 (&job, 1), |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5654 nr, n_lower, n_upper, 1, tmp_data, |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5655 ldm, pipvt, Bz, b.rows (), err |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5656 F77_CHAR_ARG_LEN (1))); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5657 |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5658 // Count non-zeros in work vector and adjust |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5659 // space in retval if needed |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5660 octave_idx_type new_nnz = 0; |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5661 for (octave_idx_type i = 0; i < nr; i++) |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5662 if (Bx[i] != 0. || Bz[i] != 0.) |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5663 new_nnz++; |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5664 |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5665 if (ii + new_nnz > x_nz) |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5666 { |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5667 // Resize the sparse matrix |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5668 octave_idx_type sz = new_nnz * (b_nc - j) + x_nz; |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5669 retval.change_capacity (sz); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5670 x_nz = sz; |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5671 } |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5672 |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5673 for (octave_idx_type i = 0; i < nr; i++) |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5674 if (Bx[i] != 0. || Bz[i] != 0.) |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5675 { |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5676 retval.xridx(ii) = i; |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5677 retval.xdata(ii++) = |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5678 Complex (Bx[i], Bz[i]); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5679 } |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5680 retval.xcidx(j+1) = ii; |
5164 | 5681 } |
7482
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5682 |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5683 retval.maybe_compress (); |
5164 | 5684 } |
5685 } | |
5686 } | |
5785 | 5687 else if (typ != MatrixType::Banded_Hermitian) |
5164 | 5688 (*current_liboctave_error_handler) ("incorrect matrix type"); |
5689 } | |
5690 | |
5691 return retval; | |
5692 } | |
5693 | |
5694 void * | |
5681 | 5695 SparseMatrix::factorize (octave_idx_type& err, double &rcond, Matrix &Control, |
5696 Matrix &Info, solve_singularity_handler sing_handler, | |
5697 bool calc_cond) const | |
5164 | 5698 { |
5699 // The return values | |
5404 | 5700 void *Numeric = 0; |
5164 | 5701 err = 0; |
5702 | |
5203 | 5703 #ifdef HAVE_UMFPACK |
5164 | 5704 // Setup the control parameters |
5705 Control = Matrix (UMFPACK_CONTROL, 1); | |
5706 double *control = Control.fortran_vec (); | |
5322 | 5707 UMFPACK_DNAME (defaults) (control); |
5164 | 5708 |
5893 | 5709 double tmp = octave_sparse_params::get_key ("spumoni"); |
5164 | 5710 if (!xisnan (tmp)) |
5711 Control (UMFPACK_PRL) = tmp; | |
5893 | 5712 tmp = octave_sparse_params::get_key ("piv_tol"); |
5164 | 5713 if (!xisnan (tmp)) |
5714 { | |
5715 Control (UMFPACK_SYM_PIVOT_TOLERANCE) = tmp; | |
5716 Control (UMFPACK_PIVOT_TOLERANCE) = tmp; | |
5717 } | |
5718 | |
5719 // Set whether we are allowed to modify Q or not | |
5893 | 5720 tmp = octave_sparse_params::get_key ("autoamd"); |
5164 | 5721 if (!xisnan (tmp)) |
5722 Control (UMFPACK_FIXQ) = tmp; | |
5723 | |
5322 | 5724 UMFPACK_DNAME (report_control) (control); |
5164 | 5725 |
5275 | 5726 const octave_idx_type *Ap = cidx (); |
5727 const octave_idx_type *Ai = ridx (); | |
5164 | 5728 const double *Ax = data (); |
5275 | 5729 octave_idx_type nr = rows (); |
5730 octave_idx_type nc = cols (); | |
5164 | 5731 |
5322 | 5732 UMFPACK_DNAME (report_matrix) (nr, nc, Ap, Ai, Ax, 1, control); |
5164 | 5733 |
5734 void *Symbolic; | |
5735 Info = Matrix (1, UMFPACK_INFO); | |
5736 double *info = Info.fortran_vec (); | |
7520 | 5737 int status = UMFPACK_DNAME (qsymbolic) (nr, nc, Ap, Ai, Ax, 0, |
5164 | 5738 &Symbolic, control, info); |
5739 | |
5740 if (status < 0) | |
5741 { | |
5742 (*current_liboctave_error_handler) | |
5743 ("SparseMatrix::solve symbolic factorization failed"); | |
5744 err = -1; | |
5745 | |
5322 | 5746 UMFPACK_DNAME (report_status) (control, status); |
5747 UMFPACK_DNAME (report_info) (control, info); | |
5748 | |
5749 UMFPACK_DNAME (free_symbolic) (&Symbolic) ; | |
5164 | 5750 } |
5751 else | |
5752 { | |
5322 | 5753 UMFPACK_DNAME (report_symbolic) (Symbolic, control); |
5754 | |
5755 status = UMFPACK_DNAME (numeric) (Ap, Ai, Ax, Symbolic, | |
5756 &Numeric, control, info) ; | |
5757 UMFPACK_DNAME (free_symbolic) (&Symbolic) ; | |
5164 | 5758 |
5681 | 5759 if (calc_cond) |
5760 rcond = Info (UMFPACK_RCOND); | |
5761 else | |
5762 rcond = 1.; | |
5164 | 5763 volatile double rcond_plus_one = rcond + 1.0; |
5764 | |
5765 if (status == UMFPACK_WARNING_singular_matrix || | |
5766 rcond_plus_one == 1.0 || xisnan (rcond)) | |
5767 { | |
5322 | 5768 UMFPACK_DNAME (report_numeric) (Numeric, control); |
5164 | 5769 |
5770 err = -2; | |
5771 | |
5772 if (sing_handler) | |
5773 sing_handler (rcond); | |
5774 else | |
5775 (*current_liboctave_error_handler) | |
5776 ("SparseMatrix::solve matrix singular to machine precision, rcond = %g", | |
5777 rcond); | |
5778 | |
5779 } | |
5610 | 5780 else if (status < 0) |
5164 | 5781 { |
5782 (*current_liboctave_error_handler) | |
5783 ("SparseMatrix::solve numeric factorization failed"); | |
5784 | |
5322 | 5785 UMFPACK_DNAME (report_status) (control, status); |
5786 UMFPACK_DNAME (report_info) (control, info); | |
5164 | 5787 |
5788 err = -1; | |
5789 } | |
5790 else | |
5791 { | |
5322 | 5792 UMFPACK_DNAME (report_numeric) (Numeric, control); |
5164 | 5793 } |
5794 } | |
5795 | |
5796 if (err != 0) | |
5322 | 5797 UMFPACK_DNAME (free_numeric) (&Numeric); |
5164 | 5798 |
5203 | 5799 #else |
5800 (*current_liboctave_error_handler) ("UMFPACK not installed"); | |
5801 #endif | |
5802 | |
5164 | 5803 return Numeric; |
5804 } | |
5805 | |
5806 Matrix | |
5785 | 5807 SparseMatrix::fsolve (MatrixType &mattype, const Matrix& b, |
5681 | 5808 octave_idx_type& err, double& rcond, |
5809 solve_singularity_handler sing_handler, | |
5810 bool calc_cond) const | |
5164 | 5811 { |
5812 Matrix retval; | |
5813 | |
5275 | 5814 octave_idx_type nr = rows (); |
5815 octave_idx_type nc = cols (); | |
5164 | 5816 err = 0; |
5817 | |
6924 | 5818 if (nr != nc || nr != b.rows ()) |
5164 | 5819 (*current_liboctave_error_handler) |
5820 ("matrix dimension mismatch solution of linear equations"); | |
6924 | 5821 else if (nr == 0 || b.cols () == 0) |
5822 retval = Matrix (nc, b.cols (), 0.0); | |
5164 | 5823 else |
5824 { | |
5825 // Print spparms("spumoni") info if requested | |
5506 | 5826 volatile int typ = mattype.type (); |
5164 | 5827 mattype.info (); |
5828 | |
5785 | 5829 if (typ == MatrixType::Hermitian) |
5164 | 5830 { |
5506 | 5831 #ifdef HAVE_CHOLMOD |
5832 cholmod_common Common; | |
5833 cholmod_common *cm = &Common; | |
5834 | |
5835 // Setup initial parameters | |
5836 CHOLMOD_NAME(start) (cm); | |
5526 | 5837 cm->prefer_zomplex = false; |
5506 | 5838 |
5893 | 5839 double spu = octave_sparse_params::get_key ("spumoni"); |
5506 | 5840 if (spu == 0.) |
5841 { | |
5842 cm->print = -1; | |
7520 | 5843 cm->print_function = 0; |
5506 | 5844 } |
5845 else | |
5846 { | |
5760 | 5847 cm->print = static_cast<int> (spu) + 2; |
5506 | 5848 cm->print_function =&SparseCholPrint; |
5849 } | |
5850 | |
5851 cm->error_handler = &SparseCholError; | |
5852 cm->complex_divide = CHOLMOD_NAME(divcomplex); | |
5853 cm->hypotenuse = CHOLMOD_NAME(hypot); | |
5854 | |
5526 | 5855 cm->final_ll = true; |
5506 | 5856 |
5857 cholmod_sparse Astore; | |
5858 cholmod_sparse *A = &Astore; | |
5859 double dummy; | |
5860 A->nrow = nr; | |
5861 A->ncol = nc; | |
5862 | |
5863 A->p = cidx(); | |
5864 A->i = ridx(); | |
5604 | 5865 A->nzmax = nnz(); |
5526 | 5866 A->packed = true; |
5867 A->sorted = true; | |
7520 | 5868 A->nz = 0; |
5506 | 5869 #ifdef IDX_TYPE_LONG |
5870 A->itype = CHOLMOD_LONG; | |
5871 #else | |
5872 A->itype = CHOLMOD_INT; | |
5873 #endif | |
5874 A->dtype = CHOLMOD_DOUBLE; | |
5875 A->stype = 1; | |
5876 A->xtype = CHOLMOD_REAL; | |
5877 | |
5878 if (nr < 1) | |
5879 A->x = &dummy; | |
5880 else | |
5881 A->x = data(); | |
5882 | |
5883 cholmod_dense Bstore; | |
5884 cholmod_dense *B = &Bstore; | |
5885 B->nrow = b.rows(); | |
5886 B->ncol = b.cols(); | |
5887 B->d = B->nrow; | |
5888 B->nzmax = B->nrow * B->ncol; | |
5889 B->dtype = CHOLMOD_DOUBLE; | |
5890 B->xtype = CHOLMOD_REAL; | |
5891 if (nc < 1 || b.cols() < 1) | |
5892 B->x = &dummy; | |
5893 else | |
5894 // We won't alter it, honest :-) | |
5895 B->x = const_cast<double *>(b.fortran_vec()); | |
5896 | |
5897 cholmod_factor *L; | |
5898 BEGIN_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE; | |
5899 L = CHOLMOD_NAME(analyze) (A, cm); | |
5900 CHOLMOD_NAME(factorize) (A, L, cm); | |
5681 | 5901 if (calc_cond) |
5902 rcond = CHOLMOD_NAME(rcond)(L, cm); | |
5903 else | |
5904 rcond = 1.0; | |
5905 | |
5506 | 5906 END_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE; |
5907 | |
5908 if (rcond == 0.0) | |
5909 { | |
5910 // Either its indefinite or singular. Try UMFPACK | |
5911 mattype.mark_as_unsymmetric (); | |
5785 | 5912 typ = MatrixType::Full; |
5506 | 5913 } |
5914 else | |
5915 { | |
5916 volatile double rcond_plus_one = rcond + 1.0; | |
5917 | |
5918 if (rcond_plus_one == 1.0 || xisnan (rcond)) | |
5919 { | |
5920 err = -2; | |
5921 | |
5922 if (sing_handler) | |
5681 | 5923 { |
5924 sing_handler (rcond); | |
5925 mattype.mark_as_rectangular (); | |
5926 } | |
5506 | 5927 else |
5928 (*current_liboctave_error_handler) | |
5929 ("SparseMatrix::solve matrix singular to machine precision, rcond = %g", | |
5930 rcond); | |
5931 | |
5932 return retval; | |
5933 } | |
5934 | |
5935 cholmod_dense *X; | |
5936 BEGIN_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE; | |
5937 X = CHOLMOD_NAME(solve) (CHOLMOD_A, L, B, cm); | |
5938 END_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE; | |
5939 | |
5940 retval.resize (b.rows (), b.cols()); | |
5941 for (octave_idx_type j = 0; j < b.cols(); j++) | |
5942 { | |
5943 octave_idx_type jr = j * b.rows(); | |
5944 for (octave_idx_type i = 0; i < b.rows(); i++) | |
5945 retval.xelem(i,j) = static_cast<double *>(X->x)[jr + i]; | |
5946 } | |
5947 | |
5948 BEGIN_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE; | |
5949 CHOLMOD_NAME(free_dense) (&X, cm); | |
5950 CHOLMOD_NAME(free_factor) (&L, cm); | |
5951 CHOLMOD_NAME(finish) (cm); | |
6482 | 5952 static char tmp[] = " "; |
5953 CHOLMOD_NAME(print_common) (tmp, cm); | |
5506 | 5954 END_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE; |
5955 } | |
5956 #else | |
5164 | 5957 (*current_liboctave_warning_handler) |
5506 | 5958 ("CHOLMOD not installed"); |
5164 | 5959 |
5960 mattype.mark_as_unsymmetric (); | |
5785 | 5961 typ = MatrixType::Full; |
5506 | 5962 #endif |
5164 | 5963 } |
5964 | |
5785 | 5965 if (typ == MatrixType::Full) |
5164 | 5966 { |
5203 | 5967 #ifdef HAVE_UMFPACK |
5164 | 5968 Matrix Control, Info; |
5969 void *Numeric = | |
5681 | 5970 factorize (err, rcond, Control, Info, sing_handler, calc_cond); |
5164 | 5971 |
5972 if (err == 0) | |
5973 { | |
5974 const double *Bx = b.fortran_vec (); | |
5975 retval.resize (b.rows (), b.cols()); | |
5976 double *result = retval.fortran_vec (); | |
5275 | 5977 octave_idx_type b_nr = b.rows (); |
5978 octave_idx_type b_nc = b.cols (); | |
5164 | 5979 int status = 0; |
5980 double *control = Control.fortran_vec (); | |
5981 double *info = Info.fortran_vec (); | |
5275 | 5982 const octave_idx_type *Ap = cidx (); |
5983 const octave_idx_type *Ai = ridx (); | |
5164 | 5984 const double *Ax = data (); |
5985 | |
5275 | 5986 for (octave_idx_type j = 0, iidx = 0; j < b_nc; j++, iidx += b_nr) |
5164 | 5987 { |
5322 | 5988 status = UMFPACK_DNAME (solve) (UMFPACK_A, Ap, |
5989 Ai, Ax, &result[iidx], &Bx[iidx], | |
5164 | 5990 Numeric, control, info); |
5991 if (status < 0) | |
5992 { | |
5993 (*current_liboctave_error_handler) | |
5994 ("SparseMatrix::solve solve failed"); | |
5995 | |
5322 | 5996 UMFPACK_DNAME (report_status) (control, status); |
5164 | 5997 |
5998 err = -1; | |
5999 | |
6000 break; | |
6001 } | |
6002 } | |
6003 | |
5322 | 6004 UMFPACK_DNAME (report_info) (control, info); |
5164 | 6005 |
5322 | 6006 UMFPACK_DNAME (free_numeric) (&Numeric); |
5164 | 6007 } |
5681 | 6008 else |
6009 mattype.mark_as_rectangular (); | |
6010 | |
5203 | 6011 #else |
6012 (*current_liboctave_error_handler) ("UMFPACK not installed"); | |
6013 #endif | |
5164 | 6014 } |
5785 | 6015 else if (typ != MatrixType::Hermitian) |
5164 | 6016 (*current_liboctave_error_handler) ("incorrect matrix type"); |
6017 } | |
6018 | |
6019 return retval; | |
6020 } | |
6021 | |
6022 SparseMatrix | |
5785 | 6023 SparseMatrix::fsolve (MatrixType &mattype, const SparseMatrix& b, |
5681 | 6024 octave_idx_type& err, double& rcond, |
6025 solve_singularity_handler sing_handler, | |
6026 bool calc_cond) const | |
5164 | 6027 { |
6028 SparseMatrix retval; | |
6029 | |
5275 | 6030 octave_idx_type nr = rows (); |
6031 octave_idx_type nc = cols (); | |
5164 | 6032 err = 0; |
6033 | |
6924 | 6034 if (nr != nc || nr != b.rows ()) |
5164 | 6035 (*current_liboctave_error_handler) |
6036 ("matrix dimension mismatch solution of linear equations"); | |
6924 | 6037 else if (nr == 0 || b.cols () == 0) |
6038 retval = SparseMatrix (nc, b.cols ()); | |
5164 | 6039 else |
6040 { | |
6041 // Print spparms("spumoni") info if requested | |
5506 | 6042 volatile int typ = mattype.type (); |
5164 | 6043 mattype.info (); |
6044 | |
5785 | 6045 if (typ == MatrixType::Hermitian) |
5164 | 6046 { |
5506 | 6047 #ifdef HAVE_CHOLMOD |
6048 cholmod_common Common; | |
6049 cholmod_common *cm = &Common; | |
6050 | |
6051 // Setup initial parameters | |
6052 CHOLMOD_NAME(start) (cm); | |
5526 | 6053 cm->prefer_zomplex = false; |
5506 | 6054 |
5893 | 6055 double spu = octave_sparse_params::get_key ("spumoni"); |
5506 | 6056 if (spu == 0.) |
6057 { | |
6058 cm->print = -1; | |
7520 | 6059 cm->print_function = 0; |
5506 | 6060 } |
6061 else | |
6062 { | |
5760 | 6063 cm->print = static_cast<int> (spu) + 2; |
5506 | 6064 cm->print_function =&SparseCholPrint; |
6065 } | |
6066 | |
6067 cm->error_handler = &SparseCholError; | |
6068 cm->complex_divide = CHOLMOD_NAME(divcomplex); | |
6069 cm->hypotenuse = CHOLMOD_NAME(hypot); | |
6070 | |
5526 | 6071 cm->final_ll = true; |
5506 | 6072 |
6073 cholmod_sparse Astore; | |
6074 cholmod_sparse *A = &Astore; | |
6075 double dummy; | |
6076 A->nrow = nr; | |
6077 A->ncol = nc; | |
6078 | |
6079 A->p = cidx(); | |
6080 A->i = ridx(); | |
5604 | 6081 A->nzmax = nnz(); |
5526 | 6082 A->packed = true; |
6083 A->sorted = true; | |
7520 | 6084 A->nz = 0; |
5506 | 6085 #ifdef IDX_TYPE_LONG |
6086 A->itype = CHOLMOD_LONG; | |
6087 #else | |
6088 A->itype = CHOLMOD_INT; | |
6089 #endif | |
6090 A->dtype = CHOLMOD_DOUBLE; | |
6091 A->stype = 1; | |
6092 A->xtype = CHOLMOD_REAL; | |
6093 | |
6094 if (nr < 1) | |
6095 A->x = &dummy; | |
6096 else | |
6097 A->x = data(); | |
6098 | |
6099 cholmod_sparse Bstore; | |
6100 cholmod_sparse *B = &Bstore; | |
6101 B->nrow = b.rows(); | |
6102 B->ncol = b.cols(); | |
6103 B->p = b.cidx(); | |
6104 B->i = b.ridx(); | |
5604 | 6105 B->nzmax = b.nnz(); |
5526 | 6106 B->packed = true; |
6107 B->sorted = true; | |
7520 | 6108 B->nz = 0; |
5506 | 6109 #ifdef IDX_TYPE_LONG |
6110 B->itype = CHOLMOD_LONG; | |
6111 #else | |
6112 B->itype = CHOLMOD_INT; | |
6113 #endif | |
6114 B->dtype = CHOLMOD_DOUBLE; | |
6115 B->stype = 0; | |
6116 B->xtype = CHOLMOD_REAL; | |
6117 | |
6118 if (b.rows() < 1 || b.cols() < 1) | |
6119 B->x = &dummy; | |
6120 else | |
6121 B->x = b.data(); | |
6122 | |
6123 cholmod_factor *L; | |
6124 BEGIN_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE; | |
6125 L = CHOLMOD_NAME(analyze) (A, cm); | |
6126 CHOLMOD_NAME(factorize) (A, L, cm); | |
5681 | 6127 if (calc_cond) |
6128 rcond = CHOLMOD_NAME(rcond)(L, cm); | |
6129 else | |
6130 rcond = 1.; | |
5506 | 6131 END_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE; |
6132 | |
6133 if (rcond == 0.0) | |
6134 { | |
6135 // Either its indefinite or singular. Try UMFPACK | |
6136 mattype.mark_as_unsymmetric (); | |
5785 | 6137 typ = MatrixType::Full; |
5506 | 6138 } |
6139 else | |
6140 { | |
6141 volatile double rcond_plus_one = rcond + 1.0; | |
6142 | |
6143 if (rcond_plus_one == 1.0 || xisnan (rcond)) | |
6144 { | |
6145 err = -2; | |
6146 | |
6147 if (sing_handler) | |
5681 | 6148 { |
6149 sing_handler (rcond); | |
6150 mattype.mark_as_rectangular (); | |
6151 } | |
5506 | 6152 else |
6153 (*current_liboctave_error_handler) | |
6154 ("SparseMatrix::solve matrix singular to machine precision, rcond = %g", | |
6155 rcond); | |
6156 | |
6157 return retval; | |
6158 } | |
6159 | |
6160 cholmod_sparse *X; | |
6161 BEGIN_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE; | |
6162 X = CHOLMOD_NAME(spsolve) (CHOLMOD_A, L, B, cm); | |
6163 END_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE; | |
6164 | |
6165 retval = SparseMatrix (static_cast<octave_idx_type>(X->nrow), | |
6166 static_cast<octave_idx_type>(X->ncol), | |
6167 static_cast<octave_idx_type>(X->nzmax)); | |
6168 for (octave_idx_type j = 0; | |
6169 j <= static_cast<octave_idx_type>(X->ncol); j++) | |
6170 retval.xcidx(j) = static_cast<octave_idx_type *>(X->p)[j]; | |
6171 for (octave_idx_type j = 0; | |
6172 j < static_cast<octave_idx_type>(X->nzmax); j++) | |
6173 { | |
6174 retval.xridx(j) = static_cast<octave_idx_type *>(X->i)[j]; | |
6175 retval.xdata(j) = static_cast<double *>(X->x)[j]; | |
6176 } | |
6177 | |
6178 BEGIN_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE; | |
6179 CHOLMOD_NAME(free_sparse) (&X, cm); | |
6180 CHOLMOD_NAME(free_factor) (&L, cm); | |
6181 CHOLMOD_NAME(finish) (cm); | |
6482 | 6182 static char tmp[] = " "; |
6183 CHOLMOD_NAME(print_common) (tmp, cm); | |
5506 | 6184 END_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE; |
6185 } | |
6186 #else | |
5164 | 6187 (*current_liboctave_warning_handler) |
5506 | 6188 ("CHOLMOD not installed"); |
5164 | 6189 |
6190 mattype.mark_as_unsymmetric (); | |
5785 | 6191 typ = MatrixType::Full; |
5506 | 6192 #endif |
5164 | 6193 } |
6194 | |
5785 | 6195 if (typ == MatrixType::Full) |
5164 | 6196 { |
5203 | 6197 #ifdef HAVE_UMFPACK |
5164 | 6198 Matrix Control, Info; |
6199 void *Numeric = factorize (err, rcond, Control, Info, | |
5681 | 6200 sing_handler, calc_cond); |
5164 | 6201 |
6202 if (err == 0) | |
6203 { | |
5275 | 6204 octave_idx_type b_nr = b.rows (); |
6205 octave_idx_type b_nc = b.cols (); | |
5164 | 6206 int status = 0; |
6207 double *control = Control.fortran_vec (); | |
6208 double *info = Info.fortran_vec (); | |
5275 | 6209 const octave_idx_type *Ap = cidx (); |
6210 const octave_idx_type *Ai = ridx (); | |
5164 | 6211 const double *Ax = data (); |
6212 | |
6213 OCTAVE_LOCAL_BUFFER (double, Bx, b_nr); | |
6214 OCTAVE_LOCAL_BUFFER (double, Xx, b_nr); | |
6215 | |
6216 // Take a first guess that the number of non-zero terms | |
6217 // will be as many as in b | |
5681 | 6218 octave_idx_type x_nz = b.nnz (); |
5275 | 6219 octave_idx_type ii = 0; |
5164 | 6220 retval = SparseMatrix (b_nr, b_nc, x_nz); |
6221 | |
6222 retval.xcidx(0) = 0; | |
5275 | 6223 for (octave_idx_type j = 0; j < b_nc; j++) |
5164 | 6224 { |
6225 | |
5275 | 6226 for (octave_idx_type i = 0; i < b_nr; i++) |
5164 | 6227 Bx[i] = b.elem (i, j); |
6228 | |
5322 | 6229 status = UMFPACK_DNAME (solve) (UMFPACK_A, Ap, |
6230 Ai, Ax, Xx, Bx, Numeric, control, | |
5164 | 6231 info); |
6232 if (status < 0) | |
6233 { | |
6234 (*current_liboctave_error_handler) | |
6235 ("SparseMatrix::solve solve failed"); | |
6236 | |
5322 | 6237 UMFPACK_DNAME (report_status) (control, status); |
5164 | 6238 |
6239 err = -1; | |
6240 | |
6241 break; | |
6242 } | |
6243 | |
5275 | 6244 for (octave_idx_type i = 0; i < b_nr; i++) |
5164 | 6245 { |
6246 double tmp = Xx[i]; | |
6247 if (tmp != 0.0) | |
6248 { | |
6249 if (ii == x_nz) | |
6250 { | |
6251 // Resize the sparse matrix | |
5275 | 6252 octave_idx_type sz = x_nz * (b_nc - j) / b_nc; |
5164 | 6253 sz = (sz > 10 ? sz : 10) + x_nz; |
6254 retval.change_capacity (sz); | |
6255 x_nz = sz; | |
6256 } | |
6257 retval.xdata(ii) = tmp; | |
6258 retval.xridx(ii++) = i; | |
6259 } | |
6260 } | |
6261 retval.xcidx(j+1) = ii; | |
6262 } | |
6263 | |
6264 retval.maybe_compress (); | |
6265 | |
5322 | 6266 UMFPACK_DNAME (report_info) (control, info); |
6267 | |
6268 UMFPACK_DNAME (free_numeric) (&Numeric); | |
5164 | 6269 } |
5681 | 6270 else |
6271 mattype.mark_as_rectangular (); | |
6272 | |
5203 | 6273 #else |
6274 (*current_liboctave_error_handler) ("UMFPACK not installed"); | |
6275 #endif | |
5164 | 6276 } |
5785 | 6277 else if (typ != MatrixType::Hermitian) |
5164 | 6278 (*current_liboctave_error_handler) ("incorrect matrix type"); |
6279 } | |
6280 | |
6281 return retval; | |
6282 } | |
6283 | |
6284 ComplexMatrix | |
5785 | 6285 SparseMatrix::fsolve (MatrixType &mattype, const ComplexMatrix& b, |
5681 | 6286 octave_idx_type& err, double& rcond, |
6287 solve_singularity_handler sing_handler, | |
6288 bool calc_cond) const | |
5164 | 6289 { |
6290 ComplexMatrix retval; | |
6291 | |
5275 | 6292 octave_idx_type nr = rows (); |
6293 octave_idx_type nc = cols (); | |
5164 | 6294 err = 0; |
6295 | |
6924 | 6296 if (nr != nc || nr != b.rows ()) |
5164 | 6297 (*current_liboctave_error_handler) |
6298 ("matrix dimension mismatch solution of linear equations"); | |
6924 | 6299 else if (nr == 0 || b.cols () == 0) |
6300 retval = ComplexMatrix (nc, b.cols (), Complex (0.0, 0.0)); | |
5164 | 6301 else |
6302 { | |
6303 // Print spparms("spumoni") info if requested | |
5506 | 6304 volatile int typ = mattype.type (); |
5164 | 6305 mattype.info (); |
6306 | |
5785 | 6307 if (typ == MatrixType::Hermitian) |
5164 | 6308 { |
5506 | 6309 #ifdef HAVE_CHOLMOD |
6310 cholmod_common Common; | |
6311 cholmod_common *cm = &Common; | |
6312 | |
6313 // Setup initial parameters | |
6314 CHOLMOD_NAME(start) (cm); | |
5526 | 6315 cm->prefer_zomplex = false; |
5506 | 6316 |
5893 | 6317 double spu = octave_sparse_params::get_key ("spumoni"); |
5506 | 6318 if (spu == 0.) |
6319 { | |
6320 cm->print = -1; | |
7520 | 6321 cm->print_function = 0; |
5506 | 6322 } |
6323 else | |
6324 { | |
5760 | 6325 cm->print = static_cast<int> (spu) + 2; |
5506 | 6326 cm->print_function =&SparseCholPrint; |
6327 } | |
6328 | |
6329 cm->error_handler = &SparseCholError; | |
6330 cm->complex_divide = CHOLMOD_NAME(divcomplex); | |
6331 cm->hypotenuse = CHOLMOD_NAME(hypot); | |
6332 | |
5526 | 6333 cm->final_ll = true; |
5506 | 6334 |
6335 cholmod_sparse Astore; | |
6336 cholmod_sparse *A = &Astore; | |
6337 double dummy; | |
6338 A->nrow = nr; | |
6339 A->ncol = nc; | |
6340 | |
6341 A->p = cidx(); | |
6342 A->i = ridx(); | |
5604 | 6343 A->nzmax = nnz(); |
5526 | 6344 A->packed = true; |
6345 A->sorted = true; | |
7520 | 6346 A->nz = 0; |
5506 | 6347 #ifdef IDX_TYPE_LONG |
6348 A->itype = CHOLMOD_LONG; | |
6349 #else | |
6350 A->itype = CHOLMOD_INT; | |
6351 #endif | |
6352 A->dtype = CHOLMOD_DOUBLE; | |
6353 A->stype = 1; | |
6354 A->xtype = CHOLMOD_REAL; | |
6355 | |
6356 if (nr < 1) | |
6357 A->x = &dummy; | |
6358 else | |
6359 A->x = data(); | |
6360 | |
6361 cholmod_dense Bstore; | |
6362 cholmod_dense *B = &Bstore; | |
6363 B->nrow = b.rows(); | |
6364 B->ncol = b.cols(); | |
6365 B->d = B->nrow; | |
6366 B->nzmax = B->nrow * B->ncol; | |
6367 B->dtype = CHOLMOD_DOUBLE; | |
6368 B->xtype = CHOLMOD_COMPLEX; | |
6369 if (nc < 1 || b.cols() < 1) | |
6370 B->x = &dummy; | |
6371 else | |
6372 // We won't alter it, honest :-) | |
6373 B->x = const_cast<Complex *>(b.fortran_vec()); | |
6374 | |
6375 cholmod_factor *L; | |
6376 BEGIN_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE; | |
6377 L = CHOLMOD_NAME(analyze) (A, cm); | |
6378 CHOLMOD_NAME(factorize) (A, L, cm); | |
5681 | 6379 if (calc_cond) |
6380 rcond = CHOLMOD_NAME(rcond)(L, cm); | |
6381 else | |
6382 rcond = 1.0; | |
5506 | 6383 END_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE; |
6384 | |
6385 if (rcond == 0.0) | |
6386 { | |
6387 // Either its indefinite or singular. Try UMFPACK | |
6388 mattype.mark_as_unsymmetric (); | |
5785 | 6389 typ = MatrixType::Full; |
5506 | 6390 } |
6391 else | |
6392 { | |
6393 volatile double rcond_plus_one = rcond + 1.0; | |
6394 | |
6395 if (rcond_plus_one == 1.0 || xisnan (rcond)) | |
6396 { | |
6397 err = -2; | |
6398 | |
6399 if (sing_handler) | |
5681 | 6400 { |
6401 sing_handler (rcond); | |
6402 mattype.mark_as_rectangular (); | |
6403 } | |
5506 | 6404 else |
6405 (*current_liboctave_error_handler) | |
6406 ("SparseMatrix::solve matrix singular to machine precision, rcond = %g", | |
6407 rcond); | |
6408 | |
6409 return retval; | |
6410 } | |
6411 | |
6412 cholmod_dense *X; | |
6413 BEGIN_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE; | |
6414 X = CHOLMOD_NAME(solve) (CHOLMOD_A, L, B, cm); | |
6415 END_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE; | |
6416 | |
6417 retval.resize (b.rows (), b.cols()); | |
6418 for (octave_idx_type j = 0; j < b.cols(); j++) | |
6419 { | |
6420 octave_idx_type jr = j * b.rows(); | |
6421 for (octave_idx_type i = 0; i < b.rows(); i++) | |
6422 retval.xelem(i,j) = static_cast<Complex *>(X->x)[jr + i]; | |
6423 } | |
6424 | |
6425 BEGIN_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE; | |
6426 CHOLMOD_NAME(free_dense) (&X, cm); | |
6427 CHOLMOD_NAME(free_factor) (&L, cm); | |
6428 CHOLMOD_NAME(finish) (cm); | |
6482 | 6429 static char tmp[] = " "; |
6430 CHOLMOD_NAME(print_common) (tmp, cm); | |
5506 | 6431 END_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE; |
6432 } | |
6433 #else | |
5164 | 6434 (*current_liboctave_warning_handler) |
5506 | 6435 ("CHOLMOD not installed"); |
5164 | 6436 |
6437 mattype.mark_as_unsymmetric (); | |
5785 | 6438 typ = MatrixType::Full; |
5506 | 6439 #endif |
5164 | 6440 } |
6441 | |
5785 | 6442 if (typ == MatrixType::Full) |
5164 | 6443 { |
5203 | 6444 #ifdef HAVE_UMFPACK |
5164 | 6445 Matrix Control, Info; |
6446 void *Numeric = factorize (err, rcond, Control, Info, | |
5681 | 6447 sing_handler, calc_cond); |
5164 | 6448 |
6449 if (err == 0) | |
6450 { | |
5275 | 6451 octave_idx_type b_nr = b.rows (); |
6452 octave_idx_type b_nc = b.cols (); | |
5164 | 6453 int status = 0; |
6454 double *control = Control.fortran_vec (); | |
6455 double *info = Info.fortran_vec (); | |
5275 | 6456 const octave_idx_type *Ap = cidx (); |
6457 const octave_idx_type *Ai = ridx (); | |
5164 | 6458 const double *Ax = data (); |
6459 | |
6460 OCTAVE_LOCAL_BUFFER (double, Bx, b_nr); | |
6461 OCTAVE_LOCAL_BUFFER (double, Bz, b_nr); | |
6462 | |
6463 retval.resize (b_nr, b_nc); | |
6464 | |
6465 OCTAVE_LOCAL_BUFFER (double, Xx, b_nr); | |
6466 OCTAVE_LOCAL_BUFFER (double, Xz, b_nr); | |
6467 | |
5275 | 6468 for (octave_idx_type j = 0; j < b_nc; j++) |
5164 | 6469 { |
5275 | 6470 for (octave_idx_type i = 0; i < b_nr; i++) |
5164 | 6471 { |
6472 Complex c = b (i,j); | |
5261 | 6473 Bx[i] = std::real (c); |
6474 Bz[i] = std::imag (c); | |
5164 | 6475 } |
6476 | |
5322 | 6477 status = UMFPACK_DNAME (solve) (UMFPACK_A, Ap, |
6478 Ai, Ax, Xx, Bx, Numeric, control, | |
5164 | 6479 info); |
5322 | 6480 int status2 = UMFPACK_DNAME (solve) (UMFPACK_A, |
6481 Ap, Ai, Ax, Xz, Bz, Numeric, | |
5164 | 6482 control, info) ; |
6483 | |
6484 if (status < 0 || status2 < 0) | |
6485 { | |
6486 (*current_liboctave_error_handler) | |
6487 ("SparseMatrix::solve solve failed"); | |
6488 | |
5322 | 6489 UMFPACK_DNAME (report_status) (control, status); |
5164 | 6490 |
6491 err = -1; | |
6492 | |
6493 break; | |
6494 } | |
6495 | |
5275 | 6496 for (octave_idx_type i = 0; i < b_nr; i++) |
5164 | 6497 retval (i, j) = Complex (Xx[i], Xz[i]); |
6498 } | |
6499 | |
5322 | 6500 UMFPACK_DNAME (report_info) (control, info); |
6501 | |
6502 UMFPACK_DNAME (free_numeric) (&Numeric); | |
5164 | 6503 } |
5681 | 6504 else |
6505 mattype.mark_as_rectangular (); | |
6506 | |
5203 | 6507 #else |
6508 (*current_liboctave_error_handler) ("UMFPACK not installed"); | |
6509 #endif | |
5164 | 6510 } |
5785 | 6511 else if (typ != MatrixType::Hermitian) |
5164 | 6512 (*current_liboctave_error_handler) ("incorrect matrix type"); |
6513 } | |
6514 | |
6515 return retval; | |
6516 } | |
6517 | |
6518 SparseComplexMatrix | |
5785 | 6519 SparseMatrix::fsolve (MatrixType &mattype, const SparseComplexMatrix& b, |
5275 | 6520 octave_idx_type& err, double& rcond, |
5681 | 6521 solve_singularity_handler sing_handler, |
6522 bool calc_cond) const | |
5164 | 6523 { |
6524 SparseComplexMatrix retval; | |
6525 | |
5275 | 6526 octave_idx_type nr = rows (); |
6527 octave_idx_type nc = cols (); | |
5164 | 6528 err = 0; |
6529 | |
6924 | 6530 if (nr != nc || nr != b.rows ()) |
5164 | 6531 (*current_liboctave_error_handler) |
6532 ("matrix dimension mismatch solution of linear equations"); | |
6924 | 6533 else if (nr == 0 || b.cols () == 0) |
6534 retval = SparseComplexMatrix (nc, b.cols ()); | |
5164 | 6535 else |
6536 { | |
6537 // Print spparms("spumoni") info if requested | |
5506 | 6538 volatile int typ = mattype.type (); |
5164 | 6539 mattype.info (); |
6540 | |
5785 | 6541 if (typ == MatrixType::Hermitian) |
5164 | 6542 { |
5506 | 6543 #ifdef HAVE_CHOLMOD |
6544 cholmod_common Common; | |
6545 cholmod_common *cm = &Common; | |
6546 | |
6547 // Setup initial parameters | |
6548 CHOLMOD_NAME(start) (cm); | |
5526 | 6549 cm->prefer_zomplex = false; |
5506 | 6550 |
5893 | 6551 double spu = octave_sparse_params::get_key ("spumoni"); |
5506 | 6552 if (spu == 0.) |
6553 { | |
6554 cm->print = -1; | |
7520 | 6555 cm->print_function = 0; |
5506 | 6556 } |
6557 else | |
6558 { | |
5760 | 6559 cm->print = static_cast<int> (spu) + 2; |
5506 | 6560 cm->print_function =&SparseCholPrint; |
6561 } | |
6562 | |
6563 cm->error_handler = &SparseCholError; | |
6564 cm->complex_divide = CHOLMOD_NAME(divcomplex); | |
6565 cm->hypotenuse = CHOLMOD_NAME(hypot); | |
6566 | |
5526 | 6567 cm->final_ll = true; |
5506 | 6568 |
6569 cholmod_sparse Astore; | |
6570 cholmod_sparse *A = &Astore; | |
6571 double dummy; | |
6572 A->nrow = nr; | |
6573 A->ncol = nc; | |
6574 | |
6575 A->p = cidx(); | |
6576 A->i = ridx(); | |
5604 | 6577 A->nzmax = nnz(); |
5526 | 6578 A->packed = true; |
6579 A->sorted = true; | |
7520 | 6580 A->nz = 0; |
5506 | 6581 #ifdef IDX_TYPE_LONG |
6582 A->itype = CHOLMOD_LONG; | |
6583 #else | |
6584 A->itype = CHOLMOD_INT; | |
6585 #endif | |
6586 A->dtype = CHOLMOD_DOUBLE; | |
6587 A->stype = 1; | |
6588 A->xtype = CHOLMOD_REAL; | |
6589 | |
6590 if (nr < 1) | |
6591 A->x = &dummy; | |
6592 else | |
6593 A->x = data(); | |
6594 | |
6595 cholmod_sparse Bstore; | |
6596 cholmod_sparse *B = &Bstore; | |
6597 B->nrow = b.rows(); | |
6598 B->ncol = b.cols(); | |
6599 B->p = b.cidx(); | |
6600 B->i = b.ridx(); | |
5604 | 6601 B->nzmax = b.nnz(); |
5526 | 6602 B->packed = true; |
6603 B->sorted = true; | |
7520 | 6604 B->nz = 0; |
5506 | 6605 #ifdef IDX_TYPE_LONG |
6606 B->itype = CHOLMOD_LONG; | |
6607 #else | |
6608 B->itype = CHOLMOD_INT; | |
6609 #endif | |
6610 B->dtype = CHOLMOD_DOUBLE; | |
6611 B->stype = 0; | |
6612 B->xtype = CHOLMOD_COMPLEX; | |
6613 | |
6614 if (b.rows() < 1 || b.cols() < 1) | |
6615 B->x = &dummy; | |
6616 else | |
6617 B->x = b.data(); | |
6618 | |
6619 cholmod_factor *L; | |
6620 BEGIN_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE; | |
6621 L = CHOLMOD_NAME(analyze) (A, cm); | |
6622 CHOLMOD_NAME(factorize) (A, L, cm); | |
5681 | 6623 if (calc_cond) |
6624 rcond = CHOLMOD_NAME(rcond)(L, cm); | |
6625 else | |
6626 rcond = 1.0; | |
5506 | 6627 END_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE; |
6628 | |
6629 if (rcond == 0.0) | |
6630 { | |
6631 // Either its indefinite or singular. Try UMFPACK | |
6632 mattype.mark_as_unsymmetric (); | |
5785 | 6633 typ = MatrixType::Full; |
5506 | 6634 } |
6635 else | |
6636 { | |
6637 volatile double rcond_plus_one = rcond + 1.0; | |
6638 | |
6639 if (rcond_plus_one == 1.0 || xisnan (rcond)) | |
6640 { | |
6641 err = -2; | |
6642 | |
6643 if (sing_handler) | |
5681 | 6644 { |
6645 sing_handler (rcond); | |
6646 mattype.mark_as_rectangular (); | |
6647 } | |
5506 | 6648 else |
6649 (*current_liboctave_error_handler) | |
6650 ("SparseMatrix::solve matrix singular to machine precision, rcond = %g", | |
6651 rcond); | |
6652 | |
6653 return retval; | |
6654 } | |
6655 | |
6656 cholmod_sparse *X; | |
6657 BEGIN_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE; | |
6658 X = CHOLMOD_NAME(spsolve) (CHOLMOD_A, L, B, cm); | |
6659 END_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE; | |
6660 | |
6661 retval = SparseComplexMatrix | |
6662 (static_cast<octave_idx_type>(X->nrow), | |
6663 static_cast<octave_idx_type>(X->ncol), | |
6664 static_cast<octave_idx_type>(X->nzmax)); | |
6665 for (octave_idx_type j = 0; | |
6666 j <= static_cast<octave_idx_type>(X->ncol); j++) | |
6667 retval.xcidx(j) = static_cast<octave_idx_type *>(X->p)[j]; | |
6668 for (octave_idx_type j = 0; | |
6669 j < static_cast<octave_idx_type>(X->nzmax); j++) | |
6670 { | |
6671 retval.xridx(j) = static_cast<octave_idx_type *>(X->i)[j]; | |
6672 retval.xdata(j) = static_cast<Complex *>(X->x)[j]; | |
6673 } | |
6674 | |
6675 BEGIN_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE; | |
6676 CHOLMOD_NAME(free_sparse) (&X, cm); | |
6677 CHOLMOD_NAME(free_factor) (&L, cm); | |
6678 CHOLMOD_NAME(finish) (cm); | |
6482 | 6679 static char tmp[] = " "; |
6680 CHOLMOD_NAME(print_common) (tmp, cm); | |
5506 | 6681 END_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE; |
6682 } | |
6683 #else | |
5164 | 6684 (*current_liboctave_warning_handler) |
5506 | 6685 ("CHOLMOD not installed"); |
5164 | 6686 |
6687 mattype.mark_as_unsymmetric (); | |
5785 | 6688 typ = MatrixType::Full; |
5506 | 6689 #endif |
5164 | 6690 } |
6691 | |
5785 | 6692 if (typ == MatrixType::Full) |
5164 | 6693 { |
5203 | 6694 #ifdef HAVE_UMFPACK |
5164 | 6695 Matrix Control, Info; |
6696 void *Numeric = factorize (err, rcond, Control, Info, | |
5681 | 6697 sing_handler, calc_cond); |
5164 | 6698 |
6699 if (err == 0) | |
6700 { | |
5275 | 6701 octave_idx_type b_nr = b.rows (); |
6702 octave_idx_type b_nc = b.cols (); | |
5164 | 6703 int status = 0; |
6704 double *control = Control.fortran_vec (); | |
6705 double *info = Info.fortran_vec (); | |
5275 | 6706 const octave_idx_type *Ap = cidx (); |
6707 const octave_idx_type *Ai = ridx (); | |
5164 | 6708 const double *Ax = data (); |
6709 | |
6710 OCTAVE_LOCAL_BUFFER (double, Bx, b_nr); | |
6711 OCTAVE_LOCAL_BUFFER (double, Bz, b_nr); | |
6712 | |
6713 // Take a first guess that the number of non-zero terms | |
6714 // will be as many as in b | |
5681 | 6715 octave_idx_type x_nz = b.nnz (); |
5275 | 6716 octave_idx_type ii = 0; |
5164 | 6717 retval = SparseComplexMatrix (b_nr, b_nc, x_nz); |
6718 | |
6719 OCTAVE_LOCAL_BUFFER (double, Xx, b_nr); | |
6720 OCTAVE_LOCAL_BUFFER (double, Xz, b_nr); | |
6721 | |
6722 retval.xcidx(0) = 0; | |
5275 | 6723 for (octave_idx_type j = 0; j < b_nc; j++) |
5164 | 6724 { |
5275 | 6725 for (octave_idx_type i = 0; i < b_nr; i++) |
5164 | 6726 { |
6727 Complex c = b (i,j); | |
5261 | 6728 Bx[i] = std::real (c); |
6729 Bz[i] = std::imag (c); | |
5164 | 6730 } |
6731 | |
5322 | 6732 status = UMFPACK_DNAME (solve) (UMFPACK_A, Ap, |
6733 Ai, Ax, Xx, Bx, Numeric, control, | |
5164 | 6734 info); |
5322 | 6735 int status2 = UMFPACK_DNAME (solve) (UMFPACK_A, |
6736 Ap, Ai, Ax, Xz, Bz, Numeric, | |
5164 | 6737 control, info) ; |
6738 | |
6739 if (status < 0 || status2 < 0) | |
6740 { | |
6741 (*current_liboctave_error_handler) | |
6742 ("SparseMatrix::solve solve failed"); | |
6743 | |
5322 | 6744 UMFPACK_DNAME (report_status) (control, status); |
5164 | 6745 |
6746 err = -1; | |
6747 | |
6748 break; | |
6749 } | |
6750 | |
5275 | 6751 for (octave_idx_type i = 0; i < b_nr; i++) |
5164 | 6752 { |
6753 Complex tmp = Complex (Xx[i], Xz[i]); | |
6754 if (tmp != 0.0) | |
6755 { | |
6756 if (ii == x_nz) | |
6757 { | |
6758 // Resize the sparse matrix | |
5275 | 6759 octave_idx_type sz = x_nz * (b_nc - j) / b_nc; |
5164 | 6760 sz = (sz > 10 ? sz : 10) + x_nz; |
6761 retval.change_capacity (sz); | |
6762 x_nz = sz; | |
6763 } | |
6764 retval.xdata(ii) = tmp; | |
6765 retval.xridx(ii++) = i; | |
6766 } | |
6767 } | |
6768 retval.xcidx(j+1) = ii; | |
6769 } | |
6770 | |
6771 retval.maybe_compress (); | |
6772 | |
5322 | 6773 UMFPACK_DNAME (report_info) (control, info); |
6774 | |
6775 UMFPACK_DNAME (free_numeric) (&Numeric); | |
5164 | 6776 } |
5681 | 6777 else |
6778 mattype.mark_as_rectangular (); | |
5203 | 6779 #else |
6780 (*current_liboctave_error_handler) ("UMFPACK not installed"); | |
6781 #endif | |
5164 | 6782 } |
5785 | 6783 else if (typ != MatrixType::Hermitian) |
5164 | 6784 (*current_liboctave_error_handler) ("incorrect matrix type"); |
6785 } | |
6786 | |
6787 return retval; | |
6788 } | |
6789 | |
6790 Matrix | |
5785 | 6791 SparseMatrix::solve (MatrixType &mattype, const Matrix& b) const |
5164 | 6792 { |
5275 | 6793 octave_idx_type info; |
5164 | 6794 double rcond; |
6795 return solve (mattype, b, info, rcond, 0); | |
6796 } | |
6797 | |
6798 Matrix | |
5785 | 6799 SparseMatrix::solve (MatrixType &mattype, const Matrix& b, |
5697 | 6800 octave_idx_type& info) const |
5164 | 6801 { |
6802 double rcond; | |
6803 return solve (mattype, b, info, rcond, 0); | |
6804 } | |
6805 | |
6806 Matrix | |
5785 | 6807 SparseMatrix::solve (MatrixType &mattype, const Matrix& b, octave_idx_type& info, |
5164 | 6808 double& rcond) const |
6809 { | |
6810 return solve (mattype, b, info, rcond, 0); | |
6811 } | |
6812 | |
6813 Matrix | |
5785 | 6814 SparseMatrix::solve (MatrixType &mattype, const Matrix& b, octave_idx_type& err, |
5697 | 6815 double& rcond, solve_singularity_handler sing_handler, |
6816 bool singular_fallback) const | |
5164 | 6817 { |
5681 | 6818 Matrix retval; |
5322 | 6819 int typ = mattype.type (false); |
5164 | 6820 |
5785 | 6821 if (typ == MatrixType::Unknown) |
5164 | 6822 typ = mattype.type (*this); |
6823 | |
5681 | 6824 // Only calculate the condition number for CHOLMOD/UMFPACK |
5785 | 6825 if (typ == MatrixType::Diagonal || typ == MatrixType::Permuted_Diagonal) |
5681 | 6826 retval = dsolve (mattype, b, err, rcond, sing_handler, false); |
5785 | 6827 else if (typ == MatrixType::Upper || typ == MatrixType::Permuted_Upper) |
5681 | 6828 retval = utsolve (mattype, b, err, rcond, sing_handler, false); |
5785 | 6829 else if (typ == MatrixType::Lower || typ == MatrixType::Permuted_Lower) |
5681 | 6830 retval = ltsolve (mattype, b, err, rcond, sing_handler, false); |
5785 | 6831 else if (typ == MatrixType::Banded || typ == MatrixType::Banded_Hermitian) |
5681 | 6832 retval = bsolve (mattype, b, err, rcond, sing_handler, false); |
5785 | 6833 else if (typ == MatrixType::Tridiagonal || |
6834 typ == MatrixType::Tridiagonal_Hermitian) | |
5681 | 6835 retval = trisolve (mattype, b, err, rcond, sing_handler, false); |
5785 | 6836 else if (typ == MatrixType::Full || typ == MatrixType::Hermitian) |
5681 | 6837 retval = fsolve (mattype, b, err, rcond, sing_handler, true); |
5785 | 6838 else if (typ != MatrixType::Rectangular) |
5164 | 6839 { |
5681 | 6840 (*current_liboctave_error_handler) ("unknown matrix type"); |
5164 | 6841 return Matrix (); |
6842 } | |
5681 | 6843 |
6844 // Rectangular or one of the above solvers flags a singular matrix | |
5785 | 6845 if (singular_fallback && mattype.type (false) == MatrixType::Rectangular) |
5681 | 6846 { |
6847 rcond = 1.; | |
6848 #ifdef USE_QRSOLVE | |
6849 retval = qrsolve (*this, b, err); | |
6850 #else | |
6851 retval = dmsolve<Matrix, SparseMatrix, Matrix> (*this, b, err); | |
6852 #endif | |
6853 } | |
6854 | |
6855 return retval; | |
5164 | 6856 } |
6857 | |
6858 SparseMatrix | |
5785 | 6859 SparseMatrix::solve (MatrixType &mattype, const SparseMatrix& b) const |
5164 | 6860 { |
5275 | 6861 octave_idx_type info; |
5164 | 6862 double rcond; |
6863 return solve (mattype, b, info, rcond, 0); | |
6864 } | |
6865 | |
6866 SparseMatrix | |
5785 | 6867 SparseMatrix::solve (MatrixType &mattype, const SparseMatrix& b, |
5275 | 6868 octave_idx_type& info) const |
5164 | 6869 { |
6870 double rcond; | |
6871 return solve (mattype, b, info, rcond, 0); | |
6872 } | |
6873 | |
6874 SparseMatrix | |
5785 | 6875 SparseMatrix::solve (MatrixType &mattype, const SparseMatrix& b, |
5275 | 6876 octave_idx_type& info, double& rcond) const |
5164 | 6877 { |
6878 return solve (mattype, b, info, rcond, 0); | |
6879 } | |
6880 | |
6881 SparseMatrix | |
5785 | 6882 SparseMatrix::solve (MatrixType &mattype, const SparseMatrix& b, |
5275 | 6883 octave_idx_type& err, double& rcond, |
5697 | 6884 solve_singularity_handler sing_handler, |
6885 bool singular_fallback) const | |
5164 | 6886 { |
5681 | 6887 SparseMatrix retval; |
5322 | 6888 int typ = mattype.type (false); |
5164 | 6889 |
5785 | 6890 if (typ == MatrixType::Unknown) |
5164 | 6891 typ = mattype.type (*this); |
6892 | |
5785 | 6893 if (typ == MatrixType::Diagonal || typ == MatrixType::Permuted_Diagonal) |
5681 | 6894 retval = dsolve (mattype, b, err, rcond, sing_handler, false); |
5785 | 6895 else if (typ == MatrixType::Upper || typ == MatrixType::Permuted_Upper) |
5681 | 6896 retval = utsolve (mattype, b, err, rcond, sing_handler, false); |
5785 | 6897 else if (typ == MatrixType::Lower || typ == MatrixType::Permuted_Lower) |
5681 | 6898 retval = ltsolve (mattype, b, err, rcond, sing_handler, false); |
5785 | 6899 else if (typ == MatrixType::Banded || typ == MatrixType::Banded_Hermitian) |
5681 | 6900 retval = bsolve (mattype, b, err, rcond, sing_handler, false); |
5785 | 6901 else if (typ == MatrixType::Tridiagonal || |
6902 typ == MatrixType::Tridiagonal_Hermitian) | |
5681 | 6903 retval = trisolve (mattype, b, err, rcond, sing_handler, false); |
5785 | 6904 else if (typ == MatrixType::Full || typ == MatrixType::Hermitian) |
5681 | 6905 retval = fsolve (mattype, b, err, rcond, sing_handler, true); |
5785 | 6906 else if (typ != MatrixType::Rectangular) |
5164 | 6907 { |
5681 | 6908 (*current_liboctave_error_handler) ("unknown matrix type"); |
5164 | 6909 return SparseMatrix (); |
6910 } | |
5681 | 6911 |
5785 | 6912 if (singular_fallback && mattype.type (false) == MatrixType::Rectangular) |
5681 | 6913 { |
6914 rcond = 1.; | |
6915 #ifdef USE_QRSOLVE | |
6916 retval = qrsolve (*this, b, err); | |
6917 #else | |
6918 retval = dmsolve<SparseMatrix, SparseMatrix, | |
6919 SparseMatrix> (*this, b, err); | |
6920 #endif | |
6921 } | |
6922 | |
6923 return retval; | |
5164 | 6924 } |
6925 | |
6926 ComplexMatrix | |
5785 | 6927 SparseMatrix::solve (MatrixType &mattype, const ComplexMatrix& b) const |
5164 | 6928 { |
5275 | 6929 octave_idx_type info; |
5164 | 6930 double rcond; |
6931 return solve (mattype, b, info, rcond, 0); | |
6932 } | |
6933 | |
6934 ComplexMatrix | |
5785 | 6935 SparseMatrix::solve (MatrixType &mattype, const ComplexMatrix& b, |
5275 | 6936 octave_idx_type& info) const |
5164 | 6937 { |
6938 double rcond; | |
6939 return solve (mattype, b, info, rcond, 0); | |
6940 } | |
6941 | |
6942 ComplexMatrix | |
5785 | 6943 SparseMatrix::solve (MatrixType &mattype, const ComplexMatrix& b, |
5275 | 6944 octave_idx_type& info, double& rcond) const |
5164 | 6945 { |
6946 return solve (mattype, b, info, rcond, 0); | |
6947 } | |
6948 | |
6949 ComplexMatrix | |
5785 | 6950 SparseMatrix::solve (MatrixType &mattype, const ComplexMatrix& b, |
5275 | 6951 octave_idx_type& err, double& rcond, |
5697 | 6952 solve_singularity_handler sing_handler, |
6953 bool singular_fallback) const | |
5164 | 6954 { |
5681 | 6955 ComplexMatrix retval; |
5322 | 6956 int typ = mattype.type (false); |
5164 | 6957 |
5785 | 6958 if (typ == MatrixType::Unknown) |
5164 | 6959 typ = mattype.type (*this); |
6960 | |
5785 | 6961 if (typ == MatrixType::Diagonal || typ == MatrixType::Permuted_Diagonal) |
5681 | 6962 retval = dsolve (mattype, b, err, rcond, sing_handler, false); |
5785 | 6963 else if (typ == MatrixType::Upper || typ == MatrixType::Permuted_Upper) |
5681 | 6964 retval = utsolve (mattype, b, err, rcond, sing_handler, false); |
5785 | 6965 else if (typ == MatrixType::Lower || typ == MatrixType::Permuted_Lower) |
5681 | 6966 retval = ltsolve (mattype, b, err, rcond, sing_handler, false); |
5785 | 6967 else if (typ == MatrixType::Banded || typ == MatrixType::Banded_Hermitian) |
5681 | 6968 retval = bsolve (mattype, b, err, rcond, sing_handler, false); |
5785 | 6969 else if (typ == MatrixType::Tridiagonal || |
6970 typ == MatrixType::Tridiagonal_Hermitian) | |
5681 | 6971 retval = trisolve (mattype, b, err, rcond, sing_handler, false); |
5785 | 6972 else if (typ == MatrixType::Full || typ == MatrixType::Hermitian) |
5681 | 6973 retval = fsolve (mattype, b, err, rcond, sing_handler, true); |
5785 | 6974 else if (typ != MatrixType::Rectangular) |
5164 | 6975 { |
5681 | 6976 (*current_liboctave_error_handler) ("unknown matrix type"); |
5164 | 6977 return ComplexMatrix (); |
6978 } | |
5681 | 6979 |
5785 | 6980 if (singular_fallback && mattype.type(false) == MatrixType::Rectangular) |
5681 | 6981 { |
6982 rcond = 1.; | |
6983 #ifdef USE_QRSOLVE | |
6984 retval = qrsolve (*this, b, err); | |
6985 #else | |
6986 retval = dmsolve<ComplexMatrix, SparseMatrix, | |
6987 ComplexMatrix> (*this, b, err); | |
6988 #endif | |
6989 } | |
6990 | |
6991 return retval; | |
5164 | 6992 } |
6993 | |
6994 SparseComplexMatrix | |
5785 | 6995 SparseMatrix::solve (MatrixType &mattype, const SparseComplexMatrix& b) const |
5164 | 6996 { |
5275 | 6997 octave_idx_type info; |
5164 | 6998 double rcond; |
6999 return solve (mattype, b, info, rcond, 0); | |
7000 } | |
7001 | |
7002 SparseComplexMatrix | |
5785 | 7003 SparseMatrix::solve (MatrixType &mattype, const SparseComplexMatrix& b, |
5275 | 7004 octave_idx_type& info) const |
5164 | 7005 { |
7006 double rcond; | |
7007 return solve (mattype, b, info, rcond, 0); | |
7008 } | |
7009 | |
7010 SparseComplexMatrix | |
5785 | 7011 SparseMatrix::solve (MatrixType &mattype, const SparseComplexMatrix& b, |
5275 | 7012 octave_idx_type& info, double& rcond) const |
5164 | 7013 { |
7014 return solve (mattype, b, info, rcond, 0); | |
7015 } | |
7016 | |
7017 SparseComplexMatrix | |
5785 | 7018 SparseMatrix::solve (MatrixType &mattype, const SparseComplexMatrix& b, |
5275 | 7019 octave_idx_type& err, double& rcond, |
5697 | 7020 solve_singularity_handler sing_handler, |
7021 bool singular_fallback) const | |
5164 | 7022 { |
5681 | 7023 SparseComplexMatrix retval; |
5322 | 7024 int typ = mattype.type (false); |
5164 | 7025 |
5785 | 7026 if (typ == MatrixType::Unknown) |
5164 | 7027 typ = mattype.type (*this); |
7028 | |
5785 | 7029 if (typ == MatrixType::Diagonal || typ == MatrixType::Permuted_Diagonal) |
5681 | 7030 retval = dsolve (mattype, b, err, rcond, sing_handler, false); |
5785 | 7031 else if (typ == MatrixType::Upper || typ == MatrixType::Permuted_Upper) |
5681 | 7032 retval = utsolve (mattype, b, err, rcond, sing_handler, false); |
5785 | 7033 else if (typ == MatrixType::Lower || typ == MatrixType::Permuted_Lower) |
5681 | 7034 retval = ltsolve (mattype, b, err, rcond, sing_handler, false); |
5785 | 7035 else if (typ == MatrixType::Banded || typ == MatrixType::Banded_Hermitian) |
5681 | 7036 retval = bsolve (mattype, b, err, rcond, sing_handler, false); |
5785 | 7037 else if (typ == MatrixType::Tridiagonal || |
7038 typ == MatrixType::Tridiagonal_Hermitian) | |
5681 | 7039 retval = trisolve (mattype, b, err, rcond, sing_handler, false); |
5785 | 7040 else if (typ == MatrixType::Full || typ == MatrixType::Hermitian) |
5681 | 7041 retval = fsolve (mattype, b, err, rcond, sing_handler, true); |
5785 | 7042 else if (typ != MatrixType::Rectangular) |
5164 | 7043 { |
5681 | 7044 (*current_liboctave_error_handler) ("unknown matrix type"); |
5164 | 7045 return SparseComplexMatrix (); |
7046 } | |
5681 | 7047 |
5785 | 7048 if (singular_fallback && mattype.type(false) == MatrixType::Rectangular) |
5681 | 7049 { |
7050 rcond = 1.; | |
7051 #ifdef USE_QRSOLVE | |
7052 retval = qrsolve (*this, b, err); | |
7053 #else | |
7054 retval = dmsolve<SparseComplexMatrix, SparseMatrix, | |
7055 SparseComplexMatrix> (*this, b, err); | |
7056 #endif | |
7057 } | |
7058 | |
7059 return retval; | |
5164 | 7060 } |
7061 | |
7062 ColumnVector | |
5785 | 7063 SparseMatrix::solve (MatrixType &mattype, const ColumnVector& b) const |
5164 | 7064 { |
5275 | 7065 octave_idx_type info; double rcond; |
5164 | 7066 return solve (mattype, b, info, rcond); |
7067 } | |
7068 | |
7069 ColumnVector | |
5785 | 7070 SparseMatrix::solve (MatrixType &mattype, const ColumnVector& b, octave_idx_type& info) const |
5164 | 7071 { |
7072 double rcond; | |
7073 return solve (mattype, b, info, rcond); | |
7074 } | |
7075 | |
7076 ColumnVector | |
5785 | 7077 SparseMatrix::solve (MatrixType &mattype, const ColumnVector& b, octave_idx_type& info, double& rcond) const |
5164 | 7078 { |
7079 return solve (mattype, b, info, rcond, 0); | |
7080 } | |
7081 | |
7082 ColumnVector | |
5785 | 7083 SparseMatrix::solve (MatrixType &mattype, const ColumnVector& b, octave_idx_type& info, double& rcond, |
5164 | 7084 solve_singularity_handler sing_handler) const |
7085 { | |
7086 Matrix tmp (b); | |
5275 | 7087 return solve (mattype, tmp, info, rcond, sing_handler).column (static_cast<octave_idx_type> (0)); |
5164 | 7088 } |
7089 | |
7090 ComplexColumnVector | |
5785 | 7091 SparseMatrix::solve (MatrixType &mattype, const ComplexColumnVector& b) const |
5164 | 7092 { |
5275 | 7093 octave_idx_type info; |
5164 | 7094 double rcond; |
7095 return solve (mattype, b, info, rcond, 0); | |
7096 } | |
7097 | |
7098 ComplexColumnVector | |
5785 | 7099 SparseMatrix::solve (MatrixType &mattype, const ComplexColumnVector& b, octave_idx_type& info) const |
5164 | 7100 { |
7101 double rcond; | |
7102 return solve (mattype, b, info, rcond, 0); | |
7103 } | |
7104 | |
7105 ComplexColumnVector | |
5785 | 7106 SparseMatrix::solve (MatrixType &mattype, const ComplexColumnVector& b, octave_idx_type& info, |
5164 | 7107 double& rcond) const |
7108 { | |
7109 return solve (mattype, b, info, rcond, 0); | |
7110 } | |
7111 | |
7112 ComplexColumnVector | |
5785 | 7113 SparseMatrix::solve (MatrixType &mattype, const ComplexColumnVector& b, octave_idx_type& info, double& rcond, |
5164 | 7114 solve_singularity_handler sing_handler) const |
7115 { | |
7116 ComplexMatrix tmp (b); | |
5275 | 7117 return solve (mattype, tmp, info, rcond, sing_handler).column (static_cast<octave_idx_type> (0)); |
5164 | 7118 } |
7119 | |
7120 Matrix | |
7121 SparseMatrix::solve (const Matrix& b) const | |
7122 { | |
5275 | 7123 octave_idx_type info; |
5164 | 7124 double rcond; |
7125 return solve (b, info, rcond, 0); | |
7126 } | |
7127 | |
7128 Matrix | |
5275 | 7129 SparseMatrix::solve (const Matrix& b, octave_idx_type& info) const |
5164 | 7130 { |
7131 double rcond; | |
7132 return solve (b, info, rcond, 0); | |
7133 } | |
7134 | |
7135 Matrix | |
5275 | 7136 SparseMatrix::solve (const Matrix& b, octave_idx_type& info, |
5164 | 7137 double& rcond) const |
7138 { | |
7139 return solve (b, info, rcond, 0); | |
7140 } | |
7141 | |
7142 Matrix | |
5275 | 7143 SparseMatrix::solve (const Matrix& b, octave_idx_type& err, |
5164 | 7144 double& rcond, |
7145 solve_singularity_handler sing_handler) const | |
7146 { | |
5785 | 7147 MatrixType mattype (*this); |
5164 | 7148 return solve (mattype, b, err, rcond, sing_handler); |
7149 } | |
7150 | |
7151 SparseMatrix | |
7152 SparseMatrix::solve (const SparseMatrix& b) const | |
7153 { | |
5275 | 7154 octave_idx_type info; |
5164 | 7155 double rcond; |
7156 return solve (b, info, rcond, 0); | |
7157 } | |
7158 | |
7159 SparseMatrix | |
7160 SparseMatrix::solve (const SparseMatrix& b, | |
5275 | 7161 octave_idx_type& info) const |
5164 | 7162 { |
7163 double rcond; | |
7164 return solve (b, info, rcond, 0); | |
7165 } | |
7166 | |
7167 SparseMatrix | |
7168 SparseMatrix::solve (const SparseMatrix& b, | |
5275 | 7169 octave_idx_type& info, double& rcond) const |
5164 | 7170 { |
7171 return solve (b, info, rcond, 0); | |
7172 } | |
7173 | |
7174 SparseMatrix | |
7175 SparseMatrix::solve (const SparseMatrix& b, | |
5275 | 7176 octave_idx_type& err, double& rcond, |
5164 | 7177 solve_singularity_handler sing_handler) const |
7178 { | |
5785 | 7179 MatrixType mattype (*this); |
5164 | 7180 return solve (mattype, b, err, rcond, sing_handler); |
7181 } | |
7182 | |
7183 ComplexMatrix | |
7184 SparseMatrix::solve (const ComplexMatrix& b, | |
5275 | 7185 octave_idx_type& info) const |
5164 | 7186 { |
7187 double rcond; | |
7188 return solve (b, info, rcond, 0); | |
7189 } | |
7190 | |
7191 ComplexMatrix | |
7192 SparseMatrix::solve (const ComplexMatrix& b, | |
5275 | 7193 octave_idx_type& info, double& rcond) const |
5164 | 7194 { |
7195 return solve (b, info, rcond, 0); | |
7196 } | |
7197 | |
7198 ComplexMatrix | |
7199 SparseMatrix::solve (const ComplexMatrix& b, | |
5275 | 7200 octave_idx_type& err, double& rcond, |
5164 | 7201 solve_singularity_handler sing_handler) const |
7202 { | |
5785 | 7203 MatrixType mattype (*this); |
5164 | 7204 return solve (mattype, b, err, rcond, sing_handler); |
7205 } | |
7206 | |
7207 SparseComplexMatrix | |
7208 SparseMatrix::solve (const SparseComplexMatrix& b) const | |
7209 { | |
5275 | 7210 octave_idx_type info; |
5164 | 7211 double rcond; |
7212 return solve (b, info, rcond, 0); | |
7213 } | |
7214 | |
7215 SparseComplexMatrix | |
7216 SparseMatrix::solve (const SparseComplexMatrix& b, | |
5275 | 7217 octave_idx_type& info) const |
5164 | 7218 { |
7219 double rcond; | |
7220 return solve (b, info, rcond, 0); | |
7221 } | |
7222 | |
7223 SparseComplexMatrix | |
7224 SparseMatrix::solve (const SparseComplexMatrix& b, | |
5275 | 7225 octave_idx_type& info, double& rcond) const |
5164 | 7226 { |
7227 return solve (b, info, rcond, 0); | |
7228 } | |
7229 | |
7230 SparseComplexMatrix | |
7231 SparseMatrix::solve (const SparseComplexMatrix& b, | |
5275 | 7232 octave_idx_type& err, double& rcond, |
5164 | 7233 solve_singularity_handler sing_handler) const |
7234 { | |
5785 | 7235 MatrixType mattype (*this); |
5164 | 7236 return solve (mattype, b, err, rcond, sing_handler); |
7237 } | |
7238 | |
7239 ColumnVector | |
7240 SparseMatrix::solve (const ColumnVector& b) const | |
7241 { | |
5275 | 7242 octave_idx_type info; double rcond; |
5164 | 7243 return solve (b, info, rcond); |
7244 } | |
7245 | |
7246 ColumnVector | |
5275 | 7247 SparseMatrix::solve (const ColumnVector& b, octave_idx_type& info) const |
5164 | 7248 { |
7249 double rcond; | |
7250 return solve (b, info, rcond); | |
7251 } | |
7252 | |
7253 ColumnVector | |
5275 | 7254 SparseMatrix::solve (const ColumnVector& b, octave_idx_type& info, double& rcond) const |
5164 | 7255 { |
7256 return solve (b, info, rcond, 0); | |
7257 } | |
7258 | |
7259 ColumnVector | |
5275 | 7260 SparseMatrix::solve (const ColumnVector& b, octave_idx_type& info, double& rcond, |
5164 | 7261 solve_singularity_handler sing_handler) const |
7262 { | |
7263 Matrix tmp (b); | |
5275 | 7264 return solve (tmp, info, rcond, sing_handler).column (static_cast<octave_idx_type> (0)); |
5164 | 7265 } |
7266 | |
7267 ComplexColumnVector | |
7268 SparseMatrix::solve (const ComplexColumnVector& b) const | |
7269 { | |
5275 | 7270 octave_idx_type info; |
5164 | 7271 double rcond; |
7272 return solve (b, info, rcond, 0); | |
7273 } | |
7274 | |
7275 ComplexColumnVector | |
5275 | 7276 SparseMatrix::solve (const ComplexColumnVector& b, octave_idx_type& info) const |
5164 | 7277 { |
7278 double rcond; | |
7279 return solve (b, info, rcond, 0); | |
7280 } | |
7281 | |
7282 ComplexColumnVector | |
5275 | 7283 SparseMatrix::solve (const ComplexColumnVector& b, octave_idx_type& info, |
5164 | 7284 double& rcond) const |
7285 { | |
7286 return solve (b, info, rcond, 0); | |
7287 } | |
7288 | |
7289 ComplexColumnVector | |
5275 | 7290 SparseMatrix::solve (const ComplexColumnVector& b, octave_idx_type& info, double& rcond, |
5164 | 7291 solve_singularity_handler sing_handler) const |
7292 { | |
7293 ComplexMatrix tmp (b); | |
5275 | 7294 return solve (tmp, info, rcond, sing_handler).column (static_cast<octave_idx_type> (0)); |
5164 | 7295 } |
7296 | |
7297 // other operations. | |
7298 | |
7299 bool | |
7300 SparseMatrix::any_element_is_negative (bool neg_zero) const | |
7301 { | |
5681 | 7302 octave_idx_type nel = nnz (); |
5164 | 7303 |
7304 if (neg_zero) | |
7305 { | |
5275 | 7306 for (octave_idx_type i = 0; i < nel; i++) |
5164 | 7307 if (lo_ieee_signbit (data (i))) |
7308 return true; | |
7309 } | |
7310 else | |
7311 { | |
5275 | 7312 for (octave_idx_type i = 0; i < nel; i++) |
5164 | 7313 if (data (i) < 0) |
7314 return true; | |
7315 } | |
7316 | |
7317 return false; | |
7318 } | |
7319 | |
7320 bool | |
7922
935be827eaf8
error for NaN values in & and | expressions
John W. Eaton <jwe@octave.org>
parents:
7802
diff
changeset
|
7321 SparseMatrix::any_element_is_nan (void) const |
935be827eaf8
error for NaN values in & and | expressions
John W. Eaton <jwe@octave.org>
parents:
7802
diff
changeset
|
7322 { |
935be827eaf8
error for NaN values in & and | expressions
John W. Eaton <jwe@octave.org>
parents:
7802
diff
changeset
|
7323 octave_idx_type nel = nnz (); |
935be827eaf8
error for NaN values in & and | expressions
John W. Eaton <jwe@octave.org>
parents:
7802
diff
changeset
|
7324 |
935be827eaf8
error for NaN values in & and | expressions
John W. Eaton <jwe@octave.org>
parents:
7802
diff
changeset
|
7325 for (octave_idx_type i = 0; i < nel; i++) |
935be827eaf8
error for NaN values in & and | expressions
John W. Eaton <jwe@octave.org>
parents:
7802
diff
changeset
|
7326 { |
935be827eaf8
error for NaN values in & and | expressions
John W. Eaton <jwe@octave.org>
parents:
7802
diff
changeset
|
7327 double val = data (i); |
935be827eaf8
error for NaN values in & and | expressions
John W. Eaton <jwe@octave.org>
parents:
7802
diff
changeset
|
7328 if (xisnan (val)) |
935be827eaf8
error for NaN values in & and | expressions
John W. Eaton <jwe@octave.org>
parents:
7802
diff
changeset
|
7329 return true; |
935be827eaf8
error for NaN values in & and | expressions
John W. Eaton <jwe@octave.org>
parents:
7802
diff
changeset
|
7330 } |
935be827eaf8
error for NaN values in & and | expressions
John W. Eaton <jwe@octave.org>
parents:
7802
diff
changeset
|
7331 |
935be827eaf8
error for NaN values in & and | expressions
John W. Eaton <jwe@octave.org>
parents:
7802
diff
changeset
|
7332 return false; |
935be827eaf8
error for NaN values in & and | expressions
John W. Eaton <jwe@octave.org>
parents:
7802
diff
changeset
|
7333 } |
935be827eaf8
error for NaN values in & and | expressions
John W. Eaton <jwe@octave.org>
parents:
7802
diff
changeset
|
7334 |
935be827eaf8
error for NaN values in & and | expressions
John W. Eaton <jwe@octave.org>
parents:
7802
diff
changeset
|
7335 bool |
5164 | 7336 SparseMatrix::any_element_is_inf_or_nan (void) const |
7337 { | |
5681 | 7338 octave_idx_type nel = nnz (); |
5275 | 7339 |
7340 for (octave_idx_type i = 0; i < nel; i++) | |
5164 | 7341 { |
7342 double val = data (i); | |
7343 if (xisinf (val) || xisnan (val)) | |
7344 return true; | |
7345 } | |
7346 | |
7347 return false; | |
7348 } | |
7349 | |
7350 bool | |
9852
aabf7a8c2e57
implement sparse logical conversion
Jaroslav Hajek <highegg@gmail.com>
parents:
9812
diff
changeset
|
7351 SparseMatrix::any_element_not_one_or_zero (void) const |
aabf7a8c2e57
implement sparse logical conversion
Jaroslav Hajek <highegg@gmail.com>
parents:
9812
diff
changeset
|
7352 { |
aabf7a8c2e57
implement sparse logical conversion
Jaroslav Hajek <highegg@gmail.com>
parents:
9812
diff
changeset
|
7353 octave_idx_type nel = nnz (); |
aabf7a8c2e57
implement sparse logical conversion
Jaroslav Hajek <highegg@gmail.com>
parents:
9812
diff
changeset
|
7354 |
aabf7a8c2e57
implement sparse logical conversion
Jaroslav Hajek <highegg@gmail.com>
parents:
9812
diff
changeset
|
7355 for (octave_idx_type i = 0; i < nel; i++) |
aabf7a8c2e57
implement sparse logical conversion
Jaroslav Hajek <highegg@gmail.com>
parents:
9812
diff
changeset
|
7356 { |
aabf7a8c2e57
implement sparse logical conversion
Jaroslav Hajek <highegg@gmail.com>
parents:
9812
diff
changeset
|
7357 double val = data (i); |
aabf7a8c2e57
implement sparse logical conversion
Jaroslav Hajek <highegg@gmail.com>
parents:
9812
diff
changeset
|
7358 if (val != 0.0 && val != 1.0) |
aabf7a8c2e57
implement sparse logical conversion
Jaroslav Hajek <highegg@gmail.com>
parents:
9812
diff
changeset
|
7359 return true; |
aabf7a8c2e57
implement sparse logical conversion
Jaroslav Hajek <highegg@gmail.com>
parents:
9812
diff
changeset
|
7360 } |
aabf7a8c2e57
implement sparse logical conversion
Jaroslav Hajek <highegg@gmail.com>
parents:
9812
diff
changeset
|
7361 |
aabf7a8c2e57
implement sparse logical conversion
Jaroslav Hajek <highegg@gmail.com>
parents:
9812
diff
changeset
|
7362 return false; |
aabf7a8c2e57
implement sparse logical conversion
Jaroslav Hajek <highegg@gmail.com>
parents:
9812
diff
changeset
|
7363 } |
aabf7a8c2e57
implement sparse logical conversion
Jaroslav Hajek <highegg@gmail.com>
parents:
9812
diff
changeset
|
7364 |
aabf7a8c2e57
implement sparse logical conversion
Jaroslav Hajek <highegg@gmail.com>
parents:
9812
diff
changeset
|
7365 bool |
6989 | 7366 SparseMatrix::all_elements_are_zero (void) const |
7367 { | |
7368 octave_idx_type nel = nnz (); | |
7369 | |
7370 for (octave_idx_type i = 0; i < nel; i++) | |
7371 if (data (i) != 0) | |
7372 return false; | |
7373 | |
7374 return true; | |
7375 } | |
7376 | |
7377 bool | |
5164 | 7378 SparseMatrix::all_elements_are_int_or_inf_or_nan (void) const |
7379 { | |
5681 | 7380 octave_idx_type nel = nnz (); |
5275 | 7381 |
7382 for (octave_idx_type i = 0; i < nel; i++) | |
5164 | 7383 { |
7384 double val = data (i); | |
7385 if (xisnan (val) || D_NINT (val) == val) | |
7386 continue; | |
7387 else | |
7388 return false; | |
7389 } | |
7390 | |
7391 return true; | |
7392 } | |
7393 | |
7394 // Return nonzero if any element of M is not an integer. Also extract | |
7395 // the largest and smallest values and return them in MAX_VAL and MIN_VAL. | |
7396 | |
7397 bool | |
7398 SparseMatrix::all_integers (double& max_val, double& min_val) const | |
7399 { | |
5681 | 7400 octave_idx_type nel = nnz (); |
5164 | 7401 |
7402 if (nel == 0) | |
7403 return false; | |
7404 | |
7405 max_val = data (0); | |
7406 min_val = data (0); | |
7407 | |
5275 | 7408 for (octave_idx_type i = 0; i < nel; i++) |
5164 | 7409 { |
7410 double val = data (i); | |
7411 | |
7412 if (val > max_val) | |
7413 max_val = val; | |
7414 | |
7415 if (val < min_val) | |
7416 min_val = val; | |
7417 | |
7418 if (D_NINT (val) != val) | |
7419 return false; | |
7420 } | |
7421 | |
7422 return true; | |
7423 } | |
7424 | |
7425 bool | |
7426 SparseMatrix::too_large_for_float (void) const | |
7427 { | |
5681 | 7428 octave_idx_type nel = nnz (); |
5275 | 7429 |
7430 for (octave_idx_type i = 0; i < nel; i++) | |
5164 | 7431 { |
7432 double val = data (i); | |
7433 | |
7434 if (val > FLT_MAX || val < FLT_MIN) | |
7435 return true; | |
7436 } | |
7437 | |
7438 return false; | |
7439 } | |
7440 | |
7441 SparseBoolMatrix | |
7442 SparseMatrix::operator ! (void) const | |
7443 { | |
5275 | 7444 octave_idx_type nr = rows (); |
7445 octave_idx_type nc = cols (); | |
5681 | 7446 octave_idx_type nz1 = nnz (); |
5275 | 7447 octave_idx_type nz2 = nr*nc - nz1; |
5164 | 7448 |
7449 SparseBoolMatrix r (nr, nc, nz2); | |
7450 | |
5275 | 7451 octave_idx_type ii = 0; |
7452 octave_idx_type jj = 0; | |
5164 | 7453 r.cidx (0) = 0; |
5275 | 7454 for (octave_idx_type i = 0; i < nc; i++) |
5164 | 7455 { |
5275 | 7456 for (octave_idx_type j = 0; j < nr; j++) |
5164 | 7457 { |
7458 if (jj < cidx(i+1) && ridx(jj) == j) | |
7459 jj++; | |
7460 else | |
7461 { | |
7462 r.data(ii) = true; | |
7463 r.ridx(ii++) = j; | |
7464 } | |
7465 } | |
7466 r.cidx (i+1) = ii; | |
7467 } | |
7468 | |
7469 return r; | |
7470 } | |
7471 | |
5775 | 7472 // FIXME Do these really belong here? Maybe they should be |
5164 | 7473 // in a base class? |
7474 | |
7475 SparseBoolMatrix | |
7476 SparseMatrix::all (int dim) const | |
7477 { | |
7478 SPARSE_ALL_OP (dim); | |
7479 } | |
7480 | |
7481 SparseBoolMatrix | |
7482 SparseMatrix::any (int dim) const | |
7483 { | |
7484 SPARSE_ANY_OP (dim); | |
7485 } | |
7486 | |
7487 SparseMatrix | |
7488 SparseMatrix::cumprod (int dim) const | |
7489 { | |
7490 SPARSE_CUMPROD (SparseMatrix, double, cumprod); | |
7491 } | |
7492 | |
7493 SparseMatrix | |
7494 SparseMatrix::cumsum (int dim) const | |
7495 { | |
7496 SPARSE_CUMSUM (SparseMatrix, double, cumsum); | |
7497 } | |
7498 | |
7499 SparseMatrix | |
7500 SparseMatrix::prod (int dim) const | |
7501 { | |
7269 | 7502 if ((rows() == 1 && dim == -1) || dim == 1) |
7503 return transpose (). prod (0). transpose(); | |
7504 else | |
7505 { | |
7506 SPARSE_REDUCTION_OP (SparseMatrix, double, *=, | |
9417
5d46c4a894e8
fix bugs in sparse reductions
Jaroslav Hajek <highegg@gmail.com>
parents:
8999
diff
changeset
|
7507 (cidx(j+1) - cidx(j) < nr ? 0.0 : 1.0), 1.0); |
7269 | 7508 } |
5164 | 7509 } |
7510 | |
7511 SparseMatrix | |
7512 SparseMatrix::sum (int dim) const | |
7513 { | |
7514 SPARSE_REDUCTION_OP (SparseMatrix, double, +=, 0.0, 0.0); | |
7515 } | |
7516 | |
7517 SparseMatrix | |
7518 SparseMatrix::sumsq (int dim) const | |
7519 { | |
7520 #define ROW_EXPR \ | |
7269 | 7521 double d = data (i); \ |
7522 tmp[ridx(i)] += d * d | |
5164 | 7523 |
7524 #define COL_EXPR \ | |
7269 | 7525 double d = data (i); \ |
5164 | 7526 tmp[j] += d * d |
7527 | |
7528 SPARSE_BASE_REDUCTION_OP (SparseMatrix, double, ROW_EXPR, COL_EXPR, | |
7529 0.0, 0.0); | |
7530 | |
7531 #undef ROW_EXPR | |
7532 #undef COL_EXPR | |
7533 } | |
7534 | |
7535 SparseMatrix | |
7536 SparseMatrix::abs (void) const | |
7537 { | |
5681 | 7538 octave_idx_type nz = nnz (); |
5164 | 7539 |
7540 SparseMatrix retval (*this); | |
7541 | |
5275 | 7542 for (octave_idx_type i = 0; i < nz; i++) |
5164 | 7543 retval.data(i) = fabs(retval.data(i)); |
7544 | |
7545 return retval; | |
7546 } | |
7547 | |
7548 SparseMatrix | |
5275 | 7549 SparseMatrix::diag (octave_idx_type k) const |
5164 | 7550 { |
7620
36594d5bbe13
Move diag function into the octave_value class
David Bateman <dbateman@free.fr>
parents:
7602
diff
changeset
|
7551 return MSparse<double>::diag (k); |
5164 | 7552 } |
7553 | |
7554 Matrix | |
7555 SparseMatrix::matrix_value (void) const | |
7556 { | |
5275 | 7557 octave_idx_type nr = rows (); |
7558 octave_idx_type nc = cols (); | |
5164 | 7559 |
7560 Matrix retval (nr, nc, 0.0); | |
5275 | 7561 for (octave_idx_type j = 0; j < nc; j++) |
7562 for (octave_idx_type i = cidx(j); i < cidx(j+1); i++) | |
5164 | 7563 retval.elem (ridx(i), j) = data (i); |
7564 | |
7565 return retval; | |
7566 } | |
7567 | |
7568 std::ostream& | |
7569 operator << (std::ostream& os, const SparseMatrix& a) | |
7570 { | |
5275 | 7571 octave_idx_type nc = a.cols (); |
5164 | 7572 |
7573 // add one to the printed indices to go from | |
7574 // zero-based to one-based arrays | |
5275 | 7575 for (octave_idx_type j = 0; j < nc; j++) { |
5164 | 7576 OCTAVE_QUIT; |
5275 | 7577 for (octave_idx_type i = a.cidx(j); i < a.cidx(j+1); i++) { |
5164 | 7578 os << a.ridx(i) + 1 << " " << j + 1 << " "; |
7579 octave_write_double (os, a.data(i)); | |
7580 os << "\n"; | |
7581 } | |
7582 } | |
7583 | |
7584 return os; | |
7585 } | |
7586 | |
7587 std::istream& | |
7588 operator >> (std::istream& is, SparseMatrix& a) | |
7589 { | |
9469
c6edba80dfae
sanity checks for loading sparse matrices
John W. Eaton <jwe@octave.org>
parents:
9417
diff
changeset
|
7590 typedef SparseMatrix::element_type elt_type; |
c6edba80dfae
sanity checks for loading sparse matrices
John W. Eaton <jwe@octave.org>
parents:
9417
diff
changeset
|
7591 |
c6edba80dfae
sanity checks for loading sparse matrices
John W. Eaton <jwe@octave.org>
parents:
9417
diff
changeset
|
7592 return read_sparse_matrix<elt_type> (is, a, octave_read_value<double>); |
5164 | 7593 } |
7594 | |
7595 SparseMatrix | |
7596 SparseMatrix::squeeze (void) const | |
7597 { | |
7598 return MSparse<double>::squeeze (); | |
7599 } | |
7600 | |
7601 SparseMatrix | |
7602 SparseMatrix::index (idx_vector& i, int resize_ok) const | |
7603 { | |
7604 return MSparse<double>::index (i, resize_ok); | |
7605 } | |
7606 | |
7607 SparseMatrix | |
7608 SparseMatrix::index (idx_vector& i, idx_vector& j, int resize_ok) const | |
7609 { | |
7610 return MSparse<double>::index (i, j, resize_ok); | |
7611 } | |
7612 | |
7613 SparseMatrix | |
7614 SparseMatrix::index (Array<idx_vector>& ra_idx, int resize_ok) const | |
7615 { | |
7616 return MSparse<double>::index (ra_idx, resize_ok); | |
7617 } | |
7618 | |
7619 SparseMatrix | |
7620 SparseMatrix::reshape (const dim_vector& new_dims) const | |
7621 { | |
7622 return MSparse<double>::reshape (new_dims); | |
7623 } | |
7624 | |
7625 SparseMatrix | |
5275 | 7626 SparseMatrix::permute (const Array<octave_idx_type>& vec, bool inv) const |
5164 | 7627 { |
7628 return MSparse<double>::permute (vec, inv); | |
7629 } | |
7630 | |
7631 SparseMatrix | |
5275 | 7632 SparseMatrix::ipermute (const Array<octave_idx_type>& vec) const |
5164 | 7633 { |
7634 return MSparse<double>::ipermute (vec); | |
7635 } | |
7636 | |
7637 // matrix by matrix -> matrix operations | |
7638 | |
7639 SparseMatrix | |
7640 operator * (const SparseMatrix& m, const SparseMatrix& a) | |
7641 { | |
5681 | 7642 SPARSE_SPARSE_MUL (SparseMatrix, double, double); |
5164 | 7643 } |
7644 | |
5429 | 7645 Matrix |
7646 operator * (const Matrix& m, const SparseMatrix& a) | |
7647 { | |
5681 | 7648 FULL_SPARSE_MUL (Matrix, double, 0.); |
5429 | 7649 } |
7650 | |
7651 Matrix | |
7802
1a446f28ce68
implement optimized sparse-dense transposed multiplication
Jaroslav Hajek <highegg@gmail.com>
parents:
7776
diff
changeset
|
7652 mul_trans (const Matrix& m, const SparseMatrix& a) |
1a446f28ce68
implement optimized sparse-dense transposed multiplication
Jaroslav Hajek <highegg@gmail.com>
parents:
7776
diff
changeset
|
7653 { |
1a446f28ce68
implement optimized sparse-dense transposed multiplication
Jaroslav Hajek <highegg@gmail.com>
parents:
7776
diff
changeset
|
7654 FULL_SPARSE_MUL_TRANS (Matrix, double, 0., ); |
1a446f28ce68
implement optimized sparse-dense transposed multiplication
Jaroslav Hajek <highegg@gmail.com>
parents:
7776
diff
changeset
|
7655 } |
1a446f28ce68
implement optimized sparse-dense transposed multiplication
Jaroslav Hajek <highegg@gmail.com>
parents:
7776
diff
changeset
|
7656 |
1a446f28ce68
implement optimized sparse-dense transposed multiplication
Jaroslav Hajek <highegg@gmail.com>
parents:
7776
diff
changeset
|
7657 Matrix |
5429 | 7658 operator * (const SparseMatrix& m, const Matrix& a) |
7659 { | |
5681 | 7660 SPARSE_FULL_MUL (Matrix, double, 0.); |
5429 | 7661 } |
7662 | |
7802
1a446f28ce68
implement optimized sparse-dense transposed multiplication
Jaroslav Hajek <highegg@gmail.com>
parents:
7776
diff
changeset
|
7663 Matrix |
1a446f28ce68
implement optimized sparse-dense transposed multiplication
Jaroslav Hajek <highegg@gmail.com>
parents:
7776
diff
changeset
|
7664 trans_mul (const SparseMatrix& m, const Matrix& a) |
1a446f28ce68
implement optimized sparse-dense transposed multiplication
Jaroslav Hajek <highegg@gmail.com>
parents:
7776
diff
changeset
|
7665 { |
1a446f28ce68
implement optimized sparse-dense transposed multiplication
Jaroslav Hajek <highegg@gmail.com>
parents:
7776
diff
changeset
|
7666 SPARSE_FULL_TRANS_MUL (Matrix, double, 0., ); |
1a446f28ce68
implement optimized sparse-dense transposed multiplication
Jaroslav Hajek <highegg@gmail.com>
parents:
7776
diff
changeset
|
7667 } |
1a446f28ce68
implement optimized sparse-dense transposed multiplication
Jaroslav Hajek <highegg@gmail.com>
parents:
7776
diff
changeset
|
7668 |
8964
f4f4d65faaa0
Implement sparse * diagonal and diagonal * sparse operations, double-prec only.
Jason Riedy <jason@acm.org>
parents:
8951
diff
changeset
|
7669 // diag * sparse and sparse * diag |
f4f4d65faaa0
Implement sparse * diagonal and diagonal * sparse operations, double-prec only.
Jason Riedy <jason@acm.org>
parents:
8951
diff
changeset
|
7670 |
f4f4d65faaa0
Implement sparse * diagonal and diagonal * sparse operations, double-prec only.
Jason Riedy <jason@acm.org>
parents:
8951
diff
changeset
|
7671 SparseMatrix |
f4f4d65faaa0
Implement sparse * diagonal and diagonal * sparse operations, double-prec only.
Jason Riedy <jason@acm.org>
parents:
8951
diff
changeset
|
7672 operator * (const DiagMatrix& d, const SparseMatrix& a) |
f4f4d65faaa0
Implement sparse * diagonal and diagonal * sparse operations, double-prec only.
Jason Riedy <jason@acm.org>
parents:
8951
diff
changeset
|
7673 { |
8967
5bbbf482909a
fix omissions adjusting JR's patches
Jaroslav Hajek <highegg@gmail.com>
parents:
8966
diff
changeset
|
7674 return do_mul_dm_sm<SparseMatrix> (d, a); |
8964
f4f4d65faaa0
Implement sparse * diagonal and diagonal * sparse operations, double-prec only.
Jason Riedy <jason@acm.org>
parents:
8951
diff
changeset
|
7675 } |
f4f4d65faaa0
Implement sparse * diagonal and diagonal * sparse operations, double-prec only.
Jason Riedy <jason@acm.org>
parents:
8951
diff
changeset
|
7676 |
f4f4d65faaa0
Implement sparse * diagonal and diagonal * sparse operations, double-prec only.
Jason Riedy <jason@acm.org>
parents:
8951
diff
changeset
|
7677 SparseMatrix |
f4f4d65faaa0
Implement sparse * diagonal and diagonal * sparse operations, double-prec only.
Jason Riedy <jason@acm.org>
parents:
8951
diff
changeset
|
7678 operator * (const SparseMatrix& a, const DiagMatrix& d) |
f4f4d65faaa0
Implement sparse * diagonal and diagonal * sparse operations, double-prec only.
Jason Riedy <jason@acm.org>
parents:
8951
diff
changeset
|
7679 { |
8967
5bbbf482909a
fix omissions adjusting JR's patches
Jaroslav Hajek <highegg@gmail.com>
parents:
8966
diff
changeset
|
7680 return do_mul_sm_dm<SparseMatrix> (a, d); |
8964
f4f4d65faaa0
Implement sparse * diagonal and diagonal * sparse operations, double-prec only.
Jason Riedy <jason@acm.org>
parents:
8951
diff
changeset
|
7681 } |
f4f4d65faaa0
Implement sparse * diagonal and diagonal * sparse operations, double-prec only.
Jason Riedy <jason@acm.org>
parents:
8951
diff
changeset
|
7682 |
8966
1bba53c0a38d
Implement diag + sparse, diag - sparse, sparse + diag, sparse - diag.
Jason Riedy <jason@acm.org>
parents:
8964
diff
changeset
|
7683 SparseMatrix |
1bba53c0a38d
Implement diag + sparse, diag - sparse, sparse + diag, sparse - diag.
Jason Riedy <jason@acm.org>
parents:
8964
diff
changeset
|
7684 operator + (const DiagMatrix& d, const SparseMatrix& a) |
1bba53c0a38d
Implement diag + sparse, diag - sparse, sparse + diag, sparse - diag.
Jason Riedy <jason@acm.org>
parents:
8964
diff
changeset
|
7685 { |
8967
5bbbf482909a
fix omissions adjusting JR's patches
Jaroslav Hajek <highegg@gmail.com>
parents:
8966
diff
changeset
|
7686 return do_add_dm_sm<SparseMatrix> (d, a); |
8966
1bba53c0a38d
Implement diag + sparse, diag - sparse, sparse + diag, sparse - diag.
Jason Riedy <jason@acm.org>
parents:
8964
diff
changeset
|
7687 } |
1bba53c0a38d
Implement diag + sparse, diag - sparse, sparse + diag, sparse - diag.
Jason Riedy <jason@acm.org>
parents:
8964
diff
changeset
|
7688 |
1bba53c0a38d
Implement diag + sparse, diag - sparse, sparse + diag, sparse - diag.
Jason Riedy <jason@acm.org>
parents:
8964
diff
changeset
|
7689 SparseMatrix |
1bba53c0a38d
Implement diag + sparse, diag - sparse, sparse + diag, sparse - diag.
Jason Riedy <jason@acm.org>
parents:
8964
diff
changeset
|
7690 operator - (const DiagMatrix& d, const SparseMatrix& a) |
1bba53c0a38d
Implement diag + sparse, diag - sparse, sparse + diag, sparse - diag.
Jason Riedy <jason@acm.org>
parents:
8964
diff
changeset
|
7691 { |
8967
5bbbf482909a
fix omissions adjusting JR's patches
Jaroslav Hajek <highegg@gmail.com>
parents:
8966
diff
changeset
|
7692 return do_sub_dm_sm<SparseMatrix> (d, a); |
8966
1bba53c0a38d
Implement diag + sparse, diag - sparse, sparse + diag, sparse - diag.
Jason Riedy <jason@acm.org>
parents:
8964
diff
changeset
|
7693 } |
1bba53c0a38d
Implement diag + sparse, diag - sparse, sparse + diag, sparse - diag.
Jason Riedy <jason@acm.org>
parents:
8964
diff
changeset
|
7694 |
1bba53c0a38d
Implement diag + sparse, diag - sparse, sparse + diag, sparse - diag.
Jason Riedy <jason@acm.org>
parents:
8964
diff
changeset
|
7695 SparseMatrix |
1bba53c0a38d
Implement diag + sparse, diag - sparse, sparse + diag, sparse - diag.
Jason Riedy <jason@acm.org>
parents:
8964
diff
changeset
|
7696 operator + (const SparseMatrix& a, const DiagMatrix& d) |
1bba53c0a38d
Implement diag + sparse, diag - sparse, sparse + diag, sparse - diag.
Jason Riedy <jason@acm.org>
parents:
8964
diff
changeset
|
7697 { |
8967
5bbbf482909a
fix omissions adjusting JR's patches
Jaroslav Hajek <highegg@gmail.com>
parents:
8966
diff
changeset
|
7698 return do_add_sm_dm<SparseMatrix> (a, d); |
8966
1bba53c0a38d
Implement diag + sparse, diag - sparse, sparse + diag, sparse - diag.
Jason Riedy <jason@acm.org>
parents:
8964
diff
changeset
|
7699 } |
1bba53c0a38d
Implement diag + sparse, diag - sparse, sparse + diag, sparse - diag.
Jason Riedy <jason@acm.org>
parents:
8964
diff
changeset
|
7700 |
1bba53c0a38d
Implement diag + sparse, diag - sparse, sparse + diag, sparse - diag.
Jason Riedy <jason@acm.org>
parents:
8964
diff
changeset
|
7701 SparseMatrix |
1bba53c0a38d
Implement diag + sparse, diag - sparse, sparse + diag, sparse - diag.
Jason Riedy <jason@acm.org>
parents:
8964
diff
changeset
|
7702 operator - (const SparseMatrix& a, const DiagMatrix& d) |
1bba53c0a38d
Implement diag + sparse, diag - sparse, sparse + diag, sparse - diag.
Jason Riedy <jason@acm.org>
parents:
8964
diff
changeset
|
7703 { |
8967
5bbbf482909a
fix omissions adjusting JR's patches
Jaroslav Hajek <highegg@gmail.com>
parents:
8966
diff
changeset
|
7704 return do_sub_sm_dm<SparseMatrix> (a, d); |
8966
1bba53c0a38d
Implement diag + sparse, diag - sparse, sparse + diag, sparse - diag.
Jason Riedy <jason@acm.org>
parents:
8964
diff
changeset
|
7705 } |
1bba53c0a38d
Implement diag + sparse, diag - sparse, sparse + diag, sparse - diag.
Jason Riedy <jason@acm.org>
parents:
8964
diff
changeset
|
7706 |
8968
91d53dc37f79
Add perm * sparse, perm \ sparse, sparse * perm, and sparse / perm operations.
Jason Riedy <jason@acm.org>
parents:
8967
diff
changeset
|
7707 // perm * sparse and sparse * perm |
91d53dc37f79
Add perm * sparse, perm \ sparse, sparse * perm, and sparse / perm operations.
Jason Riedy <jason@acm.org>
parents:
8967
diff
changeset
|
7708 |
91d53dc37f79
Add perm * sparse, perm \ sparse, sparse * perm, and sparse / perm operations.
Jason Riedy <jason@acm.org>
parents:
8967
diff
changeset
|
7709 SparseMatrix |
91d53dc37f79
Add perm * sparse, perm \ sparse, sparse * perm, and sparse / perm operations.
Jason Riedy <jason@acm.org>
parents:
8967
diff
changeset
|
7710 operator * (const PermMatrix& p, const SparseMatrix& a) |
91d53dc37f79
Add perm * sparse, perm \ sparse, sparse * perm, and sparse / perm operations.
Jason Riedy <jason@acm.org>
parents:
8967
diff
changeset
|
7711 { |
91d53dc37f79
Add perm * sparse, perm \ sparse, sparse * perm, and sparse / perm operations.
Jason Riedy <jason@acm.org>
parents:
8967
diff
changeset
|
7712 return octinternal_do_mul_pm_sm (p, a); |
91d53dc37f79
Add perm * sparse, perm \ sparse, sparse * perm, and sparse / perm operations.
Jason Riedy <jason@acm.org>
parents:
8967
diff
changeset
|
7713 } |
91d53dc37f79
Add perm * sparse, perm \ sparse, sparse * perm, and sparse / perm operations.
Jason Riedy <jason@acm.org>
parents:
8967
diff
changeset
|
7714 |
91d53dc37f79
Add perm * sparse, perm \ sparse, sparse * perm, and sparse / perm operations.
Jason Riedy <jason@acm.org>
parents:
8967
diff
changeset
|
7715 SparseMatrix |
91d53dc37f79
Add perm * sparse, perm \ sparse, sparse * perm, and sparse / perm operations.
Jason Riedy <jason@acm.org>
parents:
8967
diff
changeset
|
7716 operator * (const SparseMatrix& a, const PermMatrix& p) |
91d53dc37f79
Add perm * sparse, perm \ sparse, sparse * perm, and sparse / perm operations.
Jason Riedy <jason@acm.org>
parents:
8967
diff
changeset
|
7717 { |
91d53dc37f79
Add perm * sparse, perm \ sparse, sparse * perm, and sparse / perm operations.
Jason Riedy <jason@acm.org>
parents:
8967
diff
changeset
|
7718 return octinternal_do_mul_sm_pm (a, p); |
91d53dc37f79
Add perm * sparse, perm \ sparse, sparse * perm, and sparse / perm operations.
Jason Riedy <jason@acm.org>
parents:
8967
diff
changeset
|
7719 } |
91d53dc37f79
Add perm * sparse, perm \ sparse, sparse * perm, and sparse / perm operations.
Jason Riedy <jason@acm.org>
parents:
8967
diff
changeset
|
7720 |
5775 | 7721 // FIXME -- it would be nice to share code among the min/max |
5164 | 7722 // functions below. |
7723 | |
7724 #define EMPTY_RETURN_CHECK(T) \ | |
7725 if (nr == 0 || nc == 0) \ | |
7726 return T (nr, nc); | |
7727 | |
7728 SparseMatrix | |
7729 min (double d, const SparseMatrix& m) | |
7730 { | |
7731 SparseMatrix result; | |
7732 | |
5275 | 7733 octave_idx_type nr = m.rows (); |
7734 octave_idx_type nc = m.columns (); | |
5164 | 7735 |
7736 EMPTY_RETURN_CHECK (SparseMatrix); | |
7737 | |
7738 // Count the number of non-zero elements | |
7739 if (d < 0.) | |
7740 { | |
7741 result = SparseMatrix (nr, nc, d); | |
5275 | 7742 for (octave_idx_type j = 0; j < nc; j++) |
7743 for (octave_idx_type i = m.cidx(j); i < m.cidx(j+1); i++) | |
5164 | 7744 { |
7745 double tmp = xmin (d, m.data (i)); | |
7746 if (tmp != 0.) | |
7747 { | |
5275 | 7748 octave_idx_type idx = m.ridx(i) + j * nr; |
5164 | 7749 result.xdata(idx) = tmp; |
7750 result.xridx(idx) = m.ridx(i); | |
7751 } | |
7752 } | |
7753 } | |
7754 else | |
7755 { | |
5275 | 7756 octave_idx_type nel = 0; |
7757 for (octave_idx_type j = 0; j < nc; j++) | |
7758 for (octave_idx_type i = m.cidx(j); i < m.cidx(j+1); i++) | |
5164 | 7759 if (xmin (d, m.data (i)) != 0.) |
7760 nel++; | |
7761 | |
7762 result = SparseMatrix (nr, nc, nel); | |
7763 | |
5275 | 7764 octave_idx_type ii = 0; |
5164 | 7765 result.xcidx(0) = 0; |
5275 | 7766 for (octave_idx_type j = 0; j < nc; j++) |
5164 | 7767 { |
5275 | 7768 for (octave_idx_type i = m.cidx(j); i < m.cidx(j+1); i++) |
5164 | 7769 { |
7770 double tmp = xmin (d, m.data (i)); | |
7771 | |
7772 if (tmp != 0.) | |
7773 { | |
7774 result.xdata(ii) = tmp; | |
7775 result.xridx(ii++) = m.ridx(i); | |
7776 } | |
7777 } | |
7778 result.xcidx(j+1) = ii; | |
7779 } | |
7780 } | |
7781 | |
7782 return result; | |
7783 } | |
7784 | |
7785 SparseMatrix | |
7786 min (const SparseMatrix& m, double d) | |
7787 { | |
7788 return min (d, m); | |
7789 } | |
7790 | |
7791 SparseMatrix | |
7792 min (const SparseMatrix& a, const SparseMatrix& b) | |
7793 { | |
7794 SparseMatrix r; | |
7795 | |
7796 if ((a.rows() == b.rows()) && (a.cols() == b.cols())) | |
7797 { | |
5275 | 7798 octave_idx_type a_nr = a.rows (); |
7799 octave_idx_type a_nc = a.cols (); | |
7800 | |
7801 octave_idx_type b_nr = b.rows (); | |
7802 octave_idx_type b_nc = b.cols (); | |
5164 | 7803 |
7804 if (a_nr != b_nr || a_nc != b_nc) | |
7805 gripe_nonconformant ("min", a_nr, a_nc, b_nr, b_nc); | |
7806 else | |
7807 { | |
5681 | 7808 r = SparseMatrix (a_nr, a_nc, (a.nnz () + b.nnz ())); |
5164 | 7809 |
5275 | 7810 octave_idx_type jx = 0; |
5164 | 7811 r.cidx (0) = 0; |
5275 | 7812 for (octave_idx_type i = 0 ; i < a_nc ; i++) |
5164 | 7813 { |
5275 | 7814 octave_idx_type ja = a.cidx(i); |
7815 octave_idx_type ja_max = a.cidx(i+1); | |
5164 | 7816 bool ja_lt_max= ja < ja_max; |
7817 | |
5275 | 7818 octave_idx_type jb = b.cidx(i); |
7819 octave_idx_type jb_max = b.cidx(i+1); | |
5164 | 7820 bool jb_lt_max = jb < jb_max; |
7821 | |
7822 while (ja_lt_max || jb_lt_max ) | |
7823 { | |
7824 OCTAVE_QUIT; | |
7825 if ((! jb_lt_max) || | |
7826 (ja_lt_max && (a.ridx(ja) < b.ridx(jb)))) | |
7827 { | |
7828 double tmp = xmin (a.data(ja), 0.); | |
7829 if (tmp != 0.) | |
7830 { | |
7831 r.ridx(jx) = a.ridx(ja); | |
7832 r.data(jx) = tmp; | |
7833 jx++; | |
7834 } | |
7835 ja++; | |
7836 ja_lt_max= ja < ja_max; | |
7837 } | |
7838 else if (( !ja_lt_max ) || | |
7839 (jb_lt_max && (b.ridx(jb) < a.ridx(ja)) ) ) | |
7840 { | |
7841 double tmp = xmin (0., b.data(jb)); | |
7842 if (tmp != 0.) | |
7843 { | |
7844 r.ridx(jx) = b.ridx(jb); | |
7845 r.data(jx) = tmp; | |
7846 jx++; | |
7847 } | |
7848 jb++; | |
7849 jb_lt_max= jb < jb_max; | |
7850 } | |
7851 else | |
7852 { | |
7853 double tmp = xmin (a.data(ja), b.data(jb)); | |
7854 if (tmp != 0.) | |
7855 { | |
7856 r.data(jx) = tmp; | |
7857 r.ridx(jx) = a.ridx(ja); | |
7858 jx++; | |
7859 } | |
7860 ja++; | |
7861 ja_lt_max= ja < ja_max; | |
7862 jb++; | |
7863 jb_lt_max= jb < jb_max; | |
7864 } | |
7865 } | |
7866 r.cidx(i+1) = jx; | |
7867 } | |
7868 | |
7869 r.maybe_compress (); | |
7870 } | |
7871 } | |
7872 else | |
7873 (*current_liboctave_error_handler) ("matrix size mismatch"); | |
7874 | |
7875 return r; | |
7876 } | |
7877 | |
7878 SparseMatrix | |
7879 max (double d, const SparseMatrix& m) | |
7880 { | |
7881 SparseMatrix result; | |
7882 | |
5275 | 7883 octave_idx_type nr = m.rows (); |
7884 octave_idx_type nc = m.columns (); | |
5164 | 7885 |
7886 EMPTY_RETURN_CHECK (SparseMatrix); | |
7887 | |
7888 // Count the number of non-zero elements | |
7889 if (d > 0.) | |
7890 { | |
7891 result = SparseMatrix (nr, nc, d); | |
5275 | 7892 for (octave_idx_type j = 0; j < nc; j++) |
7893 for (octave_idx_type i = m.cidx(j); i < m.cidx(j+1); i++) | |
5164 | 7894 { |
7895 double tmp = xmax (d, m.data (i)); | |
7896 | |
7897 if (tmp != 0.) | |
7898 { | |
5275 | 7899 octave_idx_type idx = m.ridx(i) + j * nr; |
5164 | 7900 result.xdata(idx) = tmp; |
7901 result.xridx(idx) = m.ridx(i); | |
7902 } | |
7903 } | |
7904 } | |
7905 else | |
7906 { | |
5275 | 7907 octave_idx_type nel = 0; |
7908 for (octave_idx_type j = 0; j < nc; j++) | |
7909 for (octave_idx_type i = m.cidx(j); i < m.cidx(j+1); i++) | |
5164 | 7910 if (xmax (d, m.data (i)) != 0.) |
7911 nel++; | |
7912 | |
7913 result = SparseMatrix (nr, nc, nel); | |
7914 | |
5275 | 7915 octave_idx_type ii = 0; |
5164 | 7916 result.xcidx(0) = 0; |
5275 | 7917 for (octave_idx_type j = 0; j < nc; j++) |
5164 | 7918 { |
5275 | 7919 for (octave_idx_type i = m.cidx(j); i < m.cidx(j+1); i++) |
5164 | 7920 { |
7921 double tmp = xmax (d, m.data (i)); | |
7922 if (tmp != 0.) | |
7923 { | |
7924 result.xdata(ii) = tmp; | |
7925 result.xridx(ii++) = m.ridx(i); | |
7926 } | |
7927 } | |
7928 result.xcidx(j+1) = ii; | |
7929 } | |
7930 } | |
7931 | |
7932 return result; | |
7933 } | |
7934 | |
7935 SparseMatrix | |
7936 max (const SparseMatrix& m, double d) | |
7937 { | |
7938 return max (d, m); | |
7939 } | |
7940 | |
7941 SparseMatrix | |
7942 max (const SparseMatrix& a, const SparseMatrix& b) | |
7943 { | |
7944 SparseMatrix r; | |
7945 | |
7946 if ((a.rows() == b.rows()) && (a.cols() == b.cols())) | |
7947 { | |
5275 | 7948 octave_idx_type a_nr = a.rows (); |
7949 octave_idx_type a_nc = a.cols (); | |
7950 | |
7951 octave_idx_type b_nr = b.rows (); | |
7952 octave_idx_type b_nc = b.cols (); | |
5164 | 7953 |
7954 if (a_nr != b_nr || a_nc != b_nc) | |
7955 gripe_nonconformant ("min", a_nr, a_nc, b_nr, b_nc); | |
7956 else | |
7957 { | |
5681 | 7958 r = SparseMatrix (a_nr, a_nc, (a.nnz () + b.nnz ())); |
5164 | 7959 |
5275 | 7960 octave_idx_type jx = 0; |
5164 | 7961 r.cidx (0) = 0; |
5275 | 7962 for (octave_idx_type i = 0 ; i < a_nc ; i++) |
5164 | 7963 { |
5275 | 7964 octave_idx_type ja = a.cidx(i); |
7965 octave_idx_type ja_max = a.cidx(i+1); | |
5164 | 7966 bool ja_lt_max= ja < ja_max; |
7967 | |
5275 | 7968 octave_idx_type jb = b.cidx(i); |
7969 octave_idx_type jb_max = b.cidx(i+1); | |
5164 | 7970 bool jb_lt_max = jb < jb_max; |
7971 | |
7972 while (ja_lt_max || jb_lt_max ) | |
7973 { | |
7974 OCTAVE_QUIT; | |
7975 if ((! jb_lt_max) || | |
7976 (ja_lt_max && (a.ridx(ja) < b.ridx(jb)))) | |
7977 { | |
7978 double tmp = xmax (a.data(ja), 0.); | |
7979 if (tmp != 0.) | |
7980 { | |
7981 r.ridx(jx) = a.ridx(ja); | |
7982 r.data(jx) = tmp; | |
7983 jx++; | |
7984 } | |
7985 ja++; | |
7986 ja_lt_max= ja < ja_max; | |
7987 } | |
7988 else if (( !ja_lt_max ) || | |
7989 (jb_lt_max && (b.ridx(jb) < a.ridx(ja)) ) ) | |
7990 { | |
7991 double tmp = xmax (0., b.data(jb)); | |
7992 if (tmp != 0.) | |
7993 { | |
7994 r.ridx(jx) = b.ridx(jb); | |
7995 r.data(jx) = tmp; | |
7996 jx++; | |
7997 } | |
7998 jb++; | |
7999 jb_lt_max= jb < jb_max; | |
8000 } | |
8001 else | |
8002 { | |
8003 double tmp = xmax (a.data(ja), b.data(jb)); | |
8004 if (tmp != 0.) | |
8005 { | |
8006 r.data(jx) = tmp; | |
8007 r.ridx(jx) = a.ridx(ja); | |
8008 jx++; | |
8009 } | |
8010 ja++; | |
8011 ja_lt_max= ja < ja_max; | |
8012 jb++; | |
8013 jb_lt_max= jb < jb_max; | |
8014 } | |
8015 } | |
8016 r.cidx(i+1) = jx; | |
8017 } | |
8018 | |
8019 r.maybe_compress (); | |
8020 } | |
8021 } | |
8022 else | |
8023 (*current_liboctave_error_handler) ("matrix size mismatch"); | |
8024 | |
8025 return r; | |
8026 } | |
8027 | |
8028 SPARSE_SMS_CMP_OPS (SparseMatrix, 0.0, , double, 0.0, ) | |
8029 SPARSE_SMS_BOOL_OPS (SparseMatrix, double, 0.0) | |
8030 | |
8031 SPARSE_SSM_CMP_OPS (double, 0.0, , SparseMatrix, 0.0, ) | |
8032 SPARSE_SSM_BOOL_OPS (double, SparseMatrix, 0.0) | |
8033 | |
8034 SPARSE_SMSM_CMP_OPS (SparseMatrix, 0.0, , SparseMatrix, 0.0, ) | |
8035 SPARSE_SMSM_BOOL_OPS (SparseMatrix, SparseMatrix, 0.0) | |
8036 | |
8037 /* | |
8038 ;;; Local Variables: *** | |
8039 ;;; mode: C++ *** | |
8040 ;;; End: *** | |
8041 */ |