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