Mercurial > octave-nkf
annotate liboctave/CMatrix.cc @ 8336:9813c07ca946
make det take advantage of matrix type
author | Jaroslav Hajek <highegg@gmail.com> |
---|---|
date | Wed, 19 Nov 2008 15:26:39 +0100 |
parents | 64cf956a109c |
children | e02242c54c49 |
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 |
9813c07ca946
make det take advantage of matrix type
Jaroslav Hajek <highegg@gmail.com>
parents:
8335
diff
changeset
|
1597 if (typ == MatrixType::Lower || typ == MatrixType::Upper) |
9813c07ca946
make det take advantage of matrix type
Jaroslav Hajek <highegg@gmail.com>
parents:
8335
diff
changeset
|
1598 { |
9813c07ca946
make det take advantage of matrix type
Jaroslav Hajek <highegg@gmail.com>
parents:
8335
diff
changeset
|
1599 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
|
1600 retval *= elem (i,i); |
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 else if (typ == MatrixType::Hermitian) |
9813c07ca946
make det take advantage of matrix type
Jaroslav Hajek <highegg@gmail.com>
parents:
8335
diff
changeset
|
1603 { |
9813c07ca946
make det take advantage of matrix type
Jaroslav Hajek <highegg@gmail.com>
parents:
8335
diff
changeset
|
1604 ComplexMatrix atmp = *this; |
9813c07ca946
make det take advantage of matrix type
Jaroslav Hajek <highegg@gmail.com>
parents:
8335
diff
changeset
|
1605 Complex *tmp_data = atmp.fortran_vec (); |
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 info = 0; |
9813c07ca946
make det take advantage of matrix type
Jaroslav Hajek <highegg@gmail.com>
parents:
8335
diff
changeset
|
1608 double anorm = 0; |
9813c07ca946
make det take advantage of matrix type
Jaroslav Hajek <highegg@gmail.com>
parents:
8335
diff
changeset
|
1609 if (calc_cond) anorm = xnorm (*this, 1); |
9813c07ca946
make det take advantage of matrix type
Jaroslav Hajek <highegg@gmail.com>
parents:
8335
diff
changeset
|
1610 |
9813c07ca946
make det take advantage of matrix type
Jaroslav Hajek <highegg@gmail.com>
parents:
8335
diff
changeset
|
1611 |
9813c07ca946
make det take advantage of matrix type
Jaroslav Hajek <highegg@gmail.com>
parents:
8335
diff
changeset
|
1612 char job = 'L'; |
9813c07ca946
make det take advantage of matrix type
Jaroslav Hajek <highegg@gmail.com>
parents:
8335
diff
changeset
|
1613 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
|
1614 tmp_data, nr, info |
9813c07ca946
make det take advantage of matrix type
Jaroslav Hajek <highegg@gmail.com>
parents:
8335
diff
changeset
|
1615 F77_CHAR_ARG_LEN (1))); |
9813c07ca946
make det take advantage of matrix type
Jaroslav Hajek <highegg@gmail.com>
parents:
8335
diff
changeset
|
1616 |
9813c07ca946
make det take advantage of matrix type
Jaroslav Hajek <highegg@gmail.com>
parents:
8335
diff
changeset
|
1617 if (info != 0) |
9813c07ca946
make det take advantage of matrix type
Jaroslav Hajek <highegg@gmail.com>
parents:
8335
diff
changeset
|
1618 { |
9813c07ca946
make det take advantage of matrix type
Jaroslav Hajek <highegg@gmail.com>
parents:
8335
diff
changeset
|
1619 rcon = 0.0; |
9813c07ca946
make det take advantage of matrix type
Jaroslav Hajek <highegg@gmail.com>
parents:
8335
diff
changeset
|
1620 mattype.mark_as_unsymmetric (); |
9813c07ca946
make det take advantage of matrix type
Jaroslav Hajek <highegg@gmail.com>
parents:
8335
diff
changeset
|
1621 typ = MatrixType::Full; |
9813c07ca946
make det take advantage of matrix type
Jaroslav Hajek <highegg@gmail.com>
parents:
8335
diff
changeset
|
1622 } |
9813c07ca946
make det take advantage of matrix type
Jaroslav Hajek <highegg@gmail.com>
parents:
8335
diff
changeset
|
1623 else |
9813c07ca946
make det take advantage of matrix type
Jaroslav Hajek <highegg@gmail.com>
parents:
8335
diff
changeset
|
1624 { |
9813c07ca946
make det take advantage of matrix type
Jaroslav Hajek <highegg@gmail.com>
parents:
8335
diff
changeset
|
1625 Array<Complex> z (2 * nc); |
9813c07ca946
make det take advantage of matrix type
Jaroslav Hajek <highegg@gmail.com>
parents:
8335
diff
changeset
|
1626 Complex *pz = z.fortran_vec (); |
9813c07ca946
make det take advantage of matrix type
Jaroslav Hajek <highegg@gmail.com>
parents:
8335
diff
changeset
|
1627 Array<double> rz (nc); |
9813c07ca946
make det take advantage of matrix type
Jaroslav Hajek <highegg@gmail.com>
parents:
8335
diff
changeset
|
1628 double *prz = rz.fortran_vec (); |
9813c07ca946
make det take advantage of matrix type
Jaroslav Hajek <highegg@gmail.com>
parents:
8335
diff
changeset
|
1629 |
9813c07ca946
make det take advantage of matrix type
Jaroslav Hajek <highegg@gmail.com>
parents:
8335
diff
changeset
|
1630 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
|
1631 nr, tmp_data, nr, anorm, |
9813c07ca946
make det take advantage of matrix type
Jaroslav Hajek <highegg@gmail.com>
parents:
8335
diff
changeset
|
1632 rcon, pz, prz, info |
9813c07ca946
make det take advantage of matrix type
Jaroslav Hajek <highegg@gmail.com>
parents:
8335
diff
changeset
|
1633 F77_CHAR_ARG_LEN (1))); |
9813c07ca946
make det take advantage of matrix type
Jaroslav Hajek <highegg@gmail.com>
parents:
8335
diff
changeset
|
1634 |
9813c07ca946
make det take advantage of matrix type
Jaroslav Hajek <highegg@gmail.com>
parents:
8335
diff
changeset
|
1635 if (info != 0) |
9813c07ca946
make det take advantage of matrix type
Jaroslav Hajek <highegg@gmail.com>
parents:
8335
diff
changeset
|
1636 rcon = 0.0; |
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 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
|
1639 retval *= elem (i,i); |
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 retval = retval.square (); |
9813c07ca946
make det take advantage of matrix type
Jaroslav Hajek <highegg@gmail.com>
parents:
8335
diff
changeset
|
1642 } |
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 else if (typ != MatrixType::Full) |
9813c07ca946
make det take advantage of matrix type
Jaroslav Hajek <highegg@gmail.com>
parents:
8335
diff
changeset
|
1645 (*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
|
1646 |
9813c07ca946
make det take advantage of matrix type
Jaroslav Hajek <highegg@gmail.com>
parents:
8335
diff
changeset
|
1647 if (typ == MatrixType::Full) |
9813c07ca946
make det take advantage of matrix type
Jaroslav Hajek <highegg@gmail.com>
parents:
8335
diff
changeset
|
1648 { |
9813c07ca946
make det take advantage of matrix type
Jaroslav Hajek <highegg@gmail.com>
parents:
8335
diff
changeset
|
1649 Array<octave_idx_type> ipvt (nr); |
9813c07ca946
make det take advantage of matrix type
Jaroslav Hajek <highegg@gmail.com>
parents:
8335
diff
changeset
|
1650 octave_idx_type *pipvt = ipvt.fortran_vec (); |
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 ComplexMatrix atmp = *this; |
9813c07ca946
make det take advantage of matrix type
Jaroslav Hajek <highegg@gmail.com>
parents:
8335
diff
changeset
|
1653 Complex *tmp_data = atmp.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 info = 0; |
9813c07ca946
make det take advantage of matrix type
Jaroslav Hajek <highegg@gmail.com>
parents:
8335
diff
changeset
|
1656 |
9813c07ca946
make det take advantage of matrix type
Jaroslav Hajek <highegg@gmail.com>
parents:
8335
diff
changeset
|
1657 // 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
|
1658 double anorm = 0; |
9813c07ca946
make det take advantage of matrix type
Jaroslav Hajek <highegg@gmail.com>
parents:
8335
diff
changeset
|
1659 if (calc_cond) anorm = xnorm (*this, 1); |
9813c07ca946
make det take advantage of matrix type
Jaroslav Hajek <highegg@gmail.com>
parents:
8335
diff
changeset
|
1660 |
9813c07ca946
make det take advantage of matrix type
Jaroslav Hajek <highegg@gmail.com>
parents:
8335
diff
changeset
|
1661 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
|
1662 |
9813c07ca946
make det take advantage of matrix type
Jaroslav Hajek <highegg@gmail.com>
parents:
8335
diff
changeset
|
1663 // 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
|
1664 rcon = 0.0; |
9813c07ca946
make det take advantage of matrix type
Jaroslav Hajek <highegg@gmail.com>
parents:
8335
diff
changeset
|
1665 if (info != 0) |
9813c07ca946
make det take advantage of matrix type
Jaroslav Hajek <highegg@gmail.com>
parents:
8335
diff
changeset
|
1666 { |
9813c07ca946
make det take advantage of matrix type
Jaroslav Hajek <highegg@gmail.com>
parents:
8335
diff
changeset
|
1667 info = -1; |
9813c07ca946
make det take advantage of matrix type
Jaroslav Hajek <highegg@gmail.com>
parents:
8335
diff
changeset
|
1668 retval = ComplexDET (); |
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 else |
9813c07ca946
make det take advantage of matrix type
Jaroslav Hajek <highegg@gmail.com>
parents:
8335
diff
changeset
|
1671 { |
9813c07ca946
make det take advantage of matrix type
Jaroslav Hajek <highegg@gmail.com>
parents:
8335
diff
changeset
|
1672 if (calc_cond) |
9813c07ca946
make det take advantage of matrix type
Jaroslav Hajek <highegg@gmail.com>
parents:
8335
diff
changeset
|
1673 { |
9813c07ca946
make det take advantage of matrix type
Jaroslav Hajek <highegg@gmail.com>
parents:
8335
diff
changeset
|
1674 // 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
|
1675 char job = '1'; |
9813c07ca946
make det take advantage of matrix type
Jaroslav Hajek <highegg@gmail.com>
parents:
8335
diff
changeset
|
1676 Array<Complex> z (2 * nc); |
9813c07ca946
make det take advantage of matrix type
Jaroslav Hajek <highegg@gmail.com>
parents:
8335
diff
changeset
|
1677 Complex *pz = z.fortran_vec (); |
9813c07ca946
make det take advantage of matrix type
Jaroslav Hajek <highegg@gmail.com>
parents:
8335
diff
changeset
|
1678 Array<double> rz (2 * nc); |
9813c07ca946
make det take advantage of matrix type
Jaroslav Hajek <highegg@gmail.com>
parents:
8335
diff
changeset
|
1679 double *prz = rz.fortran_vec (); |
9813c07ca946
make det take advantage of matrix type
Jaroslav Hajek <highegg@gmail.com>
parents:
8335
diff
changeset
|
1680 |
9813c07ca946
make det take advantage of matrix type
Jaroslav Hajek <highegg@gmail.com>
parents:
8335
diff
changeset
|
1681 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
|
1682 nc, tmp_data, nr, anorm, |
9813c07ca946
make det take advantage of matrix type
Jaroslav Hajek <highegg@gmail.com>
parents:
8335
diff
changeset
|
1683 rcon, pz, prz, info |
9813c07ca946
make det take advantage of matrix type
Jaroslav Hajek <highegg@gmail.com>
parents:
8335
diff
changeset
|
1684 F77_CHAR_ARG_LEN (1))); |
8335 | 1685 } |
8336
9813c07ca946
make det take advantage of matrix type
Jaroslav Hajek <highegg@gmail.com>
parents:
8335
diff
changeset
|
1686 |
9813c07ca946
make det take advantage of matrix type
Jaroslav Hajek <highegg@gmail.com>
parents:
8335
diff
changeset
|
1687 if (info != 0) |
9813c07ca946
make det take advantage of matrix type
Jaroslav Hajek <highegg@gmail.com>
parents:
8335
diff
changeset
|
1688 { |
9813c07ca946
make det take advantage of matrix type
Jaroslav Hajek <highegg@gmail.com>
parents:
8335
diff
changeset
|
1689 info = -1; |
9813c07ca946
make det take advantage of matrix type
Jaroslav Hajek <highegg@gmail.com>
parents:
8335
diff
changeset
|
1690 retval = ComplexDET (); |
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 else |
9813c07ca946
make det take advantage of matrix type
Jaroslav Hajek <highegg@gmail.com>
parents:
8335
diff
changeset
|
1693 { |
9813c07ca946
make det take advantage of matrix type
Jaroslav Hajek <highegg@gmail.com>
parents:
8335
diff
changeset
|
1694 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
|
1695 { |
9813c07ca946
make det take advantage of matrix type
Jaroslav Hajek <highegg@gmail.com>
parents:
8335
diff
changeset
|
1696 Complex c = atmp(i,i); |
9813c07ca946
make det take advantage of matrix type
Jaroslav Hajek <highegg@gmail.com>
parents:
8335
diff
changeset
|
1697 retval *= (ipvt(i) != (i+1)) ? -c : c; |
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 } |
9813c07ca946
make det take advantage of matrix type
Jaroslav Hajek <highegg@gmail.com>
parents:
8335
diff
changeset
|
1700 } |
9813c07ca946
make det take advantage of matrix type
Jaroslav Hajek <highegg@gmail.com>
parents:
8335
diff
changeset
|
1701 } |
458 | 1702 } |
8336
9813c07ca946
make det take advantage of matrix type
Jaroslav Hajek <highegg@gmail.com>
parents:
8335
diff
changeset
|
1703 |
458 | 1704 return retval; |
1705 } | |
1706 | |
7788 | 1707 double |
1708 ComplexMatrix::rcond (void) const | |
1709 { | |
1710 MatrixType mattype (*this); | |
1711 return rcond (mattype); | |
1712 } | |
1713 | |
1714 double | |
1715 ComplexMatrix::rcond (MatrixType &mattype) const | |
1716 { | |
1717 double rcon; | |
1718 octave_idx_type nr = rows (); | |
1719 octave_idx_type nc = cols (); | |
1720 | |
1721 if (nr != nc) | |
1722 (*current_liboctave_error_handler) ("matrix must be square"); | |
1723 else if (nr == 0 || nc == 0) | |
1724 rcon = octave_Inf; | |
1725 else | |
1726 { | |
1727 int typ = mattype.type (); | |
1728 | |
1729 if (typ == MatrixType::Unknown) | |
1730 typ = mattype.type (*this); | |
1731 | |
1732 // Only calculate the condition number for LU/Cholesky | |
1733 if (typ == MatrixType::Upper) | |
1734 { | |
1735 const Complex *tmp_data = fortran_vec (); | |
1736 octave_idx_type info = 0; | |
1737 char norm = '1'; | |
1738 char uplo = 'U'; | |
1739 char dia = 'N'; | |
1740 | |
1741 Array<Complex> z (2 * nc); | |
1742 Complex *pz = z.fortran_vec (); | |
1743 Array<double> rz (nc); | |
1744 double *prz = rz.fortran_vec (); | |
1745 | |
1746 F77_XFCN (ztrcon, ZTRCON, (F77_CONST_CHAR_ARG2 (&norm, 1), | |
1747 F77_CONST_CHAR_ARG2 (&uplo, 1), | |
1748 F77_CONST_CHAR_ARG2 (&dia, 1), | |
1749 nr, tmp_data, nr, rcon, | |
1750 pz, prz, info | |
1751 F77_CHAR_ARG_LEN (1) | |
1752 F77_CHAR_ARG_LEN (1) | |
1753 F77_CHAR_ARG_LEN (1))); | |
1754 | |
1755 if (info != 0) | |
1756 rcon = 0; | |
1757 } | |
1758 else if (typ == MatrixType::Permuted_Upper) | |
1759 (*current_liboctave_error_handler) | |
1760 ("permuted triangular matrix not implemented"); | |
1761 else if (typ == MatrixType::Lower) | |
1762 { | |
1763 const Complex *tmp_data = fortran_vec (); | |
1764 octave_idx_type info = 0; | |
1765 char norm = '1'; | |
1766 char uplo = 'L'; | |
1767 char dia = 'N'; | |
1768 | |
1769 Array<Complex> z (2 * nc); | |
1770 Complex *pz = z.fortran_vec (); | |
1771 Array<double> rz (nc); | |
1772 double *prz = rz.fortran_vec (); | |
1773 | |
1774 F77_XFCN (ztrcon, ZTRCON, (F77_CONST_CHAR_ARG2 (&norm, 1), | |
1775 F77_CONST_CHAR_ARG2 (&uplo, 1), | |
1776 F77_CONST_CHAR_ARG2 (&dia, 1), | |
1777 nr, tmp_data, nr, rcon, | |
1778 pz, prz, info | |
1779 F77_CHAR_ARG_LEN (1) | |
1780 F77_CHAR_ARG_LEN (1) | |
1781 F77_CHAR_ARG_LEN (1))); | |
1782 | |
1783 if (info != 0) | |
1784 rcon = 0.0; | |
1785 } | |
1786 else if (typ == MatrixType::Permuted_Lower) | |
1787 (*current_liboctave_error_handler) | |
1788 ("permuted triangular matrix not implemented"); | |
1789 else if (typ == MatrixType::Full || typ == MatrixType::Hermitian) | |
1790 { | |
1791 double anorm = -1.0; | |
1792 ComplexMatrix atmp = *this; | |
1793 Complex *tmp_data = atmp.fortran_vec (); | |
1794 | |
1795 if (typ == MatrixType::Hermitian) | |
1796 { | |
1797 octave_idx_type info = 0; | |
1798 char job = 'L'; | |
1799 anorm = atmp.abs().sum(). | |
1800 row(static_cast<octave_idx_type>(0)).max(); | |
1801 | |
1802 F77_XFCN (zpotrf, ZPOTRF, (F77_CONST_CHAR_ARG2 (&job, 1), nr, | |
1803 tmp_data, nr, info | |
1804 F77_CHAR_ARG_LEN (1))); | |
1805 | |
1806 if (info != 0) | |
1807 { | |
1808 rcon = 0.0; | |
1809 | |
1810 mattype.mark_as_unsymmetric (); | |
1811 typ = MatrixType::Full; | |
1812 } | |
1813 else | |
1814 { | |
1815 Array<Complex> z (2 * nc); | |
1816 Complex *pz = z.fortran_vec (); | |
1817 Array<double> rz (nc); | |
1818 double *prz = rz.fortran_vec (); | |
1819 | |
1820 F77_XFCN (zpocon, ZPOCON, (F77_CONST_CHAR_ARG2 (&job, 1), | |
1821 nr, tmp_data, nr, anorm, | |
1822 rcon, pz, prz, info | |
1823 F77_CHAR_ARG_LEN (1))); | |
1824 | |
1825 if (info != 0) | |
1826 rcon = 0.0; | |
1827 } | |
1828 } | |
1829 | |
1830 | |
1831 if (typ == MatrixType::Full) | |
1832 { | |
1833 octave_idx_type info = 0; | |
1834 | |
1835 Array<octave_idx_type> ipvt (nr); | |
1836 octave_idx_type *pipvt = ipvt.fortran_vec (); | |
1837 | |
1838 if(anorm < 0.) | |
1839 anorm = atmp.abs().sum(). | |
1840 row(static_cast<octave_idx_type>(0)).max(); | |
1841 | |
1842 Array<Complex> z (2 * nc); | |
1843 Complex *pz = z.fortran_vec (); | |
1844 Array<double> rz (2 * nc); | |
1845 double *prz = rz.fortran_vec (); | |
1846 | |
1847 F77_XFCN (zgetrf, ZGETRF, (nr, nr, tmp_data, nr, pipvt, info)); | |
1848 | |
1849 if (info != 0) | |
1850 { | |
1851 rcon = 0.0; | |
1852 mattype.mark_as_rectangular (); | |
1853 } | |
1854 else | |
1855 { | |
1856 char job = '1'; | |
1857 F77_XFCN (zgecon, ZGECON, (F77_CONST_CHAR_ARG2 (&job, 1), | |
1858 nc, tmp_data, nr, anorm, | |
1859 rcon, pz, prz, info | |
1860 F77_CHAR_ARG_LEN (1))); | |
1861 | |
1862 if (info != 0) | |
1863 rcon = 0.0; | |
1864 } | |
1865 } | |
1866 } | |
1867 else | |
1868 rcon = 0.0; | |
1869 } | |
1870 | |
1871 return rcon; | |
1872 } | |
1873 | |
458 | 1874 ComplexMatrix |
5785 | 1875 ComplexMatrix::utsolve (MatrixType &mattype, const ComplexMatrix& b, |
7788 | 1876 octave_idx_type& info, double& rcon, |
5785 | 1877 solve_singularity_handler sing_handler, |
1878 bool calc_cond) const | |
1879 { | |
1880 ComplexMatrix retval; | |
1881 | |
1882 octave_idx_type nr = rows (); | |
1883 octave_idx_type nc = cols (); | |
1884 | |
6924 | 1885 if (nr != b.rows ()) |
5785 | 1886 (*current_liboctave_error_handler) |
1887 ("matrix dimension mismatch solution of linear equations"); | |
6924 | 1888 else if (nr == 0 || nc == 0 || b.cols () == 0) |
1889 retval = ComplexMatrix (nc, b.cols (), Complex (0.0, 0.0)); | |
5785 | 1890 else |
1891 { | |
1892 volatile int typ = mattype.type (); | |
1893 | |
1894 if (typ == MatrixType::Permuted_Upper || | |
1895 typ == MatrixType::Upper) | |
1896 { | |
1897 octave_idx_type b_nc = b.cols (); | |
7788 | 1898 rcon = 1.; |
5785 | 1899 info = 0; |
1900 | |
1901 if (typ == MatrixType::Permuted_Upper) | |
1902 { | |
1903 (*current_liboctave_error_handler) | |
6390 | 1904 ("permuted triangular matrix not implemented"); |
5785 | 1905 } |
1906 else | |
1907 { | |
1908 const Complex *tmp_data = fortran_vec (); | |
1909 | |
1910 if (calc_cond) | |
1911 { | |
1912 char norm = '1'; | |
1913 char uplo = 'U'; | |
1914 char dia = 'N'; | |
1915 | |
1916 Array<Complex> z (2 * nc); | |
1917 Complex *pz = z.fortran_vec (); | |
1918 Array<double> rz (nc); | |
1919 double *prz = rz.fortran_vec (); | |
1920 | |
1921 F77_XFCN (ztrcon, ZTRCON, (F77_CONST_CHAR_ARG2 (&norm, 1), | |
1922 F77_CONST_CHAR_ARG2 (&uplo, 1), | |
1923 F77_CONST_CHAR_ARG2 (&dia, 1), | |
7788 | 1924 nr, tmp_data, nr, rcon, |
5785 | 1925 pz, prz, info |
1926 F77_CHAR_ARG_LEN (1) | |
1927 F77_CHAR_ARG_LEN (1) | |
1928 F77_CHAR_ARG_LEN (1))); | |
1929 | |
1930 if (info != 0) | |
1931 info = -2; | |
1932 | |
7788 | 1933 volatile double rcond_plus_one = rcon + 1.0; |
1934 | |
1935 if (rcond_plus_one == 1.0 || xisnan (rcon)) | |
5785 | 1936 { |
1937 info = -2; | |
1938 | |
1939 if (sing_handler) | |
7788 | 1940 sing_handler (rcon); |
5785 | 1941 else |
1942 (*current_liboctave_error_handler) | |
1943 ("matrix singular to machine precision, rcond = %g", | |
7788 | 1944 rcon); |
5785 | 1945 } |
1946 } | |
1947 | |
1948 if (info == 0) | |
1949 { | |
1950 retval = b; | |
1951 Complex *result = retval.fortran_vec (); | |
1952 | |
1953 char uplo = 'U'; | |
1954 char trans = 'N'; | |
1955 char dia = 'N'; | |
1956 | |
1957 F77_XFCN (ztrtrs, ZTRTRS, (F77_CONST_CHAR_ARG2 (&uplo, 1), | |
1958 F77_CONST_CHAR_ARG2 (&trans, 1), | |
1959 F77_CONST_CHAR_ARG2 (&dia, 1), | |
1960 nr, b_nc, tmp_data, nr, | |
1961 result, nr, info | |
1962 F77_CHAR_ARG_LEN (1) | |
1963 F77_CHAR_ARG_LEN (1) | |
1964 F77_CHAR_ARG_LEN (1))); | |
1965 } | |
1966 } | |
1967 } | |
1968 else | |
1969 (*current_liboctave_error_handler) ("incorrect matrix type"); | |
1970 } | |
1971 | |
1972 return retval; | |
1973 } | |
1974 | |
1975 ComplexMatrix | |
1976 ComplexMatrix::ltsolve (MatrixType &mattype, const ComplexMatrix& b, | |
7788 | 1977 octave_idx_type& info, double& rcon, |
5785 | 1978 solve_singularity_handler sing_handler, |
1979 bool calc_cond) const | |
1980 { | |
1981 ComplexMatrix retval; | |
1982 | |
1983 octave_idx_type nr = rows (); | |
1984 octave_idx_type nc = cols (); | |
1985 | |
6924 | 1986 if (nr != b.rows ()) |
5785 | 1987 (*current_liboctave_error_handler) |
1988 ("matrix dimension mismatch solution of linear equations"); | |
6924 | 1989 else if (nr == 0 || nc == 0 || b.cols () == 0) |
1990 retval = ComplexMatrix (nc, b.cols (), Complex (0.0, 0.0)); | |
5785 | 1991 else |
1992 { | |
1993 volatile int typ = mattype.type (); | |
1994 | |
1995 if (typ == MatrixType::Permuted_Lower || | |
1996 typ == MatrixType::Lower) | |
1997 { | |
1998 octave_idx_type b_nc = b.cols (); | |
7788 | 1999 rcon = 1.; |
5785 | 2000 info = 0; |
2001 | |
2002 if (typ == MatrixType::Permuted_Lower) | |
2003 { | |
2004 (*current_liboctave_error_handler) | |
6390 | 2005 ("permuted triangular matrix not implemented"); |
5785 | 2006 } |
2007 else | |
2008 { | |
2009 const Complex *tmp_data = fortran_vec (); | |
2010 | |
2011 if (calc_cond) | |
2012 { | |
2013 char norm = '1'; | |
2014 char uplo = 'L'; | |
2015 char dia = 'N'; | |
2016 | |
2017 Array<Complex> z (2 * nc); | |
2018 Complex *pz = z.fortran_vec (); | |
2019 Array<double> rz (nc); | |
2020 double *prz = rz.fortran_vec (); | |
2021 | |
2022 F77_XFCN (ztrcon, ZTRCON, (F77_CONST_CHAR_ARG2 (&norm, 1), | |
2023 F77_CONST_CHAR_ARG2 (&uplo, 1), | |
2024 F77_CONST_CHAR_ARG2 (&dia, 1), | |
7788 | 2025 nr, tmp_data, nr, rcon, |
5785 | 2026 pz, prz, info |
2027 F77_CHAR_ARG_LEN (1) | |
2028 F77_CHAR_ARG_LEN (1) | |
2029 F77_CHAR_ARG_LEN (1))); | |
2030 | |
2031 if (info != 0) | |
2032 info = -2; | |
2033 | |
7788 | 2034 volatile double rcond_plus_one = rcon + 1.0; |
2035 | |
2036 if (rcond_plus_one == 1.0 || xisnan (rcon)) | |
5785 | 2037 { |
2038 info = -2; | |
2039 | |
2040 if (sing_handler) | |
7788 | 2041 sing_handler (rcon); |
5785 | 2042 else |
2043 (*current_liboctave_error_handler) | |
2044 ("matrix singular to machine precision, rcond = %g", | |
7788 | 2045 rcon); |
5785 | 2046 } |
2047 } | |
2048 | |
2049 if (info == 0) | |
2050 { | |
2051 retval = b; | |
2052 Complex *result = retval.fortran_vec (); | |
2053 | |
2054 char uplo = 'L'; | |
2055 char trans = 'N'; | |
2056 char dia = 'N'; | |
2057 | |
2058 F77_XFCN (ztrtrs, ZTRTRS, (F77_CONST_CHAR_ARG2 (&uplo, 1), | |
2059 F77_CONST_CHAR_ARG2 (&trans, 1), | |
2060 F77_CONST_CHAR_ARG2 (&dia, 1), | |
2061 nr, b_nc, tmp_data, nr, | |
2062 result, nr, info | |
2063 F77_CHAR_ARG_LEN (1) | |
2064 F77_CHAR_ARG_LEN (1) | |
2065 F77_CHAR_ARG_LEN (1))); | |
2066 } | |
2067 } | |
2068 } | |
2069 else | |
2070 (*current_liboctave_error_handler) ("incorrect matrix type"); | |
2071 } | |
2072 | |
2073 return retval; | |
2074 } | |
2075 | |
2076 ComplexMatrix | |
2077 ComplexMatrix::fsolve (MatrixType &mattype, const ComplexMatrix& b, | |
7788 | 2078 octave_idx_type& info, double& rcon, |
5785 | 2079 solve_singularity_handler sing_handler, |
2080 bool calc_cond) const | |
2081 { | |
2082 ComplexMatrix retval; | |
2083 | |
2084 octave_idx_type nr = rows (); | |
2085 octave_idx_type nc = cols (); | |
2086 | |
6924 | 2087 |
2088 if (nr != nc || nr != b.rows ()) | |
5785 | 2089 (*current_liboctave_error_handler) |
6924 | 2090 ("matrix dimension mismatch solution of linear equations"); |
2091 else if (nr == 0 || b.cols () == 0) | |
2092 retval = ComplexMatrix (nc, b.cols (), Complex (0.0, 0.0)); | |
5785 | 2093 else |
2094 { | |
2095 volatile int typ = mattype.type (); | |
2096 | |
2097 // Calculate the norm of the matrix, for later use. | |
2098 double anorm = -1.; | |
2099 | |
2100 if (typ == MatrixType::Hermitian) | |
2101 { | |
2102 info = 0; | |
2103 char job = 'L'; | |
2104 ComplexMatrix atmp = *this; | |
2105 Complex *tmp_data = atmp.fortran_vec (); | |
2106 anorm = atmp.abs().sum().row(static_cast<octave_idx_type>(0)).max(); | |
2107 | |
2108 F77_XFCN (zpotrf, ZPOTRF, (F77_CONST_CHAR_ARG2 (&job, 1), nr, | |
2109 tmp_data, nr, info | |
2110 F77_CHAR_ARG_LEN (1))); | |
2111 | |
7482
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2112 // Throw-away extra info LAPACK gives so as to not change output. |
7788 | 2113 rcon = 0.0; |
7482
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2114 if (info != 0) |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2115 { |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2116 info = -2; |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2117 |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2118 mattype.mark_as_unsymmetric (); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2119 typ = MatrixType::Full; |
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 else |
5785 | 2122 { |
7482
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2123 if (calc_cond) |
5785 | 2124 { |
7482
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2125 Array<Complex> z (2 * nc); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2126 Complex *pz = z.fortran_vec (); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2127 Array<double> rz (nc); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2128 double *prz = rz.fortran_vec (); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2129 |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2130 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
|
2131 nr, tmp_data, nr, anorm, |
7788 | 2132 rcon, pz, prz, info |
7482
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2133 F77_CHAR_ARG_LEN (1))); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2134 |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2135 if (info != 0) |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2136 info = -2; |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2137 |
7788 | 2138 volatile double rcond_plus_one = rcon + 1.0; |
2139 | |
2140 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
|
2141 { |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2142 info = -2; |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2143 |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2144 if (sing_handler) |
7788 | 2145 sing_handler (rcon); |
7482
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2146 else |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2147 (*current_liboctave_error_handler) |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2148 ("matrix singular to machine precision, rcond = %g", |
7788 | 2149 rcon); |
7482
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2150 } |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2151 } |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2152 |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2153 if (info == 0) |
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 retval = b; |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2156 Complex *result = retval.fortran_vec (); |
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 octave_idx_type b_nc = b.cols (); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2159 |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2160 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
|
2161 nr, b_nc, tmp_data, nr, |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2162 result, b.rows(), info |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2163 F77_CHAR_ARG_LEN (1))); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2164 } |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2165 else |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2166 { |
5785 | 2167 mattype.mark_as_unsymmetric (); |
2168 typ = MatrixType::Full; | |
2169 } | |
2170 } | |
2171 } | |
2172 | |
2173 if (typ == MatrixType::Full) | |
2174 { | |
2175 info = 0; | |
2176 | |
2177 Array<octave_idx_type> ipvt (nr); | |
2178 octave_idx_type *pipvt = ipvt.fortran_vec (); | |
2179 | |
2180 ComplexMatrix atmp = *this; | |
2181 Complex *tmp_data = atmp.fortran_vec (); | |
2182 | |
2183 Array<Complex> z (2 * nc); | |
2184 Complex *pz = z.fortran_vec (); | |
2185 Array<double> rz (2 * nc); | |
2186 double *prz = rz.fortran_vec (); | |
2187 | |
2188 // Calculate the norm of the matrix, for later use. | |
2189 if (anorm < 0.) | |
2190 anorm = atmp.abs().sum().row(static_cast<octave_idx_type>(0)).max(); | |
2191 | |
2192 F77_XFCN (zgetrf, ZGETRF, (nr, nr, tmp_data, nr, pipvt, info)); | |
2193 | |
7482
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2194 // Throw-away extra info LAPACK gives so as to not change output. |
7788 | 2195 rcon = 0.0; |
7482
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2196 if (info != 0) |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2197 { |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2198 info = -2; |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2199 |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2200 if (sing_handler) |
7788 | 2201 sing_handler (rcon); |
7482
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2202 else |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2203 (*current_liboctave_error_handler) |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2204 ("matrix singular to machine precision"); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2205 |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2206 mattype.mark_as_rectangular (); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2207 } |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2208 else |
5785 | 2209 { |
7482
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2210 if (calc_cond) |
5785 | 2211 { |
7482
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2212 // Now calculate the condition number for |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2213 // non-singular matrix. |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2214 char job = '1'; |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2215 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
|
2216 nc, tmp_data, nr, anorm, |
7788 | 2217 rcon, pz, prz, info |
7482
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2218 F77_CHAR_ARG_LEN (1))); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2219 |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2220 if (info != 0) |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2221 info = -2; |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2222 |
7788 | 2223 volatile double rcond_plus_one = rcon + 1.0; |
2224 | |
2225 if (rcond_plus_one == 1.0 || xisnan (rcon)) | |
5785 | 2226 { |
7482
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2227 info = -2; |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2228 |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2229 if (sing_handler) |
7788 | 2230 sing_handler (rcon); |
7482
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2231 else |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2232 (*current_liboctave_error_handler) |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2233 ("matrix singular to machine precision, rcond = %g", |
7788 | 2234 rcon); |
5785 | 2235 } |
2236 } | |
7482
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2237 |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2238 if (info == 0) |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2239 { |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2240 retval = b; |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2241 Complex *result = retval.fortran_vec (); |
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 octave_idx_type b_nc = b.cols (); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2244 |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2245 char job = 'N'; |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2246 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
|
2247 nr, b_nc, tmp_data, nr, |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2248 pipvt, result, b.rows(), info |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2249 F77_CHAR_ARG_LEN (1))); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2250 } |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2251 else |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2252 mattype.mark_as_rectangular (); |
5785 | 2253 } |
2254 } | |
2255 } | |
2256 | |
2257 return retval; | |
2258 } | |
2259 | |
2260 ComplexMatrix | |
2261 ComplexMatrix::solve (MatrixType &typ, const Matrix& b) const | |
2262 { | |
2263 octave_idx_type info; | |
7788 | 2264 double rcon; |
2265 return solve (typ, b, info, rcon, 0); | |
5785 | 2266 } |
2267 | |
2268 ComplexMatrix | |
2269 ComplexMatrix::solve (MatrixType &typ, const Matrix& b, | |
2270 octave_idx_type& info) const | |
2271 { | |
7788 | 2272 double rcon; |
2273 return solve (typ, b, info, rcon, 0); | |
5785 | 2274 } |
2275 | |
2276 ComplexMatrix | |
2277 ComplexMatrix::solve (MatrixType &typ, const Matrix& b, octave_idx_type& info, | |
7788 | 2278 double& rcon) const |
5785 | 2279 { |
7788 | 2280 return solve (typ, b, info, rcon, 0); |
5785 | 2281 } |
2282 | |
2283 ComplexMatrix | |
2284 ComplexMatrix::solve (MatrixType &typ, const Matrix& b, octave_idx_type& info, | |
7788 | 2285 double& rcon, solve_singularity_handler sing_handler, |
5785 | 2286 bool singular_fallback) const |
2287 { | |
2288 ComplexMatrix tmp (b); | |
7788 | 2289 return solve (typ, tmp, info, rcon, sing_handler, singular_fallback); |
5785 | 2290 } |
2291 | |
2292 ComplexMatrix | |
2293 ComplexMatrix::solve (MatrixType &typ, const ComplexMatrix& b) const | |
2294 { | |
2295 octave_idx_type info; | |
7788 | 2296 double rcon; |
2297 return solve (typ, b, info, rcon, 0); | |
5785 | 2298 } |
2299 | |
2300 ComplexMatrix | |
2301 ComplexMatrix::solve (MatrixType &typ, const ComplexMatrix& b, | |
2302 octave_idx_type& info) const | |
2303 { | |
7788 | 2304 double rcon; |
2305 return solve (typ, b, info, rcon, 0); | |
5785 | 2306 } |
2307 | |
2308 ComplexMatrix | |
2309 ComplexMatrix::solve (MatrixType &typ, const ComplexMatrix& b, | |
7788 | 2310 octave_idx_type& info, double& rcon) const |
5785 | 2311 { |
7788 | 2312 return solve (typ, b, info, rcon, 0); |
5785 | 2313 } |
2314 | |
2315 ComplexMatrix | |
2316 ComplexMatrix::solve (MatrixType &mattype, const ComplexMatrix& b, | |
7788 | 2317 octave_idx_type& info, double& rcon, |
5785 | 2318 solve_singularity_handler sing_handler, |
2319 bool singular_fallback) const | |
2320 { | |
2321 ComplexMatrix retval; | |
2322 int typ = mattype.type (); | |
2323 | |
2324 if (typ == MatrixType::Unknown) | |
2325 typ = mattype.type (*this); | |
2326 | |
2327 // Only calculate the condition number for LU/Cholesky | |
2328 if (typ == MatrixType::Upper || typ == MatrixType::Permuted_Upper) | |
7788 | 2329 retval = utsolve (mattype, b, info, rcon, sing_handler, false); |
5785 | 2330 else if (typ == MatrixType::Lower || typ == MatrixType::Permuted_Lower) |
7788 | 2331 retval = ltsolve (mattype, b, info, rcon, sing_handler, false); |
5785 | 2332 else if (typ == MatrixType::Full || typ == MatrixType::Hermitian) |
7788 | 2333 retval = fsolve (mattype, b, info, rcon, sing_handler, true); |
5785 | 2334 else if (typ != MatrixType::Rectangular) |
2335 { | |
2336 (*current_liboctave_error_handler) ("unknown matrix type"); | |
2337 return ComplexMatrix (); | |
2338 } | |
2339 | |
2340 // Rectangular or one of the above solvers flags a singular matrix | |
2341 if (singular_fallback && mattype.type () == MatrixType::Rectangular) | |
2342 { | |
2343 octave_idx_type rank; | |
7788 | 2344 retval = lssolve (b, info, rank, rcon); |
5785 | 2345 } |
2346 | |
2347 return retval; | |
2348 } | |
2349 | |
2350 ComplexColumnVector | |
2351 ComplexMatrix::solve (MatrixType &typ, const ColumnVector& b) const | |
2352 { | |
2353 octave_idx_type info; | |
7788 | 2354 double rcon; |
2355 return solve (typ, ComplexColumnVector (b), info, rcon, 0); | |
5785 | 2356 } |
2357 | |
2358 ComplexColumnVector | |
2359 ComplexMatrix::solve (MatrixType &typ, const ColumnVector& b, | |
2360 octave_idx_type& info) const | |
2361 { | |
7788 | 2362 double rcon; |
2363 return solve (typ, ComplexColumnVector (b), info, rcon, 0); | |
5785 | 2364 } |
2365 | |
2366 ComplexColumnVector | |
2367 ComplexMatrix::solve (MatrixType &typ, const ColumnVector& b, | |
7788 | 2368 octave_idx_type& info, double& rcon) const |
5785 | 2369 { |
7788 | 2370 return solve (typ, ComplexColumnVector (b), info, rcon, 0); |
5785 | 2371 } |
2372 | |
2373 ComplexColumnVector | |
2374 ComplexMatrix::solve (MatrixType &typ, const ColumnVector& b, | |
7788 | 2375 octave_idx_type& info, double& rcon, |
5785 | 2376 solve_singularity_handler sing_handler) const |
2377 { | |
7788 | 2378 return solve (typ, ComplexColumnVector (b), info, rcon, sing_handler); |
5785 | 2379 } |
2380 | |
2381 ComplexColumnVector | |
2382 ComplexMatrix::solve (MatrixType &typ, const ComplexColumnVector& b) const | |
2383 { | |
2384 octave_idx_type info; | |
7788 | 2385 double rcon; |
2386 return solve (typ, b, info, rcon, 0); | |
5785 | 2387 } |
2388 | |
2389 ComplexColumnVector | |
2390 ComplexMatrix::solve (MatrixType &typ, const ComplexColumnVector& b, | |
2391 octave_idx_type& info) const | |
2392 { | |
7788 | 2393 double rcon; |
2394 return solve (typ, b, info, rcon, 0); | |
5785 | 2395 } |
2396 | |
2397 ComplexColumnVector | |
2398 ComplexMatrix::solve (MatrixType &typ, const ComplexColumnVector& b, | |
7788 | 2399 octave_idx_type& info, double& rcon) const |
5785 | 2400 { |
7788 | 2401 return solve (typ, b, info, rcon, 0); |
5785 | 2402 } |
2403 | |
2404 ComplexColumnVector | |
2405 ComplexMatrix::solve (MatrixType &typ, const ComplexColumnVector& b, | |
7788 | 2406 octave_idx_type& info, double& rcon, |
5785 | 2407 solve_singularity_handler sing_handler) const |
2408 { | |
2409 | |
2410 ComplexMatrix tmp (b); | |
7788 | 2411 return solve (typ, tmp, info, rcon, sing_handler).column(static_cast<octave_idx_type> (0)); |
5785 | 2412 } |
2413 | |
2414 ComplexMatrix | |
458 | 2415 ComplexMatrix::solve (const Matrix& b) const |
2416 { | |
5275 | 2417 octave_idx_type info; |
7788 | 2418 double rcon; |
2419 return solve (b, info, rcon, 0); | |
458 | 2420 } |
2421 | |
2422 ComplexMatrix | |
5275 | 2423 ComplexMatrix::solve (const Matrix& b, octave_idx_type& info) const |
458 | 2424 { |
7788 | 2425 double rcon; |
2426 return solve (b, info, rcon, 0); | |
458 | 2427 } |
2428 | |
2429 ComplexMatrix | |
7788 | 2430 ComplexMatrix::solve (const Matrix& b, octave_idx_type& info, double& rcon) const |
458 | 2431 { |
7788 | 2432 return solve (b, info, rcon, 0); |
3480 | 2433 } |
2434 | |
2435 ComplexMatrix | |
7788 | 2436 ComplexMatrix::solve (const Matrix& b, octave_idx_type& info, double& rcon, |
3480 | 2437 solve_singularity_handler sing_handler) const |
2438 { | |
458 | 2439 ComplexMatrix tmp (b); |
7788 | 2440 return solve (tmp, info, rcon, sing_handler); |
458 | 2441 } |
2442 | |
2443 ComplexMatrix | |
2444 ComplexMatrix::solve (const ComplexMatrix& b) const | |
2445 { | |
5275 | 2446 octave_idx_type info; |
7788 | 2447 double rcon; |
2448 return solve (b, info, rcon, 0); | |
458 | 2449 } |
2450 | |
2451 ComplexMatrix | |
5275 | 2452 ComplexMatrix::solve (const ComplexMatrix& b, octave_idx_type& info) const |
458 | 2453 { |
7788 | 2454 double rcon; |
2455 return solve (b, info, rcon, 0); | |
458 | 2456 } |
3480 | 2457 |
458 | 2458 ComplexMatrix |
7788 | 2459 ComplexMatrix::solve (const ComplexMatrix& b, octave_idx_type& info, double& rcon) const |
458 | 2460 { |
7788 | 2461 return solve (b, info, rcon, 0); |
3480 | 2462 } |
2463 | |
2464 ComplexMatrix | |
7788 | 2465 ComplexMatrix::solve (const ComplexMatrix& b, octave_idx_type& info, double& rcon, |
3480 | 2466 solve_singularity_handler sing_handler) const |
2467 { | |
5785 | 2468 MatrixType mattype (*this); |
7788 | 2469 return solve (mattype, b, info, rcon, sing_handler); |
458 | 2470 } |
2471 | |
2472 ComplexColumnVector | |
3585 | 2473 ComplexMatrix::solve (const ColumnVector& b) const |
2474 { | |
5275 | 2475 octave_idx_type info; |
7788 | 2476 double rcon; |
2477 return solve (ComplexColumnVector (b), info, rcon, 0); | |
3585 | 2478 } |
2479 | |
2480 ComplexColumnVector | |
5275 | 2481 ComplexMatrix::solve (const ColumnVector& b, octave_idx_type& info) const |
3585 | 2482 { |
7788 | 2483 double rcon; |
2484 return solve (ComplexColumnVector (b), info, rcon, 0); | |
3585 | 2485 } |
2486 | |
2487 ComplexColumnVector | |
5785 | 2488 ComplexMatrix::solve (const ColumnVector& b, octave_idx_type& info, |
7788 | 2489 double& rcon) const |
3585 | 2490 { |
7788 | 2491 return solve (ComplexColumnVector (b), info, rcon, 0); |
3585 | 2492 } |
2493 | |
2494 ComplexColumnVector | |
5785 | 2495 ComplexMatrix::solve (const ColumnVector& b, octave_idx_type& info, |
7788 | 2496 double& rcon, |
3585 | 2497 solve_singularity_handler sing_handler) const |
2498 { | |
7788 | 2499 return solve (ComplexColumnVector (b), info, rcon, sing_handler); |
3585 | 2500 } |
2501 | |
2502 ComplexColumnVector | |
458 | 2503 ComplexMatrix::solve (const ComplexColumnVector& b) const |
2504 { | |
5275 | 2505 octave_idx_type info; |
7788 | 2506 double rcon; |
2507 return solve (b, info, rcon, 0); | |
458 | 2508 } |
2509 | |
2510 ComplexColumnVector | |
5275 | 2511 ComplexMatrix::solve (const ComplexColumnVector& b, octave_idx_type& info) const |
458 | 2512 { |
7788 | 2513 double rcon; |
2514 return solve (b, info, rcon, 0); | |
458 | 2515 } |
2516 | |
2517 ComplexColumnVector | |
5275 | 2518 ComplexMatrix::solve (const ComplexColumnVector& b, octave_idx_type& info, |
7788 | 2519 double& rcon) const |
458 | 2520 { |
7788 | 2521 return solve (b, info, rcon, 0); |
3480 | 2522 } |
2523 | |
2524 ComplexColumnVector | |
5275 | 2525 ComplexMatrix::solve (const ComplexColumnVector& b, octave_idx_type& info, |
7788 | 2526 double& rcon, |
3480 | 2527 solve_singularity_handler sing_handler) const |
2528 { | |
5785 | 2529 MatrixType mattype (*this); |
7788 | 2530 return solve (mattype, b, info, rcon, sing_handler); |
458 | 2531 } |
2532 | |
2533 ComplexMatrix | |
3585 | 2534 ComplexMatrix::lssolve (const Matrix& b) const |
2535 { | |
5275 | 2536 octave_idx_type info; |
2537 octave_idx_type rank; | |
7788 | 2538 double rcon; |
2539 return lssolve (ComplexMatrix (b), info, rank, rcon); | |
3585 | 2540 } |
2541 | |
2542 ComplexMatrix | |
5275 | 2543 ComplexMatrix::lssolve (const Matrix& b, octave_idx_type& info) const |
3585 | 2544 { |
5275 | 2545 octave_idx_type rank; |
7788 | 2546 double rcon; |
2547 return lssolve (ComplexMatrix (b), info, rank, rcon); | |
3585 | 2548 } |
2549 | |
2550 ComplexMatrix | |
7076 | 2551 ComplexMatrix::lssolve (const Matrix& b, octave_idx_type& info, |
2552 octave_idx_type& rank) const | |
3585 | 2553 { |
7788 | 2554 double rcon; |
2555 return lssolve (ComplexMatrix (b), info, rank, rcon); | |
7076 | 2556 } |
2557 | |
2558 ComplexMatrix | |
2559 ComplexMatrix::lssolve (const Matrix& b, octave_idx_type& info, | |
7788 | 2560 octave_idx_type& rank, double& rcon) const |
7076 | 2561 { |
7788 | 2562 return lssolve (ComplexMatrix (b), info, rank, rcon); |
3585 | 2563 } |
2564 | |
2565 ComplexMatrix | |
458 | 2566 ComplexMatrix::lssolve (const ComplexMatrix& b) const |
2567 { | |
5275 | 2568 octave_idx_type info; |
2569 octave_idx_type rank; | |
7788 | 2570 double rcon; |
2571 return lssolve (b, info, rank, rcon); | |
458 | 2572 } |
2573 | |
2574 ComplexMatrix | |
5275 | 2575 ComplexMatrix::lssolve (const ComplexMatrix& b, octave_idx_type& info) const |
458 | 2576 { |
5275 | 2577 octave_idx_type rank; |
7788 | 2578 double rcon; |
2579 return lssolve (b, info, rank, rcon); | |
458 | 2580 } |
2581 | |
2582 ComplexMatrix | |
7076 | 2583 ComplexMatrix::lssolve (const ComplexMatrix& b, octave_idx_type& info, |
2584 octave_idx_type& rank) const | |
2585 { | |
7788 | 2586 double rcon; |
2587 return lssolve (b, info, rank, rcon); | |
7076 | 2588 } |
2589 | |
2590 ComplexMatrix | |
2591 ComplexMatrix::lssolve (const ComplexMatrix& b, octave_idx_type& info, | |
7788 | 2592 octave_idx_type& rank, double& rcon) const |
458 | 2593 { |
1948 | 2594 ComplexMatrix retval; |
2595 | |
5275 | 2596 octave_idx_type nrhs = b.cols (); |
2597 | |
2598 octave_idx_type m = rows (); | |
2599 octave_idx_type n = cols (); | |
458 | 2600 |
6924 | 2601 if (m != b.rows ()) |
1948 | 2602 (*current_liboctave_error_handler) |
2603 ("matrix dimension mismatch solution of linear equations"); | |
6924 | 2604 else if (m== 0 || n == 0 || b.cols () == 0) |
2605 retval = ComplexMatrix (n, b.cols (), Complex (0.0, 0.0)); | |
1948 | 2606 else |
458 | 2607 { |
7072 | 2608 volatile octave_idx_type minmn = (m < n ? m : n); |
2609 octave_idx_type maxmn = m > n ? m : n; | |
7788 | 2610 rcon = -1.0; |
7072 | 2611 |
2612 if (m != n) | |
2613 { | |
2614 retval = ComplexMatrix (maxmn, nrhs); | |
2615 | |
2616 for (octave_idx_type j = 0; j < nrhs; j++) | |
2617 for (octave_idx_type i = 0; i < m; i++) | |
2618 retval.elem (i, j) = b.elem (i, j); | |
2619 } | |
2620 else | |
2621 retval = b; | |
2622 | |
1948 | 2623 ComplexMatrix atmp = *this; |
2624 Complex *tmp_data = atmp.fortran_vec (); | |
2625 | |
7072 | 2626 Complex *pretval = retval.fortran_vec (); |
2627 Array<double> s (minmn); | |
7071 | 2628 double *ps = s.fortran_vec (); |
2563 | 2629 |
7072 | 2630 // Ask ZGELSD what the dimension of WORK should be. |
5275 | 2631 octave_idx_type lwork = -1; |
3752 | 2632 |
2633 Array<Complex> work (1); | |
7079 | 2634 |
7477 | 2635 octave_idx_type smlsiz; |
2636 F77_FUNC (xilaenv, XILAENV) (9, F77_CONST_CHAR_ARG2 ("ZGELSD", 6), | |
2637 F77_CONST_CHAR_ARG2 (" ", 1), | |
7478 | 2638 0, 0, 0, 0, smlsiz |
7477 | 2639 F77_CHAR_ARG_LEN (6) |
7478 | 2640 F77_CHAR_ARG_LEN (1)); |
7079 | 2641 |
7486
6a6d2abe51ff
more xGELSD workspace fixes
John W. Eaton <jwe@octave.org>
parents:
7482
diff
changeset
|
2642 octave_idx_type mnthr; |
6a6d2abe51ff
more xGELSD workspace fixes
John W. Eaton <jwe@octave.org>
parents:
7482
diff
changeset
|
2643 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
|
2644 F77_CONST_CHAR_ARG2 (" ", 1), |
6a6d2abe51ff
more xGELSD workspace fixes
John W. Eaton <jwe@octave.org>
parents:
7482
diff
changeset
|
2645 m, n, nrhs, -1, mnthr |
6a6d2abe51ff
more xGELSD workspace fixes
John W. Eaton <jwe@octave.org>
parents:
7482
diff
changeset
|
2646 F77_CHAR_ARG_LEN (6) |
6a6d2abe51ff
more xGELSD workspace fixes
John W. Eaton <jwe@octave.org>
parents:
7482
diff
changeset
|
2647 F77_CHAR_ARG_LEN (1)); |
6a6d2abe51ff
more xGELSD workspace fixes
John W. Eaton <jwe@octave.org>
parents:
7482
diff
changeset
|
2648 |
7079 | 2649 // We compute the size of rwork and iwork because ZGELSD in |
2650 // older versions of LAPACK does not return them on a query | |
2651 // call. | |
7124 | 2652 double dminmn = static_cast<double> (minmn); |
2653 double dsmlsizp1 = static_cast<double> (smlsiz+1); | |
7079 | 2654 #if defined (HAVE_LOG2) |
7544
f9983d2761df
more xGELSD workspace fixes
Jaroslav Hajek <highegg@gmail.com>
parents:
7532
diff
changeset
|
2655 double tmp = log2 (dminmn / dsmlsizp1); |
7079 | 2656 #else |
7544
f9983d2761df
more xGELSD workspace fixes
Jaroslav Hajek <highegg@gmail.com>
parents:
7532
diff
changeset
|
2657 double tmp = log (dminmn / dsmlsizp1) / log (2.0); |
7079 | 2658 #endif |
7544
f9983d2761df
more xGELSD workspace fixes
Jaroslav Hajek <highegg@gmail.com>
parents:
7532
diff
changeset
|
2659 octave_idx_type nlvl = static_cast<octave_idx_type> (tmp) + 1; |
7079 | 2660 if (nlvl < 0) |
2661 nlvl = 0; | |
2662 | |
2663 octave_idx_type lrwork = minmn*(10 + 2*smlsiz + 8*nlvl) | |
2664 + 3*smlsiz*nrhs + (smlsiz+1)*(smlsiz+1); | |
2665 if (lrwork < 1) | |
2666 lrwork = 1; | |
2667 Array<double> rwork (lrwork); | |
2668 double *prwork = rwork.fortran_vec (); | |
2669 | |
2670 octave_idx_type liwork = 3 * minmn * nlvl + 11 * minmn; | |
2671 if (liwork < 1) | |
2672 liwork = 1; | |
2673 Array<octave_idx_type> iwork (liwork); | |
2674 octave_idx_type* piwork = iwork.fortran_vec (); | |
7072 | 2675 |
2676 F77_XFCN (zgelsd, ZGELSD, (m, n, nrhs, tmp_data, m, pretval, maxmn, | |
7788 | 2677 ps, rcon, rank, work.fortran_vec (), |
7079 | 2678 lwork, prwork, piwork, info)); |
1948 | 2679 |
7476 | 2680 // 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
|
2681 // 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
|
2682 // should provide sufficient workspace for ZGELSD to operate |
7476 | 2683 // efficiently. |
7488
6470f946a425
another small xGELSD workspace fix
John W. Eaton <jwe@octave.org>
parents:
7486
diff
changeset
|
2684 if (n >= mnthr) |
7476 | 2685 { |
2686 octave_idx_type addend = m; | |
2687 | |
2688 if (2*m-4 > addend) | |
2689 addend = 2*m-4; | |
2690 | |
2691 if (nrhs > addend) | |
2692 addend = nrhs; | |
2693 | |
2694 if (n-3*m > addend) | |
2695 addend = n-3*m; | |
2696 | |
2697 const octave_idx_type lworkaround = 4*m + m*m + addend; | |
2698 | |
2699 if (std::real (work(0)) < lworkaround) | |
2700 work(0) = lworkaround; | |
2701 } | |
7532
493bb0de3199
avoid another xGELSD workspace query bug
John W. Eaton <jwe@octave.org>
parents:
7503
diff
changeset
|
2702 else if (m >= n) |
493bb0de3199
avoid another xGELSD workspace query bug
John W. Eaton <jwe@octave.org>
parents:
7503
diff
changeset
|
2703 { |
493bb0de3199
avoid another xGELSD workspace query bug
John W. Eaton <jwe@octave.org>
parents:
7503
diff
changeset
|
2704 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
|
2705 |
493bb0de3199
avoid another xGELSD workspace query bug
John W. Eaton <jwe@octave.org>
parents:
7503
diff
changeset
|
2706 if (std::real (work(0)) < lworkaround) |
493bb0de3199
avoid another xGELSD workspace query bug
John W. Eaton <jwe@octave.org>
parents:
7503
diff
changeset
|
2707 work(0) = lworkaround; |
493bb0de3199
avoid another xGELSD workspace query bug
John W. Eaton <jwe@octave.org>
parents:
7503
diff
changeset
|
2708 } |
7476 | 2709 |
7482
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2710 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
|
2711 work.resize (lwork); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2712 |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2713 F77_XFCN (zgelsd, ZGELSD, (m, n, nrhs, tmp_data, m, pretval, |
7788 | 2714 maxmn, ps, rcon, rank, |
7482
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2715 work.fortran_vec (), lwork, |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2716 prwork, piwork, info)); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2717 |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2718 if (rank < minmn) |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2719 (*current_liboctave_warning_handler) |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2720 ("zgelsd: rank deficient %dx%d matrix, rank = %d, tol = %e", |
7788 | 2721 m, n, rank, rcon); |
7482
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2722 |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2723 if (s.elem (0) == 0.0) |
7788 | 2724 rcon = 0.0; |
1948 | 2725 else |
7788 | 2726 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
|
2727 |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2728 retval.resize (n, nrhs); |
458 | 2729 } |
2730 | |
2731 return retval; | |
2732 } | |
2733 | |
2734 ComplexColumnVector | |
3585 | 2735 ComplexMatrix::lssolve (const ColumnVector& b) const |
2736 { | |
5275 | 2737 octave_idx_type info; |
2738 octave_idx_type rank; | |
7788 | 2739 double rcon; |
2740 return lssolve (ComplexColumnVector (b), info, rank, rcon); | |
3585 | 2741 } |
2742 | |
2743 ComplexColumnVector | |
5275 | 2744 ComplexMatrix::lssolve (const ColumnVector& b, octave_idx_type& info) const |
3585 | 2745 { |
5275 | 2746 octave_idx_type rank; |
7788 | 2747 double rcon; |
2748 return lssolve (ComplexColumnVector (b), info, rank, rcon); | |
3585 | 2749 } |
2750 | |
2751 ComplexColumnVector | |
7076 | 2752 ComplexMatrix::lssolve (const ColumnVector& b, octave_idx_type& info, |
2753 octave_idx_type& rank) const | |
3585 | 2754 { |
7788 | 2755 double rcon; |
2756 return lssolve (ComplexColumnVector (b), info, rank, rcon); | |
7076 | 2757 } |
2758 | |
2759 ComplexColumnVector | |
2760 ComplexMatrix::lssolve (const ColumnVector& b, octave_idx_type& info, | |
7788 | 2761 octave_idx_type& rank, double& rcon) const |
7076 | 2762 { |
7788 | 2763 return lssolve (ComplexColumnVector (b), info, rank, rcon); |
3585 | 2764 } |
2765 | |
2766 ComplexColumnVector | |
458 | 2767 ComplexMatrix::lssolve (const ComplexColumnVector& b) const |
2768 { | |
5275 | 2769 octave_idx_type info; |
2770 octave_idx_type rank; | |
7788 | 2771 double rcon; |
2772 return lssolve (b, info, rank, rcon); | |
458 | 2773 } |
2774 | |
2775 ComplexColumnVector | |
5275 | 2776 ComplexMatrix::lssolve (const ComplexColumnVector& b, octave_idx_type& info) const |
458 | 2777 { |
5275 | 2778 octave_idx_type rank; |
7788 | 2779 double rcon; |
2780 return lssolve (b, info, rank, rcon); | |
458 | 2781 } |
2782 | |
2783 ComplexColumnVector | |
5275 | 2784 ComplexMatrix::lssolve (const ComplexColumnVector& b, octave_idx_type& info, |
2785 octave_idx_type& rank) const | |
458 | 2786 { |
7788 | 2787 double rcon; |
2788 return lssolve (b, info, rank, rcon); | |
7076 | 2789 |
2790 } | |
2791 | |
2792 ComplexColumnVector | |
2793 ComplexMatrix::lssolve (const ComplexColumnVector& b, octave_idx_type& info, | |
7788 | 2794 octave_idx_type& rank, double& rcon) const |
7076 | 2795 { |
1948 | 2796 ComplexColumnVector retval; |
2797 | |
5275 | 2798 octave_idx_type nrhs = 1; |
2799 | |
2800 octave_idx_type m = rows (); | |
2801 octave_idx_type n = cols (); | |
458 | 2802 |
6924 | 2803 if (m != b.length ()) |
1948 | 2804 (*current_liboctave_error_handler) |
6924 | 2805 ("matrix dimension mismatch solution of linear equations"); |
2806 else if (m == 0 || n == 0 || b.cols () == 0) | |
2807 retval = ComplexColumnVector (n, Complex (0.0, 0.0)); | |
1948 | 2808 else |
458 | 2809 { |
7072 | 2810 volatile octave_idx_type minmn = (m < n ? m : n); |
2811 octave_idx_type maxmn = m > n ? m : n; | |
7788 | 2812 rcon = -1.0; |
7072 | 2813 |
2814 if (m != n) | |
2815 { | |
2816 retval = ComplexColumnVector (maxmn); | |
2817 | |
2818 for (octave_idx_type i = 0; i < m; i++) | |
2819 retval.elem (i) = b.elem (i); | |
2820 } | |
2821 else | |
2822 retval = b; | |
2823 | |
1948 | 2824 ComplexMatrix atmp = *this; |
2825 Complex *tmp_data = atmp.fortran_vec (); | |
2826 | |
7072 | 2827 Complex *pretval = retval.fortran_vec (); |
2828 Array<double> s (minmn); | |
7071 | 2829 double *ps = s.fortran_vec (); |
1948 | 2830 |
7072 | 2831 // Ask ZGELSD what the dimension of WORK should be. |
5275 | 2832 octave_idx_type lwork = -1; |
3752 | 2833 |
2834 Array<Complex> work (1); | |
7079 | 2835 |
7544
f9983d2761df
more xGELSD workspace fixes
Jaroslav Hajek <highegg@gmail.com>
parents:
7532
diff
changeset
|
2836 octave_idx_type smlsiz; |
f9983d2761df
more xGELSD workspace fixes
Jaroslav Hajek <highegg@gmail.com>
parents:
7532
diff
changeset
|
2837 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
|
2838 F77_CONST_CHAR_ARG2 (" ", 1), |
f9983d2761df
more xGELSD workspace fixes
Jaroslav Hajek <highegg@gmail.com>
parents:
7532
diff
changeset
|
2839 0, 0, 0, 0, smlsiz |
f9983d2761df
more xGELSD workspace fixes
Jaroslav Hajek <highegg@gmail.com>
parents:
7532
diff
changeset
|
2840 F77_CHAR_ARG_LEN (6) |
f9983d2761df
more xGELSD workspace fixes
Jaroslav Hajek <highegg@gmail.com>
parents:
7532
diff
changeset
|
2841 F77_CHAR_ARG_LEN (1)); |
7079 | 2842 |
2843 // We compute the size of rwork and iwork because ZGELSD in | |
2844 // older versions of LAPACK does not return them on a query | |
2845 // call. | |
7124 | 2846 double dminmn = static_cast<double> (minmn); |
2847 double dsmlsizp1 = static_cast<double> (smlsiz+1); | |
7079 | 2848 #if defined (HAVE_LOG2) |
7544
f9983d2761df
more xGELSD workspace fixes
Jaroslav Hajek <highegg@gmail.com>
parents:
7532
diff
changeset
|
2849 double tmp = log2 (dminmn / dsmlsizp1); |
7079 | 2850 #else |
7544
f9983d2761df
more xGELSD workspace fixes
Jaroslav Hajek <highegg@gmail.com>
parents:
7532
diff
changeset
|
2851 double tmp = log (dminmn / dsmlsizp1) / log (2.0); |
7079 | 2852 #endif |
7544
f9983d2761df
more xGELSD workspace fixes
Jaroslav Hajek <highegg@gmail.com>
parents:
7532
diff
changeset
|
2853 octave_idx_type nlvl = static_cast<octave_idx_type> (tmp) + 1; |
7079 | 2854 if (nlvl < 0) |
2855 nlvl = 0; | |
2856 | |
2857 octave_idx_type lrwork = minmn*(10 + 2*smlsiz + 8*nlvl) | |
2858 + 3*smlsiz*nrhs + (smlsiz+1)*(smlsiz+1); | |
2859 if (lrwork < 1) | |
2860 lrwork = 1; | |
2861 Array<double> rwork (lrwork); | |
2862 double *prwork = rwork.fortran_vec (); | |
2863 | |
2864 octave_idx_type liwork = 3 * minmn * nlvl + 11 * minmn; | |
2865 if (liwork < 1) | |
2866 liwork = 1; | |
2867 Array<octave_idx_type> iwork (liwork); | |
2868 octave_idx_type* piwork = iwork.fortran_vec (); | |
7072 | 2869 |
2870 F77_XFCN (zgelsd, ZGELSD, (m, n, nrhs, tmp_data, m, pretval, maxmn, | |
7788 | 2871 ps, rcon, rank, work.fortran_vec (), |
7079 | 2872 lwork, prwork, piwork, info)); |
1948 | 2873 |
7482
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2874 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
|
2875 work.resize (lwork); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2876 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
|
2877 iwork.resize (iwork(0)); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2878 |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2879 F77_XFCN (zgelsd, ZGELSD, (m, n, nrhs, tmp_data, m, pretval, |
7788 | 2880 maxmn, ps, rcon, rank, |
7482
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2881 work.fortran_vec (), lwork, |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2882 prwork, piwork, info)); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2883 |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2884 if (rank < minmn) |
1948 | 2885 { |
7482
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2886 if (rank < minmn) |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2887 (*current_liboctave_warning_handler) |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2888 ("zgelsd: rank deficient %dx%d matrix, rank = %d, tol = %e", |
7788 | 2889 m, n, rank, rcon); |
7482
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2890 |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2891 if (s.elem (0) == 0.0) |
7788 | 2892 rcon = 0.0; |
7482
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2893 else |
7788 | 2894 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
|
2895 |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2896 retval.resize (n, nrhs); |
1948 | 2897 } |
458 | 2898 } |
2899 | |
2900 return retval; | |
2901 } | |
2902 | |
1819 | 2903 // Constants for matrix exponential calculation. |
2904 | |
2905 static double padec [] = | |
2906 { | |
2907 5.0000000000000000e-1, | |
2908 1.1666666666666667e-1, | |
2909 1.6666666666666667e-2, | |
2910 1.6025641025641026e-3, | |
2911 1.0683760683760684e-4, | |
2912 4.8562548562548563e-6, | |
2913 1.3875013875013875e-7, | |
2914 1.9270852604185938e-9, | |
2915 }; | |
2916 | |
7400 | 2917 static void |
7788 | 2918 solve_singularity_warning (double rcon) |
7400 | 2919 { |
2920 (*current_liboctave_warning_handler) | |
2921 ("singular matrix encountered in expm calculation, rcond = %g", | |
7788 | 2922 rcon); |
7400 | 2923 } |
2924 | |
1819 | 2925 ComplexMatrix |
2926 ComplexMatrix::expm (void) const | |
2927 { | |
2928 ComplexMatrix retval; | |
2929 | |
2930 ComplexMatrix m = *this; | |
2931 | |
5275 | 2932 octave_idx_type nc = columns (); |
1819 | 2933 |
3130 | 2934 // Preconditioning step 1: trace normalization to reduce dynamic |
2935 // range of poles, but avoid making stable eigenvalues unstable. | |
2936 | |
1819 | 2937 // trace shift value |
2938 Complex trshift = 0.0; | |
2939 | |
5275 | 2940 for (octave_idx_type i = 0; i < nc; i++) |
1819 | 2941 trshift += m.elem (i, i); |
2942 | |
2943 trshift /= nc; | |
2944 | |
3130 | 2945 if (trshift.real () < 0.0) |
6958 | 2946 { |
2947 trshift = trshift.imag (); | |
2948 if (trshift.real () > 709.0) | |
2949 trshift = 709.0; | |
2950 } | |
3130 | 2951 |
5275 | 2952 for (octave_idx_type i = 0; i < nc; i++) |
1819 | 2953 m.elem (i, i) -= trshift; |
2954 | |
2955 // Preconditioning step 2: eigenvalue balancing. | |
3331 | 2956 // code follows development in AEPBAL |
2957 | |
2958 Complex *mp = m.fortran_vec (); | |
3467 | 2959 |
5275 | 2960 octave_idx_type info, ilo, ihi,ilos,ihis; |
3468 | 2961 Array<double> dpermute (nc); |
2962 Array<double> dscale (nc); | |
2963 | |
5775 | 2964 // FIXME -- should pass job as a parameter in expm |
3468 | 2965 |
2966 // Permute first | |
2967 char job = 'P'; | |
4552 | 2968 F77_XFCN (zgebal, ZGEBAL, (F77_CONST_CHAR_ARG2 (&job, 1), |
2969 nc, mp, nc, ilo, ihi, | |
2970 dpermute.fortran_vec (), info | |
2971 F77_CHAR_ARG_LEN (1))); | |
3331 | 2972 |
3468 | 2973 // then scale |
2974 job = 'S'; | |
4552 | 2975 F77_XFCN (zgebal, ZGEBAL, (F77_CONST_CHAR_ARG2 (&job, 1), |
2976 nc, mp, nc, ilos, ihis, | |
2977 dscale.fortran_vec (), info | |
2978 F77_CHAR_ARG_LEN (1))); | |
3331 | 2979 |
1819 | 2980 // Preconditioning step 3: scaling. |
2981 | |
2982 ColumnVector work (nc); | |
3130 | 2983 double inf_norm; |
2984 | |
4552 | 2985 F77_XFCN (xzlange, XZLANGE, (F77_CONST_CHAR_ARG2 ("I", 1), |
2986 nc, nc, m.fortran_vec (), nc, | |
2987 work.fortran_vec (), inf_norm | |
2988 F77_CHAR_ARG_LEN (1))); | |
3331 | 2989 |
2800 | 2990 int sqpow = (inf_norm > 0.0 |
2991 ? static_cast<int> (1.0 + log (inf_norm) / log (2.0)) : 0); | |
1819 | 2992 |
2993 // Check whether we need to square at all. | |
2994 | |
2995 if (sqpow < 0) | |
2996 sqpow = 0; | |
2997 | |
2998 if (sqpow > 0) | |
2999 { | |
7400 | 3000 if (sqpow > 1023) |
3001 sqpow = 1023; | |
3002 | |
1819 | 3003 double scale_factor = 1.0; |
5275 | 3004 for (octave_idx_type i = 0; i < sqpow; i++) |
1819 | 3005 scale_factor *= 2.0; |
3006 | |
3007 m = m / scale_factor; | |
3008 } | |
3009 | |
3010 // npp, dpp: pade' approx polynomial matrices. | |
3011 | |
3012 ComplexMatrix npp (nc, nc, 0.0); | |
6958 | 3013 Complex *pnpp = npp.fortran_vec (); |
1819 | 3014 ComplexMatrix dpp = npp; |
6958 | 3015 Complex *pdpp = dpp.fortran_vec (); |
1819 | 3016 |
3017 // Now powers a^8 ... a^1. | |
3018 | |
3019 int minus_one_j = -1; | |
5275 | 3020 for (octave_idx_type j = 7; j >= 0; j--) |
1819 | 3021 { |
6958 | 3022 for (octave_idx_type i = 0; i < nc; i++) |
3023 { | |
3024 octave_idx_type k = i * nc + i; | |
7265 | 3025 pnpp[k] += padec[j]; |
3026 pdpp[k] += minus_one_j * padec[j]; | |
6958 | 3027 } |
7265 | 3028 |
6958 | 3029 npp = m * npp; |
7265 | 3030 pnpp = npp.fortran_vec (); |
3031 | |
6958 | 3032 dpp = m * dpp; |
7265 | 3033 pdpp = dpp.fortran_vec (); |
3034 | |
1819 | 3035 minus_one_j *= -1; |
3036 } | |
3037 | |
3038 // Zero power. | |
3039 | |
3040 dpp = -dpp; | |
5275 | 3041 for (octave_idx_type j = 0; j < nc; j++) |
1819 | 3042 { |
3043 npp.elem (j, j) += 1.0; | |
3044 dpp.elem (j, j) += 1.0; | |
3045 } | |
3046 | |
3047 // Compute pade approximation = inverse (dpp) * npp. | |
3048 | |
7788 | 3049 double rcon; |
3050 retval = dpp.solve (npp, info, rcon, solve_singularity_warning); | |
7400 | 3051 |
3052 if (info < 0) | |
3053 return retval; | |
3054 | |
1819 | 3055 // Reverse preconditioning step 3: repeated squaring. |
3056 | |
3057 while (sqpow) | |
3058 { | |
3059 retval = retval * retval; | |
3060 sqpow--; | |
3061 } | |
3062 | |
3063 // Reverse preconditioning step 2: inverse balancing. | |
3467 | 3064 // Done in two steps: inverse scaling, then inverse permutation |
3065 | |
3066 // inverse scaling (diagonal transformation) | |
5275 | 3067 for (octave_idx_type i = 0; i < nc; i++) |
3068 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
|
3069 retval(i,j) *= dscale(i) / dscale(j); |
3467 | 3070 |
4153 | 3071 OCTAVE_QUIT; |
3072 | |
3467 | 3073 // construct balancing permutation vector |
6867 | 3074 Array<octave_idx_type> iperm (nc); |
5275 | 3075 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
|
3076 iperm(i) = i; // identity permutation |
851803f7bb4d
improve inverse preconditioning according to Marco Caliari
Jaroslav Hajek <highegg@gmail.com>
parents:
7922
diff
changeset
|
3077 |
851803f7bb4d
improve inverse preconditioning according to Marco Caliari
Jaroslav Hajek <highegg@gmail.com>
parents:
7922
diff
changeset
|
3078 // 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
|
3079 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
|
3080 { |
851803f7bb4d
improve inverse preconditioning according to Marco Caliari
Jaroslav Hajek <highegg@gmail.com>
parents:
7922
diff
changeset
|
3081 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
|
3082 octave_idx_type tmp = iperm(i); |
851803f7bb4d
improve inverse preconditioning according to Marco Caliari
Jaroslav Hajek <highegg@gmail.com>
parents:
7922
diff
changeset
|
3083 iperm(i) = iperm(swapidx); |
851803f7bb4d
improve inverse preconditioning according to Marco Caliari
Jaroslav Hajek <highegg@gmail.com>
parents:
7922
diff
changeset
|
3084 iperm(swapidx) = tmp; |
851803f7bb4d
improve inverse preconditioning according to Marco Caliari
Jaroslav Hajek <highegg@gmail.com>
parents:
7922
diff
changeset
|
3085 } |
3467 | 3086 |
3087 // leading permutations in forward order | |
5275 | 3088 for (octave_idx_type i = 0; i < (ilo-1); i++) |
3468 | 3089 { |
6867 | 3090 octave_idx_type swapidx = static_cast<octave_idx_type> (dpermute(i)) - 1; |
5275 | 3091 octave_idx_type tmp = iperm(i); |
8211
851803f7bb4d
improve inverse preconditioning according to Marco Caliari
Jaroslav Hajek <highegg@gmail.com>
parents:
7922
diff
changeset
|
3092 iperm(i) = iperm (swapidx); |
4593 | 3093 iperm(swapidx) = tmp; |
3468 | 3094 } |
3467 | 3095 |
7416 | 3096 // construct inverse balancing permutation vector |
3097 Array<octave_idx_type> invpvec (nc); | |
3098 for (octave_idx_type i = 0; i < nc; i++) | |
3099 invpvec(iperm(i)) = i; // Thanks to R. A. Lippert for this method | |
3100 | |
3101 OCTAVE_QUIT; | |
3102 | |
3103 ComplexMatrix tmpMat = retval; | |
3104 for (octave_idx_type i = 0; i < nc; i++) | |
3105 for (octave_idx_type j = 0; j < nc; j++) | |
3106 retval(i,j) = tmpMat(invpvec(i),invpvec(j)); | |
3107 | |
8211
851803f7bb4d
improve inverse preconditioning according to Marco Caliari
Jaroslav Hajek <highegg@gmail.com>
parents:
7922
diff
changeset
|
3108 // Reverse preconditioning step 1: fix trace normalization. |
1819 | 3109 |
3130 | 3110 return exp (trshift) * retval; |
1819 | 3111 } |
3112 | |
1205 | 3113 // column vector by row vector -> matrix operations |
3114 | |
3115 ComplexMatrix | |
3116 operator * (const ColumnVector& v, const ComplexRowVector& a) | |
3117 { | |
3118 ComplexColumnVector tmp (v); | |
3119 return tmp * a; | |
3120 } | |
3121 | |
3122 ComplexMatrix | |
3123 operator * (const ComplexColumnVector& a, const RowVector& b) | |
3124 { | |
3125 ComplexRowVector tmp (b); | |
3126 return a * tmp; | |
3127 } | |
3128 | |
3129 ComplexMatrix | |
3130 operator * (const ComplexColumnVector& v, const ComplexRowVector& a) | |
3131 { | |
1948 | 3132 ComplexMatrix retval; |
3133 | |
5275 | 3134 octave_idx_type len = v.length (); |
3233 | 3135 |
3136 if (len != 0) | |
1205 | 3137 { |
5275 | 3138 octave_idx_type a_len = a.length (); |
3233 | 3139 |
3140 retval.resize (len, a_len); | |
3141 Complex *c = retval.fortran_vec (); | |
3142 | |
4552 | 3143 F77_XFCN (zgemm, ZGEMM, (F77_CONST_CHAR_ARG2 ("N", 1), |
3144 F77_CONST_CHAR_ARG2 ("N", 1), | |
3145 len, a_len, 1, 1.0, v.data (), len, | |
3146 a.data (), 1, 0.0, c, len | |
3147 F77_CHAR_ARG_LEN (1) | |
3148 F77_CHAR_ARG_LEN (1))); | |
1205 | 3149 } |
3150 | |
1948 | 3151 return retval; |
1205 | 3152 } |
3153 | |
458 | 3154 // matrix by diagonal matrix -> matrix operations |
3155 | |
3156 ComplexMatrix& | |
3157 ComplexMatrix::operator += (const DiagMatrix& a) | |
3158 { | |
5275 | 3159 octave_idx_type nr = rows (); |
3160 octave_idx_type nc = cols (); | |
3161 | |
3162 octave_idx_type a_nr = rows (); | |
3163 octave_idx_type a_nc = cols (); | |
2384 | 3164 |
3165 if (nr != a_nr || nc != a_nc) | |
458 | 3166 { |
2384 | 3167 gripe_nonconformant ("operator +=", nr, nc, a_nr, a_nc); |
889 | 3168 return *this; |
458 | 3169 } |
3170 | |
5275 | 3171 for (octave_idx_type i = 0; i < a.length (); i++) |
458 | 3172 elem (i, i) += a.elem (i, i); |
3173 | |
3174 return *this; | |
3175 } | |
3176 | |
3177 ComplexMatrix& | |
3178 ComplexMatrix::operator -= (const DiagMatrix& a) | |
3179 { | |
5275 | 3180 octave_idx_type nr = rows (); |
3181 octave_idx_type nc = cols (); | |
3182 | |
3183 octave_idx_type a_nr = rows (); | |
3184 octave_idx_type a_nc = cols (); | |
2384 | 3185 |
3186 if (nr != a_nr || nc != a_nc) | |
458 | 3187 { |
2384 | 3188 gripe_nonconformant ("operator -=", nr, nc, a_nr, a_nc); |
889 | 3189 return *this; |
458 | 3190 } |
3191 | |
5275 | 3192 for (octave_idx_type i = 0; i < a.length (); i++) |
458 | 3193 elem (i, i) -= a.elem (i, i); |
3194 | |
3195 return *this; | |
3196 } | |
3197 | |
3198 ComplexMatrix& | |
3199 ComplexMatrix::operator += (const ComplexDiagMatrix& a) | |
3200 { | |
5275 | 3201 octave_idx_type nr = rows (); |
3202 octave_idx_type nc = cols (); | |
3203 | |
3204 octave_idx_type a_nr = rows (); | |
3205 octave_idx_type a_nc = cols (); | |
2384 | 3206 |
3207 if (nr != a_nr || nc != a_nc) | |
458 | 3208 { |
2384 | 3209 gripe_nonconformant ("operator +=", nr, nc, a_nr, a_nc); |
889 | 3210 return *this; |
458 | 3211 } |
3212 | |
5275 | 3213 for (octave_idx_type i = 0; i < a.length (); i++) |
458 | 3214 elem (i, i) += a.elem (i, i); |
3215 | |
3216 return *this; | |
3217 } | |
3218 | |
3219 ComplexMatrix& | |
3220 ComplexMatrix::operator -= (const ComplexDiagMatrix& a) | |
3221 { | |
5275 | 3222 octave_idx_type nr = rows (); |
3223 octave_idx_type nc = cols (); | |
3224 | |
3225 octave_idx_type a_nr = rows (); | |
3226 octave_idx_type a_nc = cols (); | |
2384 | 3227 |
3228 if (nr != a_nr || nc != a_nc) | |
458 | 3229 { |
2384 | 3230 gripe_nonconformant ("operator -=", nr, nc, a_nr, a_nc); |
889 | 3231 return *this; |
458 | 3232 } |
3233 | |
5275 | 3234 for (octave_idx_type i = 0; i < a.length (); i++) |
458 | 3235 elem (i, i) -= a.elem (i, i); |
3236 | |
3237 return *this; | |
3238 } | |
3239 | |
3240 // matrix by matrix -> matrix operations | |
3241 | |
3242 ComplexMatrix& | |
3243 ComplexMatrix::operator += (const Matrix& a) | |
3244 { | |
5275 | 3245 octave_idx_type nr = rows (); |
3246 octave_idx_type nc = cols (); | |
3247 | |
3248 octave_idx_type a_nr = a.rows (); | |
3249 octave_idx_type a_nc = a.cols (); | |
2384 | 3250 |
3251 if (nr != a_nr || nc != a_nc) | |
458 | 3252 { |
2384 | 3253 gripe_nonconformant ("operator +=", nr, nc, a_nr, a_nc); |
458 | 3254 return *this; |
3255 } | |
3256 | |
3257 if (nr == 0 || nc == 0) | |
3258 return *this; | |
3259 | |
3260 Complex *d = fortran_vec (); // Ensures only one reference to my privates! | |
3261 | |
3769 | 3262 mx_inline_add2 (d, a.data (), length ()); |
458 | 3263 return *this; |
3264 } | |
3265 | |
3266 ComplexMatrix& | |
3267 ComplexMatrix::operator -= (const Matrix& a) | |
3268 { | |
5275 | 3269 octave_idx_type nr = rows (); |
3270 octave_idx_type nc = cols (); | |
3271 | |
3272 octave_idx_type a_nr = a.rows (); | |
3273 octave_idx_type a_nc = a.cols (); | |
2384 | 3274 |
3275 if (nr != a_nr || nc != a_nc) | |
458 | 3276 { |
2384 | 3277 gripe_nonconformant ("operator -=", nr, nc, a_nr, a_nc); |
458 | 3278 return *this; |
3279 } | |
3280 | |
3281 if (nr == 0 || nc == 0) | |
3282 return *this; | |
3283 | |
3284 Complex *d = fortran_vec (); // Ensures only one reference to my privates! | |
3285 | |
3769 | 3286 mx_inline_subtract2 (d, a.data (), length ()); |
458 | 3287 return *this; |
3288 } | |
3289 | |
3290 // unary operations | |
3291 | |
2964 | 3292 boolMatrix |
458 | 3293 ComplexMatrix::operator ! (void) const |
3294 { | |
5275 | 3295 octave_idx_type nr = rows (); |
3296 octave_idx_type nc = cols (); | |
2964 | 3297 |
3298 boolMatrix b (nr, nc); | |
3299 | |
5275 | 3300 for (octave_idx_type j = 0; j < nc; j++) |
3301 for (octave_idx_type i = 0; i < nr; i++) | |
5139 | 3302 b.elem (i, j) = elem (i, j) == 0.0; |
2964 | 3303 |
3304 return b; | |
458 | 3305 } |
3306 | |
3307 // other operations | |
3308 | |
2676 | 3309 Matrix |
7503
8c32f95c2639
convert mapper functions to new format
David Bateman <dbateman@free.fr>
parents:
7488
diff
changeset
|
3310 ComplexMatrix::map (dmapper fcn) const |
458 | 3311 { |
7503
8c32f95c2639
convert mapper functions to new format
David Bateman <dbateman@free.fr>
parents:
7488
diff
changeset
|
3312 return MArray2<Complex>::map<double> (func_ptr (fcn)); |
8c32f95c2639
convert mapper functions to new format
David Bateman <dbateman@free.fr>
parents:
7488
diff
changeset
|
3313 } |
8c32f95c2639
convert mapper functions to new format
David Bateman <dbateman@free.fr>
parents:
7488
diff
changeset
|
3314 |
8c32f95c2639
convert mapper functions to new format
David Bateman <dbateman@free.fr>
parents:
7488
diff
changeset
|
3315 ComplexMatrix |
8c32f95c2639
convert mapper functions to new format
David Bateman <dbateman@free.fr>
parents:
7488
diff
changeset
|
3316 ComplexMatrix::map (cmapper fcn) const |
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 return MArray2<Complex>::map<Complex> (func_ptr (fcn)); |
3248 | 3319 } |
3320 | |
3321 boolMatrix | |
7503
8c32f95c2639
convert mapper functions to new format
David Bateman <dbateman@free.fr>
parents:
7488
diff
changeset
|
3322 ComplexMatrix::map (bmapper fcn) const |
3248 | 3323 { |
7503
8c32f95c2639
convert mapper functions to new format
David Bateman <dbateman@free.fr>
parents:
7488
diff
changeset
|
3324 return MArray2<Complex>::map<bool> (func_ptr (fcn)); |
458 | 3325 } |
3326 | |
2384 | 3327 bool |
7922
935be827eaf8
error for NaN values in & and | expressions
John W. Eaton <jwe@octave.org>
parents:
7803
diff
changeset
|
3328 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
|
3329 { |
935be827eaf8
error for NaN values in & and | expressions
John W. Eaton <jwe@octave.org>
parents:
7803
diff
changeset
|
3330 octave_idx_type nr = rows (); |
935be827eaf8
error for NaN values in & and | expressions
John W. Eaton <jwe@octave.org>
parents:
7803
diff
changeset
|
3331 octave_idx_type nc = cols (); |
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 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
|
3334 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
|
3335 { |
935be827eaf8
error for NaN values in & and | expressions
John W. Eaton <jwe@octave.org>
parents:
7803
diff
changeset
|
3336 Complex val = elem (i, j); |
935be827eaf8
error for NaN values in & and | expressions
John W. Eaton <jwe@octave.org>
parents:
7803
diff
changeset
|
3337 if (xisnan (val)) |
935be827eaf8
error for NaN values in & and | expressions
John W. Eaton <jwe@octave.org>
parents:
7803
diff
changeset
|
3338 return true; |
935be827eaf8
error for NaN values in & and | expressions
John W. Eaton <jwe@octave.org>
parents:
7803
diff
changeset
|
3339 } |
935be827eaf8
error for NaN values in & and | expressions
John W. Eaton <jwe@octave.org>
parents:
7803
diff
changeset
|
3340 |
935be827eaf8
error for NaN values in & and | expressions
John W. Eaton <jwe@octave.org>
parents:
7803
diff
changeset
|
3341 return false; |
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 bool |
2384 | 3345 ComplexMatrix::any_element_is_inf_or_nan (void) const |
3346 { | |
5275 | 3347 octave_idx_type nr = rows (); |
3348 octave_idx_type nc = cols (); | |
3349 | |
3350 for (octave_idx_type j = 0; j < nc; j++) | |
3351 for (octave_idx_type i = 0; i < nr; i++) | |
2384 | 3352 { |
3353 Complex val = elem (i, j); | |
3354 if (xisinf (val) || xisnan (val)) | |
3355 return true; | |
3356 } | |
3357 | |
3358 return false; | |
3359 } | |
3360 | |
2408 | 3361 // Return true if no elements have imaginary components. |
3362 | |
3363 bool | |
3364 ComplexMatrix::all_elements_are_real (void) const | |
3365 { | |
5275 | 3366 octave_idx_type nr = rows (); |
3367 octave_idx_type nc = cols (); | |
3368 | |
3369 for (octave_idx_type j = 0; j < nc; j++) | |
4349 | 3370 { |
5275 | 3371 for (octave_idx_type i = 0; i < nr; i++) |
4349 | 3372 { |
5315 | 3373 double ip = std::imag (elem (i, j)); |
4349 | 3374 |
3375 if (ip != 0.0 || lo_ieee_signbit (ip)) | |
3376 return false; | |
3377 } | |
3378 } | |
2408 | 3379 |
3380 return true; | |
3381 } | |
3382 | |
1968 | 3383 // Return nonzero if any element of CM has a non-integer real or |
3384 // imaginary part. Also extract the largest and smallest (real or | |
3385 // imaginary) values and return them in MAX_VAL and MIN_VAL. | |
3386 | |
2384 | 3387 bool |
1968 | 3388 ComplexMatrix::all_integers (double& max_val, double& min_val) const |
3389 { | |
5275 | 3390 octave_idx_type nr = rows (); |
3391 octave_idx_type nc = cols (); | |
1968 | 3392 |
3393 if (nr > 0 && nc > 0) | |
3394 { | |
3395 Complex val = elem (0, 0); | |
3396 | |
5315 | 3397 double r_val = std::real (val); |
3398 double i_val = std::imag (val); | |
1968 | 3399 |
3400 max_val = r_val; | |
3401 min_val = r_val; | |
3402 | |
3403 if (i_val > max_val) | |
3404 max_val = i_val; | |
3405 | |
3406 if (i_val < max_val) | |
3407 min_val = i_val; | |
3408 } | |
3409 else | |
2384 | 3410 return false; |
1968 | 3411 |
5275 | 3412 for (octave_idx_type j = 0; j < nc; j++) |
3413 for (octave_idx_type i = 0; i < nr; i++) | |
1968 | 3414 { |
3415 Complex val = elem (i, j); | |
3416 | |
5315 | 3417 double r_val = std::real (val); |
3418 double i_val = std::imag (val); | |
1968 | 3419 |
3420 if (r_val > max_val) | |
3421 max_val = r_val; | |
3422 | |
3423 if (i_val > max_val) | |
3424 max_val = i_val; | |
3425 | |
3426 if (r_val < min_val) | |
3427 min_val = r_val; | |
3428 | |
3429 if (i_val < min_val) | |
3430 min_val = i_val; | |
3431 | |
3432 if (D_NINT (r_val) != r_val || D_NINT (i_val) != i_val) | |
2384 | 3433 return false; |
1968 | 3434 } |
2384 | 3435 |
3436 return true; | |
1968 | 3437 } |
3438 | |
2384 | 3439 bool |
1968 | 3440 ComplexMatrix::too_large_for_float (void) const |
3441 { | |
5275 | 3442 octave_idx_type nr = rows (); |
3443 octave_idx_type nc = cols (); | |
3444 | |
3445 for (octave_idx_type j = 0; j < nc; j++) | |
3446 for (octave_idx_type i = 0; i < nr; i++) | |
1968 | 3447 { |
3448 Complex val = elem (i, j); | |
3449 | |
5315 | 3450 double r_val = std::real (val); |
3451 double i_val = std::imag (val); | |
1968 | 3452 |
5389 | 3453 if ((! (xisnan (r_val) || xisinf (r_val)) |
5387 | 3454 && fabs (r_val) > FLT_MAX) |
5389 | 3455 || (! (xisnan (i_val) || xisinf (i_val)) |
5387 | 3456 && fabs (i_val) > FLT_MAX)) |
2384 | 3457 return true; |
1968 | 3458 } |
3459 | |
2384 | 3460 return false; |
1968 | 3461 } |
3462 | |
5775 | 3463 // FIXME Do these really belong here? Maybe they should be |
4015 | 3464 // in a base class? |
3465 | |
2832 | 3466 boolMatrix |
4015 | 3467 ComplexMatrix::all (int dim) const |
458 | 3468 { |
4015 | 3469 MX_ALL_OP (dim); |
458 | 3470 } |
3471 | |
2832 | 3472 boolMatrix |
4015 | 3473 ComplexMatrix::any (int dim) const |
458 | 3474 { |
4015 | 3475 MX_ANY_OP (dim); |
458 | 3476 } |
3477 | |
3478 ComplexMatrix | |
3723 | 3479 ComplexMatrix::cumprod (int dim) const |
458 | 3480 { |
4015 | 3481 MX_CUMULATIVE_OP (ComplexMatrix, Complex, *=); |
458 | 3482 } |
3483 | |
3484 ComplexMatrix | |
3723 | 3485 ComplexMatrix::cumsum (int dim) const |
458 | 3486 { |
4015 | 3487 MX_CUMULATIVE_OP (ComplexMatrix, Complex, +=); |
458 | 3488 } |
3489 | |
3490 ComplexMatrix | |
3723 | 3491 ComplexMatrix::prod (int dim) const |
458 | 3492 { |
3864 | 3493 MX_REDUCTION_OP (ComplexMatrix, *=, 1.0, 1.0); |
458 | 3494 } |
3495 | |
3496 ComplexMatrix | |
3723 | 3497 ComplexMatrix::sum (int dim) const |
458 | 3498 { |
3864 | 3499 MX_REDUCTION_OP (ComplexMatrix, +=, 0.0, 0.0); |
458 | 3500 } |
3501 | |
3502 ComplexMatrix | |
3723 | 3503 ComplexMatrix::sumsq (int dim) const |
458 | 3504 { |
3864 | 3505 #define ROW_EXPR \ |
3506 Complex d = elem (i, j); \ | |
3507 retval.elem (i, 0) += d * conj (d) | |
3508 | |
3509 #define COL_EXPR \ | |
3510 Complex d = elem (i, j); \ | |
3511 retval.elem (0, j) += d * conj (d) | |
3512 | |
3513 MX_BASE_REDUCTION_OP (ComplexMatrix, ROW_EXPR, COL_EXPR, 0.0, 0.0); | |
3514 | |
3515 #undef ROW_EXPR | |
3516 #undef COL_EXPR | |
458 | 3517 } |
3518 | |
4329 | 3519 Matrix ComplexMatrix::abs (void) const |
3520 { | |
5275 | 3521 octave_idx_type nr = rows (); |
3522 octave_idx_type nc = cols (); | |
4329 | 3523 |
3524 Matrix retval (nr, nc); | |
3525 | |
5275 | 3526 for (octave_idx_type j = 0; j < nc; j++) |
3527 for (octave_idx_type i = 0; i < nr; i++) | |
5315 | 3528 retval (i, j) = std::abs (elem (i, j)); |
4329 | 3529 |
3530 return retval; | |
3531 } | |
3532 | |
7620
36594d5bbe13
Move diag function into the octave_value class
David Bateman <dbateman@free.fr>
parents:
7544
diff
changeset
|
3533 ComplexMatrix |
5275 | 3534 ComplexMatrix::diag (octave_idx_type k) const |
458 | 3535 { |
7620
36594d5bbe13
Move diag function into the octave_value class
David Bateman <dbateman@free.fr>
parents:
7544
diff
changeset
|
3536 return MArray2<Complex>::diag (k); |
458 | 3537 } |
3538 | |
2354 | 3539 bool |
5275 | 3540 ComplexMatrix::row_is_real_only (octave_idx_type i) const |
2354 | 3541 { |
3542 bool retval = true; | |
3543 | |
5275 | 3544 octave_idx_type nc = columns (); |
3545 | |
3546 for (octave_idx_type j = 0; j < nc; j++) | |
2354 | 3547 { |
5315 | 3548 if (std::imag (elem (i, j)) != 0.0) |
2354 | 3549 { |
3550 retval = false; | |
3551 break; | |
3552 } | |
3553 } | |
3554 | |
3555 return retval; | |
3556 } | |
3557 | |
3558 bool | |
5275 | 3559 ComplexMatrix::column_is_real_only (octave_idx_type j) const |
2354 | 3560 { |
3561 bool retval = true; | |
3562 | |
5275 | 3563 octave_idx_type nr = rows (); |
3564 | |
3565 for (octave_idx_type i = 0; i < nr; i++) | |
2354 | 3566 { |
5315 | 3567 if (std::imag (elem (i, j)) != 0.0) |
2354 | 3568 { |
3569 retval = false; | |
3570 break; | |
3571 } | |
3572 } | |
3573 | |
3574 return retval; | |
3575 } | |
891 | 3576 |
458 | 3577 ComplexColumnVector |
3578 ComplexMatrix::row_min (void) const | |
3579 { | |
5275 | 3580 Array<octave_idx_type> dummy_idx; |
4587 | 3581 return row_min (dummy_idx); |
458 | 3582 } |
3583 | |
3584 ComplexColumnVector | |
5275 | 3585 ComplexMatrix::row_min (Array<octave_idx_type>& idx_arg) const |
458 | 3586 { |
3587 ComplexColumnVector result; | |
3588 | |
5275 | 3589 octave_idx_type nr = rows (); |
3590 octave_idx_type nc = cols (); | |
458 | 3591 |
3592 if (nr > 0 && nc > 0) | |
3593 { | |
3594 result.resize (nr); | |
4587 | 3595 idx_arg.resize (nr); |
458 | 3596 |
5275 | 3597 for (octave_idx_type i = 0; i < nr; i++) |
458 | 3598 { |
2354 | 3599 bool real_only = row_is_real_only (i); |
3600 | |
5275 | 3601 octave_idx_type idx_j; |
4469 | 3602 |
3603 Complex tmp_min; | |
3604 | |
3605 double abs_min = octave_NaN; | |
3606 | |
3607 for (idx_j = 0; idx_j < nc; idx_j++) | |
3608 { | |
3609 tmp_min = elem (i, idx_j); | |
3610 | |
5389 | 3611 if (! xisnan (tmp_min)) |
4469 | 3612 { |
5315 | 3613 abs_min = real_only ? std::real (tmp_min) : std::abs (tmp_min); |
4469 | 3614 break; |
3615 } | |
3616 } | |
3617 | |
5275 | 3618 for (octave_idx_type j = idx_j+1; j < nc; j++) |
4469 | 3619 { |
3620 Complex tmp = elem (i, j); | |
3621 | |
5389 | 3622 if (xisnan (tmp)) |
4469 | 3623 continue; |
3624 | |
5315 | 3625 double abs_tmp = real_only ? std::real (tmp) : std::abs (tmp); |
4469 | 3626 |
3627 if (abs_tmp < abs_min) | |
3628 { | |
3629 idx_j = j; | |
3630 tmp_min = tmp; | |
3631 abs_min = abs_tmp; | |
3632 } | |
3633 } | |
3634 | |
5389 | 3635 if (xisnan (tmp_min)) |
4469 | 3636 { |
3637 result.elem (i) = Complex_NaN_result; | |
4587 | 3638 idx_arg.elem (i) = 0; |
4469 | 3639 } |
891 | 3640 else |
3641 { | |
4469 | 3642 result.elem (i) = tmp_min; |
4587 | 3643 idx_arg.elem (i) = idx_j; |
891 | 3644 } |
458 | 3645 } |
3646 } | |
3647 | |
3648 return result; | |
3649 } | |
3650 | |
3651 ComplexColumnVector | |
3652 ComplexMatrix::row_max (void) const | |
3653 { | |
5275 | 3654 Array<octave_idx_type> dummy_idx; |
4587 | 3655 return row_max (dummy_idx); |
458 | 3656 } |
3657 | |
3658 ComplexColumnVector | |
5275 | 3659 ComplexMatrix::row_max (Array<octave_idx_type>& idx_arg) const |
458 | 3660 { |
3661 ComplexColumnVector result; | |
3662 | |
5275 | 3663 octave_idx_type nr = rows (); |
3664 octave_idx_type nc = cols (); | |
458 | 3665 |
3666 if (nr > 0 && nc > 0) | |
3667 { | |
3668 result.resize (nr); | |
4587 | 3669 idx_arg.resize (nr); |
458 | 3670 |
5275 | 3671 for (octave_idx_type i = 0; i < nr; i++) |
458 | 3672 { |
2354 | 3673 bool real_only = row_is_real_only (i); |
3674 | |
5275 | 3675 octave_idx_type idx_j; |
4469 | 3676 |
3677 Complex tmp_max; | |
3678 | |
3679 double abs_max = octave_NaN; | |
3680 | |
3681 for (idx_j = 0; idx_j < nc; idx_j++) | |
3682 { | |
3683 tmp_max = elem (i, idx_j); | |
3684 | |
5389 | 3685 if (! xisnan (tmp_max)) |
4469 | 3686 { |
5315 | 3687 abs_max = real_only ? std::real (tmp_max) : std::abs (tmp_max); |
4469 | 3688 break; |
3689 } | |
3690 } | |
3691 | |
5275 | 3692 for (octave_idx_type j = idx_j+1; j < nc; j++) |
4469 | 3693 { |
3694 Complex tmp = elem (i, j); | |
3695 | |
5389 | 3696 if (xisnan (tmp)) |
4469 | 3697 continue; |
3698 | |
5315 | 3699 double abs_tmp = real_only ? std::real (tmp) : std::abs (tmp); |
4469 | 3700 |
3701 if (abs_tmp > abs_max) | |
3702 { | |
3703 idx_j = j; | |
3704 tmp_max = tmp; | |
3705 abs_max = abs_tmp; | |
3706 } | |
3707 } | |
3708 | |
5389 | 3709 if (xisnan (tmp_max)) |
4469 | 3710 { |
3711 result.elem (i) = Complex_NaN_result; | |
4587 | 3712 idx_arg.elem (i) = 0; |
4469 | 3713 } |
891 | 3714 else |
3715 { | |
4469 | 3716 result.elem (i) = tmp_max; |
4587 | 3717 idx_arg.elem (i) = idx_j; |
891 | 3718 } |
458 | 3719 } |
3720 } | |
3721 | |
3722 return result; | |
3723 } | |
3724 | |
3725 ComplexRowVector | |
3726 ComplexMatrix::column_min (void) const | |
3727 { | |
5275 | 3728 Array<octave_idx_type> dummy_idx; |
4587 | 3729 return column_min (dummy_idx); |
458 | 3730 } |
3731 | |
3732 ComplexRowVector | |
5275 | 3733 ComplexMatrix::column_min (Array<octave_idx_type>& idx_arg) const |
458 | 3734 { |
3735 ComplexRowVector result; | |
3736 | |
5275 | 3737 octave_idx_type nr = rows (); |
3738 octave_idx_type nc = cols (); | |
458 | 3739 |
3740 if (nr > 0 && nc > 0) | |
3741 { | |
3742 result.resize (nc); | |
4587 | 3743 idx_arg.resize (nc); |
458 | 3744 |
5275 | 3745 for (octave_idx_type j = 0; j < nc; j++) |
458 | 3746 { |
2354 | 3747 bool real_only = column_is_real_only (j); |
3748 | |
5275 | 3749 octave_idx_type idx_i; |
4469 | 3750 |
3751 Complex tmp_min; | |
3752 | |
3753 double abs_min = octave_NaN; | |
3754 | |
3755 for (idx_i = 0; idx_i < nr; idx_i++) | |
3756 { | |
3757 tmp_min = elem (idx_i, j); | |
3758 | |
5389 | 3759 if (! xisnan (tmp_min)) |
4469 | 3760 { |
5315 | 3761 abs_min = real_only ? std::real (tmp_min) : std::abs (tmp_min); |
4469 | 3762 break; |
3763 } | |
3764 } | |
3765 | |
5275 | 3766 for (octave_idx_type i = idx_i+1; i < nr; i++) |
4469 | 3767 { |
3768 Complex tmp = elem (i, j); | |
3769 | |
5389 | 3770 if (xisnan (tmp)) |
4469 | 3771 continue; |
3772 | |
5315 | 3773 double abs_tmp = real_only ? std::real (tmp) : std::abs (tmp); |
4469 | 3774 |
3775 if (abs_tmp < abs_min) | |
3776 { | |
3777 idx_i = i; | |
3778 tmp_min = tmp; | |
3779 abs_min = abs_tmp; | |
3780 } | |
3781 } | |
3782 | |
5389 | 3783 if (xisnan (tmp_min)) |
4469 | 3784 { |
3785 result.elem (j) = Complex_NaN_result; | |
4587 | 3786 idx_arg.elem (j) = 0; |
4469 | 3787 } |
891 | 3788 else |
3789 { | |
4469 | 3790 result.elem (j) = tmp_min; |
4587 | 3791 idx_arg.elem (j) = idx_i; |
891 | 3792 } |
458 | 3793 } |
3794 } | |
3795 | |
3796 return result; | |
3797 } | |
3798 | |
3799 ComplexRowVector | |
3800 ComplexMatrix::column_max (void) const | |
3801 { | |
5275 | 3802 Array<octave_idx_type> dummy_idx; |
4587 | 3803 return column_max (dummy_idx); |
458 | 3804 } |
3805 | |
3806 ComplexRowVector | |
5275 | 3807 ComplexMatrix::column_max (Array<octave_idx_type>& idx_arg) const |
458 | 3808 { |
3809 ComplexRowVector result; | |
3810 | |
5275 | 3811 octave_idx_type nr = rows (); |
3812 octave_idx_type nc = cols (); | |
458 | 3813 |
3814 if (nr > 0 && nc > 0) | |
3815 { | |
3816 result.resize (nc); | |
4587 | 3817 idx_arg.resize (nc); |
458 | 3818 |
5275 | 3819 for (octave_idx_type j = 0; j < nc; j++) |
458 | 3820 { |
2354 | 3821 bool real_only = column_is_real_only (j); |
3822 | |
5275 | 3823 octave_idx_type idx_i; |
4469 | 3824 |
3825 Complex tmp_max; | |
3826 | |
3827 double abs_max = octave_NaN; | |
3828 | |
3829 for (idx_i = 0; idx_i < nr; idx_i++) | |
3830 { | |
3831 tmp_max = elem (idx_i, j); | |
3832 | |
5389 | 3833 if (! xisnan (tmp_max)) |
4469 | 3834 { |
5315 | 3835 abs_max = real_only ? std::real (tmp_max) : std::abs (tmp_max); |
4469 | 3836 break; |
3837 } | |
3838 } | |
3839 | |
5275 | 3840 for (octave_idx_type i = idx_i+1; i < nr; i++) |
4469 | 3841 { |
3842 Complex tmp = elem (i, j); | |
3843 | |
5389 | 3844 if (xisnan (tmp)) |
4469 | 3845 continue; |
3846 | |
5315 | 3847 double abs_tmp = real_only ? std::real (tmp) : std::abs (tmp); |
4469 | 3848 |
3849 if (abs_tmp > abs_max) | |
3850 { | |
3851 idx_i = i; | |
3852 tmp_max = tmp; | |
3853 abs_max = abs_tmp; | |
3854 } | |
3855 } | |
3856 | |
5389 | 3857 if (xisnan (tmp_max)) |
4469 | 3858 { |
3859 result.elem (j) = Complex_NaN_result; | |
4587 | 3860 idx_arg.elem (j) = 0; |
4469 | 3861 } |
891 | 3862 else |
3863 { | |
4469 | 3864 result.elem (j) = tmp_max; |
4587 | 3865 idx_arg.elem (j) = idx_i; |
891 | 3866 } |
458 | 3867 } |
3868 } | |
3869 | |
3870 return result; | |
3871 } | |
3872 | |
3873 // i/o | |
3874 | |
3504 | 3875 std::ostream& |
3876 operator << (std::ostream& os, const ComplexMatrix& a) | |
458 | 3877 { |
5275 | 3878 for (octave_idx_type i = 0; i < a.rows (); i++) |
458 | 3879 { |
5275 | 3880 for (octave_idx_type j = 0; j < a.cols (); j++) |
4130 | 3881 { |
3882 os << " "; | |
3883 octave_write_complex (os, a.elem (i, j)); | |
3884 } | |
458 | 3885 os << "\n"; |
3886 } | |
3887 return os; | |
3888 } | |
3889 | |
3504 | 3890 std::istream& |
3891 operator >> (std::istream& is, ComplexMatrix& a) | |
458 | 3892 { |
5275 | 3893 octave_idx_type nr = a.rows (); |
3894 octave_idx_type nc = a.cols (); | |
458 | 3895 |
3896 if (nr < 1 || nc < 1) | |
3504 | 3897 is.clear (std::ios::badbit); |
458 | 3898 else |
3899 { | |
3900 Complex tmp; | |
5275 | 3901 for (octave_idx_type i = 0; i < nr; i++) |
3902 for (octave_idx_type j = 0; j < nc; j++) | |
458 | 3903 { |
4130 | 3904 tmp = octave_read_complex (is); |
458 | 3905 if (is) |
3906 a.elem (i, j) = tmp; | |
3907 else | |
2993 | 3908 goto done; |
458 | 3909 } |
3910 } | |
3911 | |
2993 | 3912 done: |
3913 | |
458 | 3914 return is; |
3915 } | |
3916 | |
1819 | 3917 ComplexMatrix |
3918 Givens (const Complex& x, const Complex& y) | |
3919 { | |
3920 double cc; | |
3921 Complex cs, temp_r; | |
3922 | |
3887 | 3923 F77_FUNC (zlartg, ZLARTG) (x, y, cc, cs, temp_r); |
1819 | 3924 |
3925 ComplexMatrix g (2, 2); | |
3926 | |
3927 g.elem (0, 0) = cc; | |
3928 g.elem (1, 1) = cc; | |
3929 g.elem (0, 1) = cs; | |
3930 g.elem (1, 0) = -conj (cs); | |
3931 | |
3932 return g; | |
3933 } | |
3934 | |
3935 ComplexMatrix | |
3936 Sylvester (const ComplexMatrix& a, const ComplexMatrix& b, | |
3937 const ComplexMatrix& c) | |
3938 { | |
3939 ComplexMatrix retval; | |
3940 | |
5775 | 3941 // FIXME -- need to check that a, b, and c are all the same |
1819 | 3942 // size. |
3943 | |
3944 // Compute Schur decompositions | |
3945 | |
3946 ComplexSCHUR as (a, "U"); | |
3947 ComplexSCHUR bs (b, "U"); | |
3948 | |
3949 // Transform c to new coordinates. | |
3950 | |
3951 ComplexMatrix ua = as.unitary_matrix (); | |
3952 ComplexMatrix sch_a = as.schur_matrix (); | |
3953 | |
3954 ComplexMatrix ub = bs.unitary_matrix (); | |
3955 ComplexMatrix sch_b = bs.schur_matrix (); | |
3956 | |
3957 ComplexMatrix cx = ua.hermitian () * c * ub; | |
3958 | |
3959 // Solve the sylvester equation, back-transform, and return the | |
3960 // solution. | |
3961 | |
5275 | 3962 octave_idx_type a_nr = a.rows (); |
3963 octave_idx_type b_nr = b.rows (); | |
1819 | 3964 |
3965 double scale; | |
5275 | 3966 octave_idx_type info; |
1950 | 3967 |
3968 Complex *pa = sch_a.fortran_vec (); | |
3969 Complex *pb = sch_b.fortran_vec (); | |
3970 Complex *px = cx.fortran_vec (); | |
1819 | 3971 |
4552 | 3972 F77_XFCN (ztrsyl, ZTRSYL, (F77_CONST_CHAR_ARG2 ("N", 1), |
3973 F77_CONST_CHAR_ARG2 ("N", 1), | |
3974 1, a_nr, b_nr, pa, a_nr, pb, | |
3975 b_nr, px, a_nr, scale, info | |
3976 F77_CHAR_ARG_LEN (1) | |
3977 F77_CHAR_ARG_LEN (1))); | |
1950 | 3978 |
7482
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
3979 // FIXME -- check info? |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
3980 |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
3981 retval = -ua * cx * ub.hermitian (); |
1819 | 3982 |
3983 return retval; | |
3984 } | |
3985 | |
2828 | 3986 ComplexMatrix |
3987 operator * (const ComplexMatrix& m, const Matrix& a) | |
3988 { | |
3989 ComplexMatrix tmp (a); | |
3990 return m * tmp; | |
3991 } | |
3992 | |
3993 ComplexMatrix | |
3994 operator * (const Matrix& m, const ComplexMatrix& a) | |
3995 { | |
3996 ComplexMatrix tmp (m); | |
3997 return tmp * a; | |
3998 } | |
3999 | |
6162 | 4000 /* Simple Dot Product, Matrix-Vector and Matrix-Matrix Unit tests |
4001 %!assert([1+i 2+i 3+i] * [ 4+i ; 5+i ; 6+i], 29+21i, 1e-14) | |
4002 %!assert([1+i 2+i ; 3+i 4+i ] * [5+i ; 6+i], [15 + 14i ; 37 + 18i], 1e-14) | |
4003 %!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) | |
4004 */ | |
4005 | |
4006 /* Test some simple identities | |
4007 %!shared M, cv, rv | |
4008 %! M = randn(10,10)+i*rand(10,10); | |
4009 %! cv = randn(10,1)+i*rand(10,1); | |
4010 %! rv = randn(1,10)+i*rand(1,10); | |
4011 %!assert([M*cv,M*cv],M*[cv,cv],1e-14) | |
4012 %!assert([rv*M;rv*M],[rv;rv]*M,1e-14) | |
4013 %!assert(2*rv*cv,[rv,rv]*[cv;cv],1e-14) | |
4014 */ | |
4015 | |
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
|
4016 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
|
4017 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
|
4018 { |
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 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
|
4020 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
|
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 |
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 // 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
|
4024 |
2828 | 4025 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
|
4026 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
|
4027 bool transb, bool conjb, const ComplexMatrix& b) |
2828 | 4028 { |
4029 ComplexMatrix retval; | |
4030 | |
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
|
4031 // 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
|
4032 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
|
4033 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
|
4034 |
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 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
|
4036 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
|
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 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
|
4039 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
|
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 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
|
4042 gripe_nonconformant ("operator *", a_nr, a_nc, b_nr, b_nc); |
2828 | 4043 else |
4044 { | |
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
|
4045 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
|
4046 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
|
4047 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
|
4048 { |
776791438957
map symmetric cases to xHERK, xSYRK
Jaroslav Hajek <highegg@gmail.com>
parents:
7800
diff
changeset
|
4049 octave_idx_type lda = a.rows (); |
776791438957
map symmetric cases to xHERK, xSYRK
Jaroslav Hajek <highegg@gmail.com>
parents:
7800
diff
changeset
|
4050 |
776791438957
map symmetric cases to xHERK, xSYRK
Jaroslav Hajek <highegg@gmail.com>
parents:
7800
diff
changeset
|
4051 retval.resize (a_nr, b_nc); |
776791438957
map symmetric cases to xHERK, xSYRK
Jaroslav Hajek <highegg@gmail.com>
parents:
7800
diff
changeset
|
4052 Complex *c = retval.fortran_vec (); |
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 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
|
4055 if (conja || conjb) |
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 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
|
4058 F77_CONST_CHAR_ARG2 (ctransa, 1), |
776791438957
map symmetric cases to xHERK, xSYRK
Jaroslav Hajek <highegg@gmail.com>
parents:
7800
diff
changeset
|
4059 a_nr, a_nc, 1.0, |
776791438957
map symmetric cases to xHERK, xSYRK
Jaroslav Hajek <highegg@gmail.com>
parents:
7800
diff
changeset
|
4060 a.data (), lda, 0.0, c, a_nr |
776791438957
map symmetric cases to xHERK, xSYRK
Jaroslav Hajek <highegg@gmail.com>
parents:
7800
diff
changeset
|
4061 F77_CHAR_ARG_LEN (1) |
776791438957
map symmetric cases to xHERK, xSYRK
Jaroslav Hajek <highegg@gmail.com>
parents:
7800
diff
changeset
|
4062 F77_CHAR_ARG_LEN (1))); |
776791438957
map symmetric cases to xHERK, xSYRK
Jaroslav Hajek <highegg@gmail.com>
parents:
7800
diff
changeset
|
4063 for (int j = 0; j < a_nr; j++) |
776791438957
map symmetric cases to xHERK, xSYRK
Jaroslav Hajek <highegg@gmail.com>
parents:
7800
diff
changeset
|
4064 for (int i = 0; i < j; i++) |
776791438957
map symmetric cases to xHERK, xSYRK
Jaroslav Hajek <highegg@gmail.com>
parents:
7800
diff
changeset
|
4065 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
|
4066 } |
776791438957
map symmetric cases to xHERK, xSYRK
Jaroslav Hajek <highegg@gmail.com>
parents:
7800
diff
changeset
|
4067 else |
776791438957
map symmetric cases to xHERK, xSYRK
Jaroslav Hajek <highegg@gmail.com>
parents:
7800
diff
changeset
|
4068 { |
776791438957
map symmetric cases to xHERK, xSYRK
Jaroslav Hajek <highegg@gmail.com>
parents:
7800
diff
changeset
|
4069 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
|
4070 F77_CONST_CHAR_ARG2 (ctransa, 1), |
776791438957
map symmetric cases to xHERK, xSYRK
Jaroslav Hajek <highegg@gmail.com>
parents:
7800
diff
changeset
|
4071 a_nr, a_nc, 1.0, |
776791438957
map symmetric cases to xHERK, xSYRK
Jaroslav Hajek <highegg@gmail.com>
parents:
7800
diff
changeset
|
4072 a.data (), lda, 0.0, c, a_nr |
776791438957
map symmetric cases to xHERK, xSYRK
Jaroslav Hajek <highegg@gmail.com>
parents:
7800
diff
changeset
|
4073 F77_CHAR_ARG_LEN (1) |
776791438957
map symmetric cases to xHERK, xSYRK
Jaroslav Hajek <highegg@gmail.com>
parents:
7800
diff
changeset
|
4074 F77_CHAR_ARG_LEN (1))); |
776791438957
map symmetric cases to xHERK, xSYRK
Jaroslav Hajek <highegg@gmail.com>
parents:
7800
diff
changeset
|
4075 for (int j = 0; j < a_nr; j++) |
776791438957
map symmetric cases to xHERK, xSYRK
Jaroslav Hajek <highegg@gmail.com>
parents:
7800
diff
changeset
|
4076 for (int i = 0; i < j; i++) |
776791438957
map symmetric cases to xHERK, xSYRK
Jaroslav Hajek <highegg@gmail.com>
parents:
7800
diff
changeset
|
4077 retval.xelem (j,i) = retval.xelem (i,j); |
776791438957
map symmetric cases to xHERK, xSYRK
Jaroslav Hajek <highegg@gmail.com>
parents:
7800
diff
changeset
|
4078 |
776791438957
map symmetric cases to xHERK, xSYRK
Jaroslav Hajek <highegg@gmail.com>
parents:
7800
diff
changeset
|
4079 } |
776791438957
map symmetric cases to xHERK, xSYRK
Jaroslav Hajek <highegg@gmail.com>
parents:
7800
diff
changeset
|
4080 |
776791438957
map symmetric cases to xHERK, xSYRK
Jaroslav Hajek <highegg@gmail.com>
parents:
7800
diff
changeset
|
4081 } |
2828 | 4082 else |
4083 { | |
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
|
4084 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
|
4085 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
|
4086 |
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 retval.resize (a_nr, b_nc); |
2828 | 4088 Complex *c = retval.fortran_vec (); |
4089 | |
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
|
4090 if (b_nc == 1 && a_nr == 1) |
5983 | 4091 { |
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
|
4092 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
|
4093 { |
5861b95e9879
support for compound operators, implement trans_mul, mul_trans, herm_mul and mul_herm
Jaroslav Hajek <highegg@gmail.com>
parents:
7789
diff
changeset
|
4094 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
|
4095 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
|
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 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
|
4098 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
|
4099 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
|
4100 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
|
4101 } |
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 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
|
4103 { |
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 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
|
4105 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
|
4106 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
|
4107 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
|
4108 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
|
4109 } |
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 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
|
4111 { |
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 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
|
4113 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
|
4114 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
|
4115 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
|
4116 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
|
4117 } |
5983 | 4118 else |
6390 | 4119 { |
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
|
4120 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
|
4121 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
|
4122 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
|
4123 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
|
4124 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
|
4125 lda, b.data (), ldb, 0.0, c, a_nr |
6390 | 4126 F77_CHAR_ARG_LEN (1) |
4127 F77_CHAR_ARG_LEN (1))); | |
4128 } | |
2828 | 4129 } |
4130 } | |
4131 | |
4132 return retval; | |
4133 } | |
4134 | |
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
|
4135 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
|
4136 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
|
4137 { |
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 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
|
4139 } |
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 |
5775 | 4141 // FIXME -- it would be nice to share code among the min/max |
4309 | 4142 // functions below. |
4143 | |
4144 #define EMPTY_RETURN_CHECK(T) \ | |
4145 if (nr == 0 || nc == 0) \ | |
4146 return T (nr, nc); | |
4147 | |
4148 ComplexMatrix | |
4149 min (const Complex& c, const ComplexMatrix& m) | |
4150 { | |
5275 | 4151 octave_idx_type nr = m.rows (); |
4152 octave_idx_type nc = m.columns (); | |
4309 | 4153 |
4154 EMPTY_RETURN_CHECK (ComplexMatrix); | |
4155 | |
4156 ComplexMatrix result (nr, nc); | |
4157 | |
5275 | 4158 for (octave_idx_type j = 0; j < nc; j++) |
4159 for (octave_idx_type i = 0; i < nr; i++) | |
4309 | 4160 { |
4161 OCTAVE_QUIT; | |
4162 result (i, j) = xmin (c, m (i, j)); | |
4163 } | |
4164 | |
4165 return result; | |
4166 } | |
4167 | |
4168 ComplexMatrix | |
4169 min (const ComplexMatrix& m, const Complex& c) | |
4170 { | |
5275 | 4171 octave_idx_type nr = m.rows (); |
4172 octave_idx_type nc = m.columns (); | |
4309 | 4173 |
4174 EMPTY_RETURN_CHECK (ComplexMatrix); | |
4175 | |
4176 ComplexMatrix result (nr, nc); | |
4177 | |
5275 | 4178 for (octave_idx_type j = 0; j < nc; j++) |
4179 for (octave_idx_type i = 0; i < nr; i++) | |
4309 | 4180 { |
4181 OCTAVE_QUIT; | |
4182 result (i, j) = xmin (m (i, j), c); | |
4183 } | |
4184 | |
4185 return result; | |
4186 } | |
4187 | |
4188 ComplexMatrix | |
4189 min (const ComplexMatrix& a, const ComplexMatrix& b) | |
4190 { | |
5275 | 4191 octave_idx_type nr = a.rows (); |
4192 octave_idx_type nc = a.columns (); | |
4309 | 4193 |
4194 if (nr != b.rows () || nc != b.columns ()) | |
4195 { | |
4196 (*current_liboctave_error_handler) | |
4197 ("two-arg min expecting args of same size"); | |
4198 return ComplexMatrix (); | |
4199 } | |
4200 | |
4201 EMPTY_RETURN_CHECK (ComplexMatrix); | |
4202 | |
4203 ComplexMatrix result (nr, nc); | |
4204 | |
5275 | 4205 for (octave_idx_type j = 0; j < nc; j++) |
4309 | 4206 { |
4207 int columns_are_real_only = 1; | |
5275 | 4208 for (octave_idx_type i = 0; i < nr; i++) |
4309 | 4209 { |
4210 OCTAVE_QUIT; | |
5315 | 4211 if (std::imag (a (i, j)) != 0.0 || std::imag (b (i, j)) != 0.0) |
4309 | 4212 { |
4213 columns_are_real_only = 0; | |
4214 break; | |
4215 } | |
4216 } | |
4217 | |
4218 if (columns_are_real_only) | |
4219 { | |
5275 | 4220 for (octave_idx_type i = 0; i < nr; i++) |
5315 | 4221 result (i, j) = xmin (std::real (a (i, j)), std::real (b (i, j))); |
4309 | 4222 } |
4223 else | |
4224 { | |
5275 | 4225 for (octave_idx_type i = 0; i < nr; i++) |
4309 | 4226 { |
4227 OCTAVE_QUIT; | |
4228 result (i, j) = xmin (a (i, j), b (i, j)); | |
4229 } | |
4230 } | |
4231 } | |
4232 | |
4233 return result; | |
4234 } | |
4235 | |
4236 ComplexMatrix | |
4237 max (const Complex& c, const ComplexMatrix& m) | |
4238 { | |
5275 | 4239 octave_idx_type nr = m.rows (); |
4240 octave_idx_type nc = m.columns (); | |
4309 | 4241 |
4242 EMPTY_RETURN_CHECK (ComplexMatrix); | |
4243 | |
4244 ComplexMatrix result (nr, nc); | |
4245 | |
5275 | 4246 for (octave_idx_type j = 0; j < nc; j++) |
4247 for (octave_idx_type i = 0; i < nr; i++) | |
4309 | 4248 { |
4249 OCTAVE_QUIT; | |
4250 result (i, j) = xmax (c, m (i, j)); | |
4251 } | |
4252 | |
4253 return result; | |
4254 } | |
4255 | |
4256 ComplexMatrix | |
4257 max (const ComplexMatrix& m, const Complex& c) | |
4258 { | |
5275 | 4259 octave_idx_type nr = m.rows (); |
4260 octave_idx_type nc = m.columns (); | |
4309 | 4261 |
4262 EMPTY_RETURN_CHECK (ComplexMatrix); | |
4263 | |
4264 ComplexMatrix result (nr, nc); | |
4265 | |
5275 | 4266 for (octave_idx_type j = 0; j < nc; j++) |
4267 for (octave_idx_type i = 0; i < nr; i++) | |
4309 | 4268 { |
4269 OCTAVE_QUIT; | |
4270 result (i, j) = xmax (m (i, j), c); | |
4271 } | |
4272 | |
4273 return result; | |
4274 } | |
4275 | |
4276 ComplexMatrix | |
4277 max (const ComplexMatrix& a, const ComplexMatrix& b) | |
4278 { | |
5275 | 4279 octave_idx_type nr = a.rows (); |
4280 octave_idx_type nc = a.columns (); | |
4309 | 4281 |
4282 if (nr != b.rows () || nc != b.columns ()) | |
4283 { | |
4284 (*current_liboctave_error_handler) | |
4285 ("two-arg max expecting args of same size"); | |
4286 return ComplexMatrix (); | |
4287 } | |
4288 | |
4289 EMPTY_RETURN_CHECK (ComplexMatrix); | |
4290 | |
4291 ComplexMatrix result (nr, nc); | |
4292 | |
5275 | 4293 for (octave_idx_type j = 0; j < nc; j++) |
4309 | 4294 { |
4295 int columns_are_real_only = 1; | |
5275 | 4296 for (octave_idx_type i = 0; i < nr; i++) |
4309 | 4297 { |
4298 OCTAVE_QUIT; | |
5315 | 4299 if (std::imag (a (i, j)) != 0.0 || std::imag (b (i, j)) != 0.0) |
4309 | 4300 { |
4301 columns_are_real_only = 0; | |
4302 break; | |
4303 } | |
4304 } | |
4305 | |
4306 if (columns_are_real_only) | |
4307 { | |
5275 | 4308 for (octave_idx_type i = 0; i < nr; i++) |
4309 | 4309 { |
4310 OCTAVE_QUIT; | |
5315 | 4311 result (i, j) = xmax (std::real (a (i, j)), std::real (b (i, j))); |
4309 | 4312 } |
4313 } | |
4314 else | |
4315 { | |
5275 | 4316 for (octave_idx_type i = 0; i < nr; i++) |
4309 | 4317 { |
4318 OCTAVE_QUIT; | |
4319 result (i, j) = xmax (a (i, j), b (i, j)); | |
4320 } | |
4321 } | |
4322 } | |
4323 | |
4324 return result; | |
4325 } | |
4326 | |
5315 | 4327 MS_CMP_OPS(ComplexMatrix, std::real, Complex, std::real) |
3504 | 4328 MS_BOOL_OPS(ComplexMatrix, Complex, 0.0) |
2870 | 4329 |
5315 | 4330 SM_CMP_OPS(Complex, std::real, ComplexMatrix, std::real) |
3504 | 4331 SM_BOOL_OPS(Complex, ComplexMatrix, 0.0) |
2870 | 4332 |
5315 | 4333 MM_CMP_OPS(ComplexMatrix, std::real, ComplexMatrix, std::real) |
3504 | 4334 MM_BOOL_OPS(ComplexMatrix, ComplexMatrix, 0.0) |
2870 | 4335 |
458 | 4336 /* |
4337 ;;; Local Variables: *** | |
4338 ;;; mode: C++ *** | |
4339 ;;; End: *** | |
4340 */ |