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