Mercurial > octave-nkf
annotate liboctave/CMatrix.cc @ 7789:82be108cc558
First attempt at single precision tyeps
* * *
corrections to qrupdate single precision routines
* * *
prefer demotion to single over promotion to double
* * *
Add single precision support to log2 function
* * *
Trivial PROJECT file update
* * *
Cache optimized hermitian/transpose methods
* * *
Add tests for tranpose/hermitian and ChangeLog entry for new transpose code
author | David Bateman <dbateman@free.fr> |
---|---|
date | Sun, 27 Apr 2008 22:34:17 +0200 |
parents | 45f5faba05a2 |
children | 5861b95e9879 |
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 |
7789
82be108cc558
First attempt at single precision tyeps
David Bateman <dbateman@free.fr>
parents:
7788
diff
changeset
|
194 F77_FUNC (zffti, ZFFTI) (const octave_idx_type&, Complex*); |
4552 | 195 |
196 F77_RET_T | |
7789
82be108cc558
First attempt at single precision tyeps
David Bateman <dbateman@free.fr>
parents:
7788
diff
changeset
|
197 F77_FUNC (zfftf, ZFFTF) (const octave_idx_type&, Complex*, Complex*); |
4552 | 198 |
199 F77_RET_T | |
7789
82be108cc558
First attempt at single precision tyeps
David Bateman <dbateman@free.fr>
parents:
7788
diff
changeset
|
200 F77_FUNC (zfftb, ZFFTB) (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 conj (const ComplexMatrix& a) | |
889 { | |
5275 | 890 octave_idx_type a_len = a.length (); |
458 | 891 ComplexMatrix retval; |
892 if (a_len > 0) | |
3769 | 893 retval = ComplexMatrix (mx_inline_conj_dup (a.data (), a_len), |
894 a.rows (), a.cols ()); | |
458 | 895 return retval; |
896 } | |
897 | |
898 // resize is the destructive equivalent for this one | |
899 | |
900 ComplexMatrix | |
5275 | 901 ComplexMatrix::extract (octave_idx_type r1, octave_idx_type c1, octave_idx_type r2, octave_idx_type c2) const |
458 | 902 { |
5275 | 903 if (r1 > r2) { octave_idx_type tmp = r1; r1 = r2; r2 = tmp; } |
904 if (c1 > c2) { octave_idx_type tmp = c1; c1 = c2; c2 = tmp; } | |
905 | |
906 octave_idx_type new_r = r2 - r1 + 1; | |
907 octave_idx_type new_c = c2 - c1 + 1; | |
458 | 908 |
909 ComplexMatrix result (new_r, new_c); | |
910 | |
5275 | 911 for (octave_idx_type j = 0; j < new_c; j++) |
912 for (octave_idx_type i = 0; i < new_r; i++) | |
4316 | 913 result.xelem (i, j) = elem (r1+i, c1+j); |
914 | |
915 return result; | |
916 } | |
917 | |
918 ComplexMatrix | |
5275 | 919 ComplexMatrix::extract_n (octave_idx_type r1, octave_idx_type c1, octave_idx_type nr, octave_idx_type nc) const |
4316 | 920 { |
921 ComplexMatrix result (nr, nc); | |
922 | |
5275 | 923 for (octave_idx_type j = 0; j < nc; j++) |
924 for (octave_idx_type i = 0; i < nr; i++) | |
4316 | 925 result.xelem (i, j) = elem (r1+i, c1+j); |
458 | 926 |
927 return result; | |
928 } | |
929 | |
930 // extract row or column i. | |
931 | |
932 ComplexRowVector | |
5275 | 933 ComplexMatrix::row (octave_idx_type i) const |
458 | 934 { |
5275 | 935 octave_idx_type nc = cols (); |
458 | 936 if (i < 0 || i >= rows ()) |
937 { | |
938 (*current_liboctave_error_handler) ("invalid row selection"); | |
939 return ComplexRowVector (); | |
940 } | |
941 | |
942 ComplexRowVector retval (nc); | |
5275 | 943 for (octave_idx_type j = 0; j < cols (); j++) |
4316 | 944 retval.xelem (j) = elem (i, j); |
458 | 945 |
946 return retval; | |
947 } | |
948 | |
949 ComplexColumnVector | |
5275 | 950 ComplexMatrix::column (octave_idx_type i) const |
458 | 951 { |
5275 | 952 octave_idx_type nr = rows (); |
458 | 953 if (i < 0 || i >= cols ()) |
954 { | |
955 (*current_liboctave_error_handler) ("invalid column selection"); | |
956 return ComplexColumnVector (); | |
957 } | |
958 | |
959 ComplexColumnVector retval (nr); | |
5275 | 960 for (octave_idx_type j = 0; j < nr; j++) |
4316 | 961 retval.xelem (j) = elem (j, i); |
458 | 962 |
963 return retval; | |
964 } | |
965 | |
966 ComplexMatrix | |
967 ComplexMatrix::inverse (void) const | |
968 { | |
5275 | 969 octave_idx_type info; |
7788 | 970 double rcon; |
6207 | 971 MatrixType mattype (*this); |
7788 | 972 return inverse (mattype, info, rcon, 0, 0); |
6207 | 973 } |
974 | |
975 ComplexMatrix | |
6479 | 976 ComplexMatrix::inverse (octave_idx_type& info) const |
977 { | |
7788 | 978 double rcon; |
6479 | 979 MatrixType mattype (*this); |
7788 | 980 return inverse (mattype, info, rcon, 0, 0); |
6479 | 981 } |
982 | |
983 ComplexMatrix | |
7788 | 984 ComplexMatrix::inverse (octave_idx_type& info, double& rcon, int force, |
6479 | 985 int calc_cond) const |
986 { | |
987 MatrixType mattype (*this); | |
7788 | 988 return inverse (mattype, info, rcon, force, calc_cond); |
6479 | 989 } |
990 | |
991 ComplexMatrix | |
6207 | 992 ComplexMatrix::inverse (MatrixType &mattype) const |
993 { | |
994 octave_idx_type info; | |
7788 | 995 double rcon; |
996 return inverse (mattype, info, rcon, 0, 0); | |
6207 | 997 } |
998 | |
999 ComplexMatrix | |
1000 ComplexMatrix::inverse (MatrixType &mattype, octave_idx_type& info) const | |
1001 { | |
7788 | 1002 double rcon; |
1003 return inverse (mattype, info, rcon, 0, 0); | |
458 | 1004 } |
1005 | |
1006 ComplexMatrix | |
6207 | 1007 ComplexMatrix::tinverse (MatrixType &mattype, octave_idx_type& info, |
7788 | 1008 double& rcon, int force, int calc_cond) const |
458 | 1009 { |
6207 | 1010 ComplexMatrix retval; |
1011 | |
1012 octave_idx_type nr = rows (); | |
1013 octave_idx_type nc = cols (); | |
1014 | |
1015 if (nr != nc || nr == 0 || nc == 0) | |
1016 (*current_liboctave_error_handler) ("inverse requires square matrix"); | |
1017 else | |
1018 { | |
1019 int typ = mattype.type (); | |
1020 char uplo = (typ == MatrixType::Lower ? 'L' : 'U'); | |
1021 char udiag = 'N'; | |
1022 retval = *this; | |
1023 Complex *tmp_data = retval.fortran_vec (); | |
1024 | |
1025 F77_XFCN (ztrtri, ZTRTRI, (F77_CONST_CHAR_ARG2 (&uplo, 1), | |
1026 F77_CONST_CHAR_ARG2 (&udiag, 1), | |
1027 nr, tmp_data, nr, info | |
1028 F77_CHAR_ARG_LEN (1) | |
1029 F77_CHAR_ARG_LEN (1))); | |
1030 | |
7482
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
1031 // Throw-away extra info LAPACK gives so as to not change output. |
7788 | 1032 rcon = 0.0; |
7482
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
1033 if (info != 0) |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
1034 info = -1; |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
1035 else if (calc_cond) |
6207 | 1036 { |
7482
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
1037 octave_idx_type ztrcon_info = 0; |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
1038 char job = '1'; |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
1039 |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
1040 OCTAVE_LOCAL_BUFFER (Complex, cwork, 2*nr); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
1041 OCTAVE_LOCAL_BUFFER (double, rwork, nr); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
1042 |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
1043 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
|
1044 F77_CONST_CHAR_ARG2 (&uplo, 1), |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
1045 F77_CONST_CHAR_ARG2 (&udiag, 1), |
7788 | 1046 nr, tmp_data, nr, rcon, |
7482
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
1047 cwork, rwork, ztrcon_info |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
1048 F77_CHAR_ARG_LEN (1) |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
1049 F77_CHAR_ARG_LEN (1) |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
1050 F77_CHAR_ARG_LEN (1))); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
1051 |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
1052 if (ztrcon_info != 0) |
6207 | 1053 info = -1; |
1054 } | |
1055 | |
1056 if (info == -1 && ! force) | |
1057 retval = *this; // Restore matrix contents. | |
1058 } | |
1059 | |
1060 return retval; | |
458 | 1061 } |
1062 | |
1063 ComplexMatrix | |
6207 | 1064 ComplexMatrix::finverse (MatrixType &mattype, octave_idx_type& info, |
7788 | 1065 double& rcon, int force, int calc_cond) const |
458 | 1066 { |
1948 | 1067 ComplexMatrix retval; |
1068 | |
5275 | 1069 octave_idx_type nr = rows (); |
1070 octave_idx_type nc = cols (); | |
1948 | 1071 |
458 | 1072 if (nr != nc) |
1948 | 1073 (*current_liboctave_error_handler) ("inverse requires square matrix"); |
458 | 1074 else |
1075 { | |
5275 | 1076 Array<octave_idx_type> ipvt (nr); |
1077 octave_idx_type *pipvt = ipvt.fortran_vec (); | |
1948 | 1078 |
1079 retval = *this; | |
1080 Complex *tmp_data = retval.fortran_vec (); | |
1081 | |
4329 | 1082 Array<Complex> z(1); |
5275 | 1083 octave_idx_type lwork = -1; |
4330 | 1084 |
1085 // Query the optimum work array size. | |
4329 | 1086 |
1087 F77_XFCN (zgetri, ZGETRI, (nc, tmp_data, nr, pipvt, | |
1088 z.fortran_vec (), lwork, info)); | |
1089 | |
5315 | 1090 lwork = static_cast<octave_idx_type> (std::real(z(0))); |
4329 | 1091 lwork = (lwork < 2 *nc ? 2*nc : lwork); |
1092 z.resize (lwork); | |
1093 Complex *pz = z.fortran_vec (); | |
1094 | |
1095 info = 0; | |
1096 | |
4330 | 1097 // Calculate the norm of the matrix, for later use. |
4329 | 1098 double anorm; |
1099 if (calc_cond) | |
5275 | 1100 anorm = retval.abs().sum().row(static_cast<octave_idx_type>(0)).max(); |
4329 | 1101 |
1102 F77_XFCN (zgetrf, ZGETRF, (nc, nc, tmp_data, nr, pipvt, info)); | |
1948 | 1103 |
7482
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
1104 // Throw-away extra info LAPACK gives so as to not change output. |
7788 | 1105 rcon = 0.0; |
7482
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
1106 if (info != 0) |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
1107 info = -1; |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
1108 else if (calc_cond) |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
1109 { |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
1110 // 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
|
1111 octave_idx_type zgecon_info = 0; |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
1112 char job = '1'; |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
1113 Array<double> rz (2 * nc); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
1114 double *prz = rz.fortran_vec (); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
1115 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
|
1116 nc, tmp_data, nr, anorm, |
7788 | 1117 rcon, pz, prz, zgecon_info |
7482
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
1118 F77_CHAR_ARG_LEN (1))); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
1119 |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
1120 if (zgecon_info != 0) |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
1121 info = -1; |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
1122 } |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
1123 |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
1124 if (info == -1 && ! force) |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
1125 retval = *this; // Restore contents. |
1948 | 1126 else |
1127 { | |
7482
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
1128 octave_idx_type zgetri_info = 0; |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
1129 |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
1130 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
|
1131 pz, lwork, zgetri_info)); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
1132 |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
1133 if (zgetri_info != 0) |
1948 | 1134 info = -1; |
1135 } | |
6207 | 1136 |
1137 if (info != 0) | |
1138 mattype.mark_as_rectangular(); | |
458 | 1139 } |
4329 | 1140 |
1948 | 1141 return retval; |
458 | 1142 } |
1143 | |
1144 ComplexMatrix | |
6207 | 1145 ComplexMatrix::inverse (MatrixType &mattype, octave_idx_type& info, |
7788 | 1146 double& rcon, int force, int calc_cond) const |
6207 | 1147 { |
1148 int typ = mattype.type (false); | |
1149 ComplexMatrix ret; | |
1150 | |
1151 if (typ == MatrixType::Unknown) | |
1152 typ = mattype.type (*this); | |
1153 | |
1154 if (typ == MatrixType::Upper || typ == MatrixType::Lower) | |
7788 | 1155 ret = tinverse (mattype, info, rcon, force, calc_cond); |
6840 | 1156 else |
6207 | 1157 { |
1158 if (mattype.is_hermitian ()) | |
1159 { | |
6486 | 1160 ComplexCHOL chol (*this, info, calc_cond); |
6207 | 1161 if (info == 0) |
6486 | 1162 { |
1163 if (calc_cond) | |
7788 | 1164 rcon = chol.rcond(); |
6486 | 1165 else |
7788 | 1166 rcon = 1.0; |
6486 | 1167 ret = chol.inverse (); |
1168 } | |
6207 | 1169 else |
1170 mattype.mark_as_unsymmetric (); | |
1171 } | |
1172 | |
1173 if (!mattype.is_hermitian ()) | |
7788 | 1174 ret = finverse(mattype, info, rcon, force, calc_cond); |
1175 | |
1176 if ((mattype.is_hermitian () || calc_cond) && rcon == 0.) | |
6840 | 1177 ret = ComplexMatrix (rows (), columns (), Complex (octave_Inf, 0.)); |
6207 | 1178 } |
1179 | |
1180 return ret; | |
1181 } | |
1182 | |
1183 ComplexMatrix | |
4384 | 1184 ComplexMatrix::pseudo_inverse (double tol) const |
740 | 1185 { |
1549 | 1186 ComplexMatrix retval; |
1187 | |
3480 | 1188 ComplexSVD result (*this, SVD::economy); |
740 | 1189 |
1190 DiagMatrix S = result.singular_values (); | |
1191 ComplexMatrix U = result.left_singular_matrix (); | |
1192 ComplexMatrix V = result.right_singular_matrix (); | |
1193 | |
1194 ColumnVector sigma = S.diag (); | |
1195 | |
5275 | 1196 octave_idx_type r = sigma.length () - 1; |
1197 octave_idx_type nr = rows (); | |
1198 octave_idx_type nc = cols (); | |
740 | 1199 |
1200 if (tol <= 0.0) | |
1201 { | |
1202 if (nr > nc) | |
1203 tol = nr * sigma.elem (0) * DBL_EPSILON; | |
1204 else | |
1205 tol = nc * sigma.elem (0) * DBL_EPSILON; | |
1206 } | |
1207 | |
1208 while (r >= 0 && sigma.elem (r) < tol) | |
1209 r--; | |
1210 | |
1211 if (r < 0) | |
1549 | 1212 retval = ComplexMatrix (nc, nr, 0.0); |
740 | 1213 else |
1214 { | |
1215 ComplexMatrix Ur = U.extract (0, 0, nr-1, r); | |
1216 DiagMatrix D = DiagMatrix (sigma.extract (0, r)) . inverse (); | |
1217 ComplexMatrix Vr = V.extract (0, 0, nc-1, r); | |
1549 | 1218 retval = Vr * D * Ur.hermitian (); |
740 | 1219 } |
1549 | 1220 |
1221 return retval; | |
740 | 1222 } |
1223 | |
4773 | 1224 #if defined (HAVE_FFTW3) |
3827 | 1225 |
1226 ComplexMatrix | |
1227 ComplexMatrix::fourier (void) const | |
1228 { | |
1229 size_t nr = rows (); | |
1230 size_t nc = cols (); | |
1231 | |
1232 ComplexMatrix retval (nr, nc); | |
1233 | |
1234 size_t npts, nsamples; | |
1235 | |
1236 if (nr == 1 || nc == 1) | |
1237 { | |
1238 npts = nr > nc ? nr : nc; | |
1239 nsamples = 1; | |
1240 } | |
1241 else | |
1242 { | |
1243 npts = nr; | |
1244 nsamples = nc; | |
1245 } | |
1246 | |
1247 const Complex *in (data ()); | |
1248 Complex *out (retval.fortran_vec ()); | |
1249 | |
4773 | 1250 octave_fftw::fft (in, out, npts, nsamples); |
3827 | 1251 |
1252 return retval; | |
1253 } | |
1254 | |
1255 ComplexMatrix | |
1256 ComplexMatrix::ifourier (void) const | |
1257 { | |
1258 size_t nr = rows (); | |
1259 size_t nc = cols (); | |
1260 | |
1261 ComplexMatrix retval (nr, nc); | |
1262 | |
1263 size_t npts, nsamples; | |
1264 | |
1265 if (nr == 1 || nc == 1) | |
1266 { | |
1267 npts = nr > nc ? nr : nc; | |
1268 nsamples = 1; | |
1269 } | |
1270 else | |
1271 { | |
1272 npts = nr; | |
1273 nsamples = nc; | |
1274 } | |
1275 | |
1276 const Complex *in (data ()); | |
1277 Complex *out (retval.fortran_vec ()); | |
1278 | |
4773 | 1279 octave_fftw::ifft (in, out, npts, nsamples); |
3827 | 1280 |
1281 return retval; | |
1282 } | |
1283 | |
1284 ComplexMatrix | |
1285 ComplexMatrix::fourier2d (void) const | |
1286 { | |
4773 | 1287 dim_vector dv(rows (), cols ()); |
1288 | |
1289 ComplexMatrix retval (rows (), cols ()); | |
1290 const Complex *in (data ()); | |
1291 Complex *out (retval.fortran_vec ()); | |
1292 | |
1293 octave_fftw::fftNd (in, out, 2, dv); | |
3827 | 1294 |
1295 return retval; | |
1296 } | |
1297 | |
1298 ComplexMatrix | |
1299 ComplexMatrix::ifourier2d (void) const | |
1300 { | |
4773 | 1301 dim_vector dv(rows (), cols ()); |
1302 | |
1303 ComplexMatrix retval (rows (), cols ()); | |
1304 const Complex *in (data ()); | |
1305 Complex *out (retval.fortran_vec ()); | |
1306 | |
1307 octave_fftw::ifftNd (in, out, 2, dv); | |
3827 | 1308 |
1309 return retval; | |
1310 } | |
1311 | |
1312 #else | |
1313 | |
740 | 1314 ComplexMatrix |
458 | 1315 ComplexMatrix::fourier (void) const |
1316 { | |
1948 | 1317 ComplexMatrix retval; |
1318 | |
5275 | 1319 octave_idx_type nr = rows (); |
1320 octave_idx_type nc = cols (); | |
1321 | |
1322 octave_idx_type npts, nsamples; | |
1948 | 1323 |
458 | 1324 if (nr == 1 || nc == 1) |
1325 { | |
1326 npts = nr > nc ? nr : nc; | |
1327 nsamples = 1; | |
1328 } | |
1329 else | |
1330 { | |
1331 npts = nr; | |
1332 nsamples = nc; | |
1333 } | |
1334 | |
5275 | 1335 octave_idx_type nn = 4*npts+15; |
1948 | 1336 |
1337 Array<Complex> wsave (nn); | |
1338 Complex *pwsave = wsave.fortran_vec (); | |
1339 | |
1340 retval = *this; | |
1341 Complex *tmp_data = retval.fortran_vec (); | |
1342 | |
7789
82be108cc558
First attempt at single precision tyeps
David Bateman <dbateman@free.fr>
parents:
7788
diff
changeset
|
1343 F77_FUNC (zffti, ZFFTI) (npts, pwsave); |
458 | 1344 |
5275 | 1345 for (octave_idx_type j = 0; j < nsamples; j++) |
4153 | 1346 { |
1347 OCTAVE_QUIT; | |
1348 | |
7789
82be108cc558
First attempt at single precision tyeps
David Bateman <dbateman@free.fr>
parents:
7788
diff
changeset
|
1349 F77_FUNC (zfftf, ZFFTF) (npts, &tmp_data[npts*j], pwsave); |
4153 | 1350 } |
1948 | 1351 |
1352 return retval; | |
458 | 1353 } |
1354 | |
1355 ComplexMatrix | |
1356 ComplexMatrix::ifourier (void) const | |
1357 { | |
1948 | 1358 ComplexMatrix retval; |
1359 | |
5275 | 1360 octave_idx_type nr = rows (); |
1361 octave_idx_type nc = cols (); | |
1362 | |
1363 octave_idx_type npts, nsamples; | |
1948 | 1364 |
458 | 1365 if (nr == 1 || nc == 1) |
1366 { | |
1367 npts = nr > nc ? nr : nc; | |
1368 nsamples = 1; | |
1369 } | |
1370 else | |
1371 { | |
1372 npts = nr; | |
1373 nsamples = nc; | |
1374 } | |
1375 | |
5275 | 1376 octave_idx_type nn = 4*npts+15; |
1948 | 1377 |
1378 Array<Complex> wsave (nn); | |
1379 Complex *pwsave = wsave.fortran_vec (); | |
1380 | |
1381 retval = *this; | |
1382 Complex *tmp_data = retval.fortran_vec (); | |
1383 | |
7789
82be108cc558
First attempt at single precision tyeps
David Bateman <dbateman@free.fr>
parents:
7788
diff
changeset
|
1384 F77_FUNC (zffti, ZFFTI) (npts, pwsave); |
458 | 1385 |
5275 | 1386 for (octave_idx_type j = 0; j < nsamples; j++) |
4153 | 1387 { |
1388 OCTAVE_QUIT; | |
1389 | |
7789
82be108cc558
First attempt at single precision tyeps
David Bateman <dbateman@free.fr>
parents:
7788
diff
changeset
|
1390 F77_FUNC (zfftb, ZFFTB) (npts, &tmp_data[npts*j], pwsave); |
4153 | 1391 } |
458 | 1392 |
5275 | 1393 for (octave_idx_type j = 0; j < npts*nsamples; j++) |
3572 | 1394 tmp_data[j] = tmp_data[j] / static_cast<double> (npts); |
458 | 1395 |
1948 | 1396 return retval; |
458 | 1397 } |
1398 | |
677 | 1399 ComplexMatrix |
1400 ComplexMatrix::fourier2d (void) const | |
1401 { | |
1948 | 1402 ComplexMatrix retval; |
1403 | |
5275 | 1404 octave_idx_type nr = rows (); |
1405 octave_idx_type nc = cols (); | |
1406 | |
1407 octave_idx_type npts, nsamples; | |
1948 | 1408 |
677 | 1409 if (nr == 1 || nc == 1) |
1410 { | |
1411 npts = nr > nc ? nr : nc; | |
1412 nsamples = 1; | |
1413 } | |
1414 else | |
1415 { | |
1416 npts = nr; | |
1417 nsamples = nc; | |
1418 } | |
1419 | |
5275 | 1420 octave_idx_type nn = 4*npts+15; |
1948 | 1421 |
1422 Array<Complex> wsave (nn); | |
1423 Complex *pwsave = wsave.fortran_vec (); | |
1424 | |
1425 retval = *this; | |
1426 Complex *tmp_data = retval.fortran_vec (); | |
1427 | |
7789
82be108cc558
First attempt at single precision tyeps
David Bateman <dbateman@free.fr>
parents:
7788
diff
changeset
|
1428 F77_FUNC (zffti, ZFFTI) (npts, pwsave); |
677 | 1429 |
5275 | 1430 for (octave_idx_type j = 0; j < nsamples; j++) |
4153 | 1431 { |
1432 OCTAVE_QUIT; | |
1433 | |
7789
82be108cc558
First attempt at single precision tyeps
David Bateman <dbateman@free.fr>
parents:
7788
diff
changeset
|
1434 F77_FUNC (zfftf, ZFFTF) (npts, &tmp_data[npts*j], pwsave); |
4153 | 1435 } |
677 | 1436 |
1437 npts = nc; | |
1438 nsamples = nr; | |
1439 nn = 4*npts+15; | |
1948 | 1440 |
1441 wsave.resize (nn); | |
1442 pwsave = wsave.fortran_vec (); | |
1443 | |
4773 | 1444 Array<Complex> tmp (npts); |
1445 Complex *prow = tmp.fortran_vec (); | |
1948 | 1446 |
7789
82be108cc558
First attempt at single precision tyeps
David Bateman <dbateman@free.fr>
parents:
7788
diff
changeset
|
1447 F77_FUNC (zffti, ZFFTI) (npts, pwsave); |
677 | 1448 |
5275 | 1449 for (octave_idx_type j = 0; j < nsamples; j++) |
677 | 1450 { |
4153 | 1451 OCTAVE_QUIT; |
1452 | |
5275 | 1453 for (octave_idx_type i = 0; i < npts; i++) |
1948 | 1454 prow[i] = tmp_data[i*nr + j]; |
1455 | |
7789
82be108cc558
First attempt at single precision tyeps
David Bateman <dbateman@free.fr>
parents:
7788
diff
changeset
|
1456 F77_FUNC (zfftf, ZFFTF) (npts, prow, pwsave); |
677 | 1457 |
5275 | 1458 for (octave_idx_type i = 0; i < npts; i++) |
1948 | 1459 tmp_data[i*nr + j] = prow[i]; |
677 | 1460 } |
1461 | |
1948 | 1462 return retval; |
677 | 1463 } |
1464 | |
1465 ComplexMatrix | |
1466 ComplexMatrix::ifourier2d (void) const | |
1467 { | |
1948 | 1468 ComplexMatrix retval; |
1469 | |
5275 | 1470 octave_idx_type nr = rows (); |
1471 octave_idx_type nc = cols (); | |
1472 | |
1473 octave_idx_type npts, nsamples; | |
1948 | 1474 |
677 | 1475 if (nr == 1 || nc == 1) |
1476 { | |
1477 npts = nr > nc ? nr : nc; | |
1478 nsamples = 1; | |
1479 } | |
1480 else | |
1481 { | |
1482 npts = nr; | |
1483 nsamples = nc; | |
1484 } | |
1485 | |
5275 | 1486 octave_idx_type nn = 4*npts+15; |
1948 | 1487 |
1488 Array<Complex> wsave (nn); | |
1489 Complex *pwsave = wsave.fortran_vec (); | |
1490 | |
1491 retval = *this; | |
1492 Complex *tmp_data = retval.fortran_vec (); | |
1493 | |
7789
82be108cc558
First attempt at single precision tyeps
David Bateman <dbateman@free.fr>
parents:
7788
diff
changeset
|
1494 F77_FUNC (zffti, ZFFTI) (npts, pwsave); |
677 | 1495 |
5275 | 1496 for (octave_idx_type j = 0; j < nsamples; j++) |
4153 | 1497 { |
1498 OCTAVE_QUIT; | |
1499 | |
7789
82be108cc558
First attempt at single precision tyeps
David Bateman <dbateman@free.fr>
parents:
7788
diff
changeset
|
1500 F77_FUNC (zfftb, ZFFTB) (npts, &tmp_data[npts*j], pwsave); |
4153 | 1501 } |
677 | 1502 |
5275 | 1503 for (octave_idx_type j = 0; j < npts*nsamples; j++) |
3572 | 1504 tmp_data[j] = tmp_data[j] / static_cast<double> (npts); |
677 | 1505 |
1506 npts = nc; | |
1507 nsamples = nr; | |
1508 nn = 4*npts+15; | |
1948 | 1509 |
1510 wsave.resize (nn); | |
1511 pwsave = wsave.fortran_vec (); | |
1512 | |
4773 | 1513 Array<Complex> tmp (npts); |
1514 Complex *prow = tmp.fortran_vec (); | |
1948 | 1515 |
7789
82be108cc558
First attempt at single precision tyeps
David Bateman <dbateman@free.fr>
parents:
7788
diff
changeset
|
1516 F77_FUNC (zffti, ZFFTI) (npts, pwsave); |
677 | 1517 |
5275 | 1518 for (octave_idx_type j = 0; j < nsamples; j++) |
677 | 1519 { |
4153 | 1520 OCTAVE_QUIT; |
1521 | |
5275 | 1522 for (octave_idx_type i = 0; i < npts; i++) |
1948 | 1523 prow[i] = tmp_data[i*nr + j]; |
1524 | |
7789
82be108cc558
First attempt at single precision tyeps
David Bateman <dbateman@free.fr>
parents:
7788
diff
changeset
|
1525 F77_FUNC (zfftb, ZFFTB) (npts, prow, pwsave); |
677 | 1526 |
5275 | 1527 for (octave_idx_type i = 0; i < npts; i++) |
3572 | 1528 tmp_data[i*nr + j] = prow[i] / static_cast<double> (npts); |
677 | 1529 } |
1530 | |
1948 | 1531 return retval; |
677 | 1532 } |
1533 | |
3827 | 1534 #endif |
1535 | |
458 | 1536 ComplexDET |
1537 ComplexMatrix::determinant (void) const | |
1538 { | |
5275 | 1539 octave_idx_type info; |
7788 | 1540 double rcon; |
1541 return determinant (info, rcon, 0); | |
458 | 1542 } |
1543 | |
1544 ComplexDET | |
5275 | 1545 ComplexMatrix::determinant (octave_idx_type& info) const |
458 | 1546 { |
7788 | 1547 double rcon; |
1548 return determinant (info, rcon, 0); | |
458 | 1549 } |
1550 | |
1551 ComplexDET | |
7788 | 1552 ComplexMatrix::determinant (octave_idx_type& info, double& rcon, int calc_cond) const |
458 | 1553 { |
1554 ComplexDET retval; | |
1555 | |
5275 | 1556 octave_idx_type nr = rows (); |
1557 octave_idx_type nc = cols (); | |
458 | 1558 |
1559 if (nr == 0 || nc == 0) | |
1560 { | |
5634 | 1561 retval = ComplexDET (1.0, 0); |
458 | 1562 } |
1563 else | |
1564 { | |
5275 | 1565 Array<octave_idx_type> ipvt (nr); |
1566 octave_idx_type *pipvt = ipvt.fortran_vec (); | |
1948 | 1567 |
1568 ComplexMatrix atmp = *this; | |
1569 Complex *tmp_data = atmp.fortran_vec (); | |
1570 | |
4329 | 1571 info = 0; |
1572 | |
4330 | 1573 // Calculate the norm of the matrix, for later use. |
4329 | 1574 double anorm = 0; |
1575 if (calc_cond) | |
5275 | 1576 anorm = atmp.abs().sum().row(static_cast<octave_idx_type>(0)).max(); |
4329 | 1577 |
1578 F77_XFCN (zgetrf, ZGETRF, (nr, nc, tmp_data, nr, pipvt, info)); | |
1948 | 1579 |
7482
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
1580 // Throw-away extra info LAPACK gives so as to not change output. |
7788 | 1581 rcon = 0.0; |
7482
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
1582 if (info != 0) |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
1583 { |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
1584 info = -1; |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
1585 retval = ComplexDET (); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
1586 } |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
1587 else |
458 | 1588 { |
7482
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
1589 if (calc_cond) |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
1590 { |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
1591 // 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
|
1592 char job = '1'; |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
1593 Array<Complex> z (2*nr); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
1594 Complex *pz = z.fortran_vec (); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
1595 Array<double> rz (2*nr); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
1596 double *prz = rz.fortran_vec (); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
1597 |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
1598 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
|
1599 nc, tmp_data, nr, anorm, |
7788 | 1600 rcon, pz, prz, info |
7482
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
1601 F77_CHAR_ARG_LEN (1))); |
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 |
4509 | 1604 if (info != 0) |
1948 | 1605 { |
1606 info = -1; | |
1607 retval = ComplexDET (); | |
4329 | 1608 } |
1609 else | |
1948 | 1610 { |
7482
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
1611 Complex c = 1.0; |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
1612 int e = 0; |
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 for (octave_idx_type i = 0; i < nc; i++) |
4329 | 1615 { |
7482
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
1616 if (ipvt(i) != (i+1)) |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
1617 c = -c; |
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 c *= atmp(i,i); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
1620 |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
1621 if (c == 0.0) |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
1622 break; |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
1623 |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
1624 while (std::abs(c) < 0.5) |
4329 | 1625 { |
7482
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
1626 c *= 2.0; |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
1627 e--; |
4329 | 1628 } |
5634 | 1629 |
7482
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
1630 while (std::abs(c) >= 2.0) |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
1631 { |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
1632 c /= 2.0; |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
1633 e++; |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
1634 } |
4329 | 1635 } |
7482
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 retval = ComplexDET (c, e); |
1948 | 1638 } |
458 | 1639 } |
1640 } | |
4329 | 1641 |
458 | 1642 return retval; |
1643 } | |
1644 | |
7788 | 1645 double |
1646 ComplexMatrix::rcond (void) const | |
1647 { | |
1648 MatrixType mattype (*this); | |
1649 return rcond (mattype); | |
1650 } | |
1651 | |
1652 double | |
1653 ComplexMatrix::rcond (MatrixType &mattype) const | |
1654 { | |
1655 double rcon; | |
1656 octave_idx_type nr = rows (); | |
1657 octave_idx_type nc = cols (); | |
1658 | |
1659 if (nr != nc) | |
1660 (*current_liboctave_error_handler) ("matrix must be square"); | |
1661 else if (nr == 0 || nc == 0) | |
1662 rcon = octave_Inf; | |
1663 else | |
1664 { | |
1665 int typ = mattype.type (); | |
1666 | |
1667 if (typ == MatrixType::Unknown) | |
1668 typ = mattype.type (*this); | |
1669 | |
1670 // Only calculate the condition number for LU/Cholesky | |
1671 if (typ == MatrixType::Upper) | |
1672 { | |
1673 const Complex *tmp_data = fortran_vec (); | |
1674 octave_idx_type info = 0; | |
1675 char norm = '1'; | |
1676 char uplo = 'U'; | |
1677 char dia = 'N'; | |
1678 | |
1679 Array<Complex> z (2 * nc); | |
1680 Complex *pz = z.fortran_vec (); | |
1681 Array<double> rz (nc); | |
1682 double *prz = rz.fortran_vec (); | |
1683 | |
1684 F77_XFCN (ztrcon, ZTRCON, (F77_CONST_CHAR_ARG2 (&norm, 1), | |
1685 F77_CONST_CHAR_ARG2 (&uplo, 1), | |
1686 F77_CONST_CHAR_ARG2 (&dia, 1), | |
1687 nr, tmp_data, nr, rcon, | |
1688 pz, prz, info | |
1689 F77_CHAR_ARG_LEN (1) | |
1690 F77_CHAR_ARG_LEN (1) | |
1691 F77_CHAR_ARG_LEN (1))); | |
1692 | |
1693 if (info != 0) | |
1694 rcon = 0; | |
1695 } | |
1696 else if (typ == MatrixType::Permuted_Upper) | |
1697 (*current_liboctave_error_handler) | |
1698 ("permuted triangular matrix not implemented"); | |
1699 else if (typ == MatrixType::Lower) | |
1700 { | |
1701 const Complex *tmp_data = fortran_vec (); | |
1702 octave_idx_type info = 0; | |
1703 char norm = '1'; | |
1704 char uplo = 'L'; | |
1705 char dia = 'N'; | |
1706 | |
1707 Array<Complex> z (2 * nc); | |
1708 Complex *pz = z.fortran_vec (); | |
1709 Array<double> rz (nc); | |
1710 double *prz = rz.fortran_vec (); | |
1711 | |
1712 F77_XFCN (ztrcon, ZTRCON, (F77_CONST_CHAR_ARG2 (&norm, 1), | |
1713 F77_CONST_CHAR_ARG2 (&uplo, 1), | |
1714 F77_CONST_CHAR_ARG2 (&dia, 1), | |
1715 nr, tmp_data, nr, rcon, | |
1716 pz, prz, info | |
1717 F77_CHAR_ARG_LEN (1) | |
1718 F77_CHAR_ARG_LEN (1) | |
1719 F77_CHAR_ARG_LEN (1))); | |
1720 | |
1721 if (info != 0) | |
1722 rcon = 0.0; | |
1723 } | |
1724 else if (typ == MatrixType::Permuted_Lower) | |
1725 (*current_liboctave_error_handler) | |
1726 ("permuted triangular matrix not implemented"); | |
1727 else if (typ == MatrixType::Full || typ == MatrixType::Hermitian) | |
1728 { | |
1729 double anorm = -1.0; | |
1730 ComplexMatrix atmp = *this; | |
1731 Complex *tmp_data = atmp.fortran_vec (); | |
1732 | |
1733 if (typ == MatrixType::Hermitian) | |
1734 { | |
1735 octave_idx_type info = 0; | |
1736 char job = 'L'; | |
1737 anorm = atmp.abs().sum(). | |
1738 row(static_cast<octave_idx_type>(0)).max(); | |
1739 | |
1740 F77_XFCN (zpotrf, ZPOTRF, (F77_CONST_CHAR_ARG2 (&job, 1), nr, | |
1741 tmp_data, nr, info | |
1742 F77_CHAR_ARG_LEN (1))); | |
1743 | |
1744 if (info != 0) | |
1745 { | |
1746 rcon = 0.0; | |
1747 | |
1748 mattype.mark_as_unsymmetric (); | |
1749 typ = MatrixType::Full; | |
1750 } | |
1751 else | |
1752 { | |
1753 Array<Complex> z (2 * nc); | |
1754 Complex *pz = z.fortran_vec (); | |
1755 Array<double> rz (nc); | |
1756 double *prz = rz.fortran_vec (); | |
1757 | |
1758 F77_XFCN (zpocon, ZPOCON, (F77_CONST_CHAR_ARG2 (&job, 1), | |
1759 nr, tmp_data, nr, anorm, | |
1760 rcon, pz, prz, info | |
1761 F77_CHAR_ARG_LEN (1))); | |
1762 | |
1763 if (info != 0) | |
1764 rcon = 0.0; | |
1765 } | |
1766 } | |
1767 | |
1768 | |
1769 if (typ == MatrixType::Full) | |
1770 { | |
1771 octave_idx_type info = 0; | |
1772 | |
1773 Array<octave_idx_type> ipvt (nr); | |
1774 octave_idx_type *pipvt = ipvt.fortran_vec (); | |
1775 | |
1776 if(anorm < 0.) | |
1777 anorm = atmp.abs().sum(). | |
1778 row(static_cast<octave_idx_type>(0)).max(); | |
1779 | |
1780 Array<Complex> z (2 * nc); | |
1781 Complex *pz = z.fortran_vec (); | |
1782 Array<double> rz (2 * nc); | |
1783 double *prz = rz.fortran_vec (); | |
1784 | |
1785 F77_XFCN (zgetrf, ZGETRF, (nr, nr, tmp_data, nr, pipvt, info)); | |
1786 | |
1787 if (info != 0) | |
1788 { | |
1789 rcon = 0.0; | |
1790 mattype.mark_as_rectangular (); | |
1791 } | |
1792 else | |
1793 { | |
1794 char job = '1'; | |
1795 F77_XFCN (zgecon, ZGECON, (F77_CONST_CHAR_ARG2 (&job, 1), | |
1796 nc, tmp_data, nr, anorm, | |
1797 rcon, pz, prz, info | |
1798 F77_CHAR_ARG_LEN (1))); | |
1799 | |
1800 if (info != 0) | |
1801 rcon = 0.0; | |
1802 } | |
1803 } | |
1804 } | |
1805 else | |
1806 rcon = 0.0; | |
1807 } | |
1808 | |
1809 return rcon; | |
1810 } | |
1811 | |
458 | 1812 ComplexMatrix |
5785 | 1813 ComplexMatrix::utsolve (MatrixType &mattype, const ComplexMatrix& b, |
7788 | 1814 octave_idx_type& info, double& rcon, |
5785 | 1815 solve_singularity_handler sing_handler, |
1816 bool calc_cond) const | |
1817 { | |
1818 ComplexMatrix retval; | |
1819 | |
1820 octave_idx_type nr = rows (); | |
1821 octave_idx_type nc = cols (); | |
1822 | |
6924 | 1823 if (nr != b.rows ()) |
5785 | 1824 (*current_liboctave_error_handler) |
1825 ("matrix dimension mismatch solution of linear equations"); | |
6924 | 1826 else if (nr == 0 || nc == 0 || b.cols () == 0) |
1827 retval = ComplexMatrix (nc, b.cols (), Complex (0.0, 0.0)); | |
5785 | 1828 else |
1829 { | |
1830 volatile int typ = mattype.type (); | |
1831 | |
1832 if (typ == MatrixType::Permuted_Upper || | |
1833 typ == MatrixType::Upper) | |
1834 { | |
1835 octave_idx_type b_nc = b.cols (); | |
7788 | 1836 rcon = 1.; |
5785 | 1837 info = 0; |
1838 | |
1839 if (typ == MatrixType::Permuted_Upper) | |
1840 { | |
1841 (*current_liboctave_error_handler) | |
6390 | 1842 ("permuted triangular matrix not implemented"); |
5785 | 1843 } |
1844 else | |
1845 { | |
1846 const Complex *tmp_data = fortran_vec (); | |
1847 | |
1848 if (calc_cond) | |
1849 { | |
1850 char norm = '1'; | |
1851 char uplo = 'U'; | |
1852 char dia = 'N'; | |
1853 | |
1854 Array<Complex> z (2 * nc); | |
1855 Complex *pz = z.fortran_vec (); | |
1856 Array<double> rz (nc); | |
1857 double *prz = rz.fortran_vec (); | |
1858 | |
1859 F77_XFCN (ztrcon, ZTRCON, (F77_CONST_CHAR_ARG2 (&norm, 1), | |
1860 F77_CONST_CHAR_ARG2 (&uplo, 1), | |
1861 F77_CONST_CHAR_ARG2 (&dia, 1), | |
7788 | 1862 nr, tmp_data, nr, rcon, |
5785 | 1863 pz, prz, info |
1864 F77_CHAR_ARG_LEN (1) | |
1865 F77_CHAR_ARG_LEN (1) | |
1866 F77_CHAR_ARG_LEN (1))); | |
1867 | |
1868 if (info != 0) | |
1869 info = -2; | |
1870 | |
7788 | 1871 volatile double rcond_plus_one = rcon + 1.0; |
1872 | |
1873 if (rcond_plus_one == 1.0 || xisnan (rcon)) | |
5785 | 1874 { |
1875 info = -2; | |
1876 | |
1877 if (sing_handler) | |
7788 | 1878 sing_handler (rcon); |
5785 | 1879 else |
1880 (*current_liboctave_error_handler) | |
1881 ("matrix singular to machine precision, rcond = %g", | |
7788 | 1882 rcon); |
5785 | 1883 } |
1884 } | |
1885 | |
1886 if (info == 0) | |
1887 { | |
1888 retval = b; | |
1889 Complex *result = retval.fortran_vec (); | |
1890 | |
1891 char uplo = 'U'; | |
1892 char trans = 'N'; | |
1893 char dia = 'N'; | |
1894 | |
1895 F77_XFCN (ztrtrs, ZTRTRS, (F77_CONST_CHAR_ARG2 (&uplo, 1), | |
1896 F77_CONST_CHAR_ARG2 (&trans, 1), | |
1897 F77_CONST_CHAR_ARG2 (&dia, 1), | |
1898 nr, b_nc, tmp_data, nr, | |
1899 result, nr, info | |
1900 F77_CHAR_ARG_LEN (1) | |
1901 F77_CHAR_ARG_LEN (1) | |
1902 F77_CHAR_ARG_LEN (1))); | |
1903 } | |
1904 } | |
1905 } | |
1906 else | |
1907 (*current_liboctave_error_handler) ("incorrect matrix type"); | |
1908 } | |
1909 | |
1910 return retval; | |
1911 } | |
1912 | |
1913 ComplexMatrix | |
1914 ComplexMatrix::ltsolve (MatrixType &mattype, const ComplexMatrix& b, | |
7788 | 1915 octave_idx_type& info, double& rcon, |
5785 | 1916 solve_singularity_handler sing_handler, |
1917 bool calc_cond) const | |
1918 { | |
1919 ComplexMatrix retval; | |
1920 | |
1921 octave_idx_type nr = rows (); | |
1922 octave_idx_type nc = cols (); | |
1923 | |
6924 | 1924 if (nr != b.rows ()) |
5785 | 1925 (*current_liboctave_error_handler) |
1926 ("matrix dimension mismatch solution of linear equations"); | |
6924 | 1927 else if (nr == 0 || nc == 0 || b.cols () == 0) |
1928 retval = ComplexMatrix (nc, b.cols (), Complex (0.0, 0.0)); | |
5785 | 1929 else |
1930 { | |
1931 volatile int typ = mattype.type (); | |
1932 | |
1933 if (typ == MatrixType::Permuted_Lower || | |
1934 typ == MatrixType::Lower) | |
1935 { | |
1936 octave_idx_type b_nc = b.cols (); | |
7788 | 1937 rcon = 1.; |
5785 | 1938 info = 0; |
1939 | |
1940 if (typ == MatrixType::Permuted_Lower) | |
1941 { | |
1942 (*current_liboctave_error_handler) | |
6390 | 1943 ("permuted triangular matrix not implemented"); |
5785 | 1944 } |
1945 else | |
1946 { | |
1947 const Complex *tmp_data = fortran_vec (); | |
1948 | |
1949 if (calc_cond) | |
1950 { | |
1951 char norm = '1'; | |
1952 char uplo = 'L'; | |
1953 char dia = 'N'; | |
1954 | |
1955 Array<Complex> z (2 * nc); | |
1956 Complex *pz = z.fortran_vec (); | |
1957 Array<double> rz (nc); | |
1958 double *prz = rz.fortran_vec (); | |
1959 | |
1960 F77_XFCN (ztrcon, ZTRCON, (F77_CONST_CHAR_ARG2 (&norm, 1), | |
1961 F77_CONST_CHAR_ARG2 (&uplo, 1), | |
1962 F77_CONST_CHAR_ARG2 (&dia, 1), | |
7788 | 1963 nr, tmp_data, nr, rcon, |
5785 | 1964 pz, prz, info |
1965 F77_CHAR_ARG_LEN (1) | |
1966 F77_CHAR_ARG_LEN (1) | |
1967 F77_CHAR_ARG_LEN (1))); | |
1968 | |
1969 if (info != 0) | |
1970 info = -2; | |
1971 | |
7788 | 1972 volatile double rcond_plus_one = rcon + 1.0; |
1973 | |
1974 if (rcond_plus_one == 1.0 || xisnan (rcon)) | |
5785 | 1975 { |
1976 info = -2; | |
1977 | |
1978 if (sing_handler) | |
7788 | 1979 sing_handler (rcon); |
5785 | 1980 else |
1981 (*current_liboctave_error_handler) | |
1982 ("matrix singular to machine precision, rcond = %g", | |
7788 | 1983 rcon); |
5785 | 1984 } |
1985 } | |
1986 | |
1987 if (info == 0) | |
1988 { | |
1989 retval = b; | |
1990 Complex *result = retval.fortran_vec (); | |
1991 | |
1992 char uplo = 'L'; | |
1993 char trans = 'N'; | |
1994 char dia = 'N'; | |
1995 | |
1996 F77_XFCN (ztrtrs, ZTRTRS, (F77_CONST_CHAR_ARG2 (&uplo, 1), | |
1997 F77_CONST_CHAR_ARG2 (&trans, 1), | |
1998 F77_CONST_CHAR_ARG2 (&dia, 1), | |
1999 nr, b_nc, tmp_data, nr, | |
2000 result, nr, info | |
2001 F77_CHAR_ARG_LEN (1) | |
2002 F77_CHAR_ARG_LEN (1) | |
2003 F77_CHAR_ARG_LEN (1))); | |
2004 } | |
2005 } | |
2006 } | |
2007 else | |
2008 (*current_liboctave_error_handler) ("incorrect matrix type"); | |
2009 } | |
2010 | |
2011 return retval; | |
2012 } | |
2013 | |
2014 ComplexMatrix | |
2015 ComplexMatrix::fsolve (MatrixType &mattype, const ComplexMatrix& b, | |
7788 | 2016 octave_idx_type& info, double& rcon, |
5785 | 2017 solve_singularity_handler sing_handler, |
2018 bool calc_cond) const | |
2019 { | |
2020 ComplexMatrix retval; | |
2021 | |
2022 octave_idx_type nr = rows (); | |
2023 octave_idx_type nc = cols (); | |
2024 | |
6924 | 2025 |
2026 if (nr != nc || nr != b.rows ()) | |
5785 | 2027 (*current_liboctave_error_handler) |
6924 | 2028 ("matrix dimension mismatch solution of linear equations"); |
2029 else if (nr == 0 || b.cols () == 0) | |
2030 retval = ComplexMatrix (nc, b.cols (), Complex (0.0, 0.0)); | |
5785 | 2031 else |
2032 { | |
2033 volatile int typ = mattype.type (); | |
2034 | |
2035 // Calculate the norm of the matrix, for later use. | |
2036 double anorm = -1.; | |
2037 | |
2038 if (typ == MatrixType::Hermitian) | |
2039 { | |
2040 info = 0; | |
2041 char job = 'L'; | |
2042 ComplexMatrix atmp = *this; | |
2043 Complex *tmp_data = atmp.fortran_vec (); | |
2044 anorm = atmp.abs().sum().row(static_cast<octave_idx_type>(0)).max(); | |
2045 | |
2046 F77_XFCN (zpotrf, ZPOTRF, (F77_CONST_CHAR_ARG2 (&job, 1), nr, | |
2047 tmp_data, nr, info | |
2048 F77_CHAR_ARG_LEN (1))); | |
2049 | |
7482
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2050 // Throw-away extra info LAPACK gives so as to not change output. |
7788 | 2051 rcon = 0.0; |
7482
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2052 if (info != 0) |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2053 { |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2054 info = -2; |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2055 |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2056 mattype.mark_as_unsymmetric (); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2057 typ = MatrixType::Full; |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2058 } |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2059 else |
5785 | 2060 { |
7482
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2061 if (calc_cond) |
5785 | 2062 { |
7482
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2063 Array<Complex> z (2 * nc); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2064 Complex *pz = z.fortran_vec (); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2065 Array<double> rz (nc); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2066 double *prz = rz.fortran_vec (); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2067 |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2068 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
|
2069 nr, tmp_data, nr, anorm, |
7788 | 2070 rcon, pz, prz, info |
7482
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2071 F77_CHAR_ARG_LEN (1))); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2072 |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2073 if (info != 0) |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2074 info = -2; |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2075 |
7788 | 2076 volatile double rcond_plus_one = rcon + 1.0; |
2077 | |
2078 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
|
2079 { |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2080 info = -2; |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2081 |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2082 if (sing_handler) |
7788 | 2083 sing_handler (rcon); |
7482
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2084 else |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2085 (*current_liboctave_error_handler) |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2086 ("matrix singular to machine precision, rcond = %g", |
7788 | 2087 rcon); |
7482
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 } |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2090 |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2091 if (info == 0) |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2092 { |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2093 retval = b; |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2094 Complex *result = retval.fortran_vec (); |
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 octave_idx_type b_nc = b.cols (); |
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 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
|
2099 nr, b_nc, tmp_data, nr, |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2100 result, b.rows(), info |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2101 F77_CHAR_ARG_LEN (1))); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2102 } |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2103 else |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2104 { |
5785 | 2105 mattype.mark_as_unsymmetric (); |
2106 typ = MatrixType::Full; | |
2107 } | |
2108 } | |
2109 } | |
2110 | |
2111 if (typ == MatrixType::Full) | |
2112 { | |
2113 info = 0; | |
2114 | |
2115 Array<octave_idx_type> ipvt (nr); | |
2116 octave_idx_type *pipvt = ipvt.fortran_vec (); | |
2117 | |
2118 ComplexMatrix atmp = *this; | |
2119 Complex *tmp_data = atmp.fortran_vec (); | |
2120 | |
2121 Array<Complex> z (2 * nc); | |
2122 Complex *pz = z.fortran_vec (); | |
2123 Array<double> rz (2 * nc); | |
2124 double *prz = rz.fortran_vec (); | |
2125 | |
2126 // Calculate the norm of the matrix, for later use. | |
2127 if (anorm < 0.) | |
2128 anorm = atmp.abs().sum().row(static_cast<octave_idx_type>(0)).max(); | |
2129 | |
2130 F77_XFCN (zgetrf, ZGETRF, (nr, nr, tmp_data, nr, pipvt, info)); | |
2131 | |
7482
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2132 // Throw-away extra info LAPACK gives so as to not change output. |
7788 | 2133 rcon = 0.0; |
7482
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2134 if (info != 0) |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2135 { |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2136 info = -2; |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2137 |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2138 if (sing_handler) |
7788 | 2139 sing_handler (rcon); |
7482
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2140 else |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2141 (*current_liboctave_error_handler) |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2142 ("matrix singular to machine precision"); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2143 |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2144 mattype.mark_as_rectangular (); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2145 } |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2146 else |
5785 | 2147 { |
7482
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2148 if (calc_cond) |
5785 | 2149 { |
7482
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2150 // Now calculate the condition number for |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2151 // non-singular matrix. |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2152 char job = '1'; |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2153 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
|
2154 nc, tmp_data, nr, anorm, |
7788 | 2155 rcon, pz, prz, info |
7482
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2156 F77_CHAR_ARG_LEN (1))); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2157 |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2158 if (info != 0) |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2159 info = -2; |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2160 |
7788 | 2161 volatile double rcond_plus_one = rcon + 1.0; |
2162 | |
2163 if (rcond_plus_one == 1.0 || xisnan (rcon)) | |
5785 | 2164 { |
7482
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2165 info = -2; |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2166 |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2167 if (sing_handler) |
7788 | 2168 sing_handler (rcon); |
7482
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2169 else |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2170 (*current_liboctave_error_handler) |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2171 ("matrix singular to machine precision, rcond = %g", |
7788 | 2172 rcon); |
5785 | 2173 } |
2174 } | |
7482
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2175 |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2176 if (info == 0) |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2177 { |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2178 retval = b; |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2179 Complex *result = retval.fortran_vec (); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2180 |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2181 octave_idx_type b_nc = b.cols (); |
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 char job = 'N'; |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2184 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
|
2185 nr, b_nc, tmp_data, nr, |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2186 pipvt, result, b.rows(), info |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2187 F77_CHAR_ARG_LEN (1))); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2188 } |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2189 else |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2190 mattype.mark_as_rectangular (); |
5785 | 2191 } |
2192 } | |
2193 } | |
2194 | |
2195 return retval; | |
2196 } | |
2197 | |
2198 ComplexMatrix | |
2199 ComplexMatrix::solve (MatrixType &typ, const Matrix& b) const | |
2200 { | |
2201 octave_idx_type info; | |
7788 | 2202 double rcon; |
2203 return solve (typ, b, info, rcon, 0); | |
5785 | 2204 } |
2205 | |
2206 ComplexMatrix | |
2207 ComplexMatrix::solve (MatrixType &typ, const Matrix& b, | |
2208 octave_idx_type& info) const | |
2209 { | |
7788 | 2210 double rcon; |
2211 return solve (typ, b, info, rcon, 0); | |
5785 | 2212 } |
2213 | |
2214 ComplexMatrix | |
2215 ComplexMatrix::solve (MatrixType &typ, const Matrix& b, octave_idx_type& info, | |
7788 | 2216 double& rcon) const |
5785 | 2217 { |
7788 | 2218 return solve (typ, b, info, rcon, 0); |
5785 | 2219 } |
2220 | |
2221 ComplexMatrix | |
2222 ComplexMatrix::solve (MatrixType &typ, const Matrix& b, octave_idx_type& info, | |
7788 | 2223 double& rcon, solve_singularity_handler sing_handler, |
5785 | 2224 bool singular_fallback) const |
2225 { | |
2226 ComplexMatrix tmp (b); | |
7788 | 2227 return solve (typ, tmp, info, rcon, sing_handler, singular_fallback); |
5785 | 2228 } |
2229 | |
2230 ComplexMatrix | |
2231 ComplexMatrix::solve (MatrixType &typ, const ComplexMatrix& b) const | |
2232 { | |
2233 octave_idx_type info; | |
7788 | 2234 double rcon; |
2235 return solve (typ, b, info, rcon, 0); | |
5785 | 2236 } |
2237 | |
2238 ComplexMatrix | |
2239 ComplexMatrix::solve (MatrixType &typ, const ComplexMatrix& b, | |
2240 octave_idx_type& info) const | |
2241 { | |
7788 | 2242 double rcon; |
2243 return solve (typ, b, info, rcon, 0); | |
5785 | 2244 } |
2245 | |
2246 ComplexMatrix | |
2247 ComplexMatrix::solve (MatrixType &typ, const ComplexMatrix& b, | |
7788 | 2248 octave_idx_type& info, double& rcon) const |
5785 | 2249 { |
7788 | 2250 return solve (typ, b, info, rcon, 0); |
5785 | 2251 } |
2252 | |
2253 ComplexMatrix | |
2254 ComplexMatrix::solve (MatrixType &mattype, const ComplexMatrix& b, | |
7788 | 2255 octave_idx_type& info, double& rcon, |
5785 | 2256 solve_singularity_handler sing_handler, |
2257 bool singular_fallback) const | |
2258 { | |
2259 ComplexMatrix retval; | |
2260 int typ = mattype.type (); | |
2261 | |
2262 if (typ == MatrixType::Unknown) | |
2263 typ = mattype.type (*this); | |
2264 | |
2265 // Only calculate the condition number for LU/Cholesky | |
2266 if (typ == MatrixType::Upper || typ == MatrixType::Permuted_Upper) | |
7788 | 2267 retval = utsolve (mattype, b, info, rcon, sing_handler, false); |
5785 | 2268 else if (typ == MatrixType::Lower || typ == MatrixType::Permuted_Lower) |
7788 | 2269 retval = ltsolve (mattype, b, info, rcon, sing_handler, false); |
5785 | 2270 else if (typ == MatrixType::Full || typ == MatrixType::Hermitian) |
7788 | 2271 retval = fsolve (mattype, b, info, rcon, sing_handler, true); |
5785 | 2272 else if (typ != MatrixType::Rectangular) |
2273 { | |
2274 (*current_liboctave_error_handler) ("unknown matrix type"); | |
2275 return ComplexMatrix (); | |
2276 } | |
2277 | |
2278 // Rectangular or one of the above solvers flags a singular matrix | |
2279 if (singular_fallback && mattype.type () == MatrixType::Rectangular) | |
2280 { | |
2281 octave_idx_type rank; | |
7788 | 2282 retval = lssolve (b, info, rank, rcon); |
5785 | 2283 } |
2284 | |
2285 return retval; | |
2286 } | |
2287 | |
2288 ComplexColumnVector | |
2289 ComplexMatrix::solve (MatrixType &typ, const ColumnVector& b) const | |
2290 { | |
2291 octave_idx_type info; | |
7788 | 2292 double rcon; |
2293 return solve (typ, ComplexColumnVector (b), info, rcon, 0); | |
5785 | 2294 } |
2295 | |
2296 ComplexColumnVector | |
2297 ComplexMatrix::solve (MatrixType &typ, const ColumnVector& b, | |
2298 octave_idx_type& info) const | |
2299 { | |
7788 | 2300 double rcon; |
2301 return solve (typ, ComplexColumnVector (b), info, rcon, 0); | |
5785 | 2302 } |
2303 | |
2304 ComplexColumnVector | |
2305 ComplexMatrix::solve (MatrixType &typ, const ColumnVector& b, | |
7788 | 2306 octave_idx_type& info, double& rcon) const |
5785 | 2307 { |
7788 | 2308 return solve (typ, ComplexColumnVector (b), info, rcon, 0); |
5785 | 2309 } |
2310 | |
2311 ComplexColumnVector | |
2312 ComplexMatrix::solve (MatrixType &typ, const ColumnVector& b, | |
7788 | 2313 octave_idx_type& info, double& rcon, |
5785 | 2314 solve_singularity_handler sing_handler) const |
2315 { | |
7788 | 2316 return solve (typ, ComplexColumnVector (b), info, rcon, sing_handler); |
5785 | 2317 } |
2318 | |
2319 ComplexColumnVector | |
2320 ComplexMatrix::solve (MatrixType &typ, const ComplexColumnVector& b) const | |
2321 { | |
2322 octave_idx_type info; | |
7788 | 2323 double rcon; |
2324 return solve (typ, b, info, rcon, 0); | |
5785 | 2325 } |
2326 | |
2327 ComplexColumnVector | |
2328 ComplexMatrix::solve (MatrixType &typ, const ComplexColumnVector& b, | |
2329 octave_idx_type& info) const | |
2330 { | |
7788 | 2331 double rcon; |
2332 return solve (typ, b, info, rcon, 0); | |
5785 | 2333 } |
2334 | |
2335 ComplexColumnVector | |
2336 ComplexMatrix::solve (MatrixType &typ, const ComplexColumnVector& b, | |
7788 | 2337 octave_idx_type& info, double& rcon) const |
5785 | 2338 { |
7788 | 2339 return solve (typ, b, info, rcon, 0); |
5785 | 2340 } |
2341 | |
2342 ComplexColumnVector | |
2343 ComplexMatrix::solve (MatrixType &typ, const ComplexColumnVector& b, | |
7788 | 2344 octave_idx_type& info, double& rcon, |
5785 | 2345 solve_singularity_handler sing_handler) const |
2346 { | |
2347 | |
2348 ComplexMatrix tmp (b); | |
7788 | 2349 return solve (typ, tmp, info, rcon, sing_handler).column(static_cast<octave_idx_type> (0)); |
5785 | 2350 } |
2351 | |
2352 ComplexMatrix | |
458 | 2353 ComplexMatrix::solve (const Matrix& b) const |
2354 { | |
5275 | 2355 octave_idx_type info; |
7788 | 2356 double rcon; |
2357 return solve (b, info, rcon, 0); | |
458 | 2358 } |
2359 | |
2360 ComplexMatrix | |
5275 | 2361 ComplexMatrix::solve (const Matrix& b, octave_idx_type& info) const |
458 | 2362 { |
7788 | 2363 double rcon; |
2364 return solve (b, info, rcon, 0); | |
458 | 2365 } |
2366 | |
2367 ComplexMatrix | |
7788 | 2368 ComplexMatrix::solve (const Matrix& b, octave_idx_type& info, double& rcon) const |
458 | 2369 { |
7788 | 2370 return solve (b, info, rcon, 0); |
3480 | 2371 } |
2372 | |
2373 ComplexMatrix | |
7788 | 2374 ComplexMatrix::solve (const Matrix& b, octave_idx_type& info, double& rcon, |
3480 | 2375 solve_singularity_handler sing_handler) const |
2376 { | |
458 | 2377 ComplexMatrix tmp (b); |
7788 | 2378 return solve (tmp, info, rcon, sing_handler); |
458 | 2379 } |
2380 | |
2381 ComplexMatrix | |
2382 ComplexMatrix::solve (const ComplexMatrix& b) const | |
2383 { | |
5275 | 2384 octave_idx_type info; |
7788 | 2385 double rcon; |
2386 return solve (b, info, rcon, 0); | |
458 | 2387 } |
2388 | |
2389 ComplexMatrix | |
5275 | 2390 ComplexMatrix::solve (const ComplexMatrix& b, octave_idx_type& info) const |
458 | 2391 { |
7788 | 2392 double rcon; |
2393 return solve (b, info, rcon, 0); | |
458 | 2394 } |
3480 | 2395 |
458 | 2396 ComplexMatrix |
7788 | 2397 ComplexMatrix::solve (const ComplexMatrix& b, octave_idx_type& info, double& rcon) const |
458 | 2398 { |
7788 | 2399 return solve (b, info, rcon, 0); |
3480 | 2400 } |
2401 | |
2402 ComplexMatrix | |
7788 | 2403 ComplexMatrix::solve (const ComplexMatrix& b, octave_idx_type& info, double& rcon, |
3480 | 2404 solve_singularity_handler sing_handler) const |
2405 { | |
5785 | 2406 MatrixType mattype (*this); |
7788 | 2407 return solve (mattype, b, info, rcon, sing_handler); |
458 | 2408 } |
2409 | |
2410 ComplexColumnVector | |
3585 | 2411 ComplexMatrix::solve (const ColumnVector& b) const |
2412 { | |
5275 | 2413 octave_idx_type info; |
7788 | 2414 double rcon; |
2415 return solve (ComplexColumnVector (b), info, rcon, 0); | |
3585 | 2416 } |
2417 | |
2418 ComplexColumnVector | |
5275 | 2419 ComplexMatrix::solve (const ColumnVector& b, octave_idx_type& info) const |
3585 | 2420 { |
7788 | 2421 double rcon; |
2422 return solve (ComplexColumnVector (b), info, rcon, 0); | |
3585 | 2423 } |
2424 | |
2425 ComplexColumnVector | |
5785 | 2426 ComplexMatrix::solve (const ColumnVector& b, octave_idx_type& info, |
7788 | 2427 double& rcon) const |
3585 | 2428 { |
7788 | 2429 return solve (ComplexColumnVector (b), info, rcon, 0); |
3585 | 2430 } |
2431 | |
2432 ComplexColumnVector | |
5785 | 2433 ComplexMatrix::solve (const ColumnVector& b, octave_idx_type& info, |
7788 | 2434 double& rcon, |
3585 | 2435 solve_singularity_handler sing_handler) const |
2436 { | |
7788 | 2437 return solve (ComplexColumnVector (b), info, rcon, sing_handler); |
3585 | 2438 } |
2439 | |
2440 ComplexColumnVector | |
458 | 2441 ComplexMatrix::solve (const ComplexColumnVector& b) const |
2442 { | |
5275 | 2443 octave_idx_type info; |
7788 | 2444 double rcon; |
2445 return solve (b, info, rcon, 0); | |
458 | 2446 } |
2447 | |
2448 ComplexColumnVector | |
5275 | 2449 ComplexMatrix::solve (const ComplexColumnVector& b, octave_idx_type& info) const |
458 | 2450 { |
7788 | 2451 double rcon; |
2452 return solve (b, info, rcon, 0); | |
458 | 2453 } |
2454 | |
2455 ComplexColumnVector | |
5275 | 2456 ComplexMatrix::solve (const ComplexColumnVector& b, octave_idx_type& info, |
7788 | 2457 double& rcon) const |
458 | 2458 { |
7788 | 2459 return solve (b, info, rcon, 0); |
3480 | 2460 } |
2461 | |
2462 ComplexColumnVector | |
5275 | 2463 ComplexMatrix::solve (const ComplexColumnVector& b, octave_idx_type& info, |
7788 | 2464 double& rcon, |
3480 | 2465 solve_singularity_handler sing_handler) const |
2466 { | |
5785 | 2467 MatrixType mattype (*this); |
7788 | 2468 return solve (mattype, b, info, rcon, sing_handler); |
458 | 2469 } |
2470 | |
2471 ComplexMatrix | |
3585 | 2472 ComplexMatrix::lssolve (const Matrix& b) const |
2473 { | |
5275 | 2474 octave_idx_type info; |
2475 octave_idx_type rank; | |
7788 | 2476 double rcon; |
2477 return lssolve (ComplexMatrix (b), info, rank, rcon); | |
3585 | 2478 } |
2479 | |
2480 ComplexMatrix | |
5275 | 2481 ComplexMatrix::lssolve (const Matrix& b, octave_idx_type& info) const |
3585 | 2482 { |
5275 | 2483 octave_idx_type rank; |
7788 | 2484 double rcon; |
2485 return lssolve (ComplexMatrix (b), info, rank, rcon); | |
3585 | 2486 } |
2487 | |
2488 ComplexMatrix | |
7076 | 2489 ComplexMatrix::lssolve (const Matrix& b, octave_idx_type& info, |
2490 octave_idx_type& rank) const | |
3585 | 2491 { |
7788 | 2492 double rcon; |
2493 return lssolve (ComplexMatrix (b), info, rank, rcon); | |
7076 | 2494 } |
2495 | |
2496 ComplexMatrix | |
2497 ComplexMatrix::lssolve (const Matrix& b, octave_idx_type& info, | |
7788 | 2498 octave_idx_type& rank, double& rcon) const |
7076 | 2499 { |
7788 | 2500 return lssolve (ComplexMatrix (b), info, rank, rcon); |
3585 | 2501 } |
2502 | |
2503 ComplexMatrix | |
458 | 2504 ComplexMatrix::lssolve (const ComplexMatrix& b) const |
2505 { | |
5275 | 2506 octave_idx_type info; |
2507 octave_idx_type rank; | |
7788 | 2508 double rcon; |
2509 return lssolve (b, info, rank, rcon); | |
458 | 2510 } |
2511 | |
2512 ComplexMatrix | |
5275 | 2513 ComplexMatrix::lssolve (const ComplexMatrix& b, octave_idx_type& info) const |
458 | 2514 { |
5275 | 2515 octave_idx_type rank; |
7788 | 2516 double rcon; |
2517 return lssolve (b, info, rank, rcon); | |
458 | 2518 } |
2519 | |
2520 ComplexMatrix | |
7076 | 2521 ComplexMatrix::lssolve (const ComplexMatrix& b, octave_idx_type& info, |
2522 octave_idx_type& rank) const | |
2523 { | |
7788 | 2524 double rcon; |
2525 return lssolve (b, info, rank, rcon); | |
7076 | 2526 } |
2527 | |
2528 ComplexMatrix | |
2529 ComplexMatrix::lssolve (const ComplexMatrix& b, octave_idx_type& info, | |
7788 | 2530 octave_idx_type& rank, double& rcon) const |
458 | 2531 { |
1948 | 2532 ComplexMatrix retval; |
2533 | |
5275 | 2534 octave_idx_type nrhs = b.cols (); |
2535 | |
2536 octave_idx_type m = rows (); | |
2537 octave_idx_type n = cols (); | |
458 | 2538 |
6924 | 2539 if (m != b.rows ()) |
1948 | 2540 (*current_liboctave_error_handler) |
2541 ("matrix dimension mismatch solution of linear equations"); | |
6924 | 2542 else if (m== 0 || n == 0 || b.cols () == 0) |
2543 retval = ComplexMatrix (n, b.cols (), Complex (0.0, 0.0)); | |
1948 | 2544 else |
458 | 2545 { |
7072 | 2546 volatile octave_idx_type minmn = (m < n ? m : n); |
2547 octave_idx_type maxmn = m > n ? m : n; | |
7788 | 2548 rcon = -1.0; |
7072 | 2549 |
2550 if (m != n) | |
2551 { | |
2552 retval = ComplexMatrix (maxmn, nrhs); | |
2553 | |
2554 for (octave_idx_type j = 0; j < nrhs; j++) | |
2555 for (octave_idx_type i = 0; i < m; i++) | |
2556 retval.elem (i, j) = b.elem (i, j); | |
2557 } | |
2558 else | |
2559 retval = b; | |
2560 | |
1948 | 2561 ComplexMatrix atmp = *this; |
2562 Complex *tmp_data = atmp.fortran_vec (); | |
2563 | |
7072 | 2564 Complex *pretval = retval.fortran_vec (); |
2565 Array<double> s (minmn); | |
7071 | 2566 double *ps = s.fortran_vec (); |
2563 | 2567 |
7072 | 2568 // Ask ZGELSD what the dimension of WORK should be. |
5275 | 2569 octave_idx_type lwork = -1; |
3752 | 2570 |
2571 Array<Complex> work (1); | |
7079 | 2572 |
7477 | 2573 octave_idx_type smlsiz; |
2574 F77_FUNC (xilaenv, XILAENV) (9, F77_CONST_CHAR_ARG2 ("ZGELSD", 6), | |
2575 F77_CONST_CHAR_ARG2 (" ", 1), | |
7478 | 2576 0, 0, 0, 0, smlsiz |
7477 | 2577 F77_CHAR_ARG_LEN (6) |
7478 | 2578 F77_CHAR_ARG_LEN (1)); |
7079 | 2579 |
7486
6a6d2abe51ff
more xGELSD workspace fixes
John W. Eaton <jwe@octave.org>
parents:
7482
diff
changeset
|
2580 octave_idx_type mnthr; |
6a6d2abe51ff
more xGELSD workspace fixes
John W. Eaton <jwe@octave.org>
parents:
7482
diff
changeset
|
2581 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
|
2582 F77_CONST_CHAR_ARG2 (" ", 1), |
6a6d2abe51ff
more xGELSD workspace fixes
John W. Eaton <jwe@octave.org>
parents:
7482
diff
changeset
|
2583 m, n, nrhs, -1, mnthr |
6a6d2abe51ff
more xGELSD workspace fixes
John W. Eaton <jwe@octave.org>
parents:
7482
diff
changeset
|
2584 F77_CHAR_ARG_LEN (6) |
6a6d2abe51ff
more xGELSD workspace fixes
John W. Eaton <jwe@octave.org>
parents:
7482
diff
changeset
|
2585 F77_CHAR_ARG_LEN (1)); |
6a6d2abe51ff
more xGELSD workspace fixes
John W. Eaton <jwe@octave.org>
parents:
7482
diff
changeset
|
2586 |
7079 | 2587 // We compute the size of rwork and iwork because ZGELSD in |
2588 // older versions of LAPACK does not return them on a query | |
2589 // call. | |
7124 | 2590 double dminmn = static_cast<double> (minmn); |
2591 double dsmlsizp1 = static_cast<double> (smlsiz+1); | |
7079 | 2592 #if defined (HAVE_LOG2) |
7544
f9983d2761df
more xGELSD workspace fixes
Jaroslav Hajek <highegg@gmail.com>
parents:
7532
diff
changeset
|
2593 double tmp = log2 (dminmn / dsmlsizp1); |
7079 | 2594 #else |
7544
f9983d2761df
more xGELSD workspace fixes
Jaroslav Hajek <highegg@gmail.com>
parents:
7532
diff
changeset
|
2595 double tmp = log (dminmn / dsmlsizp1) / log (2.0); |
7079 | 2596 #endif |
7544
f9983d2761df
more xGELSD workspace fixes
Jaroslav Hajek <highegg@gmail.com>
parents:
7532
diff
changeset
|
2597 octave_idx_type nlvl = static_cast<octave_idx_type> (tmp) + 1; |
7079 | 2598 if (nlvl < 0) |
2599 nlvl = 0; | |
2600 | |
2601 octave_idx_type lrwork = minmn*(10 + 2*smlsiz + 8*nlvl) | |
2602 + 3*smlsiz*nrhs + (smlsiz+1)*(smlsiz+1); | |
2603 if (lrwork < 1) | |
2604 lrwork = 1; | |
2605 Array<double> rwork (lrwork); | |
2606 double *prwork = rwork.fortran_vec (); | |
2607 | |
2608 octave_idx_type liwork = 3 * minmn * nlvl + 11 * minmn; | |
2609 if (liwork < 1) | |
2610 liwork = 1; | |
2611 Array<octave_idx_type> iwork (liwork); | |
2612 octave_idx_type* piwork = iwork.fortran_vec (); | |
7072 | 2613 |
2614 F77_XFCN (zgelsd, ZGELSD, (m, n, nrhs, tmp_data, m, pretval, maxmn, | |
7788 | 2615 ps, rcon, rank, work.fortran_vec (), |
7079 | 2616 lwork, prwork, piwork, info)); |
1948 | 2617 |
7476 | 2618 // 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
|
2619 // 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
|
2620 // should provide sufficient workspace for ZGELSD to operate |
7476 | 2621 // efficiently. |
7488
6470f946a425
another small xGELSD workspace fix
John W. Eaton <jwe@octave.org>
parents:
7486
diff
changeset
|
2622 if (n >= mnthr) |
7476 | 2623 { |
2624 octave_idx_type addend = m; | |
2625 | |
2626 if (2*m-4 > addend) | |
2627 addend = 2*m-4; | |
2628 | |
2629 if (nrhs > addend) | |
2630 addend = nrhs; | |
2631 | |
2632 if (n-3*m > addend) | |
2633 addend = n-3*m; | |
2634 | |
2635 const octave_idx_type lworkaround = 4*m + m*m + addend; | |
2636 | |
2637 if (std::real (work(0)) < lworkaround) | |
2638 work(0) = lworkaround; | |
2639 } | |
7532
493bb0de3199
avoid another xGELSD workspace query bug
John W. Eaton <jwe@octave.org>
parents:
7503
diff
changeset
|
2640 else if (m >= n) |
493bb0de3199
avoid another xGELSD workspace query bug
John W. Eaton <jwe@octave.org>
parents:
7503
diff
changeset
|
2641 { |
493bb0de3199
avoid another xGELSD workspace query bug
John W. Eaton <jwe@octave.org>
parents:
7503
diff
changeset
|
2642 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
|
2643 |
493bb0de3199
avoid another xGELSD workspace query bug
John W. Eaton <jwe@octave.org>
parents:
7503
diff
changeset
|
2644 if (std::real (work(0)) < lworkaround) |
493bb0de3199
avoid another xGELSD workspace query bug
John W. Eaton <jwe@octave.org>
parents:
7503
diff
changeset
|
2645 work(0) = lworkaround; |
493bb0de3199
avoid another xGELSD workspace query bug
John W. Eaton <jwe@octave.org>
parents:
7503
diff
changeset
|
2646 } |
7476 | 2647 |
7482
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2648 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
|
2649 work.resize (lwork); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2650 |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2651 F77_XFCN (zgelsd, ZGELSD, (m, n, nrhs, tmp_data, m, pretval, |
7788 | 2652 maxmn, ps, rcon, rank, |
7482
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2653 work.fortran_vec (), lwork, |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2654 prwork, piwork, info)); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2655 |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2656 if (rank < minmn) |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2657 (*current_liboctave_warning_handler) |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2658 ("zgelsd: rank deficient %dx%d matrix, rank = %d, tol = %e", |
7788 | 2659 m, n, rank, rcon); |
7482
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2660 |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2661 if (s.elem (0) == 0.0) |
7788 | 2662 rcon = 0.0; |
1948 | 2663 else |
7788 | 2664 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
|
2665 |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2666 retval.resize (n, nrhs); |
458 | 2667 } |
2668 | |
2669 return retval; | |
2670 } | |
2671 | |
2672 ComplexColumnVector | |
3585 | 2673 ComplexMatrix::lssolve (const ColumnVector& b) const |
2674 { | |
5275 | 2675 octave_idx_type info; |
2676 octave_idx_type rank; | |
7788 | 2677 double rcon; |
2678 return lssolve (ComplexColumnVector (b), info, rank, rcon); | |
3585 | 2679 } |
2680 | |
2681 ComplexColumnVector | |
5275 | 2682 ComplexMatrix::lssolve (const ColumnVector& b, octave_idx_type& info) const |
3585 | 2683 { |
5275 | 2684 octave_idx_type rank; |
7788 | 2685 double rcon; |
2686 return lssolve (ComplexColumnVector (b), info, rank, rcon); | |
3585 | 2687 } |
2688 | |
2689 ComplexColumnVector | |
7076 | 2690 ComplexMatrix::lssolve (const ColumnVector& b, octave_idx_type& info, |
2691 octave_idx_type& rank) const | |
3585 | 2692 { |
7788 | 2693 double rcon; |
2694 return lssolve (ComplexColumnVector (b), info, rank, rcon); | |
7076 | 2695 } |
2696 | |
2697 ComplexColumnVector | |
2698 ComplexMatrix::lssolve (const ColumnVector& b, octave_idx_type& info, | |
7788 | 2699 octave_idx_type& rank, double& rcon) const |
7076 | 2700 { |
7788 | 2701 return lssolve (ComplexColumnVector (b), info, rank, rcon); |
3585 | 2702 } |
2703 | |
2704 ComplexColumnVector | |
458 | 2705 ComplexMatrix::lssolve (const ComplexColumnVector& b) const |
2706 { | |
5275 | 2707 octave_idx_type info; |
2708 octave_idx_type rank; | |
7788 | 2709 double rcon; |
2710 return lssolve (b, info, rank, rcon); | |
458 | 2711 } |
2712 | |
2713 ComplexColumnVector | |
5275 | 2714 ComplexMatrix::lssolve (const ComplexColumnVector& b, octave_idx_type& info) const |
458 | 2715 { |
5275 | 2716 octave_idx_type rank; |
7788 | 2717 double rcon; |
2718 return lssolve (b, info, rank, rcon); | |
458 | 2719 } |
2720 | |
2721 ComplexColumnVector | |
5275 | 2722 ComplexMatrix::lssolve (const ComplexColumnVector& b, octave_idx_type& info, |
2723 octave_idx_type& rank) const | |
458 | 2724 { |
7788 | 2725 double rcon; |
2726 return lssolve (b, info, rank, rcon); | |
7076 | 2727 |
2728 } | |
2729 | |
2730 ComplexColumnVector | |
2731 ComplexMatrix::lssolve (const ComplexColumnVector& b, octave_idx_type& info, | |
7788 | 2732 octave_idx_type& rank, double& rcon) const |
7076 | 2733 { |
1948 | 2734 ComplexColumnVector retval; |
2735 | |
5275 | 2736 octave_idx_type nrhs = 1; |
2737 | |
2738 octave_idx_type m = rows (); | |
2739 octave_idx_type n = cols (); | |
458 | 2740 |
6924 | 2741 if (m != b.length ()) |
1948 | 2742 (*current_liboctave_error_handler) |
6924 | 2743 ("matrix dimension mismatch solution of linear equations"); |
2744 else if (m == 0 || n == 0 || b.cols () == 0) | |
2745 retval = ComplexColumnVector (n, Complex (0.0, 0.0)); | |
1948 | 2746 else |
458 | 2747 { |
7072 | 2748 volatile octave_idx_type minmn = (m < n ? m : n); |
2749 octave_idx_type maxmn = m > n ? m : n; | |
7788 | 2750 rcon = -1.0; |
7072 | 2751 |
2752 if (m != n) | |
2753 { | |
2754 retval = ComplexColumnVector (maxmn); | |
2755 | |
2756 for (octave_idx_type i = 0; i < m; i++) | |
2757 retval.elem (i) = b.elem (i); | |
2758 } | |
2759 else | |
2760 retval = b; | |
2761 | |
1948 | 2762 ComplexMatrix atmp = *this; |
2763 Complex *tmp_data = atmp.fortran_vec (); | |
2764 | |
7072 | 2765 Complex *pretval = retval.fortran_vec (); |
2766 Array<double> s (minmn); | |
7071 | 2767 double *ps = s.fortran_vec (); |
1948 | 2768 |
7072 | 2769 // Ask ZGELSD what the dimension of WORK should be. |
5275 | 2770 octave_idx_type lwork = -1; |
3752 | 2771 |
2772 Array<Complex> work (1); | |
7079 | 2773 |
7544
f9983d2761df
more xGELSD workspace fixes
Jaroslav Hajek <highegg@gmail.com>
parents:
7532
diff
changeset
|
2774 octave_idx_type smlsiz; |
f9983d2761df
more xGELSD workspace fixes
Jaroslav Hajek <highegg@gmail.com>
parents:
7532
diff
changeset
|
2775 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
|
2776 F77_CONST_CHAR_ARG2 (" ", 1), |
f9983d2761df
more xGELSD workspace fixes
Jaroslav Hajek <highegg@gmail.com>
parents:
7532
diff
changeset
|
2777 0, 0, 0, 0, smlsiz |
f9983d2761df
more xGELSD workspace fixes
Jaroslav Hajek <highegg@gmail.com>
parents:
7532
diff
changeset
|
2778 F77_CHAR_ARG_LEN (6) |
f9983d2761df
more xGELSD workspace fixes
Jaroslav Hajek <highegg@gmail.com>
parents:
7532
diff
changeset
|
2779 F77_CHAR_ARG_LEN (1)); |
7079 | 2780 |
2781 // We compute the size of rwork and iwork because ZGELSD in | |
2782 // older versions of LAPACK does not return them on a query | |
2783 // call. | |
7124 | 2784 double dminmn = static_cast<double> (minmn); |
2785 double dsmlsizp1 = static_cast<double> (smlsiz+1); | |
7079 | 2786 #if defined (HAVE_LOG2) |
7544
f9983d2761df
more xGELSD workspace fixes
Jaroslav Hajek <highegg@gmail.com>
parents:
7532
diff
changeset
|
2787 double tmp = log2 (dminmn / dsmlsizp1); |
7079 | 2788 #else |
7544
f9983d2761df
more xGELSD workspace fixes
Jaroslav Hajek <highegg@gmail.com>
parents:
7532
diff
changeset
|
2789 double tmp = log (dminmn / dsmlsizp1) / log (2.0); |
7079 | 2790 #endif |
7544
f9983d2761df
more xGELSD workspace fixes
Jaroslav Hajek <highegg@gmail.com>
parents:
7532
diff
changeset
|
2791 octave_idx_type nlvl = static_cast<octave_idx_type> (tmp) + 1; |
7079 | 2792 if (nlvl < 0) |
2793 nlvl = 0; | |
2794 | |
2795 octave_idx_type lrwork = minmn*(10 + 2*smlsiz + 8*nlvl) | |
2796 + 3*smlsiz*nrhs + (smlsiz+1)*(smlsiz+1); | |
2797 if (lrwork < 1) | |
2798 lrwork = 1; | |
2799 Array<double> rwork (lrwork); | |
2800 double *prwork = rwork.fortran_vec (); | |
2801 | |
2802 octave_idx_type liwork = 3 * minmn * nlvl + 11 * minmn; | |
2803 if (liwork < 1) | |
2804 liwork = 1; | |
2805 Array<octave_idx_type> iwork (liwork); | |
2806 octave_idx_type* piwork = iwork.fortran_vec (); | |
7072 | 2807 |
2808 F77_XFCN (zgelsd, ZGELSD, (m, n, nrhs, tmp_data, m, pretval, maxmn, | |
7788 | 2809 ps, rcon, rank, work.fortran_vec (), |
7079 | 2810 lwork, prwork, piwork, info)); |
1948 | 2811 |
7482
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2812 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
|
2813 work.resize (lwork); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2814 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
|
2815 iwork.resize (iwork(0)); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2816 |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2817 F77_XFCN (zgelsd, ZGELSD, (m, n, nrhs, tmp_data, m, pretval, |
7788 | 2818 maxmn, ps, rcon, rank, |
7482
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2819 work.fortran_vec (), lwork, |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2820 prwork, piwork, info)); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2821 |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2822 if (rank < minmn) |
1948 | 2823 { |
7482
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2824 if (rank < minmn) |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2825 (*current_liboctave_warning_handler) |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2826 ("zgelsd: rank deficient %dx%d matrix, rank = %d, tol = %e", |
7788 | 2827 m, n, rank, rcon); |
7482
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2828 |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2829 if (s.elem (0) == 0.0) |
7788 | 2830 rcon = 0.0; |
7482
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2831 else |
7788 | 2832 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
|
2833 |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2834 retval.resize (n, nrhs); |
1948 | 2835 } |
458 | 2836 } |
2837 | |
2838 return retval; | |
2839 } | |
2840 | |
1819 | 2841 // Constants for matrix exponential calculation. |
2842 | |
2843 static double padec [] = | |
2844 { | |
2845 5.0000000000000000e-1, | |
2846 1.1666666666666667e-1, | |
2847 1.6666666666666667e-2, | |
2848 1.6025641025641026e-3, | |
2849 1.0683760683760684e-4, | |
2850 4.8562548562548563e-6, | |
2851 1.3875013875013875e-7, | |
2852 1.9270852604185938e-9, | |
2853 }; | |
2854 | |
7400 | 2855 static void |
7788 | 2856 solve_singularity_warning (double rcon) |
7400 | 2857 { |
2858 (*current_liboctave_warning_handler) | |
2859 ("singular matrix encountered in expm calculation, rcond = %g", | |
7788 | 2860 rcon); |
7400 | 2861 } |
2862 | |
1819 | 2863 ComplexMatrix |
2864 ComplexMatrix::expm (void) const | |
2865 { | |
2866 ComplexMatrix retval; | |
2867 | |
2868 ComplexMatrix m = *this; | |
2869 | |
5275 | 2870 octave_idx_type nc = columns (); |
1819 | 2871 |
3130 | 2872 // Preconditioning step 1: trace normalization to reduce dynamic |
2873 // range of poles, but avoid making stable eigenvalues unstable. | |
2874 | |
1819 | 2875 // trace shift value |
2876 Complex trshift = 0.0; | |
2877 | |
5275 | 2878 for (octave_idx_type i = 0; i < nc; i++) |
1819 | 2879 trshift += m.elem (i, i); |
2880 | |
2881 trshift /= nc; | |
2882 | |
3130 | 2883 if (trshift.real () < 0.0) |
6958 | 2884 { |
2885 trshift = trshift.imag (); | |
2886 if (trshift.real () > 709.0) | |
2887 trshift = 709.0; | |
2888 } | |
3130 | 2889 |
5275 | 2890 for (octave_idx_type i = 0; i < nc; i++) |
1819 | 2891 m.elem (i, i) -= trshift; |
2892 | |
2893 // Preconditioning step 2: eigenvalue balancing. | |
3331 | 2894 // code follows development in AEPBAL |
2895 | |
2896 Complex *mp = m.fortran_vec (); | |
3467 | 2897 |
5275 | 2898 octave_idx_type info, ilo, ihi,ilos,ihis; |
3468 | 2899 Array<double> dpermute (nc); |
2900 Array<double> dscale (nc); | |
2901 | |
5775 | 2902 // FIXME -- should pass job as a parameter in expm |
3468 | 2903 |
2904 // Permute first | |
2905 char job = 'P'; | |
4552 | 2906 F77_XFCN (zgebal, ZGEBAL, (F77_CONST_CHAR_ARG2 (&job, 1), |
2907 nc, mp, nc, ilo, ihi, | |
2908 dpermute.fortran_vec (), info | |
2909 F77_CHAR_ARG_LEN (1))); | |
3331 | 2910 |
3468 | 2911 // then scale |
2912 job = 'S'; | |
4552 | 2913 F77_XFCN (zgebal, ZGEBAL, (F77_CONST_CHAR_ARG2 (&job, 1), |
2914 nc, mp, nc, ilos, ihis, | |
2915 dscale.fortran_vec (), info | |
2916 F77_CHAR_ARG_LEN (1))); | |
3331 | 2917 |
1819 | 2918 // Preconditioning step 3: scaling. |
2919 | |
2920 ColumnVector work (nc); | |
3130 | 2921 double inf_norm; |
2922 | |
4552 | 2923 F77_XFCN (xzlange, XZLANGE, (F77_CONST_CHAR_ARG2 ("I", 1), |
2924 nc, nc, m.fortran_vec (), nc, | |
2925 work.fortran_vec (), inf_norm | |
2926 F77_CHAR_ARG_LEN (1))); | |
3331 | 2927 |
2800 | 2928 int sqpow = (inf_norm > 0.0 |
2929 ? static_cast<int> (1.0 + log (inf_norm) / log (2.0)) : 0); | |
1819 | 2930 |
2931 // Check whether we need to square at all. | |
2932 | |
2933 if (sqpow < 0) | |
2934 sqpow = 0; | |
2935 | |
2936 if (sqpow > 0) | |
2937 { | |
7400 | 2938 if (sqpow > 1023) |
2939 sqpow = 1023; | |
2940 | |
1819 | 2941 double scale_factor = 1.0; |
5275 | 2942 for (octave_idx_type i = 0; i < sqpow; i++) |
1819 | 2943 scale_factor *= 2.0; |
2944 | |
2945 m = m / scale_factor; | |
2946 } | |
2947 | |
2948 // npp, dpp: pade' approx polynomial matrices. | |
2949 | |
2950 ComplexMatrix npp (nc, nc, 0.0); | |
6958 | 2951 Complex *pnpp = npp.fortran_vec (); |
1819 | 2952 ComplexMatrix dpp = npp; |
6958 | 2953 Complex *pdpp = dpp.fortran_vec (); |
1819 | 2954 |
2955 // Now powers a^8 ... a^1. | |
2956 | |
2957 int minus_one_j = -1; | |
5275 | 2958 for (octave_idx_type j = 7; j >= 0; j--) |
1819 | 2959 { |
6958 | 2960 for (octave_idx_type i = 0; i < nc; i++) |
2961 { | |
2962 octave_idx_type k = i * nc + i; | |
7265 | 2963 pnpp[k] += padec[j]; |
2964 pdpp[k] += minus_one_j * padec[j]; | |
6958 | 2965 } |
7265 | 2966 |
6958 | 2967 npp = m * npp; |
7265 | 2968 pnpp = npp.fortran_vec (); |
2969 | |
6958 | 2970 dpp = m * dpp; |
7265 | 2971 pdpp = dpp.fortran_vec (); |
2972 | |
1819 | 2973 minus_one_j *= -1; |
2974 } | |
2975 | |
2976 // Zero power. | |
2977 | |
2978 dpp = -dpp; | |
5275 | 2979 for (octave_idx_type j = 0; j < nc; j++) |
1819 | 2980 { |
2981 npp.elem (j, j) += 1.0; | |
2982 dpp.elem (j, j) += 1.0; | |
2983 } | |
2984 | |
2985 // Compute pade approximation = inverse (dpp) * npp. | |
2986 | |
7788 | 2987 double rcon; |
2988 retval = dpp.solve (npp, info, rcon, solve_singularity_warning); | |
7400 | 2989 |
2990 if (info < 0) | |
2991 return retval; | |
2992 | |
1819 | 2993 // Reverse preconditioning step 3: repeated squaring. |
2994 | |
2995 while (sqpow) | |
2996 { | |
2997 retval = retval * retval; | |
2998 sqpow--; | |
2999 } | |
3000 | |
3001 // Reverse preconditioning step 2: inverse balancing. | |
3467 | 3002 // Done in two steps: inverse scaling, then inverse permutation |
3003 | |
3004 // inverse scaling (diagonal transformation) | |
5275 | 3005 for (octave_idx_type i = 0; i < nc; i++) |
3006 for (octave_idx_type j = 0; j < nc; j++) | |
3468 | 3007 retval(i,j) *= dscale(i) / dscale(j); |
3467 | 3008 |
4153 | 3009 OCTAVE_QUIT; |
3010 | |
3467 | 3011 // construct balancing permutation vector |
6867 | 3012 Array<octave_idx_type> iperm (nc); |
5275 | 3013 for (octave_idx_type i = 0; i < nc; i++) |
4593 | 3014 iperm(i) = i; // initialize to identity permutation |
3467 | 3015 |
3016 // leading permutations in forward order | |
5275 | 3017 for (octave_idx_type i = 0; i < (ilo-1); i++) |
3468 | 3018 { |
6867 | 3019 octave_idx_type swapidx = static_cast<octave_idx_type> (dpermute(i)) - 1; |
5275 | 3020 octave_idx_type tmp = iperm(i); |
4593 | 3021 iperm(i) = iperm(swapidx); |
3022 iperm(swapidx) = tmp; | |
3468 | 3023 } |
3467 | 3024 |
7416 | 3025 // construct inverse balancing permutation vector |
3026 Array<octave_idx_type> invpvec (nc); | |
3027 for (octave_idx_type i = 0; i < nc; i++) | |
3028 invpvec(iperm(i)) = i; // Thanks to R. A. Lippert for this method | |
3029 | |
3030 OCTAVE_QUIT; | |
3031 | |
3032 ComplexMatrix tmpMat = retval; | |
3033 for (octave_idx_type i = 0; i < nc; i++) | |
3034 for (octave_idx_type j = 0; j < nc; j++) | |
3035 retval(i,j) = tmpMat(invpvec(i),invpvec(j)); | |
3036 | |
3037 OCTAVE_QUIT; | |
3038 | |
3039 for (octave_idx_type i = 0; i < nc; i++) | |
3040 iperm(i) = i; // initialize to identity permutation | |
3041 | |
3467 | 3042 // trailing permutations must be done in reverse order |
5275 | 3043 for (octave_idx_type i = nc - 1; i >= ihi; i--) |
3468 | 3044 { |
6867 | 3045 octave_idx_type swapidx = static_cast<octave_idx_type> (dpermute(i)) - 1; |
5275 | 3046 octave_idx_type tmp = iperm(i); |
4593 | 3047 iperm(i) = iperm(swapidx); |
3048 iperm(swapidx) = tmp; | |
3468 | 3049 } |
3467 | 3050 |
3051 // construct inverse balancing permutation vector | |
5275 | 3052 for (octave_idx_type i = 0; i < nc; i++) |
4593 | 3053 invpvec(iperm(i)) = i; // Thanks to R. A. Lippert for this method |
3467 | 3054 |
4153 | 3055 OCTAVE_QUIT; |
3056 | |
7416 | 3057 tmpMat = retval; |
5275 | 3058 for (octave_idx_type i = 0; i < nc; i++) |
3059 for (octave_idx_type j = 0; j < nc; j++) | |
3468 | 3060 retval(i,j) = tmpMat(invpvec(i),invpvec(j)); |
1819 | 3061 |
3062 // Reverse preconditioning step 1: fix trace normalization. | |
3063 | |
3130 | 3064 return exp (trshift) * retval; |
1819 | 3065 } |
3066 | |
1205 | 3067 // column vector by row vector -> matrix operations |
3068 | |
3069 ComplexMatrix | |
3070 operator * (const ColumnVector& v, const ComplexRowVector& a) | |
3071 { | |
3072 ComplexColumnVector tmp (v); | |
3073 return tmp * a; | |
3074 } | |
3075 | |
3076 ComplexMatrix | |
3077 operator * (const ComplexColumnVector& a, const RowVector& b) | |
3078 { | |
3079 ComplexRowVector tmp (b); | |
3080 return a * tmp; | |
3081 } | |
3082 | |
3083 ComplexMatrix | |
3084 operator * (const ComplexColumnVector& v, const ComplexRowVector& a) | |
3085 { | |
1948 | 3086 ComplexMatrix retval; |
3087 | |
5275 | 3088 octave_idx_type len = v.length (); |
3233 | 3089 |
3090 if (len != 0) | |
1205 | 3091 { |
5275 | 3092 octave_idx_type a_len = a.length (); |
3233 | 3093 |
3094 retval.resize (len, a_len); | |
3095 Complex *c = retval.fortran_vec (); | |
3096 | |
4552 | 3097 F77_XFCN (zgemm, ZGEMM, (F77_CONST_CHAR_ARG2 ("N", 1), |
3098 F77_CONST_CHAR_ARG2 ("N", 1), | |
3099 len, a_len, 1, 1.0, v.data (), len, | |
3100 a.data (), 1, 0.0, c, len | |
3101 F77_CHAR_ARG_LEN (1) | |
3102 F77_CHAR_ARG_LEN (1))); | |
1205 | 3103 } |
3104 | |
1948 | 3105 return retval; |
1205 | 3106 } |
3107 | |
458 | 3108 // matrix by diagonal matrix -> matrix operations |
3109 | |
3110 ComplexMatrix& | |
3111 ComplexMatrix::operator += (const DiagMatrix& a) | |
3112 { | |
5275 | 3113 octave_idx_type nr = rows (); |
3114 octave_idx_type nc = cols (); | |
3115 | |
3116 octave_idx_type a_nr = rows (); | |
3117 octave_idx_type a_nc = cols (); | |
2384 | 3118 |
3119 if (nr != a_nr || nc != a_nc) | |
458 | 3120 { |
2384 | 3121 gripe_nonconformant ("operator +=", nr, nc, a_nr, a_nc); |
889 | 3122 return *this; |
458 | 3123 } |
3124 | |
5275 | 3125 for (octave_idx_type i = 0; i < a.length (); i++) |
458 | 3126 elem (i, i) += a.elem (i, i); |
3127 | |
3128 return *this; | |
3129 } | |
3130 | |
3131 ComplexMatrix& | |
3132 ComplexMatrix::operator -= (const DiagMatrix& a) | |
3133 { | |
5275 | 3134 octave_idx_type nr = rows (); |
3135 octave_idx_type nc = cols (); | |
3136 | |
3137 octave_idx_type a_nr = rows (); | |
3138 octave_idx_type a_nc = cols (); | |
2384 | 3139 |
3140 if (nr != a_nr || nc != a_nc) | |
458 | 3141 { |
2384 | 3142 gripe_nonconformant ("operator -=", nr, nc, a_nr, a_nc); |
889 | 3143 return *this; |
458 | 3144 } |
3145 | |
5275 | 3146 for (octave_idx_type i = 0; i < a.length (); i++) |
458 | 3147 elem (i, i) -= a.elem (i, i); |
3148 | |
3149 return *this; | |
3150 } | |
3151 | |
3152 ComplexMatrix& | |
3153 ComplexMatrix::operator += (const ComplexDiagMatrix& a) | |
3154 { | |
5275 | 3155 octave_idx_type nr = rows (); |
3156 octave_idx_type nc = cols (); | |
3157 | |
3158 octave_idx_type a_nr = rows (); | |
3159 octave_idx_type a_nc = cols (); | |
2384 | 3160 |
3161 if (nr != a_nr || nc != a_nc) | |
458 | 3162 { |
2384 | 3163 gripe_nonconformant ("operator +=", nr, nc, a_nr, a_nc); |
889 | 3164 return *this; |
458 | 3165 } |
3166 | |
5275 | 3167 for (octave_idx_type i = 0; i < a.length (); i++) |
458 | 3168 elem (i, i) += a.elem (i, i); |
3169 | |
3170 return *this; | |
3171 } | |
3172 | |
3173 ComplexMatrix& | |
3174 ComplexMatrix::operator -= (const ComplexDiagMatrix& a) | |
3175 { | |
5275 | 3176 octave_idx_type nr = rows (); |
3177 octave_idx_type nc = cols (); | |
3178 | |
3179 octave_idx_type a_nr = rows (); | |
3180 octave_idx_type a_nc = cols (); | |
2384 | 3181 |
3182 if (nr != a_nr || nc != a_nc) | |
458 | 3183 { |
2384 | 3184 gripe_nonconformant ("operator -=", nr, nc, a_nr, a_nc); |
889 | 3185 return *this; |
458 | 3186 } |
3187 | |
5275 | 3188 for (octave_idx_type i = 0; i < a.length (); i++) |
458 | 3189 elem (i, i) -= a.elem (i, i); |
3190 | |
3191 return *this; | |
3192 } | |
3193 | |
3194 // matrix by matrix -> matrix operations | |
3195 | |
3196 ComplexMatrix& | |
3197 ComplexMatrix::operator += (const Matrix& a) | |
3198 { | |
5275 | 3199 octave_idx_type nr = rows (); |
3200 octave_idx_type nc = cols (); | |
3201 | |
3202 octave_idx_type a_nr = a.rows (); | |
3203 octave_idx_type a_nc = a.cols (); | |
2384 | 3204 |
3205 if (nr != a_nr || nc != a_nc) | |
458 | 3206 { |
2384 | 3207 gripe_nonconformant ("operator +=", nr, nc, a_nr, a_nc); |
458 | 3208 return *this; |
3209 } | |
3210 | |
3211 if (nr == 0 || nc == 0) | |
3212 return *this; | |
3213 | |
3214 Complex *d = fortran_vec (); // Ensures only one reference to my privates! | |
3215 | |
3769 | 3216 mx_inline_add2 (d, a.data (), length ()); |
458 | 3217 return *this; |
3218 } | |
3219 | |
3220 ComplexMatrix& | |
3221 ComplexMatrix::operator -= (const Matrix& a) | |
3222 { | |
5275 | 3223 octave_idx_type nr = rows (); |
3224 octave_idx_type nc = cols (); | |
3225 | |
3226 octave_idx_type a_nr = a.rows (); | |
3227 octave_idx_type a_nc = a.cols (); | |
2384 | 3228 |
3229 if (nr != a_nr || nc != a_nc) | |
458 | 3230 { |
2384 | 3231 gripe_nonconformant ("operator -=", nr, nc, a_nr, a_nc); |
458 | 3232 return *this; |
3233 } | |
3234 | |
3235 if (nr == 0 || nc == 0) | |
3236 return *this; | |
3237 | |
3238 Complex *d = fortran_vec (); // Ensures only one reference to my privates! | |
3239 | |
3769 | 3240 mx_inline_subtract2 (d, a.data (), length ()); |
458 | 3241 return *this; |
3242 } | |
3243 | |
3244 // unary operations | |
3245 | |
2964 | 3246 boolMatrix |
458 | 3247 ComplexMatrix::operator ! (void) const |
3248 { | |
5275 | 3249 octave_idx_type nr = rows (); |
3250 octave_idx_type nc = cols (); | |
2964 | 3251 |
3252 boolMatrix b (nr, nc); | |
3253 | |
5275 | 3254 for (octave_idx_type j = 0; j < nc; j++) |
3255 for (octave_idx_type i = 0; i < nr; i++) | |
5139 | 3256 b.elem (i, j) = elem (i, j) == 0.0; |
2964 | 3257 |
3258 return b; | |
458 | 3259 } |
3260 | |
3261 // other operations | |
3262 | |
2676 | 3263 Matrix |
7503
8c32f95c2639
convert mapper functions to new format
David Bateman <dbateman@free.fr>
parents:
7488
diff
changeset
|
3264 ComplexMatrix::map (dmapper fcn) const |
458 | 3265 { |
7503
8c32f95c2639
convert mapper functions to new format
David Bateman <dbateman@free.fr>
parents:
7488
diff
changeset
|
3266 return MArray2<Complex>::map<double> (func_ptr (fcn)); |
8c32f95c2639
convert mapper functions to new format
David Bateman <dbateman@free.fr>
parents:
7488
diff
changeset
|
3267 } |
8c32f95c2639
convert mapper functions to new format
David Bateman <dbateman@free.fr>
parents:
7488
diff
changeset
|
3268 |
8c32f95c2639
convert mapper functions to new format
David Bateman <dbateman@free.fr>
parents:
7488
diff
changeset
|
3269 ComplexMatrix |
8c32f95c2639
convert mapper functions to new format
David Bateman <dbateman@free.fr>
parents:
7488
diff
changeset
|
3270 ComplexMatrix::map (cmapper fcn) const |
8c32f95c2639
convert mapper functions to new format
David Bateman <dbateman@free.fr>
parents:
7488
diff
changeset
|
3271 { |
8c32f95c2639
convert mapper functions to new format
David Bateman <dbateman@free.fr>
parents:
7488
diff
changeset
|
3272 return MArray2<Complex>::map<Complex> (func_ptr (fcn)); |
3248 | 3273 } |
3274 | |
3275 boolMatrix | |
7503
8c32f95c2639
convert mapper functions to new format
David Bateman <dbateman@free.fr>
parents:
7488
diff
changeset
|
3276 ComplexMatrix::map (bmapper fcn) const |
3248 | 3277 { |
7503
8c32f95c2639
convert mapper functions to new format
David Bateman <dbateman@free.fr>
parents:
7488
diff
changeset
|
3278 return MArray2<Complex>::map<bool> (func_ptr (fcn)); |
458 | 3279 } |
3280 | |
2384 | 3281 bool |
3282 ComplexMatrix::any_element_is_inf_or_nan (void) const | |
3283 { | |
5275 | 3284 octave_idx_type nr = rows (); |
3285 octave_idx_type nc = cols (); | |
3286 | |
3287 for (octave_idx_type j = 0; j < nc; j++) | |
3288 for (octave_idx_type i = 0; i < nr; i++) | |
2384 | 3289 { |
3290 Complex val = elem (i, j); | |
3291 if (xisinf (val) || xisnan (val)) | |
3292 return true; | |
3293 } | |
3294 | |
3295 return false; | |
3296 } | |
3297 | |
2408 | 3298 // Return true if no elements have imaginary components. |
3299 | |
3300 bool | |
3301 ComplexMatrix::all_elements_are_real (void) const | |
3302 { | |
5275 | 3303 octave_idx_type nr = rows (); |
3304 octave_idx_type nc = cols (); | |
3305 | |
3306 for (octave_idx_type j = 0; j < nc; j++) | |
4349 | 3307 { |
5275 | 3308 for (octave_idx_type i = 0; i < nr; i++) |
4349 | 3309 { |
5315 | 3310 double ip = std::imag (elem (i, j)); |
4349 | 3311 |
3312 if (ip != 0.0 || lo_ieee_signbit (ip)) | |
3313 return false; | |
3314 } | |
3315 } | |
2408 | 3316 |
3317 return true; | |
3318 } | |
3319 | |
1968 | 3320 // Return nonzero if any element of CM has a non-integer real or |
3321 // imaginary part. Also extract the largest and smallest (real or | |
3322 // imaginary) values and return them in MAX_VAL and MIN_VAL. | |
3323 | |
2384 | 3324 bool |
1968 | 3325 ComplexMatrix::all_integers (double& max_val, double& min_val) const |
3326 { | |
5275 | 3327 octave_idx_type nr = rows (); |
3328 octave_idx_type nc = cols (); | |
1968 | 3329 |
3330 if (nr > 0 && nc > 0) | |
3331 { | |
3332 Complex val = elem (0, 0); | |
3333 | |
5315 | 3334 double r_val = std::real (val); |
3335 double i_val = std::imag (val); | |
1968 | 3336 |
3337 max_val = r_val; | |
3338 min_val = r_val; | |
3339 | |
3340 if (i_val > max_val) | |
3341 max_val = i_val; | |
3342 | |
3343 if (i_val < max_val) | |
3344 min_val = i_val; | |
3345 } | |
3346 else | |
2384 | 3347 return false; |
1968 | 3348 |
5275 | 3349 for (octave_idx_type j = 0; j < nc; j++) |
3350 for (octave_idx_type i = 0; i < nr; i++) | |
1968 | 3351 { |
3352 Complex val = elem (i, j); | |
3353 | |
5315 | 3354 double r_val = std::real (val); |
3355 double i_val = std::imag (val); | |
1968 | 3356 |
3357 if (r_val > max_val) | |
3358 max_val = r_val; | |
3359 | |
3360 if (i_val > max_val) | |
3361 max_val = i_val; | |
3362 | |
3363 if (r_val < min_val) | |
3364 min_val = r_val; | |
3365 | |
3366 if (i_val < min_val) | |
3367 min_val = i_val; | |
3368 | |
3369 if (D_NINT (r_val) != r_val || D_NINT (i_val) != i_val) | |
2384 | 3370 return false; |
1968 | 3371 } |
2384 | 3372 |
3373 return true; | |
1968 | 3374 } |
3375 | |
2384 | 3376 bool |
1968 | 3377 ComplexMatrix::too_large_for_float (void) const |
3378 { | |
5275 | 3379 octave_idx_type nr = rows (); |
3380 octave_idx_type nc = cols (); | |
3381 | |
3382 for (octave_idx_type j = 0; j < nc; j++) | |
3383 for (octave_idx_type i = 0; i < nr; i++) | |
1968 | 3384 { |
3385 Complex val = elem (i, j); | |
3386 | |
5315 | 3387 double r_val = std::real (val); |
3388 double i_val = std::imag (val); | |
1968 | 3389 |
5389 | 3390 if ((! (xisnan (r_val) || xisinf (r_val)) |
5387 | 3391 && fabs (r_val) > FLT_MAX) |
5389 | 3392 || (! (xisnan (i_val) || xisinf (i_val)) |
5387 | 3393 && fabs (i_val) > FLT_MAX)) |
2384 | 3394 return true; |
1968 | 3395 } |
3396 | |
2384 | 3397 return false; |
1968 | 3398 } |
3399 | |
5775 | 3400 // FIXME Do these really belong here? Maybe they should be |
4015 | 3401 // in a base class? |
3402 | |
2832 | 3403 boolMatrix |
4015 | 3404 ComplexMatrix::all (int dim) const |
458 | 3405 { |
4015 | 3406 MX_ALL_OP (dim); |
458 | 3407 } |
3408 | |
2832 | 3409 boolMatrix |
4015 | 3410 ComplexMatrix::any (int dim) const |
458 | 3411 { |
4015 | 3412 MX_ANY_OP (dim); |
458 | 3413 } |
3414 | |
3415 ComplexMatrix | |
3723 | 3416 ComplexMatrix::cumprod (int dim) const |
458 | 3417 { |
4015 | 3418 MX_CUMULATIVE_OP (ComplexMatrix, Complex, *=); |
458 | 3419 } |
3420 | |
3421 ComplexMatrix | |
3723 | 3422 ComplexMatrix::cumsum (int dim) const |
458 | 3423 { |
4015 | 3424 MX_CUMULATIVE_OP (ComplexMatrix, Complex, +=); |
458 | 3425 } |
3426 | |
3427 ComplexMatrix | |
3723 | 3428 ComplexMatrix::prod (int dim) const |
458 | 3429 { |
3864 | 3430 MX_REDUCTION_OP (ComplexMatrix, *=, 1.0, 1.0); |
458 | 3431 } |
3432 | |
3433 ComplexMatrix | |
3723 | 3434 ComplexMatrix::sum (int dim) const |
458 | 3435 { |
3864 | 3436 MX_REDUCTION_OP (ComplexMatrix, +=, 0.0, 0.0); |
458 | 3437 } |
3438 | |
3439 ComplexMatrix | |
3723 | 3440 ComplexMatrix::sumsq (int dim) const |
458 | 3441 { |
3864 | 3442 #define ROW_EXPR \ |
3443 Complex d = elem (i, j); \ | |
3444 retval.elem (i, 0) += d * conj (d) | |
3445 | |
3446 #define COL_EXPR \ | |
3447 Complex d = elem (i, j); \ | |
3448 retval.elem (0, j) += d * conj (d) | |
3449 | |
3450 MX_BASE_REDUCTION_OP (ComplexMatrix, ROW_EXPR, COL_EXPR, 0.0, 0.0); | |
3451 | |
3452 #undef ROW_EXPR | |
3453 #undef COL_EXPR | |
458 | 3454 } |
3455 | |
4329 | 3456 Matrix ComplexMatrix::abs (void) const |
3457 { | |
5275 | 3458 octave_idx_type nr = rows (); |
3459 octave_idx_type nc = cols (); | |
4329 | 3460 |
3461 Matrix retval (nr, nc); | |
3462 | |
5275 | 3463 for (octave_idx_type j = 0; j < nc; j++) |
3464 for (octave_idx_type i = 0; i < nr; i++) | |
5315 | 3465 retval (i, j) = std::abs (elem (i, j)); |
4329 | 3466 |
3467 return retval; | |
3468 } | |
3469 | |
7620
36594d5bbe13
Move diag function into the octave_value class
David Bateman <dbateman@free.fr>
parents:
7544
diff
changeset
|
3470 ComplexMatrix |
5275 | 3471 ComplexMatrix::diag (octave_idx_type k) const |
458 | 3472 { |
7620
36594d5bbe13
Move diag function into the octave_value class
David Bateman <dbateman@free.fr>
parents:
7544
diff
changeset
|
3473 return MArray2<Complex>::diag (k); |
458 | 3474 } |
3475 | |
2354 | 3476 bool |
5275 | 3477 ComplexMatrix::row_is_real_only (octave_idx_type i) const |
2354 | 3478 { |
3479 bool retval = true; | |
3480 | |
5275 | 3481 octave_idx_type nc = columns (); |
3482 | |
3483 for (octave_idx_type j = 0; j < nc; j++) | |
2354 | 3484 { |
5315 | 3485 if (std::imag (elem (i, j)) != 0.0) |
2354 | 3486 { |
3487 retval = false; | |
3488 break; | |
3489 } | |
3490 } | |
3491 | |
3492 return retval; | |
3493 } | |
3494 | |
3495 bool | |
5275 | 3496 ComplexMatrix::column_is_real_only (octave_idx_type j) const |
2354 | 3497 { |
3498 bool retval = true; | |
3499 | |
5275 | 3500 octave_idx_type nr = rows (); |
3501 | |
3502 for (octave_idx_type i = 0; i < nr; i++) | |
2354 | 3503 { |
5315 | 3504 if (std::imag (elem (i, j)) != 0.0) |
2354 | 3505 { |
3506 retval = false; | |
3507 break; | |
3508 } | |
3509 } | |
3510 | |
3511 return retval; | |
3512 } | |
891 | 3513 |
458 | 3514 ComplexColumnVector |
3515 ComplexMatrix::row_min (void) const | |
3516 { | |
5275 | 3517 Array<octave_idx_type> dummy_idx; |
4587 | 3518 return row_min (dummy_idx); |
458 | 3519 } |
3520 | |
3521 ComplexColumnVector | |
5275 | 3522 ComplexMatrix::row_min (Array<octave_idx_type>& idx_arg) const |
458 | 3523 { |
3524 ComplexColumnVector result; | |
3525 | |
5275 | 3526 octave_idx_type nr = rows (); |
3527 octave_idx_type nc = cols (); | |
458 | 3528 |
3529 if (nr > 0 && nc > 0) | |
3530 { | |
3531 result.resize (nr); | |
4587 | 3532 idx_arg.resize (nr); |
458 | 3533 |
5275 | 3534 for (octave_idx_type i = 0; i < nr; i++) |
458 | 3535 { |
2354 | 3536 bool real_only = row_is_real_only (i); |
3537 | |
5275 | 3538 octave_idx_type idx_j; |
4469 | 3539 |
3540 Complex tmp_min; | |
3541 | |
3542 double abs_min = octave_NaN; | |
3543 | |
3544 for (idx_j = 0; idx_j < nc; idx_j++) | |
3545 { | |
3546 tmp_min = elem (i, idx_j); | |
3547 | |
5389 | 3548 if (! xisnan (tmp_min)) |
4469 | 3549 { |
5315 | 3550 abs_min = real_only ? std::real (tmp_min) : std::abs (tmp_min); |
4469 | 3551 break; |
3552 } | |
3553 } | |
3554 | |
5275 | 3555 for (octave_idx_type j = idx_j+1; j < nc; j++) |
4469 | 3556 { |
3557 Complex tmp = elem (i, j); | |
3558 | |
5389 | 3559 if (xisnan (tmp)) |
4469 | 3560 continue; |
3561 | |
5315 | 3562 double abs_tmp = real_only ? std::real (tmp) : std::abs (tmp); |
4469 | 3563 |
3564 if (abs_tmp < abs_min) | |
3565 { | |
3566 idx_j = j; | |
3567 tmp_min = tmp; | |
3568 abs_min = abs_tmp; | |
3569 } | |
3570 } | |
3571 | |
5389 | 3572 if (xisnan (tmp_min)) |
4469 | 3573 { |
3574 result.elem (i) = Complex_NaN_result; | |
4587 | 3575 idx_arg.elem (i) = 0; |
4469 | 3576 } |
891 | 3577 else |
3578 { | |
4469 | 3579 result.elem (i) = tmp_min; |
4587 | 3580 idx_arg.elem (i) = idx_j; |
891 | 3581 } |
458 | 3582 } |
3583 } | |
3584 | |
3585 return result; | |
3586 } | |
3587 | |
3588 ComplexColumnVector | |
3589 ComplexMatrix::row_max (void) const | |
3590 { | |
5275 | 3591 Array<octave_idx_type> dummy_idx; |
4587 | 3592 return row_max (dummy_idx); |
458 | 3593 } |
3594 | |
3595 ComplexColumnVector | |
5275 | 3596 ComplexMatrix::row_max (Array<octave_idx_type>& idx_arg) const |
458 | 3597 { |
3598 ComplexColumnVector result; | |
3599 | |
5275 | 3600 octave_idx_type nr = rows (); |
3601 octave_idx_type nc = cols (); | |
458 | 3602 |
3603 if (nr > 0 && nc > 0) | |
3604 { | |
3605 result.resize (nr); | |
4587 | 3606 idx_arg.resize (nr); |
458 | 3607 |
5275 | 3608 for (octave_idx_type i = 0; i < nr; i++) |
458 | 3609 { |
2354 | 3610 bool real_only = row_is_real_only (i); |
3611 | |
5275 | 3612 octave_idx_type idx_j; |
4469 | 3613 |
3614 Complex tmp_max; | |
3615 | |
3616 double abs_max = octave_NaN; | |
3617 | |
3618 for (idx_j = 0; idx_j < nc; idx_j++) | |
3619 { | |
3620 tmp_max = elem (i, idx_j); | |
3621 | |
5389 | 3622 if (! xisnan (tmp_max)) |
4469 | 3623 { |
5315 | 3624 abs_max = real_only ? std::real (tmp_max) : std::abs (tmp_max); |
4469 | 3625 break; |
3626 } | |
3627 } | |
3628 | |
5275 | 3629 for (octave_idx_type j = idx_j+1; j < nc; j++) |
4469 | 3630 { |
3631 Complex tmp = elem (i, j); | |
3632 | |
5389 | 3633 if (xisnan (tmp)) |
4469 | 3634 continue; |
3635 | |
5315 | 3636 double abs_tmp = real_only ? std::real (tmp) : std::abs (tmp); |
4469 | 3637 |
3638 if (abs_tmp > abs_max) | |
3639 { | |
3640 idx_j = j; | |
3641 tmp_max = tmp; | |
3642 abs_max = abs_tmp; | |
3643 } | |
3644 } | |
3645 | |
5389 | 3646 if (xisnan (tmp_max)) |
4469 | 3647 { |
3648 result.elem (i) = Complex_NaN_result; | |
4587 | 3649 idx_arg.elem (i) = 0; |
4469 | 3650 } |
891 | 3651 else |
3652 { | |
4469 | 3653 result.elem (i) = tmp_max; |
4587 | 3654 idx_arg.elem (i) = idx_j; |
891 | 3655 } |
458 | 3656 } |
3657 } | |
3658 | |
3659 return result; | |
3660 } | |
3661 | |
3662 ComplexRowVector | |
3663 ComplexMatrix::column_min (void) const | |
3664 { | |
5275 | 3665 Array<octave_idx_type> dummy_idx; |
4587 | 3666 return column_min (dummy_idx); |
458 | 3667 } |
3668 | |
3669 ComplexRowVector | |
5275 | 3670 ComplexMatrix::column_min (Array<octave_idx_type>& idx_arg) const |
458 | 3671 { |
3672 ComplexRowVector result; | |
3673 | |
5275 | 3674 octave_idx_type nr = rows (); |
3675 octave_idx_type nc = cols (); | |
458 | 3676 |
3677 if (nr > 0 && nc > 0) | |
3678 { | |
3679 result.resize (nc); | |
4587 | 3680 idx_arg.resize (nc); |
458 | 3681 |
5275 | 3682 for (octave_idx_type j = 0; j < nc; j++) |
458 | 3683 { |
2354 | 3684 bool real_only = column_is_real_only (j); |
3685 | |
5275 | 3686 octave_idx_type idx_i; |
4469 | 3687 |
3688 Complex tmp_min; | |
3689 | |
3690 double abs_min = octave_NaN; | |
3691 | |
3692 for (idx_i = 0; idx_i < nr; idx_i++) | |
3693 { | |
3694 tmp_min = elem (idx_i, j); | |
3695 | |
5389 | 3696 if (! xisnan (tmp_min)) |
4469 | 3697 { |
5315 | 3698 abs_min = real_only ? std::real (tmp_min) : std::abs (tmp_min); |
4469 | 3699 break; |
3700 } | |
3701 } | |
3702 | |
5275 | 3703 for (octave_idx_type i = idx_i+1; i < nr; i++) |
4469 | 3704 { |
3705 Complex tmp = elem (i, j); | |
3706 | |
5389 | 3707 if (xisnan (tmp)) |
4469 | 3708 continue; |
3709 | |
5315 | 3710 double abs_tmp = real_only ? std::real (tmp) : std::abs (tmp); |
4469 | 3711 |
3712 if (abs_tmp < abs_min) | |
3713 { | |
3714 idx_i = i; | |
3715 tmp_min = tmp; | |
3716 abs_min = abs_tmp; | |
3717 } | |
3718 } | |
3719 | |
5389 | 3720 if (xisnan (tmp_min)) |
4469 | 3721 { |
3722 result.elem (j) = Complex_NaN_result; | |
4587 | 3723 idx_arg.elem (j) = 0; |
4469 | 3724 } |
891 | 3725 else |
3726 { | |
4469 | 3727 result.elem (j) = tmp_min; |
4587 | 3728 idx_arg.elem (j) = idx_i; |
891 | 3729 } |
458 | 3730 } |
3731 } | |
3732 | |
3733 return result; | |
3734 } | |
3735 | |
3736 ComplexRowVector | |
3737 ComplexMatrix::column_max (void) const | |
3738 { | |
5275 | 3739 Array<octave_idx_type> dummy_idx; |
4587 | 3740 return column_max (dummy_idx); |
458 | 3741 } |
3742 | |
3743 ComplexRowVector | |
5275 | 3744 ComplexMatrix::column_max (Array<octave_idx_type>& idx_arg) const |
458 | 3745 { |
3746 ComplexRowVector result; | |
3747 | |
5275 | 3748 octave_idx_type nr = rows (); |
3749 octave_idx_type nc = cols (); | |
458 | 3750 |
3751 if (nr > 0 && nc > 0) | |
3752 { | |
3753 result.resize (nc); | |
4587 | 3754 idx_arg.resize (nc); |
458 | 3755 |
5275 | 3756 for (octave_idx_type j = 0; j < nc; j++) |
458 | 3757 { |
2354 | 3758 bool real_only = column_is_real_only (j); |
3759 | |
5275 | 3760 octave_idx_type idx_i; |
4469 | 3761 |
3762 Complex tmp_max; | |
3763 | |
3764 double abs_max = octave_NaN; | |
3765 | |
3766 for (idx_i = 0; idx_i < nr; idx_i++) | |
3767 { | |
3768 tmp_max = elem (idx_i, j); | |
3769 | |
5389 | 3770 if (! xisnan (tmp_max)) |
4469 | 3771 { |
5315 | 3772 abs_max = real_only ? std::real (tmp_max) : std::abs (tmp_max); |
4469 | 3773 break; |
3774 } | |
3775 } | |
3776 | |
5275 | 3777 for (octave_idx_type i = idx_i+1; i < nr; i++) |
4469 | 3778 { |
3779 Complex tmp = elem (i, j); | |
3780 | |
5389 | 3781 if (xisnan (tmp)) |
4469 | 3782 continue; |
3783 | |
5315 | 3784 double abs_tmp = real_only ? std::real (tmp) : std::abs (tmp); |
4469 | 3785 |
3786 if (abs_tmp > abs_max) | |
3787 { | |
3788 idx_i = i; | |
3789 tmp_max = tmp; | |
3790 abs_max = abs_tmp; | |
3791 } | |
3792 } | |
3793 | |
5389 | 3794 if (xisnan (tmp_max)) |
4469 | 3795 { |
3796 result.elem (j) = Complex_NaN_result; | |
4587 | 3797 idx_arg.elem (j) = 0; |
4469 | 3798 } |
891 | 3799 else |
3800 { | |
4469 | 3801 result.elem (j) = tmp_max; |
4587 | 3802 idx_arg.elem (j) = idx_i; |
891 | 3803 } |
458 | 3804 } |
3805 } | |
3806 | |
3807 return result; | |
3808 } | |
3809 | |
3810 // i/o | |
3811 | |
3504 | 3812 std::ostream& |
3813 operator << (std::ostream& os, const ComplexMatrix& a) | |
458 | 3814 { |
5275 | 3815 for (octave_idx_type i = 0; i < a.rows (); i++) |
458 | 3816 { |
5275 | 3817 for (octave_idx_type j = 0; j < a.cols (); j++) |
4130 | 3818 { |
3819 os << " "; | |
3820 octave_write_complex (os, a.elem (i, j)); | |
3821 } | |
458 | 3822 os << "\n"; |
3823 } | |
3824 return os; | |
3825 } | |
3826 | |
3504 | 3827 std::istream& |
3828 operator >> (std::istream& is, ComplexMatrix& a) | |
458 | 3829 { |
5275 | 3830 octave_idx_type nr = a.rows (); |
3831 octave_idx_type nc = a.cols (); | |
458 | 3832 |
3833 if (nr < 1 || nc < 1) | |
3504 | 3834 is.clear (std::ios::badbit); |
458 | 3835 else |
3836 { | |
3837 Complex tmp; | |
5275 | 3838 for (octave_idx_type i = 0; i < nr; i++) |
3839 for (octave_idx_type j = 0; j < nc; j++) | |
458 | 3840 { |
4130 | 3841 tmp = octave_read_complex (is); |
458 | 3842 if (is) |
3843 a.elem (i, j) = tmp; | |
3844 else | |
2993 | 3845 goto done; |
458 | 3846 } |
3847 } | |
3848 | |
2993 | 3849 done: |
3850 | |
458 | 3851 return is; |
3852 } | |
3853 | |
1819 | 3854 ComplexMatrix |
3855 Givens (const Complex& x, const Complex& y) | |
3856 { | |
3857 double cc; | |
3858 Complex cs, temp_r; | |
3859 | |
3887 | 3860 F77_FUNC (zlartg, ZLARTG) (x, y, cc, cs, temp_r); |
1819 | 3861 |
3862 ComplexMatrix g (2, 2); | |
3863 | |
3864 g.elem (0, 0) = cc; | |
3865 g.elem (1, 1) = cc; | |
3866 g.elem (0, 1) = cs; | |
3867 g.elem (1, 0) = -conj (cs); | |
3868 | |
3869 return g; | |
3870 } | |
3871 | |
3872 ComplexMatrix | |
3873 Sylvester (const ComplexMatrix& a, const ComplexMatrix& b, | |
3874 const ComplexMatrix& c) | |
3875 { | |
3876 ComplexMatrix retval; | |
3877 | |
5775 | 3878 // FIXME -- need to check that a, b, and c are all the same |
1819 | 3879 // size. |
3880 | |
3881 // Compute Schur decompositions | |
3882 | |
3883 ComplexSCHUR as (a, "U"); | |
3884 ComplexSCHUR bs (b, "U"); | |
3885 | |
3886 // Transform c to new coordinates. | |
3887 | |
3888 ComplexMatrix ua = as.unitary_matrix (); | |
3889 ComplexMatrix sch_a = as.schur_matrix (); | |
3890 | |
3891 ComplexMatrix ub = bs.unitary_matrix (); | |
3892 ComplexMatrix sch_b = bs.schur_matrix (); | |
3893 | |
3894 ComplexMatrix cx = ua.hermitian () * c * ub; | |
3895 | |
3896 // Solve the sylvester equation, back-transform, and return the | |
3897 // solution. | |
3898 | |
5275 | 3899 octave_idx_type a_nr = a.rows (); |
3900 octave_idx_type b_nr = b.rows (); | |
1819 | 3901 |
3902 double scale; | |
5275 | 3903 octave_idx_type info; |
1950 | 3904 |
3905 Complex *pa = sch_a.fortran_vec (); | |
3906 Complex *pb = sch_b.fortran_vec (); | |
3907 Complex *px = cx.fortran_vec (); | |
1819 | 3908 |
4552 | 3909 F77_XFCN (ztrsyl, ZTRSYL, (F77_CONST_CHAR_ARG2 ("N", 1), |
3910 F77_CONST_CHAR_ARG2 ("N", 1), | |
3911 1, a_nr, b_nr, pa, a_nr, pb, | |
3912 b_nr, px, a_nr, scale, info | |
3913 F77_CHAR_ARG_LEN (1) | |
3914 F77_CHAR_ARG_LEN (1))); | |
1950 | 3915 |
7482
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
3916 // FIXME -- check info? |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
3917 |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
3918 retval = -ua * cx * ub.hermitian (); |
1819 | 3919 |
3920 return retval; | |
3921 } | |
3922 | |
2828 | 3923 ComplexMatrix |
3924 operator * (const ComplexMatrix& m, const Matrix& a) | |
3925 { | |
3926 ComplexMatrix tmp (a); | |
3927 return m * tmp; | |
3928 } | |
3929 | |
3930 ComplexMatrix | |
3931 operator * (const Matrix& m, const ComplexMatrix& a) | |
3932 { | |
3933 ComplexMatrix tmp (m); | |
3934 return tmp * a; | |
3935 } | |
3936 | |
6162 | 3937 /* Simple Dot Product, Matrix-Vector and Matrix-Matrix Unit tests |
3938 %!assert([1+i 2+i 3+i] * [ 4+i ; 5+i ; 6+i], 29+21i, 1e-14) | |
3939 %!assert([1+i 2+i ; 3+i 4+i ] * [5+i ; 6+i], [15 + 14i ; 37 + 18i], 1e-14) | |
3940 %!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) | |
3941 */ | |
3942 | |
3943 /* Test some simple identities | |
3944 %!shared M, cv, rv | |
3945 %! M = randn(10,10)+i*rand(10,10); | |
3946 %! cv = randn(10,1)+i*rand(10,1); | |
3947 %! rv = randn(1,10)+i*rand(1,10); | |
3948 %!assert([M*cv,M*cv],M*[cv,cv],1e-14) | |
3949 %!assert([rv*M;rv*M],[rv;rv]*M,1e-14) | |
3950 %!assert(2*rv*cv,[rv,rv]*[cv;cv],1e-14) | |
3951 */ | |
3952 | |
2828 | 3953 ComplexMatrix |
3954 operator * (const ComplexMatrix& m, const ComplexMatrix& a) | |
3955 { | |
3956 ComplexMatrix retval; | |
3957 | |
5275 | 3958 octave_idx_type nr = m.rows (); |
3959 octave_idx_type nc = m.cols (); | |
3960 | |
3961 octave_idx_type a_nr = a.rows (); | |
3962 octave_idx_type a_nc = a.cols (); | |
2828 | 3963 |
3964 if (nc != a_nr) | |
3965 gripe_nonconformant ("operator *", nr, nc, a_nr, a_nc); | |
3966 else | |
3967 { | |
3968 if (nr == 0 || nc == 0 || a_nc == 0) | |
3760 | 3969 retval.resize (nr, a_nc, 0.0); |
2828 | 3970 else |
3971 { | |
5275 | 3972 octave_idx_type ld = nr; |
3973 octave_idx_type lda = a.rows (); | |
2828 | 3974 |
3975 retval.resize (nr, a_nc); | |
3976 Complex *c = retval.fortran_vec (); | |
3977 | |
5983 | 3978 if (a_nc == 1) |
3979 { | |
3980 if (nr == 1) | |
3981 F77_FUNC (xzdotu, XZDOTU) (nc, m.data (), 1, a.data (), 1, *c); | |
3982 else | |
6390 | 3983 { |
3984 F77_XFCN (zgemv, ZGEMV, (F77_CONST_CHAR_ARG2 ("N", 1), | |
3985 nr, nc, 1.0, m.data (), ld, | |
3986 a.data (), 1, 0.0, c, 1 | |
3987 F77_CHAR_ARG_LEN (1))); | |
3988 } | |
5983 | 3989 } |
3990 else | |
6390 | 3991 { |
3992 F77_XFCN (zgemm, ZGEMM, (F77_CONST_CHAR_ARG2 ("N", 1), | |
3993 F77_CONST_CHAR_ARG2 ("N", 1), | |
3994 nr, a_nc, nc, 1.0, m.data (), | |
3995 ld, a.data (), lda, 0.0, c, nr | |
3996 F77_CHAR_ARG_LEN (1) | |
3997 F77_CHAR_ARG_LEN (1))); | |
3998 } | |
2828 | 3999 } |
4000 } | |
4001 | |
4002 return retval; | |
4003 } | |
4004 | |
5775 | 4005 // FIXME -- it would be nice to share code among the min/max |
4309 | 4006 // functions below. |
4007 | |
4008 #define EMPTY_RETURN_CHECK(T) \ | |
4009 if (nr == 0 || nc == 0) \ | |
4010 return T (nr, nc); | |
4011 | |
4012 ComplexMatrix | |
4013 min (const Complex& c, const ComplexMatrix& m) | |
4014 { | |
5275 | 4015 octave_idx_type nr = m.rows (); |
4016 octave_idx_type nc = m.columns (); | |
4309 | 4017 |
4018 EMPTY_RETURN_CHECK (ComplexMatrix); | |
4019 | |
4020 ComplexMatrix result (nr, nc); | |
4021 | |
5275 | 4022 for (octave_idx_type j = 0; j < nc; j++) |
4023 for (octave_idx_type i = 0; i < nr; i++) | |
4309 | 4024 { |
4025 OCTAVE_QUIT; | |
4026 result (i, j) = xmin (c, m (i, j)); | |
4027 } | |
4028 | |
4029 return result; | |
4030 } | |
4031 | |
4032 ComplexMatrix | |
4033 min (const ComplexMatrix& m, const Complex& c) | |
4034 { | |
5275 | 4035 octave_idx_type nr = m.rows (); |
4036 octave_idx_type nc = m.columns (); | |
4309 | 4037 |
4038 EMPTY_RETURN_CHECK (ComplexMatrix); | |
4039 | |
4040 ComplexMatrix result (nr, nc); | |
4041 | |
5275 | 4042 for (octave_idx_type j = 0; j < nc; j++) |
4043 for (octave_idx_type i = 0; i < nr; i++) | |
4309 | 4044 { |
4045 OCTAVE_QUIT; | |
4046 result (i, j) = xmin (m (i, j), c); | |
4047 } | |
4048 | |
4049 return result; | |
4050 } | |
4051 | |
4052 ComplexMatrix | |
4053 min (const ComplexMatrix& a, const ComplexMatrix& b) | |
4054 { | |
5275 | 4055 octave_idx_type nr = a.rows (); |
4056 octave_idx_type nc = a.columns (); | |
4309 | 4057 |
4058 if (nr != b.rows () || nc != b.columns ()) | |
4059 { | |
4060 (*current_liboctave_error_handler) | |
4061 ("two-arg min expecting args of same size"); | |
4062 return ComplexMatrix (); | |
4063 } | |
4064 | |
4065 EMPTY_RETURN_CHECK (ComplexMatrix); | |
4066 | |
4067 ComplexMatrix result (nr, nc); | |
4068 | |
5275 | 4069 for (octave_idx_type j = 0; j < nc; j++) |
4309 | 4070 { |
4071 int columns_are_real_only = 1; | |
5275 | 4072 for (octave_idx_type i = 0; i < nr; i++) |
4309 | 4073 { |
4074 OCTAVE_QUIT; | |
5315 | 4075 if (std::imag (a (i, j)) != 0.0 || std::imag (b (i, j)) != 0.0) |
4309 | 4076 { |
4077 columns_are_real_only = 0; | |
4078 break; | |
4079 } | |
4080 } | |
4081 | |
4082 if (columns_are_real_only) | |
4083 { | |
5275 | 4084 for (octave_idx_type i = 0; i < nr; i++) |
5315 | 4085 result (i, j) = xmin (std::real (a (i, j)), std::real (b (i, j))); |
4309 | 4086 } |
4087 else | |
4088 { | |
5275 | 4089 for (octave_idx_type i = 0; i < nr; i++) |
4309 | 4090 { |
4091 OCTAVE_QUIT; | |
4092 result (i, j) = xmin (a (i, j), b (i, j)); | |
4093 } | |
4094 } | |
4095 } | |
4096 | |
4097 return result; | |
4098 } | |
4099 | |
4100 ComplexMatrix | |
4101 max (const Complex& c, const ComplexMatrix& m) | |
4102 { | |
5275 | 4103 octave_idx_type nr = m.rows (); |
4104 octave_idx_type nc = m.columns (); | |
4309 | 4105 |
4106 EMPTY_RETURN_CHECK (ComplexMatrix); | |
4107 | |
4108 ComplexMatrix result (nr, nc); | |
4109 | |
5275 | 4110 for (octave_idx_type j = 0; j < nc; j++) |
4111 for (octave_idx_type i = 0; i < nr; i++) | |
4309 | 4112 { |
4113 OCTAVE_QUIT; | |
4114 result (i, j) = xmax (c, m (i, j)); | |
4115 } | |
4116 | |
4117 return result; | |
4118 } | |
4119 | |
4120 ComplexMatrix | |
4121 max (const ComplexMatrix& m, const Complex& c) | |
4122 { | |
5275 | 4123 octave_idx_type nr = m.rows (); |
4124 octave_idx_type nc = m.columns (); | |
4309 | 4125 |
4126 EMPTY_RETURN_CHECK (ComplexMatrix); | |
4127 | |
4128 ComplexMatrix result (nr, nc); | |
4129 | |
5275 | 4130 for (octave_idx_type j = 0; j < nc; j++) |
4131 for (octave_idx_type i = 0; i < nr; i++) | |
4309 | 4132 { |
4133 OCTAVE_QUIT; | |
4134 result (i, j) = xmax (m (i, j), c); | |
4135 } | |
4136 | |
4137 return result; | |
4138 } | |
4139 | |
4140 ComplexMatrix | |
4141 max (const ComplexMatrix& a, const ComplexMatrix& b) | |
4142 { | |
5275 | 4143 octave_idx_type nr = a.rows (); |
4144 octave_idx_type nc = a.columns (); | |
4309 | 4145 |
4146 if (nr != b.rows () || nc != b.columns ()) | |
4147 { | |
4148 (*current_liboctave_error_handler) | |
4149 ("two-arg max expecting args of same size"); | |
4150 return ComplexMatrix (); | |
4151 } | |
4152 | |
4153 EMPTY_RETURN_CHECK (ComplexMatrix); | |
4154 | |
4155 ComplexMatrix result (nr, nc); | |
4156 | |
5275 | 4157 for (octave_idx_type j = 0; j < nc; j++) |
4309 | 4158 { |
4159 int columns_are_real_only = 1; | |
5275 | 4160 for (octave_idx_type i = 0; i < nr; i++) |
4309 | 4161 { |
4162 OCTAVE_QUIT; | |
5315 | 4163 if (std::imag (a (i, j)) != 0.0 || std::imag (b (i, j)) != 0.0) |
4309 | 4164 { |
4165 columns_are_real_only = 0; | |
4166 break; | |
4167 } | |
4168 } | |
4169 | |
4170 if (columns_are_real_only) | |
4171 { | |
5275 | 4172 for (octave_idx_type i = 0; i < nr; i++) |
4309 | 4173 { |
4174 OCTAVE_QUIT; | |
5315 | 4175 result (i, j) = xmax (std::real (a (i, j)), std::real (b (i, j))); |
4309 | 4176 } |
4177 } | |
4178 else | |
4179 { | |
5275 | 4180 for (octave_idx_type i = 0; i < nr; i++) |
4309 | 4181 { |
4182 OCTAVE_QUIT; | |
4183 result (i, j) = xmax (a (i, j), b (i, j)); | |
4184 } | |
4185 } | |
4186 } | |
4187 | |
4188 return result; | |
4189 } | |
4190 | |
5315 | 4191 MS_CMP_OPS(ComplexMatrix, std::real, Complex, std::real) |
3504 | 4192 MS_BOOL_OPS(ComplexMatrix, Complex, 0.0) |
2870 | 4193 |
5315 | 4194 SM_CMP_OPS(Complex, std::real, ComplexMatrix, std::real) |
3504 | 4195 SM_BOOL_OPS(Complex, ComplexMatrix, 0.0) |
2870 | 4196 |
5315 | 4197 MM_CMP_OPS(ComplexMatrix, std::real, ComplexMatrix, std::real) |
3504 | 4198 MM_BOOL_OPS(ComplexMatrix, ComplexMatrix, 0.0) |
2870 | 4199 |
458 | 4200 /* |
4201 ;;; Local Variables: *** | |
4202 ;;; mode: C++ *** | |
4203 ;;; End: *** | |
4204 */ |