Mercurial > hg > octave-lyh
annotate liboctave/CmplxCHOL.cc @ 7554:40574114c514
implement Cholesky factorization updating
author | Jaroslav Hajek <highegg@gmail.com> |
---|---|
date | Tue, 04 Mar 2008 22:25:50 -0500 |
parents | 29980c6b8604 |
children | 07522d7dcdf8 |
rev | line source |
---|---|
457 | 1 /* |
2 | |
7017 | 3 Copyright (C) 1994, 1995, 1996, 1997, 2002, 2003, 2004, 2005, 2007 |
4 John W. Eaton | |
457 | 5 |
6 This file is part of Octave. | |
7 | |
8 Octave is free software; you can redistribute it and/or modify it | |
9 under the terms of the GNU General Public License as published by the | |
7016 | 10 Free Software Foundation; either version 3 of the License, or (at your |
11 option) any later version. | |
457 | 12 |
13 Octave is distributed in the hope that it will be useful, but WITHOUT | |
14 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
15 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
16 for more details. | |
17 | |
18 You should have received a copy of the GNU General Public License | |
7016 | 19 along with Octave; see the file COPYING. If not, see |
20 <http://www.gnu.org/licenses/>. | |
457 | 21 |
22 */ | |
23 | |
7554
40574114c514
implement Cholesky factorization updating
Jaroslav Hajek <highegg@gmail.com>
parents:
7482
diff
changeset
|
24 // updating/downdating by Jaroslav Hajek 2008 |
40574114c514
implement Cholesky factorization updating
Jaroslav Hajek <highegg@gmail.com>
parents:
7482
diff
changeset
|
25 |
457 | 26 #ifdef HAVE_CONFIG_H |
1192 | 27 #include <config.h> |
457 | 28 #endif |
29 | |
7554
40574114c514
implement Cholesky factorization updating
Jaroslav Hajek <highegg@gmail.com>
parents:
7482
diff
changeset
|
30 #include <vector> |
40574114c514
implement Cholesky factorization updating
Jaroslav Hajek <highegg@gmail.com>
parents:
7482
diff
changeset
|
31 |
6486 | 32 #include "dMatrix.h" |
33 #include "dRowVector.h" | |
457 | 34 #include "CmplxCHOL.h" |
1847 | 35 #include "f77-fcn.h" |
457 | 36 #include "lo-error.h" |
37 | |
38 extern "C" | |
39 { | |
4552 | 40 F77_RET_T |
5340 | 41 F77_FUNC (zpotrf, ZPOTRF) (F77_CONST_CHAR_ARG_DECL, const octave_idx_type&, |
42 Complex*, const octave_idx_type&, octave_idx_type& | |
43 F77_CHAR_ARG_LEN_DECL); | |
44 F77_RET_T | |
45 F77_FUNC (zpotri, ZPOTRI) (F77_CONST_CHAR_ARG_DECL, const octave_idx_type&, | |
46 Complex*, const octave_idx_type&, octave_idx_type& | |
4552 | 47 F77_CHAR_ARG_LEN_DECL); |
6486 | 48 |
49 F77_RET_T | |
50 F77_FUNC (zpocon, ZPOCON) (F77_CONST_CHAR_ARG_DECL, const octave_idx_type&, | |
51 Complex*, const octave_idx_type&, const double&, | |
52 double&, Complex*, double*, | |
53 octave_idx_type& F77_CHAR_ARG_LEN_DECL); | |
7554
40574114c514
implement Cholesky factorization updating
Jaroslav Hajek <highegg@gmail.com>
parents:
7482
diff
changeset
|
54 F77_RET_T |
40574114c514
implement Cholesky factorization updating
Jaroslav Hajek <highegg@gmail.com>
parents:
7482
diff
changeset
|
55 F77_FUNC (zch1up, ZCH1UP) (const octave_idx_type&, Complex*, Complex*, double*); |
40574114c514
implement Cholesky factorization updating
Jaroslav Hajek <highegg@gmail.com>
parents:
7482
diff
changeset
|
56 |
40574114c514
implement Cholesky factorization updating
Jaroslav Hajek <highegg@gmail.com>
parents:
7482
diff
changeset
|
57 F77_RET_T |
40574114c514
implement Cholesky factorization updating
Jaroslav Hajek <highegg@gmail.com>
parents:
7482
diff
changeset
|
58 F77_FUNC (zch1dn, ZCH1DN) (const octave_idx_type&, Complex*, Complex*, double*, |
40574114c514
implement Cholesky factorization updating
Jaroslav Hajek <highegg@gmail.com>
parents:
7482
diff
changeset
|
59 octave_idx_type&); |
457 | 60 } |
61 | |
5275 | 62 octave_idx_type |
6486 | 63 ComplexCHOL::init (const ComplexMatrix& a, bool calc_cond) |
457 | 64 { |
5275 | 65 octave_idx_type a_nr = a.rows (); |
66 octave_idx_type a_nc = a.cols (); | |
457 | 67 |
1944 | 68 if (a_nr != a_nc) |
69 { | |
70 (*current_liboctave_error_handler) | |
71 ("ComplexCHOL requires square matrix"); | |
72 return -1; | |
73 } | |
457 | 74 |
5275 | 75 octave_idx_type n = a_nc; |
76 octave_idx_type info; | |
1944 | 77 |
78 chol_mat = a; | |
79 Complex *h = chol_mat.fortran_vec (); | |
457 | 80 |
6486 | 81 // Calculate the norm of the matrix, for later use. |
82 double anorm = 0; | |
83 if (calc_cond) | |
84 anorm = chol_mat.abs().sum().row(static_cast<octave_idx_type>(0)).max(); | |
85 | |
4552 | 86 F77_XFCN (zpotrf, ZPOTRF, (F77_CONST_CHAR_ARG2 ("U", 1), n, h, n, info |
87 F77_CHAR_ARG_LEN (1))); | |
457 | 88 |
7482
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7017
diff
changeset
|
89 xrcond = 0.0; |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7017
diff
changeset
|
90 if (info != 0) |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7017
diff
changeset
|
91 info = -1; |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7017
diff
changeset
|
92 else if (calc_cond) |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7017
diff
changeset
|
93 { |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7017
diff
changeset
|
94 octave_idx_type zpocon_info = 0; |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7017
diff
changeset
|
95 |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7017
diff
changeset
|
96 // Now calculate the condition number for non-singular matrix. |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7017
diff
changeset
|
97 Array<Complex> z (2*n); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7017
diff
changeset
|
98 Complex *pz = z.fortran_vec (); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7017
diff
changeset
|
99 Array<double> rz (n); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7017
diff
changeset
|
100 double *prz = rz.fortran_vec (); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7017
diff
changeset
|
101 F77_XFCN (zpocon, ZPOCON, (F77_CONST_CHAR_ARG2 ("U", 1), n, h, |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7017
diff
changeset
|
102 n, anorm, xrcond, pz, prz, zpocon_info |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7017
diff
changeset
|
103 F77_CHAR_ARG_LEN (1))); |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7017
diff
changeset
|
104 |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7017
diff
changeset
|
105 if (zpocon_info != 0) |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7017
diff
changeset
|
106 info = -1; |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7017
diff
changeset
|
107 } |
1944 | 108 else |
109 { | |
7482
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7017
diff
changeset
|
110 // If someone thinks of a more graceful way of doing this (or |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7017
diff
changeset
|
111 // faster for that matter :-)), please let me know! |
457 | 112 |
7482
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7017
diff
changeset
|
113 if (n > 1) |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7017
diff
changeset
|
114 for (octave_idx_type j = 0; j < a_nc; j++) |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7017
diff
changeset
|
115 for (octave_idx_type i = j+1; i < a_nr; i++) |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7017
diff
changeset
|
116 chol_mat.xelem (i, j) = 0.0; |
1944 | 117 } |
118 | |
119 return info; | |
457 | 120 } |
121 | |
5340 | 122 static ComplexMatrix |
123 chol2inv_internal (const ComplexMatrix& r) | |
124 { | |
125 ComplexMatrix retval; | |
126 | |
127 octave_idx_type r_nr = r.rows (); | |
128 octave_idx_type r_nc = r.cols (); | |
129 | |
130 if (r_nr == r_nc) | |
131 { | |
132 octave_idx_type n = r_nc; | |
133 octave_idx_type info; | |
134 | |
135 ComplexMatrix tmp = r; | |
136 | |
137 F77_XFCN (zpotri, ZPOTRI, (F77_CONST_CHAR_ARG2 ("U", 1), n, | |
138 tmp.fortran_vec (), n, info | |
139 F77_CHAR_ARG_LEN (1))); | |
140 | |
7482
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7017
diff
changeset
|
141 // If someone thinks of a more graceful way of doing this (or |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7017
diff
changeset
|
142 // faster for that matter :-)), please let me know! |
5340 | 143 |
7482
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7017
diff
changeset
|
144 if (n > 1) |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7017
diff
changeset
|
145 for (octave_idx_type j = 0; j < r_nc; j++) |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7017
diff
changeset
|
146 for (octave_idx_type i = j+1; i < r_nr; i++) |
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7017
diff
changeset
|
147 tmp.xelem (i, j) = std::conj (tmp.xelem (j, i)); |
5340 | 148 |
7482
29980c6b8604
don't check f77_exception_encountered
John W. Eaton <jwe@octave.org>
parents:
7017
diff
changeset
|
149 retval = tmp; |
5340 | 150 } |
151 else | |
152 (*current_liboctave_error_handler) ("chol2inv requires square matrix"); | |
153 | |
154 return retval; | |
155 } | |
156 | |
157 // Compute the inverse of a matrix using the Cholesky factorization. | |
158 ComplexMatrix | |
159 ComplexCHOL::inverse (void) const | |
160 { | |
161 return chol2inv_internal (chol_mat); | |
162 } | |
163 | |
7554
40574114c514
implement Cholesky factorization updating
Jaroslav Hajek <highegg@gmail.com>
parents:
7482
diff
changeset
|
164 void |
40574114c514
implement Cholesky factorization updating
Jaroslav Hajek <highegg@gmail.com>
parents:
7482
diff
changeset
|
165 ComplexCHOL::set (const ComplexMatrix& R) |
40574114c514
implement Cholesky factorization updating
Jaroslav Hajek <highegg@gmail.com>
parents:
7482
diff
changeset
|
166 { |
40574114c514
implement Cholesky factorization updating
Jaroslav Hajek <highegg@gmail.com>
parents:
7482
diff
changeset
|
167 if (R.is_square ()) |
40574114c514
implement Cholesky factorization updating
Jaroslav Hajek <highegg@gmail.com>
parents:
7482
diff
changeset
|
168 chol_mat = R; |
40574114c514
implement Cholesky factorization updating
Jaroslav Hajek <highegg@gmail.com>
parents:
7482
diff
changeset
|
169 else |
40574114c514
implement Cholesky factorization updating
Jaroslav Hajek <highegg@gmail.com>
parents:
7482
diff
changeset
|
170 (*current_liboctave_error_handler) ("chol2inv requires square matrix"); |
40574114c514
implement Cholesky factorization updating
Jaroslav Hajek <highegg@gmail.com>
parents:
7482
diff
changeset
|
171 } |
40574114c514
implement Cholesky factorization updating
Jaroslav Hajek <highegg@gmail.com>
parents:
7482
diff
changeset
|
172 |
40574114c514
implement Cholesky factorization updating
Jaroslav Hajek <highegg@gmail.com>
parents:
7482
diff
changeset
|
173 void |
40574114c514
implement Cholesky factorization updating
Jaroslav Hajek <highegg@gmail.com>
parents:
7482
diff
changeset
|
174 ComplexCHOL::update (const ComplexMatrix& u) |
40574114c514
implement Cholesky factorization updating
Jaroslav Hajek <highegg@gmail.com>
parents:
7482
diff
changeset
|
175 { |
40574114c514
implement Cholesky factorization updating
Jaroslav Hajek <highegg@gmail.com>
parents:
7482
diff
changeset
|
176 octave_idx_type n = chol_mat.rows (); |
40574114c514
implement Cholesky factorization updating
Jaroslav Hajek <highegg@gmail.com>
parents:
7482
diff
changeset
|
177 |
40574114c514
implement Cholesky factorization updating
Jaroslav Hajek <highegg@gmail.com>
parents:
7482
diff
changeset
|
178 if (u.length () == n) |
40574114c514
implement Cholesky factorization updating
Jaroslav Hajek <highegg@gmail.com>
parents:
7482
diff
changeset
|
179 { |
40574114c514
implement Cholesky factorization updating
Jaroslav Hajek <highegg@gmail.com>
parents:
7482
diff
changeset
|
180 ComplexMatrix tmp = u; |
40574114c514
implement Cholesky factorization updating
Jaroslav Hajek <highegg@gmail.com>
parents:
7482
diff
changeset
|
181 |
40574114c514
implement Cholesky factorization updating
Jaroslav Hajek <highegg@gmail.com>
parents:
7482
diff
changeset
|
182 OCTAVE_LOCAL_BUFFER (double, w, n); |
40574114c514
implement Cholesky factorization updating
Jaroslav Hajek <highegg@gmail.com>
parents:
7482
diff
changeset
|
183 |
40574114c514
implement Cholesky factorization updating
Jaroslav Hajek <highegg@gmail.com>
parents:
7482
diff
changeset
|
184 F77_XFCN (zch1up, ZCH1UP, (n, chol_mat.fortran_vec (), |
40574114c514
implement Cholesky factorization updating
Jaroslav Hajek <highegg@gmail.com>
parents:
7482
diff
changeset
|
185 tmp.fortran_vec (), w)); |
40574114c514
implement Cholesky factorization updating
Jaroslav Hajek <highegg@gmail.com>
parents:
7482
diff
changeset
|
186 } |
40574114c514
implement Cholesky factorization updating
Jaroslav Hajek <highegg@gmail.com>
parents:
7482
diff
changeset
|
187 else |
40574114c514
implement Cholesky factorization updating
Jaroslav Hajek <highegg@gmail.com>
parents:
7482
diff
changeset
|
188 (*current_liboctave_error_handler) ("CHOL update dimension mismatch"); |
40574114c514
implement Cholesky factorization updating
Jaroslav Hajek <highegg@gmail.com>
parents:
7482
diff
changeset
|
189 } |
40574114c514
implement Cholesky factorization updating
Jaroslav Hajek <highegg@gmail.com>
parents:
7482
diff
changeset
|
190 |
40574114c514
implement Cholesky factorization updating
Jaroslav Hajek <highegg@gmail.com>
parents:
7482
diff
changeset
|
191 octave_idx_type |
40574114c514
implement Cholesky factorization updating
Jaroslav Hajek <highegg@gmail.com>
parents:
7482
diff
changeset
|
192 ComplexCHOL::downdate (const ComplexMatrix& u) |
40574114c514
implement Cholesky factorization updating
Jaroslav Hajek <highegg@gmail.com>
parents:
7482
diff
changeset
|
193 { |
40574114c514
implement Cholesky factorization updating
Jaroslav Hajek <highegg@gmail.com>
parents:
7482
diff
changeset
|
194 octave_idx_type info = -1; |
40574114c514
implement Cholesky factorization updating
Jaroslav Hajek <highegg@gmail.com>
parents:
7482
diff
changeset
|
195 |
40574114c514
implement Cholesky factorization updating
Jaroslav Hajek <highegg@gmail.com>
parents:
7482
diff
changeset
|
196 octave_idx_type n = chol_mat.rows (); |
40574114c514
implement Cholesky factorization updating
Jaroslav Hajek <highegg@gmail.com>
parents:
7482
diff
changeset
|
197 |
40574114c514
implement Cholesky factorization updating
Jaroslav Hajek <highegg@gmail.com>
parents:
7482
diff
changeset
|
198 if (u.length () == n) |
40574114c514
implement Cholesky factorization updating
Jaroslav Hajek <highegg@gmail.com>
parents:
7482
diff
changeset
|
199 { |
40574114c514
implement Cholesky factorization updating
Jaroslav Hajek <highegg@gmail.com>
parents:
7482
diff
changeset
|
200 ComplexMatrix tmp = u; |
40574114c514
implement Cholesky factorization updating
Jaroslav Hajek <highegg@gmail.com>
parents:
7482
diff
changeset
|
201 |
40574114c514
implement Cholesky factorization updating
Jaroslav Hajek <highegg@gmail.com>
parents:
7482
diff
changeset
|
202 OCTAVE_LOCAL_BUFFER (double, w, n); |
40574114c514
implement Cholesky factorization updating
Jaroslav Hajek <highegg@gmail.com>
parents:
7482
diff
changeset
|
203 |
40574114c514
implement Cholesky factorization updating
Jaroslav Hajek <highegg@gmail.com>
parents:
7482
diff
changeset
|
204 F77_XFCN (zch1dn, ZCH1DN, (n, chol_mat.fortran_vec (), |
40574114c514
implement Cholesky factorization updating
Jaroslav Hajek <highegg@gmail.com>
parents:
7482
diff
changeset
|
205 tmp.fortran_vec (), w, info)); |
40574114c514
implement Cholesky factorization updating
Jaroslav Hajek <highegg@gmail.com>
parents:
7482
diff
changeset
|
206 } |
40574114c514
implement Cholesky factorization updating
Jaroslav Hajek <highegg@gmail.com>
parents:
7482
diff
changeset
|
207 else |
40574114c514
implement Cholesky factorization updating
Jaroslav Hajek <highegg@gmail.com>
parents:
7482
diff
changeset
|
208 (*current_liboctave_error_handler) ("CHOL update dimension mismatch"); |
40574114c514
implement Cholesky factorization updating
Jaroslav Hajek <highegg@gmail.com>
parents:
7482
diff
changeset
|
209 |
40574114c514
implement Cholesky factorization updating
Jaroslav Hajek <highegg@gmail.com>
parents:
7482
diff
changeset
|
210 return info; |
40574114c514
implement Cholesky factorization updating
Jaroslav Hajek <highegg@gmail.com>
parents:
7482
diff
changeset
|
211 } |
40574114c514
implement Cholesky factorization updating
Jaroslav Hajek <highegg@gmail.com>
parents:
7482
diff
changeset
|
212 |
5340 | 213 ComplexMatrix |
214 chol2inv (const ComplexMatrix& r) | |
215 { | |
216 return chol2inv_internal (r); | |
217 } | |
218 | |
457 | 219 /* |
220 ;;; Local Variables: *** | |
221 ;;; mode: C++ *** | |
222 ;;; End: *** | |
223 */ |