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