Mercurial > hg > octave-lyh
annotate liboctave/CSparse.cc @ 8920:eb63fbe60fab
update copyright notices
author | John W. Eaton <jwe@octave.org> |
---|---|
date | Sat, 07 Mar 2009 10:41:27 -0500 |
parents | 6e9f26506804 |
children | f4f4d65faaa0 |
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> | |
32 | |
33 #include "quit.h" | |
34 #include "lo-ieee.h" | |
35 #include "lo-mappers.h" | |
36 #include "f77-fcn.h" | |
37 #include "dRowVector.h" | |
8377
25bc2d31e1bf
improve OCTAVE_LOCAL_BUFFER
Jaroslav Hajek <highegg@gmail.com>
parents:
8366
diff
changeset
|
38 #include "oct-locbuf.h" |
5164 | 39 |
40 #include "CSparse.h" | |
41 #include "boolSparse.h" | |
42 #include "dSparse.h" | |
7602
7bfaa9611558
Rewrite sparse mappers in terms of a functor template function
David Bateman <dbateman@free.fr>
parents:
7520
diff
changeset
|
43 #include "functor.h" |
5164 | 44 #include "oct-spparms.h" |
45 #include "SparseCmplxLU.h" | |
5451 | 46 #include "oct-sparse.h" |
5506 | 47 #include "sparse-util.h" |
48 #include "SparseCmplxCHOL.h" | |
5610 | 49 #include "SparseCmplxQR.h" |
5164 | 50 |
5681 | 51 // Define whether to use a basic QR solver or one that uses a Dulmange |
52 // Mendelsohn factorization to seperate the problem into under-determined, | |
53 // well-determined and over-determined parts and solves them seperately | |
54 #ifndef USE_QRSOLVE | |
55 #include "sparse-dmsolve.cc" | |
56 #endif | |
57 | |
5164 | 58 // Fortran functions we call. |
59 extern "C" | |
60 { | |
61 F77_RET_T | |
5275 | 62 F77_FUNC (zgbtrf, ZGBTRF) (const octave_idx_type&, const octave_idx_type&, const octave_idx_type&, |
63 const octave_idx_type&, Complex*, const octave_idx_type&, octave_idx_type*, octave_idx_type&); | |
5164 | 64 |
65 F77_RET_T | |
5275 | 66 F77_FUNC (zgbtrs, ZGBTRS) (F77_CONST_CHAR_ARG_DECL, const octave_idx_type&, |
67 const octave_idx_type&, const octave_idx_type&, const octave_idx_type&, | |
68 const Complex*, const octave_idx_type&, | |
69 const octave_idx_type*, Complex*, const octave_idx_type&, octave_idx_type& | |
5164 | 70 F77_CHAR_ARG_LEN_DECL); |
71 | |
72 F77_RET_T | |
5275 | 73 F77_FUNC (zgbcon, ZGBCON) (F77_CONST_CHAR_ARG_DECL, const octave_idx_type&, |
74 const octave_idx_type&, const octave_idx_type&, Complex*, | |
75 const octave_idx_type&, const octave_idx_type*, const double&, | |
76 double&, Complex*, double*, octave_idx_type& | |
5164 | 77 F77_CHAR_ARG_LEN_DECL); |
78 | |
79 F77_RET_T | |
5275 | 80 F77_FUNC (zpbtrf, ZPBTRF) (F77_CONST_CHAR_ARG_DECL, const octave_idx_type&, |
81 const octave_idx_type&, Complex*, const octave_idx_type&, octave_idx_type& | |
5164 | 82 F77_CHAR_ARG_LEN_DECL); |
83 | |
84 F77_RET_T | |
5275 | 85 F77_FUNC (zpbtrs, ZPBTRS) (F77_CONST_CHAR_ARG_DECL, const octave_idx_type&, |
86 const octave_idx_type&, const octave_idx_type&, Complex*, const octave_idx_type&, | |
87 Complex*, const octave_idx_type&, octave_idx_type& | |
5164 | 88 F77_CHAR_ARG_LEN_DECL); |
89 | |
90 F77_RET_T | |
5275 | 91 F77_FUNC (zpbcon, ZPBCON) (F77_CONST_CHAR_ARG_DECL, const octave_idx_type&, |
92 const octave_idx_type&, Complex*, const octave_idx_type&, | |
5681 | 93 const double&, double&, Complex*, double*, octave_idx_type& |
5164 | 94 F77_CHAR_ARG_LEN_DECL); |
95 | |
96 F77_RET_T | |
5275 | 97 F77_FUNC (zgttrf, ZGTTRF) (const octave_idx_type&, Complex*, Complex*, Complex*, |
98 Complex*, octave_idx_type*, octave_idx_type&); | |
5164 | 99 |
100 F77_RET_T | |
5275 | 101 F77_FUNC (zgttrs, ZGTTRS) (F77_CONST_CHAR_ARG_DECL, const octave_idx_type&, |
102 const octave_idx_type&, const Complex*, const Complex*, | |
103 const Complex*, const Complex*, const octave_idx_type*, | |
104 Complex *, const octave_idx_type&, octave_idx_type& | |
5164 | 105 F77_CHAR_ARG_LEN_DECL); |
106 | |
107 F77_RET_T | |
5322 | 108 F77_FUNC (zptsv, ZPTSV) (const octave_idx_type&, const octave_idx_type&, double*, Complex*, |
5275 | 109 Complex*, const octave_idx_type&, octave_idx_type&); |
5164 | 110 |
111 F77_RET_T | |
5275 | 112 F77_FUNC (zgtsv, ZGTSV) (const octave_idx_type&, const octave_idx_type&, Complex*, Complex*, |
113 Complex*, Complex*, const octave_idx_type&, octave_idx_type&); | |
5164 | 114 } |
115 | |
116 SparseComplexMatrix::SparseComplexMatrix (const SparseMatrix& a) | |
5681 | 117 : MSparse<Complex> (a.rows (), a.cols (), a.nnz ()) |
5164 | 118 { |
5275 | 119 octave_idx_type nc = cols (); |
5681 | 120 octave_idx_type nz = a.nnz (); |
5275 | 121 |
122 for (octave_idx_type i = 0; i < nc + 1; i++) | |
5164 | 123 cidx (i) = a.cidx (i); |
124 | |
5275 | 125 for (octave_idx_type i = 0; i < nz; i++) |
5164 | 126 { |
5681 | 127 data (i) = Complex (a.data (i)); |
5164 | 128 ridx (i) = a.ridx (i); |
129 } | |
130 } | |
131 | |
132 SparseComplexMatrix::SparseComplexMatrix (const SparseBoolMatrix& a) | |
5681 | 133 : MSparse<Complex> (a.rows (), a.cols (), a.nnz ()) |
5164 | 134 { |
5275 | 135 octave_idx_type nc = cols (); |
5681 | 136 octave_idx_type nz = a.nnz (); |
5275 | 137 |
138 for (octave_idx_type i = 0; i < nc + 1; i++) | |
5164 | 139 cidx (i) = a.cidx (i); |
140 | |
5275 | 141 for (octave_idx_type i = 0; i < nz; i++) |
5164 | 142 { |
5681 | 143 data (i) = Complex (a.data (i)); |
5164 | 144 ridx (i) = a.ridx (i); |
145 } | |
146 } | |
147 | |
8366
8b1a2555c4e2
implement diagonal matrix objects
Jaroslav Hajek <highegg@gmail.com>
parents:
8335
diff
changeset
|
148 SparseComplexMatrix::SparseComplexMatrix (const ComplexDiagMatrix& a) |
8910
6e9f26506804
optimize diag -> sparse and perm -> sparse conversions
Jaroslav Hajek <highegg@gmail.com>
parents:
8377
diff
changeset
|
149 : MSparse<Complex> (a.rows (), a.cols (), a.length ()) |
6e9f26506804
optimize diag -> sparse and perm -> sparse conversions
Jaroslav Hajek <highegg@gmail.com>
parents:
8377
diff
changeset
|
150 { |
6e9f26506804
optimize diag -> sparse and perm -> sparse conversions
Jaroslav Hajek <highegg@gmail.com>
parents:
8377
diff
changeset
|
151 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
|
152 for (octave_idx_type i = 0; i < l; i++) |
8366
8b1a2555c4e2
implement diagonal matrix objects
Jaroslav Hajek <highegg@gmail.com>
parents:
8335
diff
changeset
|
153 { |
8910
6e9f26506804
optimize diag -> sparse and perm -> sparse conversions
Jaroslav Hajek <highegg@gmail.com>
parents:
8377
diff
changeset
|
154 cidx (i) = j; |
6e9f26506804
optimize diag -> sparse and perm -> sparse conversions
Jaroslav Hajek <highegg@gmail.com>
parents:
8377
diff
changeset
|
155 if (a(i, i) != 0.0) |
8366
8b1a2555c4e2
implement diagonal matrix objects
Jaroslav Hajek <highegg@gmail.com>
parents:
8335
diff
changeset
|
156 { |
8b1a2555c4e2
implement diagonal matrix objects
Jaroslav Hajek <highegg@gmail.com>
parents:
8335
diff
changeset
|
157 data (j) = a(i, i); |
8b1a2555c4e2
implement diagonal matrix objects
Jaroslav Hajek <highegg@gmail.com>
parents:
8335
diff
changeset
|
158 ridx (j) = i; |
8b1a2555c4e2
implement diagonal matrix objects
Jaroslav Hajek <highegg@gmail.com>
parents:
8335
diff
changeset
|
159 j++; |
8b1a2555c4e2
implement diagonal matrix objects
Jaroslav Hajek <highegg@gmail.com>
parents:
8335
diff
changeset
|
160 } |
8b1a2555c4e2
implement diagonal matrix objects
Jaroslav Hajek <highegg@gmail.com>
parents:
8335
diff
changeset
|
161 } |
8910
6e9f26506804
optimize diag -> sparse and perm -> sparse conversions
Jaroslav Hajek <highegg@gmail.com>
parents:
8377
diff
changeset
|
162 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
|
163 cidx(i) = j; |
8366
8b1a2555c4e2
implement diagonal matrix objects
Jaroslav Hajek <highegg@gmail.com>
parents:
8335
diff
changeset
|
164 } |
5164 | 165 bool |
166 SparseComplexMatrix::operator == (const SparseComplexMatrix& a) const | |
167 { | |
5275 | 168 octave_idx_type nr = rows (); |
169 octave_idx_type nc = cols (); | |
5681 | 170 octave_idx_type nz = nnz (); |
5275 | 171 octave_idx_type nr_a = a.rows (); |
172 octave_idx_type nc_a = a.cols (); | |
5681 | 173 octave_idx_type nz_a = a.nnz (); |
5164 | 174 |
175 if (nr != nr_a || nc != nc_a || nz != nz_a) | |
176 return false; | |
177 | |
5275 | 178 for (octave_idx_type i = 0; i < nc + 1; i++) |
5164 | 179 if (cidx(i) != a.cidx(i)) |
180 return false; | |
181 | |
5275 | 182 for (octave_idx_type i = 0; i < nz; i++) |
5164 | 183 if (data(i) != a.data(i) || ridx(i) != a.ridx(i)) |
184 return false; | |
185 | |
186 return true; | |
187 } | |
188 | |
189 bool | |
190 SparseComplexMatrix::operator != (const SparseComplexMatrix& a) const | |
191 { | |
192 return !(*this == a); | |
193 } | |
194 | |
195 bool | |
196 SparseComplexMatrix::is_hermitian (void) const | |
197 { | |
5275 | 198 octave_idx_type nr = rows (); |
199 octave_idx_type nc = cols (); | |
5164 | 200 |
6207 | 201 if (nr == nc && nr > 0) |
5164 | 202 { |
6207 | 203 for (octave_idx_type j = 0; j < nc; j++) |
204 { | |
205 for (octave_idx_type i = cidx(j); i < cidx(j+1); i++) | |
206 { | |
207 octave_idx_type ri = ridx(i); | |
208 | |
209 if (ri != j) | |
210 { | |
211 bool found = false; | |
212 | |
213 for (octave_idx_type k = cidx(ri); k < cidx(ri+1); k++) | |
214 { | |
215 if (ridx(k) == j) | |
216 { | |
217 if (data(i) == conj(data(k))) | |
218 found = true; | |
219 break; | |
220 } | |
221 } | |
222 | |
223 if (! found) | |
224 return false; | |
225 } | |
226 } | |
227 } | |
5164 | 228 |
229 return true; | |
230 } | |
231 | |
232 return false; | |
233 } | |
234 | |
235 static const Complex Complex_NaN_result (octave_NaN, octave_NaN); | |
236 | |
237 SparseComplexMatrix | |
238 SparseComplexMatrix::max (int dim) const | |
239 { | |
5275 | 240 Array2<octave_idx_type> dummy_idx; |
5164 | 241 return max (dummy_idx, dim); |
242 } | |
243 | |
244 SparseComplexMatrix | |
5275 | 245 SparseComplexMatrix::max (Array2<octave_idx_type>& idx_arg, int dim) const |
5164 | 246 { |
247 SparseComplexMatrix result; | |
248 dim_vector dv = dims (); | |
249 | |
250 if (dv.numel () == 0 || dim > dv.length () || dim < 0) | |
251 return result; | |
252 | |
5275 | 253 octave_idx_type nr = dv(0); |
254 octave_idx_type nc = dv(1); | |
5164 | 255 |
256 if (dim == 0) | |
257 { | |
258 idx_arg.resize (1, nc); | |
5275 | 259 octave_idx_type nel = 0; |
260 for (octave_idx_type j = 0; j < nc; j++) | |
5164 | 261 { |
262 Complex tmp_max; | |
263 double abs_max = octave_NaN; | |
5275 | 264 octave_idx_type idx_j = 0; |
265 for (octave_idx_type i = cidx(j); i < cidx(j+1); i++) | |
5164 | 266 { |
267 if (ridx(i) != idx_j) | |
268 break; | |
269 else | |
270 idx_j++; | |
271 } | |
272 | |
273 if (idx_j != nr) | |
274 { | |
275 tmp_max = 0.; | |
276 abs_max = 0.; | |
277 } | |
278 | |
5275 | 279 for (octave_idx_type i = cidx(j); i < cidx(j+1); i++) |
5164 | 280 { |
281 Complex tmp = data (i); | |
282 | |
5389 | 283 if (xisnan (tmp)) |
5164 | 284 continue; |
285 | |
5261 | 286 double abs_tmp = std::abs (tmp); |
5164 | 287 |
5389 | 288 if (xisnan (abs_max) || abs_tmp > abs_max) |
5164 | 289 { |
290 idx_j = ridx (i); | |
291 tmp_max = tmp; | |
292 abs_max = abs_tmp; | |
293 } | |
294 } | |
295 | |
5389 | 296 idx_arg.elem (j) = xisnan (tmp_max) ? 0 : idx_j; |
5164 | 297 if (abs_max != 0.) |
298 nel++; | |
299 } | |
300 | |
301 result = SparseComplexMatrix (1, nc, nel); | |
302 | |
5275 | 303 octave_idx_type ii = 0; |
5164 | 304 result.xcidx (0) = 0; |
5275 | 305 for (octave_idx_type j = 0; j < nc; j++) |
5164 | 306 { |
307 Complex tmp = elem (idx_arg(j), j); | |
308 if (tmp != 0.) | |
309 { | |
310 result.xdata (ii) = tmp; | |
311 result.xridx (ii++) = 0; | |
312 } | |
313 result.xcidx (j+1) = ii; | |
314 } | |
315 } | |
316 else | |
317 { | |
318 idx_arg.resize (nr, 1, 0); | |
319 | |
5275 | 320 for (octave_idx_type i = cidx(0); i < cidx(1); i++) |
5164 | 321 idx_arg.elem(ridx(i)) = -1; |
322 | |
5275 | 323 for (octave_idx_type j = 0; j < nc; j++) |
324 for (octave_idx_type i = 0; i < nr; i++) | |
5164 | 325 { |
326 if (idx_arg.elem(i) != -1) | |
327 continue; | |
328 bool found = false; | |
5275 | 329 for (octave_idx_type k = cidx(j); k < cidx(j+1); k++) |
5164 | 330 if (ridx(k) == i) |
331 { | |
332 found = true; | |
333 break; | |
334 } | |
335 | |
336 if (!found) | |
337 idx_arg.elem(i) = j; | |
338 | |
339 } | |
340 | |
5275 | 341 for (octave_idx_type j = 0; j < nc; j++) |
5164 | 342 { |
5275 | 343 for (octave_idx_type i = cidx(j); i < cidx(j+1); i++) |
5164 | 344 { |
5275 | 345 octave_idx_type ir = ridx (i); |
346 octave_idx_type ix = idx_arg.elem (ir); | |
5164 | 347 Complex tmp = data (i); |
348 | |
5389 | 349 if (xisnan (tmp)) |
5164 | 350 continue; |
5261 | 351 else if (ix == -1 || std::abs(tmp) > std::abs(elem (ir, ix))) |
5164 | 352 idx_arg.elem (ir) = j; |
353 } | |
354 } | |
355 | |
5275 | 356 octave_idx_type nel = 0; |
357 for (octave_idx_type j = 0; j < nr; j++) | |
5164 | 358 if (idx_arg.elem(j) == -1 || elem (j, idx_arg.elem (j)) != 0.) |
359 nel++; | |
360 | |
361 result = SparseComplexMatrix (nr, 1, nel); | |
362 | |
5275 | 363 octave_idx_type ii = 0; |
5164 | 364 result.xcidx (0) = 0; |
365 result.xcidx (1) = nel; | |
5275 | 366 for (octave_idx_type j = 0; j < nr; j++) |
5164 | 367 { |
368 if (idx_arg(j) == -1) | |
369 { | |
370 idx_arg(j) = 0; | |
371 result.xdata (ii) = Complex_NaN_result; | |
372 result.xridx (ii++) = j; | |
373 } | |
374 else | |
375 { | |
376 Complex tmp = elem (j, idx_arg(j)); | |
377 if (tmp != 0.) | |
378 { | |
379 result.xdata (ii) = tmp; | |
380 result.xridx (ii++) = j; | |
381 } | |
382 } | |
383 } | |
384 } | |
385 | |
386 return result; | |
387 } | |
388 | |
389 SparseComplexMatrix | |
390 SparseComplexMatrix::min (int dim) const | |
391 { | |
5275 | 392 Array2<octave_idx_type> dummy_idx; |
5164 | 393 return min (dummy_idx, dim); |
394 } | |
395 | |
396 SparseComplexMatrix | |
5275 | 397 SparseComplexMatrix::min (Array2<octave_idx_type>& idx_arg, int dim) const |
5164 | 398 { |
399 SparseComplexMatrix result; | |
400 dim_vector dv = dims (); | |
401 | |
402 if (dv.numel () == 0 || dim > dv.length () || dim < 0) | |
403 return result; | |
404 | |
5275 | 405 octave_idx_type nr = dv(0); |
406 octave_idx_type nc = dv(1); | |
5164 | 407 |
408 if (dim == 0) | |
409 { | |
410 idx_arg.resize (1, nc); | |
5275 | 411 octave_idx_type nel = 0; |
412 for (octave_idx_type j = 0; j < nc; j++) | |
5164 | 413 { |
414 Complex tmp_min; | |
415 double abs_min = octave_NaN; | |
5275 | 416 octave_idx_type idx_j = 0; |
417 for (octave_idx_type i = cidx(j); i < cidx(j+1); i++) | |
5164 | 418 { |
419 if (ridx(i) != idx_j) | |
420 break; | |
421 else | |
422 idx_j++; | |
423 } | |
424 | |
425 if (idx_j != nr) | |
426 { | |
427 tmp_min = 0.; | |
428 abs_min = 0.; | |
429 } | |
430 | |
5275 | 431 for (octave_idx_type i = cidx(j); i < cidx(j+1); i++) |
5164 | 432 { |
433 Complex tmp = data (i); | |
434 | |
5389 | 435 if (xisnan (tmp)) |
5164 | 436 continue; |
437 | |
5261 | 438 double abs_tmp = std::abs (tmp); |
5164 | 439 |
5389 | 440 if (xisnan (abs_min) || abs_tmp < abs_min) |
5164 | 441 { |
442 idx_j = ridx (i); | |
443 tmp_min = tmp; | |
444 abs_min = abs_tmp; | |
445 } | |
446 } | |
447 | |
5389 | 448 idx_arg.elem (j) = xisnan (tmp_min) ? 0 : idx_j; |
5164 | 449 if (abs_min != 0.) |
450 nel++; | |
451 } | |
452 | |
453 result = SparseComplexMatrix (1, nc, nel); | |
454 | |
5275 | 455 octave_idx_type ii = 0; |
5164 | 456 result.xcidx (0) = 0; |
5275 | 457 for (octave_idx_type j = 0; j < nc; j++) |
5164 | 458 { |
459 Complex tmp = elem (idx_arg(j), j); | |
460 if (tmp != 0.) | |
461 { | |
462 result.xdata (ii) = tmp; | |
463 result.xridx (ii++) = 0; | |
464 } | |
465 result.xcidx (j+1) = ii; | |
466 } | |
467 } | |
468 else | |
469 { | |
470 idx_arg.resize (nr, 1, 0); | |
471 | |
5275 | 472 for (octave_idx_type i = cidx(0); i < cidx(1); i++) |
5164 | 473 idx_arg.elem(ridx(i)) = -1; |
474 | |
5275 | 475 for (octave_idx_type j = 0; j < nc; j++) |
476 for (octave_idx_type i = 0; i < nr; i++) | |
5164 | 477 { |
478 if (idx_arg.elem(i) != -1) | |
479 continue; | |
480 bool found = false; | |
5275 | 481 for (octave_idx_type k = cidx(j); k < cidx(j+1); k++) |
5164 | 482 if (ridx(k) == i) |
483 { | |
484 found = true; | |
485 break; | |
486 } | |
487 | |
488 if (!found) | |
489 idx_arg.elem(i) = j; | |
490 | |
491 } | |
492 | |
5275 | 493 for (octave_idx_type j = 0; j < nc; j++) |
5164 | 494 { |
5275 | 495 for (octave_idx_type i = cidx(j); i < cidx(j+1); i++) |
5164 | 496 { |
5275 | 497 octave_idx_type ir = ridx (i); |
498 octave_idx_type ix = idx_arg.elem (ir); | |
5164 | 499 Complex tmp = data (i); |
500 | |
5389 | 501 if (xisnan (tmp)) |
5164 | 502 continue; |
5261 | 503 else if (ix == -1 || std::abs(tmp) < std::abs(elem (ir, ix))) |
5164 | 504 idx_arg.elem (ir) = j; |
505 } | |
506 } | |
507 | |
5275 | 508 octave_idx_type nel = 0; |
509 for (octave_idx_type j = 0; j < nr; j++) | |
5164 | 510 if (idx_arg.elem(j) == -1 || elem (j, idx_arg.elem (j)) != 0.) |
511 nel++; | |
512 | |
513 result = SparseComplexMatrix (nr, 1, nel); | |
514 | |
5275 | 515 octave_idx_type ii = 0; |
5164 | 516 result.xcidx (0) = 0; |
517 result.xcidx (1) = nel; | |
5275 | 518 for (octave_idx_type j = 0; j < nr; j++) |
5164 | 519 { |
520 if (idx_arg(j) == -1) | |
521 { | |
522 idx_arg(j) = 0; | |
523 result.xdata (ii) = Complex_NaN_result; | |
524 result.xridx (ii++) = j; | |
525 } | |
526 else | |
527 { | |
528 Complex tmp = elem (j, idx_arg(j)); | |
529 if (tmp != 0.) | |
530 { | |
531 result.xdata (ii) = tmp; | |
532 result.xridx (ii++) = j; | |
533 } | |
534 } | |
535 } | |
536 } | |
537 | |
538 return result; | |
539 } | |
540 | |
8303
b11c31849b44
improve norm computation capabilities
Jaroslav Hajek <highegg@gmail.com>
parents:
7922
diff
changeset
|
541 ComplexRowVector |
b11c31849b44
improve norm computation capabilities
Jaroslav Hajek <highegg@gmail.com>
parents:
7922
diff
changeset
|
542 SparseComplexMatrix::row (octave_idx_type i) const |
b11c31849b44
improve norm computation capabilities
Jaroslav Hajek <highegg@gmail.com>
parents:
7922
diff
changeset
|
543 { |
b11c31849b44
improve norm computation capabilities
Jaroslav Hajek <highegg@gmail.com>
parents:
7922
diff
changeset
|
544 octave_idx_type nc = columns (); |
b11c31849b44
improve norm computation capabilities
Jaroslav Hajek <highegg@gmail.com>
parents:
7922
diff
changeset
|
545 ComplexRowVector retval (nc, 0); |
b11c31849b44
improve norm computation capabilities
Jaroslav Hajek <highegg@gmail.com>
parents:
7922
diff
changeset
|
546 |
b11c31849b44
improve norm computation capabilities
Jaroslav Hajek <highegg@gmail.com>
parents:
7922
diff
changeset
|
547 for (octave_idx_type j = 0; j < nc; j++) |
b11c31849b44
improve norm computation capabilities
Jaroslav Hajek <highegg@gmail.com>
parents:
7922
diff
changeset
|
548 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
|
549 { |
b11c31849b44
improve norm computation capabilities
Jaroslav Hajek <highegg@gmail.com>
parents:
7922
diff
changeset
|
550 if (ridx (k) == i) |
b11c31849b44
improve norm computation capabilities
Jaroslav Hajek <highegg@gmail.com>
parents:
7922
diff
changeset
|
551 { |
b11c31849b44
improve norm computation capabilities
Jaroslav Hajek <highegg@gmail.com>
parents:
7922
diff
changeset
|
552 retval(j) = data (k); |
b11c31849b44
improve norm computation capabilities
Jaroslav Hajek <highegg@gmail.com>
parents:
7922
diff
changeset
|
553 break; |
b11c31849b44
improve norm computation capabilities
Jaroslav Hajek <highegg@gmail.com>
parents:
7922
diff
changeset
|
554 } |
b11c31849b44
improve norm computation capabilities
Jaroslav Hajek <highegg@gmail.com>
parents:
7922
diff
changeset
|
555 } |
b11c31849b44
improve norm computation capabilities
Jaroslav Hajek <highegg@gmail.com>
parents:
7922
diff
changeset
|
556 |
b11c31849b44
improve norm computation capabilities
Jaroslav Hajek <highegg@gmail.com>
parents:
7922
diff
changeset
|
557 return retval; |
b11c31849b44
improve norm computation capabilities
Jaroslav Hajek <highegg@gmail.com>
parents:
7922
diff
changeset
|
558 } |
b11c31849b44
improve norm computation capabilities
Jaroslav Hajek <highegg@gmail.com>
parents:
7922
diff
changeset
|
559 |
b11c31849b44
improve norm computation capabilities
Jaroslav Hajek <highegg@gmail.com>
parents:
7922
diff
changeset
|
560 ComplexColumnVector |
b11c31849b44
improve norm computation capabilities
Jaroslav Hajek <highegg@gmail.com>
parents:
7922
diff
changeset
|
561 SparseComplexMatrix::column (octave_idx_type i) const |
b11c31849b44
improve norm computation capabilities
Jaroslav Hajek <highegg@gmail.com>
parents:
7922
diff
changeset
|
562 { |
b11c31849b44
improve norm computation capabilities
Jaroslav Hajek <highegg@gmail.com>
parents:
7922
diff
changeset
|
563 octave_idx_type nr = rows (); |
b11c31849b44
improve norm computation capabilities
Jaroslav Hajek <highegg@gmail.com>
parents:
7922
diff
changeset
|
564 ComplexColumnVector retval (nr); |
b11c31849b44
improve norm computation capabilities
Jaroslav Hajek <highegg@gmail.com>
parents:
7922
diff
changeset
|
565 |
b11c31849b44
improve norm computation capabilities
Jaroslav Hajek <highegg@gmail.com>
parents:
7922
diff
changeset
|
566 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
|
567 retval(ridx (k)) = data (k); |
b11c31849b44
improve norm computation capabilities
Jaroslav Hajek <highegg@gmail.com>
parents:
7922
diff
changeset
|
568 |
b11c31849b44
improve norm computation capabilities
Jaroslav Hajek <highegg@gmail.com>
parents:
7922
diff
changeset
|
569 return retval; |
b11c31849b44
improve norm computation capabilities
Jaroslav Hajek <highegg@gmail.com>
parents:
7922
diff
changeset
|
570 } |
b11c31849b44
improve norm computation capabilities
Jaroslav Hajek <highegg@gmail.com>
parents:
7922
diff
changeset
|
571 |
5164 | 572 // destructive insert/delete/reorder operations |
573 | |
574 SparseComplexMatrix& | |
5275 | 575 SparseComplexMatrix::insert (const SparseMatrix& a, octave_idx_type r, octave_idx_type c) |
5164 | 576 { |
577 SparseComplexMatrix tmp (a); | |
6060 | 578 return insert (tmp /*a*/, r, c); |
5164 | 579 } |
580 | |
581 SparseComplexMatrix& | |
5275 | 582 SparseComplexMatrix::insert (const SparseComplexMatrix& a, octave_idx_type r, octave_idx_type c) |
5164 | 583 { |
584 MSparse<Complex>::insert (a, r, c); | |
585 return *this; | |
586 } | |
587 | |
6823 | 588 SparseComplexMatrix& |
589 SparseComplexMatrix::insert (const SparseMatrix& a, const Array<octave_idx_type>& indx) | |
590 { | |
591 SparseComplexMatrix tmp (a); | |
592 return insert (tmp /*a*/, indx); | |
593 } | |
594 | |
595 SparseComplexMatrix& | |
596 SparseComplexMatrix::insert (const SparseComplexMatrix& a, const Array<octave_idx_type>& indx) | |
597 { | |
598 MSparse<Complex>::insert (a, indx); | |
599 return *this; | |
600 } | |
601 | |
5164 | 602 SparseComplexMatrix |
603 SparseComplexMatrix::concat (const SparseComplexMatrix& rb, | |
5275 | 604 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 SparseComplexMatrix::concat (const SparseMatrix& rb, const Array<octave_idx_type>& ra_idx) |
5164 | 614 { |
615 SparseComplexMatrix tmp (rb); | |
616 if (rb.rows () > 0 && rb.cols () > 0) | |
617 insert (tmp, ra_idx(0), ra_idx(1)); | |
618 return *this; | |
619 } | |
620 | |
621 ComplexMatrix | |
622 SparseComplexMatrix::matrix_value (void) const | |
623 { | |
5275 | 624 octave_idx_type nr = rows (); |
625 octave_idx_type nc = cols (); | |
5164 | 626 ComplexMatrix retval (nr, nc, Complex (0.0, 0.0)); |
627 | |
5275 | 628 for (octave_idx_type j = 0; j < nc; j++) |
629 for (octave_idx_type i = cidx(j); i < cidx(j+1); i++) | |
5164 | 630 retval.elem (ridx(i), j) = data (i); |
631 | |
632 return retval; | |
633 } | |
634 | |
635 SparseComplexMatrix | |
636 SparseComplexMatrix::hermitian (void) const | |
637 { | |
5275 | 638 octave_idx_type nr = rows (); |
639 octave_idx_type nc = cols (); | |
5681 | 640 octave_idx_type nz = nnz (); |
5164 | 641 SparseComplexMatrix retval (nc, nr, nz); |
642 | |
5648 | 643 OCTAVE_LOCAL_BUFFER (octave_idx_type, w, nr + 1); |
644 for (octave_idx_type i = 0; i < nr; i++) | |
645 w[i] = 0; | |
646 for (octave_idx_type i = 0; i < nz; i++) | |
647 w[ridx(i)]++; | |
648 nz = 0; | |
649 for (octave_idx_type i = 0; i < nr; i++) | |
5164 | 650 { |
5648 | 651 retval.xcidx(i) = nz; |
652 nz += w[i]; | |
653 w[i] = retval.xcidx(i); | |
5164 | 654 } |
5648 | 655 retval.xcidx(nr) = nz; |
656 w[nr] = nz; | |
657 | |
658 for (octave_idx_type j = 0; j < nc; j++) | |
659 for (octave_idx_type k = cidx(j); k < cidx(j+1); k++) | |
660 { | |
661 octave_idx_type q = w [ridx(k)]++; | |
662 retval.xridx (q) = j; | |
663 retval.xdata (q) = conj (data (k)); | |
664 } | |
5164 | 665 |
666 return retval; | |
667 } | |
668 | |
669 SparseComplexMatrix | |
670 conj (const SparseComplexMatrix& a) | |
671 { | |
5275 | 672 octave_idx_type nr = a.rows (); |
673 octave_idx_type nc = a.cols (); | |
5681 | 674 octave_idx_type nz = a.nnz (); |
5164 | 675 SparseComplexMatrix retval (nc, nr, nz); |
676 | |
5275 | 677 for (octave_idx_type i = 0; i < nc + 1; i++) |
5164 | 678 retval.cidx (i) = a.cidx (i); |
679 | |
5275 | 680 for (octave_idx_type i = 0; i < nz; i++) |
5164 | 681 { |
682 retval.data (i) = conj (a.data (i)); | |
683 retval.ridx (i) = a.ridx (i); | |
684 } | |
685 | |
686 return retval; | |
687 } | |
688 | |
689 SparseComplexMatrix | |
690 SparseComplexMatrix::inverse (void) const | |
691 { | |
5275 | 692 octave_idx_type info; |
5164 | 693 double rcond; |
5785 | 694 MatrixType mattype (*this); |
5506 | 695 return inverse (mattype, info, rcond, 0, 0); |
696 } | |
697 | |
698 SparseComplexMatrix | |
5785 | 699 SparseComplexMatrix::inverse (MatrixType& mattype) const |
5506 | 700 { |
701 octave_idx_type info; | |
702 double rcond; | |
703 return inverse (mattype, info, rcond, 0, 0); | |
5164 | 704 } |
705 | |
706 SparseComplexMatrix | |
5785 | 707 SparseComplexMatrix::inverse (MatrixType& mattype, octave_idx_type& info) const |
5164 | 708 { |
709 double rcond; | |
5506 | 710 return inverse (mattype, info, rcond, 0, 0); |
711 } | |
712 | |
713 SparseComplexMatrix | |
5785 | 714 SparseComplexMatrix::dinverse (MatrixType &mattyp, octave_idx_type& info, |
5610 | 715 double& rcond, const bool, |
5506 | 716 const bool calccond) const |
717 { | |
718 SparseComplexMatrix retval; | |
719 | |
720 octave_idx_type nr = rows (); | |
721 octave_idx_type nc = cols (); | |
722 info = 0; | |
723 | |
724 if (nr == 0 || nc == 0 || nr != nc) | |
725 (*current_liboctave_error_handler) ("inverse requires square matrix"); | |
726 else | |
727 { | |
728 // Print spparms("spumoni") info if requested | |
729 int typ = mattyp.type (); | |
730 mattyp.info (); | |
731 | |
5785 | 732 if (typ == MatrixType::Diagonal || |
733 typ == MatrixType::Permuted_Diagonal) | |
5506 | 734 { |
5785 | 735 if (typ == MatrixType::Permuted_Diagonal) |
5506 | 736 retval = transpose(); |
737 else | |
738 retval = *this; | |
739 | |
740 // Force make_unique to be called | |
741 Complex *v = retval.data(); | |
742 | |
743 if (calccond) | |
744 { | |
745 double dmax = 0., dmin = octave_Inf; | |
746 for (octave_idx_type i = 0; i < nr; i++) | |
747 { | |
748 double tmp = std::abs(v[i]); | |
749 if (tmp > dmax) | |
750 dmax = tmp; | |
751 if (tmp < dmin) | |
752 dmin = tmp; | |
753 } | |
754 rcond = dmin / dmax; | |
755 } | |
756 | |
757 for (octave_idx_type i = 0; i < nr; i++) | |
758 v[i] = 1.0 / v[i]; | |
759 } | |
760 else | |
761 (*current_liboctave_error_handler) ("incorrect matrix type"); | |
762 } | |
763 | |
764 return retval; | |
765 } | |
766 | |
767 SparseComplexMatrix | |
5785 | 768 SparseComplexMatrix::tinverse (MatrixType &mattyp, octave_idx_type& info, |
5610 | 769 double& rcond, const bool, |
5506 | 770 const bool calccond) const |
771 { | |
772 SparseComplexMatrix retval; | |
773 | |
774 octave_idx_type nr = rows (); | |
775 octave_idx_type nc = cols (); | |
776 info = 0; | |
777 | |
778 if (nr == 0 || nc == 0 || nr != nc) | |
779 (*current_liboctave_error_handler) ("inverse requires square matrix"); | |
780 else | |
781 { | |
782 // Print spparms("spumoni") info if requested | |
783 int typ = mattyp.type (); | |
784 mattyp.info (); | |
785 | |
5785 | 786 if (typ == MatrixType::Upper || typ == MatrixType::Permuted_Upper || |
787 typ == MatrixType::Lower || typ == MatrixType::Permuted_Lower) | |
5506 | 788 { |
789 double anorm = 0.; | |
790 double ainvnorm = 0.; | |
791 | |
792 if (calccond) | |
793 { | |
794 // Calculate the 1-norm of matrix for rcond calculation | |
795 for (octave_idx_type j = 0; j < nr; j++) | |
796 { | |
797 double atmp = 0.; | |
798 for (octave_idx_type i = cidx(j); i < cidx(j+1); i++) | |
799 atmp += std::abs(data(i)); | |
800 if (atmp > anorm) | |
801 anorm = atmp; | |
802 } | |
803 } | |
804 | |
5785 | 805 if (typ == MatrixType::Upper || typ == MatrixType::Lower) |
5506 | 806 { |
5681 | 807 octave_idx_type nz = nnz (); |
5506 | 808 octave_idx_type cx = 0; |
809 octave_idx_type nz2 = nz; | |
810 retval = SparseComplexMatrix (nr, nc, nz2); | |
811 | |
812 for (octave_idx_type i = 0; i < nr; i++) | |
813 { | |
814 OCTAVE_QUIT; | |
815 // place the 1 in the identity position | |
816 octave_idx_type cx_colstart = cx; | |
817 | |
818 if (cx == nz2) | |
819 { | |
820 nz2 *= 2; | |
821 retval.change_capacity (nz2); | |
822 } | |
823 | |
824 retval.xcidx(i) = cx; | |
825 retval.xridx(cx) = i; | |
826 retval.xdata(cx) = 1.0; | |
827 cx++; | |
828 | |
829 // iterate accross columns of input matrix | |
830 for (octave_idx_type j = i+1; j < nr; j++) | |
831 { | |
832 Complex v = 0.; | |
833 // iterate to calculate sum | |
834 octave_idx_type colXp = retval.xcidx(i); | |
835 octave_idx_type colUp = cidx(j); | |
836 octave_idx_type rpX, rpU; | |
5876 | 837 |
838 if (cidx(j) == cidx(j+1)) | |
839 { | |
840 (*current_liboctave_error_handler) | |
841 ("division by zero"); | |
842 goto inverse_singular; | |
843 } | |
844 | |
5506 | 845 do |
846 { | |
847 OCTAVE_QUIT; | |
848 rpX = retval.xridx(colXp); | |
849 rpU = ridx(colUp); | |
850 | |
851 if (rpX < rpU) | |
852 colXp++; | |
853 else if (rpX > rpU) | |
854 colUp++; | |
855 else | |
856 { | |
857 v -= retval.xdata(colXp) * data(colUp); | |
858 colXp++; | |
859 colUp++; | |
860 } | |
861 } while ((rpX<j) && (rpU<j) && | |
862 (colXp<cx) && (colUp<nz)); | |
863 | |
5876 | 864 |
5506 | 865 // get A(m,m) |
5876 | 866 if (typ == MatrixType::Upper) |
867 colUp = cidx(j+1) - 1; | |
868 else | |
5877 | 869 colUp = cidx(j); |
5506 | 870 Complex pivot = data(colUp); |
5877 | 871 if (pivot == 0. || ridx(colUp) != j) |
5876 | 872 { |
873 (*current_liboctave_error_handler) | |
874 ("division by zero"); | |
875 goto inverse_singular; | |
876 } | |
5506 | 877 |
878 if (v != 0.) | |
879 { | |
880 if (cx == nz2) | |
881 { | |
882 nz2 *= 2; | |
883 retval.change_capacity (nz2); | |
884 } | |
885 | |
886 retval.xridx(cx) = j; | |
887 retval.xdata(cx) = v / pivot; | |
888 cx++; | |
889 } | |
890 } | |
891 | |
892 // get A(m,m) | |
5876 | 893 octave_idx_type colUp; |
894 if (typ == MatrixType::Upper) | |
895 colUp = cidx(i+1) - 1; | |
896 else | |
5877 | 897 colUp = cidx(i); |
5506 | 898 Complex pivot = data(colUp); |
5877 | 899 if (pivot == 0. || ridx(colUp) != i) |
5876 | 900 { |
901 (*current_liboctave_error_handler) ("division by zero"); | |
902 goto inverse_singular; | |
903 } | |
5506 | 904 |
905 if (pivot != 1.0) | |
906 for (octave_idx_type j = cx_colstart; j < cx; j++) | |
907 retval.xdata(j) /= pivot; | |
908 } | |
909 retval.xcidx(nr) = cx; | |
910 retval.maybe_compress (); | |
911 } | |
912 else | |
913 { | |
5681 | 914 octave_idx_type nz = nnz (); |
5506 | 915 octave_idx_type cx = 0; |
916 octave_idx_type nz2 = nz; | |
917 retval = SparseComplexMatrix (nr, nc, nz2); | |
918 | |
919 OCTAVE_LOCAL_BUFFER (Complex, work, nr); | |
920 OCTAVE_LOCAL_BUFFER (octave_idx_type, rperm, nr); | |
921 | |
922 octave_idx_type *perm = mattyp.triangular_perm(); | |
5785 | 923 if (typ == MatrixType::Permuted_Upper) |
5506 | 924 { |
925 for (octave_idx_type i = 0; i < nr; i++) | |
926 rperm[perm[i]] = i; | |
927 } | |
928 else | |
929 { | |
930 for (octave_idx_type i = 0; i < nr; i++) | |
931 rperm[i] = perm[i]; | |
932 for (octave_idx_type i = 0; i < nr; i++) | |
933 perm[rperm[i]] = i; | |
934 } | |
935 | |
936 for (octave_idx_type i = 0; i < nr; i++) | |
937 { | |
938 OCTAVE_QUIT; | |
939 octave_idx_type iidx = rperm[i]; | |
940 | |
941 for (octave_idx_type j = 0; j < nr; j++) | |
942 work[j] = 0.; | |
943 | |
944 // place the 1 in the identity position | |
945 work[iidx] = 1.0; | |
946 | |
947 // iterate accross columns of input matrix | |
948 for (octave_idx_type j = iidx+1; j < nr; j++) | |
949 { | |
950 Complex v = 0.; | |
951 octave_idx_type jidx = perm[j]; | |
952 // iterate to calculate sum | |
953 for (octave_idx_type k = cidx(jidx); | |
954 k < cidx(jidx+1); k++) | |
955 { | |
956 OCTAVE_QUIT; | |
957 v -= work[ridx(k)] * data(k); | |
958 } | |
959 | |
960 // get A(m,m) | |
5876 | 961 Complex pivot; |
962 if (typ == MatrixType::Permuted_Upper) | |
963 pivot = data(cidx(jidx+1) - 1); | |
964 else | |
5877 | 965 pivot = data(cidx(jidx)); |
5506 | 966 if (pivot == 0.) |
5876 | 967 { |
968 (*current_liboctave_error_handler) | |
969 ("division by zero"); | |
970 goto inverse_singular; | |
971 } | |
5506 | 972 |
973 work[j] = v / pivot; | |
974 } | |
975 | |
976 // get A(m,m) | |
5876 | 977 octave_idx_type colUp; |
978 if (typ == MatrixType::Permuted_Upper) | |
979 colUp = cidx(perm[iidx]+1) - 1; | |
980 else | |
5877 | 981 colUp = cidx(perm[iidx]); |
5876 | 982 |
983 Complex pivot = data(colUp); | |
984 if (pivot == 0.) | |
985 { | |
986 (*current_liboctave_error_handler) | |
987 ("division by zero"); | |
988 goto inverse_singular; | |
989 } | |
5506 | 990 |
991 octave_idx_type new_cx = cx; | |
992 for (octave_idx_type j = iidx; j < nr; j++) | |
993 if (work[j] != 0.0) | |
994 { | |
995 new_cx++; | |
996 if (pivot != 1.0) | |
997 work[j] /= pivot; | |
998 } | |
999 | |
1000 if (cx < new_cx) | |
1001 { | |
1002 nz2 = (2*nz2 < new_cx ? new_cx : 2*nz2); | |
1003 retval.change_capacity (nz2); | |
1004 } | |
1005 | |
1006 retval.xcidx(i) = cx; | |
1007 for (octave_idx_type j = iidx; j < nr; j++) | |
1008 if (work[j] != 0.) | |
1009 { | |
1010 retval.xridx(cx) = j; | |
1011 retval.xdata(cx++) = work[j]; | |
1012 } | |
1013 } | |
1014 | |
1015 retval.xcidx(nr) = cx; | |
1016 retval.maybe_compress (); | |
1017 } | |
1018 | |
1019 if (calccond) | |
1020 { | |
1021 // Calculate the 1-norm of inverse matrix for rcond calculation | |
1022 for (octave_idx_type j = 0; j < nr; j++) | |
1023 { | |
1024 double atmp = 0.; | |
1025 for (octave_idx_type i = retval.cidx(j); | |
1026 i < retval.cidx(j+1); i++) | |
1027 atmp += std::abs(retval.data(i)); | |
1028 if (atmp > ainvnorm) | |
1029 ainvnorm = atmp; | |
1030 } | |
1031 | |
1032 rcond = 1. / ainvnorm / anorm; | |
1033 } | |
1034 } | |
1035 else | |
1036 (*current_liboctave_error_handler) ("incorrect matrix type"); | |
1037 } | |
1038 | |
1039 return retval; | |
5876 | 1040 |
1041 inverse_singular: | |
1042 return SparseComplexMatrix(); | |
5164 | 1043 } |
1044 | |
1045 SparseComplexMatrix | |
5785 | 1046 SparseComplexMatrix::inverse (MatrixType& mattype, octave_idx_type& info, |
5610 | 1047 double& rcond, int, int calc_cond) const |
5506 | 1048 { |
1049 int typ = mattype.type (false); | |
1050 SparseComplexMatrix ret; | |
1051 | |
5785 | 1052 if (typ == MatrixType::Unknown) |
5506 | 1053 typ = mattype.type (*this); |
1054 | |
5785 | 1055 if (typ == MatrixType::Diagonal || typ == MatrixType::Permuted_Diagonal) |
5506 | 1056 ret = dinverse (mattype, info, rcond, true, calc_cond); |
5785 | 1057 else if (typ == MatrixType::Upper || typ == MatrixType::Permuted_Upper) |
5506 | 1058 ret = tinverse (mattype, info, rcond, true, calc_cond).transpose(); |
5785 | 1059 else if (typ == MatrixType::Lower || typ == MatrixType::Permuted_Lower) |
6185 | 1060 { |
1061 MatrixType newtype = mattype.transpose(); | |
1062 ret = transpose().tinverse (newtype, info, rcond, true, calc_cond); | |
1063 } | |
6840 | 1064 else |
5506 | 1065 { |
1066 if (mattype.is_hermitian()) | |
1067 { | |
5785 | 1068 MatrixType tmp_typ (MatrixType::Upper); |
5506 | 1069 SparseComplexCHOL fact (*this, info, false); |
1070 rcond = fact.rcond(); | |
1071 if (info == 0) | |
1072 { | |
1073 double rcond2; | |
1074 SparseMatrix Q = fact.Q(); | |
1075 SparseComplexMatrix InvL = fact.L().transpose(). | |
1076 tinverse(tmp_typ, info, rcond2, true, false); | |
1077 ret = Q * InvL.hermitian() * InvL * Q.transpose(); | |
1078 } | |
1079 else | |
1080 { | |
1081 // Matrix is either singular or not positive definite | |
1082 mattype.mark_as_unsymmetric (); | |
5785 | 1083 typ = MatrixType::Full; |
5506 | 1084 } |
1085 } | |
1086 | |
1087 if (!mattype.is_hermitian()) | |
1088 { | |
1089 octave_idx_type n = rows(); | |
1090 ColumnVector Qinit(n); | |
1091 for (octave_idx_type i = 0; i < n; i++) | |
1092 Qinit(i) = i; | |
1093 | |
5785 | 1094 MatrixType tmp_typ (MatrixType::Upper); |
7515
f3c00dc0912b
Eliminate the rest of the dispatched sparse functions
David Bateman <dbateman@free.fr>
parents:
7503
diff
changeset
|
1095 SparseComplexLU fact (*this, Qinit, Matrix (), false, false); |
5506 | 1096 rcond = fact.rcond(); |
1097 double rcond2; | |
1098 SparseComplexMatrix InvL = fact.L().transpose(). | |
1099 tinverse(tmp_typ, info, rcond2, true, false); | |
1100 SparseComplexMatrix InvU = fact.U(). | |
1101 tinverse(tmp_typ, info, rcond2, true, false).transpose(); | |
1102 ret = fact.Pc().transpose() * InvU * InvL * fact.Pr(); | |
1103 } | |
1104 } | |
1105 | |
1106 return ret; | |
5164 | 1107 } |
1108 | |
1109 ComplexDET | |
1110 SparseComplexMatrix::determinant (void) const | |
1111 { | |
5275 | 1112 octave_idx_type info; |
5164 | 1113 double rcond; |
1114 return determinant (info, rcond, 0); | |
1115 } | |
1116 | |
1117 ComplexDET | |
5275 | 1118 SparseComplexMatrix::determinant (octave_idx_type& info) const |
5164 | 1119 { |
1120 double rcond; | |
1121 return determinant (info, rcond, 0); | |
1122 } | |
1123 | |
1124 ComplexDET | |
5610 | 1125 SparseComplexMatrix::determinant (octave_idx_type& err, double& rcond, int) const |
5164 | 1126 { |
1127 ComplexDET retval; | |
5203 | 1128 #ifdef HAVE_UMFPACK |
5164 | 1129 |
5275 | 1130 octave_idx_type nr = rows (); |
1131 octave_idx_type nc = cols (); | |
5164 | 1132 |
1133 if (nr == 0 || nc == 0 || nr != nc) | |
1134 { | |
8335 | 1135 retval = ComplexDET (1.0); |
5164 | 1136 } |
1137 else | |
1138 { | |
1139 err = 0; | |
1140 | |
1141 // Setup the control parameters | |
1142 Matrix Control (UMFPACK_CONTROL, 1); | |
1143 double *control = Control.fortran_vec (); | |
5322 | 1144 UMFPACK_ZNAME (defaults) (control); |
5164 | 1145 |
5893 | 1146 double tmp = octave_sparse_params::get_key ("spumoni"); |
5164 | 1147 if (!xisnan (tmp)) |
1148 Control (UMFPACK_PRL) = tmp; | |
1149 | |
5893 | 1150 tmp = octave_sparse_params::get_key ("piv_tol"); |
5164 | 1151 if (!xisnan (tmp)) |
1152 { | |
1153 Control (UMFPACK_SYM_PIVOT_TOLERANCE) = tmp; | |
1154 Control (UMFPACK_PIVOT_TOLERANCE) = tmp; | |
1155 } | |
1156 | |
1157 // Set whether we are allowed to modify Q or not | |
5893 | 1158 tmp = octave_sparse_params::get_key ("autoamd"); |
5164 | 1159 if (!xisnan (tmp)) |
1160 Control (UMFPACK_FIXQ) = tmp; | |
1161 | |
1162 // Turn-off UMFPACK scaling for LU | |
1163 Control (UMFPACK_SCALE) = UMFPACK_SCALE_NONE; | |
1164 | |
5322 | 1165 UMFPACK_ZNAME (report_control) (control); |
5164 | 1166 |
5275 | 1167 const octave_idx_type *Ap = cidx (); |
1168 const octave_idx_type *Ai = ridx (); | |
5164 | 1169 const Complex *Ax = data (); |
1170 | |
5322 | 1171 UMFPACK_ZNAME (report_matrix) (nr, nc, Ap, Ai, |
5760 | 1172 reinterpret_cast<const double *> (Ax), |
7520 | 1173 0, 1, control); |
5164 | 1174 |
1175 void *Symbolic; | |
1176 Matrix Info (1, UMFPACK_INFO); | |
1177 double *info = Info.fortran_vec (); | |
5322 | 1178 int status = UMFPACK_ZNAME (qsymbolic) |
7520 | 1179 (nr, nc, Ap, Ai, reinterpret_cast<const double *> (Ax), 0, |
1180 0, &Symbolic, control, info); | |
5164 | 1181 |
1182 if (status < 0) | |
1183 { | |
1184 (*current_liboctave_error_handler) | |
1185 ("SparseComplexMatrix::determinant symbolic factorization failed"); | |
1186 | |
5322 | 1187 UMFPACK_ZNAME (report_status) (control, status); |
1188 UMFPACK_ZNAME (report_info) (control, info); | |
1189 | |
1190 UMFPACK_ZNAME (free_symbolic) (&Symbolic) ; | |
5164 | 1191 } |
1192 else | |
1193 { | |
5322 | 1194 UMFPACK_ZNAME (report_symbolic) (Symbolic, control); |
5164 | 1195 |
1196 void *Numeric; | |
5760 | 1197 status |
1198 = UMFPACK_ZNAME (numeric) (Ap, Ai, | |
1199 reinterpret_cast<const double *> (Ax), | |
7520 | 1200 0, Symbolic, &Numeric, control, info) ; |
5322 | 1201 UMFPACK_ZNAME (free_symbolic) (&Symbolic) ; |
5164 | 1202 |
1203 rcond = Info (UMFPACK_RCOND); | |
1204 | |
1205 if (status < 0) | |
1206 { | |
1207 (*current_liboctave_error_handler) | |
1208 ("SparseComplexMatrix::determinant numeric factorization failed"); | |
1209 | |
5322 | 1210 UMFPACK_ZNAME (report_status) (control, status); |
1211 UMFPACK_ZNAME (report_info) (control, info); | |
1212 | |
1213 UMFPACK_ZNAME (free_numeric) (&Numeric); | |
5164 | 1214 } |
1215 else | |
1216 { | |
5322 | 1217 UMFPACK_ZNAME (report_numeric) (Numeric, control); |
5164 | 1218 |
8335 | 1219 double c10[2], e10; |
1220 | |
1221 status = UMFPACK_ZNAME (get_determinant) (c10, 0, &e10, | |
1222 Numeric, info); | |
5164 | 1223 |
1224 if (status < 0) | |
1225 { | |
1226 (*current_liboctave_error_handler) | |
1227 ("SparseComplexMatrix::determinant error calculating determinant"); | |
1228 | |
5322 | 1229 UMFPACK_ZNAME (report_status) (control, status); |
1230 UMFPACK_ZNAME (report_info) (control, info); | |
5164 | 1231 } |
1232 else | |
8335 | 1233 retval = ComplexDET (Complex (c10[0], c10[1]), e10, 10); |
5346 | 1234 |
1235 UMFPACK_ZNAME (free_numeric) (&Numeric); | |
5164 | 1236 } |
1237 } | |
1238 } | |
5203 | 1239 #else |
1240 (*current_liboctave_error_handler) ("UMFPACK not installed"); | |
1241 #endif | |
5164 | 1242 |
1243 return retval; | |
1244 } | |
1245 | |
1246 ComplexMatrix | |
5785 | 1247 SparseComplexMatrix::dsolve (MatrixType &mattype, const Matrix& b, |
5681 | 1248 octave_idx_type& err, double& rcond, |
1249 solve_singularity_handler, bool calc_cond) const | |
5164 | 1250 { |
1251 ComplexMatrix retval; | |
1252 | |
5275 | 1253 octave_idx_type nr = rows (); |
1254 octave_idx_type nc = cols (); | |
5630 | 1255 octave_idx_type nm = (nc < nr ? nc : nr); |
5164 | 1256 err = 0; |
1257 | |
6924 | 1258 if (nr != b.rows ()) |
5164 | 1259 (*current_liboctave_error_handler) |
1260 ("matrix dimension mismatch solution of linear equations"); | |
6924 | 1261 else if (nr == 0 || nc == 0 || b.cols () == 0) |
1262 retval = ComplexMatrix (nc, b.cols (), Complex (0.0, 0.0)); | |
5164 | 1263 else |
1264 { | |
1265 // Print spparms("spumoni") info if requested | |
1266 int typ = mattype.type (); | |
1267 mattype.info (); | |
1268 | |
5785 | 1269 if (typ == MatrixType::Diagonal || |
1270 typ == MatrixType::Permuted_Diagonal) | |
5164 | 1271 { |
5630 | 1272 retval.resize (nc, b.cols(), Complex(0.,0.)); |
5785 | 1273 if (typ == MatrixType::Diagonal) |
5275 | 1274 for (octave_idx_type j = 0; j < b.cols(); j++) |
5630 | 1275 for (octave_idx_type i = 0; i < nm; i++) |
1276 retval(i,j) = b(i,j) / data (i); | |
5164 | 1277 else |
5275 | 1278 for (octave_idx_type j = 0; j < b.cols(); j++) |
5630 | 1279 for (octave_idx_type k = 0; k < nc; k++) |
1280 for (octave_idx_type i = cidx(k); i < cidx(k+1); i++) | |
1281 retval(k,j) = b(ridx(i),j) / data (i); | |
5164 | 1282 |
5681 | 1283 if (calc_cond) |
1284 { | |
1285 double dmax = 0., dmin = octave_Inf; | |
1286 for (octave_idx_type i = 0; i < nm; i++) | |
1287 { | |
1288 double tmp = std::abs(data(i)); | |
1289 if (tmp > dmax) | |
1290 dmax = tmp; | |
1291 if (tmp < dmin) | |
1292 dmin = tmp; | |
1293 } | |
1294 rcond = dmin / dmax; | |
1295 } | |
1296 else | |
1297 rcond = 1.0; | |
5164 | 1298 } |
1299 else | |
1300 (*current_liboctave_error_handler) ("incorrect matrix type"); | |
1301 } | |
1302 | |
1303 return retval; | |
1304 } | |
1305 | |
1306 SparseComplexMatrix | |
5785 | 1307 SparseComplexMatrix::dsolve (MatrixType &mattype, const SparseMatrix& b, |
5630 | 1308 octave_idx_type& err, double& rcond, |
5681 | 1309 solve_singularity_handler, |
1310 bool calc_cond) const | |
5164 | 1311 { |
1312 SparseComplexMatrix retval; | |
1313 | |
5275 | 1314 octave_idx_type nr = rows (); |
1315 octave_idx_type nc = cols (); | |
5630 | 1316 octave_idx_type nm = (nc < nr ? nc : nr); |
5164 | 1317 err = 0; |
1318 | |
6924 | 1319 if (nr != b.rows ()) |
5164 | 1320 (*current_liboctave_error_handler) |
1321 ("matrix dimension mismatch solution of linear equations"); | |
6924 | 1322 else if (nr == 0 || nc == 0 || b.cols () == 0) |
1323 retval = SparseComplexMatrix (nc, b.cols ()); | |
5164 | 1324 else |
1325 { | |
1326 // Print spparms("spumoni") info if requested | |
1327 int typ = mattype.type (); | |
1328 mattype.info (); | |
1329 | |
5785 | 1330 if (typ == MatrixType::Diagonal || |
1331 typ == MatrixType::Permuted_Diagonal) | |
5164 | 1332 { |
5275 | 1333 octave_idx_type b_nc = b.cols (); |
5681 | 1334 octave_idx_type b_nz = b.nnz (); |
5630 | 1335 retval = SparseComplexMatrix (nc, b_nc, b_nz); |
5164 | 1336 |
1337 retval.xcidx(0) = 0; | |
5275 | 1338 octave_idx_type ii = 0; |
5785 | 1339 if (typ == MatrixType::Diagonal) |
5275 | 1340 for (octave_idx_type j = 0; j < b.cols(); j++) |
5164 | 1341 { |
5275 | 1342 for (octave_idx_type i = b.cidx(j); i < b.cidx(j+1); i++) |
5164 | 1343 { |
5681 | 1344 if (b.ridx(i) >= nm) |
1345 break; | |
5164 | 1346 retval.xridx (ii) = b.ridx(i); |
1347 retval.xdata (ii++) = b.data(i) / data (b.ridx (i)); | |
1348 } | |
1349 retval.xcidx(j+1) = ii; | |
1350 } | |
1351 else | |
5275 | 1352 for (octave_idx_type j = 0; j < b.cols(); j++) |
5164 | 1353 { |
5630 | 1354 for (octave_idx_type l = 0; l < nc; l++) |
1355 for (octave_idx_type i = cidx(l); i < cidx(l+1); i++) | |
1356 { | |
1357 bool found = false; | |
1358 octave_idx_type k; | |
1359 for (k = b.cidx(j); k < b.cidx(j+1); k++) | |
1360 if (ridx(i) == b.ridx(k)) | |
1361 { | |
1362 found = true; | |
1363 break; | |
1364 } | |
1365 if (found) | |
5164 | 1366 { |
5630 | 1367 retval.xridx (ii) = l; |
1368 retval.xdata (ii++) = b.data(k) / data (i); | |
5164 | 1369 } |
5630 | 1370 } |
5164 | 1371 retval.xcidx(j+1) = ii; |
1372 } | |
1373 | |
5681 | 1374 if (calc_cond) |
1375 { | |
1376 double dmax = 0., dmin = octave_Inf; | |
1377 for (octave_idx_type i = 0; i < nm; i++) | |
1378 { | |
1379 double tmp = std::abs(data(i)); | |
1380 if (tmp > dmax) | |
1381 dmax = tmp; | |
1382 if (tmp < dmin) | |
1383 dmin = tmp; | |
1384 } | |
1385 rcond = dmin / dmax; | |
1386 } | |
1387 else | |
1388 rcond = 1.0; | |
5164 | 1389 } |
1390 else | |
1391 (*current_liboctave_error_handler) ("incorrect matrix type"); | |
1392 } | |
1393 | |
1394 return retval; | |
1395 } | |
1396 | |
1397 ComplexMatrix | |
5785 | 1398 SparseComplexMatrix::dsolve (MatrixType &mattype, const ComplexMatrix& b, |
5630 | 1399 octave_idx_type& err, double& rcond, |
5681 | 1400 solve_singularity_handler, |
1401 bool calc_cond) const | |
5164 | 1402 { |
1403 ComplexMatrix retval; | |
1404 | |
5275 | 1405 octave_idx_type nr = rows (); |
1406 octave_idx_type nc = cols (); | |
5630 | 1407 octave_idx_type nm = (nc < nr ? nc : nr); |
5164 | 1408 err = 0; |
1409 | |
6924 | 1410 if (nr != b.rows ()) |
5164 | 1411 (*current_liboctave_error_handler) |
1412 ("matrix dimension mismatch solution of linear equations"); | |
6924 | 1413 else if (nr == 0 || nc == 0 || b.cols () == 0) |
1414 retval = ComplexMatrix (nc, b.cols (), Complex (0.0, 0.0)); | |
5164 | 1415 else |
1416 { | |
1417 // Print spparms("spumoni") info if requested | |
1418 int typ = mattype.type (); | |
1419 mattype.info (); | |
1420 | |
5785 | 1421 if (typ == MatrixType::Diagonal || |
1422 typ == MatrixType::Permuted_Diagonal) | |
5164 | 1423 { |
5630 | 1424 retval.resize (nc, b.cols(), Complex(0.,0.)); |
5785 | 1425 if (typ == MatrixType::Diagonal) |
5275 | 1426 for (octave_idx_type j = 0; j < b.cols(); j++) |
5630 | 1427 for (octave_idx_type i = 0; i < nm; i++) |
5164 | 1428 retval(i,j) = b(i,j) / data (i); |
1429 else | |
5275 | 1430 for (octave_idx_type j = 0; j < b.cols(); j++) |
5630 | 1431 for (octave_idx_type k = 0; k < nc; k++) |
1432 for (octave_idx_type i = cidx(k); i < cidx(k+1); i++) | |
1433 retval(k,j) = b(ridx(i),j) / data (i); | |
5164 | 1434 |
5681 | 1435 if (calc_cond) |
1436 { | |
1437 double dmax = 0., dmin = octave_Inf; | |
1438 for (octave_idx_type i = 0; i < nr; i++) | |
1439 { | |
1440 double tmp = std::abs(data(i)); | |
1441 if (tmp > dmax) | |
1442 dmax = tmp; | |
1443 if (tmp < dmin) | |
1444 dmin = tmp; | |
1445 } | |
1446 rcond = dmin / dmax; | |
1447 } | |
1448 else | |
1449 rcond = 1.0; | |
5164 | 1450 } |
1451 else | |
1452 (*current_liboctave_error_handler) ("incorrect matrix type"); | |
1453 } | |
1454 | |
1455 return retval; | |
1456 } | |
1457 | |
1458 SparseComplexMatrix | |
5785 | 1459 SparseComplexMatrix::dsolve (MatrixType &mattype, const SparseComplexMatrix& b, |
5630 | 1460 octave_idx_type& err, double& rcond, |
5681 | 1461 solve_singularity_handler, |
1462 bool calc_cond) const | |
5164 | 1463 { |
1464 SparseComplexMatrix retval; | |
1465 | |
5275 | 1466 octave_idx_type nr = rows (); |
1467 octave_idx_type nc = cols (); | |
5630 | 1468 octave_idx_type nm = (nc < nr ? nc : nr); |
5164 | 1469 err = 0; |
1470 | |
6924 | 1471 if (nr != b.rows ()) |
5164 | 1472 (*current_liboctave_error_handler) |
1473 ("matrix dimension mismatch solution of linear equations"); | |
6924 | 1474 else if (nr == 0 || nc == 0 || b.cols () == 0) |
1475 retval = SparseComplexMatrix (nc, b.cols ()); | |
5164 | 1476 else |
1477 { | |
1478 // Print spparms("spumoni") info if requested | |
1479 int typ = mattype.type (); | |
1480 mattype.info (); | |
1481 | |
5785 | 1482 if (typ == MatrixType::Diagonal || |
1483 typ == MatrixType::Permuted_Diagonal) | |
5164 | 1484 { |
5275 | 1485 octave_idx_type b_nc = b.cols (); |
5681 | 1486 octave_idx_type b_nz = b.nnz (); |
5630 | 1487 retval = SparseComplexMatrix (nc, b_nc, b_nz); |
5164 | 1488 |
1489 retval.xcidx(0) = 0; | |
5275 | 1490 octave_idx_type ii = 0; |
5785 | 1491 if (typ == MatrixType::Diagonal) |
5275 | 1492 for (octave_idx_type j = 0; j < b.cols(); j++) |
5164 | 1493 { |
5275 | 1494 for (octave_idx_type i = b.cidx(j); i < b.cidx(j+1); i++) |
5164 | 1495 { |
5681 | 1496 if (b.ridx(i) >= nm) |
1497 break; | |
5164 | 1498 retval.xridx (ii) = b.ridx(i); |
1499 retval.xdata (ii++) = b.data(i) / data (b.ridx (i)); | |
1500 } | |
1501 retval.xcidx(j+1) = ii; | |
1502 } | |
1503 else | |
5275 | 1504 for (octave_idx_type j = 0; j < b.cols(); j++) |
5164 | 1505 { |
5630 | 1506 for (octave_idx_type l = 0; l < nc; l++) |
1507 for (octave_idx_type i = cidx(l); i < cidx(l+1); i++) | |
1508 { | |
1509 bool found = false; | |
1510 octave_idx_type k; | |
1511 for (k = b.cidx(j); k < b.cidx(j+1); k++) | |
1512 if (ridx(i) == b.ridx(k)) | |
1513 { | |
1514 found = true; | |
1515 break; | |
1516 } | |
1517 if (found) | |
5164 | 1518 { |
5630 | 1519 retval.xridx (ii) = l; |
1520 retval.xdata (ii++) = b.data(k) / data (i); | |
5164 | 1521 } |
5630 | 1522 } |
5164 | 1523 retval.xcidx(j+1) = ii; |
1524 } | |
1525 | |
5681 | 1526 if (calc_cond) |
1527 { | |
1528 double dmax = 0., dmin = octave_Inf; | |
1529 for (octave_idx_type i = 0; i < nm; i++) | |
1530 { | |
1531 double tmp = std::abs(data(i)); | |
1532 if (tmp > dmax) | |
1533 dmax = tmp; | |
1534 if (tmp < dmin) | |
1535 dmin = tmp; | |
1536 } | |
1537 rcond = dmin / dmax; | |
1538 } | |
1539 else | |
1540 rcond = 1.0; | |
5164 | 1541 } |
1542 else | |
1543 (*current_liboctave_error_handler) ("incorrect matrix type"); | |
1544 } | |
1545 | |
1546 return retval; | |
1547 } | |
1548 | |
1549 ComplexMatrix | |
5785 | 1550 SparseComplexMatrix::utsolve (MatrixType &mattype, const Matrix& b, |
5630 | 1551 octave_idx_type& err, double& rcond, |
5681 | 1552 solve_singularity_handler sing_handler, |
1553 bool calc_cond) const | |
5164 | 1554 { |
1555 ComplexMatrix retval; | |
1556 | |
5275 | 1557 octave_idx_type nr = rows (); |
1558 octave_idx_type nc = cols (); | |
5630 | 1559 octave_idx_type nm = (nc > nr ? nc : nr); |
5164 | 1560 err = 0; |
1561 | |
6924 | 1562 if (nr != b.rows ()) |
5164 | 1563 (*current_liboctave_error_handler) |
1564 ("matrix dimension mismatch solution of linear equations"); | |
6924 | 1565 else if (nr == 0 || nc == 0 || b.cols () == 0) |
1566 retval = ComplexMatrix (nc, b.cols (), Complex (0.0, 0.0)); | |
5164 | 1567 else |
1568 { | |
1569 // Print spparms("spumoni") info if requested | |
1570 int typ = mattype.type (); | |
1571 mattype.info (); | |
1572 | |
5785 | 1573 if (typ == MatrixType::Permuted_Upper || |
1574 typ == MatrixType::Upper) | |
5164 | 1575 { |
1576 double anorm = 0.; | |
1577 double ainvnorm = 0.; | |
5630 | 1578 octave_idx_type b_nc = b.cols (); |
5681 | 1579 rcond = 1.; |
1580 | |
1581 if (calc_cond) | |
1582 { | |
1583 // Calculate the 1-norm of matrix for rcond calculation | |
1584 for (octave_idx_type j = 0; j < nc; j++) | |
1585 { | |
1586 double atmp = 0.; | |
1587 for (octave_idx_type i = cidx(j); i < cidx(j+1); i++) | |
1588 atmp += std::abs(data(i)); | |
1589 if (atmp > anorm) | |
1590 anorm = atmp; | |
1591 } | |
5164 | 1592 } |
1593 | |
5785 | 1594 if (typ == MatrixType::Permuted_Upper) |
5164 | 1595 { |
5630 | 1596 retval.resize (nc, b_nc); |
5322 | 1597 octave_idx_type *perm = mattype.triangular_perm (); |
5681 | 1598 OCTAVE_LOCAL_BUFFER (Complex, work, nm); |
5164 | 1599 |
5630 | 1600 for (octave_idx_type j = 0; j < b_nc; j++) |
5164 | 1601 { |
5275 | 1602 for (octave_idx_type i = 0; i < nr; i++) |
5164 | 1603 work[i] = b(i,j); |
5630 | 1604 for (octave_idx_type i = nr; i < nc; i++) |
1605 work[i] = 0.; | |
1606 | |
1607 for (octave_idx_type k = nc-1; k >= 0; k--) | |
5164 | 1608 { |
5322 | 1609 octave_idx_type kidx = perm[k]; |
1610 | |
1611 if (work[k] != 0.) | |
5164 | 1612 { |
5681 | 1613 if (ridx(cidx(kidx+1)-1) != k || |
1614 data(cidx(kidx+1)-1) == 0.) | |
5164 | 1615 { |
1616 err = -2; | |
1617 goto triangular_error; | |
1618 } | |
1619 | |
5322 | 1620 Complex tmp = work[k] / data(cidx(kidx+1)-1); |
1621 work[k] = tmp; | |
1622 for (octave_idx_type i = cidx(kidx); | |
1623 i < cidx(kidx+1)-1; i++) | |
5164 | 1624 { |
5322 | 1625 octave_idx_type iidx = ridx(i); |
1626 work[iidx] = work[iidx] - tmp * data(i); | |
5164 | 1627 } |
1628 } | |
1629 } | |
1630 | |
5630 | 1631 for (octave_idx_type i = 0; i < nc; i++) |
5322 | 1632 retval (perm[i], j) = work[i]; |
5164 | 1633 } |
1634 | |
5681 | 1635 if (calc_cond) |
1636 { | |
1637 // Calculation of 1-norm of inv(*this) | |
1638 for (octave_idx_type i = 0; i < nm; i++) | |
1639 work[i] = 0.; | |
1640 | |
1641 for (octave_idx_type j = 0; j < nr; j++) | |
5164 | 1642 { |
5681 | 1643 work[j] = 1.; |
1644 | |
1645 for (octave_idx_type k = j; k >= 0; k--) | |
5164 | 1646 { |
5681 | 1647 octave_idx_type iidx = perm[k]; |
1648 | |
1649 if (work[k] != 0.) | |
5164 | 1650 { |
5681 | 1651 Complex tmp = work[k] / data(cidx(iidx+1)-1); |
1652 work[k] = tmp; | |
1653 for (octave_idx_type i = cidx(iidx); | |
1654 i < cidx(iidx+1)-1; i++) | |
1655 { | |
1656 octave_idx_type idx2 = ridx(i); | |
1657 work[idx2] = work[idx2] - tmp * data(i); | |
1658 } | |
5164 | 1659 } |
1660 } | |
5681 | 1661 double atmp = 0; |
1662 for (octave_idx_type i = 0; i < j+1; i++) | |
1663 { | |
1664 atmp += std::abs(work[i]); | |
1665 work[i] = 0.; | |
1666 } | |
1667 if (atmp > ainvnorm) | |
1668 ainvnorm = atmp; | |
5164 | 1669 } |
5681 | 1670 rcond = 1. / ainvnorm / anorm; |
5164 | 1671 } |
1672 } | |
1673 else | |
1674 { | |
5630 | 1675 OCTAVE_LOCAL_BUFFER (Complex, work, nm); |
1676 retval.resize (nc, b_nc); | |
1677 | |
1678 for (octave_idx_type j = 0; j < b_nc; j++) | |
5164 | 1679 { |
5630 | 1680 for (octave_idx_type i = 0; i < nr; i++) |
1681 work[i] = b(i,j); | |
1682 for (octave_idx_type i = nr; i < nc; i++) | |
1683 work[i] = 0.; | |
1684 | |
1685 for (octave_idx_type k = nc-1; k >= 0; k--) | |
5164 | 1686 { |
5630 | 1687 if (work[k] != 0.) |
5164 | 1688 { |
5681 | 1689 if (ridx(cidx(k+1)-1) != k || |
1690 data(cidx(k+1)-1) == 0.) | |
5164 | 1691 { |
1692 err = -2; | |
1693 goto triangular_error; | |
1694 } | |
1695 | |
5630 | 1696 Complex tmp = work[k] / data(cidx(k+1)-1); |
1697 work[k] = tmp; | |
5275 | 1698 for (octave_idx_type i = cidx(k); i < cidx(k+1)-1; i++) |
5164 | 1699 { |
5275 | 1700 octave_idx_type iidx = ridx(i); |
5630 | 1701 work[iidx] = work[iidx] - tmp * data(i); |
5164 | 1702 } |
1703 } | |
1704 } | |
5630 | 1705 |
1706 for (octave_idx_type i = 0; i < nc; i++) | |
1707 retval.xelem (i, j) = work[i]; | |
5164 | 1708 } |
1709 | |
5681 | 1710 if (calc_cond) |
1711 { | |
1712 // Calculation of 1-norm of inv(*this) | |
1713 for (octave_idx_type i = 0; i < nm; i++) | |
1714 work[i] = 0.; | |
1715 | |
1716 for (octave_idx_type j = 0; j < nr; j++) | |
5164 | 1717 { |
5681 | 1718 work[j] = 1.; |
1719 | |
1720 for (octave_idx_type k = j; k >= 0; k--) | |
5164 | 1721 { |
5681 | 1722 if (work[k] != 0.) |
5164 | 1723 { |
5681 | 1724 Complex tmp = work[k] / data(cidx(k+1)-1); |
1725 work[k] = tmp; | |
1726 for (octave_idx_type i = cidx(k); | |
1727 i < cidx(k+1)-1; i++) | |
1728 { | |
1729 octave_idx_type iidx = ridx(i); | |
1730 work[iidx] = work[iidx] - tmp * data(i); | |
1731 } | |
5164 | 1732 } |
1733 } | |
5681 | 1734 double atmp = 0; |
1735 for (octave_idx_type i = 0; i < j+1; i++) | |
1736 { | |
1737 atmp += std::abs(work[i]); | |
1738 work[i] = 0.; | |
1739 } | |
1740 if (atmp > ainvnorm) | |
1741 ainvnorm = atmp; | |
5164 | 1742 } |
5681 | 1743 rcond = 1. / ainvnorm / anorm; |
1744 } | |
1745 } | |
5164 | 1746 |
1747 triangular_error: | |
1748 if (err != 0) | |
1749 { | |
1750 if (sing_handler) | |
5681 | 1751 { |
1752 sing_handler (rcond); | |
1753 mattype.mark_as_rectangular (); | |
1754 } | |
5164 | 1755 else |
1756 (*current_liboctave_error_handler) | |
1757 ("SparseComplexMatrix::solve matrix singular to machine precision, rcond = %g", | |
1758 rcond); | |
1759 } | |
1760 | |
1761 volatile double rcond_plus_one = rcond + 1.0; | |
1762 | |
1763 if (rcond_plus_one == 1.0 || xisnan (rcond)) | |
1764 { | |
1765 err = -2; | |
1766 | |
1767 if (sing_handler) | |
5681 | 1768 { |
1769 sing_handler (rcond); | |
1770 mattype.mark_as_rectangular (); | |
1771 } | |
5164 | 1772 else |
1773 (*current_liboctave_error_handler) | |
1774 ("matrix singular to machine precision, rcond = %g", | |
1775 rcond); | |
1776 } | |
1777 } | |
1778 else | |
1779 (*current_liboctave_error_handler) ("incorrect matrix type"); | |
1780 } | |
1781 | |
1782 return retval; | |
1783 } | |
1784 | |
1785 SparseComplexMatrix | |
5785 | 1786 SparseComplexMatrix::utsolve (MatrixType &mattype, const SparseMatrix& b, |
5630 | 1787 octave_idx_type& err, double& rcond, |
5681 | 1788 solve_singularity_handler sing_handler, |
1789 bool calc_cond) const | |
5164 | 1790 { |
1791 SparseComplexMatrix retval; | |
1792 | |
5275 | 1793 octave_idx_type nr = rows (); |
1794 octave_idx_type nc = cols (); | |
5630 | 1795 octave_idx_type nm = (nc > nr ? nc : nr); |
5164 | 1796 err = 0; |
1797 | |
6924 | 1798 if (nr != b.rows ()) |
5164 | 1799 (*current_liboctave_error_handler) |
1800 ("matrix dimension mismatch solution of linear equations"); | |
6924 | 1801 else if (nr == 0 || nc == 0 || b.cols () == 0) |
1802 retval = SparseComplexMatrix (nc, b.cols ()); | |
5164 | 1803 else |
1804 { | |
1805 // Print spparms("spumoni") info if requested | |
1806 int typ = mattype.type (); | |
1807 mattype.info (); | |
1808 | |
5785 | 1809 if (typ == MatrixType::Permuted_Upper || |
1810 typ == MatrixType::Upper) | |
5164 | 1811 { |
1812 double anorm = 0.; | |
1813 double ainvnorm = 0.; | |
5681 | 1814 rcond = 1.; |
1815 | |
1816 if (calc_cond) | |
1817 { | |
1818 // Calculate the 1-norm of matrix for rcond calculation | |
1819 for (octave_idx_type j = 0; j < nc; j++) | |
1820 { | |
1821 double atmp = 0.; | |
1822 for (octave_idx_type i = cidx(j); i < cidx(j+1); i++) | |
1823 atmp += std::abs(data(i)); | |
1824 if (atmp > anorm) | |
1825 anorm = atmp; | |
1826 } | |
5164 | 1827 } |
1828 | |
5275 | 1829 octave_idx_type b_nc = b.cols (); |
5681 | 1830 octave_idx_type b_nz = b.nnz (); |
5630 | 1831 retval = SparseComplexMatrix (nc, b_nc, b_nz); |
5164 | 1832 retval.xcidx(0) = 0; |
5275 | 1833 octave_idx_type ii = 0; |
1834 octave_idx_type x_nz = b_nz; | |
5164 | 1835 |
5785 | 1836 if (typ == MatrixType::Permuted_Upper) |
5164 | 1837 { |
5322 | 1838 octave_idx_type *perm = mattype.triangular_perm (); |
5630 | 1839 OCTAVE_LOCAL_BUFFER (Complex, work, nm); |
1840 | |
1841 OCTAVE_LOCAL_BUFFER (octave_idx_type, rperm, nc); | |
1842 for (octave_idx_type i = 0; i < nc; i++) | |
5322 | 1843 rperm[perm[i]] = i; |
5164 | 1844 |
5275 | 1845 for (octave_idx_type j = 0; j < b_nc; j++) |
5164 | 1846 { |
5630 | 1847 for (octave_idx_type i = 0; i < nm; i++) |
5164 | 1848 work[i] = 0.; |
5275 | 1849 for (octave_idx_type i = b.cidx(j); i < b.cidx(j+1); i++) |
5164 | 1850 work[b.ridx(i)] = b.data(i); |
1851 | |
5630 | 1852 for (octave_idx_type k = nc-1; k >= 0; k--) |
5164 | 1853 { |
5322 | 1854 octave_idx_type kidx = perm[k]; |
1855 | |
1856 if (work[k] != 0.) | |
5164 | 1857 { |
5681 | 1858 if (ridx(cidx(kidx+1)-1) != k || |
1859 data(cidx(kidx+1)-1) == 0.) | |
5164 | 1860 { |
1861 err = -2; | |
1862 goto triangular_error; | |
1863 } | |
1864 | |
5322 | 1865 Complex tmp = work[k] / data(cidx(kidx+1)-1); |
1866 work[k] = tmp; | |
1867 for (octave_idx_type i = cidx(kidx); | |
1868 i < cidx(kidx+1)-1; i++) | |
5164 | 1869 { |
5322 | 1870 octave_idx_type iidx = ridx(i); |
1871 work[iidx] = work[iidx] - tmp * data(i); | |
5164 | 1872 } |
1873 } | |
1874 } | |
1875 | |
1876 // Count non-zeros in work vector and adjust space in | |
1877 // retval if needed | |
5275 | 1878 octave_idx_type new_nnz = 0; |
5630 | 1879 for (octave_idx_type i = 0; i < nc; i++) |
5164 | 1880 if (work[i] != 0.) |
1881 new_nnz++; | |
1882 | |
1883 if (ii + new_nnz > x_nz) | |
1884 { | |
1885 // Resize the sparse matrix | |
5275 | 1886 octave_idx_type sz = new_nnz * (b_nc - j) + x_nz; |
5164 | 1887 retval.change_capacity (sz); |
1888 x_nz = sz; | |
1889 } | |
1890 | |
5630 | 1891 for (octave_idx_type i = 0; i < nc; i++) |
5322 | 1892 if (work[rperm[i]] != 0.) |
5164 | 1893 { |
1894 retval.xridx(ii) = i; | |
5322 | 1895 retval.xdata(ii++) = work[rperm[i]]; |
5164 | 1896 } |
1897 retval.xcidx(j+1) = ii; | |
1898 } | |
1899 | |
1900 retval.maybe_compress (); | |
1901 | |
5681 | 1902 if (calc_cond) |
1903 { | |
1904 // Calculation of 1-norm of inv(*this) | |
1905 for (octave_idx_type i = 0; i < nm; i++) | |
1906 work[i] = 0.; | |
1907 | |
1908 for (octave_idx_type j = 0; j < nr; j++) | |
5164 | 1909 { |
5681 | 1910 work[j] = 1.; |
1911 | |
1912 for (octave_idx_type k = j; k >= 0; k--) | |
5164 | 1913 { |
5681 | 1914 octave_idx_type iidx = perm[k]; |
1915 | |
1916 if (work[k] != 0.) | |
5164 | 1917 { |
5681 | 1918 Complex tmp = work[k] / data(cidx(iidx+1)-1); |
1919 work[k] = tmp; | |
1920 for (octave_idx_type i = cidx(iidx); | |
1921 i < cidx(iidx+1)-1; i++) | |
1922 { | |
1923 octave_idx_type idx2 = ridx(i); | |
1924 work[idx2] = work[idx2] - tmp * data(i); | |
1925 } | |
5164 | 1926 } |
1927 } | |
5681 | 1928 double atmp = 0; |
1929 for (octave_idx_type i = 0; i < j+1; i++) | |
1930 { | |
1931 atmp += std::abs(work[i]); | |
1932 work[i] = 0.; | |
1933 } | |
1934 if (atmp > ainvnorm) | |
1935 ainvnorm = atmp; | |
5164 | 1936 } |
5681 | 1937 rcond = 1. / ainvnorm / anorm; |
5164 | 1938 } |
1939 } | |
1940 else | |
1941 { | |
5630 | 1942 OCTAVE_LOCAL_BUFFER (Complex, work, nm); |
5164 | 1943 |
5275 | 1944 for (octave_idx_type j = 0; j < b_nc; j++) |
5164 | 1945 { |
5630 | 1946 for (octave_idx_type i = 0; i < nm; i++) |
5164 | 1947 work[i] = 0.; |
5275 | 1948 for (octave_idx_type i = b.cidx(j); i < b.cidx(j+1); i++) |
5164 | 1949 work[b.ridx(i)] = b.data(i); |
1950 | |
5630 | 1951 for (octave_idx_type k = nc-1; k >= 0; k--) |
5164 | 1952 { |
1953 if (work[k] != 0.) | |
1954 { | |
5681 | 1955 if (ridx(cidx(k+1)-1) != k || |
1956 data(cidx(k+1)-1) == 0.) | |
5164 | 1957 { |
1958 err = -2; | |
1959 goto triangular_error; | |
1960 } | |
1961 | |
1962 Complex tmp = work[k] / data(cidx(k+1)-1); | |
1963 work[k] = tmp; | |
5275 | 1964 for (octave_idx_type i = cidx(k); i < cidx(k+1)-1; i++) |
5164 | 1965 { |
5275 | 1966 octave_idx_type iidx = ridx(i); |
5164 | 1967 work[iidx] = work[iidx] - tmp * data(i); |
1968 } | |
1969 } | |
1970 } | |
1971 | |
1972 // Count non-zeros in work vector and adjust space in | |
1973 // retval if needed | |
5275 | 1974 octave_idx_type new_nnz = 0; |
5630 | 1975 for (octave_idx_type i = 0; i < nc; i++) |
5164 | 1976 if (work[i] != 0.) |
1977 new_nnz++; | |
1978 | |
1979 if (ii + new_nnz > x_nz) | |
1980 { | |
1981 // Resize the sparse matrix | |
5275 | 1982 octave_idx_type sz = new_nnz * (b_nc - j) + x_nz; |
5164 | 1983 retval.change_capacity (sz); |
1984 x_nz = sz; | |
1985 } | |
1986 | |
5630 | 1987 for (octave_idx_type i = 0; i < nc; i++) |
5164 | 1988 if (work[i] != 0.) |
1989 { | |
1990 retval.xridx(ii) = i; | |
1991 retval.xdata(ii++) = work[i]; | |
1992 } | |
1993 retval.xcidx(j+1) = ii; | |
1994 } | |
1995 | |
1996 retval.maybe_compress (); | |
1997 | |
5681 | 1998 if (calc_cond) |
1999 { | |
2000 // Calculation of 1-norm of inv(*this) | |
2001 for (octave_idx_type i = 0; i < nm; i++) | |
2002 work[i] = 0.; | |
2003 | |
2004 for (octave_idx_type j = 0; j < nr; j++) | |
5164 | 2005 { |
5681 | 2006 work[j] = 1.; |
2007 | |
2008 for (octave_idx_type k = j; k >= 0; k--) | |
5164 | 2009 { |
5681 | 2010 if (work[k] != 0.) |
5164 | 2011 { |
5681 | 2012 Complex tmp = work[k] / data(cidx(k+1)-1); |
2013 work[k] = tmp; | |
2014 for (octave_idx_type i = cidx(k); | |
2015 i < cidx(k+1)-1; i++) | |
2016 { | |
2017 octave_idx_type iidx = ridx(i); | |
2018 work[iidx] = work[iidx] - tmp * data(i); | |
2019 } | |
5164 | 2020 } |
2021 } | |
5681 | 2022 double atmp = 0; |
2023 for (octave_idx_type i = 0; i < j+1; i++) | |
2024 { | |
2025 atmp += std::abs(work[i]); | |
2026 work[i] = 0.; | |
2027 } | |
2028 if (atmp > ainvnorm) | |
2029 ainvnorm = atmp; | |
5164 | 2030 } |
5681 | 2031 rcond = 1. / ainvnorm / anorm; |
2032 } | |
2033 } | |
5164 | 2034 |
2035 triangular_error: | |
2036 if (err != 0) | |
2037 { | |
2038 if (sing_handler) | |
5681 | 2039 { |
2040 sing_handler (rcond); | |
2041 mattype.mark_as_rectangular (); | |
2042 } | |
5164 | 2043 else |
2044 (*current_liboctave_error_handler) | |
2045 ("SparseComplexMatrix::solve matrix singular to machine precision, rcond = %g", | |
2046 rcond); | |
2047 } | |
2048 | |
2049 volatile double rcond_plus_one = rcond + 1.0; | |
2050 | |
2051 if (rcond_plus_one == 1.0 || xisnan (rcond)) | |
2052 { | |
2053 err = -2; | |
2054 | |
2055 if (sing_handler) | |
5681 | 2056 { |
2057 sing_handler (rcond); | |
2058 mattype.mark_as_rectangular (); | |
2059 } | |
5164 | 2060 else |
2061 (*current_liboctave_error_handler) | |
2062 ("matrix singular to machine precision, rcond = %g", | |
2063 rcond); | |
2064 } | |
2065 } | |
2066 else | |
2067 (*current_liboctave_error_handler) ("incorrect matrix type"); | |
2068 } | |
2069 return retval; | |
2070 } | |
2071 | |
2072 ComplexMatrix | |
5785 | 2073 SparseComplexMatrix::utsolve (MatrixType &mattype, const ComplexMatrix& b, |
5630 | 2074 octave_idx_type& err, double& rcond, |
5681 | 2075 solve_singularity_handler sing_handler, |
2076 bool calc_cond) const | |
5164 | 2077 { |
2078 ComplexMatrix retval; | |
2079 | |
5275 | 2080 octave_idx_type nr = rows (); |
2081 octave_idx_type nc = cols (); | |
5630 | 2082 octave_idx_type nm = (nc > nr ? nc : nr); |
5164 | 2083 err = 0; |
2084 | |
6924 | 2085 if (nr != b.rows ()) |
5164 | 2086 (*current_liboctave_error_handler) |
2087 ("matrix dimension mismatch solution of linear equations"); | |
6924 | 2088 else if (nr == 0 || nc == 0 || b.cols () == 0) |
2089 retval = ComplexMatrix (nc, b.cols (), Complex (0.0, 0.0)); | |
5164 | 2090 else |
2091 { | |
2092 // Print spparms("spumoni") info if requested | |
2093 int typ = mattype.type (); | |
2094 mattype.info (); | |
2095 | |
5785 | 2096 if (typ == MatrixType::Permuted_Upper || |
2097 typ == MatrixType::Upper) | |
5164 | 2098 { |
2099 double anorm = 0.; | |
2100 double ainvnorm = 0.; | |
5275 | 2101 octave_idx_type b_nc = b.cols (); |
5681 | 2102 rcond = 1.; |
2103 | |
2104 if (calc_cond) | |
2105 { | |
2106 // Calculate the 1-norm of matrix for rcond calculation | |
2107 for (octave_idx_type j = 0; j < nc; j++) | |
2108 { | |
2109 double atmp = 0.; | |
2110 for (octave_idx_type i = cidx(j); i < cidx(j+1); i++) | |
2111 atmp += std::abs(data(i)); | |
2112 if (atmp > anorm) | |
2113 anorm = atmp; | |
2114 } | |
5164 | 2115 } |
2116 | |
5785 | 2117 if (typ == MatrixType::Permuted_Upper) |
5164 | 2118 { |
5630 | 2119 retval.resize (nc, b_nc); |
5322 | 2120 octave_idx_type *perm = mattype.triangular_perm (); |
5630 | 2121 OCTAVE_LOCAL_BUFFER (Complex, work, nm); |
5164 | 2122 |
5275 | 2123 for (octave_idx_type j = 0; j < b_nc; j++) |
5164 | 2124 { |
5275 | 2125 for (octave_idx_type i = 0; i < nr; i++) |
5164 | 2126 work[i] = b(i,j); |
5630 | 2127 for (octave_idx_type i = nr; i < nc; i++) |
2128 work[i] = 0.; | |
2129 | |
2130 for (octave_idx_type k = nc-1; k >= 0; k--) | |
5164 | 2131 { |
5322 | 2132 octave_idx_type kidx = perm[k]; |
2133 | |
2134 if (work[k] != 0.) | |
5164 | 2135 { |
5681 | 2136 if (ridx(cidx(kidx+1)-1) != k || |
2137 data(cidx(kidx+1)-1) == 0.) | |
5164 | 2138 { |
2139 err = -2; | |
2140 goto triangular_error; | |
2141 } | |
2142 | |
5322 | 2143 Complex tmp = work[k] / data(cidx(kidx+1)-1); |
2144 work[k] = tmp; | |
2145 for (octave_idx_type i = cidx(kidx); | |
2146 i < cidx(kidx+1)-1; i++) | |
5164 | 2147 { |
5322 | 2148 octave_idx_type iidx = ridx(i); |
2149 work[iidx] = work[iidx] - tmp * data(i); | |
5164 | 2150 } |
2151 } | |
2152 } | |
2153 | |
5630 | 2154 for (octave_idx_type i = 0; i < nc; i++) |
5322 | 2155 retval (perm[i], j) = work[i]; |
5164 | 2156 } |
2157 | |
5681 | 2158 if (calc_cond) |
2159 { | |
2160 // Calculation of 1-norm of inv(*this) | |
2161 for (octave_idx_type i = 0; i < nm; i++) | |
2162 work[i] = 0.; | |
2163 | |
2164 for (octave_idx_type j = 0; j < nr; j++) | |
5164 | 2165 { |
5681 | 2166 work[j] = 1.; |
2167 | |
2168 for (octave_idx_type k = j; k >= 0; k--) | |
5164 | 2169 { |
5681 | 2170 octave_idx_type iidx = perm[k]; |
2171 | |
2172 if (work[k] != 0.) | |
5164 | 2173 { |
5681 | 2174 Complex tmp = work[k] / data(cidx(iidx+1)-1); |
2175 work[k] = tmp; | |
2176 for (octave_idx_type i = cidx(iidx); | |
2177 i < cidx(iidx+1)-1; i++) | |
2178 { | |
2179 octave_idx_type idx2 = ridx(i); | |
2180 work[idx2] = work[idx2] - tmp * data(i); | |
2181 } | |
5164 | 2182 } |
2183 } | |
5681 | 2184 double atmp = 0; |
2185 for (octave_idx_type i = 0; i < j+1; i++) | |
2186 { | |
2187 atmp += std::abs(work[i]); | |
2188 work[i] = 0.; | |
2189 } | |
2190 if (atmp > ainvnorm) | |
2191 ainvnorm = atmp; | |
5164 | 2192 } |
5681 | 2193 rcond = 1. / ainvnorm / anorm; |
5164 | 2194 } |
2195 } | |
2196 else | |
2197 { | |
5630 | 2198 OCTAVE_LOCAL_BUFFER (Complex, work, nm); |
2199 retval.resize (nc, b_nc); | |
5164 | 2200 |
5275 | 2201 for (octave_idx_type j = 0; j < b_nc; j++) |
5164 | 2202 { |
5630 | 2203 for (octave_idx_type i = 0; i < nr; i++) |
2204 work[i] = b(i,j); | |
2205 for (octave_idx_type i = nr; i < nc; i++) | |
2206 work[i] = 0.; | |
2207 | |
2208 for (octave_idx_type k = nc-1; k >= 0; k--) | |
5164 | 2209 { |
5630 | 2210 if (work[k] != 0.) |
5164 | 2211 { |
5681 | 2212 if (ridx(cidx(k+1)-1) != k || |
2213 data(cidx(k+1)-1) == 0.) | |
5164 | 2214 { |
2215 err = -2; | |
2216 goto triangular_error; | |
2217 } | |
2218 | |
5630 | 2219 Complex tmp = work[k] / data(cidx(k+1)-1); |
2220 work[k] = tmp; | |
5275 | 2221 for (octave_idx_type i = cidx(k); i < cidx(k+1)-1; i++) |
5164 | 2222 { |
5275 | 2223 octave_idx_type iidx = ridx(i); |
5630 | 2224 work[iidx] = work[iidx] - tmp * data(i); |
5164 | 2225 } |
2226 } | |
2227 } | |
5630 | 2228 |
2229 for (octave_idx_type i = 0; i < nc; i++) | |
2230 retval.xelem (i, j) = work[i]; | |
5164 | 2231 } |
2232 | |
5681 | 2233 if (calc_cond) |
2234 { | |
2235 // Calculation of 1-norm of inv(*this) | |
2236 for (octave_idx_type i = 0; i < nm; i++) | |
2237 work[i] = 0.; | |
2238 | |
2239 for (octave_idx_type j = 0; j < nr; j++) | |
5164 | 2240 { |
5681 | 2241 work[j] = 1.; |
2242 | |
2243 for (octave_idx_type k = j; k >= 0; k--) | |
5164 | 2244 { |
5681 | 2245 if (work[k] != 0.) |
5164 | 2246 { |
5681 | 2247 Complex tmp = work[k] / data(cidx(k+1)-1); |
2248 work[k] = tmp; | |
2249 for (octave_idx_type i = cidx(k); | |
2250 i < cidx(k+1)-1; i++) | |
2251 { | |
2252 octave_idx_type iidx = ridx(i); | |
2253 work[iidx] = work[iidx] - tmp * data(i); | |
2254 } | |
5164 | 2255 } |
2256 } | |
5681 | 2257 double atmp = 0; |
2258 for (octave_idx_type i = 0; i < j+1; i++) | |
2259 { | |
2260 atmp += std::abs(work[i]); | |
2261 work[i] = 0.; | |
2262 } | |
2263 if (atmp > ainvnorm) | |
2264 ainvnorm = atmp; | |
5164 | 2265 } |
5681 | 2266 rcond = 1. / ainvnorm / anorm; |
2267 } | |
2268 } | |
5164 | 2269 |
2270 triangular_error: | |
2271 if (err != 0) | |
2272 { | |
2273 if (sing_handler) | |
5681 | 2274 { |
2275 sing_handler (rcond); | |
2276 mattype.mark_as_rectangular (); | |
2277 } | |
5164 | 2278 else |
2279 (*current_liboctave_error_handler) | |
2280 ("SparseComplexMatrix::solve matrix singular to machine precision, rcond = %g", | |
2281 rcond); | |
2282 } | |
2283 | |
2284 volatile double rcond_plus_one = rcond + 1.0; | |
2285 | |
2286 if (rcond_plus_one == 1.0 || xisnan (rcond)) | |
2287 { | |
2288 err = -2; | |
2289 | |
2290 if (sing_handler) | |
5681 | 2291 { |
2292 sing_handler (rcond); | |
2293 mattype.mark_as_rectangular (); | |
2294 } | |
5164 | 2295 else |
2296 (*current_liboctave_error_handler) | |
2297 ("matrix singular to machine precision, rcond = %g", | |
2298 rcond); | |
2299 } | |
2300 } | |
2301 else | |
2302 (*current_liboctave_error_handler) ("incorrect matrix type"); | |
2303 } | |
2304 | |
2305 return retval; | |
2306 } | |
2307 | |
2308 SparseComplexMatrix | |
5785 | 2309 SparseComplexMatrix::utsolve (MatrixType &mattype, const SparseComplexMatrix& b, |
5630 | 2310 octave_idx_type& err, double& rcond, |
5681 | 2311 solve_singularity_handler sing_handler, |
2312 bool calc_cond) const | |
5164 | 2313 { |
2314 SparseComplexMatrix retval; | |
2315 | |
5275 | 2316 octave_idx_type nr = rows (); |
2317 octave_idx_type nc = cols (); | |
5630 | 2318 octave_idx_type nm = (nc > nr ? nc : nr); |
5164 | 2319 err = 0; |
2320 | |
6924 | 2321 if (nr != b.rows ()) |
5164 | 2322 (*current_liboctave_error_handler) |
2323 ("matrix dimension mismatch solution of linear equations"); | |
6924 | 2324 else if (nr == 0 || nc == 0 || b.cols () == 0) |
2325 retval = SparseComplexMatrix (nc, b.cols ()); | |
5164 | 2326 else |
2327 { | |
2328 // Print spparms("spumoni") info if requested | |
2329 int typ = mattype.type (); | |
2330 mattype.info (); | |
2331 | |
5785 | 2332 if (typ == MatrixType::Permuted_Upper || |
2333 typ == MatrixType::Upper) | |
5164 | 2334 { |
2335 double anorm = 0.; | |
2336 double ainvnorm = 0.; | |
5681 | 2337 rcond = 1.; |
2338 | |
2339 if (calc_cond) | |
2340 { | |
2341 // Calculate the 1-norm of matrix for rcond calculation | |
2342 for (octave_idx_type j = 0; j < nc; j++) | |
2343 { | |
2344 double atmp = 0.; | |
2345 for (octave_idx_type i = cidx(j); i < cidx(j+1); i++) | |
2346 atmp += std::abs(data(i)); | |
2347 if (atmp > anorm) | |
2348 anorm = atmp; | |
2349 } | |
5164 | 2350 } |
2351 | |
5275 | 2352 octave_idx_type b_nc = b.cols (); |
5681 | 2353 octave_idx_type b_nz = b.nnz (); |
5630 | 2354 retval = SparseComplexMatrix (nc, b_nc, b_nz); |
5164 | 2355 retval.xcidx(0) = 0; |
5275 | 2356 octave_idx_type ii = 0; |
2357 octave_idx_type x_nz = b_nz; | |
5164 | 2358 |
5785 | 2359 if (typ == MatrixType::Permuted_Upper) |
5164 | 2360 { |
5322 | 2361 octave_idx_type *perm = mattype.triangular_perm (); |
5630 | 2362 OCTAVE_LOCAL_BUFFER (Complex, work, nm); |
2363 | |
2364 OCTAVE_LOCAL_BUFFER (octave_idx_type, rperm, nc); | |
2365 for (octave_idx_type i = 0; i < nc; i++) | |
5322 | 2366 rperm[perm[i]] = i; |
5164 | 2367 |
5275 | 2368 for (octave_idx_type j = 0; j < b_nc; j++) |
5164 | 2369 { |
5630 | 2370 for (octave_idx_type i = 0; i < nm; i++) |
5164 | 2371 work[i] = 0.; |
5275 | 2372 for (octave_idx_type i = b.cidx(j); i < b.cidx(j+1); i++) |
5164 | 2373 work[b.ridx(i)] = b.data(i); |
2374 | |
5630 | 2375 for (octave_idx_type k = nc-1; k >= 0; k--) |
5164 | 2376 { |
5322 | 2377 octave_idx_type kidx = perm[k]; |
2378 | |
2379 if (work[k] != 0.) | |
5164 | 2380 { |
5681 | 2381 if (ridx(cidx(kidx+1)-1) != k || |
2382 data(cidx(kidx+1)-1) == 0.) | |
5164 | 2383 { |
2384 err = -2; | |
2385 goto triangular_error; | |
2386 } | |
2387 | |
5322 | 2388 Complex tmp = work[k] / data(cidx(kidx+1)-1); |
2389 work[k] = tmp; | |
2390 for (octave_idx_type i = cidx(kidx); | |
2391 i < cidx(kidx+1)-1; i++) | |
5164 | 2392 { |
5322 | 2393 octave_idx_type iidx = ridx(i); |
2394 work[iidx] = work[iidx] - tmp * data(i); | |
5164 | 2395 } |
2396 } | |
2397 } | |
2398 | |
2399 // Count non-zeros in work vector and adjust space in | |
2400 // retval if needed | |
5275 | 2401 octave_idx_type new_nnz = 0; |
5630 | 2402 for (octave_idx_type i = 0; i < nc; i++) |
5164 | 2403 if (work[i] != 0.) |
2404 new_nnz++; | |
2405 | |
2406 if (ii + new_nnz > x_nz) | |
2407 { | |
2408 // Resize the sparse matrix | |
5275 | 2409 octave_idx_type sz = new_nnz * (b_nc - j) + x_nz; |
5164 | 2410 retval.change_capacity (sz); |
2411 x_nz = sz; | |
2412 } | |
2413 | |
5630 | 2414 for (octave_idx_type i = 0; i < nc; i++) |
5322 | 2415 if (work[rperm[i]] != 0.) |
5164 | 2416 { |
2417 retval.xridx(ii) = i; | |
5322 | 2418 retval.xdata(ii++) = work[rperm[i]]; |
5164 | 2419 } |
2420 retval.xcidx(j+1) = ii; | |
2421 } | |
2422 | |
2423 retval.maybe_compress (); | |
2424 | |
5681 | 2425 if (calc_cond) |
2426 { | |
2427 // Calculation of 1-norm of inv(*this) | |
2428 for (octave_idx_type i = 0; i < nm; i++) | |
2429 work[i] = 0.; | |
2430 | |
2431 for (octave_idx_type j = 0; j < nr; j++) | |
5164 | 2432 { |
5681 | 2433 work[j] = 1.; |
2434 | |
2435 for (octave_idx_type k = j; k >= 0; k--) | |
5164 | 2436 { |
5681 | 2437 octave_idx_type iidx = perm[k]; |
2438 | |
2439 if (work[k] != 0.) | |
5164 | 2440 { |
5681 | 2441 Complex tmp = work[k] / data(cidx(iidx+1)-1); |
2442 work[k] = tmp; | |
2443 for (octave_idx_type i = cidx(iidx); | |
2444 i < cidx(iidx+1)-1; i++) | |
2445 { | |
2446 octave_idx_type idx2 = ridx(i); | |
2447 work[idx2] = work[idx2] - tmp * data(i); | |
2448 } | |
5164 | 2449 } |
2450 } | |
5681 | 2451 double atmp = 0; |
2452 for (octave_idx_type i = 0; i < j+1; i++) | |
2453 { | |
2454 atmp += std::abs(work[i]); | |
2455 work[i] = 0.; | |
2456 } | |
2457 if (atmp > ainvnorm) | |
2458 ainvnorm = atmp; | |
5164 | 2459 } |
5681 | 2460 rcond = 1. / ainvnorm / anorm; |
5164 | 2461 } |
2462 } | |
2463 else | |
2464 { | |
5630 | 2465 OCTAVE_LOCAL_BUFFER (Complex, work, nm); |
5164 | 2466 |
5275 | 2467 for (octave_idx_type j = 0; j < b_nc; j++) |
5164 | 2468 { |
5630 | 2469 for (octave_idx_type i = 0; i < nm; i++) |
5164 | 2470 work[i] = 0.; |
5275 | 2471 for (octave_idx_type i = b.cidx(j); i < b.cidx(j+1); i++) |
5164 | 2472 work[b.ridx(i)] = b.data(i); |
2473 | |
5275 | 2474 for (octave_idx_type k = nr-1; k >= 0; k--) |
5164 | 2475 { |
2476 if (work[k] != 0.) | |
2477 { | |
5681 | 2478 if (ridx(cidx(k+1)-1) != k || |
2479 data(cidx(k+1)-1) == 0.) | |
5164 | 2480 { |
2481 err = -2; | |
2482 goto triangular_error; | |
2483 } | |
2484 | |
2485 Complex tmp = work[k] / data(cidx(k+1)-1); | |
2486 work[k] = tmp; | |
5275 | 2487 for (octave_idx_type i = cidx(k); i < cidx(k+1)-1; i++) |
5164 | 2488 { |
5275 | 2489 octave_idx_type iidx = ridx(i); |
5164 | 2490 work[iidx] = work[iidx] - tmp * data(i); |
2491 } | |
2492 } | |
2493 } | |
2494 | |
2495 // Count non-zeros in work vector and adjust space in | |
2496 // retval if needed | |
5275 | 2497 octave_idx_type new_nnz = 0; |
5630 | 2498 for (octave_idx_type i = 0; i < nc; i++) |
5164 | 2499 if (work[i] != 0.) |
2500 new_nnz++; | |
2501 | |
2502 if (ii + new_nnz > x_nz) | |
2503 { | |
2504 // Resize the sparse matrix | |
5275 | 2505 octave_idx_type sz = new_nnz * (b_nc - j) + x_nz; |
5164 | 2506 retval.change_capacity (sz); |
2507 x_nz = sz; | |
2508 } | |
2509 | |
5630 | 2510 for (octave_idx_type i = 0; i < nc; i++) |
5164 | 2511 if (work[i] != 0.) |
2512 { | |
2513 retval.xridx(ii) = i; | |
2514 retval.xdata(ii++) = work[i]; | |
2515 } | |
2516 retval.xcidx(j+1) = ii; | |
2517 } | |
2518 | |
2519 retval.maybe_compress (); | |
2520 | |
5681 | 2521 if (calc_cond) |
2522 { | |
2523 // Calculation of 1-norm of inv(*this) | |
2524 for (octave_idx_type i = 0; i < nm; i++) | |
2525 work[i] = 0.; | |
2526 | |
2527 for (octave_idx_type j = 0; j < nr; j++) | |
5164 | 2528 { |
5681 | 2529 work[j] = 1.; |
2530 | |
2531 for (octave_idx_type k = j; k >= 0; k--) | |
5164 | 2532 { |
5681 | 2533 if (work[k] != 0.) |
5164 | 2534 { |
5681 | 2535 Complex tmp = work[k] / data(cidx(k+1)-1); |
2536 work[k] = tmp; | |
2537 for (octave_idx_type i = cidx(k); | |
2538 i < cidx(k+1)-1; i++) | |
2539 { | |
2540 octave_idx_type iidx = ridx(i); | |
2541 work[iidx] = work[iidx] - tmp * data(i); | |
2542 } | |
5164 | 2543 } |
2544 } | |
5681 | 2545 double atmp = 0; |
2546 for (octave_idx_type i = 0; i < j+1; i++) | |
2547 { | |
2548 atmp += std::abs(work[i]); | |
2549 work[i] = 0.; | |
2550 } | |
2551 if (atmp > ainvnorm) | |
2552 ainvnorm = atmp; | |
5164 | 2553 } |
5681 | 2554 rcond = 1. / ainvnorm / anorm; |
2555 } | |
2556 } | |
5164 | 2557 |
2558 triangular_error: | |
2559 if (err != 0) | |
2560 { | |
2561 if (sing_handler) | |
5681 | 2562 { |
2563 sing_handler (rcond); | |
2564 mattype.mark_as_rectangular (); | |
2565 } | |
5164 | 2566 else |
2567 (*current_liboctave_error_handler) | |
2568 ("SparseComplexMatrix::solve matrix singular to machine precision, rcond = %g", | |
2569 rcond); | |
2570 } | |
2571 | |
2572 volatile double rcond_plus_one = rcond + 1.0; | |
2573 | |
2574 if (rcond_plus_one == 1.0 || xisnan (rcond)) | |
2575 { | |
2576 err = -2; | |
2577 | |
2578 if (sing_handler) | |
5681 | 2579 { |
2580 sing_handler (rcond); | |
2581 mattype.mark_as_rectangular (); | |
2582 } | |
5164 | 2583 else |
2584 (*current_liboctave_error_handler) | |
2585 ("matrix singular to machine precision, rcond = %g", | |
2586 rcond); | |
2587 } | |
2588 } | |
2589 else | |
2590 (*current_liboctave_error_handler) ("incorrect matrix type"); | |
2591 } | |
2592 | |
2593 return retval; | |
2594 } | |
2595 | |
2596 ComplexMatrix | |
5785 | 2597 SparseComplexMatrix::ltsolve (MatrixType &mattype, const Matrix& b, |
5630 | 2598 octave_idx_type& err, double& rcond, |
5681 | 2599 solve_singularity_handler sing_handler, |
2600 bool calc_cond) const | |
5164 | 2601 { |
2602 ComplexMatrix retval; | |
2603 | |
5275 | 2604 octave_idx_type nr = rows (); |
2605 octave_idx_type nc = cols (); | |
5630 | 2606 octave_idx_type nm = (nc > nr ? nc : nr); |
5164 | 2607 err = 0; |
2608 | |
6924 | 2609 if (nr != b.rows ()) |
5164 | 2610 (*current_liboctave_error_handler) |
2611 ("matrix dimension mismatch solution of linear equations"); | |
6924 | 2612 else if (nr == 0 || nc == 0 || b.cols () == 0) |
2613 retval = ComplexMatrix (nc, b.cols (), Complex (0.0, 0.0)); | |
5164 | 2614 else |
2615 { | |
2616 // Print spparms("spumoni") info if requested | |
2617 int typ = mattype.type (); | |
2618 mattype.info (); | |
2619 | |
5785 | 2620 if (typ == MatrixType::Permuted_Lower || |
2621 typ == MatrixType::Lower) | |
5164 | 2622 { |
2623 double anorm = 0.; | |
2624 double ainvnorm = 0.; | |
5630 | 2625 octave_idx_type b_nc = b.cols (); |
5681 | 2626 rcond = 1.; |
2627 | |
2628 if (calc_cond) | |
2629 { | |
2630 // Calculate the 1-norm of matrix for rcond calculation | |
2631 for (octave_idx_type j = 0; j < nc; j++) | |
2632 { | |
2633 double atmp = 0.; | |
2634 for (octave_idx_type i = cidx(j); i < cidx(j+1); i++) | |
2635 atmp += std::abs(data(i)); | |
2636 if (atmp > anorm) | |
2637 anorm = atmp; | |
2638 } | |
5164 | 2639 } |
2640 | |
5785 | 2641 if (typ == MatrixType::Permuted_Lower) |
5164 | 2642 { |
5630 | 2643 retval.resize (nc, b_nc); |
2644 OCTAVE_LOCAL_BUFFER (Complex, work, nm); | |
5322 | 2645 octave_idx_type *perm = mattype.triangular_perm (); |
5164 | 2646 |
5630 | 2647 for (octave_idx_type j = 0; j < b_nc; j++) |
5164 | 2648 { |
5630 | 2649 for (octave_idx_type i = 0; i < nm; i++) |
2650 work[i] = 0.; | |
5275 | 2651 for (octave_idx_type i = 0; i < nr; i++) |
5322 | 2652 work[perm[i]] = b(i,j); |
5164 | 2653 |
5630 | 2654 for (octave_idx_type k = 0; k < nc; k++) |
5164 | 2655 { |
5322 | 2656 if (work[k] != 0.) |
5164 | 2657 { |
5322 | 2658 octave_idx_type minr = nr; |
2659 octave_idx_type mini = 0; | |
2660 | |
2661 for (octave_idx_type i = cidx(k); i < cidx(k+1); i++) | |
2662 if (perm[ridx(i)] < minr) | |
2663 { | |
2664 minr = perm[ridx(i)]; | |
2665 mini = i; | |
2666 } | |
2667 | |
5681 | 2668 if (minr != k || data (mini) == 0.) |
5164 | 2669 { |
2670 err = -2; | |
2671 goto triangular_error; | |
2672 } | |
2673 | |
5322 | 2674 Complex tmp = work[k] / data(mini); |
2675 work[k] = tmp; | |
2676 for (octave_idx_type i = cidx(k); i < cidx(k+1); i++) | |
5164 | 2677 { |
5322 | 2678 if (i == mini) |
2679 continue; | |
2680 | |
2681 octave_idx_type iidx = perm[ridx(i)]; | |
2682 work[iidx] = work[iidx] - tmp * data(i); | |
5164 | 2683 } |
2684 } | |
2685 } | |
2686 | |
5630 | 2687 for (octave_idx_type i = 0; i < nc; i++) |
5322 | 2688 retval (i, j) = work[i]; |
5164 | 2689 } |
2690 | |
5681 | 2691 if (calc_cond) |
2692 { | |
2693 // Calculation of 1-norm of inv(*this) | |
2694 for (octave_idx_type i = 0; i < nm; i++) | |
2695 work[i] = 0.; | |
2696 | |
2697 for (octave_idx_type j = 0; j < nr; j++) | |
5164 | 2698 { |
5681 | 2699 work[j] = 1.; |
2700 | |
2701 for (octave_idx_type k = 0; k < nc; k++) | |
5164 | 2702 { |
5681 | 2703 if (work[k] != 0.) |
5164 | 2704 { |
5681 | 2705 octave_idx_type minr = nr; |
2706 octave_idx_type mini = 0; | |
2707 | |
2708 for (octave_idx_type i = cidx(k); | |
2709 i < cidx(k+1); i++) | |
2710 if (perm[ridx(i)] < minr) | |
2711 { | |
2712 minr = perm[ridx(i)]; | |
2713 mini = i; | |
2714 } | |
2715 | |
2716 Complex tmp = work[k] / data(mini); | |
2717 work[k] = tmp; | |
2718 for (octave_idx_type i = cidx(k); | |
2719 i < cidx(k+1); i++) | |
2720 { | |
2721 if (i == mini) | |
2722 continue; | |
2723 | |
2724 octave_idx_type iidx = perm[ridx(i)]; | |
2725 work[iidx] = work[iidx] - tmp * data(i); | |
2726 } | |
5164 | 2727 } |
2728 } | |
5681 | 2729 |
2730 double atmp = 0; | |
2731 for (octave_idx_type i = j; i < nc; i++) | |
2732 { | |
2733 atmp += std::abs(work[i]); | |
2734 work[i] = 0.; | |
2735 } | |
2736 if (atmp > ainvnorm) | |
2737 ainvnorm = atmp; | |
5164 | 2738 } |
5681 | 2739 rcond = 1. / ainvnorm / anorm; |
5164 | 2740 } |
2741 } | |
2742 else | |
2743 { | |
5630 | 2744 OCTAVE_LOCAL_BUFFER (Complex, work, nm); |
2745 retval.resize (nc, b_nc, 0.); | |
2746 | |
2747 for (octave_idx_type j = 0; j < b_nc; j++) | |
5164 | 2748 { |
5630 | 2749 for (octave_idx_type i = 0; i < nr; i++) |
2750 work[i] = b(i,j); | |
2751 for (octave_idx_type i = nr; i < nc; i++) | |
2752 work[i] = 0.; | |
2753 for (octave_idx_type k = 0; k < nc; k++) | |
5164 | 2754 { |
5630 | 2755 if (work[k] != 0.) |
5164 | 2756 { |
5681 | 2757 if (ridx(cidx(k)) != k || |
2758 data(cidx(k)) == 0.) | |
5164 | 2759 { |
2760 err = -2; | |
2761 goto triangular_error; | |
2762 } | |
2763 | |
5630 | 2764 Complex tmp = work[k] / data(cidx(k)); |
2765 work[k] = tmp; | |
5275 | 2766 for (octave_idx_type i = cidx(k)+1; i < cidx(k+1); i++) |
5164 | 2767 { |
5275 | 2768 octave_idx_type iidx = ridx(i); |
5630 | 2769 work[iidx] = work[iidx] - tmp * data(i); |
5164 | 2770 } |
2771 } | |
2772 } | |
5630 | 2773 for (octave_idx_type i = 0; i < nc; i++) |
2774 retval.xelem (i, j) = work[i]; | |
5164 | 2775 } |
2776 | |
5681 | 2777 if (calc_cond) |
2778 { | |
2779 // Calculation of 1-norm of inv(*this) | |
2780 for (octave_idx_type i = 0; i < nm; i++) | |
2781 work[i] = 0.; | |
2782 | |
2783 for (octave_idx_type j = 0; j < nr; j++) | |
5164 | 2784 { |
5681 | 2785 work[j] = 1.; |
2786 | |
2787 for (octave_idx_type k = j; k < nc; k++) | |
5164 | 2788 { |
5681 | 2789 |
2790 if (work[k] != 0.) | |
5164 | 2791 { |
5681 | 2792 Complex tmp = work[k] / data(cidx(k)); |
2793 work[k] = tmp; | |
2794 for (octave_idx_type i = cidx(k)+1; | |
2795 i < cidx(k+1); i++) | |
2796 { | |
2797 octave_idx_type iidx = ridx(i); | |
2798 work[iidx] = work[iidx] - tmp * data(i); | |
2799 } | |
5164 | 2800 } |
2801 } | |
5681 | 2802 double atmp = 0; |
2803 for (octave_idx_type i = j; i < nc; i++) | |
2804 { | |
2805 atmp += std::abs(work[i]); | |
2806 work[i] = 0.; | |
2807 } | |
2808 if (atmp > ainvnorm) | |
2809 ainvnorm = atmp; | |
5164 | 2810 } |
5681 | 2811 rcond = 1. / ainvnorm / anorm; |
2812 } | |
2813 } | |
5164 | 2814 triangular_error: |
2815 if (err != 0) | |
2816 { | |
2817 if (sing_handler) | |
5681 | 2818 { |
2819 sing_handler (rcond); | |
2820 mattype.mark_as_rectangular (); | |
2821 } | |
5164 | 2822 else |
2823 (*current_liboctave_error_handler) | |
2824 ("SparseComplexMatrix::solve matrix singular to machine precision, rcond = %g", | |
2825 rcond); | |
2826 } | |
2827 | |
2828 volatile double rcond_plus_one = rcond + 1.0; | |
2829 | |
2830 if (rcond_plus_one == 1.0 || xisnan (rcond)) | |
2831 { | |
2832 err = -2; | |
2833 | |
2834 if (sing_handler) | |
5681 | 2835 { |
2836 sing_handler (rcond); | |
2837 mattype.mark_as_rectangular (); | |
2838 } | |
5164 | 2839 else |
2840 (*current_liboctave_error_handler) | |
2841 ("matrix singular to machine precision, rcond = %g", | |
2842 rcond); | |
2843 } | |
2844 } | |
2845 else | |
2846 (*current_liboctave_error_handler) ("incorrect matrix type"); | |
2847 } | |
2848 | |
2849 return retval; | |
2850 } | |
2851 | |
2852 SparseComplexMatrix | |
5785 | 2853 SparseComplexMatrix::ltsolve (MatrixType &mattype, const SparseMatrix& b, |
5630 | 2854 octave_idx_type& err, double& rcond, |
5681 | 2855 solve_singularity_handler sing_handler, |
2856 bool calc_cond) const | |
5164 | 2857 { |
2858 SparseComplexMatrix retval; | |
2859 | |
5275 | 2860 octave_idx_type nr = rows (); |
2861 octave_idx_type nc = cols (); | |
5630 | 2862 octave_idx_type nm = (nc > nr ? nc : nr); |
2863 | |
5164 | 2864 err = 0; |
2865 | |
6924 | 2866 if (nr != b.rows ()) |
5164 | 2867 (*current_liboctave_error_handler) |
2868 ("matrix dimension mismatch solution of linear equations"); | |
6924 | 2869 else if (nr == 0 || nc == 0 || b.cols () == 0) |
2870 retval = SparseComplexMatrix (nc, b.cols ()); | |
5164 | 2871 else |
2872 { | |
2873 // Print spparms("spumoni") info if requested | |
2874 int typ = mattype.type (); | |
2875 mattype.info (); | |
2876 | |
5785 | 2877 if (typ == MatrixType::Permuted_Lower || |
2878 typ == MatrixType::Lower) | |
5164 | 2879 { |
2880 double anorm = 0.; | |
2881 double ainvnorm = 0.; | |
5681 | 2882 rcond = 1.; |
2883 | |
2884 if (calc_cond) | |
2885 { | |
2886 // Calculate the 1-norm of matrix for rcond calculation | |
2887 for (octave_idx_type j = 0; j < nc; j++) | |
2888 { | |
2889 double atmp = 0.; | |
2890 for (octave_idx_type i = cidx(j); i < cidx(j+1); i++) | |
2891 atmp += std::abs(data(i)); | |
2892 if (atmp > anorm) | |
2893 anorm = atmp; | |
2894 } | |
5164 | 2895 } |
2896 | |
5275 | 2897 octave_idx_type b_nc = b.cols (); |
5681 | 2898 octave_idx_type b_nz = b.nnz (); |
5630 | 2899 retval = SparseComplexMatrix (nc, b_nc, b_nz); |
5164 | 2900 retval.xcidx(0) = 0; |
5275 | 2901 octave_idx_type ii = 0; |
2902 octave_idx_type x_nz = b_nz; | |
5164 | 2903 |
5785 | 2904 if (typ == MatrixType::Permuted_Lower) |
5164 | 2905 { |
5630 | 2906 OCTAVE_LOCAL_BUFFER (Complex, work, nm); |
5322 | 2907 octave_idx_type *perm = mattype.triangular_perm (); |
5164 | 2908 |
5275 | 2909 for (octave_idx_type j = 0; j < b_nc; j++) |
5164 | 2910 { |
5630 | 2911 for (octave_idx_type i = 0; i < nm; i++) |
5164 | 2912 work[i] = 0.; |
5275 | 2913 for (octave_idx_type i = b.cidx(j); i < b.cidx(j+1); i++) |
5322 | 2914 work[perm[b.ridx(i)]] = b.data(i); |
5164 | 2915 |
5630 | 2916 for (octave_idx_type k = 0; k < nc; k++) |
5164 | 2917 { |
5322 | 2918 if (work[k] != 0.) |
5164 | 2919 { |
5322 | 2920 octave_idx_type minr = nr; |
2921 octave_idx_type mini = 0; | |
2922 | |
2923 for (octave_idx_type i = cidx(k); i < cidx(k+1); i++) | |
2924 if (perm[ridx(i)] < minr) | |
2925 { | |
2926 minr = perm[ridx(i)]; | |
2927 mini = i; | |
2928 } | |
2929 | |
5681 | 2930 if (minr != k || data (mini) == 0.) |
5164 | 2931 { |
2932 err = -2; | |
2933 goto triangular_error; | |
2934 } | |
2935 | |
5322 | 2936 Complex tmp = work[k] / data(mini); |
2937 work[k] = tmp; | |
2938 for (octave_idx_type i = cidx(k); i < cidx(k+1); i++) | |
5164 | 2939 { |
5322 | 2940 if (i == mini) |
2941 continue; | |
2942 | |
2943 octave_idx_type iidx = perm[ridx(i)]; | |
2944 work[iidx] = work[iidx] - tmp * data(i); | |
5164 | 2945 } |
2946 } | |
2947 } | |
2948 | |
2949 // Count non-zeros in work vector and adjust space in | |
2950 // retval if needed | |
5275 | 2951 octave_idx_type new_nnz = 0; |
5630 | 2952 for (octave_idx_type i = 0; i < nc; i++) |
5164 | 2953 if (work[i] != 0.) |
2954 new_nnz++; | |
2955 | |
2956 if (ii + new_nnz > x_nz) | |
2957 { | |
2958 // Resize the sparse matrix | |
5275 | 2959 octave_idx_type sz = new_nnz * (b_nc - j) + x_nz; |
5164 | 2960 retval.change_capacity (sz); |
2961 x_nz = sz; | |
2962 } | |
2963 | |
5630 | 2964 for (octave_idx_type i = 0; i < nc; i++) |
5322 | 2965 if (work[i] != 0.) |
5164 | 2966 { |
2967 retval.xridx(ii) = i; | |
5322 | 2968 retval.xdata(ii++) = work[i]; |
5164 | 2969 } |
2970 retval.xcidx(j+1) = ii; | |
2971 } | |
2972 | |
2973 retval.maybe_compress (); | |
2974 | |
5681 | 2975 if (calc_cond) |
2976 { | |
2977 // Calculation of 1-norm of inv(*this) | |
2978 for (octave_idx_type i = 0; i < nm; i++) | |
2979 work[i] = 0.; | |
2980 | |
2981 for (octave_idx_type j = 0; j < nr; j++) | |
5164 | 2982 { |
5681 | 2983 work[j] = 1.; |
2984 | |
2985 for (octave_idx_type k = 0; k < nc; k++) | |
5164 | 2986 { |
5681 | 2987 if (work[k] != 0.) |
5164 | 2988 { |
5681 | 2989 octave_idx_type minr = nr; |
2990 octave_idx_type mini = 0; | |
2991 | |
2992 for (octave_idx_type i = cidx(k); | |
2993 i < cidx(k+1); i++) | |
2994 if (perm[ridx(i)] < minr) | |
2995 { | |
2996 minr = perm[ridx(i)]; | |
2997 mini = i; | |
2998 } | |
2999 | |
3000 Complex tmp = work[k] / data(mini); | |
3001 work[k] = tmp; | |
3002 for (octave_idx_type i = cidx(k); | |
3003 i < cidx(k+1); i++) | |
3004 { | |
3005 if (i == mini) | |
3006 continue; | |
3007 | |
3008 octave_idx_type iidx = perm[ridx(i)]; | |
3009 work[iidx] = work[iidx] - tmp * data(i); | |
3010 } | |
5164 | 3011 } |
3012 } | |
5681 | 3013 |
3014 double atmp = 0; | |
3015 for (octave_idx_type i = j; i < nc; i++) | |
3016 { | |
3017 atmp += std::abs(work[i]); | |
3018 work[i] = 0.; | |
3019 } | |
3020 if (atmp > ainvnorm) | |
3021 ainvnorm = atmp; | |
5164 | 3022 } |
5681 | 3023 rcond = 1. / ainvnorm / anorm; |
5164 | 3024 } |
3025 } | |
3026 else | |
3027 { | |
5630 | 3028 OCTAVE_LOCAL_BUFFER (Complex, work, nm); |
5164 | 3029 |
5275 | 3030 for (octave_idx_type j = 0; j < b_nc; j++) |
5164 | 3031 { |
5630 | 3032 for (octave_idx_type i = 0; i < nm; i++) |
5164 | 3033 work[i] = 0.; |
5275 | 3034 for (octave_idx_type i = b.cidx(j); i < b.cidx(j+1); i++) |
5164 | 3035 work[b.ridx(i)] = b.data(i); |
3036 | |
5630 | 3037 for (octave_idx_type k = 0; k < nc; k++) |
5164 | 3038 { |
3039 if (work[k] != 0.) | |
3040 { | |
5681 | 3041 if (ridx(cidx(k)) != k || |
3042 data(cidx(k)) == 0.) | |
5164 | 3043 { |
3044 err = -2; | |
3045 goto triangular_error; | |
3046 } | |
3047 | |
3048 Complex tmp = work[k] / data(cidx(k)); | |
3049 work[k] = tmp; | |
5275 | 3050 for (octave_idx_type i = cidx(k)+1; i < cidx(k+1); i++) |
5164 | 3051 { |
5275 | 3052 octave_idx_type iidx = ridx(i); |
5164 | 3053 work[iidx] = work[iidx] - tmp * data(i); |
3054 } | |
3055 } | |
3056 } | |
3057 | |
3058 // Count non-zeros in work vector and adjust space in | |
3059 // retval if needed | |
5275 | 3060 octave_idx_type new_nnz = 0; |
5630 | 3061 for (octave_idx_type i = 0; i < nc; i++) |
5164 | 3062 if (work[i] != 0.) |
3063 new_nnz++; | |
3064 | |
3065 if (ii + new_nnz > x_nz) | |
3066 { | |
3067 // Resize the sparse matrix | |
5275 | 3068 octave_idx_type sz = new_nnz * (b_nc - j) + x_nz; |
5164 | 3069 retval.change_capacity (sz); |
3070 x_nz = sz; | |
3071 } | |
3072 | |
5630 | 3073 for (octave_idx_type i = 0; i < nc; i++) |
5164 | 3074 if (work[i] != 0.) |
3075 { | |
3076 retval.xridx(ii) = i; | |
3077 retval.xdata(ii++) = work[i]; | |
3078 } | |
3079 retval.xcidx(j+1) = ii; | |
3080 } | |
3081 | |
3082 retval.maybe_compress (); | |
3083 | |
5681 | 3084 if (calc_cond) |
3085 { | |
3086 // Calculation of 1-norm of inv(*this) | |
3087 for (octave_idx_type i = 0; i < nm; i++) | |
3088 work[i] = 0.; | |
3089 | |
3090 for (octave_idx_type j = 0; j < nr; j++) | |
5164 | 3091 { |
5681 | 3092 work[j] = 1.; |
3093 | |
3094 for (octave_idx_type k = j; k < nc; k++) | |
5164 | 3095 { |
5681 | 3096 |
3097 if (work[k] != 0.) | |
5164 | 3098 { |
5681 | 3099 Complex tmp = work[k] / data(cidx(k)); |
3100 work[k] = tmp; | |
3101 for (octave_idx_type i = cidx(k)+1; | |
3102 i < cidx(k+1); i++) | |
3103 { | |
3104 octave_idx_type iidx = ridx(i); | |
3105 work[iidx] = work[iidx] - tmp * data(i); | |
3106 } | |
5164 | 3107 } |
3108 } | |
5681 | 3109 double atmp = 0; |
3110 for (octave_idx_type i = j; i < nc; i++) | |
3111 { | |
3112 atmp += std::abs(work[i]); | |
3113 work[i] = 0.; | |
3114 } | |
3115 if (atmp > ainvnorm) | |
3116 ainvnorm = atmp; | |
5164 | 3117 } |
5681 | 3118 rcond = 1. / ainvnorm / anorm; |
3119 } | |
3120 } | |
5164 | 3121 |
3122 triangular_error: | |
3123 if (err != 0) | |
3124 { | |
3125 if (sing_handler) | |
5681 | 3126 { |
3127 sing_handler (rcond); | |
3128 mattype.mark_as_rectangular (); | |
3129 } | |
5164 | 3130 else |
3131 (*current_liboctave_error_handler) | |
3132 ("SparseComplexMatrix::solve matrix singular to machine precision, rcond = %g", | |
3133 rcond); | |
3134 } | |
3135 | |
3136 volatile double rcond_plus_one = rcond + 1.0; | |
3137 | |
3138 if (rcond_plus_one == 1.0 || xisnan (rcond)) | |
3139 { | |
3140 err = -2; | |
3141 | |
3142 if (sing_handler) | |
5681 | 3143 { |
3144 sing_handler (rcond); | |
3145 mattype.mark_as_rectangular (); | |
3146 } | |
5164 | 3147 else |
3148 (*current_liboctave_error_handler) | |
3149 ("matrix singular to machine precision, rcond = %g", | |
3150 rcond); | |
3151 } | |
3152 } | |
3153 else | |
3154 (*current_liboctave_error_handler) ("incorrect matrix type"); | |
3155 } | |
3156 | |
3157 return retval; | |
3158 } | |
3159 | |
3160 ComplexMatrix | |
5785 | 3161 SparseComplexMatrix::ltsolve (MatrixType &mattype, const ComplexMatrix& b, |
5630 | 3162 octave_idx_type& err, double& rcond, |
5681 | 3163 solve_singularity_handler sing_handler, |
3164 bool calc_cond) const | |
5164 | 3165 { |
3166 ComplexMatrix retval; | |
3167 | |
5275 | 3168 octave_idx_type nr = rows (); |
3169 octave_idx_type nc = cols (); | |
5630 | 3170 octave_idx_type nm = (nc > nr ? nc : nr); |
5164 | 3171 err = 0; |
3172 | |
6924 | 3173 if (nr != b.rows ()) |
5164 | 3174 (*current_liboctave_error_handler) |
3175 ("matrix dimension mismatch solution of linear equations"); | |
6924 | 3176 else if (nr == 0 || nc == 0 || b.cols () == 0) |
3177 retval = ComplexMatrix (nc, b.cols (), Complex (0.0, 0.0)); | |
5164 | 3178 else |
3179 { | |
3180 // Print spparms("spumoni") info if requested | |
3181 int typ = mattype.type (); | |
3182 mattype.info (); | |
3183 | |
5785 | 3184 if (typ == MatrixType::Permuted_Lower || |
3185 typ == MatrixType::Lower) | |
5164 | 3186 { |
3187 double anorm = 0.; | |
3188 double ainvnorm = 0.; | |
5275 | 3189 octave_idx_type b_nc = b.cols (); |
5681 | 3190 rcond = 1.; |
3191 | |
3192 if (calc_cond) | |
3193 { | |
3194 // Calculate the 1-norm of matrix for rcond calculation | |
3195 for (octave_idx_type j = 0; j < nc; j++) | |
3196 { | |
3197 double atmp = 0.; | |
3198 for (octave_idx_type i = cidx(j); i < cidx(j+1); i++) | |
3199 atmp += std::abs(data(i)); | |
3200 if (atmp > anorm) | |
3201 anorm = atmp; | |
3202 } | |
5164 | 3203 } |
3204 | |
5785 | 3205 if (typ == MatrixType::Permuted_Lower) |
5164 | 3206 { |
5630 | 3207 retval.resize (nc, b_nc); |
3208 OCTAVE_LOCAL_BUFFER (Complex, work, nm); | |
5322 | 3209 octave_idx_type *perm = mattype.triangular_perm (); |
5164 | 3210 |
5275 | 3211 for (octave_idx_type j = 0; j < b_nc; j++) |
5164 | 3212 { |
5630 | 3213 for (octave_idx_type i = 0; i < nm; i++) |
3214 work[i] = 0.; | |
5275 | 3215 for (octave_idx_type i = 0; i < nr; i++) |
5322 | 3216 work[perm[i]] = b(i,j); |
5164 | 3217 |
5630 | 3218 for (octave_idx_type k = 0; k < nc; k++) |
5164 | 3219 { |
5322 | 3220 if (work[k] != 0.) |
5164 | 3221 { |
5322 | 3222 octave_idx_type minr = nr; |
3223 octave_idx_type mini = 0; | |
3224 | |
3225 for (octave_idx_type i = cidx(k); i < cidx(k+1); i++) | |
3226 if (perm[ridx(i)] < minr) | |
3227 { | |
3228 minr = perm[ridx(i)]; | |
3229 mini = i; | |
3230 } | |
3231 | |
5681 | 3232 if (minr != k || data (mini) == 0.) |
5164 | 3233 { |
3234 err = -2; | |
3235 goto triangular_error; | |
3236 } | |
3237 | |
5322 | 3238 Complex tmp = work[k] / data(mini); |
3239 work[k] = tmp; | |
3240 for (octave_idx_type i = cidx(k); i < cidx(k+1); i++) | |
5164 | 3241 { |
5322 | 3242 if (i == mini) |
3243 continue; | |
3244 | |
3245 octave_idx_type iidx = perm[ridx(i)]; | |
3246 work[iidx] = work[iidx] - tmp * data(i); | |
5164 | 3247 } |
3248 } | |
3249 } | |
3250 | |
5630 | 3251 for (octave_idx_type i = 0; i < nc; i++) |
5322 | 3252 retval (i, j) = work[i]; |
5164 | 3253 } |
3254 | |
5681 | 3255 if (calc_cond) |
3256 { | |
3257 // Calculation of 1-norm of inv(*this) | |
3258 for (octave_idx_type i = 0; i < nm; i++) | |
3259 work[i] = 0.; | |
3260 | |
3261 for (octave_idx_type j = 0; j < nr; j++) | |
5164 | 3262 { |
5681 | 3263 work[j] = 1.; |
3264 | |
3265 for (octave_idx_type k = 0; k < nc; k++) | |
5164 | 3266 { |
5681 | 3267 if (work[k] != 0.) |
5164 | 3268 { |
5681 | 3269 octave_idx_type minr = nr; |
3270 octave_idx_type mini = 0; | |
3271 | |
3272 for (octave_idx_type i = cidx(k); | |
3273 i < cidx(k+1); i++) | |
3274 if (perm[ridx(i)] < minr) | |
3275 { | |
3276 minr = perm[ridx(i)]; | |
3277 mini = i; | |
3278 } | |
3279 | |
3280 Complex tmp = work[k] / data(mini); | |
3281 work[k] = tmp; | |
3282 for (octave_idx_type i = cidx(k); | |
3283 i < cidx(k+1); i++) | |
3284 { | |
3285 if (i == mini) | |
3286 continue; | |
3287 | |
3288 octave_idx_type iidx = perm[ridx(i)]; | |
3289 work[iidx] = work[iidx] - tmp * data(i); | |
3290 } | |
5164 | 3291 } |
3292 } | |
5681 | 3293 |
3294 double atmp = 0; | |
3295 for (octave_idx_type i = j; i < nc; i++) | |
3296 { | |
3297 atmp += std::abs(work[i]); | |
3298 work[i] = 0.; | |
3299 } | |
3300 if (atmp > ainvnorm) | |
3301 ainvnorm = atmp; | |
5164 | 3302 } |
5681 | 3303 rcond = 1. / ainvnorm / anorm; |
5164 | 3304 } |
3305 } | |
3306 else | |
3307 { | |
5630 | 3308 OCTAVE_LOCAL_BUFFER (Complex, work, nm); |
3309 retval.resize (nc, b_nc, 0.); | |
3310 | |
5164 | 3311 |
5275 | 3312 for (octave_idx_type j = 0; j < b_nc; j++) |
5164 | 3313 { |
5630 | 3314 for (octave_idx_type i = 0; i < nr; i++) |
3315 work[i] = b(i,j); | |
3316 for (octave_idx_type i = nr; i < nc; i++) | |
3317 work[i] = 0.; | |
3318 | |
3319 for (octave_idx_type k = 0; k < nc; k++) | |
5164 | 3320 { |
5630 | 3321 if (work[k] != 0.) |
5164 | 3322 { |
5681 | 3323 if (ridx(cidx(k)) != k || |
3324 data(cidx(k)) == 0.) | |
5164 | 3325 { |
3326 err = -2; | |
3327 goto triangular_error; | |
3328 } | |
3329 | |
5630 | 3330 Complex tmp = work[k] / data(cidx(k)); |
3331 work[k] = tmp; | |
5275 | 3332 for (octave_idx_type i = cidx(k)+1; i < cidx(k+1); i++) |
5164 | 3333 { |
5275 | 3334 octave_idx_type iidx = ridx(i); |
5630 | 3335 work[iidx] = work[iidx] - tmp * data(i); |
5164 | 3336 } |
3337 } | |
3338 } | |
5630 | 3339 |
3340 for (octave_idx_type i = 0; i < nc; i++) | |
3341 retval.xelem (i, j) = work[i]; | |
5164 | 3342 } |
3343 | |
5681 | 3344 if (calc_cond) |
3345 { | |
3346 // Calculation of 1-norm of inv(*this) | |
3347 for (octave_idx_type i = 0; i < nm; i++) | |
3348 work[i] = 0.; | |
3349 | |
3350 for (octave_idx_type j = 0; j < nr; j++) | |
5164 | 3351 { |
5681 | 3352 work[j] = 1.; |
3353 | |
3354 for (octave_idx_type k = j; k < nc; k++) | |
5164 | 3355 { |
5681 | 3356 |
3357 if (work[k] != 0.) | |
5164 | 3358 { |
5681 | 3359 Complex tmp = work[k] / data(cidx(k)); |
3360 work[k] = tmp; | |
3361 for (octave_idx_type i = cidx(k)+1; | |
3362 i < cidx(k+1); i++) | |
3363 { | |
3364 octave_idx_type iidx = ridx(i); | |
3365 work[iidx] = work[iidx] - tmp * data(i); | |
3366 } | |
5164 | 3367 } |
3368 } | |
5681 | 3369 double atmp = 0; |
3370 for (octave_idx_type i = j; i < nc; i++) | |
3371 { | |
3372 atmp += std::abs(work[i]); | |
3373 work[i] = 0.; | |
3374 } | |
3375 if (atmp > ainvnorm) | |
3376 ainvnorm = atmp; | |
5164 | 3377 } |
5681 | 3378 rcond = 1. / ainvnorm / anorm; |
3379 } | |
3380 } | |
5164 | 3381 |
3382 triangular_error: | |
3383 if (err != 0) | |
3384 { | |
3385 if (sing_handler) | |
5681 | 3386 { |
3387 sing_handler (rcond); | |
3388 mattype.mark_as_rectangular (); | |
3389 } | |
5164 | 3390 else |
3391 (*current_liboctave_error_handler) | |
3392 ("SparseComplexMatrix::solve matrix singular to machine precision, rcond = %g", | |
3393 rcond); | |
3394 } | |
3395 | |
3396 volatile double rcond_plus_one = rcond + 1.0; | |
3397 | |
3398 if (rcond_plus_one == 1.0 || xisnan (rcond)) | |
3399 { | |
3400 err = -2; | |
3401 | |
3402 if (sing_handler) | |
5681 | 3403 { |
3404 sing_handler (rcond); | |
3405 mattype.mark_as_rectangular (); | |
3406 } | |
5164 | 3407 else |
3408 (*current_liboctave_error_handler) | |
3409 ("matrix singular to machine precision, rcond = %g", | |
3410 rcond); | |
3411 } | |
3412 } | |
3413 else | |
3414 (*current_liboctave_error_handler) ("incorrect matrix type"); | |
3415 } | |
3416 | |
3417 return retval; | |
3418 } | |
3419 | |
3420 SparseComplexMatrix | |
5785 | 3421 SparseComplexMatrix::ltsolve (MatrixType &mattype, const SparseComplexMatrix& b, |
5630 | 3422 octave_idx_type& err, double& rcond, |
5681 | 3423 solve_singularity_handler sing_handler, |
3424 bool calc_cond) const | |
5164 | 3425 { |
3426 SparseComplexMatrix retval; | |
3427 | |
5275 | 3428 octave_idx_type nr = rows (); |
3429 octave_idx_type nc = cols (); | |
5630 | 3430 octave_idx_type nm = (nc > nr ? nc : nr); |
5164 | 3431 err = 0; |
3432 | |
6924 | 3433 if (nr != b.rows ()) |
5164 | 3434 (*current_liboctave_error_handler) |
3435 ("matrix dimension mismatch solution of linear equations"); | |
6924 | 3436 else if (nr == 0 || nc == 0 || b.cols () == 0) |
3437 retval = SparseComplexMatrix (nc, b.cols ()); | |
5164 | 3438 else |
3439 { | |
3440 // Print spparms("spumoni") info if requested | |
3441 int typ = mattype.type (); | |
3442 mattype.info (); | |
3443 | |
5785 | 3444 if (typ == MatrixType::Permuted_Lower || |
3445 typ == MatrixType::Lower) | |
5164 | 3446 { |
3447 double anorm = 0.; | |
3448 double ainvnorm = 0.; | |
5681 | 3449 rcond = 1.; |
3450 | |
3451 if (calc_cond) | |
3452 { | |
3453 // Calculate the 1-norm of matrix for rcond calculation | |
3454 for (octave_idx_type j = 0; j < nc; j++) | |
3455 { | |
3456 double atmp = 0.; | |
3457 for (octave_idx_type i = cidx(j); i < cidx(j+1); i++) | |
3458 atmp += std::abs(data(i)); | |
3459 if (atmp > anorm) | |
3460 anorm = atmp; | |
3461 } | |
5164 | 3462 } |
3463 | |
5275 | 3464 octave_idx_type b_nc = b.cols (); |
5681 | 3465 octave_idx_type b_nz = b.nnz (); |
5630 | 3466 retval = SparseComplexMatrix (nc, b_nc, b_nz); |
5164 | 3467 retval.xcidx(0) = 0; |
5275 | 3468 octave_idx_type ii = 0; |
3469 octave_idx_type x_nz = b_nz; | |
5164 | 3470 |
5785 | 3471 if (typ == MatrixType::Permuted_Lower) |
5164 | 3472 { |
5630 | 3473 OCTAVE_LOCAL_BUFFER (Complex, work, nm); |
5322 | 3474 octave_idx_type *perm = mattype.triangular_perm (); |
5164 | 3475 |
5275 | 3476 for (octave_idx_type j = 0; j < b_nc; j++) |
5164 | 3477 { |
5630 | 3478 for (octave_idx_type i = 0; i < nm; i++) |
5164 | 3479 work[i] = 0.; |
5275 | 3480 for (octave_idx_type i = b.cidx(j); i < b.cidx(j+1); i++) |
5322 | 3481 work[perm[b.ridx(i)]] = b.data(i); |
5164 | 3482 |
5630 | 3483 for (octave_idx_type k = 0; k < nc; k++) |
5164 | 3484 { |
5322 | 3485 if (work[k] != 0.) |
5164 | 3486 { |
5322 | 3487 octave_idx_type minr = nr; |
3488 octave_idx_type mini = 0; | |
3489 | |
3490 for (octave_idx_type i = cidx(k); i < cidx(k+1); i++) | |
3491 if (perm[ridx(i)] < minr) | |
3492 { | |
3493 minr = perm[ridx(i)]; | |
3494 mini = i; | |
3495 } | |
3496 | |
5681 | 3497 if (minr != k || data (mini) == 0.) |
5164 | 3498 { |
3499 err = -2; | |
3500 goto triangular_error; | |
3501 } | |
3502 | |
5322 | 3503 Complex tmp = work[k] / data(mini); |
3504 work[k] = tmp; | |
3505 for (octave_idx_type i = cidx(k); i < cidx(k+1); i++) | |
5164 | 3506 { |
5322 | 3507 if (i == mini) |
3508 continue; | |
3509 | |
3510 octave_idx_type iidx = perm[ridx(i)]; | |
3511 work[iidx] = work[iidx] - tmp * data(i); | |
5164 | 3512 } |
3513 } | |
3514 } | |
3515 | |
3516 // Count non-zeros in work vector and adjust space in | |
3517 // retval if needed | |
5275 | 3518 octave_idx_type new_nnz = 0; |
5630 | 3519 for (octave_idx_type i = 0; i < nc; i++) |
5164 | 3520 if (work[i] != 0.) |
3521 new_nnz++; | |
3522 | |
3523 if (ii + new_nnz > x_nz) | |
3524 { | |
3525 // Resize the sparse matrix | |
5275 | 3526 octave_idx_type sz = new_nnz * (b_nc - j) + x_nz; |
5164 | 3527 retval.change_capacity (sz); |
3528 x_nz = sz; | |
3529 } | |
3530 | |
5630 | 3531 for (octave_idx_type i = 0; i < nc; i++) |
5322 | 3532 if (work[i] != 0.) |
5164 | 3533 { |
3534 retval.xridx(ii) = i; | |
5322 | 3535 retval.xdata(ii++) = work[i]; |
5164 | 3536 } |
3537 retval.xcidx(j+1) = ii; | |
3538 } | |
3539 | |
3540 retval.maybe_compress (); | |
3541 | |
5681 | 3542 if (calc_cond) |
3543 { | |
3544 // Calculation of 1-norm of inv(*this) | |
3545 for (octave_idx_type i = 0; i < nm; i++) | |
3546 work[i] = 0.; | |
3547 | |
3548 for (octave_idx_type j = 0; j < nr; j++) | |
5164 | 3549 { |
5681 | 3550 work[j] = 1.; |
3551 | |
3552 for (octave_idx_type k = 0; k < nc; k++) | |
5164 | 3553 { |
5681 | 3554 if (work[k] != 0.) |
5164 | 3555 { |
5681 | 3556 octave_idx_type minr = nr; |
3557 octave_idx_type mini = 0; | |
3558 | |
3559 for (octave_idx_type i = cidx(k); | |
3560 i < cidx(k+1); i++) | |
3561 if (perm[ridx(i)] < minr) | |
3562 { | |
3563 minr = perm[ridx(i)]; | |
3564 mini = i; | |
3565 } | |
3566 | |
3567 Complex tmp = work[k] / data(mini); | |
3568 work[k] = tmp; | |
3569 for (octave_idx_type i = cidx(k); | |
3570 i < cidx(k+1); i++) | |
3571 { | |
3572 if (i == mini) | |
3573 continue; | |
3574 | |
3575 octave_idx_type iidx = perm[ridx(i)]; | |
3576 work[iidx] = work[iidx] - tmp * data(i); | |
3577 } | |
5164 | 3578 } |
3579 } | |
5681 | 3580 |
3581 double atmp = 0; | |
3582 for (octave_idx_type i = j; i < nc; i++) | |
3583 { | |
3584 atmp += std::abs(work[i]); | |
3585 work[i] = 0.; | |
3586 } | |
3587 if (atmp > ainvnorm) | |
3588 ainvnorm = atmp; | |
5164 | 3589 } |
5681 | 3590 rcond = 1. / ainvnorm / anorm; |
5164 | 3591 } |
3592 } | |
3593 else | |
3594 { | |
5630 | 3595 OCTAVE_LOCAL_BUFFER (Complex, work, nm); |
5164 | 3596 |
5275 | 3597 for (octave_idx_type j = 0; j < b_nc; j++) |
5164 | 3598 { |
5630 | 3599 for (octave_idx_type i = 0; i < nm; i++) |
5164 | 3600 work[i] = 0.; |
5275 | 3601 for (octave_idx_type i = b.cidx(j); i < b.cidx(j+1); i++) |
5164 | 3602 work[b.ridx(i)] = b.data(i); |
3603 | |
5630 | 3604 for (octave_idx_type k = 0; k < nc; k++) |
5164 | 3605 { |
3606 if (work[k] != 0.) | |
3607 { | |
5681 | 3608 if (ridx(cidx(k)) != k || |
3609 data(cidx(k)) == 0.) | |
5164 | 3610 { |
3611 err = -2; | |
3612 goto triangular_error; | |
3613 } | |
3614 | |
3615 Complex tmp = work[k] / data(cidx(k)); | |
3616 work[k] = tmp; | |
5275 | 3617 for (octave_idx_type i = cidx(k)+1; i < cidx(k+1); i++) |
5164 | 3618 { |
5275 | 3619 octave_idx_type iidx = ridx(i); |
5164 | 3620 work[iidx] = work[iidx] - tmp * data(i); |
3621 } | |
3622 } | |
3623 } | |
3624 | |
3625 // Count non-zeros in work vector and adjust space in | |
3626 // retval if needed | |
5275 | 3627 octave_idx_type new_nnz = 0; |
5630 | 3628 for (octave_idx_type i = 0; i < nc; i++) |
5164 | 3629 if (work[i] != 0.) |
3630 new_nnz++; | |
3631 | |
3632 if (ii + new_nnz > x_nz) | |
3633 { | |
3634 // Resize the sparse matrix | |
5275 | 3635 octave_idx_type sz = new_nnz * (b_nc - j) + x_nz; |
5164 | 3636 retval.change_capacity (sz); |
3637 x_nz = sz; | |
3638 } | |
3639 | |
5630 | 3640 for (octave_idx_type i = 0; i < nc; i++) |
5164 | 3641 if (work[i] != 0.) |
3642 { | |
3643 retval.xridx(ii) = i; | |
3644 retval.xdata(ii++) = work[i]; | |
3645 } | |
3646 retval.xcidx(j+1) = ii; | |
3647 } | |
3648 | |
3649 retval.maybe_compress (); | |
3650 | |
5681 | 3651 if (calc_cond) |
3652 { | |
3653 // Calculation of 1-norm of inv(*this) | |
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 = j; k < nc; k++) | |
5164 | 3662 { |
5681 | 3663 |
3664 if (work[k] != 0.) | |
5164 | 3665 { |
5681 | 3666 Complex tmp = work[k] / data(cidx(k)); |
3667 work[k] = tmp; | |
3668 for (octave_idx_type i = cidx(k)+1; | |
3669 i < cidx(k+1); i++) | |
3670 { | |
3671 octave_idx_type iidx = ridx(i); | |
3672 work[iidx] = work[iidx] - tmp * data(i); | |
3673 } | |
5164 | 3674 } |
3675 } | |
5681 | 3676 double atmp = 0; |
3677 for (octave_idx_type i = j; i < nc; i++) | |
3678 { | |
3679 atmp += std::abs(work[i]); | |
3680 work[i] = 0.; | |
3681 } | |
3682 if (atmp > ainvnorm) | |
3683 ainvnorm = atmp; | |
5164 | 3684 } |
5681 | 3685 rcond = 1. / ainvnorm / anorm; |
3686 } | |
3687 } | |
5164 | 3688 |
3689 triangular_error: | |
3690 if (err != 0) | |
3691 { | |
3692 if (sing_handler) | |
5681 | 3693 { |
3694 sing_handler (rcond); | |
3695 mattype.mark_as_rectangular (); | |
3696 } | |
5164 | 3697 else |
3698 (*current_liboctave_error_handler) | |
3699 ("SparseComplexMatrix::solve matrix singular to machine precision, rcond = %g", | |
3700 rcond); | |
3701 } | |
3702 | |
3703 volatile double rcond_plus_one = rcond + 1.0; | |
3704 | |
3705 if (rcond_plus_one == 1.0 || xisnan (rcond)) | |
3706 { | |
3707 err = -2; | |
3708 | |
3709 if (sing_handler) | |
5681 | 3710 { |
3711 sing_handler (rcond); | |
3712 mattype.mark_as_rectangular (); | |
3713 } | |
5164 | 3714 else |
3715 (*current_liboctave_error_handler) | |
3716 ("matrix singular to machine precision, rcond = %g", | |
3717 rcond); | |
3718 } | |
3719 } | |
3720 else | |
3721 (*current_liboctave_error_handler) ("incorrect matrix type"); | |
3722 } | |
3723 | |
3724 return retval; | |
3725 } | |
3726 | |
3727 ComplexMatrix | |
5785 | 3728 SparseComplexMatrix::trisolve (MatrixType &mattype, const Matrix& b, |
5681 | 3729 octave_idx_type& err, double& rcond, |
3730 solve_singularity_handler sing_handler, | |
3731 bool calc_cond) const | |
5164 | 3732 { |
3733 ComplexMatrix retval; | |
3734 | |
5275 | 3735 octave_idx_type nr = rows (); |
3736 octave_idx_type nc = cols (); | |
5164 | 3737 err = 0; |
3738 | |
6924 | 3739 if (nr != nc || nr != b.rows ()) |
5164 | 3740 (*current_liboctave_error_handler) |
3741 ("matrix dimension mismatch solution of linear equations"); | |
6924 | 3742 else if (nr == 0 || b.cols () == 0) |
3743 retval = ComplexMatrix (nc, b.cols (), Complex (0.0, 0.0)); | |
5681 | 3744 else if (calc_cond) |
3745 (*current_liboctave_error_handler) | |
3746 ("calculation of condition number not implemented"); | |
5164 | 3747 else |
3748 { | |
3749 // Print spparms("spumoni") info if requested | |
3750 volatile int typ = mattype.type (); | |
3751 mattype.info (); | |
3752 | |
5785 | 3753 if (typ == MatrixType::Tridiagonal_Hermitian) |
5164 | 3754 { |
5322 | 3755 OCTAVE_LOCAL_BUFFER (double, D, nr); |
5164 | 3756 OCTAVE_LOCAL_BUFFER (Complex, DL, nr - 1); |
3757 | |
3758 if (mattype.is_dense ()) | |
3759 { | |
5275 | 3760 octave_idx_type ii = 0; |
3761 | |
3762 for (octave_idx_type j = 0; j < nc-1; j++) | |
5164 | 3763 { |
5322 | 3764 D[j] = std::real(data(ii++)); |
5164 | 3765 DL[j] = data(ii); |
3766 ii += 2; | |
3767 } | |
5322 | 3768 D[nc-1] = std::real(data(ii)); |
5164 | 3769 } |
3770 else | |
3771 { | |
3772 D[0] = 0.; | |
5275 | 3773 for (octave_idx_type i = 0; i < nr - 1; i++) |
5164 | 3774 { |
3775 D[i+1] = 0.; | |
3776 DL[i] = 0.; | |
3777 } | |
3778 | |
5275 | 3779 for (octave_idx_type j = 0; j < nc; j++) |
3780 for (octave_idx_type i = cidx(j); i < cidx(j+1); i++) | |
5164 | 3781 { |
3782 if (ridx(i) == j) | |
5322 | 3783 D[j] = std::real(data(i)); |
5164 | 3784 else if (ridx(i) == j + 1) |
3785 DL[j] = data(i); | |
3786 } | |
3787 } | |
3788 | |
5275 | 3789 octave_idx_type b_nc = b.cols(); |
5164 | 3790 retval = ComplexMatrix (b); |
3791 Complex *result = retval.fortran_vec (); | |
3792 | |
3793 F77_XFCN (zptsv, ZPTSV, (nr, b_nc, D, DL, result, | |
3794 b.rows(), err)); | |
3795 | |
7482
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
3796 if (err != 0) |
5164 | 3797 { |
3798 err = 0; | |
3799 mattype.mark_as_unsymmetric (); | |
5785 | 3800 typ = MatrixType::Tridiagonal; |
5164 | 3801 } |
3802 else | |
3803 rcond = 1.; | |
3804 } | |
3805 | |
5785 | 3806 if (typ == MatrixType::Tridiagonal) |
5164 | 3807 { |
3808 OCTAVE_LOCAL_BUFFER (Complex, DU, nr - 1); | |
3809 OCTAVE_LOCAL_BUFFER (Complex, D, nr); | |
3810 OCTAVE_LOCAL_BUFFER (Complex, DL, nr - 1); | |
3811 | |
3812 if (mattype.is_dense ()) | |
3813 { | |
5275 | 3814 octave_idx_type ii = 0; |
3815 | |
3816 for (octave_idx_type j = 0; j < nc-1; j++) | |
5164 | 3817 { |
3818 D[j] = data(ii++); | |
3819 DL[j] = data(ii++); | |
3820 DU[j] = data(ii++); | |
3821 } | |
3822 D[nc-1] = data(ii); | |
3823 } | |
3824 else | |
3825 { | |
3826 D[0] = 0.; | |
5275 | 3827 for (octave_idx_type i = 0; i < nr - 1; i++) |
5164 | 3828 { |
3829 D[i+1] = 0.; | |
3830 DL[i] = 0.; | |
3831 DU[i] = 0.; | |
3832 } | |
3833 | |
5275 | 3834 for (octave_idx_type j = 0; j < nc; j++) |
3835 for (octave_idx_type i = cidx(j); i < cidx(j+1); i++) | |
5164 | 3836 { |
3837 if (ridx(i) == j) | |
3838 D[j] = data(i); | |
3839 else if (ridx(i) == j + 1) | |
3840 DL[j] = data(i); | |
3841 else if (ridx(i) == j - 1) | |
5322 | 3842 DU[j-1] = data(i); |
5164 | 3843 } |
3844 } | |
3845 | |
5275 | 3846 octave_idx_type b_nc = b.cols(); |
5164 | 3847 retval = ComplexMatrix (b); |
3848 Complex *result = retval.fortran_vec (); | |
3849 | |
3850 F77_XFCN (zgtsv, ZGTSV, (nr, b_nc, DL, D, DU, result, | |
3851 b.rows(), err)); | |
3852 | |
7482
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
3853 if (err != 0) |
5164 | 3854 { |
3855 rcond = 0.; | |
3856 err = -2; | |
3857 | |
3858 if (sing_handler) | |
5681 | 3859 { |
3860 sing_handler (rcond); | |
3861 mattype.mark_as_rectangular (); | |
3862 } | |
5164 | 3863 else |
3864 (*current_liboctave_error_handler) | |
3865 ("matrix singular to machine precision"); | |
3866 | |
3867 } | |
3868 else | |
3869 rcond = 1.; | |
3870 } | |
5785 | 3871 else if (typ != MatrixType::Tridiagonal_Hermitian) |
5164 | 3872 (*current_liboctave_error_handler) ("incorrect matrix type"); |
3873 } | |
3874 | |
3875 return retval; | |
3876 } | |
3877 | |
3878 SparseComplexMatrix | |
5785 | 3879 SparseComplexMatrix::trisolve (MatrixType &mattype, const SparseMatrix& b, |
5681 | 3880 octave_idx_type& err, double& rcond, |
3881 solve_singularity_handler sing_handler, | |
3882 bool calc_cond) const | |
5164 | 3883 { |
3884 SparseComplexMatrix retval; | |
3885 | |
5275 | 3886 octave_idx_type nr = rows (); |
3887 octave_idx_type nc = cols (); | |
5164 | 3888 err = 0; |
3889 | |
6924 | 3890 if (nr != nc || nr != b.rows ()) |
5164 | 3891 (*current_liboctave_error_handler) |
3892 ("matrix dimension mismatch solution of linear equations"); | |
6924 | 3893 else if (nr == 0 || b.cols () == 0) |
3894 retval = SparseComplexMatrix (nc, b.cols ()); | |
5681 | 3895 else if (calc_cond) |
3896 (*current_liboctave_error_handler) | |
3897 ("calculation of condition number not implemented"); | |
5164 | 3898 else |
3899 { | |
3900 // Print spparms("spumoni") info if requested | |
3901 int typ = mattype.type (); | |
3902 mattype.info (); | |
3903 | |
3904 // Note can't treat symmetric case as there is no dpttrf function | |
5785 | 3905 if (typ == MatrixType::Tridiagonal || |
3906 typ == MatrixType::Tridiagonal_Hermitian) | |
5164 | 3907 { |
3908 OCTAVE_LOCAL_BUFFER (Complex, DU2, nr - 2); | |
3909 OCTAVE_LOCAL_BUFFER (Complex, DU, nr - 1); | |
3910 OCTAVE_LOCAL_BUFFER (Complex, D, nr); | |
3911 OCTAVE_LOCAL_BUFFER (Complex, DL, nr - 1); | |
5275 | 3912 Array<octave_idx_type> ipvt (nr); |
3913 octave_idx_type *pipvt = ipvt.fortran_vec (); | |
5164 | 3914 |
3915 if (mattype.is_dense ()) | |
3916 { | |
5275 | 3917 octave_idx_type ii = 0; |
3918 | |
3919 for (octave_idx_type j = 0; j < nc-1; j++) | |
5164 | 3920 { |
3921 D[j] = data(ii++); | |
3922 DL[j] = data(ii++); | |
3923 DU[j] = data(ii++); | |
3924 } | |
3925 D[nc-1] = data(ii); | |
3926 } | |
3927 else | |
3928 { | |
3929 D[0] = 0.; | |
5275 | 3930 for (octave_idx_type i = 0; i < nr - 1; i++) |
5164 | 3931 { |
3932 D[i+1] = 0.; | |
3933 DL[i] = 0.; | |
3934 DU[i] = 0.; | |
3935 } | |
3936 | |
5275 | 3937 for (octave_idx_type j = 0; j < nc; j++) |
3938 for (octave_idx_type i = cidx(j); i < cidx(j+1); i++) | |
5164 | 3939 { |
3940 if (ridx(i) == j) | |
3941 D[j] = data(i); | |
3942 else if (ridx(i) == j + 1) | |
3943 DL[j] = data(i); | |
3944 else if (ridx(i) == j - 1) | |
5322 | 3945 DU[j-1] = data(i); |
5164 | 3946 } |
3947 } | |
3948 | |
3949 F77_XFCN (zgttrf, ZGTTRF, (nr, DL, D, DU, DU2, pipvt, err)); | |
3950 | |
7482
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
3951 if (err != 0) |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
3952 { |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
3953 err = -2; |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
3954 rcond = 0.0; |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
3955 |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
3956 if (sing_handler) |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
3957 { |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
3958 sing_handler (rcond); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
3959 mattype.mark_as_rectangular (); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
3960 } |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
3961 else |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
3962 (*current_liboctave_error_handler) |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
3963 ("matrix singular to machine precision"); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
3964 |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
3965 } |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
3966 else |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
3967 { |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
3968 char job = 'N'; |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
3969 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
|
3970 octave_idx_type b_nc = b.cols (); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
3971 retval = SparseComplexMatrix (nr, b_nc, x_nz); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
3972 retval.xcidx(0) = 0; |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
3973 volatile octave_idx_type ii = 0; |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
3974 rcond = 1.0; |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
3975 |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
3976 OCTAVE_LOCAL_BUFFER (Complex, work, nr); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
3977 |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
3978 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
|
3979 { |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
3980 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
|
3981 work[i] = 0.; |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
3982 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
|
3983 work[b.ridx(i)] = b.data(i); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
3984 |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
3985 F77_XFCN (zgttrs, ZGTTRS, |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
3986 (F77_CONST_CHAR_ARG2 (&job, 1), |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
3987 nr, 1, DL, D, DU, DU2, pipvt, |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
3988 work, b.rows (), err |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
3989 F77_CHAR_ARG_LEN (1))); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
3990 |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
3991 // 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
|
3992 // space in retval if needed |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
3993 octave_idx_type new_nnz = 0; |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
3994 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
|
3995 if (work[i] != 0.) |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
3996 new_nnz++; |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
3997 |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
3998 if (ii + new_nnz > x_nz) |
5164 | 3999 { |
7482
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4000 // Resize the sparse matrix |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4001 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
|
4002 retval.change_capacity (sz); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4003 x_nz = sz; |
5164 | 4004 } |
4005 | |
7482
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4006 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
|
4007 if (work[i] != 0.) |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4008 { |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4009 retval.xridx(ii) = i; |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4010 retval.xdata(ii++) = work[i]; |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4011 } |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4012 retval.xcidx(j+1) = ii; |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4013 } |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4014 |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4015 retval.maybe_compress (); |
5164 | 4016 } |
4017 } | |
5785 | 4018 else if (typ != MatrixType::Tridiagonal_Hermitian) |
5164 | 4019 (*current_liboctave_error_handler) ("incorrect matrix type"); |
4020 } | |
4021 | |
4022 return retval; | |
4023 } | |
4024 | |
4025 ComplexMatrix | |
5785 | 4026 SparseComplexMatrix::trisolve (MatrixType &mattype, const ComplexMatrix& b, |
5275 | 4027 octave_idx_type& err, double& rcond, |
5681 | 4028 solve_singularity_handler sing_handler, |
4029 bool calc_cond) const | |
5164 | 4030 { |
4031 ComplexMatrix retval; | |
4032 | |
5275 | 4033 octave_idx_type nr = rows (); |
4034 octave_idx_type nc = cols (); | |
5164 | 4035 err = 0; |
4036 | |
6924 | 4037 if (nr != nc || nr != b.rows ()) |
5164 | 4038 (*current_liboctave_error_handler) |
4039 ("matrix dimension mismatch solution of linear equations"); | |
6924 | 4040 else if (nr == 0 || b.cols () == 0) |
4041 retval = ComplexMatrix (nc, b.cols (), Complex (0.0, 0.0)); | |
5681 | 4042 else if (calc_cond) |
4043 (*current_liboctave_error_handler) | |
4044 ("calculation of condition number not implemented"); | |
5164 | 4045 else |
4046 { | |
4047 // Print spparms("spumoni") info if requested | |
4048 volatile int typ = mattype.type (); | |
4049 mattype.info (); | |
4050 | |
5785 | 4051 if (typ == MatrixType::Tridiagonal_Hermitian) |
5164 | 4052 { |
5322 | 4053 OCTAVE_LOCAL_BUFFER (double, D, nr); |
5164 | 4054 OCTAVE_LOCAL_BUFFER (Complex, DL, nr - 1); |
4055 | |
4056 if (mattype.is_dense ()) | |
4057 { | |
5275 | 4058 octave_idx_type ii = 0; |
4059 | |
4060 for (octave_idx_type j = 0; j < nc-1; j++) | |
5164 | 4061 { |
5322 | 4062 D[j] = std::real(data(ii++)); |
5164 | 4063 DL[j] = data(ii); |
4064 ii += 2; | |
4065 } | |
5322 | 4066 D[nc-1] = std::real(data(ii)); |
5164 | 4067 } |
4068 else | |
4069 { | |
4070 D[0] = 0.; | |
5275 | 4071 for (octave_idx_type i = 0; i < nr - 1; i++) |
5164 | 4072 { |
4073 D[i+1] = 0.; | |
4074 DL[i] = 0.; | |
4075 } | |
4076 | |
5275 | 4077 for (octave_idx_type j = 0; j < nc; j++) |
4078 for (octave_idx_type i = cidx(j); i < cidx(j+1); i++) | |
5164 | 4079 { |
4080 if (ridx(i) == j) | |
5322 | 4081 D[j] = std::real (data(i)); |
5164 | 4082 else if (ridx(i) == j + 1) |
4083 DL[j] = data(i); | |
4084 } | |
4085 } | |
4086 | |
5275 | 4087 octave_idx_type b_nr = b.rows (); |
4088 octave_idx_type b_nc = b.cols(); | |
5164 | 4089 rcond = 1.; |
4090 | |
4091 retval = ComplexMatrix (b); | |
4092 Complex *result = retval.fortran_vec (); | |
4093 | |
4094 F77_XFCN (zptsv, ZPTSV, (nr, b_nc, D, DL, result, | |
4095 b_nr, err)); | |
4096 | |
7482
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4097 if (err != 0) |
5164 | 4098 { |
4099 err = 0; | |
4100 mattype.mark_as_unsymmetric (); | |
5785 | 4101 typ = MatrixType::Tridiagonal; |
5164 | 4102 } |
4103 } | |
4104 | |
5785 | 4105 if (typ == MatrixType::Tridiagonal) |
5164 | 4106 { |
4107 OCTAVE_LOCAL_BUFFER (Complex, DU, nr - 1); | |
4108 OCTAVE_LOCAL_BUFFER (Complex, D, nr); | |
4109 OCTAVE_LOCAL_BUFFER (Complex, DL, nr - 1); | |
4110 | |
4111 if (mattype.is_dense ()) | |
4112 { | |
5275 | 4113 octave_idx_type ii = 0; |
4114 | |
4115 for (octave_idx_type j = 0; j < nc-1; j++) | |
5164 | 4116 { |
4117 D[j] = data(ii++); | |
4118 DL[j] = data(ii++); | |
4119 DU[j] = data(ii++); | |
4120 } | |
4121 D[nc-1] = data(ii); | |
4122 } | |
4123 else | |
4124 { | |
4125 D[0] = 0.; | |
5275 | 4126 for (octave_idx_type i = 0; i < nr - 1; i++) |
5164 | 4127 { |
4128 D[i+1] = 0.; | |
4129 DL[i] = 0.; | |
4130 DU[i] = 0.; | |
4131 } | |
4132 | |
5275 | 4133 for (octave_idx_type j = 0; j < nc; j++) |
4134 for (octave_idx_type i = cidx(j); i < cidx(j+1); i++) | |
5164 | 4135 { |
4136 if (ridx(i) == j) | |
4137 D[j] = data(i); | |
4138 else if (ridx(i) == j + 1) | |
4139 DL[j] = data(i); | |
4140 else if (ridx(i) == j - 1) | |
5322 | 4141 DU[j-1] = data(i); |
5164 | 4142 } |
4143 } | |
4144 | |
5275 | 4145 octave_idx_type b_nr = b.rows(); |
4146 octave_idx_type b_nc = b.cols(); | |
5164 | 4147 rcond = 1.; |
4148 | |
4149 retval = ComplexMatrix (b); | |
4150 Complex *result = retval.fortran_vec (); | |
4151 | |
4152 F77_XFCN (zgtsv, ZGTSV, (nr, b_nc, DL, D, DU, result, | |
4153 b_nr, err)); | |
4154 | |
7482
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4155 if (err != 0) |
5164 | 4156 { |
4157 rcond = 0.; | |
4158 err = -2; | |
4159 | |
4160 if (sing_handler) | |
5681 | 4161 { |
4162 sing_handler (rcond); | |
4163 mattype.mark_as_rectangular (); | |
4164 } | |
5164 | 4165 else |
4166 (*current_liboctave_error_handler) | |
4167 ("matrix singular to machine precision"); | |
4168 } | |
4169 } | |
5785 | 4170 else if (typ != MatrixType::Tridiagonal_Hermitian) |
5164 | 4171 (*current_liboctave_error_handler) ("incorrect matrix type"); |
4172 } | |
4173 | |
4174 return retval; | |
4175 } | |
4176 | |
4177 SparseComplexMatrix | |
5785 | 4178 SparseComplexMatrix::trisolve (MatrixType &mattype, |
5681 | 4179 const SparseComplexMatrix& b, |
4180 octave_idx_type& err, double& rcond, | |
4181 solve_singularity_handler sing_handler, | |
4182 bool calc_cond) const | |
5164 | 4183 { |
4184 SparseComplexMatrix retval; | |
4185 | |
5275 | 4186 octave_idx_type nr = rows (); |
4187 octave_idx_type nc = cols (); | |
5164 | 4188 err = 0; |
4189 | |
6924 | 4190 if (nr != nc || nr != b.rows ()) |
5164 | 4191 (*current_liboctave_error_handler) |
4192 ("matrix dimension mismatch solution of linear equations"); | |
6924 | 4193 else if (nr == 0 || b.cols () == 0) |
4194 retval = SparseComplexMatrix (nc, b.cols ()); | |
5681 | 4195 else if (calc_cond) |
4196 (*current_liboctave_error_handler) | |
4197 ("calculation of condition number not implemented"); | |
5164 | 4198 else |
4199 { | |
4200 // Print spparms("spumoni") info if requested | |
4201 int typ = mattype.type (); | |
4202 mattype.info (); | |
4203 | |
4204 // Note can't treat symmetric case as there is no dpttrf function | |
5785 | 4205 if (typ == MatrixType::Tridiagonal || |
4206 typ == MatrixType::Tridiagonal_Hermitian) | |
5164 | 4207 { |
4208 OCTAVE_LOCAL_BUFFER (Complex, DU2, nr - 2); | |
4209 OCTAVE_LOCAL_BUFFER (Complex, DU, nr - 1); | |
4210 OCTAVE_LOCAL_BUFFER (Complex, D, nr); | |
4211 OCTAVE_LOCAL_BUFFER (Complex, DL, nr - 1); | |
5275 | 4212 Array<octave_idx_type> ipvt (nr); |
4213 octave_idx_type *pipvt = ipvt.fortran_vec (); | |
5164 | 4214 |
4215 if (mattype.is_dense ()) | |
4216 { | |
5275 | 4217 octave_idx_type ii = 0; |
4218 | |
4219 for (octave_idx_type j = 0; j < nc-1; j++) | |
5164 | 4220 { |
4221 D[j] = data(ii++); | |
4222 DL[j] = data(ii++); | |
4223 DU[j] = data(ii++); | |
4224 } | |
4225 D[nc-1] = data(ii); | |
4226 } | |
4227 else | |
4228 { | |
4229 D[0] = 0.; | |
5275 | 4230 for (octave_idx_type i = 0; i < nr - 1; i++) |
5164 | 4231 { |
4232 D[i+1] = 0.; | |
4233 DL[i] = 0.; | |
4234 DU[i] = 0.; | |
4235 } | |
4236 | |
5275 | 4237 for (octave_idx_type j = 0; j < nc; j++) |
4238 for (octave_idx_type i = cidx(j); i < cidx(j+1); i++) | |
5164 | 4239 { |
4240 if (ridx(i) == j) | |
4241 D[j] = data(i); | |
4242 else if (ridx(i) == j + 1) | |
4243 DL[j] = data(i); | |
4244 else if (ridx(i) == j - 1) | |
5322 | 4245 DU[j-1] = data(i); |
5164 | 4246 } |
4247 } | |
4248 | |
4249 F77_XFCN (zgttrf, ZGTTRF, (nr, DL, D, DU, DU2, pipvt, err)); | |
4250 | |
7482
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4251 if (err != 0) |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4252 { |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4253 rcond = 0.0; |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4254 err = -2; |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4255 |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4256 if (sing_handler) |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4257 { |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4258 sing_handler (rcond); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4259 mattype.mark_as_rectangular (); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4260 } |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4261 else |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4262 (*current_liboctave_error_handler) |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4263 ("matrix singular to machine precision"); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4264 } |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4265 else |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4266 { |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4267 rcond = 1.; |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4268 char job = 'N'; |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4269 octave_idx_type b_nr = b.rows (); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4270 octave_idx_type b_nc = b.cols (); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4271 OCTAVE_LOCAL_BUFFER (Complex, Bx, b_nr); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4272 |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4273 // 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
|
4274 // will be as many as in b |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4275 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
|
4276 volatile octave_idx_type ii = 0; |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4277 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
|
4278 |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4279 retval.xcidx(0) = 0; |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4280 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
|
4281 { |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4282 |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4283 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
|
4284 Bx[i] = b (i,j); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4285 |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4286 F77_XFCN (zgttrs, ZGTTRS, |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4287 (F77_CONST_CHAR_ARG2 (&job, 1), |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4288 nr, 1, DL, D, DU, DU2, pipvt, |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4289 Bx, b_nr, err |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4290 F77_CHAR_ARG_LEN (1))); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4291 |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4292 if (err != 0) |
5164 | 4293 { |
7482
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4294 (*current_liboctave_error_handler) |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4295 ("SparseComplexMatrix::solve solve failed"); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4296 |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4297 err = -1; |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4298 break; |
5164 | 4299 } |
4300 | |
7482
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4301 // 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
|
4302 // space in retval if needed |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4303 octave_idx_type new_nnz = 0; |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4304 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
|
4305 if (Bx[i] != 0.) |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4306 new_nnz++; |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4307 |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4308 if (ii + new_nnz > x_nz) |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4309 { |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4310 // Resize the sparse matrix |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4311 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
|
4312 retval.change_capacity (sz); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4313 x_nz = sz; |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4314 } |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4315 |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4316 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
|
4317 if (Bx[i] != 0.) |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4318 { |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4319 retval.xridx(ii) = i; |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4320 retval.xdata(ii++) = Bx[i]; |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4321 } |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4322 |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4323 retval.xcidx(j+1) = ii; |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4324 } |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4325 |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4326 retval.maybe_compress (); |
5164 | 4327 } |
4328 } | |
5785 | 4329 else if (typ != MatrixType::Tridiagonal_Hermitian) |
5164 | 4330 (*current_liboctave_error_handler) ("incorrect matrix type"); |
4331 } | |
4332 | |
4333 return retval; | |
4334 } | |
4335 | |
4336 ComplexMatrix | |
5785 | 4337 SparseComplexMatrix::bsolve (MatrixType &mattype, const Matrix& b, |
5681 | 4338 octave_idx_type& err, double& rcond, |
4339 solve_singularity_handler sing_handler, | |
4340 bool calc_cond) const | |
5164 | 4341 { |
4342 ComplexMatrix retval; | |
4343 | |
5275 | 4344 octave_idx_type nr = rows (); |
4345 octave_idx_type nc = cols (); | |
5164 | 4346 err = 0; |
4347 | |
6924 | 4348 if (nr != nc || nr != b.rows ()) |
5164 | 4349 (*current_liboctave_error_handler) |
4350 ("matrix dimension mismatch solution of linear equations"); | |
6924 | 4351 else if (nr == 0 || b.cols () == 0) |
4352 retval = ComplexMatrix (nc, b.cols (), Complex (0.0, 0.0)); | |
5164 | 4353 else |
4354 { | |
4355 // Print spparms("spumoni") info if requested | |
4356 volatile int typ = mattype.type (); | |
4357 mattype.info (); | |
4358 | |
5785 | 4359 if (typ == MatrixType::Banded_Hermitian) |
5164 | 4360 { |
5275 | 4361 octave_idx_type n_lower = mattype.nlower (); |
4362 octave_idx_type ldm = n_lower + 1; | |
5164 | 4363 ComplexMatrix m_band (ldm, nc); |
4364 Complex *tmp_data = m_band.fortran_vec (); | |
4365 | |
4366 if (! mattype.is_dense ()) | |
4367 { | |
5275 | 4368 octave_idx_type ii = 0; |
4369 | |
4370 for (octave_idx_type j = 0; j < ldm; j++) | |
4371 for (octave_idx_type i = 0; i < nc; i++) | |
5164 | 4372 tmp_data[ii++] = 0.; |
4373 } | |
4374 | |
5275 | 4375 for (octave_idx_type j = 0; j < nc; j++) |
4376 for (octave_idx_type i = cidx(j); i < cidx(j+1); i++) | |
5164 | 4377 { |
5275 | 4378 octave_idx_type ri = ridx (i); |
5164 | 4379 if (ri >= j) |
4380 m_band(ri - j, j) = data(i); | |
4381 } | |
4382 | |
4383 // Calculate the norm of the matrix, for later use. | |
5681 | 4384 double anorm; |
4385 if (calc_cond) | |
4386 anorm = m_band.abs().sum().row(0).max(); | |
5164 | 4387 |
4388 char job = 'L'; | |
4389 F77_XFCN (zpbtrf, ZPBTRF, (F77_CONST_CHAR_ARG2 (&job, 1), | |
4390 nr, n_lower, tmp_data, ldm, err | |
4391 F77_CHAR_ARG_LEN (1))); | |
4392 | |
7482
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4393 if (err != 0) |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4394 { |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4395 rcond = 0.0; |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4396 // 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
|
4397 // unsymmetric banded solver. |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4398 mattype.mark_as_unsymmetric (); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4399 typ = MatrixType::Banded; |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4400 err = 0; |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4401 } |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4402 else |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4403 { |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4404 if (calc_cond) |
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 Array<Complex> z (2 * nr); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4407 Complex *pz = z.fortran_vec (); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4408 Array<double> iz (nr); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4409 double *piz = iz.fortran_vec (); |
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 F77_XFCN (zpbcon, ZPBCON, |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4412 (F77_CONST_CHAR_ARG2 (&job, 1), |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4413 nr, n_lower, tmp_data, ldm, |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4414 anorm, rcond, pz, piz, err |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4415 F77_CHAR_ARG_LEN (1))); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4416 |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4417 if (err != 0) |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4418 err = -2; |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4419 |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4420 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
|
4421 |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4422 if (rcond_plus_one == 1.0 || xisnan (rcond)) |
5681 | 4423 { |
7482
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4424 err = -2; |
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 if (sing_handler) |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4427 { |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4428 sing_handler (rcond); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4429 mattype.mark_as_rectangular (); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4430 } |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4431 else |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4432 (*current_liboctave_error_handler) |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4433 ("matrix singular to machine precision, rcond = %g", |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4434 rcond); |
5681 | 4435 } |
7482
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 else |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4438 rcond = 1.0; |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4439 |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4440 if (err == 0) |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4441 { |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4442 retval = ComplexMatrix (b); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4443 Complex *result = retval.fortran_vec (); |
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 octave_idx_type b_nc = b.cols (); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4446 |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4447 F77_XFCN (zpbtrs, ZPBTRS, |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4448 (F77_CONST_CHAR_ARG2 (&job, 1), |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4449 nr, n_lower, b_nc, tmp_data, |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4450 ldm, result, b.rows(), err |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4451 F77_CHAR_ARG_LEN (1))); |
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 if (err != 0) |
5681 | 4454 { |
7482
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4455 (*current_liboctave_error_handler) |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4456 ("SparseMatrix::solve solve failed"); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4457 err = -1; |
5164 | 4458 } |
4459 } | |
4460 } | |
4461 } | |
4462 | |
5785 | 4463 if (typ == MatrixType::Banded) |
5164 | 4464 { |
4465 // Create the storage for the banded form of the sparse matrix | |
5275 | 4466 octave_idx_type n_upper = mattype.nupper (); |
4467 octave_idx_type n_lower = mattype.nlower (); | |
4468 octave_idx_type ldm = n_upper + 2 * n_lower + 1; | |
5164 | 4469 |
4470 ComplexMatrix m_band (ldm, nc); | |
4471 Complex *tmp_data = m_band.fortran_vec (); | |
4472 | |
4473 if (! mattype.is_dense ()) | |
4474 { | |
5275 | 4475 octave_idx_type ii = 0; |
4476 | |
4477 for (octave_idx_type j = 0; j < ldm; j++) | |
4478 for (octave_idx_type i = 0; i < nc; i++) | |
5164 | 4479 tmp_data[ii++] = 0.; |
4480 } | |
4481 | |
5275 | 4482 for (octave_idx_type j = 0; j < nc; j++) |
4483 for (octave_idx_type i = cidx(j); i < cidx(j+1); i++) | |
5164 | 4484 m_band(ridx(i) - j + n_lower + n_upper, j) = data(i); |
4485 | |
5681 | 4486 // Calculate the norm of the matrix, for later use. |
4487 double anorm; | |
4488 if (calc_cond) | |
4489 { | |
4490 for (octave_idx_type j = 0; j < nr; j++) | |
4491 { | |
4492 double atmp = 0.; | |
4493 for (octave_idx_type i = cidx(j); i < cidx(j+1); i++) | |
4494 atmp += std::abs(data(i)); | |
4495 if (atmp > anorm) | |
4496 anorm = atmp; | |
4497 } | |
4498 } | |
4499 | |
5275 | 4500 Array<octave_idx_type> ipvt (nr); |
4501 octave_idx_type *pipvt = ipvt.fortran_vec (); | |
5164 | 4502 |
5630 | 4503 F77_XFCN (zgbtrf, ZGBTRF, (nr, nc, n_lower, n_upper, tmp_data, |
5164 | 4504 ldm, pipvt, err)); |
4505 | |
7482
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4506 // 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
|
4507 // change output. |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4508 if (err != 0) |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4509 { |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4510 rcond = 0.0; |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4511 err = -2; |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4512 |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4513 if (sing_handler) |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4514 { |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4515 sing_handler (rcond); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4516 mattype.mark_as_rectangular (); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4517 } |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4518 else |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4519 (*current_liboctave_error_handler) |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4520 ("matrix singular to machine precision"); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4521 } |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4522 else |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4523 { |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4524 if (calc_cond) |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4525 { |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4526 char job = '1'; |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4527 Array<Complex> z (2 * nr); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4528 Complex *pz = z.fortran_vec (); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4529 Array<double> iz (nr); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4530 double *piz = iz.fortran_vec (); |
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 F77_XFCN (zgbcon, ZGBCON, |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4533 (F77_CONST_CHAR_ARG2 (&job, 1), |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4534 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
|
4535 anorm, rcond, pz, piz, err |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4536 F77_CHAR_ARG_LEN (1))); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4537 |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4538 if (err != 0) |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4539 err = -2; |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4540 |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4541 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
|
4542 |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4543 if (rcond_plus_one == 1.0 || xisnan (rcond)) |
5681 | 4544 { |
7482
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4545 err = -2; |
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 (sing_handler) |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4548 { |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4549 sing_handler (rcond); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4550 mattype.mark_as_rectangular (); |
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 else |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4553 (*current_liboctave_error_handler) |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4554 ("matrix singular to machine precision, rcond = %g", |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4555 rcond); |
5681 | 4556 } |
7482
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 else |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4559 rcond = 1.; |
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 if (err == 0) |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4562 { |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4563 retval = ComplexMatrix (b); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4564 Complex *result = retval.fortran_vec (); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4565 |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4566 octave_idx_type b_nc = b.cols (); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4567 |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4568 char job = 'N'; |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4569 F77_XFCN (zgbtrs, ZGBTRS, |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4570 (F77_CONST_CHAR_ARG2 (&job, 1), |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4571 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
|
4572 ldm, pipvt, result, b.rows(), err |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4573 F77_CHAR_ARG_LEN (1))); |
5164 | 4574 } |
4575 } | |
4576 } | |
5785 | 4577 else if (typ != MatrixType::Banded_Hermitian) |
5164 | 4578 (*current_liboctave_error_handler) ("incorrect matrix type"); |
4579 } | |
4580 | |
4581 return retval; | |
4582 } | |
4583 | |
4584 SparseComplexMatrix | |
5785 | 4585 SparseComplexMatrix::bsolve (MatrixType &mattype, const SparseMatrix& b, |
5275 | 4586 octave_idx_type& err, double& rcond, |
5681 | 4587 solve_singularity_handler sing_handler, |
4588 bool calc_cond) const | |
5164 | 4589 { |
4590 SparseComplexMatrix retval; | |
4591 | |
5275 | 4592 octave_idx_type nr = rows (); |
4593 octave_idx_type nc = cols (); | |
5164 | 4594 err = 0; |
4595 | |
6924 | 4596 if (nr != nc || nr != b.rows ()) |
5164 | 4597 (*current_liboctave_error_handler) |
4598 ("matrix dimension mismatch solution of linear equations"); | |
6924 | 4599 else if (nr == 0 || b.cols () == 0) |
4600 retval = SparseComplexMatrix (nc, b.cols ()); | |
5164 | 4601 else |
4602 { | |
4603 // Print spparms("spumoni") info if requested | |
4604 volatile int typ = mattype.type (); | |
4605 mattype.info (); | |
4606 | |
5785 | 4607 if (typ == MatrixType::Banded_Hermitian) |
5164 | 4608 { |
5275 | 4609 octave_idx_type n_lower = mattype.nlower (); |
4610 octave_idx_type ldm = n_lower + 1; | |
5164 | 4611 |
4612 ComplexMatrix m_band (ldm, nc); | |
4613 Complex *tmp_data = m_band.fortran_vec (); | |
4614 | |
4615 if (! mattype.is_dense ()) | |
4616 { | |
5275 | 4617 octave_idx_type ii = 0; |
4618 | |
4619 for (octave_idx_type j = 0; j < ldm; j++) | |
4620 for (octave_idx_type i = 0; i < nc; i++) | |
5164 | 4621 tmp_data[ii++] = 0.; |
4622 } | |
4623 | |
5275 | 4624 for (octave_idx_type j = 0; j < nc; j++) |
4625 for (octave_idx_type i = cidx(j); i < cidx(j+1); i++) | |
5164 | 4626 { |
5275 | 4627 octave_idx_type ri = ridx (i); |
5164 | 4628 if (ri >= j) |
4629 m_band(ri - j, j) = data(i); | |
4630 } | |
4631 | |
5681 | 4632 // Calculate the norm of the matrix, for later use. |
4633 double anorm; | |
4634 if (calc_cond) | |
4635 anorm = m_band.abs().sum().row(0).max(); | |
4636 | |
5164 | 4637 char job = 'L'; |
4638 F77_XFCN (zpbtrf, ZPBTRF, (F77_CONST_CHAR_ARG2 (&job, 1), | |
4639 nr, n_lower, tmp_data, ldm, err | |
4640 F77_CHAR_ARG_LEN (1))); | |
4641 | |
7482
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4642 if (err != 0) |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4643 { |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4644 rcond = 0.0; |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4645 mattype.mark_as_unsymmetric (); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4646 typ = MatrixType::Banded; |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4647 err = 0; |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4648 } |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4649 else |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4650 { |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4651 if (calc_cond) |
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 Array<Complex> z (2 * nr); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4654 Complex *pz = z.fortran_vec (); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4655 Array<double> iz (nr); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4656 double *piz = iz.fortran_vec (); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4657 |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4658 F77_XFCN (zpbcon, ZPBCON, |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4659 (F77_CONST_CHAR_ARG2 (&job, 1), |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4660 nr, n_lower, tmp_data, ldm, |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4661 anorm, rcond, pz, piz, err |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4662 F77_CHAR_ARG_LEN (1))); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4663 |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4664 if (err != 0) |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4665 err = -2; |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4666 |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4667 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
|
4668 |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4669 if (rcond_plus_one == 1.0 || xisnan (rcond)) |
5164 | 4670 { |
7482
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4671 err = -2; |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4672 |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4673 if (sing_handler) |
5681 | 4674 { |
7482
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4675 sing_handler (rcond); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4676 mattype.mark_as_rectangular (); |
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 else |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4679 (*current_liboctave_error_handler) |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4680 ("matrix singular to machine precision, rcond = %g", |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4681 rcond); |
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 } |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4684 else |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4685 rcond = 1.0; |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4686 |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4687 if (err == 0) |
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 octave_idx_type b_nr = b.rows (); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4690 octave_idx_type b_nc = b.cols (); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4691 OCTAVE_LOCAL_BUFFER (Complex, Bx, b_nr); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4692 |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4693 // 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
|
4694 // will be as many as in b |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4695 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
|
4696 volatile octave_idx_type ii = 0; |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4697 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
|
4698 |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4699 retval.xcidx(0) = 0; |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4700 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
|
4701 { |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4702 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
|
4703 Bx[i] = b.elem (i, j); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4704 |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4705 F77_XFCN (zpbtrs, ZPBTRS, |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4706 (F77_CONST_CHAR_ARG2 (&job, 1), |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4707 nr, n_lower, 1, tmp_data, |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4708 ldm, Bx, b_nr, err |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4709 F77_CHAR_ARG_LEN (1))); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4710 |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4711 if (err != 0) |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4712 { |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4713 (*current_liboctave_error_handler) |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4714 ("SparseComplexMatrix::solve solve failed"); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4715 err = -1; |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4716 break; |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4717 } |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4718 |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4719 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
|
4720 { |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4721 Complex tmp = Bx[i]; |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4722 if (tmp != 0.0) |
5681 | 4723 { |
7482
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4724 if (ii == x_nz) |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4725 { |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4726 // Resize the sparse matrix |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4727 octave_idx_type sz = x_nz * |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4728 (b_nc - j) / b_nc; |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4729 sz = (sz > 10 ? sz : 10) + x_nz; |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4730 retval.change_capacity (sz); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4731 x_nz = sz; |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4732 } |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4733 retval.xdata(ii) = tmp; |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4734 retval.xridx(ii++) = i; |
5681 | 4735 } |
5164 | 4736 } |
7482
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4737 retval.xcidx(j+1) = ii; |
5164 | 4738 } |
7482
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4739 |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4740 retval.maybe_compress (); |
5164 | 4741 } |
4742 } | |
4743 } | |
4744 | |
5785 | 4745 if (typ == MatrixType::Banded) |
5164 | 4746 { |
4747 // Create the storage for the banded form of the sparse matrix | |
5275 | 4748 octave_idx_type n_upper = mattype.nupper (); |
4749 octave_idx_type n_lower = mattype.nlower (); | |
4750 octave_idx_type ldm = n_upper + 2 * n_lower + 1; | |
5164 | 4751 |
4752 ComplexMatrix m_band (ldm, nc); | |
4753 Complex *tmp_data = m_band.fortran_vec (); | |
4754 | |
4755 if (! mattype.is_dense ()) | |
4756 { | |
5275 | 4757 octave_idx_type ii = 0; |
4758 | |
4759 for (octave_idx_type j = 0; j < ldm; j++) | |
4760 for (octave_idx_type i = 0; i < nc; i++) | |
5164 | 4761 tmp_data[ii++] = 0.; |
4762 } | |
4763 | |
5275 | 4764 for (octave_idx_type j = 0; j < nc; j++) |
4765 for (octave_idx_type i = cidx(j); i < cidx(j+1); i++) | |
5164 | 4766 m_band(ridx(i) - j + n_lower + n_upper, j) = data(i); |
4767 | |
5681 | 4768 // Calculate the norm of the matrix, for later use. |
4769 double anorm; | |
4770 if (calc_cond) | |
4771 { | |
4772 for (octave_idx_type j = 0; j < nr; j++) | |
4773 { | |
4774 double atmp = 0.; | |
4775 for (octave_idx_type i = cidx(j); i < cidx(j+1); i++) | |
4776 atmp += std::abs(data(i)); | |
4777 if (atmp > anorm) | |
4778 anorm = atmp; | |
4779 } | |
4780 } | |
4781 | |
5275 | 4782 Array<octave_idx_type> ipvt (nr); |
4783 octave_idx_type *pipvt = ipvt.fortran_vec (); | |
5164 | 4784 |
4785 F77_XFCN (zgbtrf, ZGBTRF, (nr, nr, n_lower, n_upper, tmp_data, | |
4786 ldm, pipvt, err)); | |
4787 | |
7482
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4788 if (err != 0) |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4789 { |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4790 rcond = 0.0; |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4791 err = -2; |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4792 |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4793 if (sing_handler) |
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 sing_handler (rcond); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4796 mattype.mark_as_rectangular (); |
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 else |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4799 (*current_liboctave_error_handler) |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4800 ("matrix singular to machine precision"); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4801 |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4802 } |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4803 else |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4804 { |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4805 if (calc_cond) |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4806 { |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4807 char job = '1'; |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4808 Array<Complex> z (2 * nr); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4809 Complex *pz = z.fortran_vec (); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4810 Array<double> iz (nr); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4811 double *piz = iz.fortran_vec (); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4812 |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4813 F77_XFCN (zgbcon, ZGBCON, |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4814 (F77_CONST_CHAR_ARG2 (&job, 1), |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4815 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
|
4816 anorm, rcond, pz, piz, err |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4817 F77_CHAR_ARG_LEN (1))); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4818 |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4819 if (err != 0) |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4820 err = -2; |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4821 |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4822 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
|
4823 |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4824 if (rcond_plus_one == 1.0 || xisnan (rcond)) |
5164 | 4825 { |
7482
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4826 err = -2; |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4827 |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4828 if (sing_handler) |
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 sing_handler (rcond); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4831 mattype.mark_as_rectangular (); |
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 else |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4834 (*current_liboctave_error_handler) |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4835 ("matrix singular to machine precision, rcond = %g", |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4836 rcond); |
5681 | 4837 } |
7482
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4838 } |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4839 else |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4840 rcond = 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 char job = 'N'; |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4845 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
|
4846 octave_idx_type b_nc = b.cols (); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4847 retval = SparseComplexMatrix (nr, b_nc, x_nz); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4848 retval.xcidx(0) = 0; |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4849 volatile octave_idx_type ii = 0; |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4850 |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4851 OCTAVE_LOCAL_BUFFER (Complex, work, nr); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4852 |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4853 for (volatile octave_idx_type j = 0; j < b_nc; j++) |
5681 | 4854 { |
7482
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4855 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
|
4856 work[i] = 0.; |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4857 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
|
4858 i < b.cidx(j+1); i++) |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4859 work[b.ridx(i)] = b.data(i); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4860 |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4861 F77_XFCN (zgbtrs, ZGBTRS, |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4862 (F77_CONST_CHAR_ARG2 (&job, 1), |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4863 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
|
4864 ldm, pipvt, work, b.rows (), err |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4865 F77_CHAR_ARG_LEN (1))); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4866 |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4867 // 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
|
4868 // space in retval if needed |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4869 octave_idx_type new_nnz = 0; |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4870 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
|
4871 if (work[i] != 0.) |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4872 new_nnz++; |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4873 |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4874 if (ii + new_nnz > x_nz) |
5164 | 4875 { |
7482
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4876 // Resize the sparse matrix |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4877 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
|
4878 retval.change_capacity (sz); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4879 x_nz = sz; |
5164 | 4880 } |
4881 | |
7482
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4882 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
|
4883 if (work[i] != 0.) |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4884 { |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4885 retval.xridx(ii) = i; |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4886 retval.xdata(ii++) = work[i]; |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4887 } |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4888 retval.xcidx(j+1) = ii; |
5164 | 4889 } |
7482
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4890 |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4891 retval.maybe_compress (); |
5164 | 4892 } |
4893 } | |
4894 } | |
5785 | 4895 else if (typ != MatrixType::Banded_Hermitian) |
5164 | 4896 (*current_liboctave_error_handler) ("incorrect matrix type"); |
4897 } | |
4898 | |
4899 return retval; | |
4900 } | |
4901 | |
4902 ComplexMatrix | |
5785 | 4903 SparseComplexMatrix::bsolve (MatrixType &mattype, const ComplexMatrix& b, |
5275 | 4904 octave_idx_type& err, double& rcond, |
5681 | 4905 solve_singularity_handler sing_handler, |
4906 bool calc_cond) const | |
5164 | 4907 { |
4908 ComplexMatrix retval; | |
4909 | |
5275 | 4910 octave_idx_type nr = rows (); |
4911 octave_idx_type nc = cols (); | |
5164 | 4912 err = 0; |
4913 | |
6924 | 4914 if (nr != nc || nr != b.rows ()) |
5164 | 4915 (*current_liboctave_error_handler) |
4916 ("matrix dimension mismatch solution of linear equations"); | |
6924 | 4917 else if (nr == 0 || b.cols () == 0) |
4918 retval = ComplexMatrix (nc, b.cols (), Complex (0.0, 0.0)); | |
5164 | 4919 else |
4920 { | |
4921 // Print spparms("spumoni") info if requested | |
4922 volatile int typ = mattype.type (); | |
4923 mattype.info (); | |
4924 | |
5785 | 4925 if (typ == MatrixType::Banded_Hermitian) |
5164 | 4926 { |
5275 | 4927 octave_idx_type n_lower = mattype.nlower (); |
4928 octave_idx_type ldm = n_lower + 1; | |
5164 | 4929 |
4930 ComplexMatrix m_band (ldm, nc); | |
4931 Complex *tmp_data = m_band.fortran_vec (); | |
4932 | |
4933 if (! mattype.is_dense ()) | |
4934 { | |
5275 | 4935 octave_idx_type ii = 0; |
4936 | |
4937 for (octave_idx_type j = 0; j < ldm; j++) | |
4938 for (octave_idx_type i = 0; i < nc; i++) | |
5164 | 4939 tmp_data[ii++] = 0.; |
4940 } | |
4941 | |
5275 | 4942 for (octave_idx_type j = 0; j < nc; j++) |
4943 for (octave_idx_type i = cidx(j); i < cidx(j+1); i++) | |
5164 | 4944 { |
5275 | 4945 octave_idx_type ri = ridx (i); |
5164 | 4946 if (ri >= j) |
4947 m_band(ri - j, j) = data(i); | |
4948 } | |
4949 | |
5681 | 4950 // Calculate the norm of the matrix, for later use. |
4951 double anorm; | |
4952 if (calc_cond) | |
4953 anorm = m_band.abs().sum().row(0).max(); | |
4954 | |
5164 | 4955 char job = 'L'; |
4956 F77_XFCN (zpbtrf, ZPBTRF, (F77_CONST_CHAR_ARG2 (&job, 1), | |
4957 nr, n_lower, tmp_data, ldm, err | |
4958 F77_CHAR_ARG_LEN (1))); | |
4959 | |
7482
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4960 if (err != 0) |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4961 { |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4962 // 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
|
4963 // unsymmetric banded solver. |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4964 rcond = 0.0; |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4965 mattype.mark_as_unsymmetric (); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4966 typ = MatrixType::Banded; |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4967 err = 0; |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4968 } |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4969 else |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4970 { |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4971 if (calc_cond) |
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 Array<Complex> z (2 * nr); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4974 Complex *pz = z.fortran_vec (); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4975 Array<double> iz (nr); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4976 double *piz = iz.fortran_vec (); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4977 |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4978 F77_XFCN (zpbcon, ZPBCON, |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4979 (F77_CONST_CHAR_ARG2 (&job, 1), |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4980 nr, n_lower, tmp_data, ldm, |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4981 anorm, rcond, pz, piz, err |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4982 F77_CHAR_ARG_LEN (1))); |
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 if (err != 0) |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4985 err = -2; |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4986 |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4987 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
|
4988 |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4989 if (rcond_plus_one == 1.0 || xisnan (rcond)) |
5681 | 4990 { |
7482
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4991 err = -2; |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4992 |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4993 if (sing_handler) |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4994 { |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4995 sing_handler (rcond); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4996 mattype.mark_as_rectangular (); |
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 else |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
4999 (*current_liboctave_error_handler) |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5000 ("matrix singular to machine precision, rcond = %g", |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5001 rcond); |
5681 | 5002 } |
7482
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5003 } |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5004 else |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5005 rcond = 1.0; |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5006 |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5007 if (err == 0) |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5008 { |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5009 octave_idx_type b_nr = b.rows (); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5010 octave_idx_type b_nc = b.cols (); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5011 retval = ComplexMatrix (b); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5012 Complex *result = retval.fortran_vec (); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5013 |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5014 F77_XFCN (zpbtrs, ZPBTRS, |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5015 (F77_CONST_CHAR_ARG2 (&job, 1), |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5016 nr, n_lower, b_nc, tmp_data, |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5017 ldm, result, b_nr, err |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5018 F77_CHAR_ARG_LEN (1))); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5019 |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5020 if (err != 0) |
5681 | 5021 { |
7482
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5022 (*current_liboctave_error_handler) |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5023 ("SparseComplexMatrix::solve solve failed"); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5024 err = -1; |
5164 | 5025 } |
5026 } | |
5027 } | |
5028 } | |
5029 | |
5785 | 5030 if (typ == MatrixType::Banded) |
5164 | 5031 { |
5032 // Create the storage for the banded form of the sparse matrix | |
5275 | 5033 octave_idx_type n_upper = mattype.nupper (); |
5034 octave_idx_type n_lower = mattype.nlower (); | |
5035 octave_idx_type ldm = n_upper + 2 * n_lower + 1; | |
5164 | 5036 |
5037 ComplexMatrix m_band (ldm, nc); | |
5038 Complex *tmp_data = m_band.fortran_vec (); | |
5039 | |
5040 if (! mattype.is_dense ()) | |
5041 { | |
5275 | 5042 octave_idx_type ii = 0; |
5043 | |
5044 for (octave_idx_type j = 0; j < ldm; j++) | |
5045 for (octave_idx_type i = 0; i < nc; i++) | |
5164 | 5046 tmp_data[ii++] = 0.; |
5047 } | |
5048 | |
5275 | 5049 for (octave_idx_type j = 0; j < nc; j++) |
5050 for (octave_idx_type i = cidx(j); i < cidx(j+1); i++) | |
5164 | 5051 m_band(ridx(i) - j + n_lower + n_upper, j) = data(i); |
5052 | |
5681 | 5053 // Calculate the norm of the matrix, for later use. |
5054 double anorm; | |
5055 if (calc_cond) | |
5056 { | |
5057 for (octave_idx_type j = 0; j < nr; j++) | |
5058 { | |
5059 double atmp = 0.; | |
5060 for (octave_idx_type i = cidx(j); i < cidx(j+1); i++) | |
5061 atmp += std::abs(data(i)); | |
5062 if (atmp > anorm) | |
5063 anorm = atmp; | |
5064 } | |
5065 } | |
5066 | |
5275 | 5067 Array<octave_idx_type> ipvt (nr); |
5068 octave_idx_type *pipvt = ipvt.fortran_vec (); | |
5164 | 5069 |
5070 F77_XFCN (zgbtrf, ZGBTRF, (nr, nr, n_lower, n_upper, tmp_data, | |
5071 ldm, pipvt, err)); | |
5072 | |
7482
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5073 if (err != 0) |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5074 { |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5075 err = -2; |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5076 rcond = 0.0; |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5077 |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5078 if (sing_handler) |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5079 { |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5080 sing_handler (rcond); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5081 mattype.mark_as_rectangular (); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5082 } |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5083 else |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5084 (*current_liboctave_error_handler) |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5085 ("matrix singular to machine precision"); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5086 } |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5087 else |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5088 { |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5089 if (calc_cond) |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5090 { |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5091 char job = '1'; |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5092 Array<Complex> z (2 * nr); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5093 Complex *pz = z.fortran_vec (); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5094 Array<double> iz (nr); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5095 double *piz = iz.fortran_vec (); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5096 |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5097 F77_XFCN (zgbcon, ZGBCON, |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5098 (F77_CONST_CHAR_ARG2 (&job, 1), |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5099 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
|
5100 anorm, rcond, pz, piz, err |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5101 F77_CHAR_ARG_LEN (1))); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5102 |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5103 if (err != 0) |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5104 err = -2; |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5105 |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5106 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
|
5107 |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5108 if (rcond_plus_one == 1.0 || xisnan (rcond)) |
5681 | 5109 { |
7482
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5110 err = -2; |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5111 |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5112 if (sing_handler) |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5113 { |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5114 sing_handler (rcond); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5115 mattype.mark_as_rectangular (); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5116 } |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5117 else |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5118 (*current_liboctave_error_handler) |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5119 ("matrix singular to machine precision, rcond = %g", |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5120 rcond); |
5681 | 5121 } |
7482
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5122 } |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5123 else |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5124 rcond = 1.; |
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 if (err == 0) |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5127 { |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5128 char job = 'N'; |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5129 octave_idx_type b_nc = b.cols (); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5130 retval = ComplexMatrix (b); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5131 Complex *result = retval.fortran_vec (); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5132 |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5133 F77_XFCN (zgbtrs, ZGBTRS, |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5134 (F77_CONST_CHAR_ARG2 (&job, 1), |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5135 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
|
5136 ldm, pipvt, result, b.rows (), err |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5137 F77_CHAR_ARG_LEN (1))); |
5164 | 5138 } |
5139 } | |
5140 } | |
5785 | 5141 else if (typ != MatrixType::Banded_Hermitian) |
5164 | 5142 (*current_liboctave_error_handler) ("incorrect matrix type"); |
5143 } | |
5144 | |
5145 return retval; | |
5146 } | |
5147 | |
5148 SparseComplexMatrix | |
5785 | 5149 SparseComplexMatrix::bsolve (MatrixType &mattype, const SparseComplexMatrix& b, |
5681 | 5150 octave_idx_type& err, double& rcond, |
5151 solve_singularity_handler sing_handler, | |
5152 bool calc_cond) const | |
5164 | 5153 { |
5154 SparseComplexMatrix retval; | |
5155 | |
5275 | 5156 octave_idx_type nr = rows (); |
5157 octave_idx_type nc = cols (); | |
5164 | 5158 err = 0; |
5159 | |
6924 | 5160 if (nr != nc || nr != b.rows ()) |
5164 | 5161 (*current_liboctave_error_handler) |
5162 ("matrix dimension mismatch solution of linear equations"); | |
6924 | 5163 else if (nr == 0 || b.cols () == 0) |
5164 retval = SparseComplexMatrix (nc, b.cols ()); | |
5164 | 5165 else |
5166 { | |
5167 // Print spparms("spumoni") info if requested | |
5168 volatile int typ = mattype.type (); | |
5169 mattype.info (); | |
5170 | |
5785 | 5171 if (typ == MatrixType::Banded_Hermitian) |
5164 | 5172 { |
5275 | 5173 octave_idx_type n_lower = mattype.nlower (); |
5174 octave_idx_type ldm = n_lower + 1; | |
5164 | 5175 |
5176 ComplexMatrix m_band (ldm, nc); | |
5177 Complex *tmp_data = m_band.fortran_vec (); | |
5178 | |
5179 if (! mattype.is_dense ()) | |
5180 { | |
5275 | 5181 octave_idx_type ii = 0; |
5182 | |
5183 for (octave_idx_type j = 0; j < ldm; j++) | |
5184 for (octave_idx_type i = 0; i < nc; i++) | |
5164 | 5185 tmp_data[ii++] = 0.; |
5186 } | |
5187 | |
5275 | 5188 for (octave_idx_type j = 0; j < nc; j++) |
5189 for (octave_idx_type i = cidx(j); i < cidx(j+1); i++) | |
5164 | 5190 { |
5275 | 5191 octave_idx_type ri = ridx (i); |
5164 | 5192 if (ri >= j) |
5193 m_band(ri - j, j) = data(i); | |
5194 } | |
5195 | |
5681 | 5196 // Calculate the norm of the matrix, for later use. |
5197 double anorm; | |
5198 if (calc_cond) | |
5199 anorm = m_band.abs().sum().row(0).max(); | |
5200 | |
5164 | 5201 char job = 'L'; |
5202 F77_XFCN (zpbtrf, ZPBTRF, (F77_CONST_CHAR_ARG2 (&job, 1), | |
5203 nr, n_lower, tmp_data, ldm, err | |
5204 F77_CHAR_ARG_LEN (1))); | |
5205 | |
7482
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5206 if (err != 0) |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5207 { |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5208 // 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
|
5209 // unsymmetric banded solver. |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5210 mattype.mark_as_unsymmetric (); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5211 typ = MatrixType::Banded; |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5212 |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5213 rcond = 0.0; |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5214 err = 0; |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5215 } |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5216 else |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5217 { |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5218 if (calc_cond) |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5219 { |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5220 Array<Complex> z (2 * nr); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5221 Complex *pz = z.fortran_vec (); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5222 Array<double> iz (nr); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5223 double *piz = iz.fortran_vec (); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5224 |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5225 F77_XFCN (zpbcon, ZPBCON, |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5226 (F77_CONST_CHAR_ARG2 (&job, 1), |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5227 nr, n_lower, tmp_data, ldm, |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5228 anorm, rcond, pz, piz, err |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5229 F77_CHAR_ARG_LEN (1))); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5230 |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5231 if (err != 0) |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5232 err = -2; |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5233 |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5234 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
|
5235 |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5236 if (rcond_plus_one == 1.0 || xisnan (rcond)) |
5681 | 5237 { |
7482
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5238 err = -2; |
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) |
5164 | 5241 { |
7482
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 (); |
5681 | 5244 } |
7482
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, rcond = %g", |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5248 rcond); |
5164 | 5249 } |
5250 } | |
7482
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5251 else |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5252 rcond = 1.0; |
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 if (err == 0) |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5255 { |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5256 octave_idx_type b_nr = b.rows (); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5257 octave_idx_type b_nc = b.cols (); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5258 OCTAVE_LOCAL_BUFFER (Complex, Bx, b_nr); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5259 |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5260 // 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
|
5261 // will be as many as in b |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5262 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
|
5263 volatile octave_idx_type ii = 0; |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5264 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
|
5265 |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5266 retval.xcidx(0) = 0; |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5267 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
|
5268 { |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5269 |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5270 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
|
5271 Bx[i] = b (i,j); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5272 |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5273 F77_XFCN (zpbtrs, ZPBTRS, |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5274 (F77_CONST_CHAR_ARG2 (&job, 1), |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5275 nr, n_lower, 1, tmp_data, |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5276 ldm, Bx, b_nr, err |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5277 F77_CHAR_ARG_LEN (1))); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5278 |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5279 if (err != 0) |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5280 { |
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 ("SparseMatrix::solve solve failed"); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5283 err = -1; |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5284 break; |
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 |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5287 // 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
|
5288 // space in retval if needed |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5289 octave_idx_type new_nnz = 0; |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5290 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
|
5291 if (Bx[i] != 0.) |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5292 new_nnz++; |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5293 |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5294 if (ii + new_nnz > x_nz) |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5295 { |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5296 // Resize the sparse matrix |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5297 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
|
5298 retval.change_capacity (sz); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5299 x_nz = sz; |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5300 } |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5301 |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5302 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
|
5303 if (Bx[i] != 0.) |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5304 { |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5305 retval.xridx(ii) = i; |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5306 retval.xdata(ii++) = Bx[i]; |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5307 } |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5308 |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5309 retval.xcidx(j+1) = ii; |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5310 } |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5311 |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5312 retval.maybe_compress (); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5313 } |
5164 | 5314 } |
5315 } | |
5316 | |
5785 | 5317 if (typ == MatrixType::Banded) |
5164 | 5318 { |
5319 // Create the storage for the banded form of the sparse matrix | |
5275 | 5320 octave_idx_type n_upper = mattype.nupper (); |
5321 octave_idx_type n_lower = mattype.nlower (); | |
5322 octave_idx_type ldm = n_upper + 2 * n_lower + 1; | |
5164 | 5323 |
5324 ComplexMatrix m_band (ldm, nc); | |
5325 Complex *tmp_data = m_band.fortran_vec (); | |
5326 | |
5327 if (! mattype.is_dense ()) | |
5328 { | |
5275 | 5329 octave_idx_type ii = 0; |
5330 | |
5331 for (octave_idx_type j = 0; j < ldm; j++) | |
5332 for (octave_idx_type i = 0; i < nc; i++) | |
5164 | 5333 tmp_data[ii++] = 0.; |
5334 } | |
5335 | |
5275 | 5336 for (octave_idx_type j = 0; j < nc; j++) |
5337 for (octave_idx_type i = cidx(j); i < cidx(j+1); i++) | |
5164 | 5338 m_band(ridx(i) - j + n_lower + n_upper, j) = data(i); |
5339 | |
5681 | 5340 // Calculate the norm of the matrix, for later use. |
5341 double anorm; | |
5342 if (calc_cond) | |
5343 { | |
5344 for (octave_idx_type j = 0; j < nr; j++) | |
5345 { | |
5346 double atmp = 0.; | |
5347 for (octave_idx_type i = cidx(j); i < cidx(j+1); i++) | |
5348 atmp += std::abs(data(i)); | |
5349 if (atmp > anorm) | |
5350 anorm = atmp; | |
5351 } | |
5352 } | |
5353 | |
5275 | 5354 Array<octave_idx_type> ipvt (nr); |
5355 octave_idx_type *pipvt = ipvt.fortran_vec (); | |
5164 | 5356 |
5357 F77_XFCN (zgbtrf, ZGBTRF, (nr, nr, n_lower, n_upper, tmp_data, | |
5358 ldm, pipvt, err)); | |
5359 | |
7482
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5360 if (err != 0) |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5361 { |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5362 err = -2; |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5363 rcond = 0.0; |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5364 |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5365 if (sing_handler) |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5366 { |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5367 sing_handler (rcond); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5368 mattype.mark_as_rectangular (); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5369 } |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5370 else |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5371 (*current_liboctave_error_handler) |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5372 ("matrix singular to machine precision"); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5373 |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5374 } |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5375 else |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5376 { |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5377 if (calc_cond) |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5378 { |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5379 char job = '1'; |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5380 Array<Complex> z (2 * nr); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5381 Complex *pz = z.fortran_vec (); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5382 Array<double> iz (nr); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5383 double *piz = iz.fortran_vec (); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5384 |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5385 F77_XFCN (zgbcon, ZGBCON, |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5386 (F77_CONST_CHAR_ARG2 (&job, 1), |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5387 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
|
5388 anorm, rcond, pz, piz, err |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5389 F77_CHAR_ARG_LEN (1))); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5390 |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5391 if (err != 0) |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5392 err = -2; |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5393 |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5394 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
|
5395 |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5396 if (rcond_plus_one == 1.0 || xisnan (rcond)) |
5164 | 5397 { |
7482
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5398 err = -2; |
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 if (sing_handler) |
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 sing_handler (rcond); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5403 mattype.mark_as_rectangular (); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5404 } |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5405 else |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5406 (*current_liboctave_error_handler) |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5407 ("matrix singular to machine precision, rcond = %g", |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5408 rcond); |
5681 | 5409 } |
7482
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5410 } |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5411 else |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5412 rcond = 1.; |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5413 |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5414 if (err == 0) |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5415 { |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5416 char job = 'N'; |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5417 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
|
5418 octave_idx_type b_nc = b.cols (); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5419 retval = SparseComplexMatrix (nr, b_nc, x_nz); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5420 retval.xcidx(0) = 0; |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5421 volatile octave_idx_type ii = 0; |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5422 |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5423 OCTAVE_LOCAL_BUFFER (Complex, Bx, nr); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5424 |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5425 for (volatile octave_idx_type j = 0; j < b_nc; j++) |
5681 | 5426 { |
7482
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5427 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
|
5428 Bx[i] = 0.; |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5429 |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5430 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
|
5431 i < b.cidx(j+1); i++) |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5432 Bx[b.ridx(i)] = b.data(i); |
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 F77_XFCN (zgbtrs, ZGBTRS, |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5435 (F77_CONST_CHAR_ARG2 (&job, 1), |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5436 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
|
5437 ldm, pipvt, Bx, b.rows (), err |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5438 F77_CHAR_ARG_LEN (1))); |
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 // 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
|
5441 // space in retval if needed |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5442 octave_idx_type new_nnz = 0; |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5443 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
|
5444 if (Bx[i] != 0.) |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5445 new_nnz++; |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5446 |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5447 if (ii + new_nnz > x_nz) |
5164 | 5448 { |
7482
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5449 // Resize the sparse matrix |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5450 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
|
5451 retval.change_capacity (sz); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5452 x_nz = sz; |
5164 | 5453 } |
5454 | |
7482
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 < nr; i++) |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5456 if (Bx[i] != 0.) |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5457 { |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5458 retval.xridx(ii) = i; |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5459 retval.xdata(ii++) = Bx[i]; |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5460 } |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5461 retval.xcidx(j+1) = ii; |
5164 | 5462 } |
7482
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5463 |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
5464 retval.maybe_compress (); |
5164 | 5465 } |
5466 } | |
5467 } | |
5785 | 5468 else if (typ != MatrixType::Banded_Hermitian) |
5164 | 5469 (*current_liboctave_error_handler) ("incorrect matrix type"); |
5470 } | |
5471 | |
5472 return retval; | |
5473 } | |
5474 | |
5475 void * | |
5681 | 5476 SparseComplexMatrix::factorize (octave_idx_type& err, double &rcond, |
5477 Matrix &Control, Matrix &Info, | |
5478 solve_singularity_handler sing_handler, | |
5479 bool calc_cond) const | |
5164 | 5480 { |
5481 // The return values | |
5404 | 5482 void *Numeric = 0; |
5164 | 5483 err = 0; |
5484 | |
5203 | 5485 #ifdef HAVE_UMFPACK |
5164 | 5486 // Setup the control parameters |
5487 Control = Matrix (UMFPACK_CONTROL, 1); | |
5488 double *control = Control.fortran_vec (); | |
5322 | 5489 UMFPACK_ZNAME (defaults) (control); |
5164 | 5490 |
5893 | 5491 double tmp = octave_sparse_params::get_key ("spumoni"); |
5164 | 5492 if (!xisnan (tmp)) |
5493 Control (UMFPACK_PRL) = tmp; | |
5893 | 5494 tmp = octave_sparse_params::get_key ("piv_tol"); |
5164 | 5495 if (!xisnan (tmp)) |
5496 { | |
5497 Control (UMFPACK_SYM_PIVOT_TOLERANCE) = tmp; | |
5498 Control (UMFPACK_PIVOT_TOLERANCE) = tmp; | |
5499 } | |
5500 | |
5501 // Set whether we are allowed to modify Q or not | |
5893 | 5502 tmp = octave_sparse_params::get_key ("autoamd"); |
5164 | 5503 if (!xisnan (tmp)) |
5504 Control (UMFPACK_FIXQ) = tmp; | |
5505 | |
5322 | 5506 UMFPACK_ZNAME (report_control) (control); |
5164 | 5507 |
5275 | 5508 const octave_idx_type *Ap = cidx (); |
5509 const octave_idx_type *Ai = ridx (); | |
5164 | 5510 const Complex *Ax = data (); |
5275 | 5511 octave_idx_type nr = rows (); |
5512 octave_idx_type nc = cols (); | |
5164 | 5513 |
5322 | 5514 UMFPACK_ZNAME (report_matrix) (nr, nc, Ap, Ai, |
5760 | 5515 reinterpret_cast<const double *> (Ax), |
7520 | 5516 0, 1, control); |
5164 | 5517 |
5518 void *Symbolic; | |
5519 Info = Matrix (1, UMFPACK_INFO); | |
5520 double *info = Info.fortran_vec (); | |
5322 | 5521 int status = UMFPACK_ZNAME (qsymbolic) (nr, nc, Ap, Ai, |
5760 | 5522 reinterpret_cast<const double *> (Ax), |
7520 | 5523 0, 0, &Symbolic, control, info); |
5164 | 5524 |
5525 if (status < 0) | |
5526 { | |
5527 (*current_liboctave_error_handler) | |
5528 ("SparseComplexMatrix::solve symbolic factorization failed"); | |
5529 err = -1; | |
5530 | |
5322 | 5531 UMFPACK_ZNAME (report_status) (control, status); |
5532 UMFPACK_ZNAME (report_info) (control, info); | |
5533 | |
5534 UMFPACK_ZNAME (free_symbolic) (&Symbolic) ; | |
5164 | 5535 } |
5536 else | |
5537 { | |
5322 | 5538 UMFPACK_ZNAME (report_symbolic) (Symbolic, control); |
5539 | |
5540 status = UMFPACK_ZNAME (numeric) (Ap, Ai, | |
7520 | 5541 reinterpret_cast<const double *> (Ax), 0, |
5164 | 5542 Symbolic, &Numeric, control, info) ; |
5322 | 5543 UMFPACK_ZNAME (free_symbolic) (&Symbolic) ; |
5164 | 5544 |
5681 | 5545 if (calc_cond) |
5546 rcond = Info (UMFPACK_RCOND); | |
5547 else | |
5548 rcond = 1.; | |
5164 | 5549 volatile double rcond_plus_one = rcond + 1.0; |
5550 | |
5551 if (status == UMFPACK_WARNING_singular_matrix || | |
5552 rcond_plus_one == 1.0 || xisnan (rcond)) | |
5553 { | |
5322 | 5554 UMFPACK_ZNAME (report_numeric) (Numeric, control); |
5164 | 5555 |
5556 err = -2; | |
5557 | |
5558 if (sing_handler) | |
5559 sing_handler (rcond); | |
5560 else | |
5561 (*current_liboctave_error_handler) | |
5562 ("SparseComplexMatrix::solve matrix singular to machine precision, rcond = %g", | |
5563 rcond); | |
5564 | |
5565 } | |
5610 | 5566 else if (status < 0) |
5164 | 5567 { |
5568 (*current_liboctave_error_handler) | |
5569 ("SparseComplexMatrix::solve numeric factorization failed"); | |
5570 | |
5322 | 5571 UMFPACK_ZNAME (report_status) (control, status); |
5572 UMFPACK_ZNAME (report_info) (control, info); | |
5164 | 5573 |
5574 err = -1; | |
5575 } | |
5576 else | |
5577 { | |
5322 | 5578 UMFPACK_ZNAME (report_numeric) (Numeric, control); |
5164 | 5579 } |
5580 } | |
5581 | |
5582 if (err != 0) | |
5322 | 5583 UMFPACK_ZNAME (free_numeric) (&Numeric); |
5203 | 5584 #else |
5585 (*current_liboctave_error_handler) ("UMFPACK not installed"); | |
5586 #endif | |
5164 | 5587 |
5588 return Numeric; | |
5589 } | |
5590 | |
5591 ComplexMatrix | |
5785 | 5592 SparseComplexMatrix::fsolve (MatrixType &mattype, const Matrix& b, |
5681 | 5593 octave_idx_type& err, double& rcond, |
5594 solve_singularity_handler sing_handler, | |
5595 bool calc_cond) const | |
5164 | 5596 { |
5597 ComplexMatrix retval; | |
5598 | |
5275 | 5599 octave_idx_type nr = rows (); |
5600 octave_idx_type nc = cols (); | |
5164 | 5601 err = 0; |
5602 | |
6924 | 5603 if (nr != nc || nr != b.rows ()) |
5164 | 5604 (*current_liboctave_error_handler) |
5605 ("matrix dimension mismatch solution of linear equations"); | |
6924 | 5606 else if (nr == 0 || b.cols () == 0) |
5607 retval = ComplexMatrix (nc, b.cols (), Complex (0.0, 0.0)); | |
5164 | 5608 else |
5609 { | |
5610 // Print spparms("spumoni") info if requested | |
5611 volatile int typ = mattype.type (); | |
5612 mattype.info (); | |
5613 | |
5785 | 5614 if (typ == MatrixType::Hermitian) |
5164 | 5615 { |
5506 | 5616 #ifdef HAVE_CHOLMOD |
5617 cholmod_common Common; | |
5618 cholmod_common *cm = &Common; | |
5619 | |
5620 // Setup initial parameters | |
5621 CHOLMOD_NAME(start) (cm); | |
5526 | 5622 cm->prefer_zomplex = false; |
5506 | 5623 |
5893 | 5624 double spu = octave_sparse_params::get_key ("spumoni"); |
5506 | 5625 if (spu == 0.) |
5626 { | |
5627 cm->print = -1; | |
7520 | 5628 cm->print_function = 0; |
5506 | 5629 } |
5630 else | |
5631 { | |
5760 | 5632 cm->print = static_cast<int> (spu) + 2; |
5506 | 5633 cm->print_function =&SparseCholPrint; |
5634 } | |
5635 | |
5636 cm->error_handler = &SparseCholError; | |
5637 cm->complex_divide = CHOLMOD_NAME(divcomplex); | |
5638 cm->hypotenuse = CHOLMOD_NAME(hypot); | |
5639 | |
5526 | 5640 cm->final_ll = true; |
5506 | 5641 |
5642 cholmod_sparse Astore; | |
5643 cholmod_sparse *A = &Astore; | |
5644 double dummy; | |
5645 A->nrow = nr; | |
5646 A->ncol = nc; | |
5647 | |
5648 A->p = cidx(); | |
5649 A->i = ridx(); | |
5604 | 5650 A->nzmax = nnz(); |
5526 | 5651 A->packed = true; |
5652 A->sorted = true; | |
7520 | 5653 A->nz = 0; |
5506 | 5654 #ifdef IDX_TYPE_LONG |
5655 A->itype = CHOLMOD_LONG; | |
5656 #else | |
5657 A->itype = CHOLMOD_INT; | |
5658 #endif | |
5659 A->dtype = CHOLMOD_DOUBLE; | |
5660 A->stype = 1; | |
5661 A->xtype = CHOLMOD_COMPLEX; | |
5662 | |
5663 if (nr < 1) | |
5664 A->x = &dummy; | |
5665 else | |
5666 A->x = data(); | |
5667 | |
5668 cholmod_dense Bstore; | |
5669 cholmod_dense *B = &Bstore; | |
5670 B->nrow = b.rows(); | |
5671 B->ncol = b.cols(); | |
5672 B->d = B->nrow; | |
5673 B->nzmax = B->nrow * B->ncol; | |
5674 B->dtype = CHOLMOD_DOUBLE; | |
5675 B->xtype = CHOLMOD_REAL; | |
5676 if (nc < 1 || b.cols() < 1) | |
5677 B->x = &dummy; | |
5678 else | |
5679 // We won't alter it, honest :-) | |
5680 B->x = const_cast<double *>(b.fortran_vec()); | |
5681 | |
5682 cholmod_factor *L; | |
5683 BEGIN_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE; | |
5684 L = CHOLMOD_NAME(analyze) (A, cm); | |
5685 CHOLMOD_NAME(factorize) (A, L, cm); | |
5681 | 5686 if (calc_cond) |
5687 rcond = CHOLMOD_NAME(rcond)(L, cm); | |
5688 else | |
5689 rcond = 1.; | |
5506 | 5690 END_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE; |
5691 | |
5692 if (rcond == 0.0) | |
5693 { | |
5694 // Either its indefinite or singular. Try UMFPACK | |
5695 mattype.mark_as_unsymmetric (); | |
5785 | 5696 typ = MatrixType::Full; |
5506 | 5697 } |
5698 else | |
5699 { | |
5700 volatile double rcond_plus_one = rcond + 1.0; | |
5701 | |
5702 if (rcond_plus_one == 1.0 || xisnan (rcond)) | |
5703 { | |
5704 err = -2; | |
5705 | |
5706 if (sing_handler) | |
5681 | 5707 { |
5708 sing_handler (rcond); | |
5709 mattype.mark_as_rectangular (); | |
5710 } | |
5506 | 5711 else |
5712 (*current_liboctave_error_handler) | |
5713 ("SparseMatrix::solve matrix singular to machine precision, rcond = %g", | |
5714 rcond); | |
5715 | |
5716 return retval; | |
5717 } | |
5718 | |
5719 cholmod_dense *X; | |
5720 BEGIN_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE; | |
5721 X = CHOLMOD_NAME(solve) (CHOLMOD_A, L, B, cm); | |
5722 END_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE; | |
5723 | |
5724 retval.resize (b.rows (), b.cols()); | |
5725 for (octave_idx_type j = 0; j < b.cols(); j++) | |
5726 { | |
5727 octave_idx_type jr = j * b.rows(); | |
5728 for (octave_idx_type i = 0; i < b.rows(); i++) | |
5729 retval.xelem(i,j) = static_cast<Complex *>(X->x)[jr + i]; | |
5730 } | |
5731 | |
5732 BEGIN_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE; | |
5733 CHOLMOD_NAME(free_dense) (&X, cm); | |
5734 CHOLMOD_NAME(free_factor) (&L, cm); | |
5735 CHOLMOD_NAME(finish) (cm); | |
6482 | 5736 static char tmp[] = " "; |
5737 CHOLMOD_NAME(print_common) (tmp, cm); | |
5506 | 5738 END_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE; |
5739 } | |
5740 #else | |
5164 | 5741 (*current_liboctave_warning_handler) |
5506 | 5742 ("CHOLMOD not installed"); |
5164 | 5743 |
5744 mattype.mark_as_unsymmetric (); | |
5785 | 5745 typ = MatrixType::Full; |
5506 | 5746 #endif |
5164 | 5747 } |
5748 | |
5785 | 5749 if (typ == MatrixType::Full) |
5164 | 5750 { |
5203 | 5751 #ifdef HAVE_UMFPACK |
5164 | 5752 Matrix Control, Info; |
5753 void *Numeric = factorize (err, rcond, Control, Info, | |
5681 | 5754 sing_handler, calc_cond); |
5164 | 5755 |
5756 if (err == 0) | |
5757 { | |
5275 | 5758 octave_idx_type b_nr = b.rows (); |
5759 octave_idx_type b_nc = b.cols (); | |
5164 | 5760 int status = 0; |
5761 double *control = Control.fortran_vec (); | |
5762 double *info = Info.fortran_vec (); | |
5275 | 5763 const octave_idx_type *Ap = cidx (); |
5764 const octave_idx_type *Ai = ridx (); | |
5164 | 5765 const Complex *Ax = data (); |
5203 | 5766 #ifdef UMFPACK_SEPARATE_SPLIT |
5164 | 5767 const double *Bx = b.fortran_vec (); |
5768 OCTAVE_LOCAL_BUFFER (double, Bz, b_nr); | |
5275 | 5769 for (octave_idx_type i = 0; i < b_nr; i++) |
5164 | 5770 Bz[i] = 0.; |
5203 | 5771 #else |
5772 OCTAVE_LOCAL_BUFFER (Complex, Bz, b_nr); | |
5773 #endif | |
5164 | 5774 retval.resize (b_nr, b_nc); |
5775 Complex *Xx = retval.fortran_vec (); | |
5776 | |
5275 | 5777 for (octave_idx_type j = 0, iidx = 0; j < b_nc; j++, iidx += b_nr) |
5164 | 5778 { |
5203 | 5779 #ifdef UMFPACK_SEPARATE_SPLIT |
5322 | 5780 status = UMFPACK_ZNAME (solve) (UMFPACK_A, Ap, |
5760 | 5781 Ai, |
5782 reinterpret_cast<const double *> (Ax), | |
7520 | 5783 0, |
5760 | 5784 reinterpret_cast<double *> (&Xx[iidx]), |
7520 | 5785 0, |
5164 | 5786 &Bx[iidx], Bz, Numeric, |
5787 control, info); | |
5203 | 5788 #else |
5275 | 5789 for (octave_idx_type i = 0; i < b_nr; i++) |
5203 | 5790 Bz[i] = b.elem (i, j); |
5791 | |
5322 | 5792 status = UMFPACK_ZNAME (solve) (UMFPACK_A, Ap, |
5760 | 5793 Ai, |
5794 reinterpret_cast<const double *> (Ax), | |
7520 | 5795 0, |
5780 | 5796 reinterpret_cast<double *> (&Xx[iidx]), |
7520 | 5797 0, |
5760 | 5798 reinterpret_cast<const double *> (Bz), |
7520 | 5799 0, Numeric, |
5203 | 5800 control, info); |
5801 #endif | |
5802 | |
5164 | 5803 if (status < 0) |
5804 { | |
5805 (*current_liboctave_error_handler) | |
5806 ("SparseComplexMatrix::solve solve failed"); | |
5807 | |
5322 | 5808 UMFPACK_ZNAME (report_status) (control, status); |
5164 | 5809 |
5810 err = -1; | |
5811 | |
5812 break; | |
5813 } | |
5814 } | |
5815 | |
5322 | 5816 UMFPACK_ZNAME (report_info) (control, info); |
5817 | |
5818 UMFPACK_ZNAME (free_numeric) (&Numeric); | |
5164 | 5819 } |
5681 | 5820 else |
5821 mattype.mark_as_rectangular (); | |
5822 | |
5203 | 5823 #else |
5824 (*current_liboctave_error_handler) ("UMFPACK not installed"); | |
5825 #endif | |
5164 | 5826 } |
5785 | 5827 else if (typ != MatrixType::Hermitian) |
5164 | 5828 (*current_liboctave_error_handler) ("incorrect matrix type"); |
5829 } | |
5830 | |
5831 return retval; | |
5832 } | |
5833 | |
5834 SparseComplexMatrix | |
5785 | 5835 SparseComplexMatrix::fsolve (MatrixType &mattype, const SparseMatrix& b, |
5275 | 5836 octave_idx_type& err, double& rcond, |
5681 | 5837 solve_singularity_handler sing_handler, |
5838 bool calc_cond) const | |
5164 | 5839 { |
5840 SparseComplexMatrix retval; | |
5841 | |
5275 | 5842 octave_idx_type nr = rows (); |
5843 octave_idx_type nc = cols (); | |
5164 | 5844 err = 0; |
5845 | |
6924 | 5846 if (nr != nc || nr != b.rows ()) |
5164 | 5847 (*current_liboctave_error_handler) |
5848 ("matrix dimension mismatch solution of linear equations"); | |
6924 | 5849 else if (nr == 0 || b.cols () == 0) |
5850 retval = SparseComplexMatrix (nc, b.cols ()); | |
5164 | 5851 else |
5852 { | |
5853 // Print spparms("spumoni") info if requested | |
5506 | 5854 volatile int typ = mattype.type (); |
5164 | 5855 mattype.info (); |
5856 | |
5785 | 5857 if (typ == MatrixType::Hermitian) |
5164 | 5858 { |
5506 | 5859 #ifdef HAVE_CHOLMOD |
5860 cholmod_common Common; | |
5861 cholmod_common *cm = &Common; | |
5862 | |
5863 // Setup initial parameters | |
5864 CHOLMOD_NAME(start) (cm); | |
5526 | 5865 cm->prefer_zomplex = false; |
5506 | 5866 |
5893 | 5867 double spu = octave_sparse_params::get_key ("spumoni"); |
5506 | 5868 if (spu == 0.) |
5869 { | |
5870 cm->print = -1; | |
7520 | 5871 cm->print_function = 0; |
5506 | 5872 } |
5873 else | |
5874 { | |
5760 | 5875 cm->print = static_cast<int> (spu) + 2; |
5506 | 5876 cm->print_function =&SparseCholPrint; |
5877 } | |
5878 | |
5879 cm->error_handler = &SparseCholError; | |
5880 cm->complex_divide = CHOLMOD_NAME(divcomplex); | |
5881 cm->hypotenuse = CHOLMOD_NAME(hypot); | |
5882 | |
5526 | 5883 cm->final_ll = true; |
5506 | 5884 |
5885 cholmod_sparse Astore; | |
5886 cholmod_sparse *A = &Astore; | |
5887 double dummy; | |
5888 A->nrow = nr; | |
5889 A->ncol = nc; | |
5890 | |
5891 A->p = cidx(); | |
5892 A->i = ridx(); | |
5604 | 5893 A->nzmax = nnz(); |
5526 | 5894 A->packed = true; |
5895 A->sorted = true; | |
7520 | 5896 A->nz = 0; |
5506 | 5897 #ifdef IDX_TYPE_LONG |
5898 A->itype = CHOLMOD_LONG; | |
5899 #else | |
5900 A->itype = CHOLMOD_INT; | |
5901 #endif | |
5902 A->dtype = CHOLMOD_DOUBLE; | |
5903 A->stype = 1; | |
5904 A->xtype = CHOLMOD_COMPLEX; | |
5905 | |
5906 if (nr < 1) | |
5907 A->x = &dummy; | |
5908 else | |
5909 A->x = data(); | |
5910 | |
5911 cholmod_sparse Bstore; | |
5912 cholmod_sparse *B = &Bstore; | |
5913 B->nrow = b.rows(); | |
5914 B->ncol = b.cols(); | |
5915 B->p = b.cidx(); | |
5916 B->i = b.ridx(); | |
5604 | 5917 B->nzmax = b.nnz(); |
5526 | 5918 B->packed = true; |
5919 B->sorted = true; | |
7520 | 5920 B->nz = 0; |
5506 | 5921 #ifdef IDX_TYPE_LONG |
5922 B->itype = CHOLMOD_LONG; | |
5923 #else | |
5924 B->itype = CHOLMOD_INT; | |
5925 #endif | |
5926 B->dtype = CHOLMOD_DOUBLE; | |
5927 B->stype = 0; | |
5928 B->xtype = CHOLMOD_REAL; | |
5929 | |
5930 if (b.rows() < 1 || b.cols() < 1) | |
5931 B->x = &dummy; | |
5932 else | |
5933 B->x = b.data(); | |
5934 | |
5935 cholmod_factor *L; | |
5936 BEGIN_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE; | |
5937 L = CHOLMOD_NAME(analyze) (A, cm); | |
5938 CHOLMOD_NAME(factorize) (A, L, cm); | |
5681 | 5939 if (calc_cond) |
5940 rcond = CHOLMOD_NAME(rcond)(L, cm); | |
5941 else | |
5942 rcond = 1.; | |
5506 | 5943 END_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE; |
5944 | |
5945 if (rcond == 0.0) | |
5946 { | |
5947 // Either its indefinite or singular. Try UMFPACK | |
5948 mattype.mark_as_unsymmetric (); | |
5785 | 5949 typ = MatrixType::Full; |
5506 | 5950 } |
5951 else | |
5952 { | |
5953 volatile double rcond_plus_one = rcond + 1.0; | |
5954 | |
5955 if (rcond_plus_one == 1.0 || xisnan (rcond)) | |
5956 { | |
5957 err = -2; | |
5958 | |
5959 if (sing_handler) | |
5681 | 5960 { |
5961 sing_handler (rcond); | |
5962 mattype.mark_as_rectangular (); | |
5963 } | |
5506 | 5964 else |
5965 (*current_liboctave_error_handler) | |
5966 ("SparseMatrix::solve matrix singular to machine precision, rcond = %g", | |
5967 rcond); | |
5968 | |
5969 return retval; | |
5970 } | |
5971 | |
5972 cholmod_sparse *X; | |
5973 BEGIN_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE; | |
5974 X = CHOLMOD_NAME(spsolve) (CHOLMOD_A, L, B, cm); | |
5975 END_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE; | |
5976 | |
5977 retval = SparseComplexMatrix | |
5978 (static_cast<octave_idx_type>(X->nrow), | |
5979 static_cast<octave_idx_type>(X->ncol), | |
5980 static_cast<octave_idx_type>(X->nzmax)); | |
5981 for (octave_idx_type j = 0; | |
5982 j <= static_cast<octave_idx_type>(X->ncol); j++) | |
5983 retval.xcidx(j) = static_cast<octave_idx_type *>(X->p)[j]; | |
5984 for (octave_idx_type j = 0; | |
5985 j < static_cast<octave_idx_type>(X->nzmax); j++) | |
5986 { | |
5987 retval.xridx(j) = static_cast<octave_idx_type *>(X->i)[j]; | |
5988 retval.xdata(j) = static_cast<Complex *>(X->x)[j]; | |
5989 } | |
5990 | |
5991 BEGIN_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE; | |
5992 CHOLMOD_NAME(free_sparse) (&X, cm); | |
5993 CHOLMOD_NAME(free_factor) (&L, cm); | |
5994 CHOLMOD_NAME(finish) (cm); | |
6482 | 5995 static char tmp[] = " "; |
5996 CHOLMOD_NAME(print_common) (tmp, cm); | |
5506 | 5997 END_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE; |
5998 } | |
5999 #else | |
5164 | 6000 (*current_liboctave_warning_handler) |
5506 | 6001 ("CHOLMOD not installed"); |
5164 | 6002 |
6003 mattype.mark_as_unsymmetric (); | |
5785 | 6004 typ = MatrixType::Full; |
5506 | 6005 #endif |
5164 | 6006 } |
6007 | |
5785 | 6008 if (typ == MatrixType::Full) |
5164 | 6009 { |
5203 | 6010 #ifdef HAVE_UMFPACK |
5164 | 6011 Matrix Control, Info; |
5681 | 6012 void *Numeric = factorize (err, rcond, Control, Info, |
6013 sing_handler, calc_cond); | |
5164 | 6014 |
6015 if (err == 0) | |
6016 { | |
5275 | 6017 octave_idx_type b_nr = b.rows (); |
6018 octave_idx_type b_nc = b.cols (); | |
5164 | 6019 int status = 0; |
6020 double *control = Control.fortran_vec (); | |
6021 double *info = Info.fortran_vec (); | |
5275 | 6022 const octave_idx_type *Ap = cidx (); |
6023 const octave_idx_type *Ai = ridx (); | |
5164 | 6024 const Complex *Ax = data (); |
6025 | |
5203 | 6026 #ifdef UMFPACK_SEPARATE_SPLIT |
5164 | 6027 OCTAVE_LOCAL_BUFFER (double, Bx, b_nr); |
6028 OCTAVE_LOCAL_BUFFER (double, Bz, b_nr); | |
5275 | 6029 for (octave_idx_type i = 0; i < b_nr; i++) |
5164 | 6030 Bz[i] = 0.; |
5203 | 6031 #else |
6032 OCTAVE_LOCAL_BUFFER (Complex, Bz, b_nr); | |
6033 #endif | |
5164 | 6034 |
6035 // Take a first guess that the number of non-zero terms | |
6036 // will be as many as in b | |
5681 | 6037 octave_idx_type x_nz = b.nnz (); |
5275 | 6038 octave_idx_type ii = 0; |
5164 | 6039 retval = SparseComplexMatrix (b_nr, b_nc, x_nz); |
6040 | |
6041 OCTAVE_LOCAL_BUFFER (Complex, Xx, b_nr); | |
6042 | |
6043 retval.xcidx(0) = 0; | |
5275 | 6044 for (octave_idx_type j = 0; j < b_nc; j++) |
5164 | 6045 { |
6046 | |
5203 | 6047 #ifdef UMFPACK_SEPARATE_SPLIT |
5275 | 6048 for (octave_idx_type i = 0; i < b_nr; i++) |
5164 | 6049 Bx[i] = b.elem (i, j); |
6050 | |
5322 | 6051 status = UMFPACK_ZNAME (solve) (UMFPACK_A, Ap, |
5760 | 6052 Ai, |
6053 reinterpret_cast<const double *> (Ax), | |
7520 | 6054 0, |
5760 | 6055 reinterpret_cast<double *> (Xx), |
7520 | 6056 0, |
5164 | 6057 Bx, Bz, Numeric, control, |
6058 info); | |
5203 | 6059 #else |
5275 | 6060 for (octave_idx_type i = 0; i < b_nr; i++) |
5203 | 6061 Bz[i] = b.elem (i, j); |
6062 | |
5322 | 6063 status = UMFPACK_ZNAME (solve) (UMFPACK_A, Ap, Ai, |
5760 | 6064 reinterpret_cast<const double *> (Ax), |
7520 | 6065 0, |
5760 | 6066 reinterpret_cast<double *> (Xx), |
7520 | 6067 0, |
5760 | 6068 reinterpret_cast<double *> (Bz), |
7520 | 6069 0, |
5203 | 6070 Numeric, control, |
6071 info); | |
6072 #endif | |
5164 | 6073 if (status < 0) |
6074 { | |
6075 (*current_liboctave_error_handler) | |
6076 ("SparseComplexMatrix::solve solve failed"); | |
6077 | |
5322 | 6078 UMFPACK_ZNAME (report_status) (control, status); |
5164 | 6079 |
6080 err = -1; | |
6081 | |
6082 break; | |
6083 } | |
6084 | |
5275 | 6085 for (octave_idx_type i = 0; i < b_nr; i++) |
5164 | 6086 { |
6087 Complex tmp = Xx[i]; | |
6088 if (tmp != 0.0) | |
6089 { | |
6090 if (ii == x_nz) | |
6091 { | |
6092 // Resize the sparse matrix | |
5275 | 6093 octave_idx_type sz = x_nz * (b_nc - j) / b_nc; |
5164 | 6094 sz = (sz > 10 ? sz : 10) + x_nz; |
6095 retval.change_capacity (sz); | |
6096 x_nz = sz; | |
6097 } | |
6098 retval.xdata(ii) = tmp; | |
6099 retval.xridx(ii++) = i; | |
6100 } | |
6101 } | |
6102 retval.xcidx(j+1) = ii; | |
6103 } | |
6104 | |
6105 retval.maybe_compress (); | |
6106 | |
5322 | 6107 UMFPACK_ZNAME (report_info) (control, info); |
6108 | |
6109 UMFPACK_ZNAME (free_numeric) (&Numeric); | |
5164 | 6110 } |
5681 | 6111 else |
6112 mattype.mark_as_rectangular (); | |
6113 | |
5203 | 6114 #else |
6115 (*current_liboctave_error_handler) ("UMFPACK not installed"); | |
6116 #endif | |
5164 | 6117 } |
5785 | 6118 else if (typ != MatrixType::Hermitian) |
5164 | 6119 (*current_liboctave_error_handler) ("incorrect matrix type"); |
6120 } | |
6121 | |
6122 return retval; | |
6123 } | |
6124 | |
6125 ComplexMatrix | |
5785 | 6126 SparseComplexMatrix::fsolve (MatrixType &mattype, const ComplexMatrix& b, |
5275 | 6127 octave_idx_type& err, double& rcond, |
5681 | 6128 solve_singularity_handler sing_handler, |
6129 bool calc_cond) const | |
5164 | 6130 { |
6131 ComplexMatrix retval; | |
6132 | |
5275 | 6133 octave_idx_type nr = rows (); |
6134 octave_idx_type nc = cols (); | |
5164 | 6135 err = 0; |
6136 | |
6924 | 6137 if (nr != nc || nr != b.rows ()) |
5164 | 6138 (*current_liboctave_error_handler) |
6139 ("matrix dimension mismatch solution of linear equations"); | |
6924 | 6140 else if (nr == 0 || b.cols () == 0) |
6141 retval = ComplexMatrix (nc, b.cols (), Complex (0.0, 0.0)); | |
5164 | 6142 else |
6143 { | |
6144 // Print spparms("spumoni") info if requested | |
5506 | 6145 volatile int typ = mattype.type (); |
5164 | 6146 mattype.info (); |
6147 | |
5785 | 6148 if (typ == MatrixType::Hermitian) |
5164 | 6149 { |
5506 | 6150 #ifdef HAVE_CHOLMOD |
6151 cholmod_common Common; | |
6152 cholmod_common *cm = &Common; | |
6153 | |
6154 // Setup initial parameters | |
6155 CHOLMOD_NAME(start) (cm); | |
5526 | 6156 cm->prefer_zomplex = false; |
5506 | 6157 |
5893 | 6158 double spu = octave_sparse_params::get_key ("spumoni"); |
5506 | 6159 if (spu == 0.) |
6160 { | |
6161 cm->print = -1; | |
7520 | 6162 cm->print_function = 0; |
5506 | 6163 } |
6164 else | |
6165 { | |
5760 | 6166 cm->print = static_cast<int> (spu) + 2; |
5506 | 6167 cm->print_function =&SparseCholPrint; |
6168 } | |
6169 | |
6170 cm->error_handler = &SparseCholError; | |
6171 cm->complex_divide = CHOLMOD_NAME(divcomplex); | |
6172 cm->hypotenuse = CHOLMOD_NAME(hypot); | |
6173 | |
5526 | 6174 cm->final_ll = true; |
5506 | 6175 |
6176 cholmod_sparse Astore; | |
6177 cholmod_sparse *A = &Astore; | |
6178 double dummy; | |
6179 A->nrow = nr; | |
6180 A->ncol = nc; | |
6181 | |
6182 A->p = cidx(); | |
6183 A->i = ridx(); | |
5604 | 6184 A->nzmax = nnz(); |
5526 | 6185 A->packed = true; |
6186 A->sorted = true; | |
7520 | 6187 A->nz = 0; |
5506 | 6188 #ifdef IDX_TYPE_LONG |
6189 A->itype = CHOLMOD_LONG; | |
6190 #else | |
6191 A->itype = CHOLMOD_INT; | |
6192 #endif | |
6193 A->dtype = CHOLMOD_DOUBLE; | |
6194 A->stype = 1; | |
6195 A->xtype = CHOLMOD_COMPLEX; | |
6196 | |
6197 if (nr < 1) | |
6198 A->x = &dummy; | |
6199 else | |
6200 A->x = data(); | |
6201 | |
6202 cholmod_dense Bstore; | |
6203 cholmod_dense *B = &Bstore; | |
6204 B->nrow = b.rows(); | |
6205 B->ncol = b.cols(); | |
6206 B->d = B->nrow; | |
6207 B->nzmax = B->nrow * B->ncol; | |
6208 B->dtype = CHOLMOD_DOUBLE; | |
6209 B->xtype = CHOLMOD_COMPLEX; | |
6210 if (nc < 1 || b.cols() < 1) | |
6211 B->x = &dummy; | |
6212 else | |
6213 // We won't alter it, honest :-) | |
6214 B->x = const_cast<Complex *>(b.fortran_vec()); | |
6215 | |
6216 cholmod_factor *L; | |
6217 BEGIN_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE; | |
6218 L = CHOLMOD_NAME(analyze) (A, cm); | |
6219 CHOLMOD_NAME(factorize) (A, L, cm); | |
5681 | 6220 if (calc_cond) |
6221 rcond = CHOLMOD_NAME(rcond)(L, cm); | |
6222 else | |
6223 rcond = 1.; | |
5506 | 6224 END_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE; |
6225 | |
6226 if (rcond == 0.0) | |
6227 { | |
6228 // Either its indefinite or singular. Try UMFPACK | |
6229 mattype.mark_as_unsymmetric (); | |
5785 | 6230 typ = MatrixType::Full; |
5506 | 6231 } |
6232 else | |
6233 { | |
6234 volatile double rcond_plus_one = rcond + 1.0; | |
6235 | |
6236 if (rcond_plus_one == 1.0 || xisnan (rcond)) | |
6237 { | |
6238 err = -2; | |
6239 | |
6240 if (sing_handler) | |
5681 | 6241 { |
6242 sing_handler (rcond); | |
6243 mattype.mark_as_rectangular (); | |
6244 } | |
5506 | 6245 else |
6246 (*current_liboctave_error_handler) | |
6247 ("SparseMatrix::solve matrix singular to machine precision, rcond = %g", | |
6248 rcond); | |
6249 | |
6250 return retval; | |
6251 } | |
6252 | |
6253 cholmod_dense *X; | |
6254 BEGIN_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE; | |
6255 X = CHOLMOD_NAME(solve) (CHOLMOD_A, L, B, cm); | |
6256 END_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE; | |
6257 | |
6258 retval.resize (b.rows (), b.cols()); | |
6259 for (octave_idx_type j = 0; j < b.cols(); j++) | |
6260 { | |
6261 octave_idx_type jr = j * b.rows(); | |
6262 for (octave_idx_type i = 0; i < b.rows(); i++) | |
6263 retval.xelem(i,j) = static_cast<Complex *>(X->x)[jr + i]; | |
6264 } | |
6265 | |
6266 BEGIN_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE; | |
6267 CHOLMOD_NAME(free_dense) (&X, cm); | |
6268 CHOLMOD_NAME(free_factor) (&L, cm); | |
6269 CHOLMOD_NAME(finish) (cm); | |
6482 | 6270 static char tmp[] = " "; |
6271 CHOLMOD_NAME(print_common) (tmp, cm); | |
5506 | 6272 END_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE; |
6273 } | |
6274 #else | |
5164 | 6275 (*current_liboctave_warning_handler) |
5506 | 6276 ("CHOLMOD not installed"); |
5164 | 6277 |
6278 mattype.mark_as_unsymmetric (); | |
5785 | 6279 typ = MatrixType::Full; |
5506 | 6280 #endif |
5164 | 6281 } |
6282 | |
5785 | 6283 if (typ == MatrixType::Full) |
5164 | 6284 { |
5203 | 6285 #ifdef HAVE_UMFPACK |
5164 | 6286 Matrix Control, Info; |
5681 | 6287 void *Numeric = factorize (err, rcond, Control, Info, |
6288 sing_handler, calc_cond); | |
5164 | 6289 |
6290 if (err == 0) | |
6291 { | |
5275 | 6292 octave_idx_type b_nr = b.rows (); |
6293 octave_idx_type b_nc = b.cols (); | |
5164 | 6294 int status = 0; |
6295 double *control = Control.fortran_vec (); | |
6296 double *info = Info.fortran_vec (); | |
5275 | 6297 const octave_idx_type *Ap = cidx (); |
6298 const octave_idx_type *Ai = ridx (); | |
5164 | 6299 const Complex *Ax = data (); |
6300 const Complex *Bx = b.fortran_vec (); | |
6301 | |
6302 retval.resize (b_nr, b_nc); | |
6303 Complex *Xx = retval.fortran_vec (); | |
6304 | |
5275 | 6305 for (octave_idx_type j = 0, iidx = 0; j < b_nc; j++, iidx += b_nr) |
5164 | 6306 { |
6307 status = | |
5322 | 6308 UMFPACK_ZNAME (solve) (UMFPACK_A, Ap, Ai, |
5760 | 6309 reinterpret_cast<const double *> (Ax), |
7520 | 6310 0, |
5760 | 6311 reinterpret_cast<double *> (&Xx[iidx]), |
7520 | 6312 0, |
5760 | 6313 reinterpret_cast<const double *> (&Bx[iidx]), |
7520 | 6314 0, Numeric, control, info); |
5164 | 6315 |
6316 if (status < 0) | |
6317 { | |
6318 (*current_liboctave_error_handler) | |
6319 ("SparseComplexMatrix::solve solve failed"); | |
6320 | |
5322 | 6321 UMFPACK_ZNAME (report_status) (control, status); |
5164 | 6322 |
6323 err = -1; | |
6324 | |
6325 break; | |
6326 } | |
6327 } | |
6328 | |
5322 | 6329 UMFPACK_ZNAME (report_info) (control, info); |
6330 | |
6331 UMFPACK_ZNAME (free_numeric) (&Numeric); | |
5164 | 6332 } |
5681 | 6333 else |
6334 mattype.mark_as_rectangular (); | |
6335 | |
5203 | 6336 #else |
6337 (*current_liboctave_error_handler) ("UMFPACK not installed"); | |
6338 #endif | |
5164 | 6339 } |
5785 | 6340 else if (typ != MatrixType::Hermitian) |
5164 | 6341 (*current_liboctave_error_handler) ("incorrect matrix type"); |
6342 } | |
6343 | |
6344 return retval; | |
6345 } | |
6346 | |
6347 SparseComplexMatrix | |
5785 | 6348 SparseComplexMatrix::fsolve (MatrixType &mattype, const SparseComplexMatrix& b, |
5275 | 6349 octave_idx_type& err, double& rcond, |
5681 | 6350 solve_singularity_handler sing_handler, |
6351 bool calc_cond) const | |
5164 | 6352 { |
6353 SparseComplexMatrix retval; | |
6354 | |
5275 | 6355 octave_idx_type nr = rows (); |
6356 octave_idx_type nc = cols (); | |
5164 | 6357 err = 0; |
6358 | |
6924 | 6359 if (nr != nc || nr != b.rows ()) |
5164 | 6360 (*current_liboctave_error_handler) |
6361 ("matrix dimension mismatch solution of linear equations"); | |
6924 | 6362 else if (nr == 0 || b.cols () == 0) |
6363 retval = SparseComplexMatrix (nc, b.cols ()); | |
5164 | 6364 else |
6365 { | |
6366 // Print spparms("spumoni") info if requested | |
5506 | 6367 volatile int typ = mattype.type (); |
5164 | 6368 mattype.info (); |
6369 | |
5785 | 6370 if (typ == MatrixType::Hermitian) |
5164 | 6371 { |
5506 | 6372 #ifdef HAVE_CHOLMOD |
6373 cholmod_common Common; | |
6374 cholmod_common *cm = &Common; | |
6375 | |
6376 // Setup initial parameters | |
6377 CHOLMOD_NAME(start) (cm); | |
5526 | 6378 cm->prefer_zomplex = false; |
5506 | 6379 |
5893 | 6380 double spu = octave_sparse_params::get_key ("spumoni"); |
5506 | 6381 if (spu == 0.) |
6382 { | |
6383 cm->print = -1; | |
7520 | 6384 cm->print_function = 0; |
5506 | 6385 } |
6386 else | |
6387 { | |
5760 | 6388 cm->print = static_cast<int> (spu) + 2; |
5506 | 6389 cm->print_function =&SparseCholPrint; |
6390 } | |
6391 | |
6392 cm->error_handler = &SparseCholError; | |
6393 cm->complex_divide = CHOLMOD_NAME(divcomplex); | |
6394 cm->hypotenuse = CHOLMOD_NAME(hypot); | |
6395 | |
5526 | 6396 cm->final_ll = true; |
5506 | 6397 |
6398 cholmod_sparse Astore; | |
6399 cholmod_sparse *A = &Astore; | |
6400 double dummy; | |
6401 A->nrow = nr; | |
6402 A->ncol = nc; | |
6403 | |
6404 A->p = cidx(); | |
6405 A->i = ridx(); | |
5604 | 6406 A->nzmax = nnz(); |
5526 | 6407 A->packed = true; |
6408 A->sorted = true; | |
7520 | 6409 A->nz = 0; |
5506 | 6410 #ifdef IDX_TYPE_LONG |
6411 A->itype = CHOLMOD_LONG; | |
6412 #else | |
6413 A->itype = CHOLMOD_INT; | |
6414 #endif | |
6415 A->dtype = CHOLMOD_DOUBLE; | |
6416 A->stype = 1; | |
6417 A->xtype = CHOLMOD_COMPLEX; | |
6418 | |
6419 if (nr < 1) | |
6420 A->x = &dummy; | |
6421 else | |
6422 A->x = data(); | |
6423 | |
6424 cholmod_sparse Bstore; | |
6425 cholmod_sparse *B = &Bstore; | |
6426 B->nrow = b.rows(); | |
6427 B->ncol = b.cols(); | |
6428 B->p = b.cidx(); | |
6429 B->i = b.ridx(); | |
5604 | 6430 B->nzmax = b.nnz(); |
5526 | 6431 B->packed = true; |
6432 B->sorted = true; | |
7520 | 6433 B->nz = 0; |
5506 | 6434 #ifdef IDX_TYPE_LONG |
6435 B->itype = CHOLMOD_LONG; | |
6436 #else | |
6437 B->itype = CHOLMOD_INT; | |
6438 #endif | |
6439 B->dtype = CHOLMOD_DOUBLE; | |
6440 B->stype = 0; | |
6441 B->xtype = CHOLMOD_COMPLEX; | |
6442 | |
6443 if (b.rows() < 1 || b.cols() < 1) | |
6444 B->x = &dummy; | |
6445 else | |
6446 B->x = b.data(); | |
6447 | |
6448 cholmod_factor *L; | |
6449 BEGIN_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE; | |
6450 L = CHOLMOD_NAME(analyze) (A, cm); | |
6451 CHOLMOD_NAME(factorize) (A, L, cm); | |
5681 | 6452 if (calc_cond) |
6453 rcond = CHOLMOD_NAME(rcond)(L, cm); | |
6454 else | |
6455 rcond = 1.; | |
5506 | 6456 END_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE; |
6457 | |
6458 if (rcond == 0.0) | |
6459 { | |
6460 // Either its indefinite or singular. Try UMFPACK | |
6461 mattype.mark_as_unsymmetric (); | |
5785 | 6462 typ = MatrixType::Full; |
5506 | 6463 } |
6464 else | |
6465 { | |
6466 volatile double rcond_plus_one = rcond + 1.0; | |
6467 | |
6468 if (rcond_plus_one == 1.0 || xisnan (rcond)) | |
6469 { | |
6470 err = -2; | |
6471 | |
6472 if (sing_handler) | |
5681 | 6473 { |
6474 sing_handler (rcond); | |
6475 mattype.mark_as_rectangular (); | |
6476 } | |
5506 | 6477 else |
6478 (*current_liboctave_error_handler) | |
6479 ("SparseMatrix::solve matrix singular to machine precision, rcond = %g", | |
6480 rcond); | |
6481 | |
6482 return retval; | |
6483 } | |
6484 | |
6485 cholmod_sparse *X; | |
6486 BEGIN_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE; | |
6487 X = CHOLMOD_NAME(spsolve) (CHOLMOD_A, L, B, cm); | |
6488 END_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE; | |
6489 | |
6490 retval = SparseComplexMatrix | |
6491 (static_cast<octave_idx_type>(X->nrow), | |
6492 static_cast<octave_idx_type>(X->ncol), | |
6493 static_cast<octave_idx_type>(X->nzmax)); | |
6494 for (octave_idx_type j = 0; | |
6495 j <= static_cast<octave_idx_type>(X->ncol); j++) | |
6496 retval.xcidx(j) = static_cast<octave_idx_type *>(X->p)[j]; | |
6497 for (octave_idx_type j = 0; | |
6498 j < static_cast<octave_idx_type>(X->nzmax); j++) | |
6499 { | |
6500 retval.xridx(j) = static_cast<octave_idx_type *>(X->i)[j]; | |
6501 retval.xdata(j) = static_cast<Complex *>(X->x)[j]; | |
6502 } | |
6503 | |
6504 BEGIN_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE; | |
6505 CHOLMOD_NAME(free_sparse) (&X, cm); | |
6506 CHOLMOD_NAME(free_factor) (&L, cm); | |
6507 CHOLMOD_NAME(finish) (cm); | |
6482 | 6508 static char tmp[] = " "; |
6509 CHOLMOD_NAME(print_common) (tmp, cm); | |
5506 | 6510 END_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE; |
6511 } | |
6512 #else | |
5164 | 6513 (*current_liboctave_warning_handler) |
5506 | 6514 ("CHOLMOD not installed"); |
5164 | 6515 |
6516 mattype.mark_as_unsymmetric (); | |
5785 | 6517 typ = MatrixType::Full; |
5506 | 6518 #endif |
5164 | 6519 } |
6520 | |
5785 | 6521 if (typ == MatrixType::Full) |
5164 | 6522 { |
5203 | 6523 #ifdef HAVE_UMFPACK |
5164 | 6524 Matrix Control, Info; |
5681 | 6525 void *Numeric = factorize (err, rcond, Control, Info, |
6526 sing_handler, calc_cond); | |
5164 | 6527 |
6528 if (err == 0) | |
6529 { | |
5275 | 6530 octave_idx_type b_nr = b.rows (); |
6531 octave_idx_type b_nc = b.cols (); | |
5164 | 6532 int status = 0; |
6533 double *control = Control.fortran_vec (); | |
6534 double *info = Info.fortran_vec (); | |
5275 | 6535 const octave_idx_type *Ap = cidx (); |
6536 const octave_idx_type *Ai = ridx (); | |
5164 | 6537 const Complex *Ax = data (); |
6538 | |
6539 OCTAVE_LOCAL_BUFFER (Complex, Bx, b_nr); | |
6540 | |
6541 // Take a first guess that the number of non-zero terms | |
6542 // will be as many as in b | |
5681 | 6543 octave_idx_type x_nz = b.nnz (); |
5275 | 6544 octave_idx_type ii = 0; |
5164 | 6545 retval = SparseComplexMatrix (b_nr, b_nc, x_nz); |
6546 | |
6547 OCTAVE_LOCAL_BUFFER (Complex, Xx, b_nr); | |
6548 | |
6549 retval.xcidx(0) = 0; | |
5275 | 6550 for (octave_idx_type j = 0; j < b_nc; j++) |
5164 | 6551 { |
5275 | 6552 for (octave_idx_type i = 0; i < b_nr; i++) |
5164 | 6553 Bx[i] = b (i,j); |
6554 | |
5322 | 6555 status = UMFPACK_ZNAME (solve) (UMFPACK_A, Ap, |
5760 | 6556 Ai, |
6557 reinterpret_cast<const double *> (Ax), | |
7520 | 6558 0, |
5760 | 6559 reinterpret_cast<double *> (Xx), |
7520 | 6560 0, |
5760 | 6561 reinterpret_cast<double *> (Bx), |
7520 | 6562 0, Numeric, control, info); |
5164 | 6563 |
6564 if (status < 0) | |
6565 { | |
6566 (*current_liboctave_error_handler) | |
6567 ("SparseComplexMatrix::solve solve failed"); | |
6568 | |
5322 | 6569 UMFPACK_ZNAME (report_status) (control, status); |
5164 | 6570 |
6571 err = -1; | |
6572 | |
6573 break; | |
6574 } | |
6575 | |
5275 | 6576 for (octave_idx_type i = 0; i < b_nr; i++) |
5164 | 6577 { |
6578 Complex tmp = Xx[i]; | |
6579 if (tmp != 0.0) | |
6580 { | |
6581 if (ii == x_nz) | |
6582 { | |
6583 // Resize the sparse matrix | |
5275 | 6584 octave_idx_type sz = x_nz * (b_nc - j) / b_nc; |
5164 | 6585 sz = (sz > 10 ? sz : 10) + x_nz; |
6586 retval.change_capacity (sz); | |
6587 x_nz = sz; | |
6588 } | |
6589 retval.xdata(ii) = tmp; | |
6590 retval.xridx(ii++) = i; | |
6591 } | |
6592 } | |
6593 retval.xcidx(j+1) = ii; | |
6594 } | |
6595 | |
6596 retval.maybe_compress (); | |
6597 | |
6598 rcond = Info (UMFPACK_RCOND); | |
6599 volatile double rcond_plus_one = rcond + 1.0; | |
6600 | |
6601 if (status == UMFPACK_WARNING_singular_matrix || | |
6602 rcond_plus_one == 1.0 || xisnan (rcond)) | |
6603 { | |
6604 err = -2; | |
6605 | |
6606 if (sing_handler) | |
6607 sing_handler (rcond); | |
6608 else | |
6609 (*current_liboctave_error_handler) | |
6610 ("SparseComplexMatrix::solve matrix singular to machine precision, rcond = %g", | |
6611 rcond); | |
6612 | |
6613 } | |
6614 | |
5322 | 6615 UMFPACK_ZNAME (report_info) (control, info); |
6616 | |
6617 UMFPACK_ZNAME (free_numeric) (&Numeric); | |
5164 | 6618 } |
5681 | 6619 else |
6620 mattype.mark_as_rectangular (); | |
6621 | |
5203 | 6622 #else |
6623 (*current_liboctave_error_handler) ("UMFPACK not installed"); | |
6624 #endif | |
5164 | 6625 } |
5785 | 6626 else if (typ != MatrixType::Hermitian) |
5164 | 6627 (*current_liboctave_error_handler) ("incorrect matrix type"); |
6628 } | |
6629 | |
6630 return retval; | |
6631 } | |
6632 | |
6633 ComplexMatrix | |
5785 | 6634 SparseComplexMatrix::solve (MatrixType &mattype, const Matrix& b) const |
5164 | 6635 { |
5275 | 6636 octave_idx_type info; |
5164 | 6637 double rcond; |
6638 return solve (mattype, b, info, rcond, 0); | |
6639 } | |
6640 | |
6641 ComplexMatrix | |
5785 | 6642 SparseComplexMatrix::solve (MatrixType &mattype, const Matrix& b, |
5275 | 6643 octave_idx_type& info) const |
5164 | 6644 { |
6645 double rcond; | |
6646 return solve (mattype, b, info, rcond, 0); | |
6647 } | |
6648 | |
6649 ComplexMatrix | |
5785 | 6650 SparseComplexMatrix::solve (MatrixType &mattype, const Matrix& b, |
5697 | 6651 octave_idx_type& info, double& rcond) const |
5164 | 6652 { |
6653 return solve (mattype, b, info, rcond, 0); | |
6654 } | |
6655 | |
6656 ComplexMatrix | |
5785 | 6657 SparseComplexMatrix::solve (MatrixType &mattype, const Matrix& b, |
5697 | 6658 octave_idx_type& err, double& rcond, |
6659 solve_singularity_handler sing_handler, | |
6660 bool singular_fallback) const | |
5164 | 6661 { |
5681 | 6662 ComplexMatrix retval; |
5322 | 6663 int typ = mattype.type (false); |
5164 | 6664 |
5785 | 6665 if (typ == MatrixType::Unknown) |
5164 | 6666 typ = mattype.type (*this); |
6667 | |
5785 | 6668 if (typ == MatrixType::Diagonal || typ == MatrixType::Permuted_Diagonal) |
5681 | 6669 retval = dsolve (mattype, b, err, rcond, sing_handler, false); |
5785 | 6670 else if (typ == MatrixType::Upper || typ == MatrixType::Permuted_Upper) |
5681 | 6671 retval = utsolve (mattype, b, err, rcond, sing_handler, false); |
5785 | 6672 else if (typ == MatrixType::Lower || typ == MatrixType::Permuted_Lower) |
5681 | 6673 retval = ltsolve (mattype, b, err, rcond, sing_handler, false); |
5785 | 6674 else if (typ == MatrixType::Banded || typ == MatrixType::Banded_Hermitian) |
5681 | 6675 retval = bsolve (mattype, b, err, rcond, sing_handler, false); |
5785 | 6676 else if (typ == MatrixType::Tridiagonal || |
6677 typ == MatrixType::Tridiagonal_Hermitian) | |
5681 | 6678 retval = trisolve (mattype, b, err, rcond, sing_handler, false); |
5785 | 6679 else if (typ == MatrixType::Full || typ == MatrixType::Hermitian) |
5681 | 6680 retval = fsolve (mattype, b, err, rcond, sing_handler, true); |
5785 | 6681 else if (typ != MatrixType::Rectangular) |
5164 | 6682 { |
5681 | 6683 (*current_liboctave_error_handler) ("unknown matrix type"); |
5164 | 6684 return ComplexMatrix (); |
6685 } | |
5681 | 6686 |
5785 | 6687 if (singular_fallback && mattype.type(false) == MatrixType::Rectangular) |
5681 | 6688 { |
6689 rcond = 1.; | |
6690 #ifdef USE_QRSOLVE | |
6691 retval = qrsolve (*this, b, err); | |
6692 #else | |
6693 retval = dmsolve<ComplexMatrix, SparseComplexMatrix, | |
6694 Matrix> (*this, b, err); | |
6695 #endif | |
6696 } | |
6697 | |
6698 return retval; | |
5164 | 6699 } |
6700 | |
6701 SparseComplexMatrix | |
5785 | 6702 SparseComplexMatrix::solve (MatrixType &mattype, const SparseMatrix& b) const |
5164 | 6703 { |
5275 | 6704 octave_idx_type info; |
5164 | 6705 double rcond; |
6706 return solve (mattype, b, info, rcond, 0); | |
6707 } | |
6708 | |
6709 SparseComplexMatrix | |
5785 | 6710 SparseComplexMatrix::solve (MatrixType &mattype, const SparseMatrix& b, |
5275 | 6711 octave_idx_type& info) const |
5164 | 6712 { |
6713 double rcond; | |
6714 return solve (mattype, b, info, rcond, 0); | |
6715 } | |
6716 | |
6717 SparseComplexMatrix | |
5785 | 6718 SparseComplexMatrix::solve (MatrixType &mattype, const SparseMatrix& b, |
5275 | 6719 octave_idx_type& info, double& rcond) const |
5164 | 6720 { |
6721 return solve (mattype, b, info, rcond, 0); | |
6722 } | |
6723 | |
6724 SparseComplexMatrix | |
5785 | 6725 SparseComplexMatrix::solve (MatrixType &mattype, const SparseMatrix& b, |
5275 | 6726 octave_idx_type& err, double& rcond, |
5697 | 6727 solve_singularity_handler sing_handler, |
6728 bool singular_fallback) const | |
5164 | 6729 { |
5681 | 6730 SparseComplexMatrix retval; |
5322 | 6731 int typ = mattype.type (false); |
5164 | 6732 |
5785 | 6733 if (typ == MatrixType::Unknown) |
5164 | 6734 typ = mattype.type (*this); |
6735 | |
5785 | 6736 if (typ == MatrixType::Diagonal || typ == MatrixType::Permuted_Diagonal) |
5681 | 6737 retval = dsolve (mattype, b, err, rcond, sing_handler, false); |
5785 | 6738 else if (typ == MatrixType::Upper || typ == MatrixType::Permuted_Upper) |
5681 | 6739 retval = utsolve (mattype, b, err, rcond, sing_handler, false); |
5785 | 6740 else if (typ == MatrixType::Lower || typ == MatrixType::Permuted_Lower) |
5681 | 6741 retval = ltsolve (mattype, b, err, rcond, sing_handler, false); |
5785 | 6742 else if (typ == MatrixType::Banded || typ == MatrixType::Banded_Hermitian) |
5681 | 6743 retval = bsolve (mattype, b, err, rcond, sing_handler, false); |
5785 | 6744 else if (typ == MatrixType::Tridiagonal || |
6745 typ == MatrixType::Tridiagonal_Hermitian) | |
5681 | 6746 retval = trisolve (mattype, b, err, rcond, sing_handler, false); |
5785 | 6747 else if (typ == MatrixType::Full || typ == MatrixType::Hermitian) |
5681 | 6748 retval = fsolve (mattype, b, err, rcond, sing_handler, true); |
5785 | 6749 else if (typ != MatrixType::Rectangular) |
5164 | 6750 { |
5681 | 6751 (*current_liboctave_error_handler) ("unknown matrix type"); |
5164 | 6752 return SparseComplexMatrix (); |
6753 } | |
5681 | 6754 |
5785 | 6755 if (singular_fallback && mattype.type(false) == MatrixType::Rectangular) |
5681 | 6756 { |
6757 rcond = 1.; | |
6758 #ifdef USE_QRSOLVE | |
6759 retval = qrsolve (*this, b, err); | |
6760 #else | |
6761 retval = dmsolve<SparseComplexMatrix, SparseComplexMatrix, | |
6762 SparseMatrix> (*this, b, err); | |
6763 #endif | |
6764 } | |
6765 | |
6766 return retval; | |
5164 | 6767 } |
6768 | |
6769 ComplexMatrix | |
5785 | 6770 SparseComplexMatrix::solve (MatrixType &mattype, const ComplexMatrix& b) const |
5164 | 6771 { |
5275 | 6772 octave_idx_type info; |
5164 | 6773 double rcond; |
6774 return solve (mattype, b, info, rcond, 0); | |
6775 } | |
6776 | |
6777 ComplexMatrix | |
5785 | 6778 SparseComplexMatrix::solve (MatrixType &mattype, const ComplexMatrix& b, |
5275 | 6779 octave_idx_type& info) const |
5164 | 6780 { |
6781 double rcond; | |
6782 return solve (mattype, b, info, rcond, 0); | |
6783 } | |
6784 | |
6785 ComplexMatrix | |
5785 | 6786 SparseComplexMatrix::solve (MatrixType &mattype, const ComplexMatrix& b, |
5697 | 6787 octave_idx_type& info, double& rcond) const |
5164 | 6788 { |
6789 return solve (mattype, b, info, rcond, 0); | |
6790 } | |
6791 | |
6792 ComplexMatrix | |
5785 | 6793 SparseComplexMatrix::solve (MatrixType &mattype, const ComplexMatrix& b, |
5697 | 6794 octave_idx_type& err, double& rcond, |
6795 solve_singularity_handler sing_handler, | |
6796 bool singular_fallback) const | |
5164 | 6797 { |
5681 | 6798 ComplexMatrix retval; |
5322 | 6799 int typ = mattype.type (false); |
5164 | 6800 |
5785 | 6801 if (typ == MatrixType::Unknown) |
5164 | 6802 typ = mattype.type (*this); |
6803 | |
5785 | 6804 if (typ == MatrixType::Diagonal || typ == MatrixType::Permuted_Diagonal) |
5681 | 6805 retval = dsolve (mattype, b, err, rcond, sing_handler, false); |
5785 | 6806 else if (typ == MatrixType::Upper || typ == MatrixType::Permuted_Upper) |
5681 | 6807 retval = utsolve (mattype, b, err, rcond, sing_handler, false); |
5785 | 6808 else if (typ == MatrixType::Lower || typ == MatrixType::Permuted_Lower) |
5681 | 6809 retval = ltsolve (mattype, b, err, rcond, sing_handler, false); |
5785 | 6810 else if (typ == MatrixType::Banded || typ == MatrixType::Banded_Hermitian) |
5681 | 6811 retval = bsolve (mattype, b, err, rcond, sing_handler, false); |
5785 | 6812 else if (typ == MatrixType::Tridiagonal || |
6813 typ == MatrixType::Tridiagonal_Hermitian) | |
5681 | 6814 retval = trisolve (mattype, b, err, rcond, sing_handler, false); |
5785 | 6815 else if (typ == MatrixType::Full || typ == MatrixType::Hermitian) |
5681 | 6816 retval = fsolve (mattype, b, err, rcond, sing_handler, true); |
5785 | 6817 else if (typ != MatrixType::Rectangular) |
5164 | 6818 { |
5681 | 6819 (*current_liboctave_error_handler) ("unknown matrix type"); |
5164 | 6820 return ComplexMatrix (); |
6821 } | |
5681 | 6822 |
5785 | 6823 if (singular_fallback && mattype.type(false) == MatrixType::Rectangular) |
5681 | 6824 { |
6825 rcond = 1.; | |
6826 #ifdef USE_QRSOLVE | |
6827 retval = qrsolve (*this, b, err); | |
6828 #else | |
6829 retval = dmsolve<ComplexMatrix, SparseComplexMatrix, | |
6830 ComplexMatrix> (*this, b, err); | |
6831 #endif | |
6832 } | |
6833 | |
6834 return retval; | |
5164 | 6835 } |
6836 | |
6837 SparseComplexMatrix | |
5785 | 6838 SparseComplexMatrix::solve (MatrixType &mattype, |
5164 | 6839 const SparseComplexMatrix& b) const |
6840 { | |
5275 | 6841 octave_idx_type info; |
5164 | 6842 double rcond; |
6843 return solve (mattype, b, info, rcond, 0); | |
6844 } | |
6845 | |
6846 SparseComplexMatrix | |
5785 | 6847 SparseComplexMatrix::solve (MatrixType &mattype, const SparseComplexMatrix& b, |
5697 | 6848 octave_idx_type& info) const |
5164 | 6849 { |
6850 double rcond; | |
6851 return solve (mattype, b, info, rcond, 0); | |
6852 } | |
6853 | |
6854 SparseComplexMatrix | |
5785 | 6855 SparseComplexMatrix::solve (MatrixType &mattype, const SparseComplexMatrix& b, |
5697 | 6856 octave_idx_type& info, double& rcond) const |
5164 | 6857 { |
6858 return solve (mattype, b, info, rcond, 0); | |
6859 } | |
6860 | |
6861 SparseComplexMatrix | |
5785 | 6862 SparseComplexMatrix::solve (MatrixType &mattype, const SparseComplexMatrix& b, |
5275 | 6863 octave_idx_type& err, double& rcond, |
5697 | 6864 solve_singularity_handler sing_handler, |
6865 bool singular_fallback) const | |
5164 | 6866 { |
5681 | 6867 SparseComplexMatrix retval; |
5322 | 6868 int typ = mattype.type (false); |
5164 | 6869 |
5785 | 6870 if (typ == MatrixType::Unknown) |
5164 | 6871 typ = mattype.type (*this); |
6872 | |
5785 | 6873 if (typ == MatrixType::Diagonal || typ == MatrixType::Permuted_Diagonal) |
5681 | 6874 retval = dsolve (mattype, b, err, rcond, sing_handler, false); |
5785 | 6875 else if (typ == MatrixType::Upper || typ == MatrixType::Permuted_Upper) |
5681 | 6876 retval = utsolve (mattype, b, err, rcond, sing_handler, false); |
5785 | 6877 else if (typ == MatrixType::Lower || typ == MatrixType::Permuted_Lower) |
5681 | 6878 retval = ltsolve (mattype, b, err, rcond, sing_handler, false); |
5785 | 6879 else if (typ == MatrixType::Banded || typ == MatrixType::Banded_Hermitian) |
5681 | 6880 retval = bsolve (mattype, b, err, rcond, sing_handler, false); |
5785 | 6881 else if (typ == MatrixType::Tridiagonal || |
6882 typ == MatrixType::Tridiagonal_Hermitian) | |
5681 | 6883 retval = trisolve (mattype, b, err, rcond, sing_handler, false); |
5785 | 6884 else if (typ == MatrixType::Full || typ == MatrixType::Hermitian) |
5681 | 6885 retval = fsolve (mattype, b, err, rcond, sing_handler, true); |
5785 | 6886 else if (typ != MatrixType::Rectangular) |
5164 | 6887 { |
5681 | 6888 (*current_liboctave_error_handler) ("unknown matrix type"); |
5164 | 6889 return SparseComplexMatrix (); |
6890 } | |
5681 | 6891 |
5785 | 6892 if (singular_fallback && mattype.type(false) == MatrixType::Rectangular) |
5681 | 6893 { |
6894 rcond = 1.; | |
6895 #ifdef USE_QRSOLVE | |
6896 retval = qrsolve (*this, b, err); | |
6897 #else | |
6898 retval = dmsolve<SparseComplexMatrix, SparseComplexMatrix, | |
6899 SparseComplexMatrix> (*this, b, err); | |
6900 #endif | |
6901 } | |
6902 | |
6903 return retval; | |
5164 | 6904 } |
6905 | |
6906 ComplexColumnVector | |
5785 | 6907 SparseComplexMatrix::solve (MatrixType &mattype, const ColumnVector& b) const |
5164 | 6908 { |
5275 | 6909 octave_idx_type info; double rcond; |
5164 | 6910 return solve (mattype, b, info, rcond); |
6911 } | |
6912 | |
6913 ComplexColumnVector | |
5785 | 6914 SparseComplexMatrix::solve (MatrixType &mattype, const ColumnVector& b, |
5275 | 6915 octave_idx_type& info) const |
5164 | 6916 { |
6917 double rcond; | |
6918 return solve (mattype, b, info, rcond); | |
6919 } | |
6920 | |
6921 ComplexColumnVector | |
5785 | 6922 SparseComplexMatrix::solve (MatrixType &mattype, const ColumnVector& b, |
5275 | 6923 octave_idx_type& info, double& rcond) const |
5164 | 6924 { |
6925 return solve (mattype, b, info, rcond, 0); | |
6926 } | |
6927 | |
6928 ComplexColumnVector | |
5785 | 6929 SparseComplexMatrix::solve (MatrixType &mattype, const ColumnVector& b, |
5275 | 6930 octave_idx_type& info, double& rcond, |
5164 | 6931 solve_singularity_handler sing_handler) const |
6932 { | |
6933 Matrix tmp (b); | |
5275 | 6934 return solve (mattype, tmp, info, rcond, sing_handler).column (static_cast<octave_idx_type> (0)); |
5164 | 6935 } |
6936 | |
6937 ComplexColumnVector | |
5785 | 6938 SparseComplexMatrix::solve (MatrixType &mattype, |
5164 | 6939 const ComplexColumnVector& b) const |
6940 { | |
5275 | 6941 octave_idx_type info; |
5164 | 6942 double rcond; |
6943 return solve (mattype, b, info, rcond, 0); | |
6944 } | |
6945 | |
6946 ComplexColumnVector | |
5785 | 6947 SparseComplexMatrix::solve (MatrixType &mattype, const ComplexColumnVector& b, |
5275 | 6948 octave_idx_type& info) const |
5164 | 6949 { |
6950 double rcond; | |
6951 return solve (mattype, b, info, rcond, 0); | |
6952 } | |
6953 | |
6954 ComplexColumnVector | |
5785 | 6955 SparseComplexMatrix::solve (MatrixType &mattype, const ComplexColumnVector& b, |
5275 | 6956 octave_idx_type& info, double& rcond) const |
5164 | 6957 { |
6958 return solve (mattype, b, info, rcond, 0); | |
6959 } | |
6960 | |
6961 ComplexColumnVector | |
5785 | 6962 SparseComplexMatrix::solve (MatrixType &mattype, const ComplexColumnVector& b, |
5275 | 6963 octave_idx_type& info, double& rcond, |
5164 | 6964 solve_singularity_handler sing_handler) const |
6965 { | |
6966 ComplexMatrix tmp (b); | |
5275 | 6967 return solve (mattype, tmp, info, rcond, sing_handler).column (static_cast<octave_idx_type> (0)); |
5164 | 6968 } |
6969 | |
6970 ComplexMatrix | |
6971 SparseComplexMatrix::solve (const Matrix& b) const | |
6972 { | |
5275 | 6973 octave_idx_type info; |
5164 | 6974 double rcond; |
6975 return solve (b, info, rcond, 0); | |
6976 } | |
6977 | |
6978 ComplexMatrix | |
5275 | 6979 SparseComplexMatrix::solve (const Matrix& b, octave_idx_type& info) const |
5164 | 6980 { |
6981 double rcond; | |
6982 return solve (b, info, rcond, 0); | |
6983 } | |
6984 | |
6985 ComplexMatrix | |
5275 | 6986 SparseComplexMatrix::solve (const Matrix& b, octave_idx_type& info, |
5164 | 6987 double& rcond) const |
6988 { | |
6989 return solve (b, info, rcond, 0); | |
6990 } | |
6991 | |
6992 ComplexMatrix | |
5275 | 6993 SparseComplexMatrix::solve (const Matrix& b, octave_idx_type& err, |
5164 | 6994 double& rcond, |
6995 solve_singularity_handler sing_handler) const | |
6996 { | |
5785 | 6997 MatrixType mattype (*this); |
5164 | 6998 return solve (mattype, b, err, rcond, sing_handler); |
6999 } | |
7000 | |
7001 SparseComplexMatrix | |
7002 SparseComplexMatrix::solve (const SparseMatrix& b) const | |
7003 { | |
5275 | 7004 octave_idx_type info; |
5164 | 7005 double rcond; |
7006 return solve (b, info, rcond, 0); | |
7007 } | |
7008 | |
7009 SparseComplexMatrix | |
7010 SparseComplexMatrix::solve (const SparseMatrix& b, | |
5275 | 7011 octave_idx_type& info) const |
5164 | 7012 { |
7013 double rcond; | |
7014 return solve (b, info, rcond, 0); | |
7015 } | |
7016 | |
7017 SparseComplexMatrix | |
7018 SparseComplexMatrix::solve (const SparseMatrix& b, | |
5275 | 7019 octave_idx_type& info, double& rcond) const |
5164 | 7020 { |
7021 return solve (b, info, rcond, 0); | |
7022 } | |
7023 | |
7024 SparseComplexMatrix | |
7025 SparseComplexMatrix::solve (const SparseMatrix& b, | |
5275 | 7026 octave_idx_type& err, double& rcond, |
5164 | 7027 solve_singularity_handler sing_handler) const |
7028 { | |
5785 | 7029 MatrixType mattype (*this); |
5164 | 7030 return solve (mattype, b, err, rcond, sing_handler); |
7031 } | |
7032 | |
7033 ComplexMatrix | |
7034 SparseComplexMatrix::solve (const ComplexMatrix& b, | |
5275 | 7035 octave_idx_type& info) const |
5164 | 7036 { |
7037 double rcond; | |
7038 return solve (b, info, rcond, 0); | |
7039 } | |
7040 | |
7041 ComplexMatrix | |
7042 SparseComplexMatrix::solve (const ComplexMatrix& b, | |
5275 | 7043 octave_idx_type& info, double& rcond) const |
5164 | 7044 { |
7045 return solve (b, info, rcond, 0); | |
7046 } | |
7047 | |
7048 ComplexMatrix | |
7049 SparseComplexMatrix::solve (const ComplexMatrix& b, | |
5275 | 7050 octave_idx_type& err, double& rcond, |
5164 | 7051 solve_singularity_handler sing_handler) const |
7052 { | |
5785 | 7053 MatrixType mattype (*this); |
5164 | 7054 return solve (mattype, b, err, rcond, sing_handler); |
7055 } | |
7056 | |
7057 SparseComplexMatrix | |
7058 SparseComplexMatrix::solve (const SparseComplexMatrix& b) const | |
7059 { | |
5275 | 7060 octave_idx_type info; |
5164 | 7061 double rcond; |
7062 return solve (b, info, rcond, 0); | |
7063 } | |
7064 | |
7065 SparseComplexMatrix | |
7066 SparseComplexMatrix::solve (const SparseComplexMatrix& b, | |
5275 | 7067 octave_idx_type& info) const |
5164 | 7068 { |
7069 double rcond; | |
7070 return solve (b, info, rcond, 0); | |
7071 } | |
7072 | |
7073 SparseComplexMatrix | |
7074 SparseComplexMatrix::solve (const SparseComplexMatrix& b, | |
5275 | 7075 octave_idx_type& info, double& rcond) const |
5164 | 7076 { |
7077 return solve (b, info, rcond, 0); | |
7078 } | |
7079 | |
7080 SparseComplexMatrix | |
7081 SparseComplexMatrix::solve (const SparseComplexMatrix& b, | |
5275 | 7082 octave_idx_type& err, double& rcond, |
5164 | 7083 solve_singularity_handler sing_handler) const |
7084 { | |
5785 | 7085 MatrixType mattype (*this); |
5164 | 7086 return solve (mattype, b, err, rcond, sing_handler); |
7087 } | |
7088 | |
7089 ComplexColumnVector | |
7090 SparseComplexMatrix::solve (const ColumnVector& b) const | |
7091 { | |
5275 | 7092 octave_idx_type info; double rcond; |
5164 | 7093 return solve (b, info, rcond); |
7094 } | |
7095 | |
7096 ComplexColumnVector | |
5275 | 7097 SparseComplexMatrix::solve (const ColumnVector& b, octave_idx_type& info) const |
5164 | 7098 { |
7099 double rcond; | |
7100 return solve (b, info, rcond); | |
7101 } | |
7102 | |
7103 ComplexColumnVector | |
5275 | 7104 SparseComplexMatrix::solve (const ColumnVector& b, octave_idx_type& info, |
5164 | 7105 double& rcond) const |
7106 { | |
7107 return solve (b, info, rcond, 0); | |
7108 } | |
7109 | |
7110 ComplexColumnVector | |
5275 | 7111 SparseComplexMatrix::solve (const ColumnVector& b, octave_idx_type& info, double& rcond, |
5164 | 7112 solve_singularity_handler sing_handler) const |
7113 { | |
7114 Matrix tmp (b); | |
5275 | 7115 return solve (tmp, info, rcond, sing_handler).column (static_cast<octave_idx_type> (0)); |
5164 | 7116 } |
7117 | |
7118 ComplexColumnVector | |
7119 SparseComplexMatrix::solve (const ComplexColumnVector& b) const | |
7120 { | |
5275 | 7121 octave_idx_type info; |
5164 | 7122 double rcond; |
7123 return solve (b, info, rcond, 0); | |
7124 } | |
7125 | |
7126 ComplexColumnVector | |
5275 | 7127 SparseComplexMatrix::solve (const ComplexColumnVector& b, octave_idx_type& info) const |
5164 | 7128 { |
7129 double rcond; | |
7130 return solve (b, info, rcond, 0); | |
7131 } | |
7132 | |
7133 ComplexColumnVector | |
5275 | 7134 SparseComplexMatrix::solve (const ComplexColumnVector& b, octave_idx_type& info, |
5164 | 7135 double& rcond) const |
7136 { | |
7137 return solve (b, info, rcond, 0); | |
7138 } | |
7139 | |
7140 ComplexColumnVector | |
5275 | 7141 SparseComplexMatrix::solve (const ComplexColumnVector& b, octave_idx_type& info, |
5164 | 7142 double& rcond, |
7143 solve_singularity_handler sing_handler) const | |
7144 { | |
7145 ComplexMatrix tmp (b); | |
5275 | 7146 return solve (tmp, info, rcond, sing_handler).column (static_cast<octave_idx_type> (0)); |
5164 | 7147 } |
7148 | |
7149 // unary operations | |
7150 SparseBoolMatrix | |
7151 SparseComplexMatrix::operator ! (void) const | |
7152 { | |
5275 | 7153 octave_idx_type nr = rows (); |
7154 octave_idx_type nc = cols (); | |
5681 | 7155 octave_idx_type nz1 = nnz (); |
5275 | 7156 octave_idx_type nz2 = nr*nc - nz1; |
5164 | 7157 |
7158 SparseBoolMatrix r (nr, nc, nz2); | |
7159 | |
5275 | 7160 octave_idx_type ii = 0; |
7161 octave_idx_type jj = 0; | |
5164 | 7162 r.cidx (0) = 0; |
5275 | 7163 for (octave_idx_type i = 0; i < nc; i++) |
5164 | 7164 { |
5275 | 7165 for (octave_idx_type j = 0; j < nr; j++) |
5164 | 7166 { |
7167 if (jj < cidx(i+1) && ridx(jj) == j) | |
7168 jj++; | |
7169 else | |
7170 { | |
7171 r.data(ii) = true; | |
7172 r.ridx(ii++) = j; | |
7173 } | |
7174 } | |
7175 r.cidx (i+1) = ii; | |
7176 } | |
7177 | |
7178 return r; | |
7179 } | |
7180 | |
7181 SparseComplexMatrix | |
7182 SparseComplexMatrix::squeeze (void) const | |
7183 { | |
7184 return MSparse<Complex>::squeeze (); | |
7185 } | |
7186 | |
7187 SparseComplexMatrix | |
7188 SparseComplexMatrix::index (idx_vector& i, int resize_ok) const | |
7189 { | |
7190 return MSparse<Complex>::index (i, resize_ok); | |
7191 } | |
7192 | |
7193 SparseComplexMatrix | |
7194 SparseComplexMatrix::index (idx_vector& i, idx_vector& j, int resize_ok) const | |
7195 { | |
7196 return MSparse<Complex>::index (i, j, resize_ok); | |
7197 } | |
7198 | |
7199 SparseComplexMatrix | |
7200 SparseComplexMatrix::index (Array<idx_vector>& ra_idx, int resize_ok) const | |
7201 { | |
7202 return MSparse<Complex>::index (ra_idx, resize_ok); | |
7203 } | |
7204 SparseComplexMatrix | |
7205 SparseComplexMatrix::reshape (const dim_vector& new_dims) const | |
7206 { | |
7207 return MSparse<Complex>::reshape (new_dims); | |
7208 } | |
7209 | |
7210 SparseComplexMatrix | |
5275 | 7211 SparseComplexMatrix::permute (const Array<octave_idx_type>& vec, bool inv) const |
5164 | 7212 { |
7213 return MSparse<Complex>::permute (vec, inv); | |
7214 } | |
7215 | |
7216 SparseComplexMatrix | |
5275 | 7217 SparseComplexMatrix::ipermute (const Array<octave_idx_type>& vec) const |
5164 | 7218 { |
7219 return MSparse<Complex>::ipermute (vec); | |
7220 } | |
7221 | |
7222 // other operations | |
7223 | |
7224 bool | |
7922
935be827eaf8
error for NaN values in & and | expressions
John W. Eaton <jwe@octave.org>
parents:
7802
diff
changeset
|
7225 SparseComplexMatrix::any_element_is_nan (void) const |
935be827eaf8
error for NaN values in & and | expressions
John W. Eaton <jwe@octave.org>
parents:
7802
diff
changeset
|
7226 { |
935be827eaf8
error for NaN values in & and | expressions
John W. Eaton <jwe@octave.org>
parents:
7802
diff
changeset
|
7227 octave_idx_type nel = nnz (); |
935be827eaf8
error for NaN values in & and | expressions
John W. Eaton <jwe@octave.org>
parents:
7802
diff
changeset
|
7228 |
935be827eaf8
error for NaN values in & and | expressions
John W. Eaton <jwe@octave.org>
parents:
7802
diff
changeset
|
7229 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
|
7230 { |
935be827eaf8
error for NaN values in & and | expressions
John W. Eaton <jwe@octave.org>
parents:
7802
diff
changeset
|
7231 Complex val = data (i); |
935be827eaf8
error for NaN values in & and | expressions
John W. Eaton <jwe@octave.org>
parents:
7802
diff
changeset
|
7232 if (xisnan (val)) |
935be827eaf8
error for NaN values in & and | expressions
John W. Eaton <jwe@octave.org>
parents:
7802
diff
changeset
|
7233 return true; |
935be827eaf8
error for NaN values in & and | expressions
John W. Eaton <jwe@octave.org>
parents:
7802
diff
changeset
|
7234 } |
935be827eaf8
error for NaN values in & and | expressions
John W. Eaton <jwe@octave.org>
parents:
7802
diff
changeset
|
7235 |
935be827eaf8
error for NaN values in & and | expressions
John W. Eaton <jwe@octave.org>
parents:
7802
diff
changeset
|
7236 return false; |
935be827eaf8
error for NaN values in & and | expressions
John W. Eaton <jwe@octave.org>
parents:
7802
diff
changeset
|
7237 } |
935be827eaf8
error for NaN values in & and | expressions
John W. Eaton <jwe@octave.org>
parents:
7802
diff
changeset
|
7238 |
935be827eaf8
error for NaN values in & and | expressions
John W. Eaton <jwe@octave.org>
parents:
7802
diff
changeset
|
7239 bool |
5164 | 7240 SparseComplexMatrix::any_element_is_inf_or_nan (void) const |
7241 { | |
5681 | 7242 octave_idx_type nel = nnz (); |
5275 | 7243 |
7244 for (octave_idx_type i = 0; i < nel; i++) | |
5164 | 7245 { |
7246 Complex val = data (i); | |
7247 if (xisinf (val) || xisnan (val)) | |
7248 return true; | |
7249 } | |
7250 | |
7251 return false; | |
7252 } | |
7253 | |
7254 // Return true if no elements have imaginary components. | |
7255 | |
7256 bool | |
7257 SparseComplexMatrix::all_elements_are_real (void) const | |
7258 { | |
5681 | 7259 octave_idx_type nel = nnz (); |
5275 | 7260 |
7261 for (octave_idx_type i = 0; i < nel; i++) | |
5164 | 7262 { |
5261 | 7263 double ip = std::imag (data (i)); |
5164 | 7264 |
7265 if (ip != 0.0 || lo_ieee_signbit (ip)) | |
7266 return false; | |
7267 } | |
7268 | |
7269 return true; | |
7270 } | |
7271 | |
7272 // Return nonzero if any element of CM has a non-integer real or | |
7273 // imaginary part. Also extract the largest and smallest (real or | |
7274 // imaginary) values and return them in MAX_VAL and MIN_VAL. | |
7275 | |
7276 bool | |
7277 SparseComplexMatrix::all_integers (double& max_val, double& min_val) const | |
7278 { | |
5681 | 7279 octave_idx_type nel = nnz (); |
5164 | 7280 |
7281 if (nel == 0) | |
7282 return false; | |
7283 | |
5261 | 7284 max_val = std::real(data (0)); |
7285 min_val = std::real(data (0)); | |
5164 | 7286 |
5275 | 7287 for (octave_idx_type i = 0; i < nel; i++) |
5164 | 7288 { |
7289 Complex val = data (i); | |
7290 | |
5261 | 7291 double r_val = std::real (val); |
7292 double i_val = std::imag (val); | |
5164 | 7293 |
7294 if (r_val > max_val) | |
7295 max_val = r_val; | |
7296 | |
7297 if (i_val > max_val) | |
7298 max_val = i_val; | |
7299 | |
7300 if (r_val < min_val) | |
7301 min_val = r_val; | |
7302 | |
7303 if (i_val < min_val) | |
7304 min_val = i_val; | |
7305 | |
7306 if (D_NINT (r_val) != r_val || D_NINT (i_val) != i_val) | |
7307 return false; | |
7308 } | |
7309 | |
7310 return true; | |
7311 } | |
7312 | |
7313 bool | |
7314 SparseComplexMatrix::too_large_for_float (void) const | |
7315 { | |
5681 | 7316 octave_idx_type nel = nnz (); |
5275 | 7317 |
7318 for (octave_idx_type i = 0; i < nel; i++) | |
5164 | 7319 { |
7320 Complex val = data (i); | |
7321 | |
5261 | 7322 double r_val = std::real (val); |
7323 double i_val = std::imag (val); | |
5164 | 7324 |
7325 if (r_val > FLT_MAX | |
7326 || i_val > FLT_MAX | |
7327 || r_val < FLT_MIN | |
7328 || i_val < FLT_MIN) | |
7329 return true; | |
7330 } | |
7331 | |
7332 return false; | |
7333 } | |
7334 | |
5775 | 7335 // FIXME Do these really belong here? Maybe they should be |
5164 | 7336 // in a base class? |
7337 | |
7338 SparseBoolMatrix | |
7339 SparseComplexMatrix::all (int dim) const | |
7340 { | |
7341 SPARSE_ALL_OP (dim); | |
7342 } | |
7343 | |
7344 SparseBoolMatrix | |
7345 SparseComplexMatrix::any (int dim) const | |
7346 { | |
7347 SPARSE_ANY_OP (dim); | |
7348 } | |
7349 | |
7350 SparseComplexMatrix | |
7351 SparseComplexMatrix::cumprod (int dim) const | |
7352 { | |
7353 SPARSE_CUMPROD (SparseComplexMatrix, Complex, cumprod); | |
7354 } | |
7355 | |
7356 SparseComplexMatrix | |
7357 SparseComplexMatrix::cumsum (int dim) const | |
7358 { | |
7359 SPARSE_CUMSUM (SparseComplexMatrix, Complex, cumsum); | |
7360 } | |
7361 | |
7362 SparseComplexMatrix | |
7363 SparseComplexMatrix::prod (int dim) const | |
7364 { | |
7269 | 7365 if ((rows() == 1 && dim == -1) || dim == 1) |
7366 return transpose (). prod (0). transpose(); | |
7367 else | |
7368 { | |
7369 SPARSE_REDUCTION_OP (SparseComplexMatrix, Complex, *=, | |
7370 (cidx(j+1) - cidx(j) < nc ? 0.0 : 1.0), 1.0); | |
7371 } | |
5164 | 7372 } |
7373 | |
7374 SparseComplexMatrix | |
7375 SparseComplexMatrix::sum (int dim) const | |
7376 { | |
7377 SPARSE_REDUCTION_OP (SparseComplexMatrix, Complex, +=, 0.0, 0.0); | |
7378 } | |
7379 | |
7380 SparseComplexMatrix | |
7381 SparseComplexMatrix::sumsq (int dim) const | |
7382 { | |
7383 #define ROW_EXPR \ | |
7269 | 7384 Complex d = data (i); \ |
7385 tmp [ridx(i)] += d * conj (d) | |
5164 | 7386 |
7387 #define COL_EXPR \ | |
7269 | 7388 Complex d = data (i); \ |
5164 | 7389 tmp [j] += d * conj (d) |
7390 | |
7391 SPARSE_BASE_REDUCTION_OP (SparseComplexMatrix, Complex, ROW_EXPR, | |
7392 COL_EXPR, 0.0, 0.0); | |
7393 | |
7394 #undef ROW_EXPR | |
7395 #undef COL_EXPR | |
7396 } | |
7397 | |
7398 SparseMatrix SparseComplexMatrix::abs (void) const | |
7399 { | |
5681 | 7400 octave_idx_type nz = nnz (); |
5275 | 7401 octave_idx_type nc = cols (); |
5164 | 7402 |
7403 SparseMatrix retval (rows(), nc, nz); | |
7404 | |
5275 | 7405 for (octave_idx_type i = 0; i < nc + 1; i++) |
5164 | 7406 retval.cidx (i) = cidx (i); |
7407 | |
5275 | 7408 for (octave_idx_type i = 0; i < nz; i++) |
5164 | 7409 { |
5261 | 7410 retval.data (i) = std::abs (data (i)); |
5164 | 7411 retval.ridx (i) = ridx (i); |
7412 } | |
7413 | |
7414 return retval; | |
7415 } | |
7416 | |
7417 SparseComplexMatrix | |
5275 | 7418 SparseComplexMatrix::diag (octave_idx_type k) const |
5164 | 7419 { |
7620
36594d5bbe13
Move diag function into the octave_value class
David Bateman <dbateman@free.fr>
parents:
7602
diff
changeset
|
7420 return MSparse<Complex>::diag (k); |
5164 | 7421 } |
7422 | |
7503
8c32f95c2639
convert mapper functions to new format
David Bateman <dbateman@free.fr>
parents:
7482
diff
changeset
|
7423 SparseMatrix |
8c32f95c2639
convert mapper functions to new format
David Bateman <dbateman@free.fr>
parents:
7482
diff
changeset
|
7424 SparseComplexMatrix::map (dmapper fcn) const |
8c32f95c2639
convert mapper functions to new format
David Bateman <dbateman@free.fr>
parents:
7482
diff
changeset
|
7425 { |
7602
7bfaa9611558
Rewrite sparse mappers in terms of a functor template function
David Bateman <dbateman@free.fr>
parents:
7520
diff
changeset
|
7426 return MSparse<Complex>::map<double> (func_ptr (fcn)); |
7503
8c32f95c2639
convert mapper functions to new format
David Bateman <dbateman@free.fr>
parents:
7482
diff
changeset
|
7427 } |
8c32f95c2639
convert mapper functions to new format
David Bateman <dbateman@free.fr>
parents:
7482
diff
changeset
|
7428 |
8c32f95c2639
convert mapper functions to new format
David Bateman <dbateman@free.fr>
parents:
7482
diff
changeset
|
7429 SparseComplexMatrix |
8c32f95c2639
convert mapper functions to new format
David Bateman <dbateman@free.fr>
parents:
7482
diff
changeset
|
7430 SparseComplexMatrix::map (cmapper fcn) const |
8c32f95c2639
convert mapper functions to new format
David Bateman <dbateman@free.fr>
parents:
7482
diff
changeset
|
7431 { |
7602
7bfaa9611558
Rewrite sparse mappers in terms of a functor template function
David Bateman <dbateman@free.fr>
parents:
7520
diff
changeset
|
7432 return MSparse<Complex>::map<Complex> (func_ptr (fcn)); |
7503
8c32f95c2639
convert mapper functions to new format
David Bateman <dbateman@free.fr>
parents:
7482
diff
changeset
|
7433 } |
8c32f95c2639
convert mapper functions to new format
David Bateman <dbateman@free.fr>
parents:
7482
diff
changeset
|
7434 |
8c32f95c2639
convert mapper functions to new format
David Bateman <dbateman@free.fr>
parents:
7482
diff
changeset
|
7435 SparseBoolMatrix |
8c32f95c2639
convert mapper functions to new format
David Bateman <dbateman@free.fr>
parents:
7482
diff
changeset
|
7436 SparseComplexMatrix::map (bmapper fcn) const |
8c32f95c2639
convert mapper functions to new format
David Bateman <dbateman@free.fr>
parents:
7482
diff
changeset
|
7437 { |
7602
7bfaa9611558
Rewrite sparse mappers in terms of a functor template function
David Bateman <dbateman@free.fr>
parents:
7520
diff
changeset
|
7438 return MSparse<Complex>::map<bool> (func_ptr (fcn)); |
7503
8c32f95c2639
convert mapper functions to new format
David Bateman <dbateman@free.fr>
parents:
7482
diff
changeset
|
7439 } |
8c32f95c2639
convert mapper functions to new format
David Bateman <dbateman@free.fr>
parents:
7482
diff
changeset
|
7440 |
5164 | 7441 std::ostream& |
7442 operator << (std::ostream& os, const SparseComplexMatrix& a) | |
7443 { | |
5275 | 7444 octave_idx_type nc = a.cols (); |
5164 | 7445 |
7446 // add one to the printed indices to go from | |
7447 // zero-based to one-based arrays | |
5275 | 7448 for (octave_idx_type j = 0; j < nc; j++) { |
5164 | 7449 OCTAVE_QUIT; |
5275 | 7450 for (octave_idx_type i = a.cidx(j); i < a.cidx(j+1); i++) { |
5164 | 7451 os << a.ridx(i) + 1 << " " << j + 1 << " "; |
7452 octave_write_complex (os, a.data(i)); | |
7453 os << "\n"; | |
7454 } | |
7455 } | |
7456 | |
7457 return os; | |
7458 } | |
7459 | |
7460 std::istream& | |
7461 operator >> (std::istream& is, SparseComplexMatrix& a) | |
7462 { | |
5275 | 7463 octave_idx_type nr = a.rows (); |
7464 octave_idx_type nc = a.cols (); | |
5604 | 7465 octave_idx_type nz = a.nzmax (); |
5164 | 7466 |
7467 if (nr < 1 || nc < 1) | |
7468 is.clear (std::ios::badbit); | |
7469 else | |
7470 { | |
5275 | 7471 octave_idx_type itmp, jtmp, jold = 0; |
5164 | 7472 Complex tmp; |
5275 | 7473 octave_idx_type ii = 0; |
5164 | 7474 |
7475 a.cidx (0) = 0; | |
5275 | 7476 for (octave_idx_type i = 0; i < nz; i++) |
5164 | 7477 { |
7478 is >> itmp; | |
7479 itmp--; | |
7480 is >> jtmp; | |
7481 jtmp--; | |
7482 tmp = octave_read_complex (is); | |
7483 | |
7484 if (is) | |
7485 { | |
7486 if (jold != jtmp) | |
7487 { | |
5275 | 7488 for (octave_idx_type j = jold; j < jtmp; j++) |
5164 | 7489 a.cidx(j+1) = ii; |
7490 | |
7491 jold = jtmp; | |
7492 } | |
7493 a.data (ii) = tmp; | |
7494 a.ridx (ii++) = itmp; | |
7495 } | |
7496 else | |
7497 goto done; | |
7498 } | |
7499 | |
5275 | 7500 for (octave_idx_type j = jold; j < nc; j++) |
5164 | 7501 a.cidx(j+1) = ii; |
7502 } | |
7503 | |
7504 done: | |
7505 | |
7506 return is; | |
7507 } | |
7508 | |
7509 SparseComplexMatrix | |
7510 operator * (const SparseComplexMatrix& m, const SparseMatrix& a) | |
7511 { | |
5681 | 7512 SPARSE_SPARSE_MUL (SparseComplexMatrix, Complex, double); |
5164 | 7513 } |
7514 | |
7515 SparseComplexMatrix | |
7516 operator * (const SparseMatrix& m, const SparseComplexMatrix& a) | |
7517 { | |
5681 | 7518 SPARSE_SPARSE_MUL (SparseComplexMatrix, Complex, Complex); |
5164 | 7519 } |
7520 | |
7521 SparseComplexMatrix | |
7522 operator * (const SparseComplexMatrix& m, const SparseComplexMatrix& a) | |
7523 { | |
5681 | 7524 SPARSE_SPARSE_MUL (SparseComplexMatrix, Complex, Complex); |
5164 | 7525 } |
7526 | |
5429 | 7527 ComplexMatrix |
7528 operator * (const ComplexMatrix& m, const SparseMatrix& a) | |
7529 { | |
5681 | 7530 FULL_SPARSE_MUL (ComplexMatrix, double, Complex (0.,0.)); |
5429 | 7531 } |
7532 | |
7533 ComplexMatrix | |
7534 operator * (const Matrix& m, const SparseComplexMatrix& a) | |
7535 { | |
5681 | 7536 FULL_SPARSE_MUL (ComplexMatrix, Complex, Complex (0.,0.)); |
5429 | 7537 } |
7538 | |
7539 ComplexMatrix | |
7540 operator * (const ComplexMatrix& m, const SparseComplexMatrix& a) | |
7541 { | |
5681 | 7542 FULL_SPARSE_MUL (ComplexMatrix, Complex, Complex (0.,0.)); |
5429 | 7543 } |
7544 | |
7545 ComplexMatrix | |
7802
1a446f28ce68
implement optimized sparse-dense transposed multiplication
Jaroslav Hajek <highegg@gmail.com>
parents:
7620
diff
changeset
|
7546 mul_trans (const ComplexMatrix& m, const SparseComplexMatrix& a) |
1a446f28ce68
implement optimized sparse-dense transposed multiplication
Jaroslav Hajek <highegg@gmail.com>
parents:
7620
diff
changeset
|
7547 { |
1a446f28ce68
implement optimized sparse-dense transposed multiplication
Jaroslav Hajek <highegg@gmail.com>
parents:
7620
diff
changeset
|
7548 FULL_SPARSE_MUL_TRANS (ComplexMatrix, Complex, Complex (0.,0.), ); |
1a446f28ce68
implement optimized sparse-dense transposed multiplication
Jaroslav Hajek <highegg@gmail.com>
parents:
7620
diff
changeset
|
7549 } |
1a446f28ce68
implement optimized sparse-dense transposed multiplication
Jaroslav Hajek <highegg@gmail.com>
parents:
7620
diff
changeset
|
7550 |
1a446f28ce68
implement optimized sparse-dense transposed multiplication
Jaroslav Hajek <highegg@gmail.com>
parents:
7620
diff
changeset
|
7551 ComplexMatrix |
1a446f28ce68
implement optimized sparse-dense transposed multiplication
Jaroslav Hajek <highegg@gmail.com>
parents:
7620
diff
changeset
|
7552 mul_herm (const ComplexMatrix& m, const SparseComplexMatrix& a) |
1a446f28ce68
implement optimized sparse-dense transposed multiplication
Jaroslav Hajek <highegg@gmail.com>
parents:
7620
diff
changeset
|
7553 { |
1a446f28ce68
implement optimized sparse-dense transposed multiplication
Jaroslav Hajek <highegg@gmail.com>
parents:
7620
diff
changeset
|
7554 FULL_SPARSE_MUL_TRANS (ComplexMatrix, Complex, Complex (0.,0.), conj); |
1a446f28ce68
implement optimized sparse-dense transposed multiplication
Jaroslav Hajek <highegg@gmail.com>
parents:
7620
diff
changeset
|
7555 } |
1a446f28ce68
implement optimized sparse-dense transposed multiplication
Jaroslav Hajek <highegg@gmail.com>
parents:
7620
diff
changeset
|
7556 |
1a446f28ce68
implement optimized sparse-dense transposed multiplication
Jaroslav Hajek <highegg@gmail.com>
parents:
7620
diff
changeset
|
7557 ComplexMatrix |
5429 | 7558 operator * (const SparseComplexMatrix& m, const Matrix& a) |
7559 { | |
5681 | 7560 SPARSE_FULL_MUL (ComplexMatrix, double, Complex (0.,0.)); |
5429 | 7561 } |
7562 | |
7563 ComplexMatrix | |
7564 operator * (const SparseMatrix& m, const ComplexMatrix& a) | |
7565 { | |
5681 | 7566 SPARSE_FULL_MUL (ComplexMatrix, Complex, Complex (0.,0.)); |
5429 | 7567 } |
7568 | |
7569 ComplexMatrix | |
7570 operator * (const SparseComplexMatrix& m, const ComplexMatrix& a) | |
7571 { | |
5681 | 7572 SPARSE_FULL_MUL (ComplexMatrix, Complex, Complex (0.,0.)); |
5429 | 7573 } |
7574 | |
7802
1a446f28ce68
implement optimized sparse-dense transposed multiplication
Jaroslav Hajek <highegg@gmail.com>
parents:
7620
diff
changeset
|
7575 ComplexMatrix |
1a446f28ce68
implement optimized sparse-dense transposed multiplication
Jaroslav Hajek <highegg@gmail.com>
parents:
7620
diff
changeset
|
7576 trans_mul (const SparseComplexMatrix& m, const ComplexMatrix& a) |
1a446f28ce68
implement optimized sparse-dense transposed multiplication
Jaroslav Hajek <highegg@gmail.com>
parents:
7620
diff
changeset
|
7577 { |
1a446f28ce68
implement optimized sparse-dense transposed multiplication
Jaroslav Hajek <highegg@gmail.com>
parents:
7620
diff
changeset
|
7578 SPARSE_FULL_TRANS_MUL (ComplexMatrix, Complex, Complex (0.,0.), ); |
1a446f28ce68
implement optimized sparse-dense transposed multiplication
Jaroslav Hajek <highegg@gmail.com>
parents:
7620
diff
changeset
|
7579 } |
1a446f28ce68
implement optimized sparse-dense transposed multiplication
Jaroslav Hajek <highegg@gmail.com>
parents:
7620
diff
changeset
|
7580 |
1a446f28ce68
implement optimized sparse-dense transposed multiplication
Jaroslav Hajek <highegg@gmail.com>
parents:
7620
diff
changeset
|
7581 ComplexMatrix |
1a446f28ce68
implement optimized sparse-dense transposed multiplication
Jaroslav Hajek <highegg@gmail.com>
parents:
7620
diff
changeset
|
7582 herm_mul (const SparseComplexMatrix& m, const ComplexMatrix& a) |
1a446f28ce68
implement optimized sparse-dense transposed multiplication
Jaroslav Hajek <highegg@gmail.com>
parents:
7620
diff
changeset
|
7583 { |
1a446f28ce68
implement optimized sparse-dense transposed multiplication
Jaroslav Hajek <highegg@gmail.com>
parents:
7620
diff
changeset
|
7584 SPARSE_FULL_TRANS_MUL (ComplexMatrix, Complex, Complex (0.,0.), conj); |
1a446f28ce68
implement optimized sparse-dense transposed multiplication
Jaroslav Hajek <highegg@gmail.com>
parents:
7620
diff
changeset
|
7585 } |
1a446f28ce68
implement optimized sparse-dense transposed multiplication
Jaroslav Hajek <highegg@gmail.com>
parents:
7620
diff
changeset
|
7586 |
5775 | 7587 // FIXME -- it would be nice to share code among the min/max |
5164 | 7588 // functions below. |
7589 | |
7590 #define EMPTY_RETURN_CHECK(T) \ | |
7591 if (nr == 0 || nc == 0) \ | |
7592 return T (nr, nc); | |
7593 | |
7594 SparseComplexMatrix | |
7595 min (const Complex& c, const SparseComplexMatrix& m) | |
7596 { | |
7597 SparseComplexMatrix result; | |
7598 | |
5275 | 7599 octave_idx_type nr = m.rows (); |
7600 octave_idx_type nc = m.columns (); | |
5164 | 7601 |
7602 EMPTY_RETURN_CHECK (SparseComplexMatrix); | |
7603 | |
7604 if (abs(c) == 0.) | |
7605 return SparseComplexMatrix (nr, nc); | |
7606 else | |
7607 { | |
7608 result = SparseComplexMatrix (m); | |
7609 | |
5275 | 7610 for (octave_idx_type j = 0; j < nc; j++) |
7611 for (octave_idx_type i = m.cidx(j); i < m.cidx(j+1); i++) | |
5164 | 7612 result.data(i) = xmin(c, m.data(i)); |
7613 } | |
7614 | |
7615 return result; | |
7616 } | |
7617 | |
7618 SparseComplexMatrix | |
7619 min (const SparseComplexMatrix& m, const Complex& c) | |
7620 { | |
7621 return min (c, m); | |
7622 } | |
7623 | |
7624 SparseComplexMatrix | |
7625 min (const SparseComplexMatrix& a, const SparseComplexMatrix& b) | |
7626 { | |
7627 SparseComplexMatrix r; | |
7628 | |
7629 if ((a.rows() == b.rows()) && (a.cols() == b.cols())) | |
7630 { | |
5275 | 7631 octave_idx_type a_nr = a.rows (); |
7632 octave_idx_type a_nc = a.cols (); | |
7633 | |
7634 octave_idx_type b_nr = b.rows (); | |
7635 octave_idx_type b_nc = b.cols (); | |
5164 | 7636 |
5681 | 7637 if (a_nr == 0 || b_nc == 0 || a.nnz () == 0 || b.nnz () == 0) |
5164 | 7638 return SparseComplexMatrix (a_nr, a_nc); |
7639 | |
7640 if (a_nr != b_nr || a_nc != b_nc) | |
7641 gripe_nonconformant ("min", a_nr, a_nc, b_nr, b_nc); | |
7642 else | |
7643 { | |
5681 | 7644 r = SparseComplexMatrix (a_nr, a_nc, (a.nnz () + b.nnz ())); |
5164 | 7645 |
5275 | 7646 octave_idx_type jx = 0; |
5164 | 7647 r.cidx (0) = 0; |
5275 | 7648 for (octave_idx_type i = 0 ; i < a_nc ; i++) |
5164 | 7649 { |
5275 | 7650 octave_idx_type ja = a.cidx(i); |
7651 octave_idx_type ja_max = a.cidx(i+1); | |
5164 | 7652 bool ja_lt_max= ja < ja_max; |
7653 | |
5275 | 7654 octave_idx_type jb = b.cidx(i); |
7655 octave_idx_type jb_max = b.cidx(i+1); | |
5164 | 7656 bool jb_lt_max = jb < jb_max; |
7657 | |
7658 while (ja_lt_max || jb_lt_max ) | |
7659 { | |
7660 OCTAVE_QUIT; | |
7661 if ((! jb_lt_max) || | |
7662 (ja_lt_max && (a.ridx(ja) < b.ridx(jb)))) | |
7663 { | |
7664 Complex tmp = xmin (a.data(ja), 0.); | |
7665 if (tmp != 0.) | |
7666 { | |
7667 r.ridx(jx) = a.ridx(ja); | |
7668 r.data(jx) = tmp; | |
7669 jx++; | |
7670 } | |
7671 ja++; | |
7672 ja_lt_max= ja < ja_max; | |
7673 } | |
7674 else if (( !ja_lt_max ) || | |
7675 (jb_lt_max && (b.ridx(jb) < a.ridx(ja)) ) ) | |
7676 { | |
7677 Complex tmp = xmin (0., b.data(jb)); | |
7678 if (tmp != 0.) | |
7679 { | |
7680 r.ridx(jx) = b.ridx(jb); | |
7681 r.data(jx) = tmp; | |
7682 jx++; | |
7683 } | |
7684 jb++; | |
7685 jb_lt_max= jb < jb_max; | |
7686 } | |
7687 else | |
7688 { | |
7689 Complex tmp = xmin (a.data(ja), b.data(jb)); | |
7690 if (tmp != 0.) | |
7691 { | |
7692 r.data(jx) = tmp; | |
7693 r.ridx(jx) = a.ridx(ja); | |
7694 jx++; | |
7695 } | |
7696 ja++; | |
7697 ja_lt_max= ja < ja_max; | |
7698 jb++; | |
7699 jb_lt_max= jb < jb_max; | |
7700 } | |
7701 } | |
7702 r.cidx(i+1) = jx; | |
7703 } | |
7704 | |
7705 r.maybe_compress (); | |
7706 } | |
7707 } | |
7708 else | |
7709 (*current_liboctave_error_handler) ("matrix size mismatch"); | |
7710 | |
7711 return r; | |
7712 } | |
7713 | |
7714 SparseComplexMatrix | |
7715 max (const Complex& c, const SparseComplexMatrix& m) | |
7716 { | |
7717 SparseComplexMatrix result; | |
7718 | |
5275 | 7719 octave_idx_type nr = m.rows (); |
7720 octave_idx_type nc = m.columns (); | |
5164 | 7721 |
7722 EMPTY_RETURN_CHECK (SparseComplexMatrix); | |
7723 | |
7724 // Count the number of non-zero elements | |
7725 if (xmax(c, 0.) != 0.) | |
7726 { | |
7727 result = SparseComplexMatrix (nr, nc, c); | |
5275 | 7728 for (octave_idx_type j = 0; j < nc; j++) |
7729 for (octave_idx_type i = m.cidx(j); i < m.cidx(j+1); i++) | |
5164 | 7730 result.xdata(m.ridx(i) + j * nr) = xmax (c, m.data(i)); |
7731 } | |
7732 else | |
7733 result = SparseComplexMatrix (m); | |
7734 | |
7735 return result; | |
7736 } | |
7737 | |
7738 SparseComplexMatrix | |
7739 max (const SparseComplexMatrix& m, const Complex& c) | |
7740 { | |
7741 return max (c, m); | |
7742 } | |
7743 | |
7744 SparseComplexMatrix | |
7745 max (const SparseComplexMatrix& a, const SparseComplexMatrix& b) | |
7746 { | |
7747 SparseComplexMatrix r; | |
7748 | |
7749 if ((a.rows() == b.rows()) && (a.cols() == b.cols())) | |
7750 { | |
5275 | 7751 octave_idx_type a_nr = a.rows (); |
7752 octave_idx_type a_nc = a.cols (); | |
7753 | |
7754 octave_idx_type b_nr = b.rows (); | |
7755 octave_idx_type b_nc = b.cols (); | |
5164 | 7756 |
7757 if (a_nr == 0 || b_nc == 0) | |
7758 return SparseComplexMatrix (a_nr, a_nc); | |
5681 | 7759 if (a.nnz () == 0) |
5164 | 7760 return SparseComplexMatrix (b); |
5681 | 7761 if (b.nnz () == 0) |
5164 | 7762 return SparseComplexMatrix (a); |
7763 | |
7764 if (a_nr != b_nr || a_nc != b_nc) | |
7765 gripe_nonconformant ("min", a_nr, a_nc, b_nr, b_nc); | |
7766 else | |
7767 { | |
5681 | 7768 r = SparseComplexMatrix (a_nr, a_nc, (a.nnz () + b.nnz ())); |
5164 | 7769 |
5275 | 7770 octave_idx_type jx = 0; |
5164 | 7771 r.cidx (0) = 0; |
5275 | 7772 for (octave_idx_type i = 0 ; i < a_nc ; i++) |
5164 | 7773 { |
5275 | 7774 octave_idx_type ja = a.cidx(i); |
7775 octave_idx_type ja_max = a.cidx(i+1); | |
5164 | 7776 bool ja_lt_max= ja < ja_max; |
7777 | |
5275 | 7778 octave_idx_type jb = b.cidx(i); |
7779 octave_idx_type jb_max = b.cidx(i+1); | |
5164 | 7780 bool jb_lt_max = jb < jb_max; |
7781 | |
7782 while (ja_lt_max || jb_lt_max ) | |
7783 { | |
7784 OCTAVE_QUIT; | |
7785 if ((! jb_lt_max) || | |
7786 (ja_lt_max && (a.ridx(ja) < b.ridx(jb)))) | |
7787 { | |
7788 Complex tmp = xmax (a.data(ja), 0.); | |
7789 if (tmp != 0.) | |
7790 { | |
7791 r.ridx(jx) = a.ridx(ja); | |
7792 r.data(jx) = tmp; | |
7793 jx++; | |
7794 } | |
7795 ja++; | |
7796 ja_lt_max= ja < ja_max; | |
7797 } | |
7798 else if (( !ja_lt_max ) || | |
7799 (jb_lt_max && (b.ridx(jb) < a.ridx(ja)) ) ) | |
7800 { | |
7801 Complex tmp = xmax (0., b.data(jb)); | |
7802 if (tmp != 0.) | |
7803 { | |
7804 r.ridx(jx) = b.ridx(jb); | |
7805 r.data(jx) = tmp; | |
7806 jx++; | |
7807 } | |
7808 jb++; | |
7809 jb_lt_max= jb < jb_max; | |
7810 } | |
7811 else | |
7812 { | |
7813 Complex tmp = xmax (a.data(ja), b.data(jb)); | |
7814 if (tmp != 0.) | |
7815 { | |
7816 r.data(jx) = tmp; | |
7817 r.ridx(jx) = a.ridx(ja); | |
7818 jx++; | |
7819 } | |
7820 ja++; | |
7821 ja_lt_max= ja < ja_max; | |
7822 jb++; | |
7823 jb_lt_max= jb < jb_max; | |
7824 } | |
7825 } | |
7826 r.cidx(i+1) = jx; | |
7827 } | |
7828 | |
7829 r.maybe_compress (); | |
7830 } | |
7831 } | |
7832 else | |
7833 (*current_liboctave_error_handler) ("matrix size mismatch"); | |
7834 | |
7835 return r; | |
7836 } | |
7837 | |
7838 SPARSE_SMS_CMP_OPS (SparseComplexMatrix, 0.0, real, Complex, | |
7839 0.0, real) | |
7840 SPARSE_SMS_BOOL_OPS (SparseComplexMatrix, Complex, 0.0) | |
7841 | |
7842 SPARSE_SSM_CMP_OPS (Complex, 0.0, real, SparseComplexMatrix, | |
7843 0.0, real) | |
7844 SPARSE_SSM_BOOL_OPS (Complex, SparseComplexMatrix, 0.0) | |
7845 | |
7846 SPARSE_SMSM_CMP_OPS (SparseComplexMatrix, 0.0, real, SparseComplexMatrix, | |
7847 0.0, real) | |
7848 SPARSE_SMSM_BOOL_OPS (SparseComplexMatrix, SparseComplexMatrix, 0.0) | |
7849 | |
7850 /* | |
7851 ;;; Local Variables: *** | |
7852 ;;; mode: C++ *** | |
7853 ;;; End: *** | |
7854 */ |