Mercurial > hg > octave-nkf
annotate liboctave/dMatrix.cc @ 8337:e02242c54c49
reuse matrix type detected in det
author | Jaroslav Hajek <highegg@gmail.com> |
---|---|
date | Wed, 19 Nov 2008 16:55:47 +0100 |
parents | 9813c07ca946 |
children | 445d27d79f4e |
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 |
8337
e02242c54c49
reuse matrix type detected in det
Jaroslav Hajek <highegg@gmail.com>
parents:
8336
diff
changeset
|
1263 if (typ == MatrixType::Unknown) |
e02242c54c49
reuse matrix type detected in det
Jaroslav Hajek <highegg@gmail.com>
parents:
8336
diff
changeset
|
1264 typ = mattype.type (*this); |
e02242c54c49
reuse matrix type detected in det
Jaroslav Hajek <highegg@gmail.com>
parents:
8336
diff
changeset
|
1265 |
8336
9813c07ca946
make det take advantage of matrix type
Jaroslav Hajek <highegg@gmail.com>
parents:
8335
diff
changeset
|
1266 if (typ == MatrixType::Lower || typ == MatrixType::Upper) |
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 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
|
1269 retval *= elem (i,i); |
9813c07ca946
make det take advantage of matrix type
Jaroslav Hajek <highegg@gmail.com>
parents:
8335
diff
changeset
|
1270 } |
9813c07ca946
make det take advantage of matrix type
Jaroslav Hajek <highegg@gmail.com>
parents:
8335
diff
changeset
|
1271 else if (typ == MatrixType::Hermitian) |
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 Matrix atmp = *this; |
9813c07ca946
make det take advantage of matrix type
Jaroslav Hajek <highegg@gmail.com>
parents:
8335
diff
changeset
|
1274 double *tmp_data = atmp.fortran_vec (); |
9813c07ca946
make det take advantage of matrix type
Jaroslav Hajek <highegg@gmail.com>
parents:
8335
diff
changeset
|
1275 |
9813c07ca946
make det take advantage of matrix type
Jaroslav Hajek <highegg@gmail.com>
parents:
8335
diff
changeset
|
1276 info = 0; |
9813c07ca946
make det take advantage of matrix type
Jaroslav Hajek <highegg@gmail.com>
parents:
8335
diff
changeset
|
1277 double anorm = 0; |
9813c07ca946
make det take advantage of matrix type
Jaroslav Hajek <highegg@gmail.com>
parents:
8335
diff
changeset
|
1278 if (calc_cond) anorm = xnorm (*this, 1); |
9813c07ca946
make det take advantage of matrix type
Jaroslav Hajek <highegg@gmail.com>
parents:
8335
diff
changeset
|
1279 |
9813c07ca946
make det take advantage of matrix type
Jaroslav Hajek <highegg@gmail.com>
parents:
8335
diff
changeset
|
1280 |
9813c07ca946
make det take advantage of matrix type
Jaroslav Hajek <highegg@gmail.com>
parents:
8335
diff
changeset
|
1281 char job = 'L'; |
9813c07ca946
make det take advantage of matrix type
Jaroslav Hajek <highegg@gmail.com>
parents:
8335
diff
changeset
|
1282 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
|
1283 tmp_data, nr, info |
9813c07ca946
make det take advantage of matrix type
Jaroslav Hajek <highegg@gmail.com>
parents:
8335
diff
changeset
|
1284 F77_CHAR_ARG_LEN (1))); |
9813c07ca946
make det take advantage of matrix type
Jaroslav Hajek <highegg@gmail.com>
parents:
8335
diff
changeset
|
1285 |
9813c07ca946
make det take advantage of matrix type
Jaroslav Hajek <highegg@gmail.com>
parents:
8335
diff
changeset
|
1286 if (info != 0) |
9813c07ca946
make det take advantage of matrix type
Jaroslav Hajek <highegg@gmail.com>
parents:
8335
diff
changeset
|
1287 { |
9813c07ca946
make det take advantage of matrix type
Jaroslav Hajek <highegg@gmail.com>
parents:
8335
diff
changeset
|
1288 rcon = 0.0; |
9813c07ca946
make det take advantage of matrix type
Jaroslav Hajek <highegg@gmail.com>
parents:
8335
diff
changeset
|
1289 mattype.mark_as_unsymmetric (); |
9813c07ca946
make det take advantage of matrix type
Jaroslav Hajek <highegg@gmail.com>
parents:
8335
diff
changeset
|
1290 typ = MatrixType::Full; |
9813c07ca946
make det take advantage of matrix type
Jaroslav Hajek <highegg@gmail.com>
parents:
8335
diff
changeset
|
1291 } |
9813c07ca946
make det take advantage of matrix type
Jaroslav Hajek <highegg@gmail.com>
parents:
8335
diff
changeset
|
1292 else |
9813c07ca946
make det take advantage of matrix type
Jaroslav Hajek <highegg@gmail.com>
parents:
8335
diff
changeset
|
1293 { |
9813c07ca946
make det take advantage of matrix type
Jaroslav Hajek <highegg@gmail.com>
parents:
8335
diff
changeset
|
1294 Array<double> z (3 * nc); |
9813c07ca946
make det take advantage of matrix type
Jaroslav Hajek <highegg@gmail.com>
parents:
8335
diff
changeset
|
1295 double *pz = z.fortran_vec (); |
9813c07ca946
make det take advantage of matrix type
Jaroslav Hajek <highegg@gmail.com>
parents:
8335
diff
changeset
|
1296 Array<octave_idx_type> iz (nc); |
9813c07ca946
make det take advantage of matrix type
Jaroslav Hajek <highegg@gmail.com>
parents:
8335
diff
changeset
|
1297 octave_idx_type *piz = iz.fortran_vec (); |
9813c07ca946
make det take advantage of matrix type
Jaroslav Hajek <highegg@gmail.com>
parents:
8335
diff
changeset
|
1298 |
9813c07ca946
make det take advantage of matrix type
Jaroslav Hajek <highegg@gmail.com>
parents:
8335
diff
changeset
|
1299 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
|
1300 nr, tmp_data, nr, anorm, |
9813c07ca946
make det take advantage of matrix type
Jaroslav Hajek <highegg@gmail.com>
parents:
8335
diff
changeset
|
1301 rcon, pz, piz, info |
9813c07ca946
make det take advantage of matrix type
Jaroslav Hajek <highegg@gmail.com>
parents:
8335
diff
changeset
|
1302 F77_CHAR_ARG_LEN (1))); |
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 if (info != 0) |
9813c07ca946
make det take advantage of matrix type
Jaroslav Hajek <highegg@gmail.com>
parents:
8335
diff
changeset
|
1305 rcon = 0.0; |
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 for (octave_idx_type i = 0; i < nc; i++) |
8337
e02242c54c49
reuse matrix type detected in det
Jaroslav Hajek <highegg@gmail.com>
parents:
8336
diff
changeset
|
1308 retval *= atmp (i,i); |
8336
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 retval = retval.square (); |
9813c07ca946
make det take advantage of matrix type
Jaroslav Hajek <highegg@gmail.com>
parents:
8335
diff
changeset
|
1311 } |
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 else if (typ != MatrixType::Full) |
9813c07ca946
make det take advantage of matrix type
Jaroslav Hajek <highegg@gmail.com>
parents:
8335
diff
changeset
|
1314 (*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
|
1315 |
9813c07ca946
make det take advantage of matrix type
Jaroslav Hajek <highegg@gmail.com>
parents:
8335
diff
changeset
|
1316 if (typ == MatrixType::Full) |
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 Array<octave_idx_type> ipvt (nr); |
9813c07ca946
make det take advantage of matrix type
Jaroslav Hajek <highegg@gmail.com>
parents:
8335
diff
changeset
|
1319 octave_idx_type *pipvt = ipvt.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 Matrix atmp = *this; |
9813c07ca946
make det take advantage of matrix type
Jaroslav Hajek <highegg@gmail.com>
parents:
8335
diff
changeset
|
1322 double *tmp_data = atmp.fortran_vec (); |
9813c07ca946
make det take advantage of matrix type
Jaroslav Hajek <highegg@gmail.com>
parents:
8335
diff
changeset
|
1323 |
9813c07ca946
make det take advantage of matrix type
Jaroslav Hajek <highegg@gmail.com>
parents:
8335
diff
changeset
|
1324 info = 0; |
9813c07ca946
make det take advantage of matrix type
Jaroslav Hajek <highegg@gmail.com>
parents:
8335
diff
changeset
|
1325 |
9813c07ca946
make det take advantage of matrix type
Jaroslav Hajek <highegg@gmail.com>
parents:
8335
diff
changeset
|
1326 // 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
|
1327 double anorm = 0; |
9813c07ca946
make det take advantage of matrix type
Jaroslav Hajek <highegg@gmail.com>
parents:
8335
diff
changeset
|
1328 if (calc_cond) anorm = xnorm (*this, 1); |
9813c07ca946
make det take advantage of matrix type
Jaroslav Hajek <highegg@gmail.com>
parents:
8335
diff
changeset
|
1329 |
9813c07ca946
make det take advantage of matrix type
Jaroslav Hajek <highegg@gmail.com>
parents:
8335
diff
changeset
|
1330 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
|
1331 |
9813c07ca946
make det take advantage of matrix type
Jaroslav Hajek <highegg@gmail.com>
parents:
8335
diff
changeset
|
1332 // 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
|
1333 rcon = 0.0; |
9813c07ca946
make det take advantage of matrix type
Jaroslav Hajek <highegg@gmail.com>
parents:
8335
diff
changeset
|
1334 if (info != 0) |
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 info = -1; |
9813c07ca946
make det take advantage of matrix type
Jaroslav Hajek <highegg@gmail.com>
parents:
8335
diff
changeset
|
1337 retval = DET (); |
9813c07ca946
make det take advantage of matrix type
Jaroslav Hajek <highegg@gmail.com>
parents:
8335
diff
changeset
|
1338 } |
9813c07ca946
make det take advantage of matrix type
Jaroslav Hajek <highegg@gmail.com>
parents:
8335
diff
changeset
|
1339 else |
9813c07ca946
make det take advantage of matrix type
Jaroslav Hajek <highegg@gmail.com>
parents:
8335
diff
changeset
|
1340 { |
9813c07ca946
make det take advantage of matrix type
Jaroslav Hajek <highegg@gmail.com>
parents:
8335
diff
changeset
|
1341 if (calc_cond) |
9813c07ca946
make det take advantage of matrix type
Jaroslav Hajek <highegg@gmail.com>
parents:
8335
diff
changeset
|
1342 { |
9813c07ca946
make det take advantage of matrix type
Jaroslav Hajek <highegg@gmail.com>
parents:
8335
diff
changeset
|
1343 // 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
|
1344 char job = '1'; |
9813c07ca946
make det take advantage of matrix type
Jaroslav Hajek <highegg@gmail.com>
parents:
8335
diff
changeset
|
1345 Array<double> z (4 * nc); |
9813c07ca946
make det take advantage of matrix type
Jaroslav Hajek <highegg@gmail.com>
parents:
8335
diff
changeset
|
1346 double *pz = z.fortran_vec (); |
9813c07ca946
make det take advantage of matrix type
Jaroslav Hajek <highegg@gmail.com>
parents:
8335
diff
changeset
|
1347 Array<octave_idx_type> iz (nc); |
9813c07ca946
make det take advantage of matrix type
Jaroslav Hajek <highegg@gmail.com>
parents:
8335
diff
changeset
|
1348 octave_idx_type *piz = iz.fortran_vec (); |
9813c07ca946
make det take advantage of matrix type
Jaroslav Hajek <highegg@gmail.com>
parents:
8335
diff
changeset
|
1349 |
9813c07ca946
make det take advantage of matrix type
Jaroslav Hajek <highegg@gmail.com>
parents:
8335
diff
changeset
|
1350 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
|
1351 nc, tmp_data, nr, anorm, |
9813c07ca946
make det take advantage of matrix type
Jaroslav Hajek <highegg@gmail.com>
parents:
8335
diff
changeset
|
1352 rcon, pz, piz, info |
9813c07ca946
make det take advantage of matrix type
Jaroslav Hajek <highegg@gmail.com>
parents:
8335
diff
changeset
|
1353 F77_CHAR_ARG_LEN (1))); |
8335 | 1354 } |
8336
9813c07ca946
make det take advantage of matrix type
Jaroslav Hajek <highegg@gmail.com>
parents:
8335
diff
changeset
|
1355 |
9813c07ca946
make det take advantage of matrix type
Jaroslav Hajek <highegg@gmail.com>
parents:
8335
diff
changeset
|
1356 if (info != 0) |
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 info = -1; |
9813c07ca946
make det take advantage of matrix type
Jaroslav Hajek <highegg@gmail.com>
parents:
8335
diff
changeset
|
1359 retval = DET (); |
9813c07ca946
make det take advantage of matrix type
Jaroslav Hajek <highegg@gmail.com>
parents:
8335
diff
changeset
|
1360 } |
9813c07ca946
make det take advantage of matrix type
Jaroslav Hajek <highegg@gmail.com>
parents:
8335
diff
changeset
|
1361 else |
9813c07ca946
make det take advantage of matrix type
Jaroslav Hajek <highegg@gmail.com>
parents:
8335
diff
changeset
|
1362 { |
9813c07ca946
make det take advantage of matrix type
Jaroslav Hajek <highegg@gmail.com>
parents:
8335
diff
changeset
|
1363 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
|
1364 { |
9813c07ca946
make det take advantage of matrix type
Jaroslav Hajek <highegg@gmail.com>
parents:
8335
diff
changeset
|
1365 double c = atmp(i,i); |
9813c07ca946
make det take advantage of matrix type
Jaroslav Hajek <highegg@gmail.com>
parents:
8335
diff
changeset
|
1366 retval *= (ipvt(i) != (i+1)) ? -c : c; |
9813c07ca946
make det take advantage of matrix type
Jaroslav Hajek <highegg@gmail.com>
parents:
8335
diff
changeset
|
1367 } |
9813c07ca946
make det take advantage of matrix type
Jaroslav Hajek <highegg@gmail.com>
parents:
8335
diff
changeset
|
1368 } |
9813c07ca946
make det take advantage of matrix type
Jaroslav Hajek <highegg@gmail.com>
parents:
8335
diff
changeset
|
1369 } |
9813c07ca946
make det take advantage of matrix type
Jaroslav Hajek <highegg@gmail.com>
parents:
8335
diff
changeset
|
1370 } |
458 | 1371 } |
1372 | |
1373 return retval; | |
1374 } | |
1375 | |
7788 | 1376 double |
1377 Matrix::rcond (void) const | |
1378 { | |
1379 MatrixType mattype (*this); | |
1380 return rcond (mattype); | |
1381 } | |
1382 | |
1383 double | |
1384 Matrix::rcond (MatrixType &mattype) const | |
1385 { | |
1386 double rcon; | |
1387 octave_idx_type nr = rows (); | |
1388 octave_idx_type nc = cols (); | |
1389 | |
1390 if (nr != nc) | |
1391 (*current_liboctave_error_handler) ("matrix must be square"); | |
1392 else if (nr == 0 || nc == 0) | |
1393 rcon = octave_Inf; | |
1394 else | |
1395 { | |
1396 int typ = mattype.type (); | |
1397 | |
1398 if (typ == MatrixType::Unknown) | |
1399 typ = mattype.type (*this); | |
1400 | |
1401 // Only calculate the condition number for LU/Cholesky | |
1402 if (typ == MatrixType::Upper) | |
1403 { | |
1404 const double *tmp_data = fortran_vec (); | |
1405 octave_idx_type info = 0; | |
1406 char norm = '1'; | |
1407 char uplo = 'U'; | |
1408 char dia = 'N'; | |
1409 | |
1410 Array<double> z (3 * nc); | |
1411 double *pz = z.fortran_vec (); | |
1412 Array<octave_idx_type> iz (nc); | |
1413 octave_idx_type *piz = iz.fortran_vec (); | |
1414 | |
1415 F77_XFCN (dtrcon, DTRCON, (F77_CONST_CHAR_ARG2 (&norm, 1), | |
1416 F77_CONST_CHAR_ARG2 (&uplo, 1), | |
1417 F77_CONST_CHAR_ARG2 (&dia, 1), | |
1418 nr, tmp_data, nr, rcon, | |
1419 pz, piz, info | |
1420 F77_CHAR_ARG_LEN (1) | |
1421 F77_CHAR_ARG_LEN (1) | |
1422 F77_CHAR_ARG_LEN (1))); | |
1423 | |
1424 if (info != 0) | |
1425 rcon = 0.0; | |
1426 } | |
1427 else if (typ == MatrixType::Permuted_Upper) | |
1428 (*current_liboctave_error_handler) | |
1429 ("permuted triangular matrix not implemented"); | |
1430 else if (typ == MatrixType::Lower) | |
1431 { | |
1432 const double *tmp_data = fortran_vec (); | |
1433 octave_idx_type info = 0; | |
1434 char norm = '1'; | |
1435 char uplo = 'L'; | |
1436 char dia = 'N'; | |
1437 | |
1438 Array<double> z (3 * nc); | |
1439 double *pz = z.fortran_vec (); | |
1440 Array<octave_idx_type> iz (nc); | |
1441 octave_idx_type *piz = iz.fortran_vec (); | |
1442 | |
1443 F77_XFCN (dtrcon, DTRCON, (F77_CONST_CHAR_ARG2 (&norm, 1), | |
1444 F77_CONST_CHAR_ARG2 (&uplo, 1), | |
1445 F77_CONST_CHAR_ARG2 (&dia, 1), | |
1446 nr, tmp_data, nr, rcon, | |
1447 pz, piz, info | |
1448 F77_CHAR_ARG_LEN (1) | |
1449 F77_CHAR_ARG_LEN (1) | |
1450 F77_CHAR_ARG_LEN (1))); | |
1451 | |
1452 if (info != 0) | |
1453 rcon = 0.0; | |
1454 } | |
1455 else if (typ == MatrixType::Permuted_Lower) | |
1456 (*current_liboctave_error_handler) | |
1457 ("permuted triangular matrix not implemented"); | |
1458 else if (typ == MatrixType::Full || typ == MatrixType::Hermitian) | |
1459 { | |
1460 double anorm = -1.0; | |
1461 Matrix atmp = *this; | |
1462 double *tmp_data = atmp.fortran_vec (); | |
1463 | |
1464 if (typ == MatrixType::Hermitian) | |
1465 { | |
1466 octave_idx_type info = 0; | |
1467 char job = 'L'; | |
1468 anorm = atmp.abs().sum(). | |
1469 row(static_cast<octave_idx_type>(0)).max(); | |
1470 | |
1471 F77_XFCN (dpotrf, DPOTRF, (F77_CONST_CHAR_ARG2 (&job, 1), nr, | |
1472 tmp_data, nr, info | |
1473 F77_CHAR_ARG_LEN (1))); | |
1474 | |
1475 if (info != 0) | |
1476 { | |
1477 rcon = 0.0; | |
1478 mattype.mark_as_unsymmetric (); | |
1479 typ = MatrixType::Full; | |
1480 } | |
1481 else | |
1482 { | |
1483 Array<double> z (3 * nc); | |
1484 double *pz = z.fortran_vec (); | |
1485 Array<octave_idx_type> iz (nc); | |
1486 octave_idx_type *piz = iz.fortran_vec (); | |
1487 | |
1488 F77_XFCN (dpocon, DPOCON, (F77_CONST_CHAR_ARG2 (&job, 1), | |
1489 nr, tmp_data, nr, anorm, | |
1490 rcon, pz, piz, info | |
1491 F77_CHAR_ARG_LEN (1))); | |
1492 | |
1493 if (info != 0) | |
1494 rcon = 0.0; | |
1495 } | |
1496 } | |
1497 | |
1498 if (typ == MatrixType::Full) | |
1499 { | |
1500 octave_idx_type info = 0; | |
1501 | |
1502 Array<octave_idx_type> ipvt (nr); | |
1503 octave_idx_type *pipvt = ipvt.fortran_vec (); | |
1504 | |
1505 if(anorm < 0.) | |
1506 anorm = atmp.abs().sum(). | |
1507 row(static_cast<octave_idx_type>(0)).max(); | |
1508 | |
1509 Array<double> z (4 * nc); | |
1510 double *pz = z.fortran_vec (); | |
1511 Array<octave_idx_type> iz (nc); | |
1512 octave_idx_type *piz = iz.fortran_vec (); | |
1513 | |
1514 F77_XFCN (dgetrf, DGETRF, (nr, nr, tmp_data, nr, pipvt, info)); | |
1515 | |
1516 if (info != 0) | |
1517 { | |
1518 rcon = 0.0; | |
1519 mattype.mark_as_rectangular (); | |
1520 } | |
1521 else | |
1522 { | |
1523 char job = '1'; | |
1524 F77_XFCN (dgecon, DGECON, (F77_CONST_CHAR_ARG2 (&job, 1), | |
1525 nc, tmp_data, nr, anorm, | |
1526 rcon, pz, piz, info | |
1527 F77_CHAR_ARG_LEN (1))); | |
1528 | |
1529 if (info != 0) | |
1530 rcon = 0.0; | |
1531 } | |
1532 } | |
1533 } | |
1534 else | |
1535 rcon = 0.0; | |
1536 } | |
1537 | |
1538 return rcon; | |
1539 } | |
1540 | |
458 | 1541 Matrix |
5785 | 1542 Matrix::utsolve (MatrixType &mattype, const Matrix& b, octave_idx_type& info, |
7788 | 1543 double& rcon, solve_singularity_handler sing_handler, |
5785 | 1544 bool calc_cond) const |
1545 { | |
1546 Matrix retval; | |
1547 | |
1548 octave_idx_type nr = rows (); | |
1549 octave_idx_type nc = cols (); | |
1550 | |
6924 | 1551 if (nr != b.rows ()) |
5785 | 1552 (*current_liboctave_error_handler) |
1553 ("matrix dimension mismatch solution of linear equations"); | |
6924 | 1554 else if (nr == 0 || nc == 0 || b.cols () == 0) |
1555 retval = Matrix (nc, b.cols (), 0.0); | |
5785 | 1556 else |
1557 { | |
1558 volatile int typ = mattype.type (); | |
1559 | |
1560 if (typ == MatrixType::Permuted_Upper || | |
1561 typ == MatrixType::Upper) | |
1562 { | |
1563 octave_idx_type b_nc = b.cols (); | |
7788 | 1564 rcon = 1.; |
5785 | 1565 info = 0; |
1566 | |
1567 if (typ == MatrixType::Permuted_Upper) | |
1568 { | |
1569 (*current_liboctave_error_handler) | |
6390 | 1570 ("permuted triangular matrix not implemented"); |
5785 | 1571 } |
1572 else | |
1573 { | |
1574 const double *tmp_data = fortran_vec (); | |
1575 | |
1576 if (calc_cond) | |
1577 { | |
1578 char norm = '1'; | |
1579 char uplo = 'U'; | |
1580 char dia = 'N'; | |
1581 | |
1582 Array<double> z (3 * nc); | |
1583 double *pz = z.fortran_vec (); | |
1584 Array<octave_idx_type> iz (nc); | |
1585 octave_idx_type *piz = iz.fortran_vec (); | |
1586 | |
1587 F77_XFCN (dtrcon, DTRCON, (F77_CONST_CHAR_ARG2 (&norm, 1), | |
1588 F77_CONST_CHAR_ARG2 (&uplo, 1), | |
1589 F77_CONST_CHAR_ARG2 (&dia, 1), | |
7788 | 1590 nr, tmp_data, nr, rcon, |
5785 | 1591 pz, piz, info |
1592 F77_CHAR_ARG_LEN (1) | |
1593 F77_CHAR_ARG_LEN (1) | |
1594 F77_CHAR_ARG_LEN (1))); | |
1595 | |
1596 if (info != 0) | |
1597 info = -2; | |
1598 | |
7788 | 1599 volatile double rcond_plus_one = rcon + 1.0; |
1600 | |
1601 if (rcond_plus_one == 1.0 || xisnan (rcon)) | |
5785 | 1602 { |
1603 info = -2; | |
1604 | |
1605 if (sing_handler) | |
7788 | 1606 sing_handler (rcon); |
5785 | 1607 else |
1608 (*current_liboctave_error_handler) | |
1609 ("matrix singular to machine precision, rcond = %g", | |
7788 | 1610 rcon); |
5785 | 1611 } |
1612 } | |
1613 | |
1614 if (info == 0) | |
1615 { | |
1616 retval = b; | |
1617 double *result = retval.fortran_vec (); | |
1618 | |
1619 char uplo = 'U'; | |
1620 char trans = 'N'; | |
1621 char dia = 'N'; | |
1622 | |
1623 F77_XFCN (dtrtrs, DTRTRS, (F77_CONST_CHAR_ARG2 (&uplo, 1), | |
1624 F77_CONST_CHAR_ARG2 (&trans, 1), | |
1625 F77_CONST_CHAR_ARG2 (&dia, 1), | |
1626 nr, b_nc, tmp_data, nr, | |
1627 result, nr, info | |
1628 F77_CHAR_ARG_LEN (1) | |
1629 F77_CHAR_ARG_LEN (1) | |
1630 F77_CHAR_ARG_LEN (1))); | |
1631 } | |
1632 } | |
1633 } | |
1634 else | |
1635 (*current_liboctave_error_handler) ("incorrect matrix type"); | |
1636 } | |
1637 | |
1638 return retval; | |
1639 } | |
1640 | |
1641 Matrix | |
1642 Matrix::ltsolve (MatrixType &mattype, const Matrix& b, octave_idx_type& info, | |
7788 | 1643 double& rcon, solve_singularity_handler sing_handler, |
5785 | 1644 bool calc_cond) const |
1645 { | |
1646 Matrix retval; | |
1647 | |
1648 octave_idx_type nr = rows (); | |
1649 octave_idx_type nc = cols (); | |
1650 | |
6924 | 1651 if (nr != b.rows ()) |
5785 | 1652 (*current_liboctave_error_handler) |
1653 ("matrix dimension mismatch solution of linear equations"); | |
6924 | 1654 else if (nr == 0 || nc == 0 || b.cols () == 0) |
1655 retval = Matrix (nc, b.cols (), 0.0); | |
5785 | 1656 else |
1657 { | |
1658 volatile int typ = mattype.type (); | |
1659 | |
1660 if (typ == MatrixType::Permuted_Lower || | |
1661 typ == MatrixType::Lower) | |
1662 { | |
1663 octave_idx_type b_nc = b.cols (); | |
7788 | 1664 rcon = 1.; |
5785 | 1665 info = 0; |
1666 | |
1667 if (typ == MatrixType::Permuted_Lower) | |
1668 { | |
1669 (*current_liboctave_error_handler) | |
6390 | 1670 ("permuted triangular matrix not implemented"); |
5785 | 1671 } |
1672 else | |
1673 { | |
1674 const double *tmp_data = fortran_vec (); | |
1675 | |
1676 if (calc_cond) | |
1677 { | |
1678 char norm = '1'; | |
1679 char uplo = 'L'; | |
1680 char dia = 'N'; | |
1681 | |
1682 Array<double> z (3 * nc); | |
1683 double *pz = z.fortran_vec (); | |
1684 Array<octave_idx_type> iz (nc); | |
1685 octave_idx_type *piz = iz.fortran_vec (); | |
1686 | |
1687 F77_XFCN (dtrcon, DTRCON, (F77_CONST_CHAR_ARG2 (&norm, 1), | |
1688 F77_CONST_CHAR_ARG2 (&uplo, 1), | |
1689 F77_CONST_CHAR_ARG2 (&dia, 1), | |
7788 | 1690 nr, tmp_data, nr, rcon, |
5785 | 1691 pz, piz, info |
1692 F77_CHAR_ARG_LEN (1) | |
1693 F77_CHAR_ARG_LEN (1) | |
1694 F77_CHAR_ARG_LEN (1))); | |
1695 | |
1696 if (info != 0) | |
1697 info = -2; | |
1698 | |
7788 | 1699 volatile double rcond_plus_one = rcon + 1.0; |
1700 | |
1701 if (rcond_plus_one == 1.0 || xisnan (rcon)) | |
5785 | 1702 { |
1703 info = -2; | |
1704 | |
1705 if (sing_handler) | |
7788 | 1706 sing_handler (rcon); |
5785 | 1707 else |
1708 (*current_liboctave_error_handler) | |
1709 ("matrix singular to machine precision, rcond = %g", | |
7788 | 1710 rcon); |
5785 | 1711 } |
1712 } | |
1713 | |
1714 if (info == 0) | |
1715 { | |
1716 retval = b; | |
1717 double *result = retval.fortran_vec (); | |
1718 | |
1719 char uplo = 'L'; | |
1720 char trans = 'N'; | |
1721 char dia = 'N'; | |
1722 | |
1723 F77_XFCN (dtrtrs, DTRTRS, (F77_CONST_CHAR_ARG2 (&uplo, 1), | |
1724 F77_CONST_CHAR_ARG2 (&trans, 1), | |
1725 F77_CONST_CHAR_ARG2 (&dia, 1), | |
1726 nr, b_nc, tmp_data, nr, | |
1727 result, nr, info | |
1728 F77_CHAR_ARG_LEN (1) | |
1729 F77_CHAR_ARG_LEN (1) | |
1730 F77_CHAR_ARG_LEN (1))); | |
1731 } | |
1732 } | |
1733 } | |
1734 else | |
1735 (*current_liboctave_error_handler) ("incorrect matrix type"); | |
1736 } | |
1737 | |
1738 return retval; | |
1739 } | |
1740 | |
1741 Matrix | |
1742 Matrix::fsolve (MatrixType &mattype, const Matrix& b, octave_idx_type& info, | |
7788 | 1743 double& rcon, solve_singularity_handler sing_handler, |
5785 | 1744 bool calc_cond) const |
1745 { | |
1746 Matrix retval; | |
1747 | |
1748 octave_idx_type nr = rows (); | |
1749 octave_idx_type nc = cols (); | |
1750 | |
6924 | 1751 if (nr != nc || nr != b.rows ()) |
5785 | 1752 (*current_liboctave_error_handler) |
1753 ("matrix dimension mismatch solution of linear equations"); | |
6924 | 1754 else if (nr == 0 || b.cols () == 0) |
1755 retval = Matrix (nc, b.cols (), 0.0); | |
5785 | 1756 else |
1757 { | |
1758 volatile int typ = mattype.type (); | |
1759 | |
1760 // Calculate the norm of the matrix, for later use. | |
1761 double anorm = -1.; | |
1762 | |
1763 if (typ == MatrixType::Hermitian) | |
1764 { | |
1765 info = 0; | |
1766 char job = 'L'; | |
1767 Matrix atmp = *this; | |
1768 double *tmp_data = atmp.fortran_vec (); | |
1769 anorm = atmp.abs().sum().row(static_cast<octave_idx_type>(0)).max(); | |
1770 | |
1771 F77_XFCN (dpotrf, DPOTRF, (F77_CONST_CHAR_ARG2 (&job, 1), nr, | |
1772 tmp_data, nr, info | |
1773 F77_CHAR_ARG_LEN (1))); | |
1774 | |
7482
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
1775 // Throw-away extra info LAPACK gives so as to not change output. |
7788 | 1776 rcon = 0.0; |
7482
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
1777 if (info != 0) |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
1778 { |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
1779 info = -2; |
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 mattype.mark_as_unsymmetric (); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
1782 typ = MatrixType::Full; |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
1783 } |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
1784 else |
5785 | 1785 { |
7482
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
1786 if (calc_cond) |
5785 | 1787 { |
7482
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
1788 Array<double> z (3 * nc); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
1789 double *pz = z.fortran_vec (); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
1790 Array<octave_idx_type> iz (nc); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
1791 octave_idx_type *piz = iz.fortran_vec (); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
1792 |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
1793 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
|
1794 nr, tmp_data, nr, anorm, |
7788 | 1795 rcon, pz, piz, info |
7482
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
1796 F77_CHAR_ARG_LEN (1))); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
1797 |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
1798 if (info != 0) |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
1799 info = -2; |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
1800 |
7788 | 1801 volatile double rcond_plus_one = rcon + 1.0; |
1802 | |
1803 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
|
1804 { |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
1805 info = -2; |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
1806 |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
1807 if (sing_handler) |
7788 | 1808 sing_handler (rcon); |
7482
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
1809 else |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
1810 (*current_liboctave_error_handler) |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
1811 ("matrix singular to machine precision, rcond = %g", |
7788 | 1812 rcon); |
7482
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
1813 } |
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 |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
1816 if (info == 0) |
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 retval = b; |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
1819 double *result = retval.fortran_vec (); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
1820 |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
1821 octave_idx_type b_nc = b.cols (); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
1822 |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
1823 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
|
1824 nr, b_nc, tmp_data, nr, |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
1825 result, b.rows(), info |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
1826 F77_CHAR_ARG_LEN (1))); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
1827 } |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
1828 else |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
1829 { |
5785 | 1830 mattype.mark_as_unsymmetric (); |
1831 typ = MatrixType::Full; | |
7482
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
1832 } |
5785 | 1833 } |
1834 } | |
1835 | |
1836 if (typ == MatrixType::Full) | |
1837 { | |
1838 info = 0; | |
1839 | |
1840 Array<octave_idx_type> ipvt (nr); | |
1841 octave_idx_type *pipvt = ipvt.fortran_vec (); | |
1842 | |
1843 Matrix atmp = *this; | |
1844 double *tmp_data = atmp.fortran_vec (); | |
1845 if(anorm < 0.) | |
1846 anorm = atmp.abs().sum().row(static_cast<octave_idx_type>(0)).max(); | |
1847 | |
1848 Array<double> z (4 * nc); | |
1849 double *pz = z.fortran_vec (); | |
1850 Array<octave_idx_type> iz (nc); | |
1851 octave_idx_type *piz = iz.fortran_vec (); | |
1852 | |
1853 F77_XFCN (dgetrf, DGETRF, (nr, nr, tmp_data, nr, pipvt, info)); | |
1854 | |
7482
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
1855 // Throw-away extra info LAPACK gives so as to not change output. |
7788 | 1856 rcon = 0.0; |
7482
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
1857 if (info != 0) |
5785 | 1858 { |
7482
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
1859 info = -2; |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
1860 |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
1861 if (sing_handler) |
7788 | 1862 sing_handler (rcon); |
7482
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
1863 else |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
1864 (*current_liboctave_error_handler) |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
1865 ("matrix singular to machine precision"); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
1866 |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
1867 mattype.mark_as_rectangular (); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
1868 } |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
1869 else |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
1870 { |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
1871 if (calc_cond) |
5785 | 1872 { |
7482
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
1873 // Now calculate the condition number for |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
1874 // non-singular matrix. |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
1875 char job = '1'; |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
1876 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
|
1877 nc, tmp_data, nr, anorm, |
7788 | 1878 rcon, pz, piz, info |
7482
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
1879 F77_CHAR_ARG_LEN (1))); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
1880 |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
1881 if (info != 0) |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
1882 info = -2; |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
1883 |
7788 | 1884 volatile double rcond_plus_one = rcon + 1.0; |
1885 | |
1886 if (rcond_plus_one == 1.0 || xisnan (rcon)) | |
5785 | 1887 { |
7482
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
1888 info = -2; |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
1889 |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
1890 if (sing_handler) |
7788 | 1891 sing_handler (rcon); |
7482
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
1892 else |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
1893 (*current_liboctave_error_handler) |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
1894 ("matrix singular to machine precision, rcond = %g", |
7788 | 1895 rcon); |
5785 | 1896 } |
1897 } | |
7482
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
1898 |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
1899 if (info == 0) |
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 retval = b; |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
1902 double *result = retval.fortran_vec (); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
1903 |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
1904 octave_idx_type b_nc = b.cols (); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
1905 |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
1906 char job = 'N'; |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
1907 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
|
1908 nr, b_nc, tmp_data, nr, |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
1909 pipvt, result, b.rows(), info |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
1910 F77_CHAR_ARG_LEN (1))); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
1911 } |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
1912 else |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
1913 mattype.mark_as_rectangular (); |
5785 | 1914 } |
1915 } | |
1916 else if (typ != MatrixType::Hermitian) | |
1917 (*current_liboctave_error_handler) ("incorrect matrix type"); | |
1918 } | |
1919 | |
1920 return retval; | |
1921 } | |
1922 | |
1923 Matrix | |
1924 Matrix::solve (MatrixType &typ, const Matrix& b) const | |
1925 { | |
1926 octave_idx_type info; | |
7788 | 1927 double rcon; |
1928 return solve (typ, b, info, rcon, 0); | |
5785 | 1929 } |
1930 | |
1931 Matrix | |
1932 Matrix::solve (MatrixType &typ, const Matrix& b, octave_idx_type& info, | |
7788 | 1933 double& rcon) const |
5785 | 1934 { |
7788 | 1935 return solve (typ, b, info, rcon, 0); |
5785 | 1936 } |
1937 | |
1938 Matrix | |
1939 Matrix::solve (MatrixType &mattype, const Matrix& b, octave_idx_type& info, | |
7788 | 1940 double& rcon, solve_singularity_handler sing_handler, |
5785 | 1941 bool singular_fallback) const |
1942 { | |
1943 Matrix retval; | |
1944 int typ = mattype.type (); | |
1945 | |
1946 if (typ == MatrixType::Unknown) | |
1947 typ = mattype.type (*this); | |
1948 | |
1949 // Only calculate the condition number for LU/Cholesky | |
1950 if (typ == MatrixType::Upper || typ == MatrixType::Permuted_Upper) | |
7788 | 1951 retval = utsolve (mattype, b, info, rcon, sing_handler, false); |
5785 | 1952 else if (typ == MatrixType::Lower || typ == MatrixType::Permuted_Lower) |
7788 | 1953 retval = ltsolve (mattype, b, info, rcon, sing_handler, false); |
5785 | 1954 else if (typ == MatrixType::Full || typ == MatrixType::Hermitian) |
7788 | 1955 retval = fsolve (mattype, b, info, rcon, sing_handler, true); |
5785 | 1956 else if (typ != MatrixType::Rectangular) |
1957 { | |
1958 (*current_liboctave_error_handler) ("unknown matrix type"); | |
1959 return Matrix (); | |
1960 } | |
1961 | |
1962 // Rectangular or one of the above solvers flags a singular matrix | |
1963 if (singular_fallback && mattype.type () == MatrixType::Rectangular) | |
1964 { | |
1965 octave_idx_type rank; | |
7788 | 1966 retval = lssolve (b, info, rank, rcon); |
5785 | 1967 } |
1968 | |
1969 return retval; | |
1970 } | |
1971 | |
1972 ComplexMatrix | |
1973 Matrix::solve (MatrixType &typ, const ComplexMatrix& b) const | |
1974 { | |
1975 ComplexMatrix tmp (*this); | |
1976 return tmp.solve (typ, b); | |
1977 } | |
1978 | |
1979 ComplexMatrix | |
1980 Matrix::solve (MatrixType &typ, const ComplexMatrix& b, | |
1981 octave_idx_type& info) const | |
1982 { | |
1983 ComplexMatrix tmp (*this); | |
1984 return tmp.solve (typ, b, info); | |
1985 } | |
1986 | |
1987 ComplexMatrix | |
1988 Matrix::solve (MatrixType &typ, const ComplexMatrix& b, octave_idx_type& info, | |
7788 | 1989 double& rcon) const |
5785 | 1990 { |
1991 ComplexMatrix tmp (*this); | |
7788 | 1992 return tmp.solve (typ, b, info, rcon); |
5785 | 1993 } |
1994 | |
1995 ComplexMatrix | |
1996 Matrix::solve (MatrixType &typ, const ComplexMatrix& b, octave_idx_type& info, | |
7788 | 1997 double& rcon, solve_singularity_handler sing_handler, |
5785 | 1998 bool singular_fallback) const |
1999 { | |
2000 ComplexMatrix tmp (*this); | |
7788 | 2001 return tmp.solve (typ, b, info, rcon, sing_handler, singular_fallback); |
5785 | 2002 } |
2003 | |
2004 ColumnVector | |
2005 Matrix::solve (MatrixType &typ, const ColumnVector& b) const | |
2006 { | |
7788 | 2007 octave_idx_type info; double rcon; |
2008 return solve (typ, b, info, rcon); | |
5785 | 2009 } |
2010 | |
2011 ColumnVector | |
2012 Matrix::solve (MatrixType &typ, const ColumnVector& b, | |
2013 octave_idx_type& info) const | |
2014 { | |
7788 | 2015 double rcon; |
2016 return solve (typ, b, info, rcon); | |
5785 | 2017 } |
2018 | |
2019 ColumnVector | |
2020 Matrix::solve (MatrixType &typ, const ColumnVector& b, octave_idx_type& info, | |
7788 | 2021 double& rcon) const |
5785 | 2022 { |
7788 | 2023 return solve (typ, b, info, rcon, 0); |
5785 | 2024 } |
2025 | |
2026 ColumnVector | |
2027 Matrix::solve (MatrixType &typ, const ColumnVector& b, octave_idx_type& info, | |
7788 | 2028 double& rcon, solve_singularity_handler sing_handler) const |
5785 | 2029 { |
2030 Matrix tmp (b); | |
7788 | 2031 return solve (typ, tmp, info, rcon, sing_handler).column(static_cast<octave_idx_type> (0)); |
5785 | 2032 } |
2033 | |
2034 ComplexColumnVector | |
2035 Matrix::solve (MatrixType &typ, const ComplexColumnVector& b) const | |
2036 { | |
2037 ComplexMatrix tmp (*this); | |
2038 return tmp.solve (typ, b); | |
2039 } | |
2040 | |
2041 ComplexColumnVector | |
2042 Matrix::solve (MatrixType &typ, const ComplexColumnVector& b, | |
2043 octave_idx_type& info) const | |
2044 { | |
2045 ComplexMatrix tmp (*this); | |
2046 return tmp.solve (typ, b, info); | |
2047 } | |
2048 | |
2049 ComplexColumnVector | |
2050 Matrix::solve (MatrixType &typ, const ComplexColumnVector& b, | |
7788 | 2051 octave_idx_type& info, double& rcon) const |
5785 | 2052 { |
2053 ComplexMatrix tmp (*this); | |
7788 | 2054 return tmp.solve (typ, b, info, rcon); |
5785 | 2055 } |
2056 | |
2057 ComplexColumnVector | |
2058 Matrix::solve (MatrixType &typ, const ComplexColumnVector& b, | |
7788 | 2059 octave_idx_type& info, double& rcon, |
5785 | 2060 solve_singularity_handler sing_handler) const |
2061 { | |
2062 ComplexMatrix tmp (*this); | |
7788 | 2063 return tmp.solve(typ, b, info, rcon, sing_handler); |
5785 | 2064 } |
2065 | |
2066 Matrix | |
458 | 2067 Matrix::solve (const Matrix& b) const |
2068 { | |
5275 | 2069 octave_idx_type info; |
7788 | 2070 double rcon; |
2071 return solve (b, info, rcon, 0); | |
458 | 2072 } |
2073 | |
2074 Matrix | |
5275 | 2075 Matrix::solve (const Matrix& b, octave_idx_type& info) const |
458 | 2076 { |
7788 | 2077 double rcon; |
2078 return solve (b, info, rcon, 0); | |
458 | 2079 } |
2080 | |
2081 Matrix | |
7788 | 2082 Matrix::solve (const Matrix& b, octave_idx_type& info, double& rcon) const |
458 | 2083 { |
7788 | 2084 return solve (b, info, rcon, 0); |
3480 | 2085 } |
2086 | |
2087 Matrix | |
5785 | 2088 Matrix::solve (const Matrix& b, octave_idx_type& info, |
7788 | 2089 double& rcon, solve_singularity_handler sing_handler) const |
3480 | 2090 { |
5785 | 2091 MatrixType mattype (*this); |
7788 | 2092 return solve (mattype, b, info, rcon, sing_handler); |
458 | 2093 } |
2094 | |
2095 ComplexMatrix | |
2096 Matrix::solve (const ComplexMatrix& b) const | |
2097 { | |
2098 ComplexMatrix tmp (*this); | |
2099 return tmp.solve (b); | |
2100 } | |
2101 | |
2102 ComplexMatrix | |
5275 | 2103 Matrix::solve (const ComplexMatrix& b, octave_idx_type& info) const |
458 | 2104 { |
2105 ComplexMatrix tmp (*this); | |
2106 return tmp.solve (b, info); | |
2107 } | |
2108 | |
2109 ComplexMatrix | |
7788 | 2110 Matrix::solve (const ComplexMatrix& b, octave_idx_type& info, double& rcon) const |
458 | 2111 { |
2112 ComplexMatrix tmp (*this); | |
7788 | 2113 return tmp.solve (b, info, rcon); |
458 | 2114 } |
2115 | |
3480 | 2116 ComplexMatrix |
7788 | 2117 Matrix::solve (const ComplexMatrix& b, octave_idx_type& info, double& rcon, |
3480 | 2118 solve_singularity_handler sing_handler) const |
2119 { | |
2120 ComplexMatrix tmp (*this); | |
7788 | 2121 return tmp.solve (b, info, rcon, sing_handler); |
3480 | 2122 } |
2123 | |
458 | 2124 ColumnVector |
2125 Matrix::solve (const ColumnVector& b) const | |
2126 { | |
7788 | 2127 octave_idx_type info; double rcon; |
2128 return solve (b, info, rcon); | |
458 | 2129 } |
2130 | |
2131 ColumnVector | |
5275 | 2132 Matrix::solve (const ColumnVector& b, octave_idx_type& info) const |
458 | 2133 { |
7788 | 2134 double rcon; |
2135 return solve (b, info, rcon); | |
458 | 2136 } |
2137 | |
2138 ColumnVector | |
7788 | 2139 Matrix::solve (const ColumnVector& b, octave_idx_type& info, double& rcon) const |
458 | 2140 { |
7788 | 2141 return solve (b, info, rcon, 0); |
3480 | 2142 } |
2143 | |
2144 ColumnVector | |
7788 | 2145 Matrix::solve (const ColumnVector& b, octave_idx_type& info, double& rcon, |
3480 | 2146 solve_singularity_handler sing_handler) const |
2147 { | |
5785 | 2148 MatrixType mattype (*this); |
7788 | 2149 return solve (mattype, b, info, rcon, sing_handler); |
458 | 2150 } |
2151 | |
2152 ComplexColumnVector | |
2153 Matrix::solve (const ComplexColumnVector& b) const | |
2154 { | |
2155 ComplexMatrix tmp (*this); | |
2156 return tmp.solve (b); | |
2157 } | |
2158 | |
2159 ComplexColumnVector | |
5275 | 2160 Matrix::solve (const ComplexColumnVector& b, octave_idx_type& info) const |
458 | 2161 { |
2162 ComplexMatrix tmp (*this); | |
2163 return tmp.solve (b, info); | |
2164 } | |
2165 | |
2166 ComplexColumnVector | |
7788 | 2167 Matrix::solve (const ComplexColumnVector& b, octave_idx_type& info, double& rcon) const |
458 | 2168 { |
2169 ComplexMatrix tmp (*this); | |
7788 | 2170 return tmp.solve (b, info, rcon); |
458 | 2171 } |
2172 | |
3480 | 2173 ComplexColumnVector |
7788 | 2174 Matrix::solve (const ComplexColumnVector& b, octave_idx_type& info, double& rcon, |
3480 | 2175 solve_singularity_handler sing_handler) const |
2176 { | |
2177 ComplexMatrix tmp (*this); | |
7788 | 2178 return tmp.solve (b, info, rcon, sing_handler); |
3480 | 2179 } |
2180 | |
458 | 2181 Matrix |
2182 Matrix::lssolve (const Matrix& b) const | |
2183 { | |
5275 | 2184 octave_idx_type info; |
2185 octave_idx_type rank; | |
7788 | 2186 double rcon; |
2187 return lssolve (b, info, rank, rcon); | |
458 | 2188 } |
2189 | |
2190 Matrix | |
5275 | 2191 Matrix::lssolve (const Matrix& b, octave_idx_type& info) const |
458 | 2192 { |
5275 | 2193 octave_idx_type rank; |
7788 | 2194 double rcon; |
2195 return lssolve (b, info, rank, rcon); | |
458 | 2196 } |
2197 | |
2198 Matrix | |
7072 | 2199 Matrix::lssolve (const Matrix& b, octave_idx_type& info, |
2200 octave_idx_type& rank) const | |
458 | 2201 { |
7788 | 2202 double rcon; |
2203 return lssolve (b, info, rank, rcon); | |
7076 | 2204 } |
2205 | |
2206 Matrix | |
2207 Matrix::lssolve (const Matrix& b, octave_idx_type& info, | |
7788 | 2208 octave_idx_type& rank, double &rcon) const |
7076 | 2209 { |
1948 | 2210 Matrix retval; |
2211 | |
5275 | 2212 octave_idx_type nrhs = b.cols (); |
2213 | |
2214 octave_idx_type m = rows (); | |
2215 octave_idx_type n = cols (); | |
458 | 2216 |
6924 | 2217 if (m != b.rows ()) |
1948 | 2218 (*current_liboctave_error_handler) |
6924 | 2219 ("matrix dimension mismatch solution of linear equations"); |
2220 else if (m == 0 || n == 0 || b.cols () == 0) | |
2221 retval = Matrix (n, b.cols (), 0.0); | |
1948 | 2222 else |
458 | 2223 { |
7072 | 2224 volatile octave_idx_type minmn = (m < n ? m : n); |
2225 octave_idx_type maxmn = m > n ? m : n; | |
7788 | 2226 rcon = -1.0; |
7072 | 2227 if (m != n) |
2228 { | |
2229 retval = Matrix (maxmn, nrhs, 0.0); | |
2230 | |
2231 for (octave_idx_type j = 0; j < nrhs; j++) | |
2232 for (octave_idx_type i = 0; i < m; i++) | |
2233 retval.elem (i, j) = b.elem (i, j); | |
2234 } | |
2235 else | |
2236 retval = b; | |
2237 | |
1948 | 2238 Matrix atmp = *this; |
2239 double *tmp_data = atmp.fortran_vec (); | |
2240 | |
7072 | 2241 double *pretval = retval.fortran_vec (); |
2242 Array<double> s (minmn); | |
7071 | 2243 double *ps = s.fortran_vec (); |
1948 | 2244 |
7072 | 2245 // Ask DGELSD what the dimension of WORK should be. |
5275 | 2246 octave_idx_type lwork = -1; |
3752 | 2247 |
2248 Array<double> work (1); | |
1948 | 2249 |
7477 | 2250 octave_idx_type smlsiz; |
2251 F77_FUNC (xilaenv, XILAENV) (9, F77_CONST_CHAR_ARG2 ("DGELSD", 6), | |
2252 F77_CONST_CHAR_ARG2 (" ", 1), | |
7478 | 2253 0, 0, 0, 0, smlsiz |
7477 | 2254 F77_CHAR_ARG_LEN (6) |
7478 | 2255 F77_CHAR_ARG_LEN (1)); |
7079 | 2256 |
7486
6a6d2abe51ff
more xGELSD workspace fixes
John W. Eaton <jwe@octave.org>
parents:
7482
diff
changeset
|
2257 octave_idx_type mnthr; |
6a6d2abe51ff
more xGELSD workspace fixes
John W. Eaton <jwe@octave.org>
parents:
7482
diff
changeset
|
2258 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
|
2259 F77_CONST_CHAR_ARG2 (" ", 1), |
6a6d2abe51ff
more xGELSD workspace fixes
John W. Eaton <jwe@octave.org>
parents:
7482
diff
changeset
|
2260 m, n, nrhs, -1, mnthr |
6a6d2abe51ff
more xGELSD workspace fixes
John W. Eaton <jwe@octave.org>
parents:
7482
diff
changeset
|
2261 F77_CHAR_ARG_LEN (6) |
6a6d2abe51ff
more xGELSD workspace fixes
John W. Eaton <jwe@octave.org>
parents:
7482
diff
changeset
|
2262 F77_CHAR_ARG_LEN (1)); |
6a6d2abe51ff
more xGELSD workspace fixes
John W. Eaton <jwe@octave.org>
parents:
7482
diff
changeset
|
2263 |
7079 | 2264 // We compute the size of iwork because DGELSD in older versions |
2265 // of LAPACK does not return it on a query call. | |
7124 | 2266 double dminmn = static_cast<double> (minmn); |
2267 double dsmlsizp1 = static_cast<double> (smlsiz+1); | |
7079 | 2268 #if defined (HAVE_LOG2) |
7367 | 2269 double tmp = log2 (dminmn / dsmlsizp1); |
7079 | 2270 #else |
7367 | 2271 double tmp = log (dminmn / dsmlsizp1) / log (2.0); |
7079 | 2272 #endif |
7544
f9983d2761df
more xGELSD workspace fixes
Jaroslav Hajek <highegg@gmail.com>
parents:
7532
diff
changeset
|
2273 octave_idx_type nlvl = static_cast<octave_idx_type> (tmp) + 1; |
7079 | 2274 if (nlvl < 0) |
2275 nlvl = 0; | |
2276 | |
2277 octave_idx_type liwork = 3 * minmn * nlvl + 11 * minmn; | |
2278 if (liwork < 1) | |
2279 liwork = 1; | |
7072 | 2280 Array<octave_idx_type> iwork (liwork); |
2281 octave_idx_type* piwork = iwork.fortran_vec (); | |
2282 | |
2283 F77_XFCN (dgelsd, DGELSD, (m, n, nrhs, tmp_data, m, pretval, maxmn, | |
7788 | 2284 ps, rcon, rank, work.fortran_vec (), |
7072 | 2285 lwork, piwork, info)); |
1948 | 2286 |
7476 | 2287 // 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
|
2288 // through 3.1.1 when n >= mnthr. The obtuse formula below |
7476 | 2289 // should provide sufficient workspace for DGELSD to operate |
2290 // efficiently. | |
7488
6470f946a425
another small xGELSD workspace fix
John W. Eaton <jwe@octave.org>
parents:
7486
diff
changeset
|
2291 if (n >= mnthr) |
7476 | 2292 { |
2293 const octave_idx_type wlalsd | |
2294 = 9*m + 2*m*smlsiz + 8*m*nlvl + m*nrhs + (smlsiz+1)*(smlsiz+1); | |
2295 | |
2296 octave_idx_type addend = m; | |
2297 | |
2298 if (2*m-4 > addend) | |
2299 addend = 2*m-4; | |
2300 | |
2301 if (nrhs > addend) | |
2302 addend = nrhs; | |
2303 | |
2304 if (n-3*m > addend) | |
2305 addend = n-3*m; | |
2306 | |
2307 if (wlalsd > addend) | |
2308 addend = wlalsd; | |
2309 | |
2310 const octave_idx_type lworkaround = 4*m + m*m + addend; | |
2311 | |
2312 if (work(0) < lworkaround) | |
2313 work(0) = lworkaround; | |
2314 } | |
7532
493bb0de3199
avoid another xGELSD workspace query bug
John W. Eaton <jwe@octave.org>
parents:
7503
diff
changeset
|
2315 else if (m >= n) |
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 octave_idx_type lworkaround |
493bb0de3199
avoid another xGELSD workspace query bug
John W. Eaton <jwe@octave.org>
parents:
7503
diff
changeset
|
2318 = 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
|
2319 |
493bb0de3199
avoid another xGELSD workspace query bug
John W. Eaton <jwe@octave.org>
parents:
7503
diff
changeset
|
2320 if (work(0) < lworkaround) |
493bb0de3199
avoid another xGELSD workspace query bug
John W. Eaton <jwe@octave.org>
parents:
7503
diff
changeset
|
2321 work(0) = lworkaround; |
493bb0de3199
avoid another xGELSD workspace query bug
John W. Eaton <jwe@octave.org>
parents:
7503
diff
changeset
|
2322 } |
7476 | 2323 |
7482
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2324 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
|
2325 work.resize (lwork); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2326 |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2327 F77_XFCN (dgelsd, DGELSD, (m, n, nrhs, tmp_data, m, pretval, |
7788 | 2328 maxmn, ps, rcon, rank, |
7482
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2329 work.fortran_vec (), lwork, |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2330 piwork, info)); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2331 |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2332 if (rank < minmn) |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2333 (*current_liboctave_warning_handler) |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2334 ("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
|
2335 if (s.elem (0) == 0.0) |
7788 | 2336 rcon = 0.0; |
1948 | 2337 else |
7788 | 2338 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
|
2339 |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2340 retval.resize (n, nrhs); |
458 | 2341 } |
2342 | |
2343 return retval; | |
2344 } | |
2345 | |
2346 ComplexMatrix | |
2347 Matrix::lssolve (const ComplexMatrix& b) const | |
2348 { | |
2349 ComplexMatrix tmp (*this); | |
5275 | 2350 octave_idx_type info; |
2351 octave_idx_type rank; | |
7788 | 2352 double rcon; |
2353 return tmp.lssolve (b, info, rank, rcon); | |
458 | 2354 } |
2355 | |
2356 ComplexMatrix | |
5275 | 2357 Matrix::lssolve (const ComplexMatrix& b, octave_idx_type& info) const |
458 | 2358 { |
2359 ComplexMatrix tmp (*this); | |
5275 | 2360 octave_idx_type rank; |
7788 | 2361 double rcon; |
2362 return tmp.lssolve (b, info, rank, rcon); | |
458 | 2363 } |
2364 | |
2365 ComplexMatrix | |
7076 | 2366 Matrix::lssolve (const ComplexMatrix& b, octave_idx_type& info, |
2367 octave_idx_type& rank) const | |
458 | 2368 { |
2369 ComplexMatrix tmp (*this); | |
7788 | 2370 double rcon; |
2371 return tmp.lssolve (b, info, rank, rcon); | |
7076 | 2372 } |
2373 | |
2374 ComplexMatrix | |
2375 Matrix::lssolve (const ComplexMatrix& b, octave_idx_type& info, | |
7788 | 2376 octave_idx_type& rank, double& rcon) const |
7076 | 2377 { |
2378 ComplexMatrix tmp (*this); | |
7788 | 2379 return tmp.lssolve (b, info, rank, rcon); |
458 | 2380 } |
2381 | |
2382 ColumnVector | |
2383 Matrix::lssolve (const ColumnVector& b) const | |
2384 { | |
5275 | 2385 octave_idx_type info; |
2386 octave_idx_type rank; | |
7788 | 2387 double rcon; |
2388 return lssolve (b, info, rank, rcon); | |
458 | 2389 } |
2390 | |
2391 ColumnVector | |
5275 | 2392 Matrix::lssolve (const ColumnVector& b, octave_idx_type& info) const |
458 | 2393 { |
5275 | 2394 octave_idx_type rank; |
7788 | 2395 double rcon; |
2396 return lssolve (b, info, rank, rcon); | |
458 | 2397 } |
2398 | |
2399 ColumnVector | |
7072 | 2400 Matrix::lssolve (const ColumnVector& b, octave_idx_type& info, |
2401 octave_idx_type& rank) const | |
458 | 2402 { |
7788 | 2403 double rcon; |
2404 return lssolve (b, info, rank, rcon); | |
7076 | 2405 } |
2406 | |
2407 ColumnVector | |
2408 Matrix::lssolve (const ColumnVector& b, octave_idx_type& info, | |
7788 | 2409 octave_idx_type& rank, double &rcon) const |
7076 | 2410 { |
1948 | 2411 ColumnVector retval; |
2412 | |
5275 | 2413 octave_idx_type nrhs = 1; |
2414 | |
2415 octave_idx_type m = rows (); | |
2416 octave_idx_type n = cols (); | |
458 | 2417 |
6924 | 2418 if (m != b.length ()) |
1948 | 2419 (*current_liboctave_error_handler) |
6924 | 2420 ("matrix dimension mismatch solution of linear equations"); |
2421 else if (m == 0 || n == 0) | |
2422 retval = ColumnVector (n, 0.0); | |
1948 | 2423 else |
458 | 2424 { |
7072 | 2425 volatile octave_idx_type minmn = (m < n ? m : n); |
2426 octave_idx_type maxmn = m > n ? m : n; | |
7788 | 2427 rcon = -1.0; |
7072 | 2428 |
2429 if (m != n) | |
2430 { | |
2431 retval = ColumnVector (maxmn, 0.0); | |
2432 | |
2433 for (octave_idx_type i = 0; i < m; i++) | |
2434 retval.elem (i) = b.elem (i); | |
2435 } | |
2436 else | |
2437 retval = b; | |
2438 | |
1948 | 2439 Matrix atmp = *this; |
2440 double *tmp_data = atmp.fortran_vec (); | |
2441 | |
7072 | 2442 double *pretval = retval.fortran_vec (); |
2443 Array<double> s (minmn); | |
7071 | 2444 double *ps = s.fortran_vec (); |
1948 | 2445 |
7072 | 2446 // Ask DGELSD what the dimension of WORK should be. |
5275 | 2447 octave_idx_type lwork = -1; |
3752 | 2448 |
2449 Array<double> work (1); | |
2450 | |
7544
f9983d2761df
more xGELSD workspace fixes
Jaroslav Hajek <highegg@gmail.com>
parents:
7532
diff
changeset
|
2451 octave_idx_type smlsiz; |
f9983d2761df
more xGELSD workspace fixes
Jaroslav Hajek <highegg@gmail.com>
parents:
7532
diff
changeset
|
2452 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
|
2453 F77_CONST_CHAR_ARG2 (" ", 1), |
f9983d2761df
more xGELSD workspace fixes
Jaroslav Hajek <highegg@gmail.com>
parents:
7532
diff
changeset
|
2454 0, 0, 0, 0, smlsiz |
f9983d2761df
more xGELSD workspace fixes
Jaroslav Hajek <highegg@gmail.com>
parents:
7532
diff
changeset
|
2455 F77_CHAR_ARG_LEN (6) |
f9983d2761df
more xGELSD workspace fixes
Jaroslav Hajek <highegg@gmail.com>
parents:
7532
diff
changeset
|
2456 F77_CHAR_ARG_LEN (1)); |
7079 | 2457 |
2458 // We compute the size of iwork because DGELSD in older versions | |
2459 // of LAPACK does not return it on a query call. | |
7124 | 2460 double dminmn = static_cast<double> (minmn); |
2461 double dsmlsizp1 = static_cast<double> (smlsiz+1); | |
7079 | 2462 #if defined (HAVE_LOG2) |
7544
f9983d2761df
more xGELSD workspace fixes
Jaroslav Hajek <highegg@gmail.com>
parents:
7532
diff
changeset
|
2463 double tmp = log2 (dminmn / dsmlsizp1); |
7079 | 2464 #else |
7544
f9983d2761df
more xGELSD workspace fixes
Jaroslav Hajek <highegg@gmail.com>
parents:
7532
diff
changeset
|
2465 double tmp = log (dminmn / dsmlsizp1) / log (2.0); |
7079 | 2466 #endif |
7544
f9983d2761df
more xGELSD workspace fixes
Jaroslav Hajek <highegg@gmail.com>
parents:
7532
diff
changeset
|
2467 octave_idx_type nlvl = static_cast<octave_idx_type> (tmp) + 1; |
7079 | 2468 if (nlvl < 0) |
2469 nlvl = 0; | |
2470 | |
2471 octave_idx_type liwork = 3 * minmn * nlvl + 11 * minmn; | |
2472 if (liwork < 1) | |
2473 liwork = 1; | |
7072 | 2474 Array<octave_idx_type> iwork (liwork); |
2475 octave_idx_type* piwork = iwork.fortran_vec (); | |
2476 | |
2477 F77_XFCN (dgelsd, DGELSD, (m, n, nrhs, tmp_data, m, pretval, maxmn, | |
7788 | 2478 ps, rcon, rank, work.fortran_vec (), |
7072 | 2479 lwork, piwork, info)); |
1948 | 2480 |
7482
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2481 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
|
2482 work.resize (lwork); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2483 |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2484 F77_XFCN (dgelsd, DGELSD, (m, n, nrhs, tmp_data, m, pretval, |
7788 | 2485 maxmn, ps, rcon, rank, |
7482
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2486 work.fortran_vec (), lwork, |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2487 piwork, info)); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2488 |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2489 if (rank < minmn) |
1948 | 2490 { |
7482
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2491 if (rank < minmn) |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2492 (*current_liboctave_warning_handler) |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2493 ("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
|
2494 if (s.elem (0) == 0.0) |
7788 | 2495 rcon = 0.0; |
7482
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2496 else |
7788 | 2497 rcon = s.elem (minmn - 1) / s.elem (0); |
1948 | 2498 } |
7482
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2499 |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
2500 retval.resize (n, nrhs); |
458 | 2501 } |
2502 | |
2503 return retval; | |
2504 } | |
2505 | |
2506 ComplexColumnVector | |
2507 Matrix::lssolve (const ComplexColumnVector& b) const | |
2508 { | |
2509 ComplexMatrix tmp (*this); | |
7076 | 2510 octave_idx_type info; |
2511 octave_idx_type rank; | |
7788 | 2512 double rcon; |
2513 return tmp.lssolve (b, info, rank, rcon); | |
458 | 2514 } |
2515 | |
2516 ComplexColumnVector | |
5275 | 2517 Matrix::lssolve (const ComplexColumnVector& b, octave_idx_type& info) const |
458 | 2518 { |
2519 ComplexMatrix tmp (*this); | |
7076 | 2520 octave_idx_type rank; |
7788 | 2521 double rcon; |
2522 return tmp.lssolve (b, info, rank, rcon); | |
458 | 2523 } |
2524 | |
2525 ComplexColumnVector | |
7076 | 2526 Matrix::lssolve (const ComplexColumnVector& b, octave_idx_type& info, |
2527 octave_idx_type& rank) const | |
458 | 2528 { |
2529 ComplexMatrix tmp (*this); | |
7788 | 2530 double rcon; |
2531 return tmp.lssolve (b, info, rank, rcon); | |
7076 | 2532 } |
2533 | |
2534 ComplexColumnVector | |
2535 Matrix::lssolve (const ComplexColumnVector& b, octave_idx_type& info, | |
7788 | 2536 octave_idx_type& rank, double &rcon) const |
7076 | 2537 { |
2538 ComplexMatrix tmp (*this); | |
7788 | 2539 return tmp.lssolve (b, info, rank, rcon); |
458 | 2540 } |
2541 | |
1819 | 2542 // Constants for matrix exponential calculation. |
2543 | |
2544 static double padec [] = | |
2545 { | |
2546 5.0000000000000000e-1, | |
2547 1.1666666666666667e-1, | |
2548 1.6666666666666667e-2, | |
2549 1.6025641025641026e-3, | |
2550 1.0683760683760684e-4, | |
2551 4.8562548562548563e-6, | |
2552 1.3875013875013875e-7, | |
2553 1.9270852604185938e-9, | |
2554 }; | |
2555 | |
7400 | 2556 static void |
7788 | 2557 solve_singularity_warning (double rcon) |
7400 | 2558 { |
2559 (*current_liboctave_warning_handler) | |
2560 ("singular matrix encountered in expm calculation, rcond = %g", | |
7788 | 2561 rcon); |
7400 | 2562 } |
2563 | |
1819 | 2564 Matrix |
2565 Matrix::expm (void) const | |
2566 { | |
2567 Matrix retval; | |
2568 | |
2569 Matrix m = *this; | |
2570 | |
6699 | 2571 if (numel () == 1) |
2572 return Matrix (1, 1, exp (m(0))); | |
2573 | |
5275 | 2574 octave_idx_type nc = columns (); |
1819 | 2575 |
3130 | 2576 // Preconditioning step 1: trace normalization to reduce dynamic |
2577 // range of poles, but avoid making stable eigenvalues unstable. | |
2578 | |
1819 | 2579 // trace shift value |
3331 | 2580 volatile double trshift = 0.0; |
1819 | 2581 |
5275 | 2582 for (octave_idx_type i = 0; i < nc; i++) |
1819 | 2583 trshift += m.elem (i, i); |
2584 | |
2585 trshift /= nc; | |
2586 | |
3130 | 2587 if (trshift > 0.0) |
2588 { | |
5275 | 2589 for (octave_idx_type i = 0; i < nc; i++) |
3130 | 2590 m.elem (i, i) -= trshift; |
2591 } | |
1819 | 2592 |
3331 | 2593 // Preconditioning step 2: balancing; code follows development |
2594 // in AEPBAL | |
2595 | |
2596 double *p_m = m.fortran_vec (); | |
2597 | |
5275 | 2598 octave_idx_type info, ilo, ihi, ilos, ihis; |
3468 | 2599 Array<double> dpermute (nc); |
2600 Array<double> dscale (nc); | |
3466 | 2601 |
3468 | 2602 // permutation first |
2603 char job = 'P'; | |
4552 | 2604 F77_XFCN (dgebal, DGEBAL, (F77_CONST_CHAR_ARG2 (&job, 1), |
2605 nc, p_m, nc, ilo, ihi, | |
2606 dpermute.fortran_vec (), info | |
2607 F77_CHAR_ARG_LEN (1))); | |
3466 | 2608 |
3468 | 2609 // then scaling |
2610 job = 'S'; | |
4552 | 2611 F77_XFCN (dgebal, DGEBAL, (F77_CONST_CHAR_ARG2 (&job, 1), |
2612 nc, p_m, nc, ilos, ihis, | |
2613 dscale.fortran_vec (), info | |
2614 F77_CHAR_ARG_LEN (1))); | |
3331 | 2615 |
1819 | 2616 // Preconditioning step 3: scaling. |
3331 | 2617 |
1819 | 2618 ColumnVector work(nc); |
3130 | 2619 double inf_norm; |
3331 | 2620 |
4552 | 2621 F77_XFCN (xdlange, XDLANGE, (F77_CONST_CHAR_ARG2 ("I", 1), |
2622 nc, nc, m.fortran_vec (), nc, | |
2623 work.fortran_vec (), inf_norm | |
2624 F77_CHAR_ARG_LEN (1))); | |
3331 | 2625 |
5275 | 2626 octave_idx_type sqpow = static_cast<octave_idx_type> (inf_norm > 0.0 |
1819 | 2627 ? (1.0 + log (inf_norm) / log (2.0)) |
2628 : 0.0); | |
3331 | 2629 |
1819 | 2630 // Check whether we need to square at all. |
3331 | 2631 |
1819 | 2632 if (sqpow < 0) |
2633 sqpow = 0; | |
3331 | 2634 |
1819 | 2635 if (sqpow > 0) |
2636 { | |
7400 | 2637 if (sqpow > 1023) |
2638 sqpow = 1023; | |
2639 | |
1819 | 2640 double scale_factor = 1.0; |
5275 | 2641 for (octave_idx_type i = 0; i < sqpow; i++) |
1819 | 2642 scale_factor *= 2.0; |
7400 | 2643 |
1819 | 2644 m = m / scale_factor; |
2645 } | |
3331 | 2646 |
1819 | 2647 // npp, dpp: pade' approx polynomial matrices. |
3331 | 2648 |
1819 | 2649 Matrix npp (nc, nc, 0.0); |
7265 | 2650 double *pnpp = npp.fortran_vec (); |
1819 | 2651 Matrix dpp = npp; |
7265 | 2652 double *pdpp = dpp.fortran_vec (); |
3331 | 2653 |
1819 | 2654 // Now powers a^8 ... a^1. |
3331 | 2655 |
5275 | 2656 octave_idx_type minus_one_j = -1; |
2657 for (octave_idx_type j = 7; j >= 0; j--) | |
1819 | 2658 { |
7265 | 2659 for (octave_idx_type i = 0; i < nc; i++) |
2660 { | |
2661 octave_idx_type k = i * nc + i; | |
2662 pnpp[k] += padec[j]; | |
2663 pdpp[k] += minus_one_j * padec[j]; | |
2664 } | |
2665 | |
2666 npp = m * npp; | |
2667 pnpp = npp.fortran_vec (); | |
2668 | |
2669 dpp = m * dpp; | |
2670 pdpp = dpp.fortran_vec (); | |
2671 | |
1819 | 2672 minus_one_j *= -1; |
2673 } | |
3331 | 2674 |
1819 | 2675 // Zero power. |
3331 | 2676 |
1819 | 2677 dpp = -dpp; |
5275 | 2678 for (octave_idx_type j = 0; j < nc; j++) |
1819 | 2679 { |
2680 npp.elem (j, j) += 1.0; | |
2681 dpp.elem (j, j) += 1.0; | |
2682 } | |
3331 | 2683 |
1819 | 2684 // Compute pade approximation = inverse (dpp) * npp. |
2685 | |
7788 | 2686 double rcon; |
2687 retval = dpp.solve (npp, info, rcon, solve_singularity_warning); | |
7400 | 2688 |
2689 if (info < 0) | |
2690 return retval; | |
2691 | |
1819 | 2692 // Reverse preconditioning step 3: repeated squaring. |
3331 | 2693 |
1819 | 2694 while (sqpow) |
2695 { | |
2696 retval = retval * retval; | |
2697 sqpow--; | |
2698 } | |
3331 | 2699 |
1819 | 2700 // Reverse preconditioning step 2: inverse balancing. |
3466 | 2701 // apply inverse scaling to computed exponential |
5275 | 2702 for (octave_idx_type i = 0; i < nc; i++) |
2703 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
|
2704 retval(i,j) *= dscale(i) / dscale(j); |
3466 | 2705 |
4153 | 2706 OCTAVE_QUIT; |
2707 | |
3466 | 2708 // construct balancing permutation vector |
5275 | 2709 Array<octave_idx_type> iperm (nc); |
2710 for (octave_idx_type i = 0; i < nc; i++) | |
4593 | 2711 iperm(i) = i; // identity permutation |
3466 | 2712 |
8211
851803f7bb4d
improve inverse preconditioning according to Marco Caliari
Jaroslav Hajek <highegg@gmail.com>
parents:
7922
diff
changeset
|
2713 // 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
|
2714 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
|
2715 { |
851803f7bb4d
improve inverse preconditioning according to Marco Caliari
Jaroslav Hajek <highegg@gmail.com>
parents:
7922
diff
changeset
|
2716 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
|
2717 octave_idx_type tmp = iperm(i); |
851803f7bb4d
improve inverse preconditioning according to Marco Caliari
Jaroslav Hajek <highegg@gmail.com>
parents:
7922
diff
changeset
|
2718 iperm(i) = iperm(swapidx); |
851803f7bb4d
improve inverse preconditioning according to Marco Caliari
Jaroslav Hajek <highegg@gmail.com>
parents:
7922
diff
changeset
|
2719 iperm(swapidx) = tmp; |
851803f7bb4d
improve inverse preconditioning according to Marco Caliari
Jaroslav Hajek <highegg@gmail.com>
parents:
7922
diff
changeset
|
2720 } |
851803f7bb4d
improve inverse preconditioning according to Marco Caliari
Jaroslav Hajek <highegg@gmail.com>
parents:
7922
diff
changeset
|
2721 |
3466 | 2722 // leading permutations in forward order |
5275 | 2723 for (octave_idx_type i = 0; i < (ilo-1); i++) |
3468 | 2724 { |
5275 | 2725 octave_idx_type swapidx = static_cast<octave_idx_type> (dpermute(i)) - 1; |
2726 octave_idx_type tmp = iperm(i); | |
4593 | 2727 iperm(i) = iperm (swapidx); |
2728 iperm(swapidx) = tmp; | |
3468 | 2729 } |
3466 | 2730 |
7416 | 2731 // construct inverse balancing permutation vector |
2732 Array<octave_idx_type> invpvec (nc); | |
2733 for (octave_idx_type i = 0; i < nc; i++) | |
2734 invpvec(iperm(i)) = i; // Thanks to R. A. Lippert for this method | |
2735 | |
2736 OCTAVE_QUIT; | |
8211
851803f7bb4d
improve inverse preconditioning according to Marco Caliari
Jaroslav Hajek <highegg@gmail.com>
parents:
7922
diff
changeset
|
2737 |
7416 | 2738 Matrix tmpMat = retval; |
2739 for (octave_idx_type i = 0; i < nc; i++) | |
2740 for (octave_idx_type j = 0; j < nc; j++) | |
2741 retval(i,j) = tmpMat(invpvec(i),invpvec(j)); | |
2742 | |
8211
851803f7bb4d
improve inverse preconditioning according to Marco Caliari
Jaroslav Hajek <highegg@gmail.com>
parents:
7922
diff
changeset
|
2743 // Reverse preconditioning step 1: fix trace normalization. |
3130 | 2744 if (trshift > 0.0) |
2745 retval = exp (trshift) * retval; | |
2746 | |
2747 return retval; | |
1819 | 2748 } |
2749 | |
458 | 2750 Matrix& |
2751 Matrix::operator += (const DiagMatrix& a) | |
2752 { | |
5275 | 2753 octave_idx_type nr = rows (); |
2754 octave_idx_type nc = cols (); | |
2755 | |
2756 octave_idx_type a_nr = a.rows (); | |
2757 octave_idx_type a_nc = a.cols (); | |
2385 | 2758 |
2759 if (nr != a_nr || nc != a_nc) | |
458 | 2760 { |
2385 | 2761 gripe_nonconformant ("operator +=", nr, nc, a_nr, a_nc); |
458 | 2762 return *this; |
2763 } | |
2764 | |
5275 | 2765 for (octave_idx_type i = 0; i < a.length (); i++) |
458 | 2766 elem (i, i) += a.elem (i, i); |
2767 | |
2768 return *this; | |
2769 } | |
2770 | |
2771 Matrix& | |
2772 Matrix::operator -= (const DiagMatrix& a) | |
2773 { | |
5275 | 2774 octave_idx_type nr = rows (); |
2775 octave_idx_type nc = cols (); | |
2776 | |
2777 octave_idx_type a_nr = a.rows (); | |
2778 octave_idx_type a_nc = a.cols (); | |
2385 | 2779 |
2780 if (nr != a_nr || nc != a_nc) | |
458 | 2781 { |
2385 | 2782 gripe_nonconformant ("operator -=", nr, nc, a_nr, a_nc); |
458 | 2783 return *this; |
2784 } | |
2785 | |
5275 | 2786 for (octave_idx_type i = 0; i < a.length (); i++) |
458 | 2787 elem (i, i) -= a.elem (i, i); |
2788 | |
2789 return *this; | |
2790 } | |
2791 | |
2792 // unary operations | |
2793 | |
2964 | 2794 boolMatrix |
458 | 2795 Matrix::operator ! (void) const |
2796 { | |
5275 | 2797 octave_idx_type nr = rows (); |
2798 octave_idx_type nc = cols (); | |
458 | 2799 |
2964 | 2800 boolMatrix b (nr, nc); |
458 | 2801 |
5275 | 2802 for (octave_idx_type j = 0; j < nc; j++) |
2803 for (octave_idx_type i = 0; i < nr; i++) | |
458 | 2804 b.elem (i, j) = ! elem (i, j); |
2805 | |
2806 return b; | |
2807 } | |
2808 | |
1205 | 2809 // column vector by row vector -> matrix operations |
458 | 2810 |
1205 | 2811 Matrix |
2812 operator * (const ColumnVector& v, const RowVector& a) | |
458 | 2813 { |
1948 | 2814 Matrix retval; |
2815 | |
5275 | 2816 octave_idx_type len = v.length (); |
3233 | 2817 |
2818 if (len != 0) | |
1205 | 2819 { |
5275 | 2820 octave_idx_type a_len = a.length (); |
3233 | 2821 |
2822 retval.resize (len, a_len); | |
2823 double *c = retval.fortran_vec (); | |
2824 | |
4552 | 2825 F77_XFCN (dgemm, DGEMM, (F77_CONST_CHAR_ARG2 ("N", 1), |
2826 F77_CONST_CHAR_ARG2 ("N", 1), | |
2827 len, a_len, 1, 1.0, v.data (), len, | |
2828 a.data (), 1, 0.0, c, len | |
2829 F77_CHAR_ARG_LEN (1) | |
2830 F77_CHAR_ARG_LEN (1))); | |
1205 | 2831 } |
458 | 2832 |
1948 | 2833 return retval; |
458 | 2834 } |
2835 | |
2836 // other operations. | |
2837 | |
2838 Matrix | |
7503
8c32f95c2639
convert mapper functions to new format
David Bateman <dbateman@free.fr>
parents:
7488
diff
changeset
|
2839 Matrix::map (dmapper fcn) const |
1205 | 2840 { |
7503
8c32f95c2639
convert mapper functions to new format
David Bateman <dbateman@free.fr>
parents:
7488
diff
changeset
|
2841 return MArray2<double>::map<double> (func_ptr (fcn)); |
8c32f95c2639
convert mapper functions to new format
David Bateman <dbateman@free.fr>
parents:
7488
diff
changeset
|
2842 } |
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 ComplexMatrix |
8c32f95c2639
convert mapper functions to new format
David Bateman <dbateman@free.fr>
parents:
7488
diff
changeset
|
2845 Matrix::map (cmapper fcn) const |
8c32f95c2639
convert mapper functions to new format
David Bateman <dbateman@free.fr>
parents:
7488
diff
changeset
|
2846 { |
8c32f95c2639
convert mapper functions to new format
David Bateman <dbateman@free.fr>
parents:
7488
diff
changeset
|
2847 return MArray2<double>::map<Complex> (func_ptr (fcn)); |
1205 | 2848 } |
2849 | |
3248 | 2850 boolMatrix |
7503
8c32f95c2639
convert mapper functions to new format
David Bateman <dbateman@free.fr>
parents:
7488
diff
changeset
|
2851 Matrix::map (bmapper fcn) const |
3248 | 2852 { |
7503
8c32f95c2639
convert mapper functions to new format
David Bateman <dbateman@free.fr>
parents:
7488
diff
changeset
|
2853 return MArray2<double>::map<bool> (func_ptr (fcn)); |
458 | 2854 } |
2855 | |
2385 | 2856 bool |
4431 | 2857 Matrix::any_element_is_negative (bool neg_zero) const |
2385 | 2858 { |
5275 | 2859 octave_idx_type nel = nelem (); |
2385 | 2860 |
4431 | 2861 if (neg_zero) |
2862 { | |
5275 | 2863 for (octave_idx_type i = 0; i < nel; i++) |
4634 | 2864 if (lo_ieee_signbit (elem (i))) |
2865 return true; | |
4431 | 2866 } |
2867 else | |
2868 { | |
5275 | 2869 for (octave_idx_type i = 0; i < nel; i++) |
4634 | 2870 if (elem (i) < 0) |
2871 return true; | |
4431 | 2872 } |
2385 | 2873 |
2874 return false; | |
2875 } | |
2876 | |
7922
935be827eaf8
error for NaN values in & and | expressions
John W. Eaton <jwe@octave.org>
parents:
7803
diff
changeset
|
2877 bool |
935be827eaf8
error for NaN values in & and | expressions
John W. Eaton <jwe@octave.org>
parents:
7803
diff
changeset
|
2878 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
|
2879 { |
935be827eaf8
error for NaN values in & and | expressions
John W. Eaton <jwe@octave.org>
parents:
7803
diff
changeset
|
2880 octave_idx_type nel = nelem (); |
935be827eaf8
error for NaN values in & and | expressions
John W. Eaton <jwe@octave.org>
parents:
7803
diff
changeset
|
2881 |
935be827eaf8
error for NaN values in & and | expressions
John W. Eaton <jwe@octave.org>
parents:
7803
diff
changeset
|
2882 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
|
2883 { |
935be827eaf8
error for NaN values in & and | expressions
John W. Eaton <jwe@octave.org>
parents:
7803
diff
changeset
|
2884 double val = elem (i); |
935be827eaf8
error for NaN values in & and | expressions
John W. Eaton <jwe@octave.org>
parents:
7803
diff
changeset
|
2885 if (xisnan (val)) |
935be827eaf8
error for NaN values in & and | expressions
John W. Eaton <jwe@octave.org>
parents:
7803
diff
changeset
|
2886 return true; |
935be827eaf8
error for NaN values in & and | expressions
John W. Eaton <jwe@octave.org>
parents:
7803
diff
changeset
|
2887 } |
935be827eaf8
error for NaN values in & and | expressions
John W. Eaton <jwe@octave.org>
parents:
7803
diff
changeset
|
2888 |
935be827eaf8
error for NaN values in & and | expressions
John W. Eaton <jwe@octave.org>
parents:
7803
diff
changeset
|
2889 return false; |
935be827eaf8
error for NaN values in & and | expressions
John W. Eaton <jwe@octave.org>
parents:
7803
diff
changeset
|
2890 } |
2385 | 2891 |
2892 bool | |
2893 Matrix::any_element_is_inf_or_nan (void) const | |
2894 { | |
5275 | 2895 octave_idx_type nel = nelem (); |
2896 | |
2897 for (octave_idx_type i = 0; i < nel; i++) | |
4634 | 2898 { |
2899 double val = elem (i); | |
2900 if (xisinf (val) || xisnan (val)) | |
2901 return true; | |
2902 } | |
2903 | |
2904 return false; | |
2385 | 2905 } |
2906 | |
2907 bool | |
5943 | 2908 Matrix::any_element_not_one_or_zero (void) const |
2909 { | |
2910 octave_idx_type nel = nelem (); | |
2911 | |
2912 for (octave_idx_type i = 0; i < nel; i++) | |
2913 { | |
2914 double val = elem (i); | |
2915 if (val != 0 && val != 1) | |
2916 return true; | |
2917 } | |
2918 | |
2919 return false; | |
2920 } | |
2921 | |
2922 bool | |
2385 | 2923 Matrix::all_elements_are_int_or_inf_or_nan (void) const |
2924 { | |
5275 | 2925 octave_idx_type nel = nelem (); |
2926 | |
2927 for (octave_idx_type i = 0; i < nel; i++) | |
4634 | 2928 { |
2929 double val = elem (i); | |
2930 if (xisnan (val) || D_NINT (val) == val) | |
2931 continue; | |
2932 else | |
2933 return false; | |
2934 } | |
2385 | 2935 |
2936 return true; | |
2937 } | |
2938 | |
1968 | 2939 // Return nonzero if any element of M is not an integer. Also extract |
2940 // the largest and smallest values and return them in MAX_VAL and MIN_VAL. | |
2941 | |
2385 | 2942 bool |
1968 | 2943 Matrix::all_integers (double& max_val, double& min_val) const |
2944 { | |
5275 | 2945 octave_idx_type nel = nelem (); |
4634 | 2946 |
2947 if (nel > 0) | |
1968 | 2948 { |
4634 | 2949 max_val = elem (0); |
2950 min_val = elem (0); | |
1968 | 2951 } |
2952 else | |
2385 | 2953 return false; |
1968 | 2954 |
5275 | 2955 for (octave_idx_type i = 0; i < nel; i++) |
4634 | 2956 { |
2957 double val = elem (i); | |
2958 | |
2959 if (val > max_val) | |
2960 max_val = val; | |
2961 | |
2962 if (val < min_val) | |
2963 min_val = val; | |
2964 | |
2965 if (D_NINT (val) != val) | |
2966 return false; | |
2967 } | |
2385 | 2968 |
2969 return true; | |
1968 | 2970 } |
2971 | |
2385 | 2972 bool |
1968 | 2973 Matrix::too_large_for_float (void) const |
2974 { | |
5275 | 2975 octave_idx_type nel = nelem (); |
2976 | |
2977 for (octave_idx_type i = 0; i < nel; i++) | |
4634 | 2978 { |
2979 double val = elem (i); | |
2980 | |
5389 | 2981 if (! (xisnan (val) || xisinf (val)) |
5387 | 2982 && fabs (val) > FLT_MAX) |
4634 | 2983 return true; |
2984 } | |
1968 | 2985 |
2385 | 2986 return false; |
1968 | 2987 } |
2988 | |
5775 | 2989 // FIXME Do these really belong here? Maybe they should be |
4015 | 2990 // in a base class? |
458 | 2991 |
2832 | 2992 boolMatrix |
4015 | 2993 Matrix::all (int dim) const |
458 | 2994 { |
4015 | 2995 MX_ALL_OP (dim); |
458 | 2996 } |
2997 | |
2832 | 2998 boolMatrix |
4015 | 2999 Matrix::any (int dim) const |
458 | 3000 { |
4015 | 3001 MX_ANY_OP (dim); |
458 | 3002 } |
3003 | |
3004 Matrix | |
3723 | 3005 Matrix::cumprod (int dim) const |
458 | 3006 { |
4015 | 3007 MX_CUMULATIVE_OP (Matrix, double, *=); |
458 | 3008 } |
3009 | |
3010 Matrix | |
3723 | 3011 Matrix::cumsum (int dim) const |
458 | 3012 { |
4015 | 3013 MX_CUMULATIVE_OP (Matrix, double, +=); |
458 | 3014 } |
3015 | |
3016 Matrix | |
3723 | 3017 Matrix::prod (int dim) const |
458 | 3018 { |
3864 | 3019 MX_REDUCTION_OP (Matrix, *=, 1.0, 1.0); |
458 | 3020 } |
3021 | |
3022 Matrix | |
3723 | 3023 Matrix::sum (int dim) const |
458 | 3024 { |
3864 | 3025 MX_REDUCTION_OP (Matrix, +=, 0.0, 0.0); |
458 | 3026 } |
3027 | |
3028 Matrix | |
3723 | 3029 Matrix::sumsq (int dim) const |
458 | 3030 { |
3864 | 3031 #define ROW_EXPR \ |
3032 double d = elem (i, j); \ | |
3033 retval.elem (i, 0) += d * d | |
3034 | |
3035 #define COL_EXPR \ | |
3036 double d = elem (i, j); \ | |
3037 retval.elem (0, j) += d * d | |
3038 | |
3039 MX_BASE_REDUCTION_OP (Matrix, ROW_EXPR, COL_EXPR, 0.0, 0.0); | |
3040 | |
3041 #undef ROW_EXPR | |
3042 #undef COL_EXPR | |
458 | 3043 } |
3044 | |
2385 | 3045 Matrix |
3046 Matrix::abs (void) const | |
3047 { | |
5275 | 3048 octave_idx_type nr = rows (); |
3049 octave_idx_type nc = cols (); | |
2385 | 3050 |
3051 Matrix retval (nr, nc); | |
3052 | |
5275 | 3053 for (octave_idx_type j = 0; j < nc; j++) |
3054 for (octave_idx_type i = 0; i < nr; i++) | |
2385 | 3055 retval (i, j) = fabs (elem (i, j)); |
3056 | |
3057 return retval; | |
3058 } | |
3059 | |
7620
36594d5bbe13
Move diag function into the octave_value class
David Bateman <dbateman@free.fr>
parents:
7544
diff
changeset
|
3060 Matrix |
5275 | 3061 Matrix::diag (octave_idx_type k) const |
458 | 3062 { |
7620
36594d5bbe13
Move diag function into the octave_value class
David Bateman <dbateman@free.fr>
parents:
7544
diff
changeset
|
3063 return MArray2<double>::diag (k); |
458 | 3064 } |
3065 | |
3066 ColumnVector | |
3067 Matrix::row_min (void) const | |
3068 { | |
5275 | 3069 Array<octave_idx_type> dummy_idx; |
4587 | 3070 return row_min (dummy_idx); |
458 | 3071 } |
3072 | |
3073 ColumnVector | |
5275 | 3074 Matrix::row_min (Array<octave_idx_type>& idx_arg) const |
458 | 3075 { |
3076 ColumnVector result; | |
3077 | |
5275 | 3078 octave_idx_type nr = rows (); |
3079 octave_idx_type nc = cols (); | |
458 | 3080 |
3081 if (nr > 0 && nc > 0) | |
3082 { | |
3083 result.resize (nr); | |
4587 | 3084 idx_arg.resize (nr); |
458 | 3085 |
5275 | 3086 for (octave_idx_type i = 0; i < nr; i++) |
458 | 3087 { |
5275 | 3088 octave_idx_type idx_j; |
4469 | 3089 |
3090 double tmp_min = octave_NaN; | |
3091 | |
3092 for (idx_j = 0; idx_j < nc; idx_j++) | |
2354 | 3093 { |
4469 | 3094 tmp_min = elem (i, idx_j); |
3095 | |
5389 | 3096 if (! xisnan (tmp_min)) |
4469 | 3097 break; |
3098 } | |
3099 | |
5275 | 3100 for (octave_idx_type j = idx_j+1; j < nc; j++) |
4469 | 3101 { |
3102 double tmp = elem (i, j); | |
3103 | |
5389 | 3104 if (xisnan (tmp)) |
4469 | 3105 continue; |
3106 else if (tmp < tmp_min) | |
2354 | 3107 { |
4469 | 3108 idx_j = j; |
3109 tmp_min = tmp; | |
2354 | 3110 } |
3111 } | |
3112 | |
4469 | 3113 result.elem (i) = tmp_min; |
5389 | 3114 idx_arg.elem (i) = xisnan (tmp_min) ? 0 : idx_j; |
458 | 3115 } |
3116 } | |
3117 | |
3118 return result; | |
3119 } | |
3120 | |
3121 ColumnVector | |
3122 Matrix::row_max (void) const | |
3123 { | |
5275 | 3124 Array<octave_idx_type> dummy_idx; |
4587 | 3125 return row_max (dummy_idx); |
458 | 3126 } |
3127 | |
3128 ColumnVector | |
5275 | 3129 Matrix::row_max (Array<octave_idx_type>& idx_arg) const |
458 | 3130 { |
3131 ColumnVector result; | |
3132 | |
5275 | 3133 octave_idx_type nr = rows (); |
3134 octave_idx_type nc = cols (); | |
458 | 3135 |
3136 if (nr > 0 && nc > 0) | |
3137 { | |
3138 result.resize (nr); | |
4587 | 3139 idx_arg.resize (nr); |
458 | 3140 |
5275 | 3141 for (octave_idx_type i = 0; i < nr; i++) |
458 | 3142 { |
5275 | 3143 octave_idx_type idx_j; |
4469 | 3144 |
3145 double tmp_max = octave_NaN; | |
3146 | |
3147 for (idx_j = 0; idx_j < nc; idx_j++) | |
2354 | 3148 { |
4469 | 3149 tmp_max = elem (i, idx_j); |
3150 | |
5389 | 3151 if (! xisnan (tmp_max)) |
4469 | 3152 break; |
3153 } | |
3154 | |
5275 | 3155 for (octave_idx_type j = idx_j+1; j < nc; j++) |
4469 | 3156 { |
3157 double tmp = elem (i, j); | |
3158 | |
5389 | 3159 if (xisnan (tmp)) |
4469 | 3160 continue; |
3161 else if (tmp > tmp_max) | |
2354 | 3162 { |
4469 | 3163 idx_j = j; |
3164 tmp_max = tmp; | |
2354 | 3165 } |
3166 } | |
3167 | |
4469 | 3168 result.elem (i) = tmp_max; |
5389 | 3169 idx_arg.elem (i) = xisnan (tmp_max) ? 0 : idx_j; |
458 | 3170 } |
3171 } | |
3172 | |
3173 return result; | |
3174 } | |
3175 | |
3176 RowVector | |
3177 Matrix::column_min (void) const | |
3178 { | |
5275 | 3179 Array<octave_idx_type> dummy_idx; |
4587 | 3180 return column_min (dummy_idx); |
458 | 3181 } |
2354 | 3182 |
458 | 3183 RowVector |
5275 | 3184 Matrix::column_min (Array<octave_idx_type>& idx_arg) const |
458 | 3185 { |
3186 RowVector result; | |
3187 | |
5275 | 3188 octave_idx_type nr = rows (); |
3189 octave_idx_type nc = cols (); | |
458 | 3190 |
3191 if (nr > 0 && nc > 0) | |
3192 { | |
3193 result.resize (nc); | |
4587 | 3194 idx_arg.resize (nc); |
458 | 3195 |
5275 | 3196 for (octave_idx_type j = 0; j < nc; j++) |
458 | 3197 { |
5275 | 3198 octave_idx_type idx_i; |
4469 | 3199 |
3200 double tmp_min = octave_NaN; | |
3201 | |
3202 for (idx_i = 0; idx_i < nr; idx_i++) | |
2354 | 3203 { |
4469 | 3204 tmp_min = elem (idx_i, j); |
3205 | |
5389 | 3206 if (! xisnan (tmp_min)) |
4469 | 3207 break; |
3208 } | |
3209 | |
5275 | 3210 for (octave_idx_type i = idx_i+1; i < nr; i++) |
4469 | 3211 { |
3212 double tmp = elem (i, j); | |
3213 | |
5389 | 3214 if (xisnan (tmp)) |
4469 | 3215 continue; |
3216 else if (tmp < tmp_min) | |
2354 | 3217 { |
4469 | 3218 idx_i = i; |
3219 tmp_min = tmp; | |
2354 | 3220 } |
3221 } | |
3222 | |
4469 | 3223 result.elem (j) = tmp_min; |
5389 | 3224 idx_arg.elem (j) = xisnan (tmp_min) ? 0 : idx_i; |
458 | 3225 } |
3226 } | |
3227 | |
3228 return result; | |
3229 } | |
3230 | |
2354 | 3231 RowVector |
3232 Matrix::column_max (void) const | |
3233 { | |
5275 | 3234 Array<octave_idx_type> dummy_idx; |
4587 | 3235 return column_max (dummy_idx); |
2354 | 3236 } |
458 | 3237 |
3238 RowVector | |
5275 | 3239 Matrix::column_max (Array<octave_idx_type>& idx_arg) const |
458 | 3240 { |
3241 RowVector result; | |
3242 | |
5275 | 3243 octave_idx_type nr = rows (); |
3244 octave_idx_type nc = cols (); | |
458 | 3245 |
3246 if (nr > 0 && nc > 0) | |
3247 { | |
3248 result.resize (nc); | |
4587 | 3249 idx_arg.resize (nc); |
458 | 3250 |
5275 | 3251 for (octave_idx_type j = 0; j < nc; j++) |
458 | 3252 { |
5275 | 3253 octave_idx_type idx_i; |
4469 | 3254 |
3255 double tmp_max = octave_NaN; | |
3256 | |
3257 for (idx_i = 0; idx_i < nr; idx_i++) | |
2354 | 3258 { |
4469 | 3259 tmp_max = elem (idx_i, j); |
3260 | |
5389 | 3261 if (! xisnan (tmp_max)) |
4469 | 3262 break; |
3263 } | |
3264 | |
5275 | 3265 for (octave_idx_type i = idx_i+1; i < nr; i++) |
4469 | 3266 { |
3267 double tmp = elem (i, j); | |
3268 | |
5389 | 3269 if (xisnan (tmp)) |
4469 | 3270 continue; |
3271 else if (tmp > tmp_max) | |
2354 | 3272 { |
4469 | 3273 idx_i = i; |
3274 tmp_max = tmp; | |
2354 | 3275 } |
3276 } | |
3277 | |
4469 | 3278 result.elem (j) = tmp_max; |
5389 | 3279 idx_arg.elem (j) = xisnan (tmp_max) ? 0 : idx_i; |
458 | 3280 } |
3281 } | |
3282 | |
3283 return result; | |
3284 } | |
3285 | |
3504 | 3286 std::ostream& |
3287 operator << (std::ostream& os, const Matrix& a) | |
458 | 3288 { |
5275 | 3289 for (octave_idx_type i = 0; i < a.rows (); i++) |
458 | 3290 { |
5275 | 3291 for (octave_idx_type j = 0; j < a.cols (); j++) |
4130 | 3292 { |
3293 os << " "; | |
3294 octave_write_double (os, a.elem (i, j)); | |
3295 } | |
458 | 3296 os << "\n"; |
3297 } | |
3298 return os; | |
3299 } | |
3300 | |
3504 | 3301 std::istream& |
3302 operator >> (std::istream& is, Matrix& a) | |
458 | 3303 { |
5275 | 3304 octave_idx_type nr = a.rows (); |
3305 octave_idx_type nc = a.cols (); | |
458 | 3306 |
3307 if (nr < 1 || nc < 1) | |
3504 | 3308 is.clear (std::ios::badbit); |
458 | 3309 else |
3310 { | |
3311 double tmp; | |
5275 | 3312 for (octave_idx_type i = 0; i < nr; i++) |
3313 for (octave_idx_type j = 0; j < nc; j++) | |
458 | 3314 { |
4130 | 3315 tmp = octave_read_double (is); |
458 | 3316 if (is) |
3317 a.elem (i, j) = tmp; | |
3318 else | |
2795 | 3319 goto done; |
458 | 3320 } |
3321 } | |
3322 | |
2795 | 3323 done: |
3324 | |
458 | 3325 return is; |
3326 } | |
3327 | |
1819 | 3328 Matrix |
3329 Givens (double x, double y) | |
3330 { | |
3331 double cc, s, temp_r; | |
3332 | |
3887 | 3333 F77_FUNC (dlartg, DLARTG) (x, y, cc, s, temp_r); |
1819 | 3334 |
3335 Matrix g (2, 2); | |
3336 | |
3337 g.elem (0, 0) = cc; | |
3338 g.elem (1, 1) = cc; | |
3339 g.elem (0, 1) = s; | |
3340 g.elem (1, 0) = -s; | |
3341 | |
3342 return g; | |
3343 } | |
3344 | |
3345 Matrix | |
3346 Sylvester (const Matrix& a, const Matrix& b, const Matrix& c) | |
3347 { | |
3348 Matrix retval; | |
3349 | |
5775 | 3350 // FIXME -- need to check that a, b, and c are all the same |
1819 | 3351 // size. |
3352 | |
3353 // Compute Schur decompositions. | |
3354 | |
3355 SCHUR as (a, "U"); | |
3356 SCHUR bs (b, "U"); | |
3357 | |
3358 // Transform c to new coordinates. | |
3359 | |
3360 Matrix ua = as.unitary_matrix (); | |
3361 Matrix sch_a = as.schur_matrix (); | |
3362 | |
3363 Matrix ub = bs.unitary_matrix (); | |
3364 Matrix sch_b = bs.schur_matrix (); | |
3365 | |
3366 Matrix cx = ua.transpose () * c * ub; | |
3367 | |
3368 // Solve the sylvester equation, back-transform, and return the | |
3369 // solution. | |
3370 | |
5275 | 3371 octave_idx_type a_nr = a.rows (); |
3372 octave_idx_type b_nr = b.rows (); | |
1819 | 3373 |
3374 double scale; | |
5275 | 3375 octave_idx_type info; |
1819 | 3376 |
1950 | 3377 double *pa = sch_a.fortran_vec (); |
3378 double *pb = sch_b.fortran_vec (); | |
3379 double *px = cx.fortran_vec (); | |
3380 | |
4552 | 3381 F77_XFCN (dtrsyl, DTRSYL, (F77_CONST_CHAR_ARG2 ("N", 1), |
3382 F77_CONST_CHAR_ARG2 ("N", 1), | |
3383 1, a_nr, b_nr, pa, a_nr, pb, | |
3384 b_nr, px, a_nr, scale, info | |
3385 F77_CHAR_ARG_LEN (1) | |
3386 F77_CHAR_ARG_LEN (1))); | |
1950 | 3387 |
3388 | |
7482
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
3389 // FIXME -- check info? |
1819 | 3390 |
7482
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7478
diff
changeset
|
3391 retval = -ua*cx*ub.transpose (); |
1819 | 3392 |
3393 return retval; | |
3394 } | |
3395 | |
2828 | 3396 // matrix by matrix -> matrix operations |
3397 | |
6162 | 3398 /* Simple Dot Product, Matrix-Vector and Matrix-Matrix Unit tests |
3399 %!assert([1 2 3] * [ 4 ; 5 ; 6], 32, 1e-14) | |
3400 %!assert([1 2 ; 3 4 ] * [5 ; 6], [17 ; 39 ], 1e-14) | |
3401 %!assert([1 2 ; 3 4 ] * [5 6 ; 7 8], [19 22; 43 50], 1e-14) | |
3402 */ | |
3403 | |
3404 /* Test some simple identities | |
3405 %!shared M, cv, rv | |
3406 %! M = randn(10,10); | |
3407 %! cv = randn(10,1); | |
3408 %! rv = randn(1,10); | |
3409 %!assert([M*cv,M*cv],M*[cv,cv],1e-14) | |
3410 %!assert([rv*M;rv*M],[rv;rv]*M,1e-14) | |
3411 %!assert(2*rv*cv,[rv,rv]*[cv;cv],1e-14) | |
3412 */ | |
3413 | |
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
|
3414 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
|
3415 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
|
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 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
|
3418 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
|
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 |
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 // 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
|
3422 |
5861b95e9879
support for compound operators, implement trans_mul, mul_trans, herm_mul and mul_herm
Jaroslav Hajek <highegg@gmail.com>
parents:
7789
diff
changeset
|
3423 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
|
3424 xgemm (bool transa, const Matrix& a, bool transb, const Matrix& b) |
2828 | 3425 { |
3426 Matrix retval; | |
3427 | |
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
|
3428 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
|
3429 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
|
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 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
|
3432 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
|
3433 |
5861b95e9879
support for compound operators, implement trans_mul, mul_trans, herm_mul and mul_herm
Jaroslav Hajek <highegg@gmail.com>
parents:
7789
diff
changeset
|
3434 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
|
3435 gripe_nonconformant ("operator *", a_nr, a_nc, b_nr, b_nc); |
2828 | 3436 else |
3437 { | |
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
|
3438 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
|
3439 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
|
3440 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
|
3441 { |
776791438957
map symmetric cases to xHERK, xSYRK
Jaroslav Hajek <highegg@gmail.com>
parents:
7800
diff
changeset
|
3442 octave_idx_type lda = a.rows (); |
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 retval.resize (a_nr, b_nc); |
776791438957
map symmetric cases to xHERK, xSYRK
Jaroslav Hajek <highegg@gmail.com>
parents:
7800
diff
changeset
|
3445 double *c = retval.fortran_vec (); |
776791438957
map symmetric cases to xHERK, xSYRK
Jaroslav Hajek <highegg@gmail.com>
parents:
7800
diff
changeset
|
3446 |
776791438957
map symmetric cases to xHERK, xSYRK
Jaroslav Hajek <highegg@gmail.com>
parents:
7800
diff
changeset
|
3447 const char *ctransa = get_blas_trans_arg (transa); |
776791438957
map symmetric cases to xHERK, xSYRK
Jaroslav Hajek <highegg@gmail.com>
parents:
7800
diff
changeset
|
3448 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
|
3449 F77_CONST_CHAR_ARG2 (ctransa, 1), |
776791438957
map symmetric cases to xHERK, xSYRK
Jaroslav Hajek <highegg@gmail.com>
parents:
7800
diff
changeset
|
3450 a_nr, a_nc, 1.0, |
776791438957
map symmetric cases to xHERK, xSYRK
Jaroslav Hajek <highegg@gmail.com>
parents:
7800
diff
changeset
|
3451 a.data (), lda, 0.0, c, a_nr |
776791438957
map symmetric cases to xHERK, xSYRK
Jaroslav Hajek <highegg@gmail.com>
parents:
7800
diff
changeset
|
3452 F77_CHAR_ARG_LEN (1) |
776791438957
map symmetric cases to xHERK, xSYRK
Jaroslav Hajek <highegg@gmail.com>
parents:
7800
diff
changeset
|
3453 F77_CHAR_ARG_LEN (1))); |
776791438957
map symmetric cases to xHERK, xSYRK
Jaroslav Hajek <highegg@gmail.com>
parents:
7800
diff
changeset
|
3454 for (int j = 0; j < a_nr; j++) |
776791438957
map symmetric cases to xHERK, xSYRK
Jaroslav Hajek <highegg@gmail.com>
parents:
7800
diff
changeset
|
3455 for (int i = 0; i < j; i++) |
776791438957
map symmetric cases to xHERK, xSYRK
Jaroslav Hajek <highegg@gmail.com>
parents:
7800
diff
changeset
|
3456 retval.xelem (j,i) = retval.xelem (i,j); |
776791438957
map symmetric cases to xHERK, xSYRK
Jaroslav Hajek <highegg@gmail.com>
parents:
7800
diff
changeset
|
3457 |
776791438957
map symmetric cases to xHERK, xSYRK
Jaroslav Hajek <highegg@gmail.com>
parents:
7800
diff
changeset
|
3458 } |
2828 | 3459 else |
3460 { | |
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
|
3461 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
|
3462 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
|
3463 |
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 retval.resize (a_nr, b_nc); |
2828 | 3465 double *c = retval.fortran_vec (); |
3466 | |
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
|
3467 if (b_nc == 1) |
5983 | 3468 { |
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
|
3469 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
|
3470 F77_FUNC (xddot, XDDOT) (a_nc, a.data (), 1, b.data (), 1, *c); |
5983 | 3471 else |
6390 | 3472 { |
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
|
3473 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
|
3474 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
|
3475 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
|
3476 b.data (), 1, 0.0, c, 1 |
6390 | 3477 F77_CHAR_ARG_LEN (1))); |
3478 } | |
5983 | 3479 } |
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
|
3480 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
|
3481 { |
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 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
|
3483 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
|
3484 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
|
3485 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
|
3486 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
|
3487 } |
5983 | 3488 else |
6390 | 3489 { |
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
|
3490 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
|
3491 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
|
3492 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
|
3493 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
|
3494 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
|
3495 lda, b.data (), ldb, 0.0, c, a_nr |
6390 | 3496 F77_CHAR_ARG_LEN (1) |
3497 F77_CHAR_ARG_LEN (1))); | |
3498 } | |
2828 | 3499 } |
3500 } | |
3501 | |
3502 return retval; | |
3503 } | |
3504 | |
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
|
3505 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
|
3506 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
|
3507 { |
5861b95e9879
support for compound operators, implement trans_mul, mul_trans, herm_mul and mul_herm
Jaroslav Hajek <highegg@gmail.com>
parents:
7789
diff
changeset
|
3508 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
|
3509 } |
5861b95e9879
support for compound operators, implement trans_mul, mul_trans, herm_mul and mul_herm
Jaroslav Hajek <highegg@gmail.com>
parents:
7789
diff
changeset
|
3510 |
5775 | 3511 // FIXME -- it would be nice to share code among the min/max |
4309 | 3512 // functions below. |
3513 | |
3514 #define EMPTY_RETURN_CHECK(T) \ | |
3515 if (nr == 0 || nc == 0) \ | |
3516 return T (nr, nc); | |
3517 | |
3518 Matrix | |
3519 min (double d, const Matrix& m) | |
3520 { | |
5275 | 3521 octave_idx_type nr = m.rows (); |
3522 octave_idx_type nc = m.columns (); | |
4309 | 3523 |
3524 EMPTY_RETURN_CHECK (Matrix); | |
3525 | |
3526 Matrix result (nr, nc); | |
3527 | |
5275 | 3528 for (octave_idx_type j = 0; j < nc; j++) |
3529 for (octave_idx_type i = 0; i < nr; i++) | |
4309 | 3530 { |
3531 OCTAVE_QUIT; | |
3532 result (i, j) = xmin (d, m (i, j)); | |
3533 } | |
3534 | |
3535 return result; | |
3536 } | |
3537 | |
3538 Matrix | |
3539 min (const Matrix& m, double d) | |
3540 { | |
5275 | 3541 octave_idx_type nr = m.rows (); |
3542 octave_idx_type nc = m.columns (); | |
4309 | 3543 |
3544 EMPTY_RETURN_CHECK (Matrix); | |
3545 | |
3546 Matrix result (nr, nc); | |
3547 | |
5275 | 3548 for (octave_idx_type j = 0; j < nc; j++) |
3549 for (octave_idx_type i = 0; i < nr; i++) | |
4309 | 3550 { |
3551 OCTAVE_QUIT; | |
3552 result (i, j) = xmin (m (i, j), d); | |
3553 } | |
3554 | |
3555 return result; | |
3556 } | |
3557 | |
3558 Matrix | |
3559 min (const Matrix& a, const Matrix& b) | |
3560 { | |
5275 | 3561 octave_idx_type nr = a.rows (); |
3562 octave_idx_type nc = a.columns (); | |
4309 | 3563 |
3564 if (nr != b.rows () || nc != b.columns ()) | |
3565 { | |
3566 (*current_liboctave_error_handler) | |
3567 ("two-arg min expecting args of same size"); | |
3568 return Matrix (); | |
3569 } | |
3570 | |
3571 EMPTY_RETURN_CHECK (Matrix); | |
3572 | |
3573 Matrix result (nr, nc); | |
3574 | |
5275 | 3575 for (octave_idx_type j = 0; j < nc; j++) |
3576 for (octave_idx_type i = 0; i < nr; i++) | |
4309 | 3577 { |
3578 OCTAVE_QUIT; | |
3579 result (i, j) = xmin (a (i, j), b (i, j)); | |
3580 } | |
3581 | |
3582 return result; | |
3583 } | |
3584 | |
3585 Matrix | |
3586 max (double d, const Matrix& m) | |
3587 { | |
5275 | 3588 octave_idx_type nr = m.rows (); |
3589 octave_idx_type nc = m.columns (); | |
4309 | 3590 |
3591 EMPTY_RETURN_CHECK (Matrix); | |
3592 | |
3593 Matrix result (nr, nc); | |
3594 | |
5275 | 3595 for (octave_idx_type j = 0; j < nc; j++) |
3596 for (octave_idx_type i = 0; i < nr; i++) | |
4309 | 3597 { |
3598 OCTAVE_QUIT; | |
3599 result (i, j) = xmax (d, m (i, j)); | |
3600 } | |
3601 | |
3602 return result; | |
3603 } | |
3604 | |
3605 Matrix | |
3606 max (const Matrix& m, double d) | |
3607 { | |
5275 | 3608 octave_idx_type nr = m.rows (); |
3609 octave_idx_type nc = m.columns (); | |
4309 | 3610 |
3611 EMPTY_RETURN_CHECK (Matrix); | |
3612 | |
3613 Matrix result (nr, nc); | |
3614 | |
5275 | 3615 for (octave_idx_type j = 0; j < nc; j++) |
3616 for (octave_idx_type i = 0; i < nr; i++) | |
4309 | 3617 { |
3618 OCTAVE_QUIT; | |
3619 result (i, j) = xmax (m (i, j), d); | |
3620 } | |
3621 | |
3622 return result; | |
3623 } | |
3624 | |
3625 Matrix | |
3626 max (const Matrix& a, const Matrix& b) | |
3627 { | |
5275 | 3628 octave_idx_type nr = a.rows (); |
3629 octave_idx_type nc = a.columns (); | |
4309 | 3630 |
3631 if (nr != b.rows () || nc != b.columns ()) | |
3632 { | |
3633 (*current_liboctave_error_handler) | |
3634 ("two-arg max expecting args of same size"); | |
3635 return Matrix (); | |
3636 } | |
3637 | |
3638 EMPTY_RETURN_CHECK (Matrix); | |
3639 | |
3640 Matrix result (nr, nc); | |
3641 | |
5275 | 3642 for (octave_idx_type j = 0; j < nc; j++) |
3643 for (octave_idx_type i = 0; i < nr; i++) | |
4309 | 3644 { |
3645 OCTAVE_QUIT; | |
3646 result (i, j) = xmax (a (i, j), b (i, j)); | |
3647 } | |
3648 | |
3649 return result; | |
3650 } | |
3651 | |
2870 | 3652 MS_CMP_OPS(Matrix, , double, ) |
3504 | 3653 MS_BOOL_OPS(Matrix, double, 0.0) |
2870 | 3654 |
3655 SM_CMP_OPS(double, , Matrix, ) | |
3504 | 3656 SM_BOOL_OPS(double, Matrix, 0.0) |
2870 | 3657 |
3658 MM_CMP_OPS(Matrix, , Matrix, ) | |
3504 | 3659 MM_BOOL_OPS(Matrix, Matrix, 0.0) |
2870 | 3660 |
458 | 3661 /* |
3662 ;;; Local Variables: *** | |
3663 ;;; mode: C++ *** | |
3664 ;;; End: *** | |
3665 */ |