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