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