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