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