comparison liboctave/dbleQR.cc @ 8547:d66c9b6e506a

imported patch qrupdate.diff
author Jaroslav Hajek <highegg@gmail.com>
date Tue, 20 Jan 2009 21:16:42 +0100
parents 445d27d79f4e
children a6edd5c23cb5
comparison
equal deleted inserted replaced
8546:3d8a914c580e 8547:d66c9b6e506a
1 /* 1 /*
2 2
3 Copyright (C) 1994, 1995, 1996, 1997, 2002, 2003, 2004, 2005, 2007 3 Copyright (C) 1994, 1995, 1996, 1997, 2002, 2003, 2004, 2005, 2007
4 John W. Eaton 4 John W. Eaton
5 Copyright (C) 2008 Jaroslav Hajek 5 Copyright (C) 2008, 2009 Jaroslav Hajek
6 6
7 This file is part of Octave. 7 This file is part of Octave.
8 8
9 Octave is free software; you can redistribute it and/or modify it 9 Octave is free software; you can redistribute it and/or modify it
10 under the terms of the GNU General Public License as published by the 10 under the terms of the GNU General Public License as published by the
29 #include "dbleQR.h" 29 #include "dbleQR.h"
30 #include "f77-fcn.h" 30 #include "f77-fcn.h"
31 #include "lo-error.h" 31 #include "lo-error.h"
32 #include "Range.h" 32 #include "Range.h"
33 #include "idx-vector.h" 33 #include "idx-vector.h"
34 #include "oct-locbuf.h"
34 35
35 extern "C" 36 extern "C"
36 { 37 {
37 F77_RET_T 38 F77_RET_T
38 F77_FUNC (dgeqrf, DGEQRF) (const octave_idx_type&, const octave_idx_type&, double*, const octave_idx_type&, 39 F77_FUNC (dgeqrf, DGEQRF) (const octave_idx_type&, const octave_idx_type&, double*, const octave_idx_type&,
40 41
41 F77_RET_T 42 F77_RET_T
42 F77_FUNC (dorgqr, DORGQR) (const octave_idx_type&, const octave_idx_type&, const octave_idx_type&, double*, 43 F77_FUNC (dorgqr, DORGQR) (const octave_idx_type&, const octave_idx_type&, const octave_idx_type&, double*,
43 const octave_idx_type&, double*, double*, const octave_idx_type&, octave_idx_type&); 44 const octave_idx_type&, double*, double*, const octave_idx_type&, octave_idx_type&);
44 45
45 // these come from qrupdate 46 #ifdef HAVE_QRUPDATE
46 47
47 F77_RET_T 48 F77_RET_T
48 F77_FUNC (dqr1up, DQR1UP) (const octave_idx_type&, const octave_idx_type&, const octave_idx_type&, 49 F77_FUNC (dqr1up, DQR1UP) (const octave_idx_type&, const octave_idx_type&, const octave_idx_type&,
49 double*, double*, const double*, const double*); 50 double*, const octave_idx_type&, double*, const octave_idx_type&,
51 double*, double*, double*);
50 52
51 F77_RET_T 53 F77_RET_T
52 F77_FUNC (dqrinc, DQRINC) (const octave_idx_type&, const octave_idx_type&, const octave_idx_type&, 54 F77_FUNC (dqrinc, DQRINC) (const octave_idx_type&, const octave_idx_type&, const octave_idx_type&,
53 double*, const double*, double*, const octave_idx_type&, const double*); 55 double*, const octave_idx_type&, double*, const octave_idx_type&,
56 const octave_idx_type&, const double*, double*);
54 57
55 F77_RET_T 58 F77_RET_T
56 F77_FUNC (dqrdec, DQRDEC) (const octave_idx_type&, const octave_idx_type&, const octave_idx_type&, 59 F77_FUNC (dqrdec, DQRDEC) (const octave_idx_type&, const octave_idx_type&, const octave_idx_type&,
57 double*, const double*, double*, const octave_idx_type&); 60 double*, const octave_idx_type&, double*, const octave_idx_type&,
61 const octave_idx_type&, double*);
58 62
59 F77_RET_T 63 F77_RET_T
60 F77_FUNC (dqrinr, DQRINR) (const octave_idx_type&, const octave_idx_type&, 64 F77_FUNC (dqrinr, DQRINR) (const octave_idx_type&, const octave_idx_type&,
61 const double*, double*, const double*, double*, 65 double*, const octave_idx_type&, double*, const octave_idx_type&,
62 const octave_idx_type&, const double*); 66 const octave_idx_type&, const double*, double*);
63 67
64 F77_RET_T 68 F77_RET_T
65 F77_FUNC (dqrder, DQRDER) (const octave_idx_type&, const octave_idx_type&, 69 F77_FUNC (dqrder, DQRDER) (const octave_idx_type&, const octave_idx_type&,
66 const double*, double*, const double*, double *, 70 double*, const octave_idx_type&, double*, const octave_idx_type&,
67 const octave_idx_type&); 71 const octave_idx_type&, double*);
68 72
69 F77_RET_T 73 F77_RET_T
70 F77_FUNC (dqrshc, DQRSHC) (const octave_idx_type&, const octave_idx_type&, const octave_idx_type&, 74 F77_FUNC (dqrshc, DQRSHC) (const octave_idx_type&, const octave_idx_type&, const octave_idx_type&,
71 double*, double*, const octave_idx_type&, const octave_idx_type&); 75 double*, const octave_idx_type&, double*, const octave_idx_type&,
76 const octave_idx_type&, const octave_idx_type&,
77 double*);
78
79 #endif
72 } 80 }
73 81
74 QR::QR (const Matrix& a, QR::type qr_type) 82 QR::QR (const Matrix& a, QR::type qr_type)
75 : q (), r () 83 : q (), r ()
76 { 84 {
159 167
160 this->q = q_arg; 168 this->q = q_arg;
161 this->r = r_arg; 169 this->r = r_arg;
162 } 170 }
163 171
172 #ifdef HAVE_QRUPDATE
173
174 void
175 QR::update (const ColumnVector& u, const ColumnVector& v)
176 {
177 octave_idx_type m = q.rows ();
178 octave_idx_type n = r.columns ();
179 octave_idx_type k = q.columns ();
180
181 if (u.length () == m && v.length () == n)
182 {
183 ColumnVector utmp = u, vtmp = v;
184 OCTAVE_LOCAL_BUFFER (double, w, 2*k);
185 F77_XFCN (dqr1up, DQR1UP, (m, n, k, q.fortran_vec (), m, r.fortran_vec (), k,
186 utmp.fortran_vec (), vtmp.fortran_vec (), w));
187 }
188 else
189 (*current_liboctave_error_handler) ("QR update dimensions mismatch");
190 }
191
164 void 192 void
165 QR::update (const Matrix& u, const Matrix& v) 193 QR::update (const Matrix& u, const Matrix& v)
166 { 194 {
167 octave_idx_type m = q.rows (); 195 octave_idx_type m = q.rows ();
168 octave_idx_type n = r.columns (); 196 octave_idx_type n = r.columns ();
169 octave_idx_type k = q.columns (); 197 octave_idx_type k = q.columns ();
170 198
171 if (u.length () == m && v.length () == n) 199 if (u.rows () == m && v.rows () == n && u.cols () == v.cols ())
172 F77_XFCN (dqr1up, DQR1UP, (m, n, k, q.fortran_vec (), r.fortran_vec (), 200 {
173 u.data (), v.data ())); 201 OCTAVE_LOCAL_BUFFER (double, w, 2*k);
174 else 202 for (octave_idx_type i = 0; i < u.cols (); i++)
175 (*current_liboctave_error_handler) ("QR update dimensions mismatch"); 203 {
176 } 204 ColumnVector utmp = u.column (i), vtmp = v.column (i);
177 205 F77_XFCN (dqr1up, DQR1UP, (m, n, k, q.fortran_vec (), m, r.fortran_vec (), k,
178 void 206 utmp.fortran_vec (), vtmp.fortran_vec (), w));
179 QR::insert_col (const Matrix& u, octave_idx_type j) 207 }
208 }
209 else
210 (*current_liboctave_error_handler) ("qrupdate: dimensions mismatch");
211 }
212
213 void
214 QR::insert_col (const ColumnVector& u, octave_idx_type j)
180 { 215 {
181 octave_idx_type m = q.rows (); 216 octave_idx_type m = q.rows ();
182 octave_idx_type n = r.columns (); 217 octave_idx_type n = r.columns ();
183 octave_idx_type k = q.columns (); 218 octave_idx_type k = q.columns ();
184 219
185 if (u.length () != m) 220 if (u.length () != m)
186 (*current_liboctave_error_handler) ("QR insert dimensions mismatch"); 221 (*current_liboctave_error_handler) ("qrinsert: dimensions mismatch");
187 else if (j < 0 || j > n) 222 else if (j < 0 || j > n)
188 (*current_liboctave_error_handler) ("QR insert index out of range"); 223 (*current_liboctave_error_handler) ("qrinsert: index out of range");
189 else 224 else
190 { 225 {
191 Matrix r1 (m, n+1); 226 if (k < m)
192 227 {
193 F77_XFCN (dqrinc, DQRINC, (m, n, k, q.fortran_vec (), r.data (), 228 q.resize (m, k+1);
194 r1.fortran_vec (), j+1, u.data ())); 229 r.resize (k+1, n+1);
195 230 }
196 r = r1; 231 else
232 {
233 r.resize (k, n+1);
234 }
235
236 ColumnVector utmp = u;
237 OCTAVE_LOCAL_BUFFER (double, w, k);
238 F77_XFCN (dqrinc, DQRINC, (m, n, k, q.fortran_vec (), q.rows (),
239 r.fortran_vec (), r.rows (), j + 1,
240 utmp.data (), w));
241 }
242 }
243
244 void
245 QR::insert_col (const Matrix& u, const Array<octave_idx_type>& j)
246 {
247 octave_idx_type m = q.rows ();
248 octave_idx_type n = r.columns ();
249 octave_idx_type k = q.columns ();
250
251 Array<octave_idx_type> jsi;
252 Array<octave_idx_type> js = j.sort (jsi, ASCENDING);
253 octave_idx_type nj = js.length ();
254 bool dups = false;
255 for (octave_idx_type i = 0; i < nj - 1; i++)
256 dups = dups && js(i) == js(i+1);
257
258 if (dups)
259 (*current_liboctave_error_handler) ("qrinsert: duplicate index detected");
260 else if (u.length () != m || u.columns () != nj)
261 (*current_liboctave_error_handler) ("qrinsert: dimensions mismatch");
262 else if (nj > 0 && (js(0) < 0 || js(nj-1) > n))
263 (*current_liboctave_error_handler) ("qrinsert: index out of range");
264 else if (nj > 0)
265 {
266 octave_idx_type kmax = std::min (k + nj, m);
267 if (k < m)
268 {
269 q.resize (m, kmax);
270 r.resize (kmax, n + nj);
271 }
272 else
273 {
274 r.resize (k, n + nj);
275 }
276
277 OCTAVE_LOCAL_BUFFER (double, w, kmax);
278 for (octave_idx_type i = 0; i < js.length (); i++)
279 {
280 ColumnVector utmp = u.column (jsi(i));
281 F77_XFCN (dqrinc, DQRINC, (m, n + i, std::min (kmax, k + i),
282 q.fortran_vec (), q.rows (),
283 r.fortran_vec (), r.rows (), js(i) + 1,
284 utmp.data (), w));
285 }
197 } 286 }
198 } 287 }
199 288
200 void 289 void
201 QR::delete_col (octave_idx_type j) 290 QR::delete_col (octave_idx_type j)
202 { 291 {
203 octave_idx_type m = q.rows (); 292 octave_idx_type m = q.rows ();
204 octave_idx_type k = r.rows (); 293 octave_idx_type k = r.rows ();
205 octave_idx_type n = r.columns (); 294 octave_idx_type n = r.columns ();
206 295
207 if (k < m && k < n) 296 if (j < 0 || j > n-1)
208 (*current_liboctave_error_handler) ("QR delete dimensions mismatch"); 297 (*current_liboctave_error_handler) ("qrdelete: index out of range");
209 else if (j < 0 || j > n-1) 298 else
210 (*current_liboctave_error_handler) ("QR delete index out of range"); 299 {
211 else 300 OCTAVE_LOCAL_BUFFER (double, w, k);
212 { 301 F77_XFCN (dqrdec, DQRDEC, (m, n, k, q.fortran_vec (), q.rows (),
213 Matrix r1 (k, n-1); 302 r.fortran_vec (), r.rows (), j + 1, w));
214 303
215 F77_XFCN (dqrdec, DQRDEC, (m, n, k, q.fortran_vec (), r.data (), 304 if (k < m)
216 r1.fortran_vec (), j+1)); 305 {
217 306 q.resize (m, k-1);
218 r = r1; 307 r.resize (k-1, n-1);
219 } 308 }
220 } 309 else
221 310 {
222 void 311 r.resize (k, n-1);
223 QR::insert_row (const Matrix& u, octave_idx_type j) 312 }
313 }
314 }
315
316 void
317 QR::delete_col (const Array<octave_idx_type>& j)
318 {
319 octave_idx_type m = q.rows ();
320 octave_idx_type n = r.columns ();
321 octave_idx_type k = q.columns ();
322
323 Array<octave_idx_type> jsi;
324 Array<octave_idx_type> js = j.sort (jsi, DESCENDING);
325 octave_idx_type nj = js.length ();
326 bool dups = false;
327 for (octave_idx_type i = 0; i < nj - 1; i++)
328 dups = dups && js(i) == js(i+1);
329
330 if (dups)
331 (*current_liboctave_error_handler) ("qrinsert: duplicate index detected");
332 else if (nj > 0 && (js(0) > n-1 || js(nj-1) < 0))
333 (*current_liboctave_error_handler) ("qrinsert: index out of range");
334 else if (nj > 0)
335 {
336 OCTAVE_LOCAL_BUFFER (double, w, k);
337 for (octave_idx_type i = 0; i < js.length (); i++)
338 {
339 F77_XFCN (dqrdec, DQRDEC, (m, n - i, k == m ? k : k - i,
340 q.fortran_vec (), q.rows (),
341 r.fortran_vec (), r.rows (), js(i) + 1, w));
342 }
343 if (k < m)
344 {
345 q.resize (m, k - nj);
346 r.resize (k - nj, n - nj);
347 }
348 else
349 {
350 r.resize (k, n - nj);
351 }
352
353 }
354 }
355
356 void
357 QR::insert_row (const RowVector& u, octave_idx_type j)
224 { 358 {
225 octave_idx_type m = r.rows (); 359 octave_idx_type m = r.rows ();
226 octave_idx_type n = r.columns (); 360 octave_idx_type n = r.columns ();
361 octave_idx_type k = std::min (m, n);
227 362
228 if (! q.is_square () || u.length () != n) 363 if (! q.is_square () || u.length () != n)
229 (*current_liboctave_error_handler) ("QR insert dimensions mismatch"); 364 (*current_liboctave_error_handler) ("qrinsert: dimensions mismatch");
230 else if (j < 0 || j > m) 365 else if (j < 0 || j > m)
231 (*current_liboctave_error_handler) ("QR insert index out of range"); 366 (*current_liboctave_error_handler) ("qrinsert: index out of range");
232 else 367 else
233 { 368 {
234 Matrix q1 (m+1, m+1); 369 q.resize (m + 1, m + 1);
235 Matrix r1 (m+1, n); 370 r.resize (m + 1, n);
236 371 RowVector utmp = u;
237 F77_XFCN (dqrinr, DQRINR, (m, n, q.data (), q1.fortran_vec (), 372 OCTAVE_LOCAL_BUFFER (double, w, k);
238 r.data (), r1.fortran_vec (), j+1, u.data ())); 373 F77_XFCN (dqrinr, DQRINR, (m, n, q.fortran_vec (), q.rows (),
239 374 r.fortran_vec (), r.rows (),
240 q = q1; 375 j + 1, utmp.fortran_vec (), w));
241 r = r1; 376
242 } 377 }
243 } 378 }
244 379
245 void 380 void
246 QR::delete_row (octave_idx_type j) 381 QR::delete_row (octave_idx_type j)
247 { 382 {
248 octave_idx_type m = r.rows (); 383 octave_idx_type m = r.rows ();
249 octave_idx_type n = r.columns (); 384 octave_idx_type n = r.columns ();
250 385
251 if (! q.is_square ()) 386 if (! q.is_square ())
252 (*current_liboctave_error_handler) ("QR delete dimensions mismatch"); 387 (*current_liboctave_error_handler) ("qrdelete: dimensions mismatch");
253 else if (j < 0 || j > m-1) 388 else if (j < 0 || j > m-1)
254 (*current_liboctave_error_handler) ("QR delete index out of range"); 389 (*current_liboctave_error_handler) ("qrdelete: index out of range");
255 else 390 else
256 { 391 {
257 Matrix q1 (m-1, m-1); 392 OCTAVE_LOCAL_BUFFER (double, w, 2*m);
258 Matrix r1 (m-1, n); 393 F77_XFCN (dqrder, DQRDER, (m, n, q.fortran_vec (), q.rows (),
259 394 r.fortran_vec (), r.rows (), j + 1,
260 F77_XFCN (dqrder, DQRDER, (m, n, q.data (), q1.fortran_vec (), 395 w));
261 r.data (), r1.fortran_vec (), j+1 )); 396
262 397 q.resize (m - 1, m - 1);
263 q = q1; 398 r.resize (m - 1, n);
264 r = r1;
265 } 399 }
266 } 400 }
267 401
268 void 402 void
269 QR::shift_cols (octave_idx_type i, octave_idx_type j) 403 QR::shift_cols (octave_idx_type i, octave_idx_type j)
271 octave_idx_type m = q.rows (); 405 octave_idx_type m = q.rows ();
272 octave_idx_type k = r.rows (); 406 octave_idx_type k = r.rows ();
273 octave_idx_type n = r.columns (); 407 octave_idx_type n = r.columns ();
274 408
275 if (i < 0 || i > n-1 || j < 0 || j > n-1) 409 if (i < 0 || i > n-1 || j < 0 || j > n-1)
276 (*current_liboctave_error_handler) ("QR shift index out of range"); 410 (*current_liboctave_error_handler) ("qrshift: index out of range");
277 else 411 else
278 F77_XFCN (dqrshc, DQRSHC, (m, n, k, q.fortran_vec (), r.fortran_vec (), i+1, j+1)); 412 {
279 } 413 OCTAVE_LOCAL_BUFFER (double, w, 2*k);
280 414 F77_XFCN (dqrshc, DQRSHC, (m, n, k,
281 void 415 q.fortran_vec (), q.rows (),
282 QR::economize (void) 416 r.fortran_vec (), r.rows (),
283 { 417 i + 1, j + 1, w));
284 octave_idx_type r_nc = r.columns (); 418 }
285 419 }
286 if (r.rows () > r_nc) 420
287 { 421 #endif
288 q.resize (q.rows (), r_nc);
289 r.resize (r_nc, r_nc);
290 }
291 }
292
293 422
294 /* 423 /*
295 ;;; Local Variables: *** 424 ;;; Local Variables: ***
296 ;;; mode: C++ *** 425 ;;; mode: C++ ***
297 ;;; End: *** 426 ;;; End: ***