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