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