Mercurial > hg > octave-lyh
annotate liboctave/CMatrix.cc @ 7788:45f5faba05a2
Add the rcond function
author | David Bateman <dbateman@free.fr> |
---|---|
date | Wed, 14 May 2008 18:09:56 +0200 |
parents | 36594d5bbe13 |
children | 82be108cc558 |
rev | line source |
---|---|
1993 | 1 // Matrix manipulations. |
458 | 2 /* |
3 | |
7017 | 4 Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, |
5 2003, 2004, 2005, 2006, 2007 John W. Eaton | |
458 | 6 |
7 This file is part of Octave. | |
8 | |
9 Octave is free software; you can redistribute it and/or modify it | |
10 under the terms of the GNU General Public License as published by the | |
7016 | 11 Free Software Foundation; either version 3 of the License, or (at your |
12 option) any later version. | |
458 | 13 |
14 Octave is distributed in the hope that it will be useful, but WITHOUT | |
15 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
16 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
17 for more details. | |
18 | |
19 You should have received a copy of the GNU General Public License | |
7016 | 20 along with Octave; see the file COPYING. If not, see |
21 <http://www.gnu.org/licenses/>. | |
458 | 22 |
23 */ | |
24 | |
25 #ifdef HAVE_CONFIG_H | |
1192 | 26 #include <config.h> |
458 | 27 #endif |
28 | |
1367 | 29 #include <cfloat> |
30 | |
3503 | 31 #include <iostream> |
6209 | 32 #include <vector> |
1367 | 33 |
5775 | 34 // FIXME |
2443 | 35 #ifdef HAVE_SYS_TYPES_H |
36 #include <sys/types.h> | |
37 #endif | |
458 | 38 |
4669 | 39 #include "Array-util.h" |
2828 | 40 #include "CMatrix.h" |
1819 | 41 #include "CmplxAEPBAL.h" |
458 | 42 #include "CmplxDET.h" |
1819 | 43 #include "CmplxSCHUR.h" |
740 | 44 #include "CmplxSVD.h" |
6207 | 45 #include "CmplxCHOL.h" |
1847 | 46 #include "f77-fcn.h" |
7503
8c32f95c2639
convert mapper functions to new format
David Bateman <dbateman@free.fr>
parents:
7488
diff
changeset
|
47 #include "functor.h" |
458 | 48 #include "lo-error.h" |
2354 | 49 #include "lo-ieee.h" |
50 #include "lo-mappers.h" | |
1968 | 51 #include "lo-utils.h" |
1367 | 52 #include "mx-base.h" |
2828 | 53 #include "mx-cm-dm.h" |
3176 | 54 #include "mx-dm-cm.h" |
2828 | 55 #include "mx-cm-s.h" |
1367 | 56 #include "mx-inlines.cc" |
1650 | 57 #include "oct-cmplx.h" |
458 | 58 |
4773 | 59 #if defined (HAVE_FFTW3) |
3827 | 60 #include "oct-fftw.h" |
61 #endif | |
62 | |
458 | 63 // Fortran functions we call. |
64 | |
65 extern "C" | |
66 { | |
7477 | 67 F77_RET_T |
68 F77_FUNC (xilaenv, XILAENV) (const octave_idx_type&, F77_CONST_CHAR_ARG_DECL, | |
69 F77_CONST_CHAR_ARG_DECL, | |
70 const octave_idx_type&, const octave_idx_type&, | |
7478 | 71 const octave_idx_type&, const octave_idx_type&, |
72 octave_idx_type& | |
73 F77_CHAR_ARG_LEN_DECL F77_CHAR_ARG_LEN_DECL); | |
7476 | 74 |
4552 | 75 F77_RET_T |
76 F77_FUNC (zgebal, ZGEBAL) (F77_CONST_CHAR_ARG_DECL, | |
5275 | 77 const octave_idx_type&, Complex*, const octave_idx_type&, octave_idx_type&, |
78 octave_idx_type&, double*, octave_idx_type& | |
4552 | 79 F77_CHAR_ARG_LEN_DECL); |
80 | |
81 F77_RET_T | |
82 F77_FUNC (dgebak, DGEBAK) (F77_CONST_CHAR_ARG_DECL, | |
83 F77_CONST_CHAR_ARG_DECL, | |
5275 | 84 const octave_idx_type&, const octave_idx_type&, const octave_idx_type&, double*, |
85 const octave_idx_type&, double*, const octave_idx_type&, octave_idx_type& | |
4552 | 86 F77_CHAR_ARG_LEN_DECL |
87 F77_CHAR_ARG_LEN_DECL); | |
88 | |
89 F77_RET_T | |
90 F77_FUNC (zgemm, ZGEMM) (F77_CONST_CHAR_ARG_DECL, | |
91 F77_CONST_CHAR_ARG_DECL, | |
5275 | 92 const octave_idx_type&, const octave_idx_type&, const octave_idx_type&, |
93 const Complex&, const Complex*, const octave_idx_type&, | |
94 const Complex*, const octave_idx_type&, const Complex&, | |
95 Complex*, const octave_idx_type& | |
4552 | 96 F77_CHAR_ARG_LEN_DECL |
97 F77_CHAR_ARG_LEN_DECL); | |
98 | |
99 F77_RET_T | |
5983 | 100 F77_FUNC (zgemv, ZGEMV) (F77_CONST_CHAR_ARG_DECL, |
101 const octave_idx_type&, const octave_idx_type&, const Complex&, | |
102 const Complex*, const octave_idx_type&, const Complex*, | |
103 const octave_idx_type&, const Complex&, Complex*, const octave_idx_type& | |
104 F77_CHAR_ARG_LEN_DECL); | |
105 | |
106 F77_RET_T | |
107 F77_FUNC (xzdotu, XZDOTU) (const octave_idx_type&, const Complex*, const octave_idx_type&, | |
108 const Complex*, const octave_idx_type&, Complex&); | |
109 | |
110 F77_RET_T | |
5275 | 111 F77_FUNC (zgetrf, ZGETRF) (const octave_idx_type&, const octave_idx_type&, Complex*, const octave_idx_type&, |
112 octave_idx_type*, octave_idx_type&); | |
4552 | 113 |
114 F77_RET_T | |
115 F77_FUNC (zgetrs, ZGETRS) (F77_CONST_CHAR_ARG_DECL, | |
5275 | 116 const octave_idx_type&, const octave_idx_type&, Complex*, const octave_idx_type&, |
117 const octave_idx_type*, Complex*, const octave_idx_type&, octave_idx_type& | |
4552 | 118 F77_CHAR_ARG_LEN_DECL); |
119 | |
120 F77_RET_T | |
5275 | 121 F77_FUNC (zgetri, ZGETRI) (const octave_idx_type&, Complex*, const octave_idx_type&, const octave_idx_type*, |
122 Complex*, const octave_idx_type&, octave_idx_type&); | |
4552 | 123 |
124 F77_RET_T | |
125 F77_FUNC (zgecon, ZGECON) (F77_CONST_CHAR_ARG_DECL, | |
5275 | 126 const octave_idx_type&, Complex*, |
127 const octave_idx_type&, const double&, double&, | |
128 Complex*, double*, octave_idx_type& | |
4552 | 129 F77_CHAR_ARG_LEN_DECL); |
130 | |
131 F77_RET_T | |
7072 | 132 F77_FUNC (zgelsy, ZGELSY) (const octave_idx_type&, const octave_idx_type&, const octave_idx_type&, |
133 Complex*, const octave_idx_type&, Complex*, | |
134 const octave_idx_type&, octave_idx_type*, double&, octave_idx_type&, | |
135 Complex*, const octave_idx_type&, double*, octave_idx_type&); | |
136 | |
137 F77_RET_T | |
138 F77_FUNC (zgelsd, ZGELSD) (const octave_idx_type&, const octave_idx_type&, const octave_idx_type&, | |
5275 | 139 Complex*, const octave_idx_type&, Complex*, |
7071 | 140 const octave_idx_type&, double*, double&, octave_idx_type&, |
7072 | 141 Complex*, const octave_idx_type&, double*, |
142 octave_idx_type*, octave_idx_type&); | |
458 | 143 |
5785 | 144 F77_RET_T |
145 F77_FUNC (zpotrf, ZPOTRF) (F77_CONST_CHAR_ARG_DECL, const octave_idx_type&, | |
146 Complex*, const octave_idx_type&, | |
147 octave_idx_type& F77_CHAR_ARG_LEN_DECL); | |
148 | |
149 F77_RET_T | |
150 F77_FUNC (zpocon, ZPOCON) (F77_CONST_CHAR_ARG_DECL, const octave_idx_type&, | |
151 Complex*, const octave_idx_type&, const double&, | |
152 double&, Complex*, double*, | |
153 octave_idx_type& F77_CHAR_ARG_LEN_DECL); | |
154 | |
155 F77_RET_T | |
156 F77_FUNC (zpotrs, ZPOTRS) (F77_CONST_CHAR_ARG_DECL, const octave_idx_type&, | |
157 const octave_idx_type&, const Complex*, | |
158 const octave_idx_type&, Complex*, | |
159 const octave_idx_type&, octave_idx_type& | |
160 F77_CHAR_ARG_LEN_DECL); | |
161 | |
162 F77_RET_T | |
6207 | 163 F77_FUNC (ztrtri, ZTRTRI) (F77_CONST_CHAR_ARG_DECL, F77_CONST_CHAR_ARG_DECL, |
164 const octave_idx_type&, const Complex*, | |
165 const octave_idx_type&, octave_idx_type& | |
166 F77_CHAR_ARG_LEN_DECL | |
167 F77_CHAR_ARG_LEN_DECL); | |
168 | |
169 F77_RET_T | |
5785 | 170 F77_FUNC (ztrcon, ZTRCON) (F77_CONST_CHAR_ARG_DECL, F77_CONST_CHAR_ARG_DECL, |
171 F77_CONST_CHAR_ARG_DECL, const octave_idx_type&, | |
172 const Complex*, const octave_idx_type&, double&, | |
173 Complex*, double*, octave_idx_type& | |
174 F77_CHAR_ARG_LEN_DECL | |
175 F77_CHAR_ARG_LEN_DECL | |
176 F77_CHAR_ARG_LEN_DECL); | |
177 | |
178 F77_RET_T | |
179 F77_FUNC (ztrtrs, ZTRTRS) (F77_CONST_CHAR_ARG_DECL, F77_CONST_CHAR_ARG_DECL, | |
180 F77_CONST_CHAR_ARG_DECL, const octave_idx_type&, | |
181 const octave_idx_type&, const Complex*, | |
182 const octave_idx_type&, Complex*, | |
183 const octave_idx_type&, octave_idx_type& | |
184 F77_CHAR_ARG_LEN_DECL | |
185 F77_CHAR_ARG_LEN_DECL | |
186 F77_CHAR_ARG_LEN_DECL); | |
187 | |
1360 | 188 // Note that the original complex fft routines were not written for |
189 // double complex arguments. They have been modified by adding an | |
190 // implicit double precision (a-h,o-z) statement at the beginning of | |
191 // each subroutine. | |
458 | 192 |
4552 | 193 F77_RET_T |
5275 | 194 F77_FUNC (cffti, CFFTI) (const octave_idx_type&, Complex*); |
4552 | 195 |
196 F77_RET_T | |
5275 | 197 F77_FUNC (cfftf, CFFTF) (const octave_idx_type&, Complex*, Complex*); |
4552 | 198 |
199 F77_RET_T | |
5275 | 200 F77_FUNC (cfftb, CFFTB) (const octave_idx_type&, Complex*, Complex*); |
4552 | 201 |
202 F77_RET_T | |
203 F77_FUNC (zlartg, ZLARTG) (const Complex&, const Complex&, | |
204 double&, Complex&, Complex&); | |
205 | |
206 F77_RET_T | |
207 F77_FUNC (ztrsyl, ZTRSYL) (F77_CONST_CHAR_ARG_DECL, | |
208 F77_CONST_CHAR_ARG_DECL, | |
5275 | 209 const octave_idx_type&, const octave_idx_type&, const octave_idx_type&, |
210 const Complex*, const octave_idx_type&, | |
211 const Complex*, const octave_idx_type&, | |
212 const Complex*, const octave_idx_type&, double&, octave_idx_type& | |
4552 | 213 F77_CHAR_ARG_LEN_DECL |
214 F77_CHAR_ARG_LEN_DECL); | |
215 | |
216 F77_RET_T | |
217 F77_FUNC (xzlange, XZLANGE) (F77_CONST_CHAR_ARG_DECL, | |
5275 | 218 const octave_idx_type&, const octave_idx_type&, const Complex*, |
219 const octave_idx_type&, double*, double& | |
4552 | 220 F77_CHAR_ARG_LEN_DECL); |
458 | 221 } |
222 | |
2354 | 223 static const Complex Complex_NaN_result (octave_NaN, octave_NaN); |
224 | |
1360 | 225 // Complex Matrix class |
458 | 226 |
227 ComplexMatrix::ComplexMatrix (const Matrix& a) | |
1214 | 228 : MArray2<Complex> (a.rows (), a.cols ()) |
458 | 229 { |
5275 | 230 for (octave_idx_type j = 0; j < cols (); j++) |
231 for (octave_idx_type i = 0; i < rows (); i++) | |
458 | 232 elem (i, j) = a.elem (i, j); |
233 } | |
234 | |
2349 | 235 ComplexMatrix::ComplexMatrix (const RowVector& rv) |
236 : MArray2<Complex> (1, rv.length (), 0.0) | |
237 { | |
5275 | 238 for (octave_idx_type i = 0; i < rv.length (); i++) |
2349 | 239 elem (0, i) = rv.elem (i); |
240 } | |
241 | |
242 ComplexMatrix::ComplexMatrix (const ColumnVector& cv) | |
243 : MArray2<Complex> (cv.length (), 1, 0.0) | |
244 { | |
5275 | 245 for (octave_idx_type i = 0; i < cv.length (); i++) |
2349 | 246 elem (i, 0) = cv.elem (i); |
247 } | |
248 | |
458 | 249 ComplexMatrix::ComplexMatrix (const DiagMatrix& a) |
1214 | 250 : MArray2<Complex> (a.rows (), a.cols (), 0.0) |
458 | 251 { |
5275 | 252 for (octave_idx_type i = 0; i < a.length (); i++) |
458 | 253 elem (i, i) = a.elem (i, i); |
254 } | |
255 | |
2349 | 256 ComplexMatrix::ComplexMatrix (const ComplexRowVector& rv) |
257 : MArray2<Complex> (1, rv.length (), 0.0) | |
258 { | |
5275 | 259 for (octave_idx_type i = 0; i < rv.length (); i++) |
2349 | 260 elem (0, i) = rv.elem (i); |
261 } | |
262 | |
263 ComplexMatrix::ComplexMatrix (const ComplexColumnVector& cv) | |
264 : MArray2<Complex> (cv.length (), 1, 0.0) | |
265 { | |
5275 | 266 for (octave_idx_type i = 0; i < cv.length (); i++) |
2349 | 267 elem (i, 0) = cv.elem (i); |
268 } | |
269 | |
458 | 270 ComplexMatrix::ComplexMatrix (const ComplexDiagMatrix& a) |
1214 | 271 : MArray2<Complex> (a.rows (), a.cols (), 0.0) |
458 | 272 { |
5275 | 273 for (octave_idx_type i = 0; i < a.length (); i++) |
458 | 274 elem (i, i) = a.elem (i, i); |
275 } | |
276 | |
5775 | 277 // FIXME -- could we use a templated mixed-type copy function |
1574 | 278 // here? |
279 | |
2828 | 280 ComplexMatrix::ComplexMatrix (const boolMatrix& a) |
3180 | 281 : MArray2<Complex> (a.rows (), a.cols (), 0.0) |
2828 | 282 { |
5275 | 283 for (octave_idx_type i = 0; i < a.rows (); i++) |
284 for (octave_idx_type j = 0; j < a.cols (); j++) | |
2828 | 285 elem (i, j) = a.elem (i, j); |
286 } | |
287 | |
1574 | 288 ComplexMatrix::ComplexMatrix (const charMatrix& a) |
3180 | 289 : MArray2<Complex> (a.rows (), a.cols (), 0.0) |
1574 | 290 { |
5275 | 291 for (octave_idx_type i = 0; i < a.rows (); i++) |
292 for (octave_idx_type j = 0; j < a.cols (); j++) | |
1574 | 293 elem (i, j) = a.elem (i, j); |
294 } | |
295 | |
2384 | 296 bool |
458 | 297 ComplexMatrix::operator == (const ComplexMatrix& a) const |
298 { | |
299 if (rows () != a.rows () || cols () != a.cols ()) | |
2384 | 300 return false; |
458 | 301 |
3769 | 302 return mx_inline_equal (data (), a.data (), length ()); |
458 | 303 } |
304 | |
2384 | 305 bool |
458 | 306 ComplexMatrix::operator != (const ComplexMatrix& a) const |
307 { | |
308 return !(*this == a); | |
309 } | |
310 | |
2815 | 311 bool |
312 ComplexMatrix::is_hermitian (void) const | |
313 { | |
5275 | 314 octave_idx_type nr = rows (); |
315 octave_idx_type nc = cols (); | |
2815 | 316 |
317 if (is_square () && nr > 0) | |
318 { | |
5275 | 319 for (octave_idx_type i = 0; i < nr; i++) |
320 for (octave_idx_type j = i; j < nc; j++) | |
2815 | 321 if (elem (i, j) != conj (elem (j, i))) |
322 return false; | |
323 | |
324 return true; | |
325 } | |
326 | |
327 return false; | |
328 } | |
329 | |
458 | 330 // destructive insert/delete/reorder operations |
331 | |
332 ComplexMatrix& | |
5275 | 333 ComplexMatrix::insert (const Matrix& a, octave_idx_type r, octave_idx_type c) |
458 | 334 { |
5275 | 335 octave_idx_type a_nr = a.rows (); |
336 octave_idx_type a_nc = a.cols (); | |
1699 | 337 |
338 if (r < 0 || r + a_nr > rows () || c < 0 || c + a_nc > cols ()) | |
458 | 339 { |
340 (*current_liboctave_error_handler) ("range error for insert"); | |
341 return *this; | |
342 } | |
343 | |
4316 | 344 if (a_nr >0 && a_nc > 0) |
345 { | |
346 make_unique (); | |
347 | |
5275 | 348 for (octave_idx_type j = 0; j < a_nc; j++) |
349 for (octave_idx_type i = 0; i < a_nr; i++) | |
4316 | 350 xelem (r+i, c+j) = a.elem (i, j); |
351 } | |
458 | 352 |
353 return *this; | |
354 } | |
355 | |
356 ComplexMatrix& | |
5275 | 357 ComplexMatrix::insert (const RowVector& a, octave_idx_type r, octave_idx_type c) |
458 | 358 { |
5275 | 359 octave_idx_type a_len = a.length (); |
4316 | 360 |
1699 | 361 if (r < 0 || r >= rows () || c < 0 || c + a_len > cols ()) |
458 | 362 { |
363 (*current_liboctave_error_handler) ("range error for insert"); | |
364 return *this; | |
365 } | |
366 | |
4316 | 367 if (a_len > 0) |
368 { | |
369 make_unique (); | |
370 | |
5275 | 371 for (octave_idx_type i = 0; i < a_len; i++) |
4316 | 372 xelem (r, c+i) = a.elem (i); |
373 } | |
458 | 374 |
375 return *this; | |
376 } | |
377 | |
378 ComplexMatrix& | |
5275 | 379 ComplexMatrix::insert (const ColumnVector& a, octave_idx_type r, octave_idx_type c) |
458 | 380 { |
5275 | 381 octave_idx_type a_len = a.length (); |
4316 | 382 |
1699 | 383 if (r < 0 || r + a_len > rows () || c < 0 || c >= cols ()) |
458 | 384 { |
385 (*current_liboctave_error_handler) ("range error for insert"); | |
386 return *this; | |
387 } | |
388 | |
4316 | 389 if (a_len > 0) |
390 { | |
391 make_unique (); | |
392 | |
5275 | 393 for (octave_idx_type i = 0; i < a_len; i++) |
4316 | 394 xelem (r+i, c) = a.elem (i); |
395 } | |
458 | 396 |
397 return *this; | |
398 } | |
399 | |
400 ComplexMatrix& | |
5275 | 401 ComplexMatrix::insert (const DiagMatrix& a, octave_idx_type r, octave_idx_type c) |
458 | 402 { |
5275 | 403 octave_idx_type a_nr = a.rows (); |
404 octave_idx_type a_nc = a.cols (); | |
1699 | 405 |
406 if (r < 0 || r + a_nr > rows () || c < 0 || c + a_nc > cols ()) | |
458 | 407 { |
408 (*current_liboctave_error_handler) ("range error for insert"); | |
409 return *this; | |
410 } | |
411 | |
1699 | 412 fill (0.0, r, c, r + a_nr - 1, c + a_nc - 1); |
413 | |
5275 | 414 octave_idx_type a_len = a.length (); |
4316 | 415 |
416 if (a_len > 0) | |
417 { | |
418 make_unique (); | |
419 | |
5275 | 420 for (octave_idx_type i = 0; i < a_len; i++) |
4316 | 421 xelem (r+i, c+i) = a.elem (i, i); |
422 } | |
458 | 423 |
424 return *this; | |
425 } | |
426 | |
427 ComplexMatrix& | |
5275 | 428 ComplexMatrix::insert (const ComplexMatrix& a, octave_idx_type r, octave_idx_type c) |
458 | 429 { |
1561 | 430 Array2<Complex>::insert (a, r, c); |
458 | 431 return *this; |
432 } | |
433 | |
434 ComplexMatrix& | |
5275 | 435 ComplexMatrix::insert (const ComplexRowVector& a, octave_idx_type r, octave_idx_type c) |
458 | 436 { |
5275 | 437 octave_idx_type a_len = a.length (); |
1699 | 438 if (r < 0 || r >= rows () || c < 0 || c + a_len > cols ()) |
458 | 439 { |
440 (*current_liboctave_error_handler) ("range error for insert"); | |
441 return *this; | |
442 } | |
443 | |
5275 | 444 for (octave_idx_type i = 0; i < a_len; i++) |
458 | 445 elem (r, c+i) = a.elem (i); |
446 | |
447 return *this; | |
448 } | |
449 | |
450 ComplexMatrix& | |
5275 | 451 ComplexMatrix::insert (const ComplexColumnVector& a, octave_idx_type r, octave_idx_type c) |
458 | 452 { |
5275 | 453 octave_idx_type a_len = a.length (); |
4316 | 454 |
1699 | 455 if (r < 0 || r + a_len > rows () || c < 0 || c >= cols ()) |
458 | 456 { |
457 (*current_liboctave_error_handler) ("range error for insert"); | |
458 return *this; | |
459 } | |
460 | |
4316 | 461 if (a_len > 0) |
462 { | |
463 make_unique (); | |
464 | |
5275 | 465 for (octave_idx_type i = 0; i < a_len; i++) |
4316 | 466 xelem (r+i, c) = a.elem (i); |
467 } | |
458 | 468 |
469 return *this; | |
470 } | |
471 | |
472 ComplexMatrix& | |
5275 | 473 ComplexMatrix::insert (const ComplexDiagMatrix& a, octave_idx_type r, octave_idx_type c) |
458 | 474 { |
5275 | 475 octave_idx_type a_nr = a.rows (); |
476 octave_idx_type a_nc = a.cols (); | |
1699 | 477 |
478 if (r < 0 || r + a_nr > rows () || c < 0 || c + a_nc > cols ()) | |
458 | 479 { |
480 (*current_liboctave_error_handler) ("range error for insert"); | |
481 return *this; | |
482 } | |
483 | |
1699 | 484 fill (0.0, r, c, r + a_nr - 1, c + a_nc - 1); |
485 | |
5275 | 486 octave_idx_type a_len = a.length (); |
4316 | 487 |
488 if (a_len > 0) | |
489 { | |
490 make_unique (); | |
491 | |
5275 | 492 for (octave_idx_type i = 0; i < a_len; i++) |
4316 | 493 xelem (r+i, c+i) = a.elem (i, i); |
494 } | |
458 | 495 |
496 return *this; | |
497 } | |
498 | |
499 ComplexMatrix& | |
500 ComplexMatrix::fill (double val) | |
501 { | |
5275 | 502 octave_idx_type nr = rows (); |
503 octave_idx_type nc = cols (); | |
4316 | 504 |
458 | 505 if (nr > 0 && nc > 0) |
4316 | 506 { |
507 make_unique (); | |
508 | |
5275 | 509 for (octave_idx_type j = 0; j < nc; j++) |
510 for (octave_idx_type i = 0; i < nr; i++) | |
4316 | 511 xelem (i, j) = val; |
512 } | |
458 | 513 |
514 return *this; | |
515 } | |
516 | |
517 ComplexMatrix& | |
518 ComplexMatrix::fill (const Complex& val) | |
519 { | |
5275 | 520 octave_idx_type nr = rows (); |
521 octave_idx_type nc = cols (); | |
4316 | 522 |
458 | 523 if (nr > 0 && nc > 0) |
4316 | 524 { |
525 make_unique (); | |
526 | |
5275 | 527 for (octave_idx_type j = 0; j < nc; j++) |
528 for (octave_idx_type i = 0; i < nr; i++) | |
4316 | 529 xelem (i, j) = val; |
530 } | |
458 | 531 |
532 return *this; | |
533 } | |
534 | |
535 ComplexMatrix& | |
5275 | 536 ComplexMatrix::fill (double val, octave_idx_type r1, octave_idx_type c1, octave_idx_type r2, octave_idx_type c2) |
458 | 537 { |
5275 | 538 octave_idx_type nr = rows (); |
539 octave_idx_type nc = cols (); | |
4316 | 540 |
458 | 541 if (r1 < 0 || r2 < 0 || c1 < 0 || c2 < 0 |
542 || r1 >= nr || r2 >= nr || c1 >= nc || c2 >= nc) | |
543 { | |
544 (*current_liboctave_error_handler) ("range error for fill"); | |
545 return *this; | |
546 } | |
547 | |
5275 | 548 if (r1 > r2) { octave_idx_type tmp = r1; r1 = r2; r2 = tmp; } |
549 if (c1 > c2) { octave_idx_type tmp = c1; c1 = c2; c2 = tmp; } | |
458 | 550 |
4316 | 551 if (r2 >= r1 && c2 >= c1) |
552 { | |
553 make_unique (); | |
554 | |
5275 | 555 for (octave_idx_type j = c1; j <= c2; j++) |
556 for (octave_idx_type i = r1; i <= r2; i++) | |
4316 | 557 xelem (i, j) = val; |
558 } | |
458 | 559 |
560 return *this; | |
561 } | |
562 | |
563 ComplexMatrix& | |
5275 | 564 ComplexMatrix::fill (const Complex& val, octave_idx_type r1, octave_idx_type c1, octave_idx_type r2, octave_idx_type c2) |
458 | 565 { |
5275 | 566 octave_idx_type nr = rows (); |
567 octave_idx_type nc = cols (); | |
4316 | 568 |
458 | 569 if (r1 < 0 || r2 < 0 || c1 < 0 || c2 < 0 |
570 || r1 >= nr || r2 >= nr || c1 >= nc || c2 >= nc) | |
571 { | |
572 (*current_liboctave_error_handler) ("range error for fill"); | |
573 return *this; | |
574 } | |
575 | |
5275 | 576 if (r1 > r2) { octave_idx_type tmp = r1; r1 = r2; r2 = tmp; } |
577 if (c1 > c2) { octave_idx_type tmp = c1; c1 = c2; c2 = tmp; } | |
458 | 578 |
4316 | 579 if (r2 >= r1 && c2 >=c1) |
580 { | |
581 make_unique (); | |
582 | |
5275 | 583 for (octave_idx_type j = c1; j <= c2; j++) |
584 for (octave_idx_type i = r1; i <= r2; i++) | |
4316 | 585 xelem (i, j) = val; |
586 } | |
458 | 587 |
588 return *this; | |
589 } | |
590 | |
591 ComplexMatrix | |
592 ComplexMatrix::append (const Matrix& a) const | |
593 { | |
5275 | 594 octave_idx_type nr = rows (); |
595 octave_idx_type nc = cols (); | |
458 | 596 if (nr != a.rows ()) |
597 { | |
598 (*current_liboctave_error_handler) ("row dimension mismatch for append"); | |
599 return *this; | |
600 } | |
601 | |
5275 | 602 octave_idx_type nc_insert = nc; |
458 | 603 ComplexMatrix retval (nr, nc + a.cols ()); |
604 retval.insert (*this, 0, 0); | |
605 retval.insert (a, 0, nc_insert); | |
606 return retval; | |
607 } | |
608 | |
609 ComplexMatrix | |
610 ComplexMatrix::append (const RowVector& a) const | |
611 { | |
5275 | 612 octave_idx_type nr = rows (); |
613 octave_idx_type nc = cols (); | |
458 | 614 if (nr != 1) |
615 { | |
616 (*current_liboctave_error_handler) ("row dimension mismatch for append"); | |
617 return *this; | |
618 } | |
619 | |
5275 | 620 octave_idx_type nc_insert = nc; |
458 | 621 ComplexMatrix retval (nr, nc + a.length ()); |
622 retval.insert (*this, 0, 0); | |
623 retval.insert (a, 0, nc_insert); | |
624 return retval; | |
625 } | |
626 | |
627 ComplexMatrix | |
628 ComplexMatrix::append (const ColumnVector& a) const | |
629 { | |
5275 | 630 octave_idx_type nr = rows (); |
631 octave_idx_type nc = cols (); | |
458 | 632 if (nr != a.length ()) |
633 { | |
634 (*current_liboctave_error_handler) ("row dimension mismatch for append"); | |
635 return *this; | |
636 } | |
637 | |
5275 | 638 octave_idx_type nc_insert = nc; |
458 | 639 ComplexMatrix retval (nr, nc + 1); |
640 retval.insert (*this, 0, 0); | |
641 retval.insert (a, 0, nc_insert); | |
642 return retval; | |
643 } | |
644 | |
645 ComplexMatrix | |
646 ComplexMatrix::append (const DiagMatrix& a) const | |
647 { | |
5275 | 648 octave_idx_type nr = rows (); |
649 octave_idx_type nc = cols (); | |
458 | 650 if (nr != a.rows ()) |
651 { | |
652 (*current_liboctave_error_handler) ("row dimension mismatch for append"); | |
653 return *this; | |
654 } | |
655 | |
5275 | 656 octave_idx_type nc_insert = nc; |
458 | 657 ComplexMatrix retval (nr, nc + a.cols ()); |
658 retval.insert (*this, 0, 0); | |
659 retval.insert (a, 0, nc_insert); | |
660 return retval; | |
661 } | |
662 | |
663 ComplexMatrix | |
664 ComplexMatrix::append (const ComplexMatrix& a) const | |
665 { | |
5275 | 666 octave_idx_type nr = rows (); |
667 octave_idx_type nc = cols (); | |
458 | 668 if (nr != a.rows ()) |
669 { | |
670 (*current_liboctave_error_handler) ("row dimension mismatch for append"); | |
671 return *this; | |
672 } | |
673 | |
5275 | 674 octave_idx_type nc_insert = nc; |
458 | 675 ComplexMatrix retval (nr, nc + a.cols ()); |
676 retval.insert (*this, 0, 0); | |
677 retval.insert (a, 0, nc_insert); | |
678 return retval; | |
679 } | |
680 | |
681 ComplexMatrix | |
682 ComplexMatrix::append (const ComplexRowVector& a) const | |
683 { | |
5275 | 684 octave_idx_type nr = rows (); |
685 octave_idx_type nc = cols (); | |
458 | 686 if (nr != 1) |
687 { | |
688 (*current_liboctave_error_handler) ("row dimension mismatch for append"); | |
689 return *this; | |
690 } | |
691 | |
5275 | 692 octave_idx_type nc_insert = nc; |
458 | 693 ComplexMatrix retval (nr, nc + a.length ()); |
694 retval.insert (*this, 0, 0); | |
695 retval.insert (a, 0, nc_insert); | |
696 return retval; | |
697 } | |
698 | |
699 ComplexMatrix | |
700 ComplexMatrix::append (const ComplexColumnVector& a) const | |
701 { | |
5275 | 702 octave_idx_type nr = rows (); |
703 octave_idx_type nc = cols (); | |
458 | 704 if (nr != a.length ()) |
705 { | |
706 (*current_liboctave_error_handler) ("row dimension mismatch for append"); | |
707 return *this; | |
708 } | |
709 | |
5275 | 710 octave_idx_type nc_insert = nc; |
458 | 711 ComplexMatrix retval (nr, nc + 1); |
712 retval.insert (*this, 0, 0); | |
713 retval.insert (a, 0, nc_insert); | |
714 return retval; | |
715 } | |
716 | |
717 ComplexMatrix | |
718 ComplexMatrix::append (const ComplexDiagMatrix& a) const | |
719 { | |
5275 | 720 octave_idx_type nr = rows (); |
721 octave_idx_type nc = cols (); | |
458 | 722 if (nr != a.rows ()) |
723 { | |
724 (*current_liboctave_error_handler) ("row dimension mismatch for append"); | |
725 return *this; | |
726 } | |
727 | |
5275 | 728 octave_idx_type nc_insert = nc; |
458 | 729 ComplexMatrix retval (nr, nc + a.cols ()); |
730 retval.insert (*this, 0, 0); | |
731 retval.insert (a, 0, nc_insert); | |
732 return retval; | |
733 } | |
734 | |
735 ComplexMatrix | |
736 ComplexMatrix::stack (const Matrix& a) const | |
737 { | |
5275 | 738 octave_idx_type nr = rows (); |
739 octave_idx_type nc = cols (); | |
458 | 740 if (nc != a.cols ()) |
741 { | |
742 (*current_liboctave_error_handler) | |
743 ("column dimension mismatch for stack"); | |
744 return *this; | |
745 } | |
746 | |
5275 | 747 octave_idx_type nr_insert = nr; |
458 | 748 ComplexMatrix retval (nr + a.rows (), nc); |
749 retval.insert (*this, 0, 0); | |
750 retval.insert (a, nr_insert, 0); | |
751 return retval; | |
752 } | |
753 | |
754 ComplexMatrix | |
755 ComplexMatrix::stack (const RowVector& a) const | |
756 { | |
5275 | 757 octave_idx_type nr = rows (); |
758 octave_idx_type nc = cols (); | |
458 | 759 if (nc != a.length ()) |
760 { | |
761 (*current_liboctave_error_handler) | |
762 ("column dimension mismatch for stack"); | |
763 return *this; | |
764 } | |
765 | |
5275 | 766 octave_idx_type nr_insert = nr; |
458 | 767 ComplexMatrix retval (nr + 1, nc); |
768 retval.insert (*this, 0, 0); | |
769 retval.insert (a, nr_insert, 0); | |
770 return retval; | |
771 } | |
772 | |
773 ComplexMatrix | |
774 ComplexMatrix::stack (const ColumnVector& a) const | |
775 { | |
5275 | 776 octave_idx_type nr = rows (); |
777 octave_idx_type nc = cols (); | |
458 | 778 if (nc != 1) |
779 { | |
780 (*current_liboctave_error_handler) | |
781 ("column dimension mismatch for stack"); | |
782 return *this; | |
783 } | |
784 | |
5275 | 785 octave_idx_type nr_insert = nr; |
458 | 786 ComplexMatrix retval (nr + a.length (), nc); |
787 retval.insert (*this, 0, 0); | |
788 retval.insert (a, nr_insert, 0); | |
789 return retval; | |
790 } | |
791 | |
792 ComplexMatrix | |
793 ComplexMatrix::stack (const DiagMatrix& a) const | |
794 { | |
5275 | 795 octave_idx_type nr = rows (); |
796 octave_idx_type nc = cols (); | |
458 | 797 if (nc != a.cols ()) |
798 { | |
799 (*current_liboctave_error_handler) | |
800 ("column dimension mismatch for stack"); | |
801 return *this; | |
802 } | |
803 | |
5275 | 804 octave_idx_type nr_insert = nr; |
458 | 805 ComplexMatrix retval (nr + a.rows (), nc); |
806 retval.insert (*this, 0, 0); | |
807 retval.insert (a, nr_insert, 0); | |
808 return retval; | |
809 } | |
810 | |
811 ComplexMatrix | |
812 ComplexMatrix::stack (const ComplexMatrix& a) const | |
813 { | |
5275 | 814 octave_idx_type nr = rows (); |
815 octave_idx_type nc = cols (); | |
458 | 816 if (nc != a.cols ()) |
817 { | |
818 (*current_liboctave_error_handler) | |
819 ("column dimension mismatch for stack"); | |
820 return *this; | |
821 } | |
822 | |
5275 | 823 octave_idx_type nr_insert = nr; |
458 | 824 ComplexMatrix retval (nr + a.rows (), nc); |
825 retval.insert (*this, 0, 0); | |
826 retval.insert (a, nr_insert, 0); | |
827 return retval; | |
828 } | |
829 | |
830 ComplexMatrix | |
831 ComplexMatrix::stack (const ComplexRowVector& a) const | |
832 { | |
5275 | 833 octave_idx_type nr = rows (); |
834 octave_idx_type nc = cols (); | |
458 | 835 if (nc != a.length ()) |
836 { | |
837 (*current_liboctave_error_handler) | |
838 ("column dimension mismatch for stack"); | |
839 return *this; | |
840 } | |
841 | |
5275 | 842 octave_idx_type nr_insert = nr; |
458 | 843 ComplexMatrix retval (nr + 1, nc); |
844 retval.insert (*this, 0, 0); | |
845 retval.insert (a, nr_insert, 0); | |
846 return retval; | |
847 } | |
848 | |
849 ComplexMatrix | |
850 ComplexMatrix::stack (const ComplexColumnVector& a) const | |
851 { | |
5275 | 852 octave_idx_type nr = rows (); |
853 octave_idx_type nc = cols (); | |
458 | 854 if (nc != 1) |
855 { | |
856 (*current_liboctave_error_handler) | |
857 ("column dimension mismatch for stack"); | |
858 return *this; | |
859 } | |
860 | |
5275 | 861 octave_idx_type nr_insert = nr; |
458 | 862 ComplexMatrix retval (nr + a.length (), nc); |
863 retval.insert (*this, 0, 0); | |
864 retval.insert (a, nr_insert, 0); | |
865 return retval; | |
866 } | |
867 | |
868 ComplexMatrix | |
869 ComplexMatrix::stack (const ComplexDiagMatrix& a) const | |
870 { | |
5275 | 871 octave_idx_type nr = rows (); |
872 octave_idx_type nc = cols (); | |
458 | 873 if (nc != a.cols ()) |
874 { | |
875 (*current_liboctave_error_handler) | |
876 ("column dimension mismatch for stack"); | |
877 return *this; | |
878 } | |
879 | |
5275 | 880 octave_idx_type nr_insert = nr; |
458 | 881 ComplexMatrix retval (nr + a.rows (), nc); |
882 retval.insert (*this, 0, 0); | |
883 retval.insert (a, nr_insert, 0); | |
884 return retval; | |
885 } | |
886 | |
887 ComplexMatrix | |
888 ComplexMatrix::hermitian (void) const | |
889 { | |
5275 | 890 octave_idx_type nr = rows (); |
891 octave_idx_type nc = cols (); | |
458 | 892 ComplexMatrix result; |
893 if (length () > 0) | |
894 { | |
895 result.resize (nc, nr); | |
5275 | 896 for (octave_idx_type j = 0; j < nc; j++) |
897 for (octave_idx_type i = 0; i < nr; i++) | |
458 | 898 result.elem (j, i) = conj (elem (i, j)); |
899 } | |
900 return result; | |
901 } | |
902 | |
903 ComplexMatrix | |
904 conj (const ComplexMatrix& a) | |
905 { | |
5275 | 906 octave_idx_type a_len = a.length (); |
458 | 907 ComplexMatrix retval; |
908 if (a_len > 0) | |
3769 | 909 retval = ComplexMatrix (mx_inline_conj_dup (a.data (), a_len), |
910 a.rows (), a.cols ()); | |
458 | 911 return retval; |
912 } | |
913 | |
914 // resize is the destructive equivalent for this one | |
915 | |
916 ComplexMatrix | |
5275 | 917 ComplexMatrix::extract (octave_idx_type r1, octave_idx_type c1, octave_idx_type r2, octave_idx_type c2) const |
458 | 918 { |
5275 | 919 if (r1 > r2) { octave_idx_type tmp = r1; r1 = r2; r2 = tmp; } |
920 if (c1 > c2) { octave_idx_type tmp = c1; c1 = c2; c2 = tmp; } | |
921 | |
922 octave_idx_type new_r = r2 - r1 + 1; | |
923 octave_idx_type new_c = c2 - c1 + 1; | |
458 | 924 |
925 ComplexMatrix result (new_r, new_c); | |
926 | |
5275 | 927 for (octave_idx_type j = 0; j < new_c; j++) |
928 for (octave_idx_type i = 0; i < new_r; i++) | |
4316 | 929 result.xelem (i, j) = elem (r1+i, c1+j); |
930 | |
931 return result; | |
932 } | |
933 | |
934 ComplexMatrix | |
5275 | 935 ComplexMatrix::extract_n (octave_idx_type r1, octave_idx_type c1, octave_idx_type nr, octave_idx_type nc) const |
4316 | 936 { |
937 ComplexMatrix result (nr, nc); | |
938 | |
5275 | 939 for (octave_idx_type j = 0; j < nc; j++) |
940 for (octave_idx_type i = 0; i < nr; i++) | |
4316 | 941 result.xelem (i, j) = elem (r1+i, c1+j); |
458 | 942 |
943 return result; | |
944 } | |
945 | |
946 // extract row or column i. | |
947 | |
948 ComplexRowVector | |
5275 | 949 ComplexMatrix::row (octave_idx_type i) const |
458 | 950 { |
5275 | 951 octave_idx_type nc = cols (); |
458 | 952 if (i < 0 || i >= rows ()) |
953 { | |
954 (*current_liboctave_error_handler) ("invalid row selection"); | |
955 return ComplexRowVector (); | |
956 } | |
957 | |
958 ComplexRowVector retval (nc); | |
5275 | 959 for (octave_idx_type j = 0; j < cols (); j++) |
4316 | 960 retval.xelem (j) = elem (i, j); |
458 | 961 |
962 return retval; | |
963 } | |
964 | |
965 ComplexColumnVector | |
5275 | 966 ComplexMatrix::column (octave_idx_type i) const |
458 | 967 { |
5275 | 968 octave_idx_type nr = rows (); |
458 | 969 if (i < 0 || i >= cols ()) |
970 { | |
971 (*current_liboctave_error_handler) ("invalid column selection"); | |
972 return ComplexColumnVector (); | |
973 } | |
974 | |
975 ComplexColumnVector retval (nr); | |
5275 | 976 for (octave_idx_type j = 0; j < nr; j++) |
4316 | 977 retval.xelem (j) = elem (j, i); |
458 | 978 |
979 return retval; | |
980 } | |
981 | |
982 ComplexMatrix | |
983 ComplexMatrix::inverse (void) const | |
984 { | |
5275 | 985 octave_idx_type info; |
7788 | 986 double rcon; |
6207 | 987 MatrixType mattype (*this); |
7788 | 988 return inverse (mattype, info, rcon, 0, 0); |
6207 | 989 } |
990 | |
991 ComplexMatrix | |
6479 | 992 ComplexMatrix::inverse (octave_idx_type& info) const |
993 { | |
7788 | 994 double rcon; |
6479 | 995 MatrixType mattype (*this); |
7788 | 996 return inverse (mattype, info, rcon, 0, 0); |
6479 | 997 } |
998 | |
999 ComplexMatrix | |
7788 | 1000 ComplexMatrix::inverse (octave_idx_type& info, double& rcon, int force, |
6479 | 1001 int calc_cond) const |
1002 { | |
1003 MatrixType mattype (*this); | |
7788 | 1004 return inverse (mattype, info, rcon, force, calc_cond); |
6479 | 1005 } |
1006 | |
1007 ComplexMatrix | |
6207 | 1008 ComplexMatrix::inverse (MatrixType &mattype) const |
1009 { | |
1010 octave_idx_type info; | |
7788 | 1011 double rcon; |
1012 return inverse (mattype, info, rcon, 0, 0); | |
6207 | 1013 } |
1014 | |
1015 ComplexMatrix | |
1016 ComplexMatrix::inverse (MatrixType &mattype, octave_idx_type& info) const | |
1017 { | |
7788 | 1018 double rcon; |
1019 return inverse (mattype, info, rcon, 0, 0); | |
458 | 1020 } |
1021 | |
1022 ComplexMatrix | |
6207 | 1023 ComplexMatrix::tinverse (MatrixType &mattype, octave_idx_type& info, |
7788 | 1024 double& rcon, int force, int calc_cond) const |
458 | 1025 { |
6207 | 1026 ComplexMatrix retval; |
1027 | |
1028 octave_idx_type nr = rows (); | |
1029 octave_idx_type nc = cols (); | |
1030 | |
1031 if (nr != nc || nr == 0 || nc == 0) | |
1032 (*current_liboctave_error_handler) ("inverse requires square matrix"); | |
1033 else | |
1034 { | |
1035 int typ = mattype.type (); | |
1036 char uplo = (typ == MatrixType::Lower ? 'L' : 'U'); | |
1037 char udiag = 'N'; | |
1038 retval = *this; | |
1039 Complex *tmp_data = retval.fortran_vec (); | |
1040 | |
1041 F77_XFCN (ztrtri, ZTRTRI, (F77_CONST_CHAR_ARG2 (&uplo, 1), | |
1042 F77_CONST_CHAR_ARG2 (&udiag, 1), | |
1043 nr, tmp_data, nr, info | |
1044 F77_CHAR_ARG_LEN (1) | |
1045 F77_CHAR_ARG_LEN (1))); | |
1046 | |
7482
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
1047 // Throw-away extra info LAPACK gives so as to not change output. |
7788 | 1048 rcon = 0.0; |
7482
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
1049 if (info != 0) |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
1050 info = -1; |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
1051 else if (calc_cond) |
6207 | 1052 { |
7482
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
1053 octave_idx_type ztrcon_info = 0; |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
1054 char job = '1'; |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
1055 |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
1056 OCTAVE_LOCAL_BUFFER (Complex, cwork, 2*nr); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
1057 OCTAVE_LOCAL_BUFFER (double, rwork, nr); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
1058 |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
1059 F77_XFCN (ztrcon, ZTRCON, (F77_CONST_CHAR_ARG2 (&job, 1), |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
1060 F77_CONST_CHAR_ARG2 (&uplo, 1), |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
1061 F77_CONST_CHAR_ARG2 (&udiag, 1), |
7788 | 1062 nr, tmp_data, nr, rcon, |
7482
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
1063 cwork, rwork, ztrcon_info |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
1064 F77_CHAR_ARG_LEN (1) |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
1065 F77_CHAR_ARG_LEN (1) |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
1066 F77_CHAR_ARG_LEN (1))); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
1067 |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
1068 if (ztrcon_info != 0) |
6207 | 1069 info = -1; |
1070 } | |
1071 | |
1072 if (info == -1 && ! force) | |
1073 retval = *this; // Restore matrix contents. | |
1074 } | |
1075 | |
1076 return retval; | |
458 | 1077 } |
1078 | |
1079 ComplexMatrix | |
6207 | 1080 ComplexMatrix::finverse (MatrixType &mattype, octave_idx_type& info, |
7788 | 1081 double& rcon, int force, int calc_cond) const |
458 | 1082 { |
1948 | 1083 ComplexMatrix retval; |
1084 | |
5275 | 1085 octave_idx_type nr = rows (); |
1086 octave_idx_type nc = cols (); | |
1948 | 1087 |
458 | 1088 if (nr != nc) |
1948 | 1089 (*current_liboctave_error_handler) ("inverse requires square matrix"); |
458 | 1090 else |
1091 { | |
5275 | 1092 Array<octave_idx_type> ipvt (nr); |
1093 octave_idx_type *pipvt = ipvt.fortran_vec (); | |
1948 | 1094 |
1095 retval = *this; | |
1096 Complex *tmp_data = retval.fortran_vec (); | |
1097 | |
4329 | 1098 Array<Complex> z(1); |
5275 | 1099 octave_idx_type lwork = -1; |
4330 | 1100 |
1101 // Query the optimum work array size. | |
4329 | 1102 |
1103 F77_XFCN (zgetri, ZGETRI, (nc, tmp_data, nr, pipvt, | |
1104 z.fortran_vec (), lwork, info)); | |
1105 | |
5315 | 1106 lwork = static_cast<octave_idx_type> (std::real(z(0))); |
4329 | 1107 lwork = (lwork < 2 *nc ? 2*nc : lwork); |
1108 z.resize (lwork); | |
1109 Complex *pz = z.fortran_vec (); | |
1110 | |
1111 info = 0; | |
1112 | |
4330 | 1113 // Calculate the norm of the matrix, for later use. |
4329 | 1114 double anorm; |
1115 if (calc_cond) | |
5275 | 1116 anorm = retval.abs().sum().row(static_cast<octave_idx_type>(0)).max(); |
4329 | 1117 |
1118 F77_XFCN (zgetrf, ZGETRF, (nc, nc, tmp_data, nr, pipvt, info)); | |
1948 | 1119 |
7482
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
1120 // Throw-away extra info LAPACK gives so as to not change output. |
7788 | 1121 rcon = 0.0; |
7482
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
1122 if (info != 0) |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
1123 info = -1; |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
1124 else if (calc_cond) |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
1125 { |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
1126 // Now calculate the condition number for non-singular matrix. |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
1127 octave_idx_type zgecon_info = 0; |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
1128 char job = '1'; |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
1129 Array<double> rz (2 * nc); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
1130 double *prz = rz.fortran_vec (); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
1131 F77_XFCN (zgecon, ZGECON, (F77_CONST_CHAR_ARG2 (&job, 1), |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
1132 nc, tmp_data, nr, anorm, |
7788 | 1133 rcon, pz, prz, zgecon_info |
7482
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
1134 F77_CHAR_ARG_LEN (1))); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
1135 |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
1136 if (zgecon_info != 0) |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
1137 info = -1; |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
1138 } |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
1139 |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
1140 if (info == -1 && ! force) |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
1141 retval = *this; // Restore contents. |
1948 | 1142 else |
1143 { | |
7482
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
1144 octave_idx_type zgetri_info = 0; |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
1145 |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
1146 F77_XFCN (zgetri, ZGETRI, (nc, tmp_data, nr, pipvt, |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
1147 pz, lwork, zgetri_info)); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
1148 |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
1149 if (zgetri_info != 0) |
1948 | 1150 info = -1; |
1151 } | |
6207 | 1152 |
1153 if (info != 0) | |
1154 mattype.mark_as_rectangular(); | |
458 | 1155 } |
4329 | 1156 |
1948 | 1157 return retval; |
458 | 1158 } |
1159 | |
1160 ComplexMatrix | |
6207 | 1161 ComplexMatrix::inverse (MatrixType &mattype, octave_idx_type& info, |
7788 | 1162 double& rcon, int force, int calc_cond) const |
6207 | 1163 { |
1164 int typ = mattype.type (false); | |
1165 ComplexMatrix ret; | |
1166 | |
1167 if (typ == MatrixType::Unknown) | |
1168 typ = mattype.type (*this); | |
1169 | |
1170 if (typ == MatrixType::Upper || typ == MatrixType::Lower) | |
7788 | 1171 ret = tinverse (mattype, info, rcon, force, calc_cond); |
6840 | 1172 else |
6207 | 1173 { |
1174 if (mattype.is_hermitian ()) | |
1175 { | |
6486 | 1176 ComplexCHOL chol (*this, info, calc_cond); |
6207 | 1177 if (info == 0) |
6486 | 1178 { |
1179 if (calc_cond) | |
7788 | 1180 rcon = chol.rcond(); |
6486 | 1181 else |
7788 | 1182 rcon = 1.0; |
6486 | 1183 ret = chol.inverse (); |
1184 } | |
6207 | 1185 else |
1186 mattype.mark_as_unsymmetric (); | |
1187 } | |
1188 | |
1189 if (!mattype.is_hermitian ()) | |
7788 | 1190 ret = finverse(mattype, info, rcon, force, calc_cond); |
1191 | |
1192 if ((mattype.is_hermitian () || calc_cond) && rcon == 0.) | |
6840 | 1193 ret = ComplexMatrix (rows (), columns (), Complex (octave_Inf, 0.)); |
6207 | 1194 } |
1195 | |
1196 return ret; | |
1197 } | |
1198 | |
1199 ComplexMatrix | |
4384 | 1200 ComplexMatrix::pseudo_inverse (double tol) const |
740 | 1201 { |
1549 | 1202 ComplexMatrix retval; |
1203 | |
3480 | 1204 ComplexSVD result (*this, SVD::economy); |
740 | 1205 |
1206 DiagMatrix S = result.singular_values (); | |
1207 ComplexMatrix U = result.left_singular_matrix (); | |
1208 ComplexMatrix V = result.right_singular_matrix (); | |
1209 | |
1210 ColumnVector sigma = S.diag (); | |
1211 | |
5275 | 1212 octave_idx_type r = sigma.length () - 1; |
1213 octave_idx_type nr = rows (); | |
1214 octave_idx_type nc = cols (); | |
740 | 1215 |
1216 if (tol <= 0.0) | |
1217 { | |
1218 if (nr > nc) | |
1219 tol = nr * sigma.elem (0) * DBL_EPSILON; | |
1220 else | |
1221 tol = nc * sigma.elem (0) * DBL_EPSILON; | |
1222 } | |
1223 | |
1224 while (r >= 0 && sigma.elem (r) < tol) | |
1225 r--; | |
1226 | |
1227 if (r < 0) | |
1549 | 1228 retval = ComplexMatrix (nc, nr, 0.0); |
740 | 1229 else |
1230 { | |
1231 ComplexMatrix Ur = U.extract (0, 0, nr-1, r); | |
1232 DiagMatrix D = DiagMatrix (sigma.extract (0, r)) . inverse (); | |
1233 ComplexMatrix Vr = V.extract (0, 0, nc-1, r); | |
1549 | 1234 retval = Vr * D * Ur.hermitian (); |
740 | 1235 } |
1549 | 1236 |
1237 return retval; | |
740 | 1238 } |
1239 | |
4773 | 1240 #if defined (HAVE_FFTW3) |
3827 | 1241 |
1242 ComplexMatrix | |
1243 ComplexMatrix::fourier (void) const | |
1244 { | |
1245 size_t nr = rows (); | |
1246 size_t nc = cols (); | |
1247 | |
1248 ComplexMatrix retval (nr, nc); | |
1249 | |
1250 size_t npts, nsamples; | |
1251 | |
1252 if (nr == 1 || nc == 1) | |
1253 { | |
1254 npts = nr > nc ? nr : nc; | |
1255 nsamples = 1; | |
1256 } | |
1257 else | |
1258 { | |
1259 npts = nr; | |
1260 nsamples = nc; | |
1261 } | |
1262 | |
1263 const Complex *in (data ()); | |
1264 Complex *out (retval.fortran_vec ()); | |
1265 | |
4773 | 1266 octave_fftw::fft (in, out, npts, nsamples); |
3827 | 1267 |
1268 return retval; | |
1269 } | |
1270 | |
1271 ComplexMatrix | |
1272 ComplexMatrix::ifourier (void) const | |
1273 { | |
1274 size_t nr = rows (); | |
1275 size_t nc = cols (); | |
1276 | |
1277 ComplexMatrix retval (nr, nc); | |
1278 | |
1279 size_t npts, nsamples; | |
1280 | |
1281 if (nr == 1 || nc == 1) | |
1282 { | |
1283 npts = nr > nc ? nr : nc; | |
1284 nsamples = 1; | |
1285 } | |
1286 else | |
1287 { | |
1288 npts = nr; | |
1289 nsamples = nc; | |
1290 } | |
1291 | |
1292 const Complex *in (data ()); | |
1293 Complex *out (retval.fortran_vec ()); | |
1294 | |
4773 | 1295 octave_fftw::ifft (in, out, npts, nsamples); |
3827 | 1296 |
1297 return retval; | |
1298 } | |
1299 | |
1300 ComplexMatrix | |
1301 ComplexMatrix::fourier2d (void) const | |
1302 { | |
4773 | 1303 dim_vector dv(rows (), cols ()); |
1304 | |
1305 ComplexMatrix retval (rows (), cols ()); | |
1306 const Complex *in (data ()); | |
1307 Complex *out (retval.fortran_vec ()); | |
1308 | |
1309 octave_fftw::fftNd (in, out, 2, dv); | |
3827 | 1310 |
1311 return retval; | |
1312 } | |
1313 | |
1314 ComplexMatrix | |
1315 ComplexMatrix::ifourier2d (void) const | |
1316 { | |
4773 | 1317 dim_vector dv(rows (), cols ()); |
1318 | |
1319 ComplexMatrix retval (rows (), cols ()); | |
1320 const Complex *in (data ()); | |
1321 Complex *out (retval.fortran_vec ()); | |
1322 | |
1323 octave_fftw::ifftNd (in, out, 2, dv); | |
3827 | 1324 |
1325 return retval; | |
1326 } | |
1327 | |
1328 #else | |
1329 | |
740 | 1330 ComplexMatrix |
458 | 1331 ComplexMatrix::fourier (void) const |
1332 { | |
1948 | 1333 ComplexMatrix retval; |
1334 | |
5275 | 1335 octave_idx_type nr = rows (); |
1336 octave_idx_type nc = cols (); | |
1337 | |
1338 octave_idx_type npts, nsamples; | |
1948 | 1339 |
458 | 1340 if (nr == 1 || nc == 1) |
1341 { | |
1342 npts = nr > nc ? nr : nc; | |
1343 nsamples = 1; | |
1344 } | |
1345 else | |
1346 { | |
1347 npts = nr; | |
1348 nsamples = nc; | |
1349 } | |
1350 | |
5275 | 1351 octave_idx_type nn = 4*npts+15; |
1948 | 1352 |
1353 Array<Complex> wsave (nn); | |
1354 Complex *pwsave = wsave.fortran_vec (); | |
1355 | |
1356 retval = *this; | |
1357 Complex *tmp_data = retval.fortran_vec (); | |
1358 | |
3887 | 1359 F77_FUNC (cffti, CFFTI) (npts, pwsave); |
458 | 1360 |
5275 | 1361 for (octave_idx_type j = 0; j < nsamples; j++) |
4153 | 1362 { |
1363 OCTAVE_QUIT; | |
1364 | |
1365 F77_FUNC (cfftf, CFFTF) (npts, &tmp_data[npts*j], pwsave); | |
1366 } | |
1948 | 1367 |
1368 return retval; | |
458 | 1369 } |
1370 | |
1371 ComplexMatrix | |
1372 ComplexMatrix::ifourier (void) const | |
1373 { | |
1948 | 1374 ComplexMatrix retval; |
1375 | |
5275 | 1376 octave_idx_type nr = rows (); |
1377 octave_idx_type nc = cols (); | |
1378 | |
1379 octave_idx_type npts, nsamples; | |
1948 | 1380 |
458 | 1381 if (nr == 1 || nc == 1) |
1382 { | |
1383 npts = nr > nc ? nr : nc; | |
1384 nsamples = 1; | |
1385 } | |
1386 else | |
1387 { | |
1388 npts = nr; | |
1389 nsamples = nc; | |
1390 } | |
1391 | |
5275 | 1392 octave_idx_type nn = 4*npts+15; |
1948 | 1393 |
1394 Array<Complex> wsave (nn); | |
1395 Complex *pwsave = wsave.fortran_vec (); | |
1396 | |
1397 retval = *this; | |
1398 Complex *tmp_data = retval.fortran_vec (); | |
1399 | |
3887 | 1400 F77_FUNC (cffti, CFFTI) (npts, pwsave); |
458 | 1401 |
5275 | 1402 for (octave_idx_type j = 0; j < nsamples; j++) |
4153 | 1403 { |
1404 OCTAVE_QUIT; | |
1405 | |
1406 F77_FUNC (cfftb, CFFTB) (npts, &tmp_data[npts*j], pwsave); | |
1407 } | |
458 | 1408 |
5275 | 1409 for (octave_idx_type j = 0; j < npts*nsamples; j++) |
3572 | 1410 tmp_data[j] = tmp_data[j] / static_cast<double> (npts); |
458 | 1411 |
1948 | 1412 return retval; |
458 | 1413 } |
1414 | |
677 | 1415 ComplexMatrix |
1416 ComplexMatrix::fourier2d (void) const | |
1417 { | |
1948 | 1418 ComplexMatrix retval; |
1419 | |
5275 | 1420 octave_idx_type nr = rows (); |
1421 octave_idx_type nc = cols (); | |
1422 | |
1423 octave_idx_type npts, nsamples; | |
1948 | 1424 |
677 | 1425 if (nr == 1 || nc == 1) |
1426 { | |
1427 npts = nr > nc ? nr : nc; | |
1428 nsamples = 1; | |
1429 } | |
1430 else | |
1431 { | |
1432 npts = nr; | |
1433 nsamples = nc; | |
1434 } | |
1435 | |
5275 | 1436 octave_idx_type nn = 4*npts+15; |
1948 | 1437 |
1438 Array<Complex> wsave (nn); | |
1439 Complex *pwsave = wsave.fortran_vec (); | |
1440 | |
1441 retval = *this; | |
1442 Complex *tmp_data = retval.fortran_vec (); | |
1443 | |
3887 | 1444 F77_FUNC (cffti, CFFTI) (npts, pwsave); |
677 | 1445 |
5275 | 1446 for (octave_idx_type j = 0; j < nsamples; j++) |
4153 | 1447 { |
1448 OCTAVE_QUIT; | |
1449 | |
1450 F77_FUNC (cfftf, CFFTF) (npts, &tmp_data[npts*j], pwsave); | |
1451 } | |
677 | 1452 |
1453 npts = nc; | |
1454 nsamples = nr; | |
1455 nn = 4*npts+15; | |
1948 | 1456 |
1457 wsave.resize (nn); | |
1458 pwsave = wsave.fortran_vec (); | |
1459 | |
4773 | 1460 Array<Complex> tmp (npts); |
1461 Complex *prow = tmp.fortran_vec (); | |
1948 | 1462 |
3887 | 1463 F77_FUNC (cffti, CFFTI) (npts, pwsave); |
677 | 1464 |
5275 | 1465 for (octave_idx_type j = 0; j < nsamples; j++) |
677 | 1466 { |
4153 | 1467 OCTAVE_QUIT; |
1468 | |
5275 | 1469 for (octave_idx_type i = 0; i < npts; i++) |
1948 | 1470 prow[i] = tmp_data[i*nr + j]; |
1471 | |
3887 | 1472 F77_FUNC (cfftf, CFFTF) (npts, prow, pwsave); |
677 | 1473 |
5275 | 1474 for (octave_idx_type i = 0; i < npts; i++) |
1948 | 1475 tmp_data[i*nr + j] = prow[i]; |
677 | 1476 } |
1477 | |
1948 | 1478 return retval; |
677 | 1479 } |
1480 | |
1481 ComplexMatrix | |
1482 ComplexMatrix::ifourier2d (void) const | |
1483 { | |
1948 | 1484 ComplexMatrix retval; |
1485 | |
5275 | 1486 octave_idx_type nr = rows (); |
1487 octave_idx_type nc = cols (); | |
1488 | |
1489 octave_idx_type npts, nsamples; | |
1948 | 1490 |
677 | 1491 if (nr == 1 || nc == 1) |
1492 { | |
1493 npts = nr > nc ? nr : nc; | |
1494 nsamples = 1; | |
1495 } | |
1496 else | |
1497 { | |
1498 npts = nr; | |
1499 nsamples = nc; | |
1500 } | |
1501 | |
5275 | 1502 octave_idx_type nn = 4*npts+15; |
1948 | 1503 |
1504 Array<Complex> wsave (nn); | |
1505 Complex *pwsave = wsave.fortran_vec (); | |
1506 | |
1507 retval = *this; | |
1508 Complex *tmp_data = retval.fortran_vec (); | |
1509 | |
3887 | 1510 F77_FUNC (cffti, CFFTI) (npts, pwsave); |
677 | 1511 |
5275 | 1512 for (octave_idx_type j = 0; j < nsamples; j++) |
4153 | 1513 { |
1514 OCTAVE_QUIT; | |
1515 | |
1516 F77_FUNC (cfftb, CFFTB) (npts, &tmp_data[npts*j], pwsave); | |
1517 } | |
677 | 1518 |
5275 | 1519 for (octave_idx_type j = 0; j < npts*nsamples; j++) |
3572 | 1520 tmp_data[j] = tmp_data[j] / static_cast<double> (npts); |
677 | 1521 |
1522 npts = nc; | |
1523 nsamples = nr; | |
1524 nn = 4*npts+15; | |
1948 | 1525 |
1526 wsave.resize (nn); | |
1527 pwsave = wsave.fortran_vec (); | |
1528 | |
4773 | 1529 Array<Complex> tmp (npts); |
1530 Complex *prow = tmp.fortran_vec (); | |
1948 | 1531 |
3887 | 1532 F77_FUNC (cffti, CFFTI) (npts, pwsave); |
677 | 1533 |
5275 | 1534 for (octave_idx_type j = 0; j < nsamples; j++) |
677 | 1535 { |
4153 | 1536 OCTAVE_QUIT; |
1537 | |
5275 | 1538 for (octave_idx_type i = 0; i < npts; i++) |
1948 | 1539 prow[i] = tmp_data[i*nr + j]; |
1540 | |
3887 | 1541 F77_FUNC (cfftb, CFFTB) (npts, prow, pwsave); |
677 | 1542 |
5275 | 1543 for (octave_idx_type i = 0; i < npts; i++) |
3572 | 1544 tmp_data[i*nr + j] = prow[i] / static_cast<double> (npts); |
677 | 1545 } |
1546 | |
1948 | 1547 return retval; |
677 | 1548 } |
1549 | |
3827 | 1550 #endif |
1551 | |
458 | 1552 ComplexDET |
1553 ComplexMatrix::determinant (void) const | |
1554 { | |
5275 | 1555 octave_idx_type info; |
7788 | 1556 double rcon; |
1557 return determinant (info, rcon, 0); | |
458 | 1558 } |
1559 | |
1560 ComplexDET | |
5275 | 1561 ComplexMatrix::determinant (octave_idx_type& info) const |
458 | 1562 { |
7788 | 1563 double rcon; |
1564 return determinant (info, rcon, 0); | |
458 | 1565 } |
1566 | |
1567 ComplexDET | |
7788 | 1568 ComplexMatrix::determinant (octave_idx_type& info, double& rcon, int calc_cond) const |
458 | 1569 { |
1570 ComplexDET retval; | |
1571 | |
5275 | 1572 octave_idx_type nr = rows (); |
1573 octave_idx_type nc = cols (); | |
458 | 1574 |
1575 if (nr == 0 || nc == 0) | |
1576 { | |
5634 | 1577 retval = ComplexDET (1.0, 0); |
458 | 1578 } |
1579 else | |
1580 { | |
5275 | 1581 Array<octave_idx_type> ipvt (nr); |
1582 octave_idx_type *pipvt = ipvt.fortran_vec (); | |
1948 | 1583 |
1584 ComplexMatrix atmp = *this; | |
1585 Complex *tmp_data = atmp.fortran_vec (); | |
1586 | |
4329 | 1587 info = 0; |
1588 | |
4330 | 1589 // Calculate the norm of the matrix, for later use. |
4329 | 1590 double anorm = 0; |
1591 if (calc_cond) | |
5275 | 1592 anorm = atmp.abs().sum().row(static_cast<octave_idx_type>(0)).max(); |
4329 | 1593 |
1594 F77_XFCN (zgetrf, ZGETRF, (nr, nc, tmp_data, nr, pipvt, info)); | |
1948 | 1595 |
7482
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
1596 // Throw-away extra info LAPACK gives so as to not change output. |
7788 | 1597 rcon = 0.0; |
7482
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
1598 if (info != 0) |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
1599 { |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
1600 info = -1; |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
1601 retval = ComplexDET (); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
1602 } |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
1603 else |
458 | 1604 { |
7482
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
1605 if (calc_cond) |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
1606 { |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
1607 // Now calc the condition number for non-singular matrix. |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
1608 char job = '1'; |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
1609 Array<Complex> z (2*nr); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
1610 Complex *pz = z.fortran_vec (); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
1611 Array<double> rz (2*nr); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
1612 double *prz = rz.fortran_vec (); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
1613 |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
1614 F77_XFCN (zgecon, ZGECON, (F77_CONST_CHAR_ARG2 (&job, 1), |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
1615 nc, tmp_data, nr, anorm, |
7788 | 1616 rcon, pz, prz, info |
7482
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
1617 F77_CHAR_ARG_LEN (1))); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
1618 } |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
1619 |
4509 | 1620 if (info != 0) |
1948 | 1621 { |
1622 info = -1; | |
1623 retval = ComplexDET (); | |
4329 | 1624 } |
1625 else | |
1948 | 1626 { |
7482
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
1627 Complex c = 1.0; |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
1628 int e = 0; |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
1629 |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
1630 for (octave_idx_type i = 0; i < nc; i++) |
4329 | 1631 { |
7482
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
1632 if (ipvt(i) != (i+1)) |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
1633 c = -c; |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
1634 |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
1635 c *= atmp(i,i); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
1636 |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
1637 if (c == 0.0) |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
1638 break; |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
1639 |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
1640 while (std::abs(c) < 0.5) |
4329 | 1641 { |
7482
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
1642 c *= 2.0; |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
1643 e--; |
4329 | 1644 } |
5634 | 1645 |
7482
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
1646 while (std::abs(c) >= 2.0) |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
1647 { |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
1648 c /= 2.0; |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
1649 e++; |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
1650 } |
4329 | 1651 } |
7482
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
1652 |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
1653 retval = ComplexDET (c, e); |
1948 | 1654 } |
458 | 1655 } |
1656 } | |
4329 | 1657 |
458 | 1658 return retval; |
1659 } | |
1660 | |
7788 | 1661 double |
1662 ComplexMatrix::rcond (void) const | |
1663 { | |
1664 MatrixType mattype (*this); | |
1665 return rcond (mattype); | |
1666 } | |
1667 | |
1668 double | |
1669 ComplexMatrix::rcond (MatrixType &mattype) const | |
1670 { | |
1671 double rcon; | |
1672 octave_idx_type nr = rows (); | |
1673 octave_idx_type nc = cols (); | |
1674 | |
1675 if (nr != nc) | |
1676 (*current_liboctave_error_handler) ("matrix must be square"); | |
1677 else if (nr == 0 || nc == 0) | |
1678 rcon = octave_Inf; | |
1679 else | |
1680 { | |
1681 int typ = mattype.type (); | |
1682 | |
1683 if (typ == MatrixType::Unknown) | |
1684 typ = mattype.type (*this); | |
1685 | |
1686 // Only calculate the condition number for LU/Cholesky | |
1687 if (typ == MatrixType::Upper) | |
1688 { | |
1689 const Complex *tmp_data = fortran_vec (); | |
1690 octave_idx_type info = 0; | |
1691 char norm = '1'; | |
1692 char uplo = 'U'; | |
1693 char dia = 'N'; | |
1694 | |
1695 Array<Complex> z (2 * nc); | |
1696 Complex *pz = z.fortran_vec (); | |
1697 Array<double> rz (nc); | |
1698 double *prz = rz.fortran_vec (); | |
1699 | |
1700 F77_XFCN (ztrcon, ZTRCON, (F77_CONST_CHAR_ARG2 (&norm, 1), | |
1701 F77_CONST_CHAR_ARG2 (&uplo, 1), | |
1702 F77_CONST_CHAR_ARG2 (&dia, 1), | |
1703 nr, tmp_data, nr, rcon, | |
1704 pz, prz, info | |
1705 F77_CHAR_ARG_LEN (1) | |
1706 F77_CHAR_ARG_LEN (1) | |
1707 F77_CHAR_ARG_LEN (1))); | |
1708 | |
1709 if (info != 0) | |
1710 rcon = 0; | |
1711 } | |
1712 else if (typ == MatrixType::Permuted_Upper) | |
1713 (*current_liboctave_error_handler) | |
1714 ("permuted triangular matrix not implemented"); | |
1715 else if (typ == MatrixType::Lower) | |
1716 { | |
1717 const Complex *tmp_data = fortran_vec (); | |
1718 octave_idx_type info = 0; | |
1719 char norm = '1'; | |
1720 char uplo = 'L'; | |
1721 char dia = 'N'; | |
1722 | |
1723 Array<Complex> z (2 * nc); | |
1724 Complex *pz = z.fortran_vec (); | |
1725 Array<double> rz (nc); | |
1726 double *prz = rz.fortran_vec (); | |
1727 | |
1728 F77_XFCN (ztrcon, ZTRCON, (F77_CONST_CHAR_ARG2 (&norm, 1), | |
1729 F77_CONST_CHAR_ARG2 (&uplo, 1), | |
1730 F77_CONST_CHAR_ARG2 (&dia, 1), | |
1731 nr, tmp_data, nr, rcon, | |
1732 pz, prz, info | |
1733 F77_CHAR_ARG_LEN (1) | |
1734 F77_CHAR_ARG_LEN (1) | |
1735 F77_CHAR_ARG_LEN (1))); | |
1736 | |
1737 if (info != 0) | |
1738 rcon = 0.0; | |
1739 } | |
1740 else if (typ == MatrixType::Permuted_Lower) | |
1741 (*current_liboctave_error_handler) | |
1742 ("permuted triangular matrix not implemented"); | |
1743 else if (typ == MatrixType::Full || typ == MatrixType::Hermitian) | |
1744 { | |
1745 double anorm = -1.0; | |
1746 ComplexMatrix atmp = *this; | |
1747 Complex *tmp_data = atmp.fortran_vec (); | |
1748 | |
1749 if (typ == MatrixType::Hermitian) | |
1750 { | |
1751 octave_idx_type info = 0; | |
1752 char job = 'L'; | |
1753 anorm = atmp.abs().sum(). | |
1754 row(static_cast<octave_idx_type>(0)).max(); | |
1755 | |
1756 F77_XFCN (zpotrf, ZPOTRF, (F77_CONST_CHAR_ARG2 (&job, 1), nr, | |
1757 tmp_data, nr, info | |
1758 F77_CHAR_ARG_LEN (1))); | |
1759 | |
1760 if (info != 0) | |
1761 { | |
1762 rcon = 0.0; | |
1763 | |
1764 mattype.mark_as_unsymmetric (); | |
1765 typ = MatrixType::Full; | |
1766 } | |
1767 else | |
1768 { | |
1769 Array<Complex> z (2 * nc); | |
1770 Complex *pz = z.fortran_vec (); | |
1771 Array<double> rz (nc); | |
1772 double *prz = rz.fortran_vec (); | |
1773 | |
1774 F77_XFCN (zpocon, ZPOCON, (F77_CONST_CHAR_ARG2 (&job, 1), | |
1775 nr, tmp_data, nr, anorm, | |
1776 rcon, pz, prz, info | |
1777 F77_CHAR_ARG_LEN (1))); | |
1778 | |
1779 if (info != 0) | |
1780 rcon = 0.0; | |
1781 } | |
1782 } | |
1783 | |
1784 | |
1785 if (typ == MatrixType::Full) | |
1786 { | |
1787 octave_idx_type info = 0; | |
1788 | |
1789 Array<octave_idx_type> ipvt (nr); | |
1790 octave_idx_type *pipvt = ipvt.fortran_vec (); | |
1791 | |
1792 if(anorm < 0.) | |
1793 anorm = atmp.abs().sum(). | |
1794 row(static_cast<octave_idx_type>(0)).max(); | |
1795 | |
1796 Array<Complex> z (2 * nc); | |
1797 Complex *pz = z.fortran_vec (); | |
1798 Array<double> rz (2 * nc); | |
1799 double *prz = rz.fortran_vec (); | |
1800 | |
1801 F77_XFCN (zgetrf, ZGETRF, (nr, nr, tmp_data, nr, pipvt, info)); | |
1802 | |
1803 if (info != 0) | |
1804 { | |
1805 rcon = 0.0; | |
1806 mattype.mark_as_rectangular (); | |
1807 } | |
1808 else | |
1809 { | |
1810 char job = '1'; | |
1811 F77_XFCN (zgecon, ZGECON, (F77_CONST_CHAR_ARG2 (&job, 1), | |
1812 nc, tmp_data, nr, anorm, | |
1813 rcon, pz, prz, info | |
1814 F77_CHAR_ARG_LEN (1))); | |
1815 | |
1816 if (info != 0) | |
1817 rcon = 0.0; | |
1818 } | |
1819 } | |
1820 } | |
1821 else | |
1822 rcon = 0.0; | |
1823 } | |
1824 | |
1825 return rcon; | |
1826 } | |
1827 | |
458 | 1828 ComplexMatrix |
5785 | 1829 ComplexMatrix::utsolve (MatrixType &mattype, const ComplexMatrix& b, |
7788 | 1830 octave_idx_type& info, double& rcon, |
5785 | 1831 solve_singularity_handler sing_handler, |
1832 bool calc_cond) const | |
1833 { | |
1834 ComplexMatrix retval; | |
1835 | |
1836 octave_idx_type nr = rows (); | |
1837 octave_idx_type nc = cols (); | |
1838 | |
6924 | 1839 if (nr != b.rows ()) |
5785 | 1840 (*current_liboctave_error_handler) |
1841 ("matrix dimension mismatch solution of linear equations"); | |
6924 | 1842 else if (nr == 0 || nc == 0 || b.cols () == 0) |
1843 retval = ComplexMatrix (nc, b.cols (), Complex (0.0, 0.0)); | |
5785 | 1844 else |
1845 { | |
1846 volatile int typ = mattype.type (); | |
1847 | |
1848 if (typ == MatrixType::Permuted_Upper || | |
1849 typ == MatrixType::Upper) | |
1850 { | |
1851 octave_idx_type b_nc = b.cols (); | |
7788 | 1852 rcon = 1.; |
5785 | 1853 info = 0; |
1854 | |
1855 if (typ == MatrixType::Permuted_Upper) | |
1856 { | |
1857 (*current_liboctave_error_handler) | |
6390 | 1858 ("permuted triangular matrix not implemented"); |
5785 | 1859 } |
1860 else | |
1861 { | |
1862 const Complex *tmp_data = fortran_vec (); | |
1863 | |
1864 if (calc_cond) | |
1865 { | |
1866 char norm = '1'; | |
1867 char uplo = 'U'; | |
1868 char dia = 'N'; | |
1869 | |
1870 Array<Complex> z (2 * nc); | |
1871 Complex *pz = z.fortran_vec (); | |
1872 Array<double> rz (nc); | |
1873 double *prz = rz.fortran_vec (); | |
1874 | |
1875 F77_XFCN (ztrcon, ZTRCON, (F77_CONST_CHAR_ARG2 (&norm, 1), | |
1876 F77_CONST_CHAR_ARG2 (&uplo, 1), | |
1877 F77_CONST_CHAR_ARG2 (&dia, 1), | |
7788 | 1878 nr, tmp_data, nr, rcon, |
5785 | 1879 pz, prz, info |
1880 F77_CHAR_ARG_LEN (1) | |
1881 F77_CHAR_ARG_LEN (1) | |
1882 F77_CHAR_ARG_LEN (1))); | |
1883 | |
1884 if (info != 0) | |
1885 info = -2; | |
1886 | |
7788 | 1887 volatile double rcond_plus_one = rcon + 1.0; |
1888 | |
1889 if (rcond_plus_one == 1.0 || xisnan (rcon)) | |
5785 | 1890 { |
1891 info = -2; | |
1892 | |
1893 if (sing_handler) | |
7788 | 1894 sing_handler (rcon); |
5785 | 1895 else |
1896 (*current_liboctave_error_handler) | |
1897 ("matrix singular to machine precision, rcond = %g", | |
7788 | 1898 rcon); |
5785 | 1899 } |
1900 } | |
1901 | |
1902 if (info == 0) | |
1903 { | |
1904 retval = b; | |
1905 Complex *result = retval.fortran_vec (); | |
1906 | |
1907 char uplo = 'U'; | |
1908 char trans = 'N'; | |
1909 char dia = 'N'; | |
1910 | |
1911 F77_XFCN (ztrtrs, ZTRTRS, (F77_CONST_CHAR_ARG2 (&uplo, 1), | |
1912 F77_CONST_CHAR_ARG2 (&trans, 1), | |
1913 F77_CONST_CHAR_ARG2 (&dia, 1), | |
1914 nr, b_nc, tmp_data, nr, | |
1915 result, nr, info | |
1916 F77_CHAR_ARG_LEN (1) | |
1917 F77_CHAR_ARG_LEN (1) | |
1918 F77_CHAR_ARG_LEN (1))); | |
1919 } | |
1920 } | |
1921 } | |
1922 else | |
1923 (*current_liboctave_error_handler) ("incorrect matrix type"); | |
1924 } | |
1925 | |
1926 return retval; | |
1927 } | |
1928 | |
1929 ComplexMatrix | |
1930 ComplexMatrix::ltsolve (MatrixType &mattype, const ComplexMatrix& b, | |
7788 | 1931 octave_idx_type& info, double& rcon, |
5785 | 1932 solve_singularity_handler sing_handler, |
1933 bool calc_cond) const | |
1934 { | |
1935 ComplexMatrix retval; | |
1936 | |
1937 octave_idx_type nr = rows (); | |
1938 octave_idx_type nc = cols (); | |
1939 | |
6924 | 1940 if (nr != b.rows ()) |
5785 | 1941 (*current_liboctave_error_handler) |
1942 ("matrix dimension mismatch solution of linear equations"); | |
6924 | 1943 else if (nr == 0 || nc == 0 || b.cols () == 0) |
1944 retval = ComplexMatrix (nc, b.cols (), Complex (0.0, 0.0)); | |
5785 | 1945 else |
1946 { | |
1947 volatile int typ = mattype.type (); | |
1948 | |
1949 if (typ == MatrixType::Permuted_Lower || | |
1950 typ == MatrixType::Lower) | |
1951 { | |
1952 octave_idx_type b_nc = b.cols (); | |
7788 | 1953 rcon = 1.; |
5785 | 1954 info = 0; |
1955 | |
1956 if (typ == MatrixType::Permuted_Lower) | |
1957 { | |
1958 (*current_liboctave_error_handler) | |
6390 | 1959 ("permuted triangular matrix not implemented"); |
5785 | 1960 } |
1961 else | |
1962 { | |
1963 const Complex *tmp_data = fortran_vec (); | |
1964 | |
1965 if (calc_cond) | |
1966 { | |
1967 char norm = '1'; | |
1968 char uplo = 'L'; | |
1969 char dia = 'N'; | |
1970 | |
1971 Array<Complex> z (2 * nc); | |
1972 Complex *pz = z.fortran_vec (); | |
1973 Array<double> rz (nc); | |
1974 double *prz = rz.fortran_vec (); | |
1975 | |
1976 F77_XFCN (ztrcon, ZTRCON, (F77_CONST_CHAR_ARG2 (&norm, 1), | |
1977 F77_CONST_CHAR_ARG2 (&uplo, 1), | |
1978 F77_CONST_CHAR_ARG2 (&dia, 1), | |
7788 | 1979 nr, tmp_data, nr, rcon, |
5785 | 1980 pz, prz, info |
1981 F77_CHAR_ARG_LEN (1) | |
1982 F77_CHAR_ARG_LEN (1) | |
1983 F77_CHAR_ARG_LEN (1))); | |
1984 | |
1985 if (info != 0) | |
1986 info = -2; | |
1987 | |
7788 | 1988 volatile double rcond_plus_one = rcon + 1.0; |
1989 | |
1990 if (rcond_plus_one == 1.0 || xisnan (rcon)) | |
5785 | 1991 { |
1992 info = -2; | |
1993 | |
1994 if (sing_handler) | |
7788 | 1995 sing_handler (rcon); |
5785 | 1996 else |
1997 (*current_liboctave_error_handler) | |
1998 ("matrix singular to machine precision, rcond = %g", | |
7788 | 1999 rcon); |
5785 | 2000 } |
2001 } | |
2002 | |
2003 if (info == 0) | |
2004 { | |
2005 retval = b; | |
2006 Complex *result = retval.fortran_vec (); | |
2007 | |
2008 char uplo = 'L'; | |
2009 char trans = 'N'; | |
2010 char dia = 'N'; | |
2011 | |
2012 F77_XFCN (ztrtrs, ZTRTRS, (F77_CONST_CHAR_ARG2 (&uplo, 1), | |
2013 F77_CONST_CHAR_ARG2 (&trans, 1), | |
2014 F77_CONST_CHAR_ARG2 (&dia, 1), | |
2015 nr, b_nc, tmp_data, nr, | |
2016 result, nr, info | |
2017 F77_CHAR_ARG_LEN (1) | |
2018 F77_CHAR_ARG_LEN (1) | |
2019 F77_CHAR_ARG_LEN (1))); | |
2020 } | |
2021 } | |
2022 } | |
2023 else | |
2024 (*current_liboctave_error_handler) ("incorrect matrix type"); | |
2025 } | |
2026 | |
2027 return retval; | |
2028 } | |
2029 | |
2030 ComplexMatrix | |
2031 ComplexMatrix::fsolve (MatrixType &mattype, const ComplexMatrix& b, | |
7788 | 2032 octave_idx_type& info, double& rcon, |
5785 | 2033 solve_singularity_handler sing_handler, |
2034 bool calc_cond) const | |
2035 { | |
2036 ComplexMatrix retval; | |
2037 | |
2038 octave_idx_type nr = rows (); | |
2039 octave_idx_type nc = cols (); | |
2040 | |
6924 | 2041 |
2042 if (nr != nc || nr != b.rows ()) | |
5785 | 2043 (*current_liboctave_error_handler) |
6924 | 2044 ("matrix dimension mismatch solution of linear equations"); |
2045 else if (nr == 0 || b.cols () == 0) | |
2046 retval = ComplexMatrix (nc, b.cols (), Complex (0.0, 0.0)); | |
5785 | 2047 else |
2048 { | |
2049 volatile int typ = mattype.type (); | |
2050 | |
2051 // Calculate the norm of the matrix, for later use. | |
2052 double anorm = -1.; | |
2053 | |
2054 if (typ == MatrixType::Hermitian) | |
2055 { | |
2056 info = 0; | |
2057 char job = 'L'; | |
2058 ComplexMatrix atmp = *this; | |
2059 Complex *tmp_data = atmp.fortran_vec (); | |
2060 anorm = atmp.abs().sum().row(static_cast<octave_idx_type>(0)).max(); | |
2061 | |
2062 F77_XFCN (zpotrf, ZPOTRF, (F77_CONST_CHAR_ARG2 (&job, 1), nr, | |
2063 tmp_data, nr, info | |
2064 F77_CHAR_ARG_LEN (1))); | |
2065 | |
7482
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2066 // Throw-away extra info LAPACK gives so as to not change output. |
7788 | 2067 rcon = 0.0; |
7482
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2068 if (info != 0) |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2069 { |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2070 info = -2; |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2071 |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2072 mattype.mark_as_unsymmetric (); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2073 typ = MatrixType::Full; |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2074 } |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2075 else |
5785 | 2076 { |
7482
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2077 if (calc_cond) |
5785 | 2078 { |
7482
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2079 Array<Complex> z (2 * nc); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2080 Complex *pz = z.fortran_vec (); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2081 Array<double> rz (nc); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2082 double *prz = rz.fortran_vec (); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2083 |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2084 F77_XFCN (zpocon, ZPOCON, (F77_CONST_CHAR_ARG2 (&job, 1), |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2085 nr, tmp_data, nr, anorm, |
7788 | 2086 rcon, pz, prz, info |
7482
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2087 F77_CHAR_ARG_LEN (1))); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2088 |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2089 if (info != 0) |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2090 info = -2; |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2091 |
7788 | 2092 volatile double rcond_plus_one = rcon + 1.0; |
2093 | |
2094 if (rcond_plus_one == 1.0 || xisnan (rcon)) | |
7482
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2095 { |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2096 info = -2; |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2097 |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2098 if (sing_handler) |
7788 | 2099 sing_handler (rcon); |
7482
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2100 else |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2101 (*current_liboctave_error_handler) |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2102 ("matrix singular to machine precision, rcond = %g", |
7788 | 2103 rcon); |
7482
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2104 } |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2105 } |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2106 |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2107 if (info == 0) |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2108 { |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2109 retval = b; |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2110 Complex *result = retval.fortran_vec (); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2111 |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2112 octave_idx_type b_nc = b.cols (); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2113 |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2114 F77_XFCN (zpotrs, ZPOTRS, (F77_CONST_CHAR_ARG2 (&job, 1), |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2115 nr, b_nc, tmp_data, nr, |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2116 result, b.rows(), info |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2117 F77_CHAR_ARG_LEN (1))); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2118 } |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2119 else |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2120 { |
5785 | 2121 mattype.mark_as_unsymmetric (); |
2122 typ = MatrixType::Full; | |
2123 } | |
2124 } | |
2125 } | |
2126 | |
2127 if (typ == MatrixType::Full) | |
2128 { | |
2129 info = 0; | |
2130 | |
2131 Array<octave_idx_type> ipvt (nr); | |
2132 octave_idx_type *pipvt = ipvt.fortran_vec (); | |
2133 | |
2134 ComplexMatrix atmp = *this; | |
2135 Complex *tmp_data = atmp.fortran_vec (); | |
2136 | |
2137 Array<Complex> z (2 * nc); | |
2138 Complex *pz = z.fortran_vec (); | |
2139 Array<double> rz (2 * nc); | |
2140 double *prz = rz.fortran_vec (); | |
2141 | |
2142 // Calculate the norm of the matrix, for later use. | |
2143 if (anorm < 0.) | |
2144 anorm = atmp.abs().sum().row(static_cast<octave_idx_type>(0)).max(); | |
2145 | |
2146 F77_XFCN (zgetrf, ZGETRF, (nr, nr, tmp_data, nr, pipvt, info)); | |
2147 | |
7482
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2148 // Throw-away extra info LAPACK gives so as to not change output. |
7788 | 2149 rcon = 0.0; |
7482
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2150 if (info != 0) |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2151 { |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2152 info = -2; |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2153 |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2154 if (sing_handler) |
7788 | 2155 sing_handler (rcon); |
7482
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2156 else |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2157 (*current_liboctave_error_handler) |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2158 ("matrix singular to machine precision"); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2159 |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2160 mattype.mark_as_rectangular (); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2161 } |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2162 else |
5785 | 2163 { |
7482
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2164 if (calc_cond) |
5785 | 2165 { |
7482
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2166 // Now calculate the condition number for |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2167 // non-singular matrix. |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2168 char job = '1'; |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2169 F77_XFCN (zgecon, ZGECON, (F77_CONST_CHAR_ARG2 (&job, 1), |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2170 nc, tmp_data, nr, anorm, |
7788 | 2171 rcon, pz, prz, info |
7482
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2172 F77_CHAR_ARG_LEN (1))); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2173 |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2174 if (info != 0) |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2175 info = -2; |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2176 |
7788 | 2177 volatile double rcond_plus_one = rcon + 1.0; |
2178 | |
2179 if (rcond_plus_one == 1.0 || xisnan (rcon)) | |
5785 | 2180 { |
7482
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2181 info = -2; |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2182 |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2183 if (sing_handler) |
7788 | 2184 sing_handler (rcon); |
7482
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2185 else |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2186 (*current_liboctave_error_handler) |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2187 ("matrix singular to machine precision, rcond = %g", |
7788 | 2188 rcon); |
5785 | 2189 } |
2190 } | |
7482
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2191 |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2192 if (info == 0) |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2193 { |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2194 retval = b; |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2195 Complex *result = retval.fortran_vec (); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2196 |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2197 octave_idx_type b_nc = b.cols (); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2198 |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2199 char job = 'N'; |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2200 F77_XFCN (zgetrs, ZGETRS, (F77_CONST_CHAR_ARG2 (&job, 1), |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2201 nr, b_nc, tmp_data, nr, |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2202 pipvt, result, b.rows(), info |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2203 F77_CHAR_ARG_LEN (1))); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2204 } |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2205 else |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2206 mattype.mark_as_rectangular (); |
5785 | 2207 } |
2208 } | |
2209 } | |
2210 | |
2211 return retval; | |
2212 } | |
2213 | |
2214 ComplexMatrix | |
2215 ComplexMatrix::solve (MatrixType &typ, const Matrix& b) const | |
2216 { | |
2217 octave_idx_type info; | |
7788 | 2218 double rcon; |
2219 return solve (typ, b, info, rcon, 0); | |
5785 | 2220 } |
2221 | |
2222 ComplexMatrix | |
2223 ComplexMatrix::solve (MatrixType &typ, const Matrix& b, | |
2224 octave_idx_type& info) const | |
2225 { | |
7788 | 2226 double rcon; |
2227 return solve (typ, b, info, rcon, 0); | |
5785 | 2228 } |
2229 | |
2230 ComplexMatrix | |
2231 ComplexMatrix::solve (MatrixType &typ, const Matrix& b, octave_idx_type& info, | |
7788 | 2232 double& rcon) const |
5785 | 2233 { |
7788 | 2234 return solve (typ, b, info, rcon, 0); |
5785 | 2235 } |
2236 | |
2237 ComplexMatrix | |
2238 ComplexMatrix::solve (MatrixType &typ, const Matrix& b, octave_idx_type& info, | |
7788 | 2239 double& rcon, solve_singularity_handler sing_handler, |
5785 | 2240 bool singular_fallback) const |
2241 { | |
2242 ComplexMatrix tmp (b); | |
7788 | 2243 return solve (typ, tmp, info, rcon, sing_handler, singular_fallback); |
5785 | 2244 } |
2245 | |
2246 ComplexMatrix | |
2247 ComplexMatrix::solve (MatrixType &typ, const ComplexMatrix& b) const | |
2248 { | |
2249 octave_idx_type info; | |
7788 | 2250 double rcon; |
2251 return solve (typ, b, info, rcon, 0); | |
5785 | 2252 } |
2253 | |
2254 ComplexMatrix | |
2255 ComplexMatrix::solve (MatrixType &typ, const ComplexMatrix& b, | |
2256 octave_idx_type& info) const | |
2257 { | |
7788 | 2258 double rcon; |
2259 return solve (typ, b, info, rcon, 0); | |
5785 | 2260 } |
2261 | |
2262 ComplexMatrix | |
2263 ComplexMatrix::solve (MatrixType &typ, const ComplexMatrix& b, | |
7788 | 2264 octave_idx_type& info, double& rcon) const |
5785 | 2265 { |
7788 | 2266 return solve (typ, b, info, rcon, 0); |
5785 | 2267 } |
2268 | |
2269 ComplexMatrix | |
2270 ComplexMatrix::solve (MatrixType &mattype, const ComplexMatrix& b, | |
7788 | 2271 octave_idx_type& info, double& rcon, |
5785 | 2272 solve_singularity_handler sing_handler, |
2273 bool singular_fallback) const | |
2274 { | |
2275 ComplexMatrix retval; | |
2276 int typ = mattype.type (); | |
2277 | |
2278 if (typ == MatrixType::Unknown) | |
2279 typ = mattype.type (*this); | |
2280 | |
2281 // Only calculate the condition number for LU/Cholesky | |
2282 if (typ == MatrixType::Upper || typ == MatrixType::Permuted_Upper) | |
7788 | 2283 retval = utsolve (mattype, b, info, rcon, sing_handler, false); |
5785 | 2284 else if (typ == MatrixType::Lower || typ == MatrixType::Permuted_Lower) |
7788 | 2285 retval = ltsolve (mattype, b, info, rcon, sing_handler, false); |
5785 | 2286 else if (typ == MatrixType::Full || typ == MatrixType::Hermitian) |
7788 | 2287 retval = fsolve (mattype, b, info, rcon, sing_handler, true); |
5785 | 2288 else if (typ != MatrixType::Rectangular) |
2289 { | |
2290 (*current_liboctave_error_handler) ("unknown matrix type"); | |
2291 return ComplexMatrix (); | |
2292 } | |
2293 | |
2294 // Rectangular or one of the above solvers flags a singular matrix | |
2295 if (singular_fallback && mattype.type () == MatrixType::Rectangular) | |
2296 { | |
2297 octave_idx_type rank; | |
7788 | 2298 retval = lssolve (b, info, rank, rcon); |
5785 | 2299 } |
2300 | |
2301 return retval; | |
2302 } | |
2303 | |
2304 ComplexColumnVector | |
2305 ComplexMatrix::solve (MatrixType &typ, const ColumnVector& b) const | |
2306 { | |
2307 octave_idx_type info; | |
7788 | 2308 double rcon; |
2309 return solve (typ, ComplexColumnVector (b), info, rcon, 0); | |
5785 | 2310 } |
2311 | |
2312 ComplexColumnVector | |
2313 ComplexMatrix::solve (MatrixType &typ, const ColumnVector& b, | |
2314 octave_idx_type& info) const | |
2315 { | |
7788 | 2316 double rcon; |
2317 return solve (typ, ComplexColumnVector (b), info, rcon, 0); | |
5785 | 2318 } |
2319 | |
2320 ComplexColumnVector | |
2321 ComplexMatrix::solve (MatrixType &typ, const ColumnVector& b, | |
7788 | 2322 octave_idx_type& info, double& rcon) const |
5785 | 2323 { |
7788 | 2324 return solve (typ, ComplexColumnVector (b), info, rcon, 0); |
5785 | 2325 } |
2326 | |
2327 ComplexColumnVector | |
2328 ComplexMatrix::solve (MatrixType &typ, const ColumnVector& b, | |
7788 | 2329 octave_idx_type& info, double& rcon, |
5785 | 2330 solve_singularity_handler sing_handler) const |
2331 { | |
7788 | 2332 return solve (typ, ComplexColumnVector (b), info, rcon, sing_handler); |
5785 | 2333 } |
2334 | |
2335 ComplexColumnVector | |
2336 ComplexMatrix::solve (MatrixType &typ, const ComplexColumnVector& b) const | |
2337 { | |
2338 octave_idx_type info; | |
7788 | 2339 double rcon; |
2340 return solve (typ, b, info, rcon, 0); | |
5785 | 2341 } |
2342 | |
2343 ComplexColumnVector | |
2344 ComplexMatrix::solve (MatrixType &typ, const ComplexColumnVector& b, | |
2345 octave_idx_type& info) const | |
2346 { | |
7788 | 2347 double rcon; |
2348 return solve (typ, b, info, rcon, 0); | |
5785 | 2349 } |
2350 | |
2351 ComplexColumnVector | |
2352 ComplexMatrix::solve (MatrixType &typ, const ComplexColumnVector& b, | |
7788 | 2353 octave_idx_type& info, double& rcon) const |
5785 | 2354 { |
7788 | 2355 return solve (typ, b, info, rcon, 0); |
5785 | 2356 } |
2357 | |
2358 ComplexColumnVector | |
2359 ComplexMatrix::solve (MatrixType &typ, const ComplexColumnVector& b, | |
7788 | 2360 octave_idx_type& info, double& rcon, |
5785 | 2361 solve_singularity_handler sing_handler) const |
2362 { | |
2363 | |
2364 ComplexMatrix tmp (b); | |
7788 | 2365 return solve (typ, tmp, info, rcon, sing_handler).column(static_cast<octave_idx_type> (0)); |
5785 | 2366 } |
2367 | |
2368 ComplexMatrix | |
458 | 2369 ComplexMatrix::solve (const Matrix& b) const |
2370 { | |
5275 | 2371 octave_idx_type info; |
7788 | 2372 double rcon; |
2373 return solve (b, info, rcon, 0); | |
458 | 2374 } |
2375 | |
2376 ComplexMatrix | |
5275 | 2377 ComplexMatrix::solve (const Matrix& b, octave_idx_type& info) const |
458 | 2378 { |
7788 | 2379 double rcon; |
2380 return solve (b, info, rcon, 0); | |
458 | 2381 } |
2382 | |
2383 ComplexMatrix | |
7788 | 2384 ComplexMatrix::solve (const Matrix& b, octave_idx_type& info, double& rcon) const |
458 | 2385 { |
7788 | 2386 return solve (b, info, rcon, 0); |
3480 | 2387 } |
2388 | |
2389 ComplexMatrix | |
7788 | 2390 ComplexMatrix::solve (const Matrix& b, octave_idx_type& info, double& rcon, |
3480 | 2391 solve_singularity_handler sing_handler) const |
2392 { | |
458 | 2393 ComplexMatrix tmp (b); |
7788 | 2394 return solve (tmp, info, rcon, sing_handler); |
458 | 2395 } |
2396 | |
2397 ComplexMatrix | |
2398 ComplexMatrix::solve (const ComplexMatrix& b) const | |
2399 { | |
5275 | 2400 octave_idx_type info; |
7788 | 2401 double rcon; |
2402 return solve (b, info, rcon, 0); | |
458 | 2403 } |
2404 | |
2405 ComplexMatrix | |
5275 | 2406 ComplexMatrix::solve (const ComplexMatrix& b, octave_idx_type& info) const |
458 | 2407 { |
7788 | 2408 double rcon; |
2409 return solve (b, info, rcon, 0); | |
458 | 2410 } |
3480 | 2411 |
458 | 2412 ComplexMatrix |
7788 | 2413 ComplexMatrix::solve (const ComplexMatrix& b, octave_idx_type& info, double& rcon) const |
458 | 2414 { |
7788 | 2415 return solve (b, info, rcon, 0); |
3480 | 2416 } |
2417 | |
2418 ComplexMatrix | |
7788 | 2419 ComplexMatrix::solve (const ComplexMatrix& b, octave_idx_type& info, double& rcon, |
3480 | 2420 solve_singularity_handler sing_handler) const |
2421 { | |
5785 | 2422 MatrixType mattype (*this); |
7788 | 2423 return solve (mattype, b, info, rcon, sing_handler); |
458 | 2424 } |
2425 | |
2426 ComplexColumnVector | |
3585 | 2427 ComplexMatrix::solve (const ColumnVector& b) const |
2428 { | |
5275 | 2429 octave_idx_type info; |
7788 | 2430 double rcon; |
2431 return solve (ComplexColumnVector (b), info, rcon, 0); | |
3585 | 2432 } |
2433 | |
2434 ComplexColumnVector | |
5275 | 2435 ComplexMatrix::solve (const ColumnVector& b, octave_idx_type& info) const |
3585 | 2436 { |
7788 | 2437 double rcon; |
2438 return solve (ComplexColumnVector (b), info, rcon, 0); | |
3585 | 2439 } |
2440 | |
2441 ComplexColumnVector | |
5785 | 2442 ComplexMatrix::solve (const ColumnVector& b, octave_idx_type& info, |
7788 | 2443 double& rcon) const |
3585 | 2444 { |
7788 | 2445 return solve (ComplexColumnVector (b), info, rcon, 0); |
3585 | 2446 } |
2447 | |
2448 ComplexColumnVector | |
5785 | 2449 ComplexMatrix::solve (const ColumnVector& b, octave_idx_type& info, |
7788 | 2450 double& rcon, |
3585 | 2451 solve_singularity_handler sing_handler) const |
2452 { | |
7788 | 2453 return solve (ComplexColumnVector (b), info, rcon, sing_handler); |
3585 | 2454 } |
2455 | |
2456 ComplexColumnVector | |
458 | 2457 ComplexMatrix::solve (const ComplexColumnVector& b) const |
2458 { | |
5275 | 2459 octave_idx_type info; |
7788 | 2460 double rcon; |
2461 return solve (b, info, rcon, 0); | |
458 | 2462 } |
2463 | |
2464 ComplexColumnVector | |
5275 | 2465 ComplexMatrix::solve (const ComplexColumnVector& b, octave_idx_type& info) const |
458 | 2466 { |
7788 | 2467 double rcon; |
2468 return solve (b, info, rcon, 0); | |
458 | 2469 } |
2470 | |
2471 ComplexColumnVector | |
5275 | 2472 ComplexMatrix::solve (const ComplexColumnVector& b, octave_idx_type& info, |
7788 | 2473 double& rcon) const |
458 | 2474 { |
7788 | 2475 return solve (b, info, rcon, 0); |
3480 | 2476 } |
2477 | |
2478 ComplexColumnVector | |
5275 | 2479 ComplexMatrix::solve (const ComplexColumnVector& b, octave_idx_type& info, |
7788 | 2480 double& rcon, |
3480 | 2481 solve_singularity_handler sing_handler) const |
2482 { | |
5785 | 2483 MatrixType mattype (*this); |
7788 | 2484 return solve (mattype, b, info, rcon, sing_handler); |
458 | 2485 } |
2486 | |
2487 ComplexMatrix | |
3585 | 2488 ComplexMatrix::lssolve (const Matrix& b) const |
2489 { | |
5275 | 2490 octave_idx_type info; |
2491 octave_idx_type rank; | |
7788 | 2492 double rcon; |
2493 return lssolve (ComplexMatrix (b), info, rank, rcon); | |
3585 | 2494 } |
2495 | |
2496 ComplexMatrix | |
5275 | 2497 ComplexMatrix::lssolve (const Matrix& b, octave_idx_type& info) const |
3585 | 2498 { |
5275 | 2499 octave_idx_type rank; |
7788 | 2500 double rcon; |
2501 return lssolve (ComplexMatrix (b), info, rank, rcon); | |
3585 | 2502 } |
2503 | |
2504 ComplexMatrix | |
7076 | 2505 ComplexMatrix::lssolve (const Matrix& b, octave_idx_type& info, |
2506 octave_idx_type& rank) const | |
3585 | 2507 { |
7788 | 2508 double rcon; |
2509 return lssolve (ComplexMatrix (b), info, rank, rcon); | |
7076 | 2510 } |
2511 | |
2512 ComplexMatrix | |
2513 ComplexMatrix::lssolve (const Matrix& b, octave_idx_type& info, | |
7788 | 2514 octave_idx_type& rank, double& rcon) const |
7076 | 2515 { |
7788 | 2516 return lssolve (ComplexMatrix (b), info, rank, rcon); |
3585 | 2517 } |
2518 | |
2519 ComplexMatrix | |
458 | 2520 ComplexMatrix::lssolve (const ComplexMatrix& b) const |
2521 { | |
5275 | 2522 octave_idx_type info; |
2523 octave_idx_type rank; | |
7788 | 2524 double rcon; |
2525 return lssolve (b, info, rank, rcon); | |
458 | 2526 } |
2527 | |
2528 ComplexMatrix | |
5275 | 2529 ComplexMatrix::lssolve (const ComplexMatrix& b, octave_idx_type& info) const |
458 | 2530 { |
5275 | 2531 octave_idx_type rank; |
7788 | 2532 double rcon; |
2533 return lssolve (b, info, rank, rcon); | |
458 | 2534 } |
2535 | |
2536 ComplexMatrix | |
7076 | 2537 ComplexMatrix::lssolve (const ComplexMatrix& b, octave_idx_type& info, |
2538 octave_idx_type& rank) const | |
2539 { | |
7788 | 2540 double rcon; |
2541 return lssolve (b, info, rank, rcon); | |
7076 | 2542 } |
2543 | |
2544 ComplexMatrix | |
2545 ComplexMatrix::lssolve (const ComplexMatrix& b, octave_idx_type& info, | |
7788 | 2546 octave_idx_type& rank, double& rcon) const |
458 | 2547 { |
1948 | 2548 ComplexMatrix retval; |
2549 | |
5275 | 2550 octave_idx_type nrhs = b.cols (); |
2551 | |
2552 octave_idx_type m = rows (); | |
2553 octave_idx_type n = cols (); | |
458 | 2554 |
6924 | 2555 if (m != b.rows ()) |
1948 | 2556 (*current_liboctave_error_handler) |
2557 ("matrix dimension mismatch solution of linear equations"); | |
6924 | 2558 else if (m== 0 || n == 0 || b.cols () == 0) |
2559 retval = ComplexMatrix (n, b.cols (), Complex (0.0, 0.0)); | |
1948 | 2560 else |
458 | 2561 { |
7072 | 2562 volatile octave_idx_type minmn = (m < n ? m : n); |
2563 octave_idx_type maxmn = m > n ? m : n; | |
7788 | 2564 rcon = -1.0; |
7072 | 2565 |
2566 if (m != n) | |
2567 { | |
2568 retval = ComplexMatrix (maxmn, nrhs); | |
2569 | |
2570 for (octave_idx_type j = 0; j < nrhs; j++) | |
2571 for (octave_idx_type i = 0; i < m; i++) | |
2572 retval.elem (i, j) = b.elem (i, j); | |
2573 } | |
2574 else | |
2575 retval = b; | |
2576 | |
1948 | 2577 ComplexMatrix atmp = *this; |
2578 Complex *tmp_data = atmp.fortran_vec (); | |
2579 | |
7072 | 2580 Complex *pretval = retval.fortran_vec (); |
2581 Array<double> s (minmn); | |
7071 | 2582 double *ps = s.fortran_vec (); |
2563 | 2583 |
7072 | 2584 // Ask ZGELSD what the dimension of WORK should be. |
5275 | 2585 octave_idx_type lwork = -1; |
3752 | 2586 |
2587 Array<Complex> work (1); | |
7079 | 2588 |
7477 | 2589 octave_idx_type smlsiz; |
2590 F77_FUNC (xilaenv, XILAENV) (9, F77_CONST_CHAR_ARG2 ("ZGELSD", 6), | |
2591 F77_CONST_CHAR_ARG2 (" ", 1), | |
7478 | 2592 0, 0, 0, 0, smlsiz |
7477 | 2593 F77_CHAR_ARG_LEN (6) |
7478 | 2594 F77_CHAR_ARG_LEN (1)); |
7079 | 2595 |
7486
6a6d2abe51ff
more xGELSD workspace fixes
John W. Eaton <jwe@octave.org>
parents:
7482
diff
changeset
|
2596 octave_idx_type mnthr; |
6a6d2abe51ff
more xGELSD workspace fixes
John W. Eaton <jwe@octave.org>
parents:
7482
diff
changeset
|
2597 F77_FUNC (xilaenv, XILAENV) (6, F77_CONST_CHAR_ARG2 ("ZGELSD", 6), |
6a6d2abe51ff
more xGELSD workspace fixes
John W. Eaton <jwe@octave.org>
parents:
7482
diff
changeset
|
2598 F77_CONST_CHAR_ARG2 (" ", 1), |
6a6d2abe51ff
more xGELSD workspace fixes
John W. Eaton <jwe@octave.org>
parents:
7482
diff
changeset
|
2599 m, n, nrhs, -1, mnthr |
6a6d2abe51ff
more xGELSD workspace fixes
John W. Eaton <jwe@octave.org>
parents:
7482
diff
changeset
|
2600 F77_CHAR_ARG_LEN (6) |
6a6d2abe51ff
more xGELSD workspace fixes
John W. Eaton <jwe@octave.org>
parents:
7482
diff
changeset
|
2601 F77_CHAR_ARG_LEN (1)); |
6a6d2abe51ff
more xGELSD workspace fixes
John W. Eaton <jwe@octave.org>
parents:
7482
diff
changeset
|
2602 |
7079 | 2603 // We compute the size of rwork and iwork because ZGELSD in |
2604 // older versions of LAPACK does not return them on a query | |
2605 // call. | |
7124 | 2606 double dminmn = static_cast<double> (minmn); |
2607 double dsmlsizp1 = static_cast<double> (smlsiz+1); | |
7079 | 2608 #if defined (HAVE_LOG2) |
7544
f9983d2761df
more xGELSD workspace fixes
Jaroslav Hajek <highegg@gmail.com>
parents:
7532
diff
changeset
|
2609 double tmp = log2 (dminmn / dsmlsizp1); |
7079 | 2610 #else |
7544
f9983d2761df
more xGELSD workspace fixes
Jaroslav Hajek <highegg@gmail.com>
parents:
7532
diff
changeset
|
2611 double tmp = log (dminmn / dsmlsizp1) / log (2.0); |
7079 | 2612 #endif |
7544
f9983d2761df
more xGELSD workspace fixes
Jaroslav Hajek <highegg@gmail.com>
parents:
7532
diff
changeset
|
2613 octave_idx_type nlvl = static_cast<octave_idx_type> (tmp) + 1; |
7079 | 2614 if (nlvl < 0) |
2615 nlvl = 0; | |
2616 | |
2617 octave_idx_type lrwork = minmn*(10 + 2*smlsiz + 8*nlvl) | |
2618 + 3*smlsiz*nrhs + (smlsiz+1)*(smlsiz+1); | |
2619 if (lrwork < 1) | |
2620 lrwork = 1; | |
2621 Array<double> rwork (lrwork); | |
2622 double *prwork = rwork.fortran_vec (); | |
2623 | |
2624 octave_idx_type liwork = 3 * minmn * nlvl + 11 * minmn; | |
2625 if (liwork < 1) | |
2626 liwork = 1; | |
2627 Array<octave_idx_type> iwork (liwork); | |
2628 octave_idx_type* piwork = iwork.fortran_vec (); | |
7072 | 2629 |
2630 F77_XFCN (zgelsd, ZGELSD, (m, n, nrhs, tmp_data, m, pretval, maxmn, | |
7788 | 2631 ps, rcon, rank, work.fortran_vec (), |
7079 | 2632 lwork, prwork, piwork, info)); |
1948 | 2633 |
7476 | 2634 // The workspace query is broken in at least LAPACK 3.0.0 |
7488
6470f946a425
another small xGELSD workspace fix
John W. Eaton <jwe@octave.org>
parents:
7486
diff
changeset
|
2635 // through 3.1.1 when n >= mnthr. The obtuse formula below |
7486
6a6d2abe51ff
more xGELSD workspace fixes
John W. Eaton <jwe@octave.org>
parents:
7482
diff
changeset
|
2636 // should provide sufficient workspace for ZGELSD to operate |
7476 | 2637 // efficiently. |
7488
6470f946a425
another small xGELSD workspace fix
John W. Eaton <jwe@octave.org>
parents:
7486
diff
changeset
|
2638 if (n >= mnthr) |
7476 | 2639 { |
2640 octave_idx_type addend = m; | |
2641 | |
2642 if (2*m-4 > addend) | |
2643 addend = 2*m-4; | |
2644 | |
2645 if (nrhs > addend) | |
2646 addend = nrhs; | |
2647 | |
2648 if (n-3*m > addend) | |
2649 addend = n-3*m; | |
2650 | |
2651 const octave_idx_type lworkaround = 4*m + m*m + addend; | |
2652 | |
2653 if (std::real (work(0)) < lworkaround) | |
2654 work(0) = lworkaround; | |
2655 } | |
7532
493bb0de3199
avoid another xGELSD workspace query bug
John W. Eaton <jwe@octave.org>
parents:
7503
diff
changeset
|
2656 else if (m >= n) |
493bb0de3199
avoid another xGELSD workspace query bug
John W. Eaton <jwe@octave.org>
parents:
7503
diff
changeset
|
2657 { |
493bb0de3199
avoid another xGELSD workspace query bug
John W. Eaton <jwe@octave.org>
parents:
7503
diff
changeset
|
2658 octave_idx_type lworkaround = 2*m + m*nrhs; |
493bb0de3199
avoid another xGELSD workspace query bug
John W. Eaton <jwe@octave.org>
parents:
7503
diff
changeset
|
2659 |
493bb0de3199
avoid another xGELSD workspace query bug
John W. Eaton <jwe@octave.org>
parents:
7503
diff
changeset
|
2660 if (std::real (work(0)) < lworkaround) |
493bb0de3199
avoid another xGELSD workspace query bug
John W. Eaton <jwe@octave.org>
parents:
7503
diff
changeset
|
2661 work(0) = lworkaround; |
493bb0de3199
avoid another xGELSD workspace query bug
John W. Eaton <jwe@octave.org>
parents:
7503
diff
changeset
|
2662 } |
7476 | 2663 |
7482
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2664 lwork = static_cast<octave_idx_type> (std::real (work(0))); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2665 work.resize (lwork); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2666 |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2667 F77_XFCN (zgelsd, ZGELSD, (m, n, nrhs, tmp_data, m, pretval, |
7788 | 2668 maxmn, ps, rcon, rank, |
7482
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2669 work.fortran_vec (), lwork, |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2670 prwork, piwork, info)); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2671 |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2672 if (rank < minmn) |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2673 (*current_liboctave_warning_handler) |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2674 ("zgelsd: rank deficient %dx%d matrix, rank = %d, tol = %e", |
7788 | 2675 m, n, rank, rcon); |
7482
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2676 |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2677 if (s.elem (0) == 0.0) |
7788 | 2678 rcon = 0.0; |
1948 | 2679 else |
7788 | 2680 rcon = s.elem (minmn - 1) / s.elem (0); |
7482
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2681 |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2682 retval.resize (n, nrhs); |
458 | 2683 } |
2684 | |
2685 return retval; | |
2686 } | |
2687 | |
2688 ComplexColumnVector | |
3585 | 2689 ComplexMatrix::lssolve (const ColumnVector& b) const |
2690 { | |
5275 | 2691 octave_idx_type info; |
2692 octave_idx_type rank; | |
7788 | 2693 double rcon; |
2694 return lssolve (ComplexColumnVector (b), info, rank, rcon); | |
3585 | 2695 } |
2696 | |
2697 ComplexColumnVector | |
5275 | 2698 ComplexMatrix::lssolve (const ColumnVector& b, octave_idx_type& info) const |
3585 | 2699 { |
5275 | 2700 octave_idx_type rank; |
7788 | 2701 double rcon; |
2702 return lssolve (ComplexColumnVector (b), info, rank, rcon); | |
3585 | 2703 } |
2704 | |
2705 ComplexColumnVector | |
7076 | 2706 ComplexMatrix::lssolve (const ColumnVector& b, octave_idx_type& info, |
2707 octave_idx_type& rank) const | |
3585 | 2708 { |
7788 | 2709 double rcon; |
2710 return lssolve (ComplexColumnVector (b), info, rank, rcon); | |
7076 | 2711 } |
2712 | |
2713 ComplexColumnVector | |
2714 ComplexMatrix::lssolve (const ColumnVector& b, octave_idx_type& info, | |
7788 | 2715 octave_idx_type& rank, double& rcon) const |
7076 | 2716 { |
7788 | 2717 return lssolve (ComplexColumnVector (b), info, rank, rcon); |
3585 | 2718 } |
2719 | |
2720 ComplexColumnVector | |
458 | 2721 ComplexMatrix::lssolve (const ComplexColumnVector& b) const |
2722 { | |
5275 | 2723 octave_idx_type info; |
2724 octave_idx_type rank; | |
7788 | 2725 double rcon; |
2726 return lssolve (b, info, rank, rcon); | |
458 | 2727 } |
2728 | |
2729 ComplexColumnVector | |
5275 | 2730 ComplexMatrix::lssolve (const ComplexColumnVector& b, octave_idx_type& info) const |
458 | 2731 { |
5275 | 2732 octave_idx_type rank; |
7788 | 2733 double rcon; |
2734 return lssolve (b, info, rank, rcon); | |
458 | 2735 } |
2736 | |
2737 ComplexColumnVector | |
5275 | 2738 ComplexMatrix::lssolve (const ComplexColumnVector& b, octave_idx_type& info, |
2739 octave_idx_type& rank) const | |
458 | 2740 { |
7788 | 2741 double rcon; |
2742 return lssolve (b, info, rank, rcon); | |
7076 | 2743 |
2744 } | |
2745 | |
2746 ComplexColumnVector | |
2747 ComplexMatrix::lssolve (const ComplexColumnVector& b, octave_idx_type& info, | |
7788 | 2748 octave_idx_type& rank, double& rcon) const |
7076 | 2749 { |
1948 | 2750 ComplexColumnVector retval; |
2751 | |
5275 | 2752 octave_idx_type nrhs = 1; |
2753 | |
2754 octave_idx_type m = rows (); | |
2755 octave_idx_type n = cols (); | |
458 | 2756 |
6924 | 2757 if (m != b.length ()) |
1948 | 2758 (*current_liboctave_error_handler) |
6924 | 2759 ("matrix dimension mismatch solution of linear equations"); |
2760 else if (m == 0 || n == 0 || b.cols () == 0) | |
2761 retval = ComplexColumnVector (n, Complex (0.0, 0.0)); | |
1948 | 2762 else |
458 | 2763 { |
7072 | 2764 volatile octave_idx_type minmn = (m < n ? m : n); |
2765 octave_idx_type maxmn = m > n ? m : n; | |
7788 | 2766 rcon = -1.0; |
7072 | 2767 |
2768 if (m != n) | |
2769 { | |
2770 retval = ComplexColumnVector (maxmn); | |
2771 | |
2772 for (octave_idx_type i = 0; i < m; i++) | |
2773 retval.elem (i) = b.elem (i); | |
2774 } | |
2775 else | |
2776 retval = b; | |
2777 | |
1948 | 2778 ComplexMatrix atmp = *this; |
2779 Complex *tmp_data = atmp.fortran_vec (); | |
2780 | |
7072 | 2781 Complex *pretval = retval.fortran_vec (); |
2782 Array<double> s (minmn); | |
7071 | 2783 double *ps = s.fortran_vec (); |
1948 | 2784 |
7072 | 2785 // Ask ZGELSD what the dimension of WORK should be. |
5275 | 2786 octave_idx_type lwork = -1; |
3752 | 2787 |
2788 Array<Complex> work (1); | |
7079 | 2789 |
7544
f9983d2761df
more xGELSD workspace fixes
Jaroslav Hajek <highegg@gmail.com>
parents:
7532
diff
changeset
|
2790 octave_idx_type smlsiz; |
f9983d2761df
more xGELSD workspace fixes
Jaroslav Hajek <highegg@gmail.com>
parents:
7532
diff
changeset
|
2791 F77_FUNC (xilaenv, XILAENV) (9, F77_CONST_CHAR_ARG2 ("ZGELSD", 6), |
f9983d2761df
more xGELSD workspace fixes
Jaroslav Hajek <highegg@gmail.com>
parents:
7532
diff
changeset
|
2792 F77_CONST_CHAR_ARG2 (" ", 1), |
f9983d2761df
more xGELSD workspace fixes
Jaroslav Hajek <highegg@gmail.com>
parents:
7532
diff
changeset
|
2793 0, 0, 0, 0, smlsiz |
f9983d2761df
more xGELSD workspace fixes
Jaroslav Hajek <highegg@gmail.com>
parents:
7532
diff
changeset
|
2794 F77_CHAR_ARG_LEN (6) |
f9983d2761df
more xGELSD workspace fixes
Jaroslav Hajek <highegg@gmail.com>
parents:
7532
diff
changeset
|
2795 F77_CHAR_ARG_LEN (1)); |
7079 | 2796 |
2797 // We compute the size of rwork and iwork because ZGELSD in | |
2798 // older versions of LAPACK does not return them on a query | |
2799 // call. | |
7124 | 2800 double dminmn = static_cast<double> (minmn); |
2801 double dsmlsizp1 = static_cast<double> (smlsiz+1); | |
7079 | 2802 #if defined (HAVE_LOG2) |
7544
f9983d2761df
more xGELSD workspace fixes
Jaroslav Hajek <highegg@gmail.com>
parents:
7532
diff
changeset
|
2803 double tmp = log2 (dminmn / dsmlsizp1); |
7079 | 2804 #else |
7544
f9983d2761df
more xGELSD workspace fixes
Jaroslav Hajek <highegg@gmail.com>
parents:
7532
diff
changeset
|
2805 double tmp = log (dminmn / dsmlsizp1) / log (2.0); |
7079 | 2806 #endif |
7544
f9983d2761df
more xGELSD workspace fixes
Jaroslav Hajek <highegg@gmail.com>
parents:
7532
diff
changeset
|
2807 octave_idx_type nlvl = static_cast<octave_idx_type> (tmp) + 1; |
7079 | 2808 if (nlvl < 0) |
2809 nlvl = 0; | |
2810 | |
2811 octave_idx_type lrwork = minmn*(10 + 2*smlsiz + 8*nlvl) | |
2812 + 3*smlsiz*nrhs + (smlsiz+1)*(smlsiz+1); | |
2813 if (lrwork < 1) | |
2814 lrwork = 1; | |
2815 Array<double> rwork (lrwork); | |
2816 double *prwork = rwork.fortran_vec (); | |
2817 | |
2818 octave_idx_type liwork = 3 * minmn * nlvl + 11 * minmn; | |
2819 if (liwork < 1) | |
2820 liwork = 1; | |
2821 Array<octave_idx_type> iwork (liwork); | |
2822 octave_idx_type* piwork = iwork.fortran_vec (); | |
7072 | 2823 |
2824 F77_XFCN (zgelsd, ZGELSD, (m, n, nrhs, tmp_data, m, pretval, maxmn, | |
7788 | 2825 ps, rcon, rank, work.fortran_vec (), |
7079 | 2826 lwork, prwork, piwork, info)); |
1948 | 2827 |
7482
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2828 lwork = static_cast<octave_idx_type> (std::real (work(0))); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2829 work.resize (lwork); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2830 rwork.resize (static_cast<octave_idx_type> (rwork(0))); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2831 iwork.resize (iwork(0)); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2832 |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2833 F77_XFCN (zgelsd, ZGELSD, (m, n, nrhs, tmp_data, m, pretval, |
7788 | 2834 maxmn, ps, rcon, rank, |
7482
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2835 work.fortran_vec (), lwork, |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2836 prwork, piwork, info)); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2837 |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2838 if (rank < minmn) |
1948 | 2839 { |
7482
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2840 if (rank < minmn) |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2841 (*current_liboctave_warning_handler) |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2842 ("zgelsd: rank deficient %dx%d matrix, rank = %d, tol = %e", |
7788 | 2843 m, n, rank, rcon); |
7482
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2844 |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2845 if (s.elem (0) == 0.0) |
7788 | 2846 rcon = 0.0; |
7482
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2847 else |
7788 | 2848 rcon = s.elem (minmn - 1) / s.elem (0); |
7482
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2849 |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2850 retval.resize (n, nrhs); |
1948 | 2851 } |
458 | 2852 } |
2853 | |
2854 return retval; | |
2855 } | |
2856 | |
1819 | 2857 // Constants for matrix exponential calculation. |
2858 | |
2859 static double padec [] = | |
2860 { | |
2861 5.0000000000000000e-1, | |
2862 1.1666666666666667e-1, | |
2863 1.6666666666666667e-2, | |
2864 1.6025641025641026e-3, | |
2865 1.0683760683760684e-4, | |
2866 4.8562548562548563e-6, | |
2867 1.3875013875013875e-7, | |
2868 1.9270852604185938e-9, | |
2869 }; | |
2870 | |
7400 | 2871 static void |
7788 | 2872 solve_singularity_warning (double rcon) |
7400 | 2873 { |
2874 (*current_liboctave_warning_handler) | |
2875 ("singular matrix encountered in expm calculation, rcond = %g", | |
7788 | 2876 rcon); |
7400 | 2877 } |
2878 | |
1819 | 2879 ComplexMatrix |
2880 ComplexMatrix::expm (void) const | |
2881 { | |
2882 ComplexMatrix retval; | |
2883 | |
2884 ComplexMatrix m = *this; | |
2885 | |
5275 | 2886 octave_idx_type nc = columns (); |
1819 | 2887 |
3130 | 2888 // Preconditioning step 1: trace normalization to reduce dynamic |
2889 // range of poles, but avoid making stable eigenvalues unstable. | |
2890 | |
1819 | 2891 // trace shift value |
2892 Complex trshift = 0.0; | |
2893 | |
5275 | 2894 for (octave_idx_type i = 0; i < nc; i++) |
1819 | 2895 trshift += m.elem (i, i); |
2896 | |
2897 trshift /= nc; | |
2898 | |
3130 | 2899 if (trshift.real () < 0.0) |
6958 | 2900 { |
2901 trshift = trshift.imag (); | |
2902 if (trshift.real () > 709.0) | |
2903 trshift = 709.0; | |
2904 } | |
3130 | 2905 |
5275 | 2906 for (octave_idx_type i = 0; i < nc; i++) |
1819 | 2907 m.elem (i, i) -= trshift; |
2908 | |
2909 // Preconditioning step 2: eigenvalue balancing. | |
3331 | 2910 // code follows development in AEPBAL |
2911 | |
2912 Complex *mp = m.fortran_vec (); | |
3467 | 2913 |
5275 | 2914 octave_idx_type info, ilo, ihi,ilos,ihis; |
3468 | 2915 Array<double> dpermute (nc); |
2916 Array<double> dscale (nc); | |
2917 | |
5775 | 2918 // FIXME -- should pass job as a parameter in expm |
3468 | 2919 |
2920 // Permute first | |
2921 char job = 'P'; | |
4552 | 2922 F77_XFCN (zgebal, ZGEBAL, (F77_CONST_CHAR_ARG2 (&job, 1), |
2923 nc, mp, nc, ilo, ihi, | |
2924 dpermute.fortran_vec (), info | |
2925 F77_CHAR_ARG_LEN (1))); | |
3331 | 2926 |
3468 | 2927 // then scale |
2928 job = 'S'; | |
4552 | 2929 F77_XFCN (zgebal, ZGEBAL, (F77_CONST_CHAR_ARG2 (&job, 1), |
2930 nc, mp, nc, ilos, ihis, | |
2931 dscale.fortran_vec (), info | |
2932 F77_CHAR_ARG_LEN (1))); | |
3331 | 2933 |
1819 | 2934 // Preconditioning step 3: scaling. |
2935 | |
2936 ColumnVector work (nc); | |
3130 | 2937 double inf_norm; |
2938 | |
4552 | 2939 F77_XFCN (xzlange, XZLANGE, (F77_CONST_CHAR_ARG2 ("I", 1), |
2940 nc, nc, m.fortran_vec (), nc, | |
2941 work.fortran_vec (), inf_norm | |
2942 F77_CHAR_ARG_LEN (1))); | |
3331 | 2943 |
2800 | 2944 int sqpow = (inf_norm > 0.0 |
2945 ? static_cast<int> (1.0 + log (inf_norm) / log (2.0)) : 0); | |
1819 | 2946 |
2947 // Check whether we need to square at all. | |
2948 | |
2949 if (sqpow < 0) | |
2950 sqpow = 0; | |
2951 | |
2952 if (sqpow > 0) | |
2953 { | |
7400 | 2954 if (sqpow > 1023) |
2955 sqpow = 1023; | |
2956 | |
1819 | 2957 double scale_factor = 1.0; |
5275 | 2958 for (octave_idx_type i = 0; i < sqpow; i++) |
1819 | 2959 scale_factor *= 2.0; |
2960 | |
2961 m = m / scale_factor; | |
2962 } | |
2963 | |
2964 // npp, dpp: pade' approx polynomial matrices. | |
2965 | |
2966 ComplexMatrix npp (nc, nc, 0.0); | |
6958 | 2967 Complex *pnpp = npp.fortran_vec (); |
1819 | 2968 ComplexMatrix dpp = npp; |
6958 | 2969 Complex *pdpp = dpp.fortran_vec (); |
1819 | 2970 |
2971 // Now powers a^8 ... a^1. | |
2972 | |
2973 int minus_one_j = -1; | |
5275 | 2974 for (octave_idx_type j = 7; j >= 0; j--) |
1819 | 2975 { |
6958 | 2976 for (octave_idx_type i = 0; i < nc; i++) |
2977 { | |
2978 octave_idx_type k = i * nc + i; | |
7265 | 2979 pnpp[k] += padec[j]; |
2980 pdpp[k] += minus_one_j * padec[j]; | |
6958 | 2981 } |
7265 | 2982 |
6958 | 2983 npp = m * npp; |
7265 | 2984 pnpp = npp.fortran_vec (); |
2985 | |
6958 | 2986 dpp = m * dpp; |
7265 | 2987 pdpp = dpp.fortran_vec (); |
2988 | |
1819 | 2989 minus_one_j *= -1; |
2990 } | |
2991 | |
2992 // Zero power. | |
2993 | |
2994 dpp = -dpp; | |
5275 | 2995 for (octave_idx_type j = 0; j < nc; j++) |
1819 | 2996 { |
2997 npp.elem (j, j) += 1.0; | |
2998 dpp.elem (j, j) += 1.0; | |
2999 } | |
3000 | |
3001 // Compute pade approximation = inverse (dpp) * npp. | |
3002 | |
7788 | 3003 double rcon; |
3004 retval = dpp.solve (npp, info, rcon, solve_singularity_warning); | |
7400 | 3005 |
3006 if (info < 0) | |
3007 return retval; | |
3008 | |
1819 | 3009 // Reverse preconditioning step 3: repeated squaring. |
3010 | |
3011 while (sqpow) | |
3012 { | |
3013 retval = retval * retval; | |
3014 sqpow--; | |
3015 } | |
3016 | |
3017 // Reverse preconditioning step 2: inverse balancing. | |
3467 | 3018 // Done in two steps: inverse scaling, then inverse permutation |
3019 | |
3020 // inverse scaling (diagonal transformation) | |
5275 | 3021 for (octave_idx_type i = 0; i < nc; i++) |
3022 for (octave_idx_type j = 0; j < nc; j++) | |
3468 | 3023 retval(i,j) *= dscale(i) / dscale(j); |
3467 | 3024 |
4153 | 3025 OCTAVE_QUIT; |
3026 | |
3467 | 3027 // construct balancing permutation vector |
6867 | 3028 Array<octave_idx_type> iperm (nc); |
5275 | 3029 for (octave_idx_type i = 0; i < nc; i++) |
4593 | 3030 iperm(i) = i; // initialize to identity permutation |
3467 | 3031 |
3032 // leading permutations in forward order | |
5275 | 3033 for (octave_idx_type i = 0; i < (ilo-1); i++) |
3468 | 3034 { |
6867 | 3035 octave_idx_type swapidx = static_cast<octave_idx_type> (dpermute(i)) - 1; |
5275 | 3036 octave_idx_type tmp = iperm(i); |
4593 | 3037 iperm(i) = iperm(swapidx); |
3038 iperm(swapidx) = tmp; | |
3468 | 3039 } |
3467 | 3040 |
7416 | 3041 // construct inverse balancing permutation vector |
3042 Array<octave_idx_type> invpvec (nc); | |
3043 for (octave_idx_type i = 0; i < nc; i++) | |
3044 invpvec(iperm(i)) = i; // Thanks to R. A. Lippert for this method | |
3045 | |
3046 OCTAVE_QUIT; | |
3047 | |
3048 ComplexMatrix tmpMat = retval; | |
3049 for (octave_idx_type i = 0; i < nc; i++) | |
3050 for (octave_idx_type j = 0; j < nc; j++) | |
3051 retval(i,j) = tmpMat(invpvec(i),invpvec(j)); | |
3052 | |
3053 OCTAVE_QUIT; | |
3054 | |
3055 for (octave_idx_type i = 0; i < nc; i++) | |
3056 iperm(i) = i; // initialize to identity permutation | |
3057 | |
3467 | 3058 // trailing permutations must be done in reverse order |
5275 | 3059 for (octave_idx_type i = nc - 1; i >= ihi; i--) |
3468 | 3060 { |
6867 | 3061 octave_idx_type swapidx = static_cast<octave_idx_type> (dpermute(i)) - 1; |
5275 | 3062 octave_idx_type tmp = iperm(i); |
4593 | 3063 iperm(i) = iperm(swapidx); |
3064 iperm(swapidx) = tmp; | |
3468 | 3065 } |
3467 | 3066 |
3067 // construct inverse balancing permutation vector | |
5275 | 3068 for (octave_idx_type i = 0; i < nc; i++) |
4593 | 3069 invpvec(iperm(i)) = i; // Thanks to R. A. Lippert for this method |
3467 | 3070 |
4153 | 3071 OCTAVE_QUIT; |
3072 | |
7416 | 3073 tmpMat = retval; |
5275 | 3074 for (octave_idx_type i = 0; i < nc; i++) |
3075 for (octave_idx_type j = 0; j < nc; j++) | |
3468 | 3076 retval(i,j) = tmpMat(invpvec(i),invpvec(j)); |
1819 | 3077 |
3078 // Reverse preconditioning step 1: fix trace normalization. | |
3079 | |
3130 | 3080 return exp (trshift) * retval; |
1819 | 3081 } |
3082 | |
1205 | 3083 // column vector by row vector -> matrix operations |
3084 | |
3085 ComplexMatrix | |
3086 operator * (const ColumnVector& v, const ComplexRowVector& a) | |
3087 { | |
3088 ComplexColumnVector tmp (v); | |
3089 return tmp * a; | |
3090 } | |
3091 | |
3092 ComplexMatrix | |
3093 operator * (const ComplexColumnVector& a, const RowVector& b) | |
3094 { | |
3095 ComplexRowVector tmp (b); | |
3096 return a * tmp; | |
3097 } | |
3098 | |
3099 ComplexMatrix | |
3100 operator * (const ComplexColumnVector& v, const ComplexRowVector& a) | |
3101 { | |
1948 | 3102 ComplexMatrix retval; |
3103 | |
5275 | 3104 octave_idx_type len = v.length (); |
3233 | 3105 |
3106 if (len != 0) | |
1205 | 3107 { |
5275 | 3108 octave_idx_type a_len = a.length (); |
3233 | 3109 |
3110 retval.resize (len, a_len); | |
3111 Complex *c = retval.fortran_vec (); | |
3112 | |
4552 | 3113 F77_XFCN (zgemm, ZGEMM, (F77_CONST_CHAR_ARG2 ("N", 1), |
3114 F77_CONST_CHAR_ARG2 ("N", 1), | |
3115 len, a_len, 1, 1.0, v.data (), len, | |
3116 a.data (), 1, 0.0, c, len | |
3117 F77_CHAR_ARG_LEN (1) | |
3118 F77_CHAR_ARG_LEN (1))); | |
1205 | 3119 } |
3120 | |
1948 | 3121 return retval; |
1205 | 3122 } |
3123 | |
458 | 3124 // matrix by diagonal matrix -> matrix operations |
3125 | |
3126 ComplexMatrix& | |
3127 ComplexMatrix::operator += (const DiagMatrix& a) | |
3128 { | |
5275 | 3129 octave_idx_type nr = rows (); |
3130 octave_idx_type nc = cols (); | |
3131 | |
3132 octave_idx_type a_nr = rows (); | |
3133 octave_idx_type a_nc = cols (); | |
2384 | 3134 |
3135 if (nr != a_nr || nc != a_nc) | |
458 | 3136 { |
2384 | 3137 gripe_nonconformant ("operator +=", nr, nc, a_nr, a_nc); |
889 | 3138 return *this; |
458 | 3139 } |
3140 | |
5275 | 3141 for (octave_idx_type i = 0; i < a.length (); i++) |
458 | 3142 elem (i, i) += a.elem (i, i); |
3143 | |
3144 return *this; | |
3145 } | |
3146 | |
3147 ComplexMatrix& | |
3148 ComplexMatrix::operator -= (const DiagMatrix& a) | |
3149 { | |
5275 | 3150 octave_idx_type nr = rows (); |
3151 octave_idx_type nc = cols (); | |
3152 | |
3153 octave_idx_type a_nr = rows (); | |
3154 octave_idx_type a_nc = cols (); | |
2384 | 3155 |
3156 if (nr != a_nr || nc != a_nc) | |
458 | 3157 { |
2384 | 3158 gripe_nonconformant ("operator -=", nr, nc, a_nr, a_nc); |
889 | 3159 return *this; |
458 | 3160 } |
3161 | |
5275 | 3162 for (octave_idx_type i = 0; i < a.length (); i++) |
458 | 3163 elem (i, i) -= a.elem (i, i); |
3164 | |
3165 return *this; | |
3166 } | |
3167 | |
3168 ComplexMatrix& | |
3169 ComplexMatrix::operator += (const ComplexDiagMatrix& a) | |
3170 { | |
5275 | 3171 octave_idx_type nr = rows (); |
3172 octave_idx_type nc = cols (); | |
3173 | |
3174 octave_idx_type a_nr = rows (); | |
3175 octave_idx_type a_nc = cols (); | |
2384 | 3176 |
3177 if (nr != a_nr || nc != a_nc) | |
458 | 3178 { |
2384 | 3179 gripe_nonconformant ("operator +=", nr, nc, a_nr, a_nc); |
889 | 3180 return *this; |
458 | 3181 } |
3182 | |
5275 | 3183 for (octave_idx_type i = 0; i < a.length (); i++) |
458 | 3184 elem (i, i) += a.elem (i, i); |
3185 | |
3186 return *this; | |
3187 } | |
3188 | |
3189 ComplexMatrix& | |
3190 ComplexMatrix::operator -= (const ComplexDiagMatrix& a) | |
3191 { | |
5275 | 3192 octave_idx_type nr = rows (); |
3193 octave_idx_type nc = cols (); | |
3194 | |
3195 octave_idx_type a_nr = rows (); | |
3196 octave_idx_type a_nc = cols (); | |
2384 | 3197 |
3198 if (nr != a_nr || nc != a_nc) | |
458 | 3199 { |
2384 | 3200 gripe_nonconformant ("operator -=", nr, nc, a_nr, a_nc); |
889 | 3201 return *this; |
458 | 3202 } |
3203 | |
5275 | 3204 for (octave_idx_type i = 0; i < a.length (); i++) |
458 | 3205 elem (i, i) -= a.elem (i, i); |
3206 | |
3207 return *this; | |
3208 } | |
3209 | |
3210 // matrix by matrix -> matrix operations | |
3211 | |
3212 ComplexMatrix& | |
3213 ComplexMatrix::operator += (const Matrix& a) | |
3214 { | |
5275 | 3215 octave_idx_type nr = rows (); |
3216 octave_idx_type nc = cols (); | |
3217 | |
3218 octave_idx_type a_nr = a.rows (); | |
3219 octave_idx_type a_nc = a.cols (); | |
2384 | 3220 |
3221 if (nr != a_nr || nc != a_nc) | |
458 | 3222 { |
2384 | 3223 gripe_nonconformant ("operator +=", nr, nc, a_nr, a_nc); |
458 | 3224 return *this; |
3225 } | |
3226 | |
3227 if (nr == 0 || nc == 0) | |
3228 return *this; | |
3229 | |
3230 Complex *d = fortran_vec (); // Ensures only one reference to my privates! | |
3231 | |
3769 | 3232 mx_inline_add2 (d, a.data (), length ()); |
458 | 3233 return *this; |
3234 } | |
3235 | |
3236 ComplexMatrix& | |
3237 ComplexMatrix::operator -= (const Matrix& a) | |
3238 { | |
5275 | 3239 octave_idx_type nr = rows (); |
3240 octave_idx_type nc = cols (); | |
3241 | |
3242 octave_idx_type a_nr = a.rows (); | |
3243 octave_idx_type a_nc = a.cols (); | |
2384 | 3244 |
3245 if (nr != a_nr || nc != a_nc) | |
458 | 3246 { |
2384 | 3247 gripe_nonconformant ("operator -=", nr, nc, a_nr, a_nc); |
458 | 3248 return *this; |
3249 } | |
3250 | |
3251 if (nr == 0 || nc == 0) | |
3252 return *this; | |
3253 | |
3254 Complex *d = fortran_vec (); // Ensures only one reference to my privates! | |
3255 | |
3769 | 3256 mx_inline_subtract2 (d, a.data (), length ()); |
458 | 3257 return *this; |
3258 } | |
3259 | |
3260 // unary operations | |
3261 | |
2964 | 3262 boolMatrix |
458 | 3263 ComplexMatrix::operator ! (void) const |
3264 { | |
5275 | 3265 octave_idx_type nr = rows (); |
3266 octave_idx_type nc = cols (); | |
2964 | 3267 |
3268 boolMatrix b (nr, nc); | |
3269 | |
5275 | 3270 for (octave_idx_type j = 0; j < nc; j++) |
3271 for (octave_idx_type i = 0; i < nr; i++) | |
5139 | 3272 b.elem (i, j) = elem (i, j) == 0.0; |
2964 | 3273 |
3274 return b; | |
458 | 3275 } |
3276 | |
3277 // other operations | |
3278 | |
2676 | 3279 Matrix |
7503
8c32f95c2639
convert mapper functions to new format
David Bateman <dbateman@free.fr>
parents:
7488
diff
changeset
|
3280 ComplexMatrix::map (dmapper fcn) const |
458 | 3281 { |
7503
8c32f95c2639
convert mapper functions to new format
David Bateman <dbateman@free.fr>
parents:
7488
diff
changeset
|
3282 return MArray2<Complex>::map<double> (func_ptr (fcn)); |
8c32f95c2639
convert mapper functions to new format
David Bateman <dbateman@free.fr>
parents:
7488
diff
changeset
|
3283 } |
8c32f95c2639
convert mapper functions to new format
David Bateman <dbateman@free.fr>
parents:
7488
diff
changeset
|
3284 |
8c32f95c2639
convert mapper functions to new format
David Bateman <dbateman@free.fr>
parents:
7488
diff
changeset
|
3285 ComplexMatrix |
8c32f95c2639
convert mapper functions to new format
David Bateman <dbateman@free.fr>
parents:
7488
diff
changeset
|
3286 ComplexMatrix::map (cmapper fcn) const |
8c32f95c2639
convert mapper functions to new format
David Bateman <dbateman@free.fr>
parents:
7488
diff
changeset
|
3287 { |
8c32f95c2639
convert mapper functions to new format
David Bateman <dbateman@free.fr>
parents:
7488
diff
changeset
|
3288 return MArray2<Complex>::map<Complex> (func_ptr (fcn)); |
3248 | 3289 } |
3290 | |
3291 boolMatrix | |
7503
8c32f95c2639
convert mapper functions to new format
David Bateman <dbateman@free.fr>
parents:
7488
diff
changeset
|
3292 ComplexMatrix::map (bmapper fcn) const |
3248 | 3293 { |
7503
8c32f95c2639
convert mapper functions to new format
David Bateman <dbateman@free.fr>
parents:
7488
diff
changeset
|
3294 return MArray2<Complex>::map<bool> (func_ptr (fcn)); |
458 | 3295 } |
3296 | |
2384 | 3297 bool |
3298 ComplexMatrix::any_element_is_inf_or_nan (void) const | |
3299 { | |
5275 | 3300 octave_idx_type nr = rows (); |
3301 octave_idx_type nc = cols (); | |
3302 | |
3303 for (octave_idx_type j = 0; j < nc; j++) | |
3304 for (octave_idx_type i = 0; i < nr; i++) | |
2384 | 3305 { |
3306 Complex val = elem (i, j); | |
3307 if (xisinf (val) || xisnan (val)) | |
3308 return true; | |
3309 } | |
3310 | |
3311 return false; | |
3312 } | |
3313 | |
2408 | 3314 // Return true if no elements have imaginary components. |
3315 | |
3316 bool | |
3317 ComplexMatrix::all_elements_are_real (void) const | |
3318 { | |
5275 | 3319 octave_idx_type nr = rows (); |
3320 octave_idx_type nc = cols (); | |
3321 | |
3322 for (octave_idx_type j = 0; j < nc; j++) | |
4349 | 3323 { |
5275 | 3324 for (octave_idx_type i = 0; i < nr; i++) |
4349 | 3325 { |
5315 | 3326 double ip = std::imag (elem (i, j)); |
4349 | 3327 |
3328 if (ip != 0.0 || lo_ieee_signbit (ip)) | |
3329 return false; | |
3330 } | |
3331 } | |
2408 | 3332 |
3333 return true; | |
3334 } | |
3335 | |
1968 | 3336 // Return nonzero if any element of CM has a non-integer real or |
3337 // imaginary part. Also extract the largest and smallest (real or | |
3338 // imaginary) values and return them in MAX_VAL and MIN_VAL. | |
3339 | |
2384 | 3340 bool |
1968 | 3341 ComplexMatrix::all_integers (double& max_val, double& min_val) const |
3342 { | |
5275 | 3343 octave_idx_type nr = rows (); |
3344 octave_idx_type nc = cols (); | |
1968 | 3345 |
3346 if (nr > 0 && nc > 0) | |
3347 { | |
3348 Complex val = elem (0, 0); | |
3349 | |
5315 | 3350 double r_val = std::real (val); |
3351 double i_val = std::imag (val); | |
1968 | 3352 |
3353 max_val = r_val; | |
3354 min_val = r_val; | |
3355 | |
3356 if (i_val > max_val) | |
3357 max_val = i_val; | |
3358 | |
3359 if (i_val < max_val) | |
3360 min_val = i_val; | |
3361 } | |
3362 else | |
2384 | 3363 return false; |
1968 | 3364 |
5275 | 3365 for (octave_idx_type j = 0; j < nc; j++) |
3366 for (octave_idx_type i = 0; i < nr; i++) | |
1968 | 3367 { |
3368 Complex val = elem (i, j); | |
3369 | |
5315 | 3370 double r_val = std::real (val); |
3371 double i_val = std::imag (val); | |
1968 | 3372 |
3373 if (r_val > max_val) | |
3374 max_val = r_val; | |
3375 | |
3376 if (i_val > max_val) | |
3377 max_val = i_val; | |
3378 | |
3379 if (r_val < min_val) | |
3380 min_val = r_val; | |
3381 | |
3382 if (i_val < min_val) | |
3383 min_val = i_val; | |
3384 | |
3385 if (D_NINT (r_val) != r_val || D_NINT (i_val) != i_val) | |
2384 | 3386 return false; |
1968 | 3387 } |
2384 | 3388 |
3389 return true; | |
1968 | 3390 } |
3391 | |
2384 | 3392 bool |
1968 | 3393 ComplexMatrix::too_large_for_float (void) const |
3394 { | |
5275 | 3395 octave_idx_type nr = rows (); |
3396 octave_idx_type nc = cols (); | |
3397 | |
3398 for (octave_idx_type j = 0; j < nc; j++) | |
3399 for (octave_idx_type i = 0; i < nr; i++) | |
1968 | 3400 { |
3401 Complex val = elem (i, j); | |
3402 | |
5315 | 3403 double r_val = std::real (val); |
3404 double i_val = std::imag (val); | |
1968 | 3405 |
5389 | 3406 if ((! (xisnan (r_val) || xisinf (r_val)) |
5387 | 3407 && fabs (r_val) > FLT_MAX) |
5389 | 3408 || (! (xisnan (i_val) || xisinf (i_val)) |
5387 | 3409 && fabs (i_val) > FLT_MAX)) |
2384 | 3410 return true; |
1968 | 3411 } |
3412 | |
2384 | 3413 return false; |
1968 | 3414 } |
3415 | |
5775 | 3416 // FIXME Do these really belong here? Maybe they should be |
4015 | 3417 // in a base class? |
3418 | |
2832 | 3419 boolMatrix |
4015 | 3420 ComplexMatrix::all (int dim) const |
458 | 3421 { |
4015 | 3422 MX_ALL_OP (dim); |
458 | 3423 } |
3424 | |
2832 | 3425 boolMatrix |
4015 | 3426 ComplexMatrix::any (int dim) const |
458 | 3427 { |
4015 | 3428 MX_ANY_OP (dim); |
458 | 3429 } |
3430 | |
3431 ComplexMatrix | |
3723 | 3432 ComplexMatrix::cumprod (int dim) const |
458 | 3433 { |
4015 | 3434 MX_CUMULATIVE_OP (ComplexMatrix, Complex, *=); |
458 | 3435 } |
3436 | |
3437 ComplexMatrix | |
3723 | 3438 ComplexMatrix::cumsum (int dim) const |
458 | 3439 { |
4015 | 3440 MX_CUMULATIVE_OP (ComplexMatrix, Complex, +=); |
458 | 3441 } |
3442 | |
3443 ComplexMatrix | |
3723 | 3444 ComplexMatrix::prod (int dim) const |
458 | 3445 { |
3864 | 3446 MX_REDUCTION_OP (ComplexMatrix, *=, 1.0, 1.0); |
458 | 3447 } |
3448 | |
3449 ComplexMatrix | |
3723 | 3450 ComplexMatrix::sum (int dim) const |
458 | 3451 { |
3864 | 3452 MX_REDUCTION_OP (ComplexMatrix, +=, 0.0, 0.0); |
458 | 3453 } |
3454 | |
3455 ComplexMatrix | |
3723 | 3456 ComplexMatrix::sumsq (int dim) const |
458 | 3457 { |
3864 | 3458 #define ROW_EXPR \ |
3459 Complex d = elem (i, j); \ | |
3460 retval.elem (i, 0) += d * conj (d) | |
3461 | |
3462 #define COL_EXPR \ | |
3463 Complex d = elem (i, j); \ | |
3464 retval.elem (0, j) += d * conj (d) | |
3465 | |
3466 MX_BASE_REDUCTION_OP (ComplexMatrix, ROW_EXPR, COL_EXPR, 0.0, 0.0); | |
3467 | |
3468 #undef ROW_EXPR | |
3469 #undef COL_EXPR | |
458 | 3470 } |
3471 | |
4329 | 3472 Matrix ComplexMatrix::abs (void) const |
3473 { | |
5275 | 3474 octave_idx_type nr = rows (); |
3475 octave_idx_type nc = cols (); | |
4329 | 3476 |
3477 Matrix retval (nr, nc); | |
3478 | |
5275 | 3479 for (octave_idx_type j = 0; j < nc; j++) |
3480 for (octave_idx_type i = 0; i < nr; i++) | |
5315 | 3481 retval (i, j) = std::abs (elem (i, j)); |
4329 | 3482 |
3483 return retval; | |
3484 } | |
3485 | |
7620
36594d5bbe13
Move diag function into the octave_value class
David Bateman <dbateman@free.fr>
parents:
7544
diff
changeset
|
3486 ComplexMatrix |
5275 | 3487 ComplexMatrix::diag (octave_idx_type k) const |
458 | 3488 { |
7620
36594d5bbe13
Move diag function into the octave_value class
David Bateman <dbateman@free.fr>
parents:
7544
diff
changeset
|
3489 return MArray2<Complex>::diag (k); |
458 | 3490 } |
3491 | |
2354 | 3492 bool |
5275 | 3493 ComplexMatrix::row_is_real_only (octave_idx_type i) const |
2354 | 3494 { |
3495 bool retval = true; | |
3496 | |
5275 | 3497 octave_idx_type nc = columns (); |
3498 | |
3499 for (octave_idx_type j = 0; j < nc; j++) | |
2354 | 3500 { |
5315 | 3501 if (std::imag (elem (i, j)) != 0.0) |
2354 | 3502 { |
3503 retval = false; | |
3504 break; | |
3505 } | |
3506 } | |
3507 | |
3508 return retval; | |
3509 } | |
3510 | |
3511 bool | |
5275 | 3512 ComplexMatrix::column_is_real_only (octave_idx_type j) const |
2354 | 3513 { |
3514 bool retval = true; | |
3515 | |
5275 | 3516 octave_idx_type nr = rows (); |
3517 | |
3518 for (octave_idx_type i = 0; i < nr; i++) | |
2354 | 3519 { |
5315 | 3520 if (std::imag (elem (i, j)) != 0.0) |
2354 | 3521 { |
3522 retval = false; | |
3523 break; | |
3524 } | |
3525 } | |
3526 | |
3527 return retval; | |
3528 } | |
891 | 3529 |
458 | 3530 ComplexColumnVector |
3531 ComplexMatrix::row_min (void) const | |
3532 { | |
5275 | 3533 Array<octave_idx_type> dummy_idx; |
4587 | 3534 return row_min (dummy_idx); |
458 | 3535 } |
3536 | |
3537 ComplexColumnVector | |
5275 | 3538 ComplexMatrix::row_min (Array<octave_idx_type>& idx_arg) const |
458 | 3539 { |
3540 ComplexColumnVector result; | |
3541 | |
5275 | 3542 octave_idx_type nr = rows (); |
3543 octave_idx_type nc = cols (); | |
458 | 3544 |
3545 if (nr > 0 && nc > 0) | |
3546 { | |
3547 result.resize (nr); | |
4587 | 3548 idx_arg.resize (nr); |
458 | 3549 |
5275 | 3550 for (octave_idx_type i = 0; i < nr; i++) |
458 | 3551 { |
2354 | 3552 bool real_only = row_is_real_only (i); |
3553 | |
5275 | 3554 octave_idx_type idx_j; |
4469 | 3555 |
3556 Complex tmp_min; | |
3557 | |
3558 double abs_min = octave_NaN; | |
3559 | |
3560 for (idx_j = 0; idx_j < nc; idx_j++) | |
3561 { | |
3562 tmp_min = elem (i, idx_j); | |
3563 | |
5389 | 3564 if (! xisnan (tmp_min)) |
4469 | 3565 { |
5315 | 3566 abs_min = real_only ? std::real (tmp_min) : std::abs (tmp_min); |
4469 | 3567 break; |
3568 } | |
3569 } | |
3570 | |
5275 | 3571 for (octave_idx_type j = idx_j+1; j < nc; j++) |
4469 | 3572 { |
3573 Complex tmp = elem (i, j); | |
3574 | |
5389 | 3575 if (xisnan (tmp)) |
4469 | 3576 continue; |
3577 | |
5315 | 3578 double abs_tmp = real_only ? std::real (tmp) : std::abs (tmp); |
4469 | 3579 |
3580 if (abs_tmp < abs_min) | |
3581 { | |
3582 idx_j = j; | |
3583 tmp_min = tmp; | |
3584 abs_min = abs_tmp; | |
3585 } | |
3586 } | |
3587 | |
5389 | 3588 if (xisnan (tmp_min)) |
4469 | 3589 { |
3590 result.elem (i) = Complex_NaN_result; | |
4587 | 3591 idx_arg.elem (i) = 0; |
4469 | 3592 } |
891 | 3593 else |
3594 { | |
4469 | 3595 result.elem (i) = tmp_min; |
4587 | 3596 idx_arg.elem (i) = idx_j; |
891 | 3597 } |
458 | 3598 } |
3599 } | |
3600 | |
3601 return result; | |
3602 } | |
3603 | |
3604 ComplexColumnVector | |
3605 ComplexMatrix::row_max (void) const | |
3606 { | |
5275 | 3607 Array<octave_idx_type> dummy_idx; |
4587 | 3608 return row_max (dummy_idx); |
458 | 3609 } |
3610 | |
3611 ComplexColumnVector | |
5275 | 3612 ComplexMatrix::row_max (Array<octave_idx_type>& idx_arg) const |
458 | 3613 { |
3614 ComplexColumnVector result; | |
3615 | |
5275 | 3616 octave_idx_type nr = rows (); |
3617 octave_idx_type nc = cols (); | |
458 | 3618 |
3619 if (nr > 0 && nc > 0) | |
3620 { | |
3621 result.resize (nr); | |
4587 | 3622 idx_arg.resize (nr); |
458 | 3623 |
5275 | 3624 for (octave_idx_type i = 0; i < nr; i++) |
458 | 3625 { |
2354 | 3626 bool real_only = row_is_real_only (i); |
3627 | |
5275 | 3628 octave_idx_type idx_j; |
4469 | 3629 |
3630 Complex tmp_max; | |
3631 | |
3632 double abs_max = octave_NaN; | |
3633 | |
3634 for (idx_j = 0; idx_j < nc; idx_j++) | |
3635 { | |
3636 tmp_max = elem (i, idx_j); | |
3637 | |
5389 | 3638 if (! xisnan (tmp_max)) |
4469 | 3639 { |
5315 | 3640 abs_max = real_only ? std::real (tmp_max) : std::abs (tmp_max); |
4469 | 3641 break; |
3642 } | |
3643 } | |
3644 | |
5275 | 3645 for (octave_idx_type j = idx_j+1; j < nc; j++) |
4469 | 3646 { |
3647 Complex tmp = elem (i, j); | |
3648 | |
5389 | 3649 if (xisnan (tmp)) |
4469 | 3650 continue; |
3651 | |
5315 | 3652 double abs_tmp = real_only ? std::real (tmp) : std::abs (tmp); |
4469 | 3653 |
3654 if (abs_tmp > abs_max) | |
3655 { | |
3656 idx_j = j; | |
3657 tmp_max = tmp; | |
3658 abs_max = abs_tmp; | |
3659 } | |
3660 } | |
3661 | |
5389 | 3662 if (xisnan (tmp_max)) |
4469 | 3663 { |
3664 result.elem (i) = Complex_NaN_result; | |
4587 | 3665 idx_arg.elem (i) = 0; |
4469 | 3666 } |
891 | 3667 else |
3668 { | |
4469 | 3669 result.elem (i) = tmp_max; |
4587 | 3670 idx_arg.elem (i) = idx_j; |
891 | 3671 } |
458 | 3672 } |
3673 } | |
3674 | |
3675 return result; | |
3676 } | |
3677 | |
3678 ComplexRowVector | |
3679 ComplexMatrix::column_min (void) const | |
3680 { | |
5275 | 3681 Array<octave_idx_type> dummy_idx; |
4587 | 3682 return column_min (dummy_idx); |
458 | 3683 } |
3684 | |
3685 ComplexRowVector | |
5275 | 3686 ComplexMatrix::column_min (Array<octave_idx_type>& idx_arg) const |
458 | 3687 { |
3688 ComplexRowVector result; | |
3689 | |
5275 | 3690 octave_idx_type nr = rows (); |
3691 octave_idx_type nc = cols (); | |
458 | 3692 |
3693 if (nr > 0 && nc > 0) | |
3694 { | |
3695 result.resize (nc); | |
4587 | 3696 idx_arg.resize (nc); |
458 | 3697 |
5275 | 3698 for (octave_idx_type j = 0; j < nc; j++) |
458 | 3699 { |
2354 | 3700 bool real_only = column_is_real_only (j); |
3701 | |
5275 | 3702 octave_idx_type idx_i; |
4469 | 3703 |
3704 Complex tmp_min; | |
3705 | |
3706 double abs_min = octave_NaN; | |
3707 | |
3708 for (idx_i = 0; idx_i < nr; idx_i++) | |
3709 { | |
3710 tmp_min = elem (idx_i, j); | |
3711 | |
5389 | 3712 if (! xisnan (tmp_min)) |
4469 | 3713 { |
5315 | 3714 abs_min = real_only ? std::real (tmp_min) : std::abs (tmp_min); |
4469 | 3715 break; |
3716 } | |
3717 } | |
3718 | |
5275 | 3719 for (octave_idx_type i = idx_i+1; i < nr; i++) |
4469 | 3720 { |
3721 Complex tmp = elem (i, j); | |
3722 | |
5389 | 3723 if (xisnan (tmp)) |
4469 | 3724 continue; |
3725 | |
5315 | 3726 double abs_tmp = real_only ? std::real (tmp) : std::abs (tmp); |
4469 | 3727 |
3728 if (abs_tmp < abs_min) | |
3729 { | |
3730 idx_i = i; | |
3731 tmp_min = tmp; | |
3732 abs_min = abs_tmp; | |
3733 } | |
3734 } | |
3735 | |
5389 | 3736 if (xisnan (tmp_min)) |
4469 | 3737 { |
3738 result.elem (j) = Complex_NaN_result; | |
4587 | 3739 idx_arg.elem (j) = 0; |
4469 | 3740 } |
891 | 3741 else |
3742 { | |
4469 | 3743 result.elem (j) = tmp_min; |
4587 | 3744 idx_arg.elem (j) = idx_i; |
891 | 3745 } |
458 | 3746 } |
3747 } | |
3748 | |
3749 return result; | |
3750 } | |
3751 | |
3752 ComplexRowVector | |
3753 ComplexMatrix::column_max (void) const | |
3754 { | |
5275 | 3755 Array<octave_idx_type> dummy_idx; |
4587 | 3756 return column_max (dummy_idx); |
458 | 3757 } |
3758 | |
3759 ComplexRowVector | |
5275 | 3760 ComplexMatrix::column_max (Array<octave_idx_type>& idx_arg) const |
458 | 3761 { |
3762 ComplexRowVector result; | |
3763 | |
5275 | 3764 octave_idx_type nr = rows (); |
3765 octave_idx_type nc = cols (); | |
458 | 3766 |
3767 if (nr > 0 && nc > 0) | |
3768 { | |
3769 result.resize (nc); | |
4587 | 3770 idx_arg.resize (nc); |
458 | 3771 |
5275 | 3772 for (octave_idx_type j = 0; j < nc; j++) |
458 | 3773 { |
2354 | 3774 bool real_only = column_is_real_only (j); |
3775 | |
5275 | 3776 octave_idx_type idx_i; |
4469 | 3777 |
3778 Complex tmp_max; | |
3779 | |
3780 double abs_max = octave_NaN; | |
3781 | |
3782 for (idx_i = 0; idx_i < nr; idx_i++) | |
3783 { | |
3784 tmp_max = elem (idx_i, j); | |
3785 | |
5389 | 3786 if (! xisnan (tmp_max)) |
4469 | 3787 { |
5315 | 3788 abs_max = real_only ? std::real (tmp_max) : std::abs (tmp_max); |
4469 | 3789 break; |
3790 } | |
3791 } | |
3792 | |
5275 | 3793 for (octave_idx_type i = idx_i+1; i < nr; i++) |
4469 | 3794 { |
3795 Complex tmp = elem (i, j); | |
3796 | |
5389 | 3797 if (xisnan (tmp)) |
4469 | 3798 continue; |
3799 | |
5315 | 3800 double abs_tmp = real_only ? std::real (tmp) : std::abs (tmp); |
4469 | 3801 |
3802 if (abs_tmp > abs_max) | |
3803 { | |
3804 idx_i = i; | |
3805 tmp_max = tmp; | |
3806 abs_max = abs_tmp; | |
3807 } | |
3808 } | |
3809 | |
5389 | 3810 if (xisnan (tmp_max)) |
4469 | 3811 { |
3812 result.elem (j) = Complex_NaN_result; | |
4587 | 3813 idx_arg.elem (j) = 0; |
4469 | 3814 } |
891 | 3815 else |
3816 { | |
4469 | 3817 result.elem (j) = tmp_max; |
4587 | 3818 idx_arg.elem (j) = idx_i; |
891 | 3819 } |
458 | 3820 } |
3821 } | |
3822 | |
3823 return result; | |
3824 } | |
3825 | |
3826 // i/o | |
3827 | |
3504 | 3828 std::ostream& |
3829 operator << (std::ostream& os, const ComplexMatrix& a) | |
458 | 3830 { |
5275 | 3831 for (octave_idx_type i = 0; i < a.rows (); i++) |
458 | 3832 { |
5275 | 3833 for (octave_idx_type j = 0; j < a.cols (); j++) |
4130 | 3834 { |
3835 os << " "; | |
3836 octave_write_complex (os, a.elem (i, j)); | |
3837 } | |
458 | 3838 os << "\n"; |
3839 } | |
3840 return os; | |
3841 } | |
3842 | |
3504 | 3843 std::istream& |
3844 operator >> (std::istream& is, ComplexMatrix& a) | |
458 | 3845 { |
5275 | 3846 octave_idx_type nr = a.rows (); |
3847 octave_idx_type nc = a.cols (); | |
458 | 3848 |
3849 if (nr < 1 || nc < 1) | |
3504 | 3850 is.clear (std::ios::badbit); |
458 | 3851 else |
3852 { | |
3853 Complex tmp; | |
5275 | 3854 for (octave_idx_type i = 0; i < nr; i++) |
3855 for (octave_idx_type j = 0; j < nc; j++) | |
458 | 3856 { |
4130 | 3857 tmp = octave_read_complex (is); |
458 | 3858 if (is) |
3859 a.elem (i, j) = tmp; | |
3860 else | |
2993 | 3861 goto done; |
458 | 3862 } |
3863 } | |
3864 | |
2993 | 3865 done: |
3866 | |
458 | 3867 return is; |
3868 } | |
3869 | |
1819 | 3870 ComplexMatrix |
3871 Givens (const Complex& x, const Complex& y) | |
3872 { | |
3873 double cc; | |
3874 Complex cs, temp_r; | |
3875 | |
3887 | 3876 F77_FUNC (zlartg, ZLARTG) (x, y, cc, cs, temp_r); |
1819 | 3877 |
3878 ComplexMatrix g (2, 2); | |
3879 | |
3880 g.elem (0, 0) = cc; | |
3881 g.elem (1, 1) = cc; | |
3882 g.elem (0, 1) = cs; | |
3883 g.elem (1, 0) = -conj (cs); | |
3884 | |
3885 return g; | |
3886 } | |
3887 | |
3888 ComplexMatrix | |
3889 Sylvester (const ComplexMatrix& a, const ComplexMatrix& b, | |
3890 const ComplexMatrix& c) | |
3891 { | |
3892 ComplexMatrix retval; | |
3893 | |
5775 | 3894 // FIXME -- need to check that a, b, and c are all the same |
1819 | 3895 // size. |
3896 | |
3897 // Compute Schur decompositions | |
3898 | |
3899 ComplexSCHUR as (a, "U"); | |
3900 ComplexSCHUR bs (b, "U"); | |
3901 | |
3902 // Transform c to new coordinates. | |
3903 | |
3904 ComplexMatrix ua = as.unitary_matrix (); | |
3905 ComplexMatrix sch_a = as.schur_matrix (); | |
3906 | |
3907 ComplexMatrix ub = bs.unitary_matrix (); | |
3908 ComplexMatrix sch_b = bs.schur_matrix (); | |
3909 | |
3910 ComplexMatrix cx = ua.hermitian () * c * ub; | |
3911 | |
3912 // Solve the sylvester equation, back-transform, and return the | |
3913 // solution. | |
3914 | |
5275 | 3915 octave_idx_type a_nr = a.rows (); |
3916 octave_idx_type b_nr = b.rows (); | |
1819 | 3917 |
3918 double scale; | |
5275 | 3919 octave_idx_type info; |
1950 | 3920 |
3921 Complex *pa = sch_a.fortran_vec (); | |
3922 Complex *pb = sch_b.fortran_vec (); | |
3923 Complex *px = cx.fortran_vec (); | |
1819 | 3924 |
4552 | 3925 F77_XFCN (ztrsyl, ZTRSYL, (F77_CONST_CHAR_ARG2 ("N", 1), |
3926 F77_CONST_CHAR_ARG2 ("N", 1), | |
3927 1, a_nr, b_nr, pa, a_nr, pb, | |
3928 b_nr, px, a_nr, scale, info | |
3929 F77_CHAR_ARG_LEN (1) | |
3930 F77_CHAR_ARG_LEN (1))); | |
1950 | 3931 |
7482
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
3932 // FIXME -- check info? |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
3933 |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
3934 retval = -ua * cx * ub.hermitian (); |
1819 | 3935 |
3936 return retval; | |
3937 } | |
3938 | |
2828 | 3939 ComplexMatrix |
3940 operator * (const ComplexMatrix& m, const Matrix& a) | |
3941 { | |
3942 ComplexMatrix tmp (a); | |
3943 return m * tmp; | |
3944 } | |
3945 | |
3946 ComplexMatrix | |
3947 operator * (const Matrix& m, const ComplexMatrix& a) | |
3948 { | |
3949 ComplexMatrix tmp (m); | |
3950 return tmp * a; | |
3951 } | |
3952 | |
6162 | 3953 /* Simple Dot Product, Matrix-Vector and Matrix-Matrix Unit tests |
3954 %!assert([1+i 2+i 3+i] * [ 4+i ; 5+i ; 6+i], 29+21i, 1e-14) | |
3955 %!assert([1+i 2+i ; 3+i 4+i ] * [5+i ; 6+i], [15 + 14i ; 37 + 18i], 1e-14) | |
3956 %!assert([1+i 2+i ; 3+i 4+i ] * [5+i 6+i ; 7+i 8+i], [17 + 15i 20 + 17i; 41 + 19i 48 + 21i], 1e-14) | |
3957 */ | |
3958 | |
3959 /* Test some simple identities | |
3960 %!shared M, cv, rv | |
3961 %! M = randn(10,10)+i*rand(10,10); | |
3962 %! cv = randn(10,1)+i*rand(10,1); | |
3963 %! rv = randn(1,10)+i*rand(1,10); | |
3964 %!assert([M*cv,M*cv],M*[cv,cv],1e-14) | |
3965 %!assert([rv*M;rv*M],[rv;rv]*M,1e-14) | |
3966 %!assert(2*rv*cv,[rv,rv]*[cv;cv],1e-14) | |
3967 */ | |
3968 | |
2828 | 3969 ComplexMatrix |
3970 operator * (const ComplexMatrix& m, const ComplexMatrix& a) | |
3971 { | |
3972 ComplexMatrix retval; | |
3973 | |
5275 | 3974 octave_idx_type nr = m.rows (); |
3975 octave_idx_type nc = m.cols (); | |
3976 | |
3977 octave_idx_type a_nr = a.rows (); | |
3978 octave_idx_type a_nc = a.cols (); | |
2828 | 3979 |
3980 if (nc != a_nr) | |
3981 gripe_nonconformant ("operator *", nr, nc, a_nr, a_nc); | |
3982 else | |
3983 { | |
3984 if (nr == 0 || nc == 0 || a_nc == 0) | |
3760 | 3985 retval.resize (nr, a_nc, 0.0); |
2828 | 3986 else |
3987 { | |
5275 | 3988 octave_idx_type ld = nr; |
3989 octave_idx_type lda = a.rows (); | |
2828 | 3990 |
3991 retval.resize (nr, a_nc); | |
3992 Complex *c = retval.fortran_vec (); | |
3993 | |
5983 | 3994 if (a_nc == 1) |
3995 { | |
3996 if (nr == 1) | |
3997 F77_FUNC (xzdotu, XZDOTU) (nc, m.data (), 1, a.data (), 1, *c); | |
3998 else | |
6390 | 3999 { |
4000 F77_XFCN (zgemv, ZGEMV, (F77_CONST_CHAR_ARG2 ("N", 1), | |
4001 nr, nc, 1.0, m.data (), ld, | |
4002 a.data (), 1, 0.0, c, 1 | |
4003 F77_CHAR_ARG_LEN (1))); | |
4004 } | |
5983 | 4005 } |
4006 else | |
6390 | 4007 { |
4008 F77_XFCN (zgemm, ZGEMM, (F77_CONST_CHAR_ARG2 ("N", 1), | |
4009 F77_CONST_CHAR_ARG2 ("N", 1), | |
4010 nr, a_nc, nc, 1.0, m.data (), | |
4011 ld, a.data (), lda, 0.0, c, nr | |
4012 F77_CHAR_ARG_LEN (1) | |
4013 F77_CHAR_ARG_LEN (1))); | |
4014 } | |
2828 | 4015 } |
4016 } | |
4017 | |
4018 return retval; | |
4019 } | |
4020 | |
5775 | 4021 // FIXME -- it would be nice to share code among the min/max |
4309 | 4022 // functions below. |
4023 | |
4024 #define EMPTY_RETURN_CHECK(T) \ | |
4025 if (nr == 0 || nc == 0) \ | |
4026 return T (nr, nc); | |
4027 | |
4028 ComplexMatrix | |
4029 min (const Complex& c, const ComplexMatrix& m) | |
4030 { | |
5275 | 4031 octave_idx_type nr = m.rows (); |
4032 octave_idx_type nc = m.columns (); | |
4309 | 4033 |
4034 EMPTY_RETURN_CHECK (ComplexMatrix); | |
4035 | |
4036 ComplexMatrix result (nr, nc); | |
4037 | |
5275 | 4038 for (octave_idx_type j = 0; j < nc; j++) |
4039 for (octave_idx_type i = 0; i < nr; i++) | |
4309 | 4040 { |
4041 OCTAVE_QUIT; | |
4042 result (i, j) = xmin (c, m (i, j)); | |
4043 } | |
4044 | |
4045 return result; | |
4046 } | |
4047 | |
4048 ComplexMatrix | |
4049 min (const ComplexMatrix& m, const Complex& c) | |
4050 { | |
5275 | 4051 octave_idx_type nr = m.rows (); |
4052 octave_idx_type nc = m.columns (); | |
4309 | 4053 |
4054 EMPTY_RETURN_CHECK (ComplexMatrix); | |
4055 | |
4056 ComplexMatrix result (nr, nc); | |
4057 | |
5275 | 4058 for (octave_idx_type j = 0; j < nc; j++) |
4059 for (octave_idx_type i = 0; i < nr; i++) | |
4309 | 4060 { |
4061 OCTAVE_QUIT; | |
4062 result (i, j) = xmin (m (i, j), c); | |
4063 } | |
4064 | |
4065 return result; | |
4066 } | |
4067 | |
4068 ComplexMatrix | |
4069 min (const ComplexMatrix& a, const ComplexMatrix& b) | |
4070 { | |
5275 | 4071 octave_idx_type nr = a.rows (); |
4072 octave_idx_type nc = a.columns (); | |
4309 | 4073 |
4074 if (nr != b.rows () || nc != b.columns ()) | |
4075 { | |
4076 (*current_liboctave_error_handler) | |
4077 ("two-arg min expecting args of same size"); | |
4078 return ComplexMatrix (); | |
4079 } | |
4080 | |
4081 EMPTY_RETURN_CHECK (ComplexMatrix); | |
4082 | |
4083 ComplexMatrix result (nr, nc); | |
4084 | |
5275 | 4085 for (octave_idx_type j = 0; j < nc; j++) |
4309 | 4086 { |
4087 int columns_are_real_only = 1; | |
5275 | 4088 for (octave_idx_type i = 0; i < nr; i++) |
4309 | 4089 { |
4090 OCTAVE_QUIT; | |
5315 | 4091 if (std::imag (a (i, j)) != 0.0 || std::imag (b (i, j)) != 0.0) |
4309 | 4092 { |
4093 columns_are_real_only = 0; | |
4094 break; | |
4095 } | |
4096 } | |
4097 | |
4098 if (columns_are_real_only) | |
4099 { | |
5275 | 4100 for (octave_idx_type i = 0; i < nr; i++) |
5315 | 4101 result (i, j) = xmin (std::real (a (i, j)), std::real (b (i, j))); |
4309 | 4102 } |
4103 else | |
4104 { | |
5275 | 4105 for (octave_idx_type i = 0; i < nr; i++) |
4309 | 4106 { |
4107 OCTAVE_QUIT; | |
4108 result (i, j) = xmin (a (i, j), b (i, j)); | |
4109 } | |
4110 } | |
4111 } | |
4112 | |
4113 return result; | |
4114 } | |
4115 | |
4116 ComplexMatrix | |
4117 max (const Complex& c, const ComplexMatrix& m) | |
4118 { | |
5275 | 4119 octave_idx_type nr = m.rows (); |
4120 octave_idx_type nc = m.columns (); | |
4309 | 4121 |
4122 EMPTY_RETURN_CHECK (ComplexMatrix); | |
4123 | |
4124 ComplexMatrix result (nr, nc); | |
4125 | |
5275 | 4126 for (octave_idx_type j = 0; j < nc; j++) |
4127 for (octave_idx_type i = 0; i < nr; i++) | |
4309 | 4128 { |
4129 OCTAVE_QUIT; | |
4130 result (i, j) = xmax (c, m (i, j)); | |
4131 } | |
4132 | |
4133 return result; | |
4134 } | |
4135 | |
4136 ComplexMatrix | |
4137 max (const ComplexMatrix& m, const Complex& c) | |
4138 { | |
5275 | 4139 octave_idx_type nr = m.rows (); |
4140 octave_idx_type nc = m.columns (); | |
4309 | 4141 |
4142 EMPTY_RETURN_CHECK (ComplexMatrix); | |
4143 | |
4144 ComplexMatrix result (nr, nc); | |
4145 | |
5275 | 4146 for (octave_idx_type j = 0; j < nc; j++) |
4147 for (octave_idx_type i = 0; i < nr; i++) | |
4309 | 4148 { |
4149 OCTAVE_QUIT; | |
4150 result (i, j) = xmax (m (i, j), c); | |
4151 } | |
4152 | |
4153 return result; | |
4154 } | |
4155 | |
4156 ComplexMatrix | |
4157 max (const ComplexMatrix& a, const ComplexMatrix& b) | |
4158 { | |
5275 | 4159 octave_idx_type nr = a.rows (); |
4160 octave_idx_type nc = a.columns (); | |
4309 | 4161 |
4162 if (nr != b.rows () || nc != b.columns ()) | |
4163 { | |
4164 (*current_liboctave_error_handler) | |
4165 ("two-arg max expecting args of same size"); | |
4166 return ComplexMatrix (); | |
4167 } | |
4168 | |
4169 EMPTY_RETURN_CHECK (ComplexMatrix); | |
4170 | |
4171 ComplexMatrix result (nr, nc); | |
4172 | |
5275 | 4173 for (octave_idx_type j = 0; j < nc; j++) |
4309 | 4174 { |
4175 int columns_are_real_only = 1; | |
5275 | 4176 for (octave_idx_type i = 0; i < nr; i++) |
4309 | 4177 { |
4178 OCTAVE_QUIT; | |
5315 | 4179 if (std::imag (a (i, j)) != 0.0 || std::imag (b (i, j)) != 0.0) |
4309 | 4180 { |
4181 columns_are_real_only = 0; | |
4182 break; | |
4183 } | |
4184 } | |
4185 | |
4186 if (columns_are_real_only) | |
4187 { | |
5275 | 4188 for (octave_idx_type i = 0; i < nr; i++) |
4309 | 4189 { |
4190 OCTAVE_QUIT; | |
5315 | 4191 result (i, j) = xmax (std::real (a (i, j)), std::real (b (i, j))); |
4309 | 4192 } |
4193 } | |
4194 else | |
4195 { | |
5275 | 4196 for (octave_idx_type i = 0; i < nr; i++) |
4309 | 4197 { |
4198 OCTAVE_QUIT; | |
4199 result (i, j) = xmax (a (i, j), b (i, j)); | |
4200 } | |
4201 } | |
4202 } | |
4203 | |
4204 return result; | |
4205 } | |
4206 | |
5315 | 4207 MS_CMP_OPS(ComplexMatrix, std::real, Complex, std::real) |
3504 | 4208 MS_BOOL_OPS(ComplexMatrix, Complex, 0.0) |
2870 | 4209 |
5315 | 4210 SM_CMP_OPS(Complex, std::real, ComplexMatrix, std::real) |
3504 | 4211 SM_BOOL_OPS(Complex, ComplexMatrix, 0.0) |
2870 | 4212 |
5315 | 4213 MM_CMP_OPS(ComplexMatrix, std::real, ComplexMatrix, std::real) |
3504 | 4214 MM_BOOL_OPS(ComplexMatrix, ComplexMatrix, 0.0) |
2870 | 4215 |
458 | 4216 /* |
4217 ;;; Local Variables: *** | |
4218 ;;; mode: C++ *** | |
4219 ;;; End: *** | |
4220 */ |