Mercurial > hg > octave-nkf
annotate liboctave/CMatrix.cc @ 11652:ef95e842ba81 release-3-0-x
another small xGELSD workspace fix
author | John W. Eaton <jwe@octave.org> |
---|---|
date | Fri, 15 Feb 2008 19:54:25 -0500 |
parents | 74de76325d12 |
children | ef2b2df1ed9a |
rev | line source |
---|---|
1993 | 1 // Matrix manipulations. |
458 | 2 /* |
3 | |
7017 | 4 Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, |
5 2003, 2004, 2005, 2006, 2007 John W. Eaton | |
458 | 6 |
7 This file is part of Octave. | |
8 | |
9 Octave is free software; you can redistribute it and/or modify it | |
10 under the terms of the GNU General Public License as published by the | |
7016 | 11 Free Software Foundation; either version 3 of the License, or (at your |
12 option) any later version. | |
458 | 13 |
14 Octave is distributed in the hope that it will be useful, but WITHOUT | |
15 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
16 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
17 for more details. | |
18 | |
19 You should have received a copy of the GNU General Public License | |
7016 | 20 along with Octave; see the file COPYING. If not, see |
21 <http://www.gnu.org/licenses/>. | |
458 | 22 |
23 */ | |
24 | |
25 #ifdef HAVE_CONFIG_H | |
1192 | 26 #include <config.h> |
458 | 27 #endif |
28 | |
1367 | 29 #include <cfloat> |
30 | |
3503 | 31 #include <iostream> |
6209 | 32 #include <vector> |
1367 | 33 |
5775 | 34 // FIXME |
2443 | 35 #ifdef HAVE_SYS_TYPES_H |
36 #include <sys/types.h> | |
37 #endif | |
458 | 38 |
4669 | 39 #include "Array-util.h" |
2828 | 40 #include "CMatrix.h" |
1819 | 41 #include "CmplxAEPBAL.h" |
458 | 42 #include "CmplxDET.h" |
1819 | 43 #include "CmplxSCHUR.h" |
740 | 44 #include "CmplxSVD.h" |
6207 | 45 #include "CmplxCHOL.h" |
1847 | 46 #include "f77-fcn.h" |
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) |
7124 | 2523 double tmp = log2 (dminmn) / dsmlsizp1 + 1; |
7079 | 2524 #else |
7124 | 2525 double tmp = log (dminmn) / dsmlsizp1 / log (2.0) + 1; |
7079 | 2526 #endif |
2527 octave_idx_type nlvl = static_cast<int> (tmp); | |
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 } | |
2570 | |
1948 | 2571 if (f77_exception_encountered) |
7072 | 2572 (*current_liboctave_error_handler) |
2573 ("unrecoverable error in zgelsd"); | |
1948 | 2574 else |
2575 { | |
5315 | 2576 lwork = static_cast<octave_idx_type> (std::real (work(0))); |
3752 | 2577 work.resize (lwork); |
7072 | 2578 |
2579 F77_XFCN (zgelsd, ZGELSD, (m, n, nrhs, tmp_data, m, pretval, | |
2580 maxmn, ps, rcond, rank, | |
2581 work.fortran_vec (), lwork, | |
7079 | 2582 prwork, piwork, info)); |
3752 | 2583 |
2584 if (f77_exception_encountered) | |
7072 | 2585 (*current_liboctave_error_handler) |
2586 ("unrecoverable error in zgelsd"); | |
7076 | 2587 else |
2588 { | |
2589 if (rank < minmn) | |
2590 (*current_liboctave_warning_handler) | |
2591 ("zgelsd: rank deficient %dx%d matrix, rank = %d, tol = %e", | |
2592 m, n, rank, rcond); | |
2593 | |
2594 if (s.elem (0) == 0.0) | |
2595 rcond = 0.0; | |
2596 else | |
2597 rcond = s.elem (minmn - 1) / s.elem (0); | |
7079 | 2598 |
2599 retval.resize (n, nrhs); | |
7076 | 2600 } |
1948 | 2601 } |
458 | 2602 } |
2603 | |
2604 return retval; | |
2605 } | |
2606 | |
2607 ComplexColumnVector | |
3585 | 2608 ComplexMatrix::lssolve (const ColumnVector& b) const |
2609 { | |
5275 | 2610 octave_idx_type info; |
2611 octave_idx_type rank; | |
7076 | 2612 double rcond; |
2613 return lssolve (ComplexColumnVector (b), info, rank, rcond); | |
3585 | 2614 } |
2615 | |
2616 ComplexColumnVector | |
5275 | 2617 ComplexMatrix::lssolve (const ColumnVector& b, octave_idx_type& info) const |
3585 | 2618 { |
5275 | 2619 octave_idx_type rank; |
7076 | 2620 double rcond; |
2621 return lssolve (ComplexColumnVector (b), info, rank, rcond); | |
3585 | 2622 } |
2623 | |
2624 ComplexColumnVector | |
7076 | 2625 ComplexMatrix::lssolve (const ColumnVector& b, octave_idx_type& info, |
2626 octave_idx_type& rank) const | |
3585 | 2627 { |
7076 | 2628 double rcond; |
2629 return lssolve (ComplexColumnVector (b), info, rank, rcond); | |
2630 } | |
2631 | |
2632 ComplexColumnVector | |
2633 ComplexMatrix::lssolve (const ColumnVector& b, octave_idx_type& info, | |
2634 octave_idx_type& rank, double& rcond) const | |
2635 { | |
2636 return lssolve (ComplexColumnVector (b), info, rank, rcond); | |
3585 | 2637 } |
2638 | |
2639 ComplexColumnVector | |
458 | 2640 ComplexMatrix::lssolve (const ComplexColumnVector& b) const |
2641 { | |
5275 | 2642 octave_idx_type info; |
2643 octave_idx_type rank; | |
7076 | 2644 double rcond; |
2645 return lssolve (b, info, rank, rcond); | |
458 | 2646 } |
2647 | |
2648 ComplexColumnVector | |
5275 | 2649 ComplexMatrix::lssolve (const ComplexColumnVector& b, octave_idx_type& info) const |
458 | 2650 { |
5275 | 2651 octave_idx_type rank; |
7076 | 2652 double rcond; |
2653 return lssolve (b, info, rank, rcond); | |
458 | 2654 } |
2655 | |
2656 ComplexColumnVector | |
5275 | 2657 ComplexMatrix::lssolve (const ComplexColumnVector& b, octave_idx_type& info, |
2658 octave_idx_type& rank) const | |
458 | 2659 { |
7076 | 2660 double rcond; |
2661 return lssolve (b, info, rank, rcond); | |
2662 | |
2663 } | |
2664 | |
2665 ComplexColumnVector | |
2666 ComplexMatrix::lssolve (const ComplexColumnVector& b, octave_idx_type& info, | |
2667 octave_idx_type& rank, double& rcond) const | |
2668 { | |
1948 | 2669 ComplexColumnVector retval; |
2670 | |
5275 | 2671 octave_idx_type nrhs = 1; |
2672 | |
2673 octave_idx_type m = rows (); | |
2674 octave_idx_type n = cols (); | |
458 | 2675 |
6924 | 2676 if (m != b.length ()) |
1948 | 2677 (*current_liboctave_error_handler) |
6924 | 2678 ("matrix dimension mismatch solution of linear equations"); |
2679 else if (m == 0 || n == 0 || b.cols () == 0) | |
2680 retval = ComplexColumnVector (n, Complex (0.0, 0.0)); | |
1948 | 2681 else |
458 | 2682 { |
7072 | 2683 volatile octave_idx_type minmn = (m < n ? m : n); |
2684 octave_idx_type maxmn = m > n ? m : n; | |
7076 | 2685 rcond = -1.0; |
7072 | 2686 |
2687 if (m != n) | |
2688 { | |
2689 retval = ComplexColumnVector (maxmn); | |
2690 | |
2691 for (octave_idx_type i = 0; i < m; i++) | |
2692 retval.elem (i) = b.elem (i); | |
2693 } | |
2694 else | |
2695 retval = b; | |
2696 | |
1948 | 2697 ComplexMatrix atmp = *this; |
2698 Complex *tmp_data = atmp.fortran_vec (); | |
2699 | |
7072 | 2700 Complex *pretval = retval.fortran_vec (); |
2701 Array<double> s (minmn); | |
7071 | 2702 double *ps = s.fortran_vec (); |
1948 | 2703 |
7072 | 2704 // Ask ZGELSD what the dimension of WORK should be. |
5275 | 2705 octave_idx_type lwork = -1; |
3752 | 2706 |
2707 Array<Complex> work (1); | |
7079 | 2708 |
2709 // FIXME: Can SMLSIZ be other than 25? | |
2710 octave_idx_type smlsiz = 25; | |
2711 | |
2712 // We compute the size of rwork and iwork because ZGELSD in | |
2713 // older versions of LAPACK does not return them on a query | |
2714 // call. | |
7124 | 2715 double dminmn = static_cast<double> (minmn); |
2716 double dsmlsizp1 = static_cast<double> (smlsiz+1); | |
7079 | 2717 #if defined (HAVE_LOG2) |
7124 | 2718 double tmp = log2 (dminmn) / dsmlsizp1 + 1; |
7079 | 2719 #else |
7124 | 2720 double tmp = log (dminmn) / dsmlsizp1 / log (2.0) + 1; |
7079 | 2721 #endif |
2722 octave_idx_type nlvl = static_cast<int> (tmp); | |
2723 if (nlvl < 0) | |
2724 nlvl = 0; | |
2725 | |
2726 octave_idx_type lrwork = minmn*(10 + 2*smlsiz + 8*nlvl) | |
2727 + 3*smlsiz*nrhs + (smlsiz+1)*(smlsiz+1); | |
2728 if (lrwork < 1) | |
2729 lrwork = 1; | |
2730 Array<double> rwork (lrwork); | |
2731 double *prwork = rwork.fortran_vec (); | |
2732 | |
2733 octave_idx_type liwork = 3 * minmn * nlvl + 11 * minmn; | |
2734 if (liwork < 1) | |
2735 liwork = 1; | |
2736 Array<octave_idx_type> iwork (liwork); | |
2737 octave_idx_type* piwork = iwork.fortran_vec (); | |
7072 | 2738 |
2739 F77_XFCN (zgelsd, ZGELSD, (m, n, nrhs, tmp_data, m, pretval, maxmn, | |
2740 ps, rcond, rank, work.fortran_vec (), | |
7079 | 2741 lwork, prwork, piwork, info)); |
1948 | 2742 |
2743 if (f77_exception_encountered) | |
7072 | 2744 (*current_liboctave_error_handler) |
2745 ("unrecoverable error in zgelsd"); | |
1948 | 2746 else |
2747 { | |
7072 | 2748 lwork = static_cast<octave_idx_type> (std::real (work(0))); |
3752 | 2749 work.resize (lwork); |
7072 | 2750 rwork.resize (static_cast<octave_idx_type> (rwork(0))); |
2751 iwork.resize (iwork(0)); | |
2752 | |
2753 F77_XFCN (zgelsd, ZGELSD, (m, n, nrhs, tmp_data, m, pretval, | |
2754 maxmn, ps, rcond, rank, | |
2755 work.fortran_vec (), lwork, | |
7079 | 2756 prwork, piwork, info)); |
3752 | 2757 |
2758 if (f77_exception_encountered) | |
7072 | 2759 (*current_liboctave_error_handler) |
2760 ("unrecoverable error in zgelsd"); | |
2761 else if (rank < minmn) | |
7076 | 2762 { |
2763 if (rank < minmn) | |
2764 (*current_liboctave_warning_handler) | |
2765 ("zgelsd: rank deficient %dx%d matrix, rank = %d, tol = %e", | |
2766 m, n, rank, rcond); | |
2767 | |
2768 if (s.elem (0) == 0.0) | |
2769 rcond = 0.0; | |
2770 else | |
2771 rcond = s.elem (minmn - 1) / s.elem (0); | |
7079 | 2772 |
2773 retval.resize (n, nrhs); | |
7076 | 2774 } |
1948 | 2775 } |
458 | 2776 } |
2777 | |
2778 return retval; | |
2779 } | |
2780 | |
1819 | 2781 // Constants for matrix exponential calculation. |
2782 | |
2783 static double padec [] = | |
2784 { | |
2785 5.0000000000000000e-1, | |
2786 1.1666666666666667e-1, | |
2787 1.6666666666666667e-2, | |
2788 1.6025641025641026e-3, | |
2789 1.0683760683760684e-4, | |
2790 4.8562548562548563e-6, | |
2791 1.3875013875013875e-7, | |
2792 1.9270852604185938e-9, | |
2793 }; | |
2794 | |
2795 ComplexMatrix | |
2796 ComplexMatrix::expm (void) const | |
2797 { | |
2798 ComplexMatrix retval; | |
2799 | |
2800 ComplexMatrix m = *this; | |
2801 | |
5275 | 2802 octave_idx_type nc = columns (); |
1819 | 2803 |
3130 | 2804 // Preconditioning step 1: trace normalization to reduce dynamic |
2805 // range of poles, but avoid making stable eigenvalues unstable. | |
2806 | |
1819 | 2807 // trace shift value |
2808 Complex trshift = 0.0; | |
2809 | |
5275 | 2810 for (octave_idx_type i = 0; i < nc; i++) |
1819 | 2811 trshift += m.elem (i, i); |
2812 | |
2813 trshift /= nc; | |
2814 | |
3130 | 2815 if (trshift.real () < 0.0) |
6958 | 2816 { |
2817 trshift = trshift.imag (); | |
2818 if (trshift.real () > 709.0) | |
2819 trshift = 709.0; | |
2820 } | |
3130 | 2821 |
5275 | 2822 for (octave_idx_type i = 0; i < nc; i++) |
1819 | 2823 m.elem (i, i) -= trshift; |
2824 | |
2825 // Preconditioning step 2: eigenvalue balancing. | |
3331 | 2826 // code follows development in AEPBAL |
2827 | |
2828 Complex *mp = m.fortran_vec (); | |
3467 | 2829 |
5275 | 2830 octave_idx_type info, ilo, ihi,ilos,ihis; |
3468 | 2831 Array<double> dpermute (nc); |
2832 Array<double> dscale (nc); | |
2833 | |
5775 | 2834 // FIXME -- should pass job as a parameter in expm |
3468 | 2835 |
2836 // Permute first | |
2837 char job = 'P'; | |
4552 | 2838 F77_XFCN (zgebal, ZGEBAL, (F77_CONST_CHAR_ARG2 (&job, 1), |
2839 nc, mp, nc, ilo, ihi, | |
2840 dpermute.fortran_vec (), info | |
2841 F77_CHAR_ARG_LEN (1))); | |
3331 | 2842 |
2843 if (f77_exception_encountered) | |
2844 { | |
2845 (*current_liboctave_error_handler) ("unrecoverable error in zgebal"); | |
2846 return retval; | |
2847 } | |
2848 | |
3468 | 2849 // then scale |
2850 job = 'S'; | |
4552 | 2851 F77_XFCN (zgebal, ZGEBAL, (F77_CONST_CHAR_ARG2 (&job, 1), |
2852 nc, mp, nc, ilos, ihis, | |
2853 dscale.fortran_vec (), info | |
2854 F77_CHAR_ARG_LEN (1))); | |
3331 | 2855 |
2856 if (f77_exception_encountered) | |
2857 { | |
3467 | 2858 (*current_liboctave_error_handler) ("unrecoverable error in zgebal"); |
3331 | 2859 return retval; |
2860 } | |
1819 | 2861 |
2862 // Preconditioning step 3: scaling. | |
2863 | |
2864 ColumnVector work (nc); | |
3130 | 2865 double inf_norm; |
2866 | |
4552 | 2867 F77_XFCN (xzlange, XZLANGE, (F77_CONST_CHAR_ARG2 ("I", 1), |
2868 nc, nc, m.fortran_vec (), nc, | |
2869 work.fortran_vec (), inf_norm | |
2870 F77_CHAR_ARG_LEN (1))); | |
3331 | 2871 |
2872 if (f77_exception_encountered) | |
2873 { | |
2874 (*current_liboctave_error_handler) ("unrecoverable error in zlange"); | |
2875 return retval; | |
2876 } | |
1819 | 2877 |
2800 | 2878 int sqpow = (inf_norm > 0.0 |
2879 ? static_cast<int> (1.0 + log (inf_norm) / log (2.0)) : 0); | |
1819 | 2880 |
2881 // Check whether we need to square at all. | |
2882 | |
2883 if (sqpow < 0) | |
2884 sqpow = 0; | |
2885 | |
2886 if (sqpow > 0) | |
2887 { | |
2888 double scale_factor = 1.0; | |
5275 | 2889 for (octave_idx_type i = 0; i < sqpow; i++) |
1819 | 2890 scale_factor *= 2.0; |
2891 | |
2892 m = m / scale_factor; | |
2893 } | |
2894 | |
2895 // npp, dpp: pade' approx polynomial matrices. | |
2896 | |
2897 ComplexMatrix npp (nc, nc, 0.0); | |
6958 | 2898 Complex *pnpp = npp.fortran_vec (); |
1819 | 2899 ComplexMatrix dpp = npp; |
6958 | 2900 Complex *pdpp = dpp.fortran_vec (); |
1819 | 2901 |
2902 // Now powers a^8 ... a^1. | |
2903 | |
2904 int minus_one_j = -1; | |
5275 | 2905 for (octave_idx_type j = 7; j >= 0; j--) |
1819 | 2906 { |
6958 | 2907 for (octave_idx_type i = 0; i < nc; i++) |
2908 { | |
2909 octave_idx_type k = i * nc + i; | |
7265 | 2910 pnpp[k] += padec[j]; |
2911 pdpp[k] += minus_one_j * padec[j]; | |
6958 | 2912 } |
7265 | 2913 |
6958 | 2914 npp = m * npp; |
7265 | 2915 pnpp = npp.fortran_vec (); |
2916 | |
6958 | 2917 dpp = m * dpp; |
7265 | 2918 pdpp = dpp.fortran_vec (); |
2919 | |
1819 | 2920 minus_one_j *= -1; |
2921 } | |
2922 | |
2923 // Zero power. | |
2924 | |
2925 dpp = -dpp; | |
5275 | 2926 for (octave_idx_type j = 0; j < nc; j++) |
1819 | 2927 { |
2928 npp.elem (j, j) += 1.0; | |
2929 dpp.elem (j, j) += 1.0; | |
2930 } | |
2931 | |
2932 // Compute pade approximation = inverse (dpp) * npp. | |
2933 | |
2934 retval = dpp.solve (npp); | |
2935 | |
2936 // Reverse preconditioning step 3: repeated squaring. | |
2937 | |
2938 while (sqpow) | |
2939 { | |
2940 retval = retval * retval; | |
2941 sqpow--; | |
2942 } | |
2943 | |
2944 // Reverse preconditioning step 2: inverse balancing. | |
3467 | 2945 // Done in two steps: inverse scaling, then inverse permutation |
2946 | |
2947 // inverse scaling (diagonal transformation) | |
5275 | 2948 for (octave_idx_type i = 0; i < nc; i++) |
2949 for (octave_idx_type j = 0; j < nc; j++) | |
3468 | 2950 retval(i,j) *= dscale(i) / dscale(j); |
3467 | 2951 |
4153 | 2952 OCTAVE_QUIT; |
2953 | |
3467 | 2954 // construct balancing permutation vector |
6867 | 2955 Array<octave_idx_type> iperm (nc); |
5275 | 2956 for (octave_idx_type i = 0; i < nc; i++) |
4593 | 2957 iperm(i) = i; // initialize to identity permutation |
3467 | 2958 |
2959 // leading permutations in forward order | |
5275 | 2960 for (octave_idx_type i = 0; i < (ilo-1); i++) |
3468 | 2961 { |
6867 | 2962 octave_idx_type swapidx = static_cast<octave_idx_type> (dpermute(i)) - 1; |
5275 | 2963 octave_idx_type tmp = iperm(i); |
4593 | 2964 iperm(i) = iperm(swapidx); |
2965 iperm(swapidx) = tmp; | |
3468 | 2966 } |
3467 | 2967 |
2968 // trailing permutations must be done in reverse order | |
5275 | 2969 for (octave_idx_type i = nc - 1; i >= ihi; i--) |
3468 | 2970 { |
6867 | 2971 octave_idx_type swapidx = static_cast<octave_idx_type> (dpermute(i)) - 1; |
5275 | 2972 octave_idx_type tmp = iperm(i); |
4593 | 2973 iperm(i) = iperm(swapidx); |
2974 iperm(swapidx) = tmp; | |
3468 | 2975 } |
3467 | 2976 |
2977 // construct inverse balancing permutation vector | |
6867 | 2978 Array<octave_idx_type> invpvec (nc); |
5275 | 2979 for (octave_idx_type i = 0; i < nc; i++) |
4593 | 2980 invpvec(iperm(i)) = i; // Thanks to R. A. Lippert for this method |
3467 | 2981 |
4153 | 2982 OCTAVE_QUIT; |
2983 | |
3467 | 2984 ComplexMatrix tmpMat = retval; |
5275 | 2985 for (octave_idx_type i = 0; i < nc; i++) |
2986 for (octave_idx_type j = 0; j < nc; j++) | |
3468 | 2987 retval(i,j) = tmpMat(invpvec(i),invpvec(j)); |
1819 | 2988 |
2989 // Reverse preconditioning step 1: fix trace normalization. | |
2990 | |
3130 | 2991 return exp (trshift) * retval; |
1819 | 2992 } |
2993 | |
1205 | 2994 // column vector by row vector -> matrix operations |
2995 | |
2996 ComplexMatrix | |
2997 operator * (const ColumnVector& v, const ComplexRowVector& a) | |
2998 { | |
2999 ComplexColumnVector tmp (v); | |
3000 return tmp * a; | |
3001 } | |
3002 | |
3003 ComplexMatrix | |
3004 operator * (const ComplexColumnVector& a, const RowVector& b) | |
3005 { | |
3006 ComplexRowVector tmp (b); | |
3007 return a * tmp; | |
3008 } | |
3009 | |
3010 ComplexMatrix | |
3011 operator * (const ComplexColumnVector& v, const ComplexRowVector& a) | |
3012 { | |
1948 | 3013 ComplexMatrix retval; |
3014 | |
5275 | 3015 octave_idx_type len = v.length (); |
3233 | 3016 |
3017 if (len != 0) | |
1205 | 3018 { |
5275 | 3019 octave_idx_type a_len = a.length (); |
3233 | 3020 |
3021 retval.resize (len, a_len); | |
3022 Complex *c = retval.fortran_vec (); | |
3023 | |
4552 | 3024 F77_XFCN (zgemm, ZGEMM, (F77_CONST_CHAR_ARG2 ("N", 1), |
3025 F77_CONST_CHAR_ARG2 ("N", 1), | |
3026 len, a_len, 1, 1.0, v.data (), len, | |
3027 a.data (), 1, 0.0, c, len | |
3028 F77_CHAR_ARG_LEN (1) | |
3029 F77_CHAR_ARG_LEN (1))); | |
3233 | 3030 |
3031 if (f77_exception_encountered) | |
3032 (*current_liboctave_error_handler) | |
3033 ("unrecoverable error in zgemm"); | |
1205 | 3034 } |
3035 | |
1948 | 3036 return retval; |
1205 | 3037 } |
3038 | |
458 | 3039 // matrix by diagonal matrix -> matrix operations |
3040 | |
3041 ComplexMatrix& | |
3042 ComplexMatrix::operator += (const DiagMatrix& a) | |
3043 { | |
5275 | 3044 octave_idx_type nr = rows (); |
3045 octave_idx_type nc = cols (); | |
3046 | |
3047 octave_idx_type a_nr = rows (); | |
3048 octave_idx_type a_nc = cols (); | |
2384 | 3049 |
3050 if (nr != a_nr || nc != a_nc) | |
458 | 3051 { |
2384 | 3052 gripe_nonconformant ("operator +=", nr, nc, a_nr, a_nc); |
889 | 3053 return *this; |
458 | 3054 } |
3055 | |
5275 | 3056 for (octave_idx_type i = 0; i < a.length (); i++) |
458 | 3057 elem (i, i) += a.elem (i, i); |
3058 | |
3059 return *this; | |
3060 } | |
3061 | |
3062 ComplexMatrix& | |
3063 ComplexMatrix::operator -= (const DiagMatrix& a) | |
3064 { | |
5275 | 3065 octave_idx_type nr = rows (); |
3066 octave_idx_type nc = cols (); | |
3067 | |
3068 octave_idx_type a_nr = rows (); | |
3069 octave_idx_type a_nc = cols (); | |
2384 | 3070 |
3071 if (nr != a_nr || nc != a_nc) | |
458 | 3072 { |
2384 | 3073 gripe_nonconformant ("operator -=", nr, nc, a_nr, a_nc); |
889 | 3074 return *this; |
458 | 3075 } |
3076 | |
5275 | 3077 for (octave_idx_type i = 0; i < a.length (); i++) |
458 | 3078 elem (i, i) -= a.elem (i, i); |
3079 | |
3080 return *this; | |
3081 } | |
3082 | |
3083 ComplexMatrix& | |
3084 ComplexMatrix::operator += (const ComplexDiagMatrix& a) | |
3085 { | |
5275 | 3086 octave_idx_type nr = rows (); |
3087 octave_idx_type nc = cols (); | |
3088 | |
3089 octave_idx_type a_nr = rows (); | |
3090 octave_idx_type a_nc = cols (); | |
2384 | 3091 |
3092 if (nr != a_nr || nc != a_nc) | |
458 | 3093 { |
2384 | 3094 gripe_nonconformant ("operator +=", nr, nc, a_nr, a_nc); |
889 | 3095 return *this; |
458 | 3096 } |
3097 | |
5275 | 3098 for (octave_idx_type i = 0; i < a.length (); i++) |
458 | 3099 elem (i, i) += a.elem (i, i); |
3100 | |
3101 return *this; | |
3102 } | |
3103 | |
3104 ComplexMatrix& | |
3105 ComplexMatrix::operator -= (const ComplexDiagMatrix& a) | |
3106 { | |
5275 | 3107 octave_idx_type nr = rows (); |
3108 octave_idx_type nc = cols (); | |
3109 | |
3110 octave_idx_type a_nr = rows (); | |
3111 octave_idx_type a_nc = cols (); | |
2384 | 3112 |
3113 if (nr != a_nr || nc != a_nc) | |
458 | 3114 { |
2384 | 3115 gripe_nonconformant ("operator -=", nr, nc, a_nr, a_nc); |
889 | 3116 return *this; |
458 | 3117 } |
3118 | |
5275 | 3119 for (octave_idx_type i = 0; i < a.length (); i++) |
458 | 3120 elem (i, i) -= a.elem (i, i); |
3121 | |
3122 return *this; | |
3123 } | |
3124 | |
3125 // matrix by matrix -> matrix operations | |
3126 | |
3127 ComplexMatrix& | |
3128 ComplexMatrix::operator += (const Matrix& a) | |
3129 { | |
5275 | 3130 octave_idx_type nr = rows (); |
3131 octave_idx_type nc = cols (); | |
3132 | |
3133 octave_idx_type a_nr = a.rows (); | |
3134 octave_idx_type a_nc = a.cols (); | |
2384 | 3135 |
3136 if (nr != a_nr || nc != a_nc) | |
458 | 3137 { |
2384 | 3138 gripe_nonconformant ("operator +=", nr, nc, a_nr, a_nc); |
458 | 3139 return *this; |
3140 } | |
3141 | |
3142 if (nr == 0 || nc == 0) | |
3143 return *this; | |
3144 | |
3145 Complex *d = fortran_vec (); // Ensures only one reference to my privates! | |
3146 | |
3769 | 3147 mx_inline_add2 (d, a.data (), length ()); |
458 | 3148 return *this; |
3149 } | |
3150 | |
3151 ComplexMatrix& | |
3152 ComplexMatrix::operator -= (const Matrix& a) | |
3153 { | |
5275 | 3154 octave_idx_type nr = rows (); |
3155 octave_idx_type nc = cols (); | |
3156 | |
3157 octave_idx_type a_nr = a.rows (); | |
3158 octave_idx_type a_nc = a.cols (); | |
2384 | 3159 |
3160 if (nr != a_nr || nc != a_nc) | |
458 | 3161 { |
2384 | 3162 gripe_nonconformant ("operator -=", nr, nc, a_nr, a_nc); |
458 | 3163 return *this; |
3164 } | |
3165 | |
3166 if (nr == 0 || nc == 0) | |
3167 return *this; | |
3168 | |
3169 Complex *d = fortran_vec (); // Ensures only one reference to my privates! | |
3170 | |
3769 | 3171 mx_inline_subtract2 (d, a.data (), length ()); |
458 | 3172 return *this; |
3173 } | |
3174 | |
3175 // unary operations | |
3176 | |
2964 | 3177 boolMatrix |
458 | 3178 ComplexMatrix::operator ! (void) const |
3179 { | |
5275 | 3180 octave_idx_type nr = rows (); |
3181 octave_idx_type nc = cols (); | |
2964 | 3182 |
3183 boolMatrix b (nr, nc); | |
3184 | |
5275 | 3185 for (octave_idx_type j = 0; j < nc; j++) |
3186 for (octave_idx_type i = 0; i < nr; i++) | |
5139 | 3187 b.elem (i, j) = elem (i, j) == 0.0; |
2964 | 3188 |
3189 return b; | |
458 | 3190 } |
3191 | |
3192 // other operations | |
3193 | |
3194 ComplexMatrix | |
2676 | 3195 ComplexMatrix::map (c_c_Mapper f) const |
458 | 3196 { |
2676 | 3197 ComplexMatrix b (*this); |
3198 return b.apply (f); | |
458 | 3199 } |
3200 | |
2676 | 3201 Matrix |
3202 ComplexMatrix::map (d_c_Mapper f) const | |
458 | 3203 { |
5275 | 3204 octave_idx_type nr = rows (); |
3205 octave_idx_type nc = cols (); | |
3248 | 3206 |
3207 Matrix retval (nr, nc); | |
3208 | |
5275 | 3209 for (octave_idx_type j = 0; j < nc; j++) |
3210 for (octave_idx_type i = 0; i < nr; i++) | |
3248 | 3211 retval(i,j) = f (elem(i,j)); |
3212 | |
3213 return retval; | |
3214 } | |
3215 | |
3216 boolMatrix | |
3217 ComplexMatrix::map (b_c_Mapper f) const | |
3218 { | |
5275 | 3219 octave_idx_type nr = rows (); |
3220 octave_idx_type nc = cols (); | |
3248 | 3221 |
3222 boolMatrix retval (nr, nc); | |
3223 | |
5275 | 3224 for (octave_idx_type j = 0; j < nc; j++) |
3225 for (octave_idx_type i = 0; i < nr; i++) | |
3248 | 3226 retval(i,j) = f (elem(i,j)); |
2676 | 3227 |
3228 return retval; | |
3229 } | |
3230 | |
3231 ComplexMatrix& | |
3232 ComplexMatrix::apply (c_c_Mapper f) | |
3233 { | |
3234 Complex *d = fortran_vec (); // Ensures only one reference to my privates! | |
3235 | |
5275 | 3236 for (octave_idx_type i = 0; i < length (); i++) |
2676 | 3237 d[i] = f (d[i]); |
3238 | |
3239 return *this; | |
458 | 3240 } |
3241 | |
2384 | 3242 bool |
3243 ComplexMatrix::any_element_is_inf_or_nan (void) const | |
3244 { | |
5275 | 3245 octave_idx_type nr = rows (); |
3246 octave_idx_type nc = cols (); | |
3247 | |
3248 for (octave_idx_type j = 0; j < nc; j++) | |
3249 for (octave_idx_type i = 0; i < nr; i++) | |
2384 | 3250 { |
3251 Complex val = elem (i, j); | |
3252 if (xisinf (val) || xisnan (val)) | |
3253 return true; | |
3254 } | |
3255 | |
3256 return false; | |
3257 } | |
3258 | |
2408 | 3259 // Return true if no elements have imaginary components. |
3260 | |
3261 bool | |
3262 ComplexMatrix::all_elements_are_real (void) const | |
3263 { | |
5275 | 3264 octave_idx_type nr = rows (); |
3265 octave_idx_type nc = cols (); | |
3266 | |
3267 for (octave_idx_type j = 0; j < nc; j++) | |
4349 | 3268 { |
5275 | 3269 for (octave_idx_type i = 0; i < nr; i++) |
4349 | 3270 { |
5315 | 3271 double ip = std::imag (elem (i, j)); |
4349 | 3272 |
3273 if (ip != 0.0 || lo_ieee_signbit (ip)) | |
3274 return false; | |
3275 } | |
3276 } | |
2408 | 3277 |
3278 return true; | |
3279 } | |
3280 | |
1968 | 3281 // Return nonzero if any element of CM has a non-integer real or |
3282 // imaginary part. Also extract the largest and smallest (real or | |
3283 // imaginary) values and return them in MAX_VAL and MIN_VAL. | |
3284 | |
2384 | 3285 bool |
1968 | 3286 ComplexMatrix::all_integers (double& max_val, double& min_val) const |
3287 { | |
5275 | 3288 octave_idx_type nr = rows (); |
3289 octave_idx_type nc = cols (); | |
1968 | 3290 |
3291 if (nr > 0 && nc > 0) | |
3292 { | |
3293 Complex val = elem (0, 0); | |
3294 | |
5315 | 3295 double r_val = std::real (val); |
3296 double i_val = std::imag (val); | |
1968 | 3297 |
3298 max_val = r_val; | |
3299 min_val = r_val; | |
3300 | |
3301 if (i_val > max_val) | |
3302 max_val = i_val; | |
3303 | |
3304 if (i_val < max_val) | |
3305 min_val = i_val; | |
3306 } | |
3307 else | |
2384 | 3308 return false; |
1968 | 3309 |
5275 | 3310 for (octave_idx_type j = 0; j < nc; j++) |
3311 for (octave_idx_type i = 0; i < nr; i++) | |
1968 | 3312 { |
3313 Complex val = elem (i, j); | |
3314 | |
5315 | 3315 double r_val = std::real (val); |
3316 double i_val = std::imag (val); | |
1968 | 3317 |
3318 if (r_val > max_val) | |
3319 max_val = r_val; | |
3320 | |
3321 if (i_val > max_val) | |
3322 max_val = i_val; | |
3323 | |
3324 if (r_val < min_val) | |
3325 min_val = r_val; | |
3326 | |
3327 if (i_val < min_val) | |
3328 min_val = i_val; | |
3329 | |
3330 if (D_NINT (r_val) != r_val || D_NINT (i_val) != i_val) | |
2384 | 3331 return false; |
1968 | 3332 } |
2384 | 3333 |
3334 return true; | |
1968 | 3335 } |
3336 | |
2384 | 3337 bool |
1968 | 3338 ComplexMatrix::too_large_for_float (void) const |
3339 { | |
5275 | 3340 octave_idx_type nr = rows (); |
3341 octave_idx_type nc = cols (); | |
3342 | |
3343 for (octave_idx_type j = 0; j < nc; j++) | |
3344 for (octave_idx_type i = 0; i < nr; i++) | |
1968 | 3345 { |
3346 Complex val = elem (i, j); | |
3347 | |
5315 | 3348 double r_val = std::real (val); |
3349 double i_val = std::imag (val); | |
1968 | 3350 |
5389 | 3351 if ((! (xisnan (r_val) || xisinf (r_val)) |
5387 | 3352 && fabs (r_val) > FLT_MAX) |
5389 | 3353 || (! (xisnan (i_val) || xisinf (i_val)) |
5387 | 3354 && fabs (i_val) > FLT_MAX)) |
2384 | 3355 return true; |
1968 | 3356 } |
3357 | |
2384 | 3358 return false; |
1968 | 3359 } |
3360 | |
5775 | 3361 // FIXME Do these really belong here? Maybe they should be |
4015 | 3362 // in a base class? |
3363 | |
2832 | 3364 boolMatrix |
4015 | 3365 ComplexMatrix::all (int dim) const |
458 | 3366 { |
4015 | 3367 MX_ALL_OP (dim); |
458 | 3368 } |
3369 | |
2832 | 3370 boolMatrix |
4015 | 3371 ComplexMatrix::any (int dim) const |
458 | 3372 { |
4015 | 3373 MX_ANY_OP (dim); |
458 | 3374 } |
3375 | |
3376 ComplexMatrix | |
3723 | 3377 ComplexMatrix::cumprod (int dim) const |
458 | 3378 { |
4015 | 3379 MX_CUMULATIVE_OP (ComplexMatrix, Complex, *=); |
458 | 3380 } |
3381 | |
3382 ComplexMatrix | |
3723 | 3383 ComplexMatrix::cumsum (int dim) const |
458 | 3384 { |
4015 | 3385 MX_CUMULATIVE_OP (ComplexMatrix, Complex, +=); |
458 | 3386 } |
3387 | |
3388 ComplexMatrix | |
3723 | 3389 ComplexMatrix::prod (int dim) const |
458 | 3390 { |
3864 | 3391 MX_REDUCTION_OP (ComplexMatrix, *=, 1.0, 1.0); |
458 | 3392 } |
3393 | |
3394 ComplexMatrix | |
3723 | 3395 ComplexMatrix::sum (int dim) const |
458 | 3396 { |
3864 | 3397 MX_REDUCTION_OP (ComplexMatrix, +=, 0.0, 0.0); |
458 | 3398 } |
3399 | |
3400 ComplexMatrix | |
3723 | 3401 ComplexMatrix::sumsq (int dim) const |
458 | 3402 { |
3864 | 3403 #define ROW_EXPR \ |
3404 Complex d = elem (i, j); \ | |
3405 retval.elem (i, 0) += d * conj (d) | |
3406 | |
3407 #define COL_EXPR \ | |
3408 Complex d = elem (i, j); \ | |
3409 retval.elem (0, j) += d * conj (d) | |
3410 | |
3411 MX_BASE_REDUCTION_OP (ComplexMatrix, ROW_EXPR, COL_EXPR, 0.0, 0.0); | |
3412 | |
3413 #undef ROW_EXPR | |
3414 #undef COL_EXPR | |
458 | 3415 } |
3416 | |
4329 | 3417 Matrix ComplexMatrix::abs (void) const |
3418 { | |
5275 | 3419 octave_idx_type nr = rows (); |
3420 octave_idx_type nc = cols (); | |
4329 | 3421 |
3422 Matrix retval (nr, nc); | |
3423 | |
5275 | 3424 for (octave_idx_type j = 0; j < nc; j++) |
3425 for (octave_idx_type i = 0; i < nr; i++) | |
5315 | 3426 retval (i, j) = std::abs (elem (i, j)); |
4329 | 3427 |
3428 return retval; | |
3429 } | |
3430 | |
458 | 3431 ComplexColumnVector |
3432 ComplexMatrix::diag (void) const | |
3433 { | |
3434 return diag (0); | |
3435 } | |
3436 | |
3437 ComplexColumnVector | |
5275 | 3438 ComplexMatrix::diag (octave_idx_type k) const |
458 | 3439 { |
5275 | 3440 octave_idx_type nnr = rows (); |
3441 octave_idx_type nnc = cols (); | |
458 | 3442 if (k > 0) |
3443 nnc -= k; | |
3444 else if (k < 0) | |
3445 nnr += k; | |
3446 | |
3447 ComplexColumnVector d; | |
3448 | |
3449 if (nnr > 0 && nnc > 0) | |
3450 { | |
5275 | 3451 octave_idx_type ndiag = (nnr < nnc) ? nnr : nnc; |
458 | 3452 |
3453 d.resize (ndiag); | |
3454 | |
3455 if (k > 0) | |
3456 { | |
5275 | 3457 for (octave_idx_type i = 0; i < ndiag; i++) |
458 | 3458 d.elem (i) = elem (i, i+k); |
3459 } | |
4509 | 3460 else if (k < 0) |
458 | 3461 { |
5275 | 3462 for (octave_idx_type i = 0; i < ndiag; i++) |
458 | 3463 d.elem (i) = elem (i-k, i); |
3464 } | |
3465 else | |
3466 { | |
5275 | 3467 for (octave_idx_type i = 0; i < ndiag; i++) |
458 | 3468 d.elem (i) = elem (i, i); |
3469 } | |
3470 } | |
3471 else | |
4513 | 3472 (*current_liboctave_error_handler) |
3473 ("diag: requested diagonal out of range"); | |
458 | 3474 |
3475 return d; | |
3476 } | |
3477 | |
2354 | 3478 bool |
5275 | 3479 ComplexMatrix::row_is_real_only (octave_idx_type i) const |
2354 | 3480 { |
3481 bool retval = true; | |
3482 | |
5275 | 3483 octave_idx_type nc = columns (); |
3484 | |
3485 for (octave_idx_type j = 0; j < nc; j++) | |
2354 | 3486 { |
5315 | 3487 if (std::imag (elem (i, j)) != 0.0) |
2354 | 3488 { |
3489 retval = false; | |
3490 break; | |
3491 } | |
3492 } | |
3493 | |
3494 return retval; | |
3495 } | |
3496 | |
3497 bool | |
5275 | 3498 ComplexMatrix::column_is_real_only (octave_idx_type j) const |
2354 | 3499 { |
3500 bool retval = true; | |
3501 | |
5275 | 3502 octave_idx_type nr = rows (); |
3503 | |
3504 for (octave_idx_type i = 0; i < nr; i++) | |
2354 | 3505 { |
5315 | 3506 if (std::imag (elem (i, j)) != 0.0) |
2354 | 3507 { |
3508 retval = false; | |
3509 break; | |
3510 } | |
3511 } | |
3512 | |
3513 return retval; | |
3514 } | |
891 | 3515 |
458 | 3516 ComplexColumnVector |
3517 ComplexMatrix::row_min (void) const | |
3518 { | |
5275 | 3519 Array<octave_idx_type> dummy_idx; |
4587 | 3520 return row_min (dummy_idx); |
458 | 3521 } |
3522 | |
3523 ComplexColumnVector | |
5275 | 3524 ComplexMatrix::row_min (Array<octave_idx_type>& idx_arg) const |
458 | 3525 { |
3526 ComplexColumnVector result; | |
3527 | |
5275 | 3528 octave_idx_type nr = rows (); |
3529 octave_idx_type nc = cols (); | |
458 | 3530 |
3531 if (nr > 0 && nc > 0) | |
3532 { | |
3533 result.resize (nr); | |
4587 | 3534 idx_arg.resize (nr); |
458 | 3535 |
5275 | 3536 for (octave_idx_type i = 0; i < nr; i++) |
458 | 3537 { |
2354 | 3538 bool real_only = row_is_real_only (i); |
3539 | |
5275 | 3540 octave_idx_type idx_j; |
4469 | 3541 |
3542 Complex tmp_min; | |
3543 | |
3544 double abs_min = octave_NaN; | |
3545 | |
3546 for (idx_j = 0; idx_j < nc; idx_j++) | |
3547 { | |
3548 tmp_min = elem (i, idx_j); | |
3549 | |
5389 | 3550 if (! xisnan (tmp_min)) |
4469 | 3551 { |
5315 | 3552 abs_min = real_only ? std::real (tmp_min) : std::abs (tmp_min); |
4469 | 3553 break; |
3554 } | |
3555 } | |
3556 | |
5275 | 3557 for (octave_idx_type j = idx_j+1; j < nc; j++) |
4469 | 3558 { |
3559 Complex tmp = elem (i, j); | |
3560 | |
5389 | 3561 if (xisnan (tmp)) |
4469 | 3562 continue; |
3563 | |
5315 | 3564 double abs_tmp = real_only ? std::real (tmp) : std::abs (tmp); |
4469 | 3565 |
3566 if (abs_tmp < abs_min) | |
3567 { | |
3568 idx_j = j; | |
3569 tmp_min = tmp; | |
3570 abs_min = abs_tmp; | |
3571 } | |
3572 } | |
3573 | |
5389 | 3574 if (xisnan (tmp_min)) |
4469 | 3575 { |
3576 result.elem (i) = Complex_NaN_result; | |
4587 | 3577 idx_arg.elem (i) = 0; |
4469 | 3578 } |
891 | 3579 else |
3580 { | |
4469 | 3581 result.elem (i) = tmp_min; |
4587 | 3582 idx_arg.elem (i) = idx_j; |
891 | 3583 } |
458 | 3584 } |
3585 } | |
3586 | |
3587 return result; | |
3588 } | |
3589 | |
3590 ComplexColumnVector | |
3591 ComplexMatrix::row_max (void) const | |
3592 { | |
5275 | 3593 Array<octave_idx_type> dummy_idx; |
4587 | 3594 return row_max (dummy_idx); |
458 | 3595 } |
3596 | |
3597 ComplexColumnVector | |
5275 | 3598 ComplexMatrix::row_max (Array<octave_idx_type>& idx_arg) const |
458 | 3599 { |
3600 ComplexColumnVector result; | |
3601 | |
5275 | 3602 octave_idx_type nr = rows (); |
3603 octave_idx_type nc = cols (); | |
458 | 3604 |
3605 if (nr > 0 && nc > 0) | |
3606 { | |
3607 result.resize (nr); | |
4587 | 3608 idx_arg.resize (nr); |
458 | 3609 |
5275 | 3610 for (octave_idx_type i = 0; i < nr; i++) |
458 | 3611 { |
2354 | 3612 bool real_only = row_is_real_only (i); |
3613 | |
5275 | 3614 octave_idx_type idx_j; |
4469 | 3615 |
3616 Complex tmp_max; | |
3617 | |
3618 double abs_max = octave_NaN; | |
3619 | |
3620 for (idx_j = 0; idx_j < nc; idx_j++) | |
3621 { | |
3622 tmp_max = elem (i, idx_j); | |
3623 | |
5389 | 3624 if (! xisnan (tmp_max)) |
4469 | 3625 { |
5315 | 3626 abs_max = real_only ? std::real (tmp_max) : std::abs (tmp_max); |
4469 | 3627 break; |
3628 } | |
3629 } | |
3630 | |
5275 | 3631 for (octave_idx_type j = idx_j+1; j < nc; j++) |
4469 | 3632 { |
3633 Complex tmp = elem (i, j); | |
3634 | |
5389 | 3635 if (xisnan (tmp)) |
4469 | 3636 continue; |
3637 | |
5315 | 3638 double abs_tmp = real_only ? std::real (tmp) : std::abs (tmp); |
4469 | 3639 |
3640 if (abs_tmp > abs_max) | |
3641 { | |
3642 idx_j = j; | |
3643 tmp_max = tmp; | |
3644 abs_max = abs_tmp; | |
3645 } | |
3646 } | |
3647 | |
5389 | 3648 if (xisnan (tmp_max)) |
4469 | 3649 { |
3650 result.elem (i) = Complex_NaN_result; | |
4587 | 3651 idx_arg.elem (i) = 0; |
4469 | 3652 } |
891 | 3653 else |
3654 { | |
4469 | 3655 result.elem (i) = tmp_max; |
4587 | 3656 idx_arg.elem (i) = idx_j; |
891 | 3657 } |
458 | 3658 } |
3659 } | |
3660 | |
3661 return result; | |
3662 } | |
3663 | |
3664 ComplexRowVector | |
3665 ComplexMatrix::column_min (void) const | |
3666 { | |
5275 | 3667 Array<octave_idx_type> dummy_idx; |
4587 | 3668 return column_min (dummy_idx); |
458 | 3669 } |
3670 | |
3671 ComplexRowVector | |
5275 | 3672 ComplexMatrix::column_min (Array<octave_idx_type>& idx_arg) const |
458 | 3673 { |
3674 ComplexRowVector result; | |
3675 | |
5275 | 3676 octave_idx_type nr = rows (); |
3677 octave_idx_type nc = cols (); | |
458 | 3678 |
3679 if (nr > 0 && nc > 0) | |
3680 { | |
3681 result.resize (nc); | |
4587 | 3682 idx_arg.resize (nc); |
458 | 3683 |
5275 | 3684 for (octave_idx_type j = 0; j < nc; j++) |
458 | 3685 { |
2354 | 3686 bool real_only = column_is_real_only (j); |
3687 | |
5275 | 3688 octave_idx_type idx_i; |
4469 | 3689 |
3690 Complex tmp_min; | |
3691 | |
3692 double abs_min = octave_NaN; | |
3693 | |
3694 for (idx_i = 0; idx_i < nr; idx_i++) | |
3695 { | |
3696 tmp_min = elem (idx_i, j); | |
3697 | |
5389 | 3698 if (! xisnan (tmp_min)) |
4469 | 3699 { |
5315 | 3700 abs_min = real_only ? std::real (tmp_min) : std::abs (tmp_min); |
4469 | 3701 break; |
3702 } | |
3703 } | |
3704 | |
5275 | 3705 for (octave_idx_type i = idx_i+1; i < nr; i++) |
4469 | 3706 { |
3707 Complex tmp = elem (i, j); | |
3708 | |
5389 | 3709 if (xisnan (tmp)) |
4469 | 3710 continue; |
3711 | |
5315 | 3712 double abs_tmp = real_only ? std::real (tmp) : std::abs (tmp); |
4469 | 3713 |
3714 if (abs_tmp < abs_min) | |
3715 { | |
3716 idx_i = i; | |
3717 tmp_min = tmp; | |
3718 abs_min = abs_tmp; | |
3719 } | |
3720 } | |
3721 | |
5389 | 3722 if (xisnan (tmp_min)) |
4469 | 3723 { |
3724 result.elem (j) = Complex_NaN_result; | |
4587 | 3725 idx_arg.elem (j) = 0; |
4469 | 3726 } |
891 | 3727 else |
3728 { | |
4469 | 3729 result.elem (j) = tmp_min; |
4587 | 3730 idx_arg.elem (j) = idx_i; |
891 | 3731 } |
458 | 3732 } |
3733 } | |
3734 | |
3735 return result; | |
3736 } | |
3737 | |
3738 ComplexRowVector | |
3739 ComplexMatrix::column_max (void) const | |
3740 { | |
5275 | 3741 Array<octave_idx_type> dummy_idx; |
4587 | 3742 return column_max (dummy_idx); |
458 | 3743 } |
3744 | |
3745 ComplexRowVector | |
5275 | 3746 ComplexMatrix::column_max (Array<octave_idx_type>& idx_arg) const |
458 | 3747 { |
3748 ComplexRowVector result; | |
3749 | |
5275 | 3750 octave_idx_type nr = rows (); |
3751 octave_idx_type nc = cols (); | |
458 | 3752 |
3753 if (nr > 0 && nc > 0) | |
3754 { | |
3755 result.resize (nc); | |
4587 | 3756 idx_arg.resize (nc); |
458 | 3757 |
5275 | 3758 for (octave_idx_type j = 0; j < nc; j++) |
458 | 3759 { |
2354 | 3760 bool real_only = column_is_real_only (j); |
3761 | |
5275 | 3762 octave_idx_type idx_i; |
4469 | 3763 |
3764 Complex tmp_max; | |
3765 | |
3766 double abs_max = octave_NaN; | |
3767 | |
3768 for (idx_i = 0; idx_i < nr; idx_i++) | |
3769 { | |
3770 tmp_max = elem (idx_i, j); | |
3771 | |
5389 | 3772 if (! xisnan (tmp_max)) |
4469 | 3773 { |
5315 | 3774 abs_max = real_only ? std::real (tmp_max) : std::abs (tmp_max); |
4469 | 3775 break; |
3776 } | |
3777 } | |
3778 | |
5275 | 3779 for (octave_idx_type i = idx_i+1; i < nr; i++) |
4469 | 3780 { |
3781 Complex tmp = elem (i, j); | |
3782 | |
5389 | 3783 if (xisnan (tmp)) |
4469 | 3784 continue; |
3785 | |
5315 | 3786 double abs_tmp = real_only ? std::real (tmp) : std::abs (tmp); |
4469 | 3787 |
3788 if (abs_tmp > abs_max) | |
3789 { | |
3790 idx_i = i; | |
3791 tmp_max = tmp; | |
3792 abs_max = abs_tmp; | |
3793 } | |
3794 } | |
3795 | |
5389 | 3796 if (xisnan (tmp_max)) |
4469 | 3797 { |
3798 result.elem (j) = Complex_NaN_result; | |
4587 | 3799 idx_arg.elem (j) = 0; |
4469 | 3800 } |
891 | 3801 else |
3802 { | |
4469 | 3803 result.elem (j) = tmp_max; |
4587 | 3804 idx_arg.elem (j) = idx_i; |
891 | 3805 } |
458 | 3806 } |
3807 } | |
3808 | |
3809 return result; | |
3810 } | |
3811 | |
3812 // i/o | |
3813 | |
3504 | 3814 std::ostream& |
3815 operator << (std::ostream& os, const ComplexMatrix& a) | |
458 | 3816 { |
5275 | 3817 for (octave_idx_type i = 0; i < a.rows (); i++) |
458 | 3818 { |
5275 | 3819 for (octave_idx_type j = 0; j < a.cols (); j++) |
4130 | 3820 { |
3821 os << " "; | |
3822 octave_write_complex (os, a.elem (i, j)); | |
3823 } | |
458 | 3824 os << "\n"; |
3825 } | |
3826 return os; | |
3827 } | |
3828 | |
3504 | 3829 std::istream& |
3830 operator >> (std::istream& is, ComplexMatrix& a) | |
458 | 3831 { |
5275 | 3832 octave_idx_type nr = a.rows (); |
3833 octave_idx_type nc = a.cols (); | |
458 | 3834 |
3835 if (nr < 1 || nc < 1) | |
3504 | 3836 is.clear (std::ios::badbit); |
458 | 3837 else |
3838 { | |
3839 Complex tmp; | |
5275 | 3840 for (octave_idx_type i = 0; i < nr; i++) |
3841 for (octave_idx_type j = 0; j < nc; j++) | |
458 | 3842 { |
4130 | 3843 tmp = octave_read_complex (is); |
458 | 3844 if (is) |
3845 a.elem (i, j) = tmp; | |
3846 else | |
2993 | 3847 goto done; |
458 | 3848 } |
3849 } | |
3850 | |
2993 | 3851 done: |
3852 | |
458 | 3853 return is; |
3854 } | |
3855 | |
1819 | 3856 ComplexMatrix |
3857 Givens (const Complex& x, const Complex& y) | |
3858 { | |
3859 double cc; | |
3860 Complex cs, temp_r; | |
3861 | |
3887 | 3862 F77_FUNC (zlartg, ZLARTG) (x, y, cc, cs, temp_r); |
1819 | 3863 |
3864 ComplexMatrix g (2, 2); | |
3865 | |
3866 g.elem (0, 0) = cc; | |
3867 g.elem (1, 1) = cc; | |
3868 g.elem (0, 1) = cs; | |
3869 g.elem (1, 0) = -conj (cs); | |
3870 | |
3871 return g; | |
3872 } | |
3873 | |
3874 ComplexMatrix | |
3875 Sylvester (const ComplexMatrix& a, const ComplexMatrix& b, | |
3876 const ComplexMatrix& c) | |
3877 { | |
3878 ComplexMatrix retval; | |
3879 | |
5775 | 3880 // FIXME -- need to check that a, b, and c are all the same |
1819 | 3881 // size. |
3882 | |
3883 // Compute Schur decompositions | |
3884 | |
3885 ComplexSCHUR as (a, "U"); | |
3886 ComplexSCHUR bs (b, "U"); | |
3887 | |
3888 // Transform c to new coordinates. | |
3889 | |
3890 ComplexMatrix ua = as.unitary_matrix (); | |
3891 ComplexMatrix sch_a = as.schur_matrix (); | |
3892 | |
3893 ComplexMatrix ub = bs.unitary_matrix (); | |
3894 ComplexMatrix sch_b = bs.schur_matrix (); | |
3895 | |
3896 ComplexMatrix cx = ua.hermitian () * c * ub; | |
3897 | |
3898 // Solve the sylvester equation, back-transform, and return the | |
3899 // solution. | |
3900 | |
5275 | 3901 octave_idx_type a_nr = a.rows (); |
3902 octave_idx_type b_nr = b.rows (); | |
1819 | 3903 |
3904 double scale; | |
5275 | 3905 octave_idx_type info; |
1950 | 3906 |
3907 Complex *pa = sch_a.fortran_vec (); | |
3908 Complex *pb = sch_b.fortran_vec (); | |
3909 Complex *px = cx.fortran_vec (); | |
1819 | 3910 |
4552 | 3911 F77_XFCN (ztrsyl, ZTRSYL, (F77_CONST_CHAR_ARG2 ("N", 1), |
3912 F77_CONST_CHAR_ARG2 ("N", 1), | |
3913 1, a_nr, b_nr, pa, a_nr, pb, | |
3914 b_nr, px, a_nr, scale, info | |
3915 F77_CHAR_ARG_LEN (1) | |
3916 F77_CHAR_ARG_LEN (1))); | |
1950 | 3917 |
3918 if (f77_exception_encountered) | |
3919 (*current_liboctave_error_handler) ("unrecoverable error in ztrsyl"); | |
3920 else | |
3921 { | |
5775 | 3922 // FIXME -- check info? |
1950 | 3923 |
3924 retval = -ua * cx * ub.hermitian (); | |
3925 } | |
1819 | 3926 |
3927 return retval; | |
3928 } | |
3929 | |
2828 | 3930 ComplexMatrix |
3931 operator * (const ComplexMatrix& m, const Matrix& a) | |
3932 { | |
3933 ComplexMatrix tmp (a); | |
3934 return m * tmp; | |
3935 } | |
3936 | |
3937 ComplexMatrix | |
3938 operator * (const Matrix& m, const ComplexMatrix& a) | |
3939 { | |
3940 ComplexMatrix tmp (m); | |
3941 return tmp * a; | |
3942 } | |
3943 | |
6162 | 3944 /* Simple Dot Product, Matrix-Vector and Matrix-Matrix Unit tests |
3945 %!assert([1+i 2+i 3+i] * [ 4+i ; 5+i ; 6+i], 29+21i, 1e-14) | |
3946 %!assert([1+i 2+i ; 3+i 4+i ] * [5+i ; 6+i], [15 + 14i ; 37 + 18i], 1e-14) | |
3947 %!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) | |
3948 */ | |
3949 | |
3950 /* Test some simple identities | |
3951 %!shared M, cv, rv | |
3952 %! M = randn(10,10)+i*rand(10,10); | |
3953 %! cv = randn(10,1)+i*rand(10,1); | |
3954 %! rv = randn(1,10)+i*rand(1,10); | |
3955 %!assert([M*cv,M*cv],M*[cv,cv],1e-14) | |
3956 %!assert([rv*M;rv*M],[rv;rv]*M,1e-14) | |
3957 %!assert(2*rv*cv,[rv,rv]*[cv;cv],1e-14) | |
3958 */ | |
3959 | |
2828 | 3960 ComplexMatrix |
3961 operator * (const ComplexMatrix& m, const ComplexMatrix& a) | |
3962 { | |
3963 ComplexMatrix retval; | |
3964 | |
5275 | 3965 octave_idx_type nr = m.rows (); |
3966 octave_idx_type nc = m.cols (); | |
3967 | |
3968 octave_idx_type a_nr = a.rows (); | |
3969 octave_idx_type a_nc = a.cols (); | |
2828 | 3970 |
3971 if (nc != a_nr) | |
3972 gripe_nonconformant ("operator *", nr, nc, a_nr, a_nc); | |
3973 else | |
3974 { | |
3975 if (nr == 0 || nc == 0 || a_nc == 0) | |
3760 | 3976 retval.resize (nr, a_nc, 0.0); |
2828 | 3977 else |
3978 { | |
5275 | 3979 octave_idx_type ld = nr; |
3980 octave_idx_type lda = a.rows (); | |
2828 | 3981 |
3982 retval.resize (nr, a_nc); | |
3983 Complex *c = retval.fortran_vec (); | |
3984 | |
5983 | 3985 if (a_nc == 1) |
3986 { | |
3987 if (nr == 1) | |
3988 F77_FUNC (xzdotu, XZDOTU) (nc, m.data (), 1, a.data (), 1, *c); | |
3989 else | |
6390 | 3990 { |
3991 F77_XFCN (zgemv, ZGEMV, (F77_CONST_CHAR_ARG2 ("N", 1), | |
3992 nr, nc, 1.0, m.data (), ld, | |
3993 a.data (), 1, 0.0, c, 1 | |
3994 F77_CHAR_ARG_LEN (1))); | |
3995 | |
3996 if (f77_exception_encountered) | |
3997 (*current_liboctave_error_handler) | |
3998 ("unrecoverable error in zgemv"); | |
3999 } | |
5983 | 4000 } |
4001 else | |
6390 | 4002 { |
4003 F77_XFCN (zgemm, ZGEMM, (F77_CONST_CHAR_ARG2 ("N", 1), | |
4004 F77_CONST_CHAR_ARG2 ("N", 1), | |
4005 nr, a_nc, nc, 1.0, m.data (), | |
4006 ld, a.data (), lda, 0.0, c, nr | |
4007 F77_CHAR_ARG_LEN (1) | |
4008 F77_CHAR_ARG_LEN (1))); | |
4009 | |
4010 if (f77_exception_encountered) | |
4011 (*current_liboctave_error_handler) | |
4012 ("unrecoverable error in zgemm"); | |
4013 } | |
2828 | 4014 } |
4015 } | |
4016 | |
4017 return retval; | |
4018 } | |
4019 | |
5775 | 4020 // FIXME -- it would be nice to share code among the min/max |
4309 | 4021 // functions below. |
4022 | |
4023 #define EMPTY_RETURN_CHECK(T) \ | |
4024 if (nr == 0 || nc == 0) \ | |
4025 return T (nr, nc); | |
4026 | |
4027 ComplexMatrix | |
4028 min (const Complex& c, const ComplexMatrix& m) | |
4029 { | |
5275 | 4030 octave_idx_type nr = m.rows (); |
4031 octave_idx_type nc = m.columns (); | |
4309 | 4032 |
4033 EMPTY_RETURN_CHECK (ComplexMatrix); | |
4034 | |
4035 ComplexMatrix result (nr, nc); | |
4036 | |
5275 | 4037 for (octave_idx_type j = 0; j < nc; j++) |
4038 for (octave_idx_type i = 0; i < nr; i++) | |
4309 | 4039 { |
4040 OCTAVE_QUIT; | |
4041 result (i, j) = xmin (c, m (i, j)); | |
4042 } | |
4043 | |
4044 return result; | |
4045 } | |
4046 | |
4047 ComplexMatrix | |
4048 min (const ComplexMatrix& m, const Complex& c) | |
4049 { | |
5275 | 4050 octave_idx_type nr = m.rows (); |
4051 octave_idx_type nc = m.columns (); | |
4309 | 4052 |
4053 EMPTY_RETURN_CHECK (ComplexMatrix); | |
4054 | |
4055 ComplexMatrix result (nr, nc); | |
4056 | |
5275 | 4057 for (octave_idx_type j = 0; j < nc; j++) |
4058 for (octave_idx_type i = 0; i < nr; i++) | |
4309 | 4059 { |
4060 OCTAVE_QUIT; | |
4061 result (i, j) = xmin (m (i, j), c); | |
4062 } | |
4063 | |
4064 return result; | |
4065 } | |
4066 | |
4067 ComplexMatrix | |
4068 min (const ComplexMatrix& a, const ComplexMatrix& b) | |
4069 { | |
5275 | 4070 octave_idx_type nr = a.rows (); |
4071 octave_idx_type nc = a.columns (); | |
4309 | 4072 |
4073 if (nr != b.rows () || nc != b.columns ()) | |
4074 { | |
4075 (*current_liboctave_error_handler) | |
4076 ("two-arg min expecting args of same size"); | |
4077 return ComplexMatrix (); | |
4078 } | |
4079 | |
4080 EMPTY_RETURN_CHECK (ComplexMatrix); | |
4081 | |
4082 ComplexMatrix result (nr, nc); | |
4083 | |
5275 | 4084 for (octave_idx_type j = 0; j < nc; j++) |
4309 | 4085 { |
4086 int columns_are_real_only = 1; | |
5275 | 4087 for (octave_idx_type i = 0; i < nr; i++) |
4309 | 4088 { |
4089 OCTAVE_QUIT; | |
5315 | 4090 if (std::imag (a (i, j)) != 0.0 || std::imag (b (i, j)) != 0.0) |
4309 | 4091 { |
4092 columns_are_real_only = 0; | |
4093 break; | |
4094 } | |
4095 } | |
4096 | |
4097 if (columns_are_real_only) | |
4098 { | |
5275 | 4099 for (octave_idx_type i = 0; i < nr; i++) |
5315 | 4100 result (i, j) = xmin (std::real (a (i, j)), std::real (b (i, j))); |
4309 | 4101 } |
4102 else | |
4103 { | |
5275 | 4104 for (octave_idx_type i = 0; i < nr; i++) |
4309 | 4105 { |
4106 OCTAVE_QUIT; | |
4107 result (i, j) = xmin (a (i, j), b (i, j)); | |
4108 } | |
4109 } | |
4110 } | |
4111 | |
4112 return result; | |
4113 } | |
4114 | |
4115 ComplexMatrix | |
4116 max (const Complex& c, const ComplexMatrix& m) | |
4117 { | |
5275 | 4118 octave_idx_type nr = m.rows (); |
4119 octave_idx_type nc = m.columns (); | |
4309 | 4120 |
4121 EMPTY_RETURN_CHECK (ComplexMatrix); | |
4122 | |
4123 ComplexMatrix result (nr, nc); | |
4124 | |
5275 | 4125 for (octave_idx_type j = 0; j < nc; j++) |
4126 for (octave_idx_type i = 0; i < nr; i++) | |
4309 | 4127 { |
4128 OCTAVE_QUIT; | |
4129 result (i, j) = xmax (c, m (i, j)); | |
4130 } | |
4131 | |
4132 return result; | |
4133 } | |
4134 | |
4135 ComplexMatrix | |
4136 max (const ComplexMatrix& m, const Complex& c) | |
4137 { | |
5275 | 4138 octave_idx_type nr = m.rows (); |
4139 octave_idx_type nc = m.columns (); | |
4309 | 4140 |
4141 EMPTY_RETURN_CHECK (ComplexMatrix); | |
4142 | |
4143 ComplexMatrix result (nr, nc); | |
4144 | |
5275 | 4145 for (octave_idx_type j = 0; j < nc; j++) |
4146 for (octave_idx_type i = 0; i < nr; i++) | |
4309 | 4147 { |
4148 OCTAVE_QUIT; | |
4149 result (i, j) = xmax (m (i, j), c); | |
4150 } | |
4151 | |
4152 return result; | |
4153 } | |
4154 | |
4155 ComplexMatrix | |
4156 max (const ComplexMatrix& a, const ComplexMatrix& b) | |
4157 { | |
5275 | 4158 octave_idx_type nr = a.rows (); |
4159 octave_idx_type nc = a.columns (); | |
4309 | 4160 |
4161 if (nr != b.rows () || nc != b.columns ()) | |
4162 { | |
4163 (*current_liboctave_error_handler) | |
4164 ("two-arg max expecting args of same size"); | |
4165 return ComplexMatrix (); | |
4166 } | |
4167 | |
4168 EMPTY_RETURN_CHECK (ComplexMatrix); | |
4169 | |
4170 ComplexMatrix result (nr, nc); | |
4171 | |
5275 | 4172 for (octave_idx_type j = 0; j < nc; j++) |
4309 | 4173 { |
4174 int columns_are_real_only = 1; | |
5275 | 4175 for (octave_idx_type i = 0; i < nr; i++) |
4309 | 4176 { |
4177 OCTAVE_QUIT; | |
5315 | 4178 if (std::imag (a (i, j)) != 0.0 || std::imag (b (i, j)) != 0.0) |
4309 | 4179 { |
4180 columns_are_real_only = 0; | |
4181 break; | |
4182 } | |
4183 } | |
4184 | |
4185 if (columns_are_real_only) | |
4186 { | |
5275 | 4187 for (octave_idx_type i = 0; i < nr; i++) |
4309 | 4188 { |
4189 OCTAVE_QUIT; | |
5315 | 4190 result (i, j) = xmax (std::real (a (i, j)), std::real (b (i, j))); |
4309 | 4191 } |
4192 } | |
4193 else | |
4194 { | |
5275 | 4195 for (octave_idx_type i = 0; i < nr; i++) |
4309 | 4196 { |
4197 OCTAVE_QUIT; | |
4198 result (i, j) = xmax (a (i, j), b (i, j)); | |
4199 } | |
4200 } | |
4201 } | |
4202 | |
4203 return result; | |
4204 } | |
4205 | |
5315 | 4206 MS_CMP_OPS(ComplexMatrix, std::real, Complex, std::real) |
3504 | 4207 MS_BOOL_OPS(ComplexMatrix, Complex, 0.0) |
2870 | 4208 |
5315 | 4209 SM_CMP_OPS(Complex, std::real, ComplexMatrix, std::real) |
3504 | 4210 SM_BOOL_OPS(Complex, ComplexMatrix, 0.0) |
2870 | 4211 |
5315 | 4212 MM_CMP_OPS(ComplexMatrix, std::real, ComplexMatrix, std::real) |
3504 | 4213 MM_BOOL_OPS(ComplexMatrix, ComplexMatrix, 0.0) |
2870 | 4214 |
458 | 4215 /* |
4216 ;;; Local Variables: *** | |
4217 ;;; mode: C++ *** | |
4218 ;;; End: *** | |
4219 */ |