GNU Octave  6.2.0
A high-level interpreted language, primarily intended for numerical computations, mostly compatible with Matlab
qr.cc
Go to the documentation of this file.
1 ////////////////////////////////////////////////////////////////////////
2 //
3 // Copyright (C) 1994-2021 The Octave Project Developers
4 //
5 // See the file COPYRIGHT.md in the top-level directory of this
6 // distribution or <https://octave.org/copyright/>.
7 //
8 // This file is part of Octave.
9 //
10 // Octave is free software: you can redistribute it and/or modify it
11 // under the terms of the GNU General Public License as published by
12 // the Free Software Foundation, either version 3 of the License, or
13 // (at your option) any later version.
14 //
15 // Octave is distributed in the hope that it will be useful, but
16 // WITHOUT ANY WARRANTY; without even the implied warranty of
17 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 // GNU General Public License for more details.
19 //
20 // You should have received a copy of the GNU General Public License
21 // along with Octave; see the file COPYING. If not, see
22 // <https://www.gnu.org/licenses/>.
23 //
24 ////////////////////////////////////////////////////////////////////////
25 
26 #if defined (HAVE_CONFIG_H)
27 # include "config.h"
28 #endif
29 
30 #include <algorithm>
31 
32 #include "Array.h"
33 #include "CColVector.h"
34 #include "CMatrix.h"
35 #include "CRowVector.h"
36 #include "dColVector.h"
37 #include "dMatrix.h"
38 #include "dRowVector.h"
39 #include "fCColVector.h"
40 #include "fCMatrix.h"
41 #include "fCRowVector.h"
42 #include "fColVector.h"
43 #include "fMatrix.h"
44 #include "fRowVector.h"
45 #include "lo-error.h"
46 #include "lo-lapack-proto.h"
47 #include "lo-qrupdate-proto.h"
48 #include "oct-cmplx.h"
49 #include "oct-locbuf.h"
50 #include "oct-sort.h"
51 #include "qr.h"
52 
53 namespace octave
54 {
55  namespace math
56  {
57  template <typename T>
58  qr<T>::qr (const T& q_arg, const T& r_arg)
59  : q (q_arg), r (r_arg)
60  {
61  octave_idx_type q_nr = q.rows ();
62  octave_idx_type q_nc = q.cols ();
63 
64  octave_idx_type r_nr = r.rows ();
65  octave_idx_type r_nc = r.cols ();
66 
67  if (! (q_nc == r_nr && (q_nr == q_nc || (q_nr > q_nc && r_nr == r_nc))))
68  (*current_liboctave_error_handler) ("QR dimensions mismatch");
69  }
70 
71  template <typename T>
72  typename qr<T>::type
73  qr<T>::get_type (void) const
74  {
75  type retval;
76 
77  if (! q.isempty () && q.issquare ())
79  else if (q.rows () > q.cols () && r.issquare ())
81  else
83 
84  return retval;
85  }
86 
87  template <typename T>
88  bool
89  qr<T>::regular (void) const
90  {
91  bool retval = true;
92 
93  octave_idx_type k = std::min (r.rows (), r.cols ());
94 
95  for (octave_idx_type i = 0; i < k; i++)
96  {
97  if (r(i, i) == ELT_T ())
98  {
99  retval = false;
100  break;
101  }
102  }
103 
104  return retval;
105  }
106 
107 #if ! defined (HAVE_QRUPDATE)
108 
109  // Replacement update methods.
110 
111  void
112  warn_qrupdate_once (void)
113  {
114  static bool warned = false;
115 
116  if (! warned)
117  {
118  (*current_liboctave_warning_with_id_handler)
119  ("Octave:missing-dependency",
120  "In this version of Octave, QR & Cholesky updating routines "
121  "simply update the matrix and recalculate factorizations. "
122  "To use fast algorithms, link Octave with the qrupdate library. "
123  "See <http://sourceforge.net/projects/qrupdate>.");
124 
125  warned = true;
126  }
127  }
128 
129  template <typename T>
130  void
131  qr<T>::update (const CV_T& u, const CV_T& v)
132  {
134 
135  octave_idx_type m = q.rows ();
136  octave_idx_type n = r.cols ();
137 
138  if (u.numel () != m || v.numel () != n)
139  (*current_liboctave_error_handler) ("qrupdate: dimensions mismatch");
140 
141  init (q*r + T (u) * T (v).hermitian (), get_type ());
142  }
143 
144  template <typename T>
145  void
146  qr<T>::update (const T& u, const T& v)
147  {
149 
150  octave_idx_type m = q.rows ();
151  octave_idx_type n = r.cols ();
152 
153  if (u.rows () != m || v.rows () != n || u.cols () != v.cols ())
154  (*current_liboctave_error_handler) ("qrupdate: dimensions mismatch");
155 
156  init (q*r + u * v.hermitian (), get_type ());
157  }
158 
159  template <typename T, typename CV_T>
160  static
161  T
162  insert_col (const T& a, octave_idx_type i, const CV_T& x)
163  {
164  T retval (a.rows (), a.cols () + 1);
166  a.index (idx_vector::colon, idx_vector (0, i)));
169  a.index (idx_vector::colon, idx_vector (i, a.cols ())));
170  return retval;
171  }
172 
173  template <typename T, typename RV_T>
174  static
175  T
176  insert_row (const T& a, octave_idx_type i, const RV_T& x)
177  {
178  T retval (a.rows () + 1, a.cols ());
180  a.index (idx_vector (0, i), idx_vector::colon));
183  a.index (idx_vector (i, a.rows ()), idx_vector::colon));
184  return retval;
185  }
186 
187  template <typename T>
188  static
189  T
190  delete_col (const T& a, octave_idx_type i)
191  {
192  T retval = a;
194  return retval;
195  }
196 
197  template <typename T>
198  static
199  T
200  delete_row (const T& a, octave_idx_type i)
201  {
202  T retval = a;
204  return retval;
205  }
206 
207  template <typename T>
208  static
209  T
210  shift_cols (const T& a, octave_idx_type i, octave_idx_type j)
211  {
212  octave_idx_type n = a.cols ();
214  for (octave_idx_type k = 0; k < n; k++) p(k) = k;
215  if (i < j)
216  {
217  for (octave_idx_type k = i; k < j; k++) p(k) = k+1;
218  p(j) = i;
219  }
220  else if (j < i)
221  {
222  p(j) = i;
223  for (octave_idx_type k = j+1; k < i+1; k++) p(k) = k-1;
224  }
225 
226  return a.index (idx_vector::colon, idx_vector (p));
227  }
228 
229  template <typename T>
230  void
231  qr<T>::insert_col (const CV_T& u, octave_idx_type j)
232  {
234 
235  octave_idx_type m = q.rows ();
236  octave_idx_type n = r.cols ();
237 
238  if (u.numel () != m)
239  (*current_liboctave_error_handler) ("qrinsert: dimensions mismatch");
240 
241  if (j < 0 || j > n)
242  (*current_liboctave_error_handler) ("qrinsert: index out of range");
243 
244  init (math::insert_col (q*r, j, u), get_type ());
245  }
246 
247  template <typename T>
248  void
249  qr<T>::insert_col (const T& u, const Array<octave_idx_type>& j)
250  {
252 
253  octave_idx_type m = q.rows ();
254  octave_idx_type n = r.cols ();
255 
257  Array<octave_idx_type> js = j.sort (jsi, 0, ASCENDING);
258  octave_idx_type nj = js.numel ();
259  bool dups = false;
260  for (octave_idx_type i = 0; i < nj - 1; i++)
261  dups = dups && js(i) == js(i+1);
262 
263  if (dups)
264  (*current_liboctave_error_handler) ("qrinsert: duplicate index detected");
265 
266  if (u.numel () != m || u.cols () != nj)
267  (*current_liboctave_error_handler) ("qrinsert: dimensions mismatch");
268 
269  if (nj > 0 && (js(0) < 0 || js(nj-1) > n))
270  (*current_liboctave_error_handler) ("qrinsert: index out of range");
271 
272  if (nj > 0)
273  {
274  T a = q*r;
275  for (octave_idx_type i = 0; i < nj; i++)
276  a = math::insert_col (a, js(i), u.column (i));
277 
278  init (a, get_type ());
279  }
280  }
281 
282  template <typename T>
283  void
285  {
287 
288  octave_idx_type n = r.cols ();
289 
290  if (j < 0 || j > n-1)
291  (*current_liboctave_error_handler) ("qrdelete: index out of range");
292 
293  init (math::delete_col (q*r, j), get_type ());
294  }
295 
296  template <typename T>
297  void
299  {
301 
302  octave_idx_type n = r.cols ();
303 
305  Array<octave_idx_type> js = j.sort (jsi, 0, DESCENDING);
306  octave_idx_type nj = js.numel ();
307  bool dups = false;
308  for (octave_idx_type i = 0; i < nj - 1; i++)
309  dups = dups && js(i) == js(i+1);
310 
311  if (dups)
312  (*current_liboctave_error_handler) ("qrinsert: duplicate index detected");
313 
314  if (nj > 0 && (js(0) > n-1 || js(nj-1) < 0))
315  (*current_liboctave_error_handler) ("qrinsert: index out of range");
316 
317  if (nj > 0)
318  {
319  T a = q*r;
320  for (octave_idx_type i = 0; i < nj; i++)
321  a = math::delete_col (a, js(i));
322 
323  init (a, get_type ());
324  }
325  }
326 
327  template <typename T>
328  void
329  qr<T>::insert_row (const RV_T& u, octave_idx_type j)
330  {
332 
333  octave_idx_type m = r.rows ();
334  octave_idx_type n = r.cols ();
335 
336  if (! q.issquare () || u.numel () != n)
337  (*current_liboctave_error_handler) ("qrinsert: dimensions mismatch");
338 
339  if (j < 0 || j > m)
340  (*current_liboctave_error_handler) ("qrinsert: index out of range");
341 
342  init (math::insert_row (q*r, j, u), get_type ());
343  }
344 
345  template <typename T>
346  void
348  {
350 
351  octave_idx_type m = r.rows ();
352 
353  if (! q.issquare ())
354  (*current_liboctave_error_handler) ("qrdelete: dimensions mismatch");
355 
356  if (j < 0 || j > m-1)
357  (*current_liboctave_error_handler) ("qrdelete: index out of range");
358 
359  init (math::delete_row (q*r, j), get_type ());
360  }
361 
362  template <typename T>
363  void
365  {
367 
368  octave_idx_type n = r.cols ();
369 
370  if (i < 0 || i > n-1 || j < 0 || j > n-1)
371  (*current_liboctave_error_handler) ("qrshift: index out of range");
372 
373  init (math::shift_cols (q*r, i, j), get_type ());
374  }
375 
376 #endif
377 
378  // Specializations.
379 
380  template <>
381  void
382  qr<Matrix>::form (octave_idx_type n_arg, Matrix& afact, double *tau,
383  type qr_type)
384  {
385  F77_INT n = to_f77_int (n_arg);
386  F77_INT m = to_f77_int (afact.rows ());
387  F77_INT min_mn = std::min (m, n);
388  F77_INT info;
389 
390  if (qr_type == qr<Matrix>::raw)
391  {
392  for (F77_INT j = 0; j < min_mn; j++)
393  {
394  F77_INT limit = (j < min_mn - 1 ? j : min_mn - 1);
395  for (F77_INT i = limit + 1; i < m; i++)
396  afact.elem (i, j) *= tau[j];
397  }
398 
399  r = afact;
400  }
401  else
402  {
403  // Attempt to minimize copying.
404  if (m >= n)
405  {
406  // afact will become q.
407  q = afact;
408  F77_INT k = (qr_type == qr<Matrix>::economy ? n : m);
409  r = Matrix (k, n);
410  for (F77_INT j = 0; j < n; j++)
411  {
412  F77_INT i = 0;
413  for (; i <= j; i++)
414  r.xelem (i, j) = afact.xelem (i, j);
415  for (; i < k; i++)
416  r.xelem (i, j) = 0;
417  }
418  afact = Matrix (); // optimize memory
419  }
420  else
421  {
422  // afact will become r.
423  q = Matrix (m, m);
424  for (F77_INT j = 0; j < m; j++)
425  for (F77_INT i = j + 1; i < m; i++)
426  {
427  q.xelem (i, j) = afact.xelem (i, j);
428  afact.xelem (i, j) = 0;
429  }
430  r = afact;
431  }
432 
433  if (m > 0)
434  {
435  F77_INT k = to_f77_int (q.cols ());
436  // workspace query.
437  double rlwork;
438  F77_XFCN (dorgqr, DORGQR, (m, k, min_mn, q.fortran_vec (), m,
439  tau, &rlwork, -1, info));
440 
441  // allocate buffer and do the job.
442  F77_INT lwork = static_cast<F77_INT> (rlwork);
443  lwork = std::max (lwork, static_cast<F77_INT> (1));
444  OCTAVE_LOCAL_BUFFER (double, work, lwork);
445  F77_XFCN (dorgqr, DORGQR, (m, k, min_mn, q.fortran_vec (), m,
446  tau, work, lwork, info));
447  }
448  }
449  }
450 
451  template <>
452  void
454  {
455  F77_INT m = to_f77_int (a.rows ());
456  F77_INT n = to_f77_int (a.cols ());
457 
458  F77_INT min_mn = (m < n ? m : n);
459  OCTAVE_LOCAL_BUFFER (double, tau, min_mn);
460 
461  F77_INT info = 0;
462 
463  Matrix afact = a;
464  if (m > n && qr_type == qr<Matrix>::std)
465  afact.resize (m, m);
466 
467  if (m > 0)
468  {
469  // workspace query.
470  double rlwork;
471  F77_XFCN (dgeqrf, DGEQRF, (m, n, afact.fortran_vec (), m, tau,
472  &rlwork, -1, info));
473 
474  // allocate buffer and do the job.
475  F77_INT lwork = static_cast<F77_INT> (rlwork);
476  lwork = std::max (lwork, static_cast<F77_INT> (1));
477  OCTAVE_LOCAL_BUFFER (double, work, lwork);
478  F77_XFCN (dgeqrf, DGEQRF, (m, n, afact.fortran_vec (), m, tau,
479  work, lwork, info));
480  }
481 
482  form (n, afact, tau, qr_type);
483  }
484 
485 #if defined (HAVE_QRUPDATE)
486 
487  template <>
488  void
490  {
491  F77_INT m = to_f77_int (q.rows ());
492  F77_INT n = to_f77_int (r.cols ());
493  F77_INT k = to_f77_int (q.cols ());
494 
495  F77_INT u_nel = to_f77_int (u.numel ());
496  F77_INT v_nel = to_f77_int (v.numel ());
497 
498  if (u_nel != m || v_nel != n)
499  (*current_liboctave_error_handler) ("qrupdate: dimensions mismatch");
500 
501  ColumnVector utmp = u;
502  ColumnVector vtmp = v;
503  OCTAVE_LOCAL_BUFFER (double, w, 2*k);
504  F77_XFCN (dqr1up, DQR1UP, (m, n, k, q.fortran_vec (), m,
505  r.fortran_vec (), k, utmp.fortran_vec (),
506  vtmp.fortran_vec (), w));
507  }
508 
509  template <>
510  void
511  qr<Matrix>::update (const Matrix& u, const Matrix& v)
512  {
513  F77_INT m = to_f77_int (q.rows ());
514  F77_INT n = to_f77_int (r.cols ());
515  F77_INT k = to_f77_int (q.cols ());
516 
517  F77_INT u_rows = to_f77_int (u.rows ());
518  F77_INT u_cols = to_f77_int (u.cols ());
519 
520  F77_INT v_rows = to_f77_int (v.rows ());
521  F77_INT v_cols = to_f77_int (v.cols ());
522 
523  if (u_rows != m || v_rows != n || u_cols != v_cols)
524  (*current_liboctave_error_handler) ("qrupdate: dimensions mismatch");
525 
526  OCTAVE_LOCAL_BUFFER (double, w, 2*k);
527  for (volatile F77_INT i = 0; i < u_cols; i++)
528  {
529  ColumnVector utmp = u.column (i);
530  ColumnVector vtmp = v.column (i);
531  F77_XFCN (dqr1up, DQR1UP, (m, n, k, q.fortran_vec (), m,
532  r.fortran_vec (), k, utmp.fortran_vec (),
533  vtmp.fortran_vec (), w));
534  }
535  }
536 
537  template <>
538  void
540  {
541  F77_INT j = to_f77_int (j_arg);
542 
543  F77_INT m = to_f77_int (q.rows ());
544  F77_INT n = to_f77_int (r.cols ());
545  F77_INT k = to_f77_int (q.cols ());
546 
547  F77_INT u_nel = to_f77_int (u.numel ());
548 
549  if (u_nel != m)
550  (*current_liboctave_error_handler) ("qrinsert: dimensions mismatch");
551 
552  if (j < 0 || j > n)
553  (*current_liboctave_error_handler) ("qrinsert: index out of range");
554 
555  if (k < m)
556  {
557  q.resize (m, k+1);
558  r.resize (k+1, n+1);
559  }
560  else
561  r.resize (k, n+1);
562 
563  F77_INT ldq = to_f77_int (q.rows ());
564  F77_INT ldr = to_f77_int (r.rows ());
565 
566  ColumnVector utmp = u;
567  OCTAVE_LOCAL_BUFFER (double, w, k);
568  F77_XFCN (dqrinc, DQRINC, (m, n, k, q.fortran_vec (), ldq,
569  r.fortran_vec (), ldr, j + 1,
570  utmp.data (), w));
571  }
572 
573  template <>
574  void
576  {
577  F77_INT m = to_f77_int (q.rows ());
578  F77_INT n = to_f77_int (r.cols ());
579  F77_INT k = to_f77_int (q.cols ());
580 
582  Array<octave_idx_type> js = j.sort (jsi, 0, ASCENDING);
583  F77_INT nj = to_f77_int (js.numel ());
584  bool dups = false;
585  for (F77_INT i = 0; i < nj - 1; i++)
586  dups = dups && js(i) == js(i+1);
587 
588  if (dups)
589  (*current_liboctave_error_handler) ("qrinsert: duplicate index detected");
590 
591  F77_INT u_nel = to_f77_int (u.numel ());
592  F77_INT u_cols = to_f77_int (u.cols ());
593 
594  if (u_nel != m || u_cols != nj)
595  (*current_liboctave_error_handler) ("qrinsert: dimensions mismatch");
596 
597  F77_INT js_beg = to_f77_int (js(0));
598  F77_INT js_end = to_f77_int (js(nj-1));
599 
600  if (nj > 0 && (js_beg < 0 || js_end > n))
601  (*current_liboctave_error_handler) ("qrinsert: index out of range");
602 
603  if (nj > 0)
604  {
605  F77_INT kmax = std::min (k + nj, m);
606  if (k < m)
607  {
608  q.resize (m, kmax);
609  r.resize (kmax, n + nj);
610  }
611  else
612  r.resize (k, n + nj);
613 
614  F77_INT ldq = to_f77_int (q.rows ());
615  F77_INT ldr = to_f77_int (r.rows ());
616 
617  OCTAVE_LOCAL_BUFFER (double, w, kmax);
618  for (volatile F77_INT i = 0; i < nj; i++)
619  {
620  F77_INT ii = i;
621  ColumnVector utmp = u.column (jsi(i));
622  F77_INT js_elt = to_f77_int (js(ii));
623  F77_XFCN (dqrinc, DQRINC, (m, n + ii, std::min (kmax, k + ii),
624  q.fortran_vec (), ldq,
625  r.fortran_vec (), ldr, js_elt + 1,
626  utmp.data (), w));
627  }
628  }
629  }
630 
631  template <>
632  void
634  {
635  F77_INT j = to_f77_int (j_arg);
636 
637  F77_INT m = to_f77_int (q.rows ());
638  F77_INT k = to_f77_int (r.rows ());
639  F77_INT n = to_f77_int (r.cols ());
640 
641  if (j < 0 || j > n-1)
642  (*current_liboctave_error_handler) ("qrdelete: index out of range");
643 
644  F77_INT ldq = to_f77_int (q.rows ());
645  F77_INT ldr = to_f77_int (r.rows ());
646 
647  OCTAVE_LOCAL_BUFFER (double, w, k);
648  F77_XFCN (dqrdec, DQRDEC, (m, n, k, q.fortran_vec (), ldq,
649  r.fortran_vec (), ldr, j + 1, w));
650 
651  if (k < m)
652  {
653  q.resize (m, k-1);
654  r.resize (k-1, n-1);
655  }
656  else
657  r.resize (k, n-1);
658  }
659 
660  template <>
661  void
663  {
664  F77_INT m = to_f77_int (q.rows ());
665  F77_INT n = to_f77_int (r.cols ());
666  F77_INT k = to_f77_int (q.cols ());
667 
669  Array<octave_idx_type> js = j.sort (jsi, 0, DESCENDING);
670  F77_INT nj = to_f77_int (js.numel ());
671  bool dups = false;
672  for (F77_INT i = 0; i < nj - 1; i++)
673  dups = dups && js(i) == js(i+1);
674 
675  if (dups)
676  (*current_liboctave_error_handler) ("qrinsert: duplicate index detected");
677 
678  F77_INT js_beg = to_f77_int (js(0));
679  F77_INT js_end = to_f77_int (js(nj-1));
680 
681  if (nj > 0 && (js_beg > n-1 || js_end < 0))
682  (*current_liboctave_error_handler) ("qrinsert: index out of range");
683 
684  if (nj > 0)
685  {
686  F77_INT ldq = to_f77_int (q.rows ());
687  F77_INT ldr = to_f77_int (r.rows ());
688 
689  OCTAVE_LOCAL_BUFFER (double, w, k);
690  for (volatile F77_INT i = 0; i < nj; i++)
691  {
692  F77_INT ii = i;
693  F77_INT js_elt = to_f77_int (js(ii));
694  F77_XFCN (dqrdec, DQRDEC, (m, n - ii, (k == m ? k : k - ii),
695  q.fortran_vec (), ldq,
696  r.fortran_vec (), ldr,
697  js_elt + 1, w));
698  }
699 
700  if (k < m)
701  {
702  q.resize (m, k - nj);
703  r.resize (k - nj, n - nj);
704  }
705  else
706  r.resize (k, n - nj);
707  }
708  }
709 
710  template <>
711  void
713  {
714  F77_INT j = to_f77_int (j_arg);
715 
716  F77_INT m = to_f77_int (r.rows ());
717  F77_INT n = to_f77_int (r.cols ());
718  F77_INT k = std::min (m, n);
719 
720  F77_INT u_nel = to_f77_int (u.numel ());
721 
722  if (! q.issquare () || u_nel != n)
723  (*current_liboctave_error_handler) ("qrinsert: dimensions mismatch");
724 
725  if (j < 0 || j > m)
726  (*current_liboctave_error_handler) ("qrinsert: index out of range");
727 
728  q.resize (m + 1, m + 1);
729  r.resize (m + 1, n);
730 
731  F77_INT ldq = to_f77_int (q.rows ());
732  F77_INT ldr = to_f77_int (r.rows ());
733 
734  RowVector utmp = u;
735  OCTAVE_LOCAL_BUFFER (double, w, k);
736  F77_XFCN (dqrinr, DQRINR, (m, n, q.fortran_vec (), ldq,
737  r.fortran_vec (), ldr,
738  j + 1, utmp.fortran_vec (), w));
739 
740  }
741 
742  template <>
743  void
745  {
746  F77_INT j = to_f77_int (j_arg);
747 
748  F77_INT m = to_f77_int (r.rows ());
749  F77_INT n = to_f77_int (r.cols ());
750 
751  if (! q.issquare ())
752  (*current_liboctave_error_handler) ("qrdelete: dimensions mismatch");
753 
754  if (j < 0 || j > m-1)
755  (*current_liboctave_error_handler) ("qrdelete: index out of range");
756 
757  F77_INT ldq = to_f77_int (q.rows ());
758  F77_INT ldr = to_f77_int (r.rows ());
759 
760  OCTAVE_LOCAL_BUFFER (double, w, 2*m);
761  F77_XFCN (dqrder, DQRDER, (m, n, q.fortran_vec (), ldq,
762  r.fortran_vec (), ldr, j + 1, w));
763 
764  q.resize (m - 1, m - 1);
765  r.resize (m - 1, n);
766  }
767 
768  template <>
769  void
771  {
772  F77_INT i = to_f77_int (i_arg);
773  F77_INT j = to_f77_int (j_arg);
774 
775  F77_INT m = to_f77_int (q.rows ());
776  F77_INT k = to_f77_int (r.rows ());
777  F77_INT n = to_f77_int (r.cols ());
778 
779  if (i < 0 || i > n-1 || j < 0 || j > n-1)
780  (*current_liboctave_error_handler) ("qrshift: index out of range");
781 
782  F77_INT ldq = to_f77_int (q.rows ());
783  F77_INT ldr = to_f77_int (r.rows ());
784 
785  OCTAVE_LOCAL_BUFFER (double, w, 2*k);
786  F77_XFCN (dqrshc, DQRSHC, (m, n, k,
787  q.fortran_vec (), ldq,
788  r.fortran_vec (), ldr,
789  i + 1, j + 1, w));
790  }
791 
792 #endif
793 
794  template <>
795  void
797  float *tau, type qr_type)
798  {
799  F77_INT n = to_f77_int (n_arg);
800  F77_INT m = to_f77_int (afact.rows ());
801  F77_INT min_mn = std::min (m, n);
802  F77_INT info;
803 
805  {
806  for (F77_INT j = 0; j < min_mn; j++)
807  {
808  F77_INT limit = (j < min_mn - 1 ? j : min_mn - 1);
809  for (F77_INT i = limit + 1; i < m; i++)
810  afact.elem (i, j) *= tau[j];
811  }
812 
813  r = afact;
814  }
815  else
816  {
817  // Attempt to minimize copying.
818  if (m >= n)
819  {
820  // afact will become q.
821  q = afact;
823  r = FloatMatrix (k, n);
824  for (F77_INT j = 0; j < n; j++)
825  {
826  F77_INT i = 0;
827  for (; i <= j; i++)
828  r.xelem (i, j) = afact.xelem (i, j);
829  for (; i < k; i++)
830  r.xelem (i, j) = 0;
831  }
832  afact = FloatMatrix (); // optimize memory
833  }
834  else
835  {
836  // afact will become r.
837  q = FloatMatrix (m, m);
838  for (F77_INT j = 0; j < m; j++)
839  for (F77_INT i = j + 1; i < m; i++)
840  {
841  q.xelem (i, j) = afact.xelem (i, j);
842  afact.xelem (i, j) = 0;
843  }
844  r = afact;
845  }
846 
847  if (m > 0)
848  {
849  F77_INT k = to_f77_int (q.cols ());
850  // workspace query.
851  float rlwork;
852  F77_XFCN (sorgqr, SORGQR, (m, k, min_mn, q.fortran_vec (), m,
853  tau, &rlwork, -1, info));
854 
855  // allocate buffer and do the job.
856  F77_INT lwork = static_cast<F77_INT> (rlwork);
857  lwork = std::max (lwork, static_cast<F77_INT> (1));
858  OCTAVE_LOCAL_BUFFER (float, work, lwork);
859  F77_XFCN (sorgqr, SORGQR, (m, k, min_mn, q.fortran_vec (), m,
860  tau, work, lwork, info));
861  }
862  }
863  }
864 
865  template <>
866  void
868  {
869  F77_INT m = to_f77_int (a.rows ());
870  F77_INT n = to_f77_int (a.cols ());
871 
872  F77_INT min_mn = (m < n ? m : n);
873  OCTAVE_LOCAL_BUFFER (float, tau, min_mn);
874 
875  F77_INT info = 0;
876 
877  FloatMatrix afact = a;
878  if (m > n && qr_type == qr<FloatMatrix>::std)
879  afact.resize (m, m);
880 
881  if (m > 0)
882  {
883  // workspace query.
884  float rlwork;
885  F77_XFCN (sgeqrf, SGEQRF, (m, n, afact.fortran_vec (), m, tau,
886  &rlwork, -1, info));
887 
888  // allocate buffer and do the job.
889  F77_INT lwork = static_cast<F77_INT> (rlwork);
890  lwork = std::max (lwork, static_cast<F77_INT> (1));
891  OCTAVE_LOCAL_BUFFER (float, work, lwork);
892  F77_XFCN (sgeqrf, SGEQRF, (m, n, afact.fortran_vec (), m, tau,
893  work, lwork, info));
894  }
895 
896  form (n, afact, tau, qr_type);
897  }
898 
899 #if defined (HAVE_QRUPDATE)
900 
901  template <>
902  void
904  {
905  F77_INT m = to_f77_int (q.rows ());
906  F77_INT n = to_f77_int (r.cols ());
907  F77_INT k = to_f77_int (q.cols ());
908 
909  F77_INT u_nel = to_f77_int (u.numel ());
910  F77_INT v_nel = to_f77_int (v.numel ());
911 
912  if (u_nel != m || v_nel != n)
913  (*current_liboctave_error_handler) ("qrupdate: dimensions mismatch");
914 
915  FloatColumnVector utmp = u;
916  FloatColumnVector vtmp = v;
917  OCTAVE_LOCAL_BUFFER (float, w, 2*k);
918  F77_XFCN (sqr1up, SQR1UP, (m, n, k, q.fortran_vec (), m,
919  r.fortran_vec (), k, utmp.fortran_vec (),
920  vtmp.fortran_vec (), w));
921  }
922 
923  template <>
924  void
926  {
927  F77_INT m = to_f77_int (q.rows ());
928  F77_INT n = to_f77_int (r.cols ());
929  F77_INT k = to_f77_int (q.cols ());
930 
931  F77_INT u_rows = to_f77_int (u.rows ());
932  F77_INT u_cols = to_f77_int (u.cols ());
933 
934  F77_INT v_rows = to_f77_int (v.rows ());
935  F77_INT v_cols = to_f77_int (v.cols ());
936 
937  if (u_rows != m || v_rows != n || u_cols != v_cols)
938  (*current_liboctave_error_handler) ("qrupdate: dimensions mismatch");
939 
940  OCTAVE_LOCAL_BUFFER (float, w, 2*k);
941  for (volatile F77_INT i = 0; i < u_cols; i++)
942  {
943  FloatColumnVector utmp = u.column (i);
944  FloatColumnVector vtmp = v.column (i);
945  F77_XFCN (sqr1up, SQR1UP, (m, n, k, q.fortran_vec (), m,
946  r.fortran_vec (), k, utmp.fortran_vec (),
947  vtmp.fortran_vec (), w));
948  }
949  }
950 
951  template <>
952  void
954  octave_idx_type j_arg)
955  {
956  F77_INT j = to_f77_int (j_arg);
957 
958  F77_INT m = to_f77_int (q.rows ());
959  F77_INT n = to_f77_int (r.cols ());
960  F77_INT k = to_f77_int (q.cols ());
961 
962  F77_INT u_nel = to_f77_int (u.numel ());
963 
964  if (u_nel != m)
965  (*current_liboctave_error_handler) ("qrinsert: dimensions mismatch");
966 
967  if (j < 0 || j > n)
968  (*current_liboctave_error_handler) ("qrinsert: index out of range");
969 
970  if (k < m)
971  {
972  q.resize (m, k+1);
973  r.resize (k+1, n+1);
974  }
975  else
976  r.resize (k, n+1);
977 
978  F77_INT ldq = to_f77_int (q.rows ());
979  F77_INT ldr = to_f77_int (r.rows ());
980 
981  FloatColumnVector utmp = u;
982  OCTAVE_LOCAL_BUFFER (float, w, k);
983  F77_XFCN (sqrinc, SQRINC, (m, n, k, q.fortran_vec (), ldq,
984  r.fortran_vec (), ldr, j + 1,
985  utmp.data (), w));
986  }
987 
988  template <>
989  void
991  const Array<octave_idx_type>& j)
992  {
993  F77_INT m = to_f77_int (q.rows ());
994  F77_INT n = to_f77_int (r.cols ());
995  F77_INT k = to_f77_int (q.cols ());
996 
998  Array<octave_idx_type> js = j.sort (jsi, 0, ASCENDING);
999  F77_INT nj = to_f77_int (js.numel ());
1000  bool dups = false;
1001  for (F77_INT i = 0; i < nj - 1; i++)
1002  dups = dups && js(i) == js(i+1);
1003 
1004  if (dups)
1005  (*current_liboctave_error_handler) ("qrinsert: duplicate index detected");
1006 
1007  F77_INT u_nel = to_f77_int (u.numel ());
1008  F77_INT u_cols = to_f77_int (u.cols ());
1009 
1010  if (u_nel != m || u_cols != nj)
1011  (*current_liboctave_error_handler) ("qrinsert: dimensions mismatch");
1012 
1013  F77_INT js_beg = to_f77_int (js(0));
1014  F77_INT js_end = to_f77_int (js(nj-1));
1015 
1016  if (nj > 0 && (js_beg < 0 || js_end > n))
1017  (*current_liboctave_error_handler) ("qrinsert: index out of range");
1018 
1019  if (nj > 0)
1020  {
1021  F77_INT kmax = std::min (k + nj, m);
1022  if (k < m)
1023  {
1024  q.resize (m, kmax);
1025  r.resize (kmax, n + nj);
1026  }
1027  else
1028  r.resize (k, n + nj);
1029 
1030  F77_INT ldq = to_f77_int (q.rows ());
1031  F77_INT ldr = to_f77_int (r.rows ());
1032 
1033  OCTAVE_LOCAL_BUFFER (float, w, kmax);
1034  for (volatile F77_INT i = 0; i < nj; i++)
1035  {
1036  F77_INT ii = i;
1037  FloatColumnVector utmp = u.column (jsi(i));
1038  F77_INT js_elt = to_f77_int (js(ii));
1039  F77_XFCN (sqrinc, SQRINC, (m, n + ii, std::min (kmax, k + ii),
1040  q.fortran_vec (), ldq,
1041  r.fortran_vec (), ldr, js_elt + 1,
1042  utmp.data (), w));
1043  }
1044  }
1045  }
1046 
1047  template <>
1048  void
1050  {
1051  F77_INT j = to_f77_int (j_arg);
1052 
1053  F77_INT m = to_f77_int (q.rows ());
1054  F77_INT k = to_f77_int (r.rows ());
1055  F77_INT n = to_f77_int (r.cols ());
1056 
1057  if (j < 0 || j > n-1)
1058  (*current_liboctave_error_handler) ("qrdelete: index out of range");
1059 
1060  F77_INT ldq = to_f77_int (q.rows ());
1061  F77_INT ldr = to_f77_int (r.rows ());
1062 
1063  OCTAVE_LOCAL_BUFFER (float, w, k);
1064  F77_XFCN (sqrdec, SQRDEC, (m, n, k, q.fortran_vec (), ldq,
1065  r.fortran_vec (), ldr, j + 1, w));
1066 
1067  if (k < m)
1068  {
1069  q.resize (m, k-1);
1070  r.resize (k-1, n-1);
1071  }
1072  else
1073  r.resize (k, n-1);
1074  }
1075 
1076  template <>
1077  void
1079  {
1080  F77_INT m = to_f77_int (q.rows ());
1081  F77_INT n = to_f77_int (r.cols ());
1082  F77_INT k = to_f77_int (q.cols ());
1083 
1085  Array<octave_idx_type> js = j.sort (jsi, 0, DESCENDING);
1086  F77_INT nj = to_f77_int (js.numel ());
1087  bool dups = false;
1088  for (F77_INT i = 0; i < nj - 1; i++)
1089  dups = dups && js(i) == js(i+1);
1090 
1091  if (dups)
1092  (*current_liboctave_error_handler) ("qrinsert: duplicate index detected");
1093 
1094  F77_INT js_beg = to_f77_int (js(0));
1095  F77_INT js_end = to_f77_int (js(nj-1));
1096 
1097  if (nj > 0 && (js_beg > n-1 || js_end < 0))
1098  (*current_liboctave_error_handler) ("qrinsert: index out of range");
1099 
1100  if (nj > 0)
1101  {
1102  F77_INT ldq = to_f77_int (q.rows ());
1103  F77_INT ldr = to_f77_int (r.rows ());
1104 
1105  OCTAVE_LOCAL_BUFFER (float, w, k);
1106  for (volatile F77_INT i = 0; i < nj; i++)
1107  {
1108  F77_INT ii = i;
1109  F77_INT js_elt = to_f77_int (js(ii));
1110  F77_XFCN (sqrdec, SQRDEC, (m, n - ii, (k == m ? k : k - ii),
1111  q.fortran_vec (), ldq,
1112  r.fortran_vec (), ldr,
1113  js_elt + 1, w));
1114  }
1115 
1116  if (k < m)
1117  {
1118  q.resize (m, k - nj);
1119  r.resize (k - nj, n - nj);
1120  }
1121  else
1122  r.resize (k, n - nj);
1123  }
1124  }
1125 
1126  template <>
1127  void
1129  octave_idx_type j_arg)
1130  {
1131  F77_INT j = to_f77_int (j_arg);
1132 
1133  F77_INT m = to_f77_int (r.rows ());
1134  F77_INT n = to_f77_int (r.cols ());
1135  F77_INT k = std::min (m, n);
1136 
1137  F77_INT u_nel = to_f77_int (u.numel ());
1138 
1139  if (! q.issquare () || u_nel != n)
1140  (*current_liboctave_error_handler) ("qrinsert: dimensions mismatch");
1141 
1142  if (j < 0 || j > m)
1143  (*current_liboctave_error_handler) ("qrinsert: index out of range");
1144 
1145  q.resize (m + 1, m + 1);
1146  r.resize (m + 1, n);
1147 
1148  F77_INT ldq = to_f77_int (q.rows ());
1149  F77_INT ldr = to_f77_int (r.rows ());
1150 
1151  FloatRowVector utmp = u;
1152  OCTAVE_LOCAL_BUFFER (float, w, k);
1153  F77_XFCN (sqrinr, SQRINR, (m, n, q.fortran_vec (), ldq,
1154  r.fortran_vec (), ldr,
1155  j + 1, utmp.fortran_vec (), w));
1156 
1157  }
1158 
1159  template <>
1160  void
1162  {
1163  F77_INT j = to_f77_int (j_arg);
1164 
1165  F77_INT m = to_f77_int (r.rows ());
1166  F77_INT n = to_f77_int (r.cols ());
1167 
1168  if (! q.issquare ())
1169  (*current_liboctave_error_handler) ("qrdelete: dimensions mismatch");
1170 
1171  if (j < 0 || j > m-1)
1172  (*current_liboctave_error_handler) ("qrdelete: index out of range");
1173 
1174  F77_INT ldq = to_f77_int (q.rows ());
1175  F77_INT ldr = to_f77_int (r.rows ());
1176 
1177  OCTAVE_LOCAL_BUFFER (float, w, 2*m);
1178  F77_XFCN (sqrder, SQRDER, (m, n, q.fortran_vec (), ldq,
1179  r.fortran_vec (), ldr, j + 1,
1180  w));
1181 
1182  q.resize (m - 1, m - 1);
1183  r.resize (m - 1, n);
1184  }
1185 
1186  template <>
1187  void
1189  {
1190  F77_INT i = to_f77_int (i_arg);
1191  F77_INT j = to_f77_int (j_arg);
1192 
1193  F77_INT m = to_f77_int (q.rows ());
1194  F77_INT k = to_f77_int (r.rows ());
1195  F77_INT n = to_f77_int (r.cols ());
1196 
1197  if (i < 0 || i > n-1 || j < 0 || j > n-1)
1198  (*current_liboctave_error_handler) ("qrshift: index out of range");
1199 
1200  F77_INT ldq = to_f77_int (q.rows ());
1201  F77_INT ldr = to_f77_int (r.rows ());
1202 
1203  OCTAVE_LOCAL_BUFFER (float, w, 2*k);
1204  F77_XFCN (sqrshc, SQRSHC, (m, n, k,
1205  q.fortran_vec (), ldq,
1206  r.fortran_vec (), ldr,
1207  i + 1, j + 1, w));
1208  }
1209 
1210 #endif
1211 
1212  template <>
1213  void
1215  Complex *tau, type qr_type)
1216  {
1217  F77_INT n = to_f77_int (n_arg);
1218  F77_INT m = to_f77_int (afact.rows ());
1219  F77_INT min_mn = std::min (m, n);
1220  F77_INT info;
1221 
1223  {
1224  for (F77_INT j = 0; j < min_mn; j++)
1225  {
1226  F77_INT limit = (j < min_mn - 1 ? j : min_mn - 1);
1227  for (F77_INT i = limit + 1; i < m; i++)
1228  afact.elem (i, j) *= tau[j];
1229  }
1230 
1231  r = afact;
1232  }
1233  else
1234  {
1235  // Attempt to minimize copying.
1236  if (m >= n)
1237  {
1238  // afact will become q.
1239  q = afact;
1241  r = ComplexMatrix (k, n);
1242  for (F77_INT j = 0; j < n; j++)
1243  {
1244  F77_INT i = 0;
1245  for (; i <= j; i++)
1246  r.xelem (i, j) = afact.xelem (i, j);
1247  for (; i < k; i++)
1248  r.xelem (i, j) = 0;
1249  }
1250  afact = ComplexMatrix (); // optimize memory
1251  }
1252  else
1253  {
1254  // afact will become r.
1255  q = ComplexMatrix (m, m);
1256  for (F77_INT j = 0; j < m; j++)
1257  for (F77_INT i = j + 1; i < m; i++)
1258  {
1259  q.xelem (i, j) = afact.xelem (i, j);
1260  afact.xelem (i, j) = 0;
1261  }
1262  r = afact;
1263  }
1264 
1265  if (m > 0)
1266  {
1267  F77_INT k = to_f77_int (q.cols ());
1268  // workspace query.
1269  Complex clwork;
1270  F77_XFCN (zungqr, ZUNGQR, (m, k, min_mn,
1271  F77_DBLE_CMPLX_ARG (q.fortran_vec ()),
1272  m, F77_DBLE_CMPLX_ARG (tau),
1273  F77_DBLE_CMPLX_ARG (&clwork), -1,
1274  info));
1275 
1276  // allocate buffer and do the job.
1277  F77_INT lwork = static_cast<F77_INT> (clwork.real ());
1278  lwork = std::max (lwork, static_cast<F77_INT> (1));
1279  OCTAVE_LOCAL_BUFFER (Complex, work, lwork);
1280  F77_XFCN (zungqr, ZUNGQR, (m, k, min_mn,
1281  F77_DBLE_CMPLX_ARG (q.fortran_vec ()),
1282  m, F77_DBLE_CMPLX_ARG (tau),
1283  F77_DBLE_CMPLX_ARG (work), lwork,
1284  info));
1285  }
1286  }
1287  }
1288 
1289  template <>
1290  void
1292  {
1293  F77_INT m = to_f77_int (a.rows ());
1294  F77_INT n = to_f77_int (a.cols ());
1295 
1296  F77_INT min_mn = (m < n ? m : n);
1297  OCTAVE_LOCAL_BUFFER (Complex, tau, min_mn);
1298 
1299  F77_INT info = 0;
1300 
1301  ComplexMatrix afact = a;
1302  if (m > n && qr_type == qr<ComplexMatrix>::std)
1303  afact.resize (m, m);
1304 
1305  if (m > 0)
1306  {
1307  // workspace query.
1308  Complex clwork;
1309  F77_XFCN (zgeqrf, ZGEQRF, (m, n,
1310  F77_DBLE_CMPLX_ARG (afact.fortran_vec ()),
1311  m, F77_DBLE_CMPLX_ARG (tau),
1312  F77_DBLE_CMPLX_ARG (&clwork), -1, info));
1313 
1314  // allocate buffer and do the job.
1315  F77_INT lwork = static_cast<F77_INT> (clwork.real ());
1316  lwork = std::max (lwork, static_cast<F77_INT> (1));
1317  OCTAVE_LOCAL_BUFFER (Complex, work, lwork);
1318  F77_XFCN (zgeqrf, ZGEQRF, (m, n,
1319  F77_DBLE_CMPLX_ARG (afact.fortran_vec ()),
1320  m, F77_DBLE_CMPLX_ARG (tau),
1321  F77_DBLE_CMPLX_ARG (work), lwork, info));
1322  }
1323 
1324  form (n, afact, tau, qr_type);
1325  }
1326 
1327 #if defined (HAVE_QRUPDATE)
1328 
1329  template <>
1330  void
1332  const ComplexColumnVector& v)
1333  {
1334  F77_INT m = to_f77_int (q.rows ());
1335  F77_INT n = to_f77_int (r.cols ());
1336  F77_INT k = to_f77_int (q.cols ());
1337 
1338  F77_INT u_nel = to_f77_int (u.numel ());
1339  F77_INT v_nel = to_f77_int (v.numel ());
1340 
1341  if (u_nel != m || v_nel != n)
1342  (*current_liboctave_error_handler) ("qrupdate: dimensions mismatch");
1343 
1344  ComplexColumnVector utmp = u;
1345  ComplexColumnVector vtmp = v;
1347  OCTAVE_LOCAL_BUFFER (double, rw, k);
1348  F77_XFCN (zqr1up, ZQR1UP, (m, n, k, F77_DBLE_CMPLX_ARG (q.fortran_vec ()),
1349  m, F77_DBLE_CMPLX_ARG (r.fortran_vec ()), k,
1350  F77_DBLE_CMPLX_ARG (utmp.fortran_vec ()),
1351  F77_DBLE_CMPLX_ARG (vtmp.fortran_vec ()),
1352  F77_DBLE_CMPLX_ARG (w), rw));
1353  }
1354 
1355  template <>
1356  void
1358  {
1359  F77_INT m = to_f77_int (q.rows ());
1360  F77_INT n = to_f77_int (r.cols ());
1361  F77_INT k = to_f77_int (q.cols ());
1362 
1363  F77_INT u_rows = to_f77_int (u.rows ());
1364  F77_INT u_cols = to_f77_int (u.cols ());
1365 
1366  F77_INT v_rows = to_f77_int (v.rows ());
1367  F77_INT v_cols = to_f77_int (v.cols ());
1368 
1369  if (u_rows != m || v_rows != n || u_cols != v_cols)
1370  (*current_liboctave_error_handler) ("qrupdate: dimensions mismatch");
1371 
1373  OCTAVE_LOCAL_BUFFER (double, rw, k);
1374  for (volatile F77_INT i = 0; i < u_cols; i++)
1375  {
1376  ComplexColumnVector utmp = u.column (i);
1377  ComplexColumnVector vtmp = v.column (i);
1378  F77_XFCN (zqr1up, ZQR1UP, (m, n, k,
1379  F77_DBLE_CMPLX_ARG (q.fortran_vec ()),
1380  m, F77_DBLE_CMPLX_ARG (r.fortran_vec ()), k,
1381  F77_DBLE_CMPLX_ARG (utmp.fortran_vec ()),
1382  F77_DBLE_CMPLX_ARG (vtmp.fortran_vec ()),
1383  F77_DBLE_CMPLX_ARG (w), rw));
1384  }
1385  }
1386 
1387  template <>
1388  void
1390  octave_idx_type j_arg)
1391  {
1392  F77_INT j = to_f77_int (j_arg);
1393 
1394  F77_INT m = to_f77_int (q.rows ());
1395  F77_INT n = to_f77_int (r.cols ());
1396  F77_INT k = to_f77_int (q.cols ());
1397 
1398  F77_INT u_nel = to_f77_int (u.numel ());
1399 
1400  if (u_nel != m)
1401  (*current_liboctave_error_handler) ("qrinsert: dimensions mismatch");
1402 
1403  if (j < 0 || j > n)
1404  (*current_liboctave_error_handler) ("qrinsert: index out of range");
1405 
1406  if (k < m)
1407  {
1408  q.resize (m, k+1);
1409  r.resize (k+1, n+1);
1410  }
1411  else
1412  r.resize (k, n+1);
1413 
1414  F77_INT ldq = to_f77_int (q.rows ());
1415  F77_INT ldr = to_f77_int (r.rows ());
1416 
1417  ComplexColumnVector utmp = u;
1418  OCTAVE_LOCAL_BUFFER (double, rw, k);
1419  F77_XFCN (zqrinc, ZQRINC, (m, n, k, F77_DBLE_CMPLX_ARG (q.fortran_vec ()),
1420  ldq, F77_DBLE_CMPLX_ARG (r.fortran_vec ()),
1421  ldr, j + 1,
1422  F77_CONST_DBLE_CMPLX_ARG (utmp.data ()), rw));
1423  }
1424 
1425  template <>
1426  void
1428  const Array<octave_idx_type>& j)
1429  {
1430  F77_INT m = to_f77_int (q.rows ());
1431  F77_INT n = to_f77_int (r.cols ());
1432  F77_INT k = to_f77_int (q.cols ());
1433 
1435  Array<octave_idx_type> js = j.sort (jsi, 0, ASCENDING);
1436  F77_INT nj = to_f77_int (js.numel ());
1437  bool dups = false;
1438  for (F77_INT i = 0; i < nj - 1; i++)
1439  dups = dups && js(i) == js(i+1);
1440 
1441  if (dups)
1442  (*current_liboctave_error_handler) ("qrinsert: duplicate index detected");
1443 
1444  F77_INT u_nel = to_f77_int (u.numel ());
1445  F77_INT u_cols = to_f77_int (u.cols ());
1446 
1447  if (u_nel != m || u_cols != nj)
1448  (*current_liboctave_error_handler) ("qrinsert: dimensions mismatch");
1449 
1450  F77_INT js_beg = to_f77_int (js(0));
1451  F77_INT js_end = to_f77_int (js(nj-1));
1452 
1453  if (nj > 0 && (js_beg < 0 || js_end > n))
1454  (*current_liboctave_error_handler) ("qrinsert: index out of range");
1455 
1456  if (nj > 0)
1457  {
1458  F77_INT kmax = std::min (k + nj, m);
1459  if (k < m)
1460  {
1461  q.resize (m, kmax);
1462  r.resize (kmax, n + nj);
1463  }
1464  else
1465  r.resize (k, n + nj);
1466 
1467  F77_INT ldq = to_f77_int (q.rows ());
1468  F77_INT ldr = to_f77_int (r.rows ());
1469 
1470  OCTAVE_LOCAL_BUFFER (double, rw, kmax);
1471  for (volatile F77_INT i = 0; i < nj; i++)
1472  {
1473  F77_INT ii = i;
1474  ComplexColumnVector utmp = u.column (jsi(i));
1475  F77_INT js_elt = to_f77_int (js(ii));
1476  F77_XFCN (zqrinc, ZQRINC, (m, n + ii, std::min (kmax, k + ii),
1477  F77_DBLE_CMPLX_ARG (q.fortran_vec ()),
1478  ldq,
1479  F77_DBLE_CMPLX_ARG (r.fortran_vec ()),
1480  ldr, js_elt + 1,
1481  F77_CONST_DBLE_CMPLX_ARG (utmp.data ()),
1482  rw));
1483  }
1484  }
1485  }
1486 
1487  template <>
1488  void
1490  {
1491  F77_INT j = to_f77_int (j_arg);
1492 
1493  F77_INT m = to_f77_int (q.rows ());
1494  F77_INT k = to_f77_int (r.rows ());
1495  F77_INT n = to_f77_int (r.cols ());
1496 
1497  if (j < 0 || j > n-1)
1498  (*current_liboctave_error_handler) ("qrdelete: index out of range");
1499 
1500  F77_INT ldq = to_f77_int (q.rows ());
1501  F77_INT ldr = to_f77_int (r.rows ());
1502 
1503  OCTAVE_LOCAL_BUFFER (double, rw, k);
1504  F77_XFCN (zqrdec, ZQRDEC, (m, n, k, F77_DBLE_CMPLX_ARG (q.fortran_vec ()),
1505  ldq, F77_DBLE_CMPLX_ARG (r.fortran_vec ()),
1506  ldr, j + 1, rw));
1507 
1508  if (k < m)
1509  {
1510  q.resize (m, k-1);
1511  r.resize (k-1, n-1);
1512  }
1513  else
1514  r.resize (k, n-1);
1515  }
1516 
1517  template <>
1518  void
1520  {
1521  F77_INT m = to_f77_int (q.rows ());
1522  F77_INT n = to_f77_int (r.cols ());
1523  F77_INT k = to_f77_int (q.cols ());
1524 
1526  Array<octave_idx_type> js = j.sort (jsi, 0, DESCENDING);
1527  F77_INT nj = to_f77_int (js.numel ());
1528  bool dups = false;
1529  for (F77_INT i = 0; i < nj - 1; i++)
1530  dups = dups && js(i) == js(i+1);
1531 
1532  if (dups)
1533  (*current_liboctave_error_handler) ("qrinsert: duplicate index detected");
1534 
1535  F77_INT js_beg = to_f77_int (js(0));
1536  F77_INT js_end = to_f77_int (js(nj-1));
1537 
1538  if (nj > 0 && (js_beg > n-1 || js_end < 0))
1539  (*current_liboctave_error_handler) ("qrinsert: index out of range");
1540 
1541  if (nj > 0)
1542  {
1543  F77_INT ldq = to_f77_int (q.rows ());
1544  F77_INT ldr = to_f77_int (r.rows ());
1545 
1546  OCTAVE_LOCAL_BUFFER (double, rw, k);
1547  for (volatile F77_INT i = 0; i < nj; i++)
1548  {
1549  F77_INT ii = i;
1550  F77_INT js_elt = to_f77_int (js(ii));
1551  F77_XFCN (zqrdec, ZQRDEC, (m, n - ii, (k == m ? k : k - ii),
1552  F77_DBLE_CMPLX_ARG (q.fortran_vec ()),
1553  ldq,
1554  F77_DBLE_CMPLX_ARG (r.fortran_vec ()),
1555  ldr, js_elt + 1, rw));
1556  }
1557 
1558  if (k < m)
1559  {
1560  q.resize (m, k - nj);
1561  r.resize (k - nj, n - nj);
1562  }
1563  else
1564  r.resize (k, n - nj);
1565  }
1566  }
1567 
1568  template <>
1569  void
1571  octave_idx_type j_arg)
1572  {
1573  F77_INT j = to_f77_int (j_arg);
1574 
1575  F77_INT m = to_f77_int (r.rows ());
1576  F77_INT n = to_f77_int (r.cols ());
1577  F77_INT k = std::min (m, n);
1578 
1579  F77_INT u_nel = to_f77_int (u.numel ());
1580 
1581  if (! q.issquare () || u_nel != n)
1582  (*current_liboctave_error_handler) ("qrinsert: dimensions mismatch");
1583 
1584  if (j < 0 || j > m)
1585  (*current_liboctave_error_handler) ("qrinsert: index out of range");
1586 
1587  q.resize (m + 1, m + 1);
1588  r.resize (m + 1, n);
1589 
1590  F77_INT ldq = to_f77_int (q.rows ());
1591  F77_INT ldr = to_f77_int (r.rows ());
1592 
1593  ComplexRowVector utmp = u;
1594  OCTAVE_LOCAL_BUFFER (double, rw, k);
1595  F77_XFCN (zqrinr, ZQRINR, (m, n, F77_DBLE_CMPLX_ARG (q.fortran_vec ()),
1596  ldq, F77_DBLE_CMPLX_ARG (r.fortran_vec ()),
1597  ldr, j + 1,
1598  F77_DBLE_CMPLX_ARG (utmp.fortran_vec ()), rw));
1599 
1600  }
1601 
1602  template <>
1603  void
1605  {
1606  F77_INT j = to_f77_int (j_arg);
1607 
1608  F77_INT m = to_f77_int (r.rows ());
1609  F77_INT n = to_f77_int (r.cols ());
1610 
1611  if (! q.issquare ())
1612  (*current_liboctave_error_handler) ("qrdelete: dimensions mismatch");
1613 
1614  if (j < 0 || j > m-1)
1615  (*current_liboctave_error_handler) ("qrdelete: index out of range");
1616 
1617  F77_INT ldq = to_f77_int (q.rows ());
1618  F77_INT ldr = to_f77_int (r.rows ());
1619 
1621  OCTAVE_LOCAL_BUFFER (double, rw, m);
1622  F77_XFCN (zqrder, ZQRDER, (m, n, F77_DBLE_CMPLX_ARG (q.fortran_vec ()),
1623  ldq, F77_DBLE_CMPLX_ARG (r.fortran_vec ()),
1624  ldr, j + 1, F77_DBLE_CMPLX_ARG (w), rw));
1625 
1626  q.resize (m - 1, m - 1);
1627  r.resize (m - 1, n);
1628  }
1629 
1630  template <>
1631  void
1633  octave_idx_type j_arg)
1634  {
1635  F77_INT i = to_f77_int (i_arg);
1636  F77_INT j = to_f77_int (j_arg);
1637 
1638  F77_INT m = to_f77_int (q.rows ());
1639  F77_INT k = to_f77_int (r.rows ());
1640  F77_INT n = to_f77_int (r.cols ());
1641 
1642  if (i < 0 || i > n-1 || j < 0 || j > n-1)
1643  (*current_liboctave_error_handler) ("qrshift: index out of range");
1644 
1645  F77_INT ldq = to_f77_int (q.rows ());
1646  F77_INT ldr = to_f77_int (r.rows ());
1647 
1649  OCTAVE_LOCAL_BUFFER (double, rw, k);
1650  F77_XFCN (zqrshc, ZQRSHC, (m, n, k,
1651  F77_DBLE_CMPLX_ARG (q.fortran_vec ()), ldq,
1652  F77_DBLE_CMPLX_ARG (r.fortran_vec ()), ldr,
1653  i + 1, j + 1, F77_DBLE_CMPLX_ARG (w), rw));
1654  }
1655 
1656 #endif
1657 
1658  template <>
1659  void
1661  FloatComplex *tau, type qr_type)
1662  {
1663  F77_INT n = to_f77_int (n_arg);
1664  F77_INT m = to_f77_int (afact.rows ());
1665  F77_INT min_mn = std::min (m, n);
1666  F77_INT info;
1667 
1669  {
1670  for (F77_INT j = 0; j < min_mn; j++)
1671  {
1672  F77_INT limit = (j < min_mn - 1 ? j : min_mn - 1);
1673  for (F77_INT i = limit + 1; i < m; i++)
1674  afact.elem (i, j) *= tau[j];
1675  }
1676 
1677  r = afact;
1678  }
1679  else
1680  {
1681  // Attempt to minimize copying.
1682  if (m >= n)
1683  {
1684  // afact will become q.
1685  q = afact;
1687  r = FloatComplexMatrix (k, n);
1688  for (F77_INT j = 0; j < n; j++)
1689  {
1690  F77_INT i = 0;
1691  for (; i <= j; i++)
1692  r.xelem (i, j) = afact.xelem (i, j);
1693  for (; i < k; i++)
1694  r.xelem (i, j) = 0;
1695  }
1696  afact = FloatComplexMatrix (); // optimize memory
1697  }
1698  else
1699  {
1700  // afact will become r.
1701  q = FloatComplexMatrix (m, m);
1702  for (F77_INT j = 0; j < m; j++)
1703  for (F77_INT i = j + 1; i < m; i++)
1704  {
1705  q.xelem (i, j) = afact.xelem (i, j);
1706  afact.xelem (i, j) = 0;
1707  }
1708  r = afact;
1709  }
1710 
1711  if (m > 0)
1712  {
1713  F77_INT k = to_f77_int (q.cols ());
1714  // workspace query.
1715  FloatComplex clwork;
1716  F77_XFCN (cungqr, CUNGQR, (m, k, min_mn,
1717  F77_CMPLX_ARG (q.fortran_vec ()), m,
1718  F77_CMPLX_ARG (tau),
1719  F77_CMPLX_ARG (&clwork), -1, info));
1720 
1721  // allocate buffer and do the job.
1722  F77_INT lwork = static_cast<F77_INT> (clwork.real ());
1723  lwork = std::max (lwork, static_cast<F77_INT> (1));
1724  OCTAVE_LOCAL_BUFFER (FloatComplex, work, lwork);
1725  F77_XFCN (cungqr, CUNGQR, (m, k, min_mn,
1726  F77_CMPLX_ARG (q.fortran_vec ()), m,
1727  F77_CMPLX_ARG (tau),
1728  F77_CMPLX_ARG (work), lwork, info));
1729  }
1730  }
1731  }
1732 
1733  template <>
1734  void
1736  {
1737  F77_INT m = to_f77_int (a.rows ());
1738  F77_INT n = to_f77_int (a.cols ());
1739 
1740  F77_INT min_mn = (m < n ? m : n);
1741  OCTAVE_LOCAL_BUFFER (FloatComplex, tau, min_mn);
1742 
1743  F77_INT info = 0;
1744 
1745  FloatComplexMatrix afact = a;
1746  if (m > n && qr_type == qr<FloatComplexMatrix>::std)
1747  afact.resize (m, m);
1748 
1749  if (m > 0)
1750  {
1751  // workspace query.
1752  FloatComplex clwork;
1753  F77_XFCN (cgeqrf, CGEQRF, (m, n, F77_CMPLX_ARG (afact.fortran_vec ()),
1754  m, F77_CMPLX_ARG (tau),
1755  F77_CMPLX_ARG (&clwork), -1, info));
1756 
1757  // allocate buffer and do the job.
1758  F77_INT lwork = static_cast<F77_INT> (clwork.real ());
1759  lwork = std::max (lwork, static_cast<F77_INT> (1));
1760  OCTAVE_LOCAL_BUFFER (FloatComplex, work, lwork);
1761  F77_XFCN (cgeqrf, CGEQRF, (m, n, F77_CMPLX_ARG (afact.fortran_vec ()),
1762  m, F77_CMPLX_ARG (tau),
1763  F77_CMPLX_ARG (work), lwork, info));
1764  }
1765 
1766  form (n, afact, tau, qr_type);
1767  }
1768 
1769 #if defined (HAVE_QRUPDATE)
1770 
1771  template <>
1772  void
1774  const FloatComplexColumnVector& v)
1775  {
1776  F77_INT m = to_f77_int (q.rows ());
1777  F77_INT n = to_f77_int (r.cols ());
1778  F77_INT k = to_f77_int (q.cols ());
1779 
1780  F77_INT u_nel = to_f77_int (u.numel ());
1781  F77_INT v_nel = to_f77_int (v.numel ());
1782 
1783  if (u_nel != m || v_nel != n)
1784  (*current_liboctave_error_handler) ("qrupdate: dimensions mismatch");
1785 
1786  FloatComplexColumnVector utmp = u;
1787  FloatComplexColumnVector vtmp = v;
1789  OCTAVE_LOCAL_BUFFER (float, rw, k);
1790  F77_XFCN (cqr1up, CQR1UP, (m, n, k, F77_CMPLX_ARG (q.fortran_vec ()),
1791  m, F77_CMPLX_ARG (r.fortran_vec ()), k,
1792  F77_CMPLX_ARG (utmp.fortran_vec ()),
1793  F77_CMPLX_ARG (vtmp.fortran_vec ()),
1794  F77_CMPLX_ARG (w), rw));
1795  }
1796 
1797  template <>
1798  void
1800  const FloatComplexMatrix& v)
1801  {
1802  F77_INT m = to_f77_int (q.rows ());
1803  F77_INT n = to_f77_int (r.cols ());
1804  F77_INT k = to_f77_int (q.cols ());
1805 
1806  F77_INT u_rows = to_f77_int (u.rows ());
1807  F77_INT u_cols = to_f77_int (u.cols ());
1808 
1809  F77_INT v_rows = to_f77_int (v.rows ());
1810  F77_INT v_cols = to_f77_int (v.cols ());
1811 
1812  if (u_rows != m || v_rows != n || u_cols != v_cols)
1813  (*current_liboctave_error_handler) ("qrupdate: dimensions mismatch");
1814 
1816  OCTAVE_LOCAL_BUFFER (float, rw, k);
1817  for (volatile F77_INT i = 0; i < u_cols; i++)
1818  {
1819  FloatComplexColumnVector utmp = u.column (i);
1820  FloatComplexColumnVector vtmp = v.column (i);
1821  F77_XFCN (cqr1up, CQR1UP, (m, n, k, F77_CMPLX_ARG (q.fortran_vec ()),
1822  m, F77_CMPLX_ARG (r.fortran_vec ()), k,
1823  F77_CMPLX_ARG (utmp.fortran_vec ()),
1824  F77_CMPLX_ARG (vtmp.fortran_vec ()),
1825  F77_CMPLX_ARG (w), rw));
1826  }
1827  }
1828 
1829  template <>
1830  void
1832  octave_idx_type j_arg)
1833  {
1834  F77_INT j = to_f77_int (j_arg);
1835 
1836  F77_INT m = to_f77_int (q.rows ());
1837  F77_INT n = to_f77_int (r.cols ());
1838  F77_INT k = to_f77_int (q.cols ());
1839 
1840  F77_INT u_nel = to_f77_int (u.numel ());
1841 
1842  if (u_nel != m)
1843  (*current_liboctave_error_handler) ("qrinsert: dimensions mismatch");
1844 
1845  if (j < 0 || j > n)
1846  (*current_liboctave_error_handler) ("qrinsert: index out of range");
1847 
1848  if (k < m)
1849  {
1850  q.resize (m, k+1);
1851  r.resize (k+1, n+1);
1852  }
1853  else
1854  r.resize (k, n+1);
1855 
1856  F77_INT ldq = to_f77_int (q.rows ());
1857  F77_INT ldr = to_f77_int (r.rows ());
1858 
1859  FloatComplexColumnVector utmp = u;
1860  OCTAVE_LOCAL_BUFFER (float, rw, k);
1861  F77_XFCN (cqrinc, CQRINC, (m, n, k, F77_CMPLX_ARG (q.fortran_vec ()), ldq,
1862  F77_CMPLX_ARG (r.fortran_vec ()), ldr, j + 1,
1863  F77_CONST_CMPLX_ARG (utmp.data ()), rw));
1864  }
1865 
1866  template <>
1867  void
1869  const Array<octave_idx_type>& j)
1870  {
1871  F77_INT m = to_f77_int (q.rows ());
1872  F77_INT n = to_f77_int (r.cols ());
1873  F77_INT k = to_f77_int (q.cols ());
1874 
1876  Array<octave_idx_type> js = j.sort (jsi, 0, ASCENDING);
1877  F77_INT nj = to_f77_int (js.numel ());
1878  bool dups = false;
1879  for (F77_INT i = 0; i < nj - 1; i++)
1880  dups = dups && js(i) == js(i+1);
1881 
1882  if (dups)
1883  (*current_liboctave_error_handler) ("qrinsert: duplicate index detected");
1884 
1885  F77_INT u_nel = to_f77_int (u.numel ());
1886  F77_INT u_cols = to_f77_int (u.cols ());
1887 
1888  if (u_nel != m || u_cols != nj)
1889  (*current_liboctave_error_handler) ("qrinsert: dimensions mismatch");
1890 
1891  F77_INT js_beg = to_f77_int (js(0));
1892  F77_INT js_end = to_f77_int (js(nj-1));
1893 
1894  if (nj > 0 && (js_beg < 0 || js_end > n))
1895  (*current_liboctave_error_handler) ("qrinsert: index out of range");
1896 
1897  if (nj > 0)
1898  {
1899  F77_INT kmax = std::min (k + nj, m);
1900  if (k < m)
1901  {
1902  q.resize (m, kmax);
1903  r.resize (kmax, n + nj);
1904  }
1905  else
1906  r.resize (k, n + nj);
1907 
1908  F77_INT ldq = to_f77_int (q.rows ());
1909  F77_INT ldr = to_f77_int (r.rows ());
1910 
1911  OCTAVE_LOCAL_BUFFER (float, rw, kmax);
1912  for (volatile F77_INT i = 0; i < nj; i++)
1913  {
1914  F77_INT ii = i;
1915  F77_INT js_elt = to_f77_int (js(ii));
1916  F77_XFCN (cqrinc, CQRINC, (m, n + ii, std::min (kmax, k + ii),
1917  F77_CMPLX_ARG (q.fortran_vec ()), ldq,
1918  F77_CMPLX_ARG (r.fortran_vec ()), ldr,
1919  js_elt + 1,
1920  F77_CONST_CMPLX_ARG (u.column (jsi(i)).data ()),
1921  rw));
1922  }
1923  }
1924  }
1925 
1926  template <>
1927  void
1929  {
1930  F77_INT j = to_f77_int (j_arg);
1931 
1932  F77_INT m = to_f77_int (q.rows ());
1933  F77_INT k = to_f77_int (r.rows ());
1934  F77_INT n = to_f77_int (r.cols ());
1935 
1936  if (j < 0 || j > n-1)
1937  (*current_liboctave_error_handler) ("qrdelete: index out of range");
1938 
1939  F77_INT ldq = to_f77_int (q.rows ());
1940  F77_INT ldr = to_f77_int (r.rows ());
1941 
1942  OCTAVE_LOCAL_BUFFER (float, rw, k);
1943  F77_XFCN (cqrdec, CQRDEC, (m, n, k, F77_CMPLX_ARG (q.fortran_vec ()), ldq,
1944  F77_CMPLX_ARG (r.fortran_vec ()), ldr, j + 1,
1945  rw));
1946 
1947  if (k < m)
1948  {
1949  q.resize (m, k-1);
1950  r.resize (k-1, n-1);
1951  }
1952  else
1953  r.resize (k, n-1);
1954  }
1955 
1956  template <>
1957  void
1959  {
1960  F77_INT m = to_f77_int (q.rows ());
1961  F77_INT n = to_f77_int (r.cols ());
1962  F77_INT k = to_f77_int (q.cols ());
1963 
1965  Array<octave_idx_type> js = j.sort (jsi, 0, DESCENDING);
1966  F77_INT nj = to_f77_int (js.numel ());
1967  bool dups = false;
1968  for (F77_INT i = 0; i < nj - 1; i++)
1969  dups = dups && js(i) == js(i+1);
1970 
1971  if (dups)
1972  (*current_liboctave_error_handler) ("qrinsert: duplicate index detected");
1973 
1974  F77_INT js_beg = to_f77_int (js(0));
1975  F77_INT js_end = to_f77_int (js(nj-1));
1976 
1977  if (nj > 0 && (js_beg > n-1 || js_end < 0))
1978  (*current_liboctave_error_handler) ("qrinsert: index out of range");
1979 
1980  if (nj > 0)
1981  {
1982  F77_INT ldq = to_f77_int (q.rows ());
1983  F77_INT ldr = to_f77_int (r.rows ());
1984 
1985  OCTAVE_LOCAL_BUFFER (float, rw, k);
1986  for (volatile F77_INT i = 0; i < nj; i++)
1987  {
1988  F77_INT ii = i;
1989  F77_INT js_elt = to_f77_int (js(ii));
1990  F77_XFCN (cqrdec, CQRDEC, (m, n - ii, (k == m ? k : k - ii),
1991  F77_CMPLX_ARG (q.fortran_vec ()), ldq,
1992  F77_CMPLX_ARG (r.fortran_vec ()), ldr,
1993  js_elt + 1, rw));
1994  }
1995 
1996  if (k < m)
1997  {
1998  q.resize (m, k - nj);
1999  r.resize (k - nj, n - nj);
2000  }
2001  else
2002  r.resize (k, n - nj);
2003  }
2004  }
2005 
2006  template <>
2007  void
2009  octave_idx_type j_arg)
2010  {
2011  F77_INT j = to_f77_int (j_arg);
2012 
2013  F77_INT m = to_f77_int (r.rows ());
2014  F77_INT n = to_f77_int (r.cols ());
2015  F77_INT k = std::min (m, n);
2016 
2017  F77_INT u_nel = to_f77_int (u.numel ());
2018 
2019  if (! q.issquare () || u_nel != n)
2020  (*current_liboctave_error_handler) ("qrinsert: dimensions mismatch");
2021 
2022  if (j < 0 || j > m)
2023  (*current_liboctave_error_handler) ("qrinsert: index out of range");
2024 
2025  q.resize (m + 1, m + 1);
2026  r.resize (m + 1, n);
2027 
2028  F77_INT ldq = to_f77_int (q.rows ());
2029  F77_INT ldr = to_f77_int (r.rows ());
2030 
2031  FloatComplexRowVector utmp = u;
2032  OCTAVE_LOCAL_BUFFER (float, rw, k);
2033  F77_XFCN (cqrinr, CQRINR, (m, n, F77_CMPLX_ARG (q.fortran_vec ()), ldq,
2034  F77_CMPLX_ARG (r.fortran_vec ()), ldr,
2035  j + 1, F77_CMPLX_ARG (utmp.fortran_vec ()),
2036  rw));
2037 
2038  }
2039 
2040  template <>
2041  void
2043  {
2044  F77_INT j = to_f77_int (j_arg);
2045 
2046  F77_INT m = to_f77_int (r.rows ());
2047  F77_INT n = to_f77_int (r.cols ());
2048 
2049  if (! q.issquare ())
2050  (*current_liboctave_error_handler) ("qrdelete: dimensions mismatch");
2051 
2052  if (j < 0 || j > m-1)
2053  (*current_liboctave_error_handler) ("qrdelete: index out of range");
2054 
2055  F77_INT ldq = to_f77_int (q.rows ());
2056  F77_INT ldr = to_f77_int (r.rows ());
2057 
2059  OCTAVE_LOCAL_BUFFER (float, rw, m);
2060  F77_XFCN (cqrder, CQRDER, (m, n, F77_CMPLX_ARG (q.fortran_vec ()), ldq,
2061  F77_CMPLX_ARG (r.fortran_vec ()), ldr, j + 1,
2062  F77_CMPLX_ARG (w), rw));
2063 
2064  q.resize (m - 1, m - 1);
2065  r.resize (m - 1, n);
2066  }
2067 
2068  template <>
2069  void
2071  octave_idx_type j_arg)
2072  {
2073  F77_INT i = to_f77_int (i_arg);
2074  F77_INT j = to_f77_int (j_arg);
2075 
2076  F77_INT m = to_f77_int (q.rows ());
2077  F77_INT k = to_f77_int (r.rows ());
2078  F77_INT n = to_f77_int (r.cols ());
2079 
2080  if (i < 0 || i > n-1 || j < 0 || j > n-1)
2081  (*current_liboctave_error_handler) ("qrshift: index out of range");
2082 
2083  F77_INT ldq = to_f77_int (q.rows ());
2084  F77_INT ldr = to_f77_int (r.rows ());
2085 
2087  OCTAVE_LOCAL_BUFFER (float, rw, k);
2088  F77_XFCN (cqrshc, CQRSHC, (m, n, k,
2089  F77_CMPLX_ARG (q.fortran_vec ()), ldq,
2090  F77_CMPLX_ARG (r.fortran_vec ()), ldr,
2091  i + 1, j + 1, F77_CMPLX_ARG (w), rw));
2092  }
2093 
2094 #endif
2095 
2096  // Instantiations we need.
2097 
2098  template class qr<Matrix>;
2099 
2100  template class qr<FloatMatrix>;
2101 
2102  template class qr<ComplexMatrix>;
2103 
2104  template class qr<FloatComplexMatrix>;
2105  }
2106 }
charNDArray max(char d, const charNDArray &m)
Definition: chNDArray.cc:230
charNDArray min(char d, const charNDArray &m)
Definition: chNDArray.cc:207
Array< T > sort(int dim=0, sortmode mode=ASCENDING) const
Size of the specified dimension.
Definition: Array.cc:1757
void assign(const idx_vector &i, const Array< T > &rhs, const T &rfv)
Indexed assignment (always with resize & fill).
Definition: Array.cc:1116
T & xelem(octave_idx_type n)
Size of the specified dimension.
Definition: Array.h:469
octave_idx_type numel(void) const
Number of elements in the array.
Definition: Array.h:377
T & elem(octave_idx_type n)
Size of the specified dimension.
Definition: Array.h:499
const T * data(void) const
Size of the specified dimension.
Definition: Array.h:581
octave_idx_type cols(void) const
Definition: Array.h:423
octave_idx_type rows(void) const
Definition: Array.h:415
Array< T > column(octave_idx_type k) const
Extract column: A(:,k+1).
Definition: Array.cc:261
const T * fortran_vec(void) const
Size of the specified dimension.
Definition: Array.h:583
void delete_elements(const idx_vector &i)
Deleting elements.
Definition: Array.cc:1390
void resize(octave_idx_type nr, octave_idx_type nc, const Complex &rfv=Complex(0))
Definition: CMatrix.h:190
ComplexColumnVector column(octave_idx_type i) const
Definition: CMatrix.cc:708
FloatComplexColumnVector column(octave_idx_type i) const
Definition: fCMatrix.cc:711
void resize(octave_idx_type nr, octave_idx_type nc, const FloatComplex &rfv=FloatComplex(0))
Definition: fCMatrix.h:194
void resize(octave_idx_type nr, octave_idx_type nc, float rfv=0)
Definition: fMatrix.h:155
FloatColumnVector column(octave_idx_type i) const
Definition: fMatrix.cc:428
Definition: dMatrix.h:42
void resize(octave_idx_type nr, octave_idx_type nc, double rfv=0)
Definition: dMatrix.h:151
ColumnVector column(octave_idx_type i) const
Definition: dMatrix.cc:422
Vector representing the dimensions (size) of an Array.
Definition: dim-vector.h:95
static const idx_vector colon
Definition: idx-vector.h:499
octave_idx_type index(const T *src, octave_idx_type n, T *dest) const
Definition: idx-vector.h:622
void update(const CV_T &u, const CV_T &v)
bool regular(void) const
Definition: qr.cc:89
void init(const T &a, type qr_type)
void insert_row(const RV_T &u, octave_idx_type j)
T::element_type ELT_T
Definition: qr.h:43
void insert_col(const CV_T &u, octave_idx_type j)
qr(void)
Definition: qr.h:54
type get_type(void) const
Definition: qr.cc:73
void shift_cols(octave_idx_type i, octave_idx_type j)
void delete_col(octave_idx_type j)
void form(octave_idx_type n, T &afact, ELT_T *tau, type qr_type)
void delete_row(octave_idx_type j)
Definition: mx-defs.h:82
#define F77_CONST_CMPLX_ARG(x)
Definition: f77-fcn.h:312
#define F77_DBLE_CMPLX_ARG(x)
Definition: f77-fcn.h:315
#define F77_CMPLX_ARG(x)
Definition: f77-fcn.h:309
#define F77_XFCN(f, F, args)
Definition: f77-fcn.h:44
octave_f77_int_type F77_INT
Definition: f77-fcn.h:305
#define F77_CONST_DBLE_CMPLX_ARG(x)
Definition: f77-fcn.h:318
static octave::math::qr< T >::type qr_type(int nargout, bool economy)
Definition: qr.cc:72
OCTAVE_NORETURN liboctave_error_handler current_liboctave_error_handler
Definition: lo-error.c:41
F77_RET_T const F77_DBLE * x
T octave_idx_type m
Definition: mx-inlines.cc:773
octave_idx_type n
Definition: mx-inlines.cc:753
T * r
Definition: mx-inlines.cc:773
std::complex< double > w(std::complex< double > z, double relerr=0)
void warn_qrupdate_once(void)
std::complex< double > Complex
Definition: oct-cmplx.h:33
std::complex< float > FloatComplex
Definition: oct-cmplx.h:34
#define OCTAVE_LOCAL_BUFFER(T, buf, size)
Definition: oct-locbuf.h:44
@ ASCENDING
Definition: oct-sort.h:95
@ DESCENDING
Definition: oct-sort.h:95
octave_value::octave_value(const Array< char > &chm, char type) return retval
Definition: ov.cc:811