GNU Octave  4.4.1
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) 1996-2018 John W. Eaton
4 Copyright (C) 2008-2009 Jaroslav Hajek
5 Copyright (C) 2008-2009 VZLU Prague
6 
7 This file is part of Octave.
8 
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
11 the Free Software Foundation, either version 3 of the License, or
12 (at your option) any later version.
13 
14 Octave is distributed in the hope that it will be useful, but
15 WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
18 
19 You should have received a copy of the GNU General Public License
20 along with Octave; see the file COPYING. If not, see
21 <https://www.gnu.org/licenses/>.
22 
23 */
24 
25 #if defined (HAVE_CONFIG_H)
26 # include "config.h"
27 #endif
28 
29 #include <string>
30 
31 #include "MArray.h"
32 #include "Matrix.h"
33 #include "qr.h"
34 #include "qrp.h"
35 #include "sparse-qr.h"
36 
37 #include "defun-dld.h"
38 #include "error.h"
39 #include "errwarn.h"
40 #include "ov.h"
41 #include "ovl.h"
42 
43 template <typename MT>
44 static octave_value
46 {
47  MT R = fact.R ();
48  if (R.issquare () && fact.regular ())
50  else
51  return R;
52 }
53 
54 template <typename T>
55 static typename octave::math::qr<T>::type
56 qr_type (int nargout, bool economy)
57 {
58  if (nargout == 0 || nargout == 1)
60  else if (economy)
62  else
64 }
65 
66 // [Q, R] = qr (X): form Q unitary and R upper triangular such
67 // that Q * R = X
68 //
69 // [Q, R] = qr (X, 0): form the economy decomposition such that if X is
70 // m by n then only the first n columns of Q are
71 // computed.
72 //
73 // [Q, R, P] = qr (X): form QRP factorization of X where
74 // P is a permutation matrix such that
75 // A * P = Q * R
76 //
77 // [Q, R, P] = qr (X, 0): form the economy decomposition with
78 // permutation vector P such that Q * R = X(:, P)
79 //
80 // qr (X) alone returns the output of the LAPACK routine dgeqrf, such
81 // that R = triu (qr (X))
82 
83 DEFUN_DLD (qr, args, nargout,
84  doc: /* -*- texinfo -*-
85 @deftypefn {} {[@var{Q}, @var{R}] =} qr (@var{A})
86 @deftypefnx {} {[@var{Q}, @var{R}, @var{P}] =} qr (@var{A}) # non-sparse A
87 @deftypefnx {} {@var{X} =} qr (@var{A}) # non-sparse A
88 @deftypefnx {} {@var{R} =} qr (@var{A}) # sparse A
89 @deftypefnx {} {[@var{C}, @var{R}] =} qr (@var{A}, @var{B})
90 @deftypefnx {} {[@dots{}] =} qr (@dots{}, 0)
91 @deftypefnx {} {[@dots{}] =} qr (@dots{}, "vector")
92 @deftypefnx {} {[@dots{}] =} qr (@dots{}, "matrix")
93 @cindex QR factorization
94 Compute the QR@tie{}factorization of @var{A}, using standard @sc{lapack}
95 subroutines.
96 
97 The QR@tie{}factorization is
98 @tex
99 $QR = A$ where $Q$ is an orthogonal matrix and $R$ is upper triangular.
100 @end tex
101 @ifnottex
102 
103 @example
104 @var{Q} * @var{R} = @var{A}
105 @end example
106 
107 @noindent
108 where @var{Q} is an orthogonal matrix and @var{R} is upper triangular.
109 @end ifnottex
110 
111 For example, given the matrix @code{@var{A} = [1, 2; 3, 4]},
112 
113 @example
114 [@var{Q}, @var{R}] = qr (@var{A})
115 @end example
116 
117 @noindent
118 returns
119 
120 @example
121 @group
122 @var{Q} =
123 
124  -0.31623 -0.94868
125  -0.94868 0.31623
126 
127 @var{R} =
128 
129  -3.16228 -4.42719
130  0.00000 -0.63246
131 @end group
132 @end example
133 
134 @noindent
135 which multiplied together return the original matrix
136 
137 @example
138 @group
139 @var{Q} * @var{R}
140  @result{}
141  1.0000 2.0000
142  3.0000 4.0000
143 @end group
144 @end example
145 
146 If just a single return value is requested then it is either @var{R}, if
147 @var{A} is sparse, or @var{X}, such that @code{@var{R} = triu (@var{X})} if
148 @var{A} is full. (Note: unlike most commands, the single return value is not
149 the first return value when multiple values are requested.)
150 
151 If the matrix @var{A} is full, and a third output @var{P} is requested, then
152 @code{qr} calculates the permuted QR@tie{}factorization
153 @tex
154 $QR = AP$ where $Q$ is an orthogonal matrix, $R$ is upper triangular, and $P$
155 is a permutation matrix.
156 @end tex
157 @ifnottex
158 
159 @example
160 @var{Q} * @var{R} = @var{A} * @var{P}
161 @end example
162 
163 @noindent
164 where @var{Q} is an orthogonal matrix, @var{R} is upper triangular, and
165 @var{P} is a permutation matrix.
166 @end ifnottex
167 
168 The permuted QR@tie{}factorization has the additional property that the
169 diagonal entries of @var{R} are ordered by decreasing magnitude. In other
170 words, @code{abs (diag (@var{R}))} will be ordered from largest to smallest.
171 
172 For example, given the matrix @code{@var{A} = [1, 2; 3, 4]},
173 
174 @example
175 [@var{Q}, @var{R}, @var{P}] = qr (@var{A})
176 @end example
177 
178 @noindent
179 returns
180 
181 @example
182 @group
183 @var{Q} =
184 
185  -0.44721 -0.89443
186  -0.89443 0.44721
187 
188 @var{R} =
189 
190  -4.47214 -3.13050
191  0.00000 0.44721
192 
193 @var{P} =
194 
195  0 1
196  1 0
197 @end group
198 @end example
199 
200 If the input matrix @var{A} is sparse then the sparse QR@tie{}factorization
201 is computed using @sc{CSparse}. Because the matrix @var{Q} is, in general, a
202 full matrix, it is recommended to request only one return value @var{R}. In
203 that case, the computation avoids the construction of @var{Q} and returns
204 @var{R} such that @code{@var{R} = chol (@var{A}' * @var{A})}.
205 
206 If an additional matrix @var{B} is supplied and two return values are
207 requested, then @code{qr} returns @var{C}, where
208 @code{@var{C} = @var{Q}' * @var{B}}. This allows the least squares
209 approximation of @code{@var{A} \ @var{B}} to be calculated as
210 
211 @example
212 @group
213 [@var{C}, @var{R}] = qr (@var{A}, @var{B})
214 @var{x} = @var{R} \ @var{C}
215 @end group
216 @end example
217 
218 If the final argument is the string @qcode{"vector"} then @var{P} is a
219 permutation vector (of the columns of @var{A}) instead of a permutation matrix.
220 In this case, the defining relationship is
221 
222 @example
223 @var{Q} * @var{R} = @var{A}(:, @var{P})
224 @end example
225 
226 The default, however, is to return a permutation matrix and this may be
227 explicitly specified by using a final argument of @qcode{"matrix"}.
228 
229 If the final argument is the scalar 0 an @qcode{"economy"} factorization is
230 returned. When the original matrix @var{A} has size MxN and M > N then the
231 @qcode{"economy"} factorization will calculate just N rows in @var{R} and N
232 columns in @var{Q} and omit the zeros in @var{R}. If M @leq{} N there is no
233 difference between the economy and standard factorizations. When calculating
234 an @qcode{"economy"} factorization the output @var{P} is always a vector
235 rather than a matrix.
236 
237 Background: The QR factorization has applications in the solution of least
238 squares problems
239 @tex
240 $$
241 \min_x \left\Vert A x - b \right\Vert_2
242 $$
243 @end tex
244 @ifnottex
245 
246 @example
247 min norm (A*x - b)
248 @end example
249 
250 @end ifnottex
251 for overdetermined systems of equations (i.e.,
252 @tex
253 $A$
254 @end tex
255 @ifnottex
256 @var{A}
257 @end ifnottex
258 is a tall, thin matrix).
259 
260 The permuted QR@tie{}factorization
261 @code{[@var{Q}, @var{R}, @var{P}] = qr (@var{A})} allows the construction of an
262 orthogonal basis of @code{span (A)}.
263 
264 @seealso{chol, hess, lu, qz, schur, svd, qrupdate, qrinsert, qrdelete, qrshift}
265 @end deftypefn */)
266 {
267  int nargin = args.length ();
268 
270  print_usage ();
271 
273 
274  octave_value arg = args(0);
275 
276  bool economy = false;
277  bool is_cmplx = false;
278  bool have_b = 0;
279  bool vector_p = 0;
280 
281  if (arg.iscomplex ())
282  is_cmplx = true;
283  if (nargin > 1)
284  {
285  have_b = true;
286  if (args(nargin-1).is_scalar_type ())
287  {
288  int val = args(nargin-1).int_value ();
289  if (val == 0)
290  {
291  economy = true;
292  have_b = (nargin > 2);
293  }
294  else if (nargin == 3) // argument 3 should be 0 or a string
295  print_usage ();
296  }
297  else if (args(nargin-1).is_string ())
298  {
299  std::string str = args(nargin-1).string_value ();
300  if (str == "vector")
301  vector_p = true;
302  else if (str != "matrix")
303  error ("qr: type for P must be 'matrix' or 'vector', not %s",
304  str.c_str ());
305  have_b = (nargin > 2);
306  }
307  else if (! args(nargin-1).is_matrix_type ())
308  err_wrong_type_arg ("qr", args(nargin-1));
309  else if (nargin == 3) // should be caught by is_scalar_type or is_string
310  print_usage ();
311 
312  if (have_b && args(1).iscomplex ())
313  is_cmplx = true;
314  }
315 
316  if (arg.issparse ())
317  {
318  if (nargout > 2)
319  error ("qr: Permutation output is not supported for sparse input");
320 
321  if (is_cmplx)
322  {
324 
325  if (have_b)
326  {
327  retval = ovl (q.C (args(1).complex_matrix_value ()),
328  q.R (economy));
329  if (arg.rows () < arg.columns ())
330  warning ("qr: non minimum norm solution for under-determined "
331  "problem %dx%d", arg.rows (), arg.columns ());
332  }
333  else if (nargout > 1)
334  retval = ovl (q.Q (), q.R (economy));
335  else
336  retval = ovl (q.R (economy));
337  }
338  else
339  {
341 
342  if (have_b)
343  {
344  retval = ovl (q.C (args(1).matrix_value ()), q.R (economy));
345  if (arg.rows () < arg.columns ())
346  warning ("qr: non minimum norm solution for under-determined "
347  "problem %dx%d", arg.rows (), arg.columns ());
348  }
349  else if (nargout > 1)
350  retval = ovl (q.Q (), q.R (economy));
351  else
352  retval = ovl (q.R (economy));
353  }
354  }
355  else
356  {
357  if (arg.is_single_type ())
358  {
359  if (arg.isreal ())
360  {
362  = qr_type<FloatMatrix> (nargout, economy);
363 
365 
366  switch (nargout)
367  {
368  case 0:
369  case 1:
370  {
372  retval = ovl (fact.R ());
373  }
374  break;
375 
376  case 2:
377  {
379  retval = ovl (fact.Q (), get_qr_r (fact));
380  if (have_b)
381  {
382  if (is_cmplx)
383  retval(0) = fact.Q ().transpose ()
384  * args(1).float_complex_matrix_value ();
385  else
386  retval(0) = fact.Q ().transpose ()
387  * args(1).float_matrix_value ();
388  }
389  }
390  break;
391 
392  default:
393  {
395 
396  if (economy || vector_p)
397  retval = ovl (fact.Q (), get_qr_r (fact), fact.Pvec ());
398  else
399  retval = ovl (fact.Q (), get_qr_r (fact), fact.P ());
400  }
401  break;
402  }
403  }
404  else if (arg.iscomplex ())
405  {
407  = qr_type<FloatComplexMatrix> (nargout, economy);
408 
410 
411  switch (nargout)
412  {
413  case 0:
414  case 1:
415  {
417  retval = ovl (fact.R ());
418  }
419  break;
420 
421  case 2:
422  {
424  retval = ovl (fact.Q (), get_qr_r (fact));
425  if (have_b)
426  retval (0) = conj (fact.Q ().transpose ())
427  * args(1).float_complex_matrix_value ();
428  }
429  break;
430 
431  default:
432  {
434  if (economy || vector_p)
435  retval = ovl (fact.Q (), get_qr_r (fact), fact.Pvec ());
436  else
437  retval = ovl (fact.Q (), get_qr_r (fact), fact.P ());
438  }
439  break;
440  }
441  }
442  }
443  else
444  {
445  if (arg.isreal ())
446  {
448  = qr_type<Matrix> (nargout, economy);
449 
450  Matrix m = arg.matrix_value ();
451 
452  switch (nargout)
453  {
454  case 0:
455  case 1:
456  {
457  octave::math::qr<Matrix> fact (m, type);
458  retval = ovl (fact.R ());
459  }
460  break;
461 
462  case 2:
463  {
464  octave::math::qr<Matrix> fact (m, type);
465  retval = ovl (fact.Q (), get_qr_r (fact));
466  if (have_b)
467  {
468  if (is_cmplx)
469  retval(0) = fact.Q ().transpose ()
470  * args(1).complex_matrix_value ();
471  else
472  retval(0) = fact.Q ().transpose ()
473  * args(1).matrix_value ();
474  }
475  }
476  break;
477 
478  default:
479  {
481  if (economy || vector_p)
482  retval = ovl (fact.Q (), get_qr_r (fact), fact.Pvec ());
483  else
484  retval = ovl (fact.Q (), get_qr_r (fact), fact.P ());
485  }
486  break;
487  }
488  }
489  else if (arg.iscomplex ())
490  {
492  = qr_type<ComplexMatrix> (nargout, economy);
493 
495 
496  switch (nargout)
497  {
498  case 0:
499  case 1:
500  {
502  retval = ovl (fact.R ());
503  }
504  break;
505 
506  case 2:
507  {
509  retval = ovl (fact.Q (), get_qr_r (fact));
510  if (have_b)
511  retval (0) = conj (fact.Q ().transpose ())
512  * args(1).complex_matrix_value ();
513  }
514  break;
515 
516  default:
517  {
519  if (economy || vector_p)
520  retval = ovl (fact.Q (), get_qr_r (fact), fact.Pvec ());
521  else
522  retval = ovl (fact.Q (), get_qr_r (fact), fact.P ());
523  }
524  break;
525  }
526  }
527  else
528  err_wrong_type_arg ("qr", arg);
529  }
530  }
531 
532  return retval;
533 }
534 
535 /*
536 %!test
537 %! a = [0, 2, 1; 2, 1, 2];
538 %!
539 %! [q, r] = qr (a);
540 %! [qe, re] = qr (a, 0);
541 %!
542 %! assert (q * r, a, sqrt (eps));
543 %! assert (qe * re, a, sqrt (eps));
544 
545 %!test
546 %! a = [0, 2, 1; 2, 1, 2];
547 %!
548 %! [q, r] = qr (a);
549 %! [qe, re] = qr (a, 0);
550 %!
551 %! assert (q * r, a, sqrt (eps));
552 %! assert (qe * re, a, sqrt (eps));
553 
554 %!test
555 %! a = [0, 2, 1; 2, 1, 2];
556 %!
557 %! [q, r, p] = qr (a); # FIXME: not giving right dimensions.
558 %! [qe, re, pe] = qr (a, 0);
559 %!
560 %! assert (q * r, a * p, sqrt (eps));
561 %! assert (qe * re, a(:, pe), sqrt (eps));
562 
563 %!test
564 %! a = [0, 2; 2, 1; 1, 2];
565 %!
566 %! [q, r] = qr (a);
567 %! [qe, re] = qr (a, 0);
568 %!
569 %! assert (q * r, a, sqrt (eps));
570 %! assert (qe * re, a, sqrt (eps));
571 
572 %!test
573 %! a = [0, 2; 2, 1; 1, 2];
574 %!
575 %! [q, r, p] = qr (a);
576 %! [qe, re, pe] = qr (a, 0);
577 %!
578 %! assert (q * r, a * p, sqrt (eps));
579 %! assert (qe * re, a(:, pe), sqrt (eps));
580 
581 %!test
582 %! a = [0, 2, 1; 2, 1, 2; 3, 1, 2];
583 %! b = [1, 3, 2; 1, 1, 0; 3, 0, 2];
584 %!
585 %! [q, r] = qr (a);
586 %! [c, re] = qr (a, b);
587 %!
588 %! assert (r, re, sqrt (eps));
589 %! assert (q'*b, c, sqrt (eps));
590 
591 %!test
592 %! a = [0, 2, i; 2, 1, 2; 3, 1, 2];
593 %! b = [1, 3, 2; 1, i, 0; 3, 0, 2];
594 %!
595 %! [q, r] = qr (a);
596 %! [c, re] = qr (a, b);
597 %!
598 %! assert (r, re, sqrt (eps));
599 %! assert (q'*b, c, sqrt (eps));
600 
601 %!test
602 %! a = [0, 2, i; 2, 1, 2; 3, 1, 2];
603 %! b = [1, 3, 2; 1, 1, 0; 3, 0, 2];
604 %!
605 %! [q, r] = qr (a);
606 %! [c, re] = qr (a, b);
607 %!
608 %! assert (r, re, sqrt (eps));
609 %! assert (q'*b, c, sqrt (eps));
610 
611 %!test
612 %! a = [0, 2, 1; 2, 1, 2; 3, 1, 2];
613 %! b = [1, 3, 2; 1, i, 0; 3, 0, 2];
614 %!
615 %! [q, r] = qr (a);
616 %! [c, re] = qr (a, b);
617 %!
618 %! assert (r, re, sqrt (eps));
619 %! assert (q'*b, c, sqrt (eps));
620 
621 %!test
622 %! assert (qr (zeros (0, 0)), zeros (0, 0))
623 %! assert (qr (zeros (1, 0)), zeros (1, 0))
624 %! assert (qr (zeros (0, 1)), zeros (0, 1))
625 
626 %!error qr ()
627 %!error qr ([1, 2; 3, 4], 0, 2)
628 
629 %!function retval = __testqr (q, r, a, p)
630 %! tol = 100*eps (class (q));
631 %! retval = 0;
632 %! if (nargin == 3)
633 %! n1 = norm (q*r - a);
634 %! n2 = norm (q'*q - eye (columns (q)));
635 %! retval = (n1 < tol && n2 < tol);
636 %! else
637 %! n1 = norm (q'*q - eye (columns (q)));
638 %! retval = (n1 < tol);
639 %! if (isvector (p))
640 %! n2 = norm (q*r - a(:,p));
641 %! retval = (retval && n2 < tol);
642 %! else
643 %! n2 = norm (q*r - a*p);
644 %! retval = (retval && n2 < tol);
645 %! endif
646 %! endif
647 %!endfunction
648 
649 %!test
650 %! t = ones (24, 1);
651 %! j = 1;
652 %!
653 %! if (false) # eliminate big matrix tests
654 %! a = rand (5000, 20);
655 %! [q,r] = qr (a, 0); t(j++) = __testqr (q, r, a);
656 %! [q,r] = qr (a',0); t(j++) = __testqr (q, r, a');
657 %! [q,r,p] = qr (a, 0); t(j++) = __testqr (q, r, a, p);
658 %! [q,r,p] = qr (a',0); t(j++) = __testqr (q, r, a', p);
659 %!
660 %! a = a+1i*eps;
661 %! [q,r] = qr (a, 0); t(j++) = __testqr (q, r, a);
662 %! [q,r] = qr (a',0); t(j++) = __testqr (q, r, a');
663 %! [q,r,p] = qr (a, 0); t(j++) = __testqr (q, r, a, p);
664 %! [q,r,p] = qr (a',0); t(j++) = __testqr (q, r, a', p);
665 %! endif
666 %!
667 %! a = [ ones(1,15); sqrt(eps)*eye(15) ];
668 %! [q,r] = qr (a); t(j++) = __testqr (q, r, a);
669 %! [q,r] = qr (a'); t(j++) = __testqr (q, r, a');
670 %! [q,r,p] = qr (a); t(j++) = __testqr (q, r, a, p);
671 %! [q,r,p] = qr (a'); t(j++) = __testqr (q, r, a', p);
672 %!
673 %! a = a+1i*eps;
674 %! [q,r] = qr (a); t(j++) = __testqr (q, r, a);
675 %! [q,r] = qr (a'); t(j++) = __testqr (q, r, a');
676 %! [q,r,p] = qr (a); t(j++) = __testqr (q, r, a, p);
677 %! [q,r,p] = qr (a'); t(j++) = __testqr (q, r, a', p);
678 %!
679 %! a = [ ones(1,15); sqrt(eps)*eye(15) ];
680 %! [q,r] = qr (a, 0); t(j++) = __testqr (q, r, a);
681 %! [q,r] = qr (a',0); t(j++) = __testqr (q, r, a');
682 %! [q,r,p] = qr (a, 0); t(j++) = __testqr (q, r, a, p);
683 %! [q,r,p] = qr (a',0); t(j++) = __testqr (q, r, a', p);
684 %!
685 %! a = a+1i*eps;
686 %! [q,r] = qr (a, 0); t(j++) = __testqr (q, r, a);
687 %! [q,r] = qr (a',0); t(j++) = __testqr (q, r, a');
688 %! [q,r,p] = qr (a, 0); t(j++) = __testqr (q, r, a, p);
689 %! [q,r,p] = qr (a',0); t(j++) = __testqr (q, r, a', p);
690 %!
691 %! a = [ 611 196 -192 407 -8 -52 -49 29
692 %! 196 899 113 -192 -71 -43 -8 -44
693 %! -192 113 899 196 61 49 8 52
694 %! 407 -192 196 611 8 44 59 -23
695 %! -8 -71 61 8 411 -599 208 208
696 %! -52 -43 49 44 -599 411 208 208
697 %! -49 -8 8 59 208 208 99 -911
698 %! 29 -44 52 -23 208 208 -911 99 ];
699 %! [q,r] = qr (a);
700 %!
701 %! assert (all (t) && norm (q*r - a) < 5000*eps);
702 
703 %!test
704 %! a = single ([0, 2, 1; 2, 1, 2]);
705 %!
706 %! [q, r] = qr (a);
707 %! [qe, re] = qr (a, 0);
708 %!
709 %! assert (q * r, a, sqrt (eps ("single")));
710 %! assert (qe * re, a, sqrt (eps ("single")));
711 
712 %!test
713 %! a = single ([0, 2, 1; 2, 1, 2]);
714 %!
715 %! [q, r, p] = qr (a); # FIXME: not giving right dimensions.
716 %! [qe, re, pe] = qr (a, 0);
717 %!
718 %! assert (q * r, a * p, sqrt (eps ("single")));
719 %! assert (qe * re, a(:, pe), sqrt (eps ("single")));
720 
721 %!test
722 %! a = single ([0, 2; 2, 1; 1, 2]);
723 %!
724 %! [q, r] = qr (a);
725 %! [qe, re] = qr (a, 0);
726 %!
727 %! assert (q * r, a, sqrt (eps ("single")));
728 %! assert (qe * re, a, sqrt (eps ("single")));
729 
730 %!test
731 %! a = single ([0, 2; 2, 1; 1, 2]);
732 %!
733 %! [q, r, p] = qr (a);
734 %! [qe, re, pe] = qr (a, 0);
735 %!
736 %! assert (q * r, a * p, sqrt (eps ("single")));
737 %! assert (qe * re, a(:, pe), sqrt (eps ("single")));
738 
739 %!test
740 %! a = single([0, 2, 1; 2, 1, 2; 3, 1, 2]);
741 %! b = single([1, 3, 2; 1, 1, 0; 3, 0, 2]);
742 %!
743 %! [q, r] = qr (a);
744 %! [c, re] = qr (a, b);
745 %!
746 %! assert (r, re, sqrt (eps ("single")));
747 %! assert (q'*b, c, sqrt (eps ("single")));
748 
749 %!test
750 %! a = single([0, 2, i; 2, 1, 2; 3, 1, 2]);
751 %! b = single([1, 3, 2; 1, i, 0; 3, 0, 2]);
752 %!
753 %! [q, r] = qr (a);
754 %! [c, re] = qr (a, b);
755 %!
756 %! assert (r, re, sqrt (eps ("single")));
757 %! assert (q'*b, c, sqrt (eps ("single")));
758 
759 %!test
760 %! a = single([0, 2, i; 2, 1, 2; 3, 1, 2]);
761 %! b = single([1, 3, 2; 1, 1, 0; 3, 0, 2]);
762 %!
763 %! [q, r] = qr (a);
764 %! [c, re] = qr (a, b);
765 %!
766 %! assert (r, re, sqrt (eps));
767 %! assert (q'*b, c, sqrt (eps));
768 
769 %!test
770 %! a = single([0, 2, 1; 2, 1, 2; 3, 1, 2]);
771 %! b = single([1, 3, 2; 1, i, 0; 3, 0, 2]);
772 %!
773 %! [q, r] = qr (a);
774 %! [c, re] = qr (a, b);
775 %!
776 %! assert (r, re, sqrt (eps ("single")));
777 %! assert (q'*b, c, sqrt (eps ("single")));
778 
779 %!error qr ()
780 %!error qr ([1, 2; 3, 4], 0, 2)
781 
782 %!test
783 %! t = ones (24, 1);
784 %! j = 1;
785 %!
786 %! if (false) # eliminate big matrix tests
787 %! a = rand (5000,20);
788 %! [q,r] = qr (a, 0); t(j++) = __testqr (q, r, a);
789 %! [q,r] = qr (a',0); t(j++) = __testqr (q, r, a');
790 %! [q,r,p] = qr (a, 0); t(j++) = __testqr (q, r, a, p);
791 %! [q,r,p] = qr (a',0); t(j++) = __testqr (q, r, a', p);
792 %!
793 %! a = a+1i*eps ("single");
794 %! [q,r] = qr (a, 0); t(j++) = __testqr (q, r, a);
795 %! [q,r] = qr (a',0); t(j++) = __testqr (q, r, a');
796 %! [q,r,p] = qr (a, 0); t(j++) = __testqr (q, r, a, p);
797 %! [q,r,p] = qr (a',0); t(j++) = __testqr (q, r, a', p);
798 %! endif
799 %!
800 %! a = [ ones(1,15); sqrt(eps("single"))*eye(15) ];
801 %! [q,r] = qr (a); t(j++) = __testqr (q, r, a);
802 %! [q,r] = qr (a'); t(j++) = __testqr (q, r, a');
803 %! [q,r,p] = qr (a); t(j++) = __testqr (q, r, a, p);
804 %! [q,r,p] = qr (a'); t(j++) = __testqr (q, r, a', p);
805 %!
806 %! a = a+1i*eps ("single");
807 %! [q,r] = qr (a); t(j++) = __testqr (q, r, a);
808 %! [q,r] = qr (a'); t(j++) = __testqr (q, r, a');
809 %! [q,r,p] = qr (a); t(j++) = __testqr (q, r, a, p);
810 %! [q,r,p] = qr (a'); t(j++) = __testqr (q, r, a', p);
811 %!
812 %! a = [ ones(1,15); sqrt(eps("single"))*eye(15) ];
813 %! [q,r] = qr (a, 0); t(j++) = __testqr (q, r, a);
814 %! [q,r] = qr (a',0); t(j++) = __testqr (q, r, a');
815 %! [q,r,p] = qr (a, 0); t(j++) = __testqr (q, r, a, p);
816 %! [q,r,p] = qr (a',0); t(j++) = __testqr (q, r, a', p);
817 %!
818 %! a = a+1i*eps ("single");
819 %! [q,r] = qr (a, 0); t(j++) = __testqr (q, r, a);
820 %! [q,r] = qr (a',0); t(j++) = __testqr (q, r, a');
821 %! [q,r,p] = qr (a, 0); t(j++) = __testqr (q, r, a, p);
822 %! [q,r,p] = qr (a',0); t(j++) = __testqr (q, r, a',p);
823 %!
824 %! a = [ 611 196 -192 407 -8 -52 -49 29
825 %! 196 899 113 -192 -71 -43 -8 -44
826 %! -192 113 899 196 61 49 8 52
827 %! 407 -192 196 611 8 44 59 -23
828 %! -8 -71 61 8 411 -599 208 208
829 %! -52 -43 49 44 -599 411 208 208
830 %! -49 -8 8 59 208 208 99 -911
831 %! 29 -44 52 -23 208 208 -911 99 ];
832 %! [q,r] = qr (a);
833 %!
834 %! assert (all (t) && norm (q*r-a) < 5000*eps ("single"));
835 
836 ## The deactivated tests below can't be tested till rectangular back-subs is
837 ## implemented for sparse matrices.
838 
839 %!testif HAVE_CXSPARSE
840 %! n = 20; d = 0.2;
841 %! a = sprandn (n,n,d) + speye (n,n);
842 %! r = qr (a);
843 %! assert (r'*r, a'*a, 1e-10);
844 
845 %!testif HAVE_COLAMD
846 %! n = 20; d = 0.2;
847 %! a = sprandn (n,n,d) + speye (n,n);
848 %! q = symamd (a);
849 %! a = a(q,q);
850 %! r = qr (a);
851 %! assert (r'*r, a'*a, 1e-10);
852 
853 %!testif HAVE_CXSPARSE
854 %! n = 20; d = 0.2;
855 %! a = sprandn (n,n,d) + speye (n,n);
856 %! [c,r] = qr (a, ones (n,1));
857 %! assert (r\c, full (a)\ones (n,1), 10e-10);
858 
859 %!testif HAVE_CXSPARSE
860 %! n = 20; d = 0.2;
861 %! a = sprandn (n,n,d) + speye (n,n);
862 %! b = randn (n,2);
863 %! [c,r] = qr (a, b);
864 %! assert (r\c, full (a)\b, 10e-10);
865 
866 ## Test under-determined systems!!
867 %!#testif HAVE_CXSPARSE
868 %! n = 20; d = 0.2;
869 %! a = sprandn (n,n+1,d) + speye (n,n+1);
870 %! b = randn (n,2);
871 %! [c,r] = qr (a, b);
872 %! assert (r\c, full (a)\b, 10e-10);
873 
874 %!testif HAVE_CXSPARSE
875 %! n = 20; d = 0.2;
876 %! a = 1i*sprandn (n,n,d) + speye (n,n);
877 %! r = qr (a);
878 %! assert (r'*r,a'*a,1e-10);
879 
880 %!testif HAVE_COLAMD
881 %! n = 20; d = 0.2;
882 %! a = 1i*sprandn (n,n,d) + speye (n,n);
883 %! q = symamd (a);
884 %! a = a(q,q);
885 %! r = qr (a);
886 %! assert (r'*r, a'*a, 1e-10);
887 
888 %!testif HAVE_CXSPARSE
889 %! n = 20; d = 0.2;
890 %! a = 1i*sprandn (n,n,d) + speye (n,n);
891 %! [c,r] = qr (a, ones (n,1));
892 %! assert (r\c, full (a)\ones (n,1), 10e-10);
893 
894 %!testif HAVE_CXSPARSE
895 %! n = 20; d = 0.2;
896 %! a = 1i*sprandn (n,n,d) + speye (n,n);
897 %! b = randn (n,2);
898 %! [c,r] = qr (a, b);
899 %! assert (r\c, full (a)\b, 10e-10);
900 
901 ## Test under-determined systems!!
902 %!#testif HAVE_CXSPARSE
903 %! n = 20; d = 0.2;
904 %! a = 1i*sprandn (n,n+1,d) + speye (n,n+1);
905 %! b = randn (n,2);
906 %! [c,r] = qr (a, b);
907 %! assert (r\c, full (a)\b, 10e-10);
908 
909 */
910 
911 static
912 bool check_qr_dims (const octave_value& q, const octave_value& r,
913  bool allow_ecf = false)
914 {
915  octave_idx_type m = q.rows ();
916  octave_idx_type k = r.rows ();
917  octave_idx_type n = r.columns ();
918  return ((q.ndims () == 2 && r.ndims () == 2 && k == q.columns ())
919  && (m == k || (allow_ecf && k == n && k < m)));
920 }
921 
922 static
923 bool check_index (const octave_value& i, bool vector_allowed = false)
924 {
925  return ((i.isreal () || i.isinteger ())
926  && (i.is_scalar_type () || vector_allowed));
927 }
928 
929 DEFUN_DLD (qrupdate, args, ,
930  doc: /* -*- texinfo -*-
931 @deftypefn {} {[@var{Q1}, @var{R1}] =} qrupdate (@var{Q}, @var{R}, @var{u}, @var{v})
932 Update a QR factorization given update vectors or matrices.
933 
934 Given a QR@tie{}factorization of a real or complex matrix
935 @w{@var{A} = @var{Q}*@var{R}}, @var{Q}@tie{}unitary and
936 @var{R}@tie{}upper trapezoidal, return the QR@tie{}factorization of
937 @w{@var{A} + @var{u}*@var{v}'}, where @var{u} and @var{v} are column vectors
938 (rank-1 update) or matrices with equal number of columns
939 (rank-k update). Notice that the latter case is done as a sequence of
940 rank-1 updates; thus, for k large enough, it will be both faster and more
941 accurate to recompute the factorization from scratch.
942 
943 The QR@tie{}factorization supplied may be either full (Q is square) or
944 economized (R is square).
945 
946 @seealso{qr, qrinsert, qrdelete, qrshift}
947 @end deftypefn */)
948 {
950 
951  if (args.length () != 4)
952  print_usage ();
953 
954  octave_value argq = args(0);
955  octave_value argr = args(1);
956  octave_value argu = args(2);
957  octave_value argv = args(3);
958 
959  if (! argq.isnumeric () || ! argr.isnumeric ()
960  || ! argu.isnumeric () || ! argv.isnumeric ())
961  print_usage ();
962 
963  if (! check_qr_dims (argq, argr, true))
964  error ("qrupdate: Q and R dimensions don't match");
965 
966  if (argq.isreal () && argr.isreal () && argu.isreal ()
967  && argv.isreal ())
968  {
969  // all real case
970  if (argq.is_single_type () || argr.is_single_type ()
971  || argu.is_single_type () || argv.is_single_type ())
972  {
973  FloatMatrix Q = argq.float_matrix_value ();
974  FloatMatrix R = argr.float_matrix_value ();
975  FloatMatrix u = argu.float_matrix_value ();
976  FloatMatrix v = argv.float_matrix_value ();
977 
979  fact.update (u, v);
980 
981  retval = ovl (fact.Q (), get_qr_r (fact));
982  }
983  else
984  {
985  Matrix Q = argq.matrix_value ();
986  Matrix R = argr.matrix_value ();
987  Matrix u = argu.matrix_value ();
988  Matrix v = argv.matrix_value ();
989 
990  octave::math::qr<Matrix> fact (Q, R);
991  fact.update (u, v);
992 
993  retval = ovl (fact.Q (), get_qr_r (fact));
994  }
995  }
996  else
997  {
998  // complex case
999  if (argq.is_single_type () || argr.is_single_type ()
1000  || argu.is_single_type () || argv.is_single_type ())
1001  {
1005  FloatComplexMatrix v = argv.float_complex_matrix_value ();
1006 
1008  fact.update (u, v);
1009 
1010  retval = ovl (fact.Q (), get_qr_r (fact));
1011  }
1012  else
1013  {
1015  ComplexMatrix R = argr.complex_matrix_value ();
1017  ComplexMatrix v = argv.complex_matrix_value ();
1018 
1020  fact.update (u, v);
1021 
1022  retval = ovl (fact.Q (), get_qr_r (fact));
1023  }
1024  }
1025 
1026  return retval;
1027 }
1028 
1029 /*
1030 %!shared A, u, v, Ac, uc, vc
1031 %! A = [0.091364 0.613038 0.999083;
1032 %! 0.594638 0.425302 0.603537;
1033 %! 0.383594 0.291238 0.085574;
1034 %! 0.265712 0.268003 0.238409;
1035 %! 0.669966 0.743851 0.445057 ];
1036 %!
1037 %! u = [0.85082;
1038 %! 0.76426;
1039 %! 0.42883;
1040 %! 0.53010;
1041 %! 0.80683 ];
1042 %!
1043 %! v = [0.98810;
1044 %! 0.24295;
1045 %! 0.43167 ];
1046 %!
1047 %! Ac = [0.620405 + 0.956953i 0.480013 + 0.048806i 0.402627 + 0.338171i;
1048 %! 0.589077 + 0.658457i 0.013205 + 0.279323i 0.229284 + 0.721929i;
1049 %! 0.092758 + 0.345687i 0.928679 + 0.241052i 0.764536 + 0.832406i;
1050 %! 0.912098 + 0.721024i 0.049018 + 0.269452i 0.730029 + 0.796517i;
1051 %! 0.112849 + 0.603871i 0.486352 + 0.142337i 0.355646 + 0.151496i ];
1052 %!
1053 %! uc = [0.20351 + 0.05401i;
1054 %! 0.13141 + 0.43708i;
1055 %! 0.29808 + 0.08789i;
1056 %! 0.69821 + 0.38844i;
1057 %! 0.74871 + 0.25821i ];
1058 %!
1059 %! vc = [0.85839 + 0.29468i;
1060 %! 0.20820 + 0.93090i;
1061 %! 0.86184 + 0.34689i ];
1062 %!
1063 
1064 %!test
1065 %! [Q,R] = qr (A);
1066 %! [Q,R] = qrupdate (Q, R, u, v);
1067 %! assert (norm (vec (Q'*Q - eye (5)), Inf) < 1e1*eps);
1068 %! assert (norm (vec (triu (R)-R), Inf) == 0);
1069 %! assert (norm (vec (Q*R - A - u*v'), Inf) < norm (A)*1e1*eps);
1070 %!
1071 %!test
1072 %! [Q,R] = qr (Ac);
1073 %! [Q,R] = qrupdate (Q, R, uc, vc);
1074 %! assert (norm (vec (Q'*Q - eye (5)), Inf) < 1e1*eps);
1075 %! assert (norm (vec (triu (R)-R), Inf) == 0);
1076 %! assert (norm (vec (Q*R - Ac - uc*vc'), Inf) < norm (Ac)*1e1*eps);
1077 
1078 %!test
1079 %! [Q,R] = qr (single (A));
1080 %! [Q,R] = qrupdate (Q, R, single (u), single (v));
1081 %! assert (norm (vec (Q'*Q - eye (5,"single")), Inf) < 1e1*eps ("single"));
1082 %! assert (norm (vec (triu (R)-R), Inf) == 0);
1083 %! assert (norm (vec (Q*R - single (A) - single (u)*single (v)'), Inf) < norm (single (A))*1e1*eps ("single"));
1084 %!
1085 %!test
1086 %! [Q,R] = qr (single (Ac));
1087 %! [Q,R] = qrupdate (Q, R, single (uc), single (vc));
1088 %! assert (norm (vec (Q'*Q - eye (5,"single")), Inf) < 1e1*eps ("single"));
1089 %! assert (norm (vec (triu (R)-R), Inf) == 0);
1090 %! assert (norm (vec (Q*R - single (Ac) - single (uc)*single (vc)'), Inf) < norm (single (Ac))*1e1*eps ("single"));
1091 */
1092 
1093 DEFUN_DLD (qrinsert, args, ,
1094  doc: /* -*- texinfo -*-
1095 @deftypefn {} {[@var{Q1}, @var{R1}] =} qrinsert (@var{Q}, @var{R}, @var{j}, @var{x}, @var{orient})
1096 Update a QR factorization given a row or column to insert in the original factored matrix.
1097 
1098 
1099 Given a QR@tie{}factorization of a real or complex matrix
1100 @w{@var{A} = @var{Q}*@var{R}}, @var{Q}@tie{}unitary and
1101 @var{R}@tie{}upper trapezoidal, return the QR@tie{}factorization of
1102 @w{[A(:,1:j-1) x A(:,j:n)]}, where @var{u} is a column vector to be inserted
1103 into @var{A} (if @var{orient} is @qcode{"col"}), or the
1104 QR@tie{}factorization of @w{[A(1:j-1,:);x;A(:,j:n)]}, where @var{x} is a row
1105 vector to be inserted into @var{A} (if @var{orient} is @qcode{"row"}).
1106 
1107 The default value of @var{orient} is @qcode{"col"}. If @var{orient} is
1108 @qcode{"col"}, @var{u} may be a matrix and @var{j} an index vector
1109 resulting in the QR@tie{}factorization of a matrix @var{B} such that
1110 @w{B(:,@var{j})} gives @var{u} and @w{B(:,@var{j}) = []} gives @var{A}.
1111 Notice that the latter case is done as a sequence of k insertions;
1112 thus, for k large enough, it will be both faster and more accurate to
1113 recompute the factorization from scratch.
1114 
1115 If @var{orient} is @qcode{"col"}, the QR@tie{}factorization supplied may
1116 be either full (Q is square) or economized (R is square).
1117 
1118 If @var{orient} is @qcode{"row"}, full factorization is needed.
1119 @seealso{qr, qrupdate, qrdelete, qrshift}
1120 @end deftypefn */)
1121 {
1122  int nargin = args.length ();
1123 
1124  if (nargin < 4 || nargin > 5)
1125  print_usage ();
1126 
1127  octave_value argq = args(0);
1128  octave_value argr = args(1);
1129  octave_value argj = args(2);
1130  octave_value argx = args(3);
1131 
1132  if (! argq.isnumeric () || ! argr.isnumeric ()
1133  || ! argx.isnumeric ()
1134  || (nargin > 4 && ! args(4).is_string ()))
1135  print_usage ();
1136 
1137  std::string orient = (nargin < 5) ? "col" : args(4).string_value ();
1138  bool col = (orient == "col");
1139 
1140  if (! col && orient != "row")
1141  error (R"(qrinsert: ORIENT must be "col" or "row")");
1142 
1143  if (! check_qr_dims (argq, argr, col) || (! col && argx.rows () != 1))
1144  error ("qrinsert: dimension mismatch");
1145 
1146  if (! check_index (argj, col))
1147  error ("qrinsert: invalid index J");
1148 
1150 
1152 
1153  octave_idx_type one = 1;
1154 
1155  if (argq.isreal () && argr.isreal () && argx.isreal ())
1156  {
1157  // real case
1158  if (argq.is_single_type () || argr.is_single_type ()
1159  || argx.is_single_type ())
1160  {
1161  FloatMatrix Q = argq.float_matrix_value ();
1162  FloatMatrix R = argr.float_matrix_value ();
1163  FloatMatrix x = argx.float_matrix_value ();
1164 
1165  octave::math::qr<FloatMatrix> fact (Q, R);
1166 
1167  if (col)
1168  fact.insert_col (x, j-one);
1169  else
1170  fact.insert_row (x.row (0), j(0)-one);
1171 
1172  retval = ovl (fact.Q (), get_qr_r (fact));
1173  }
1174  else
1175  {
1176  Matrix Q = argq.matrix_value ();
1177  Matrix R = argr.matrix_value ();
1178  Matrix x = argx.matrix_value ();
1179 
1180  octave::math::qr<Matrix> fact (Q, R);
1181 
1182  if (col)
1183  fact.insert_col (x, j-one);
1184  else
1185  fact.insert_row (x.row (0), j(0)-one);
1186 
1187  retval = ovl (fact.Q (), get_qr_r (fact));
1188  }
1189  }
1190  else
1191  {
1192  // complex case
1193  if (argq.is_single_type () || argr.is_single_type ()
1194  || argx.is_single_type ())
1195  {
1198  FloatComplexMatrix R =
1202 
1204 
1205  if (col)
1206  fact.insert_col (x, j-one);
1207  else
1208  fact.insert_row (x.row (0), j(0)-one);
1209 
1210  retval = ovl (fact.Q (), get_qr_r (fact));
1211  }
1212  else
1213  {
1215  ComplexMatrix R = argr.complex_matrix_value ();
1217 
1219 
1220  if (col)
1221  fact.insert_col (x, j-one);
1222  else
1223  fact.insert_row (x.row (0), j(0)-one);
1224 
1225  retval = ovl (fact.Q (), get_qr_r (fact));
1226  }
1227  }
1228 
1229  return retval;
1230 }
1231 
1232 /*
1233 %!test
1234 %! [Q,R] = qr (A);
1235 %! [Q,R] = qrinsert (Q, R, 3, u);
1236 %! assert (norm (vec (Q'*Q - eye (5)), Inf) < 1e1*eps);
1237 %! assert (norm (vec (triu (R) - R), Inf) == 0);
1238 %! assert (norm (vec (Q*R - [A(:,1:2) u A(:,3)]), Inf) < norm (A)*1e1*eps);
1239 %!test
1240 %! [Q,R] = qr (Ac);
1241 %! [Q,R] = qrinsert (Q, R, 3, uc);
1242 %! assert (norm (vec (Q'*Q - eye (5)), Inf) < 1e1*eps);
1243 %! assert (norm (vec (triu (R) - R), Inf) == 0);
1244 %! assert (norm (vec (Q*R - [Ac(:,1:2) uc Ac(:,3)]), Inf) < norm (Ac)*1e1*eps);
1245 %!test
1246 %! x = [0.85082 0.76426 0.42883 ];
1247 %!
1248 %! [Q,R] = qr (A);
1249 %! [Q,R] = qrinsert (Q, R, 3, x, "row");
1250 %! assert (norm (vec (Q'*Q - eye (6)), Inf) < 1e1*eps);
1251 %! assert (norm (vec (triu (R) - R), Inf) == 0);
1252 %! assert (norm (vec (Q*R - [A(1:2,:);x;A(3:5,:)]), Inf) < norm (A)*1e1*eps);
1253 %!test
1254 %! x = [0.20351 + 0.05401i 0.13141 + 0.43708i 0.29808 + 0.08789i ];
1255 %!
1256 %! [Q,R] = qr (Ac);
1257 %! [Q,R] = qrinsert (Q, R, 3, x, "row");
1258 %! assert (norm (vec (Q'*Q - eye (6)), Inf) < 1e1*eps);
1259 %! assert (norm (vec (triu (R) - R), Inf) == 0);
1260 %! assert (norm (vec (Q*R - [Ac(1:2,:);x;Ac(3:5,:)]), Inf) < norm (Ac)*1e1*eps);
1261 
1262 %!test
1263 %! [Q,R] = qr (single (A));
1264 %! [Q,R] = qrinsert (Q, R, 3, single (u));
1265 %! assert (norm (vec (Q'*Q - eye (5,"single")), Inf) < 1e1*eps ("single"));
1266 %! assert (norm (vec (triu (R) - R), Inf) == 0);
1267 %! assert (norm (vec (Q*R - single ([A(:,1:2) u A(:,3)])), Inf) < norm (single (A))*1e1*eps ("single"));
1268 %!test
1269 %! [Q,R] = qr (single (Ac));
1270 %! [Q,R] = qrinsert (Q, R, 3, single (uc));
1271 %! assert (norm (vec (Q'*Q - eye (5,"single")), Inf) < 1e1*eps ("single"));
1272 %! assert (norm (vec (triu (R) - R), Inf) == 0);
1273 %! assert (norm (vec (Q*R - single ([Ac(:,1:2) uc Ac(:,3)])), Inf) < norm (single (Ac))*1e1*eps ("single"));
1274 %!test
1275 %! x = single ([0.85082 0.76426 0.42883 ]);
1276 %!
1277 %! [Q,R] = qr (single (A));
1278 %! [Q,R] = qrinsert (Q, R, 3, x, "row");
1279 %! assert (norm (vec (Q'*Q - eye (6,"single")), Inf) < 1e1*eps ("single"));
1280 %! assert (norm (vec (triu (R) - R), Inf) == 0);
1281 %! assert (norm (vec (Q*R - single ([A(1:2,:);x;A(3:5,:)])), Inf) < norm (single (A))*1e1*eps ("single"));
1282 %!test
1283 %! x = single ([0.20351 + 0.05401i 0.13141 + 0.43708i 0.29808 + 0.08789i ]);
1284 %!
1285 %! [Q,R] = qr (single (Ac));
1286 %! [Q,R] = qrinsert (Q, R, 3, x, "row");
1287 %! assert (norm (vec (Q'*Q - eye (6,"single")), Inf) < 1e1*eps ("single"));
1288 %! assert (norm (vec (triu (R) - R), Inf) == 0);
1289 %! assert (norm (vec (Q*R - single ([Ac(1:2,:);x;Ac(3:5,:)])), Inf) < norm (single (Ac))*1e1*eps ("single"));
1290 */
1291 
1292 DEFUN_DLD (qrdelete, args, ,
1293  doc: /* -*- texinfo -*-
1294 @deftypefn {} {[@var{Q1}, @var{R1}] =} qrdelete (@var{Q}, @var{R}, @var{j}, @var{orient})
1295 Update a QR factorization given a row or column to delete from the original factored matrix.
1296 
1297 Given a QR@tie{}factorization of a real or complex matrix
1298 @w{@var{A} = @var{Q}*@var{R}}, @var{Q}@tie{}unitary and
1299 @var{R}@tie{}upper trapezoidal, return the QR@tie{}factorization of
1300 @w{[A(:,1:j-1), U, A(:,j:n)]},
1301 where @var{u} is a column vector to be inserted into @var{A}
1302 (if @var{orient} is @qcode{"col"}),
1303 or the QR@tie{}factorization of @w{[A(1:j-1,:);X;A(:,j:n)]},
1304 where @var{x} is a row @var{orient} is @qcode{"row"}).
1305 The default value of @var{orient} is @qcode{"col"}.
1306 
1307 If @var{orient} is @qcode{"col"}, @var{j} may be an index vector
1308 resulting in the QR@tie{}factorization of a matrix @var{B} such that
1309 @w{A(:,@var{j}) = []} gives @var{B}. Notice that the latter case is done as
1310 a sequence of k deletions; thus, for k large enough, it will be both faster
1311 and more accurate to recompute the factorization from scratch.
1312 
1313 If @var{orient} is @qcode{"col"}, the QR@tie{}factorization supplied may
1314 be either full (Q is square) or economized (R is square).
1315 
1316 If @var{orient} is @qcode{"row"}, full factorization is needed.
1317 @seealso{qr, qrupdate, qrinsert, qrshift}
1318 @end deftypefn */)
1319 {
1320  int nargin = args.length ();
1321 
1322  if (nargin < 3 || nargin > 4)
1323  print_usage ();
1324 
1325  octave_value argq = args(0);
1326  octave_value argr = args(1);
1327  octave_value argj = args(2);
1328 
1329  if (! argq.isnumeric () || ! argr.isnumeric ()
1330  || (nargin > 3 && ! args(3).is_string ()))
1331  print_usage ();
1332 
1333  std::string orient = (nargin < 4) ? "col" : args(3).string_value ();
1334  bool col = orient == "col";
1335 
1336  if (! col && orient != "row")
1337  error (R"(qrdelete: ORIENT must be "col" or "row")");
1338 
1339  if (! check_qr_dims (argq, argr, col))
1340  error ("qrdelete: dimension mismatch");
1341 
1343  if (! check_index (argj, col))
1344  error ("qrdelete: invalid index J");
1345 
1347 
1348  octave_idx_type one = 1;
1349 
1350  if (argq.isreal () && argr.isreal ())
1351  {
1352  // real case
1353  if (argq.is_single_type () || argr.is_single_type ())
1354  {
1355  FloatMatrix Q = argq.float_matrix_value ();
1356  FloatMatrix R = argr.float_matrix_value ();
1357 
1358  octave::math::qr<FloatMatrix> fact (Q, R);
1359 
1360  if (col)
1361  fact.delete_col (j-one);
1362  else
1363  fact.delete_row (j(0)-one);
1364 
1365  retval = ovl (fact.Q (), get_qr_r (fact));
1366  }
1367  else
1368  {
1369  Matrix Q = argq.matrix_value ();
1370  Matrix R = argr.matrix_value ();
1371 
1372  octave::math::qr<Matrix> fact (Q, R);
1373 
1374  if (col)
1375  fact.delete_col (j-one);
1376  else
1377  fact.delete_row (j(0)-one);
1378 
1379  retval = ovl (fact.Q (), get_qr_r (fact));
1380  }
1381  }
1382  else
1383  {
1384  // complex case
1385  if (argq.is_single_type () || argr.is_single_type ())
1386  {
1389  FloatComplexMatrix R =
1391 
1393 
1394  if (col)
1395  fact.delete_col (j-one);
1396  else
1397  fact.delete_row (j(0)-one);
1398 
1399  retval = ovl (fact.Q (), get_qr_r (fact));
1400  }
1401  else
1402  {
1404  ComplexMatrix R = argr.complex_matrix_value ();
1405 
1407 
1408  if (col)
1409  fact.delete_col (j-one);
1410  else
1411  fact.delete_row (j(0)-one);
1412 
1413  retval = ovl (fact.Q (), get_qr_r (fact));
1414  }
1415  }
1416 
1417  return retval;
1418 }
1419 
1420 /*
1421 %!test
1422 %! AA = [0.091364 0.613038 0.027504 0.999083;
1423 %! 0.594638 0.425302 0.562834 0.603537;
1424 %! 0.383594 0.291238 0.742073 0.085574;
1425 %! 0.265712 0.268003 0.783553 0.238409;
1426 %! 0.669966 0.743851 0.457255 0.445057 ];
1427 %!
1428 %! [Q,R] = qr (AA);
1429 %! [Q,R] = qrdelete (Q, R, 3);
1430 %! assert (norm (vec (Q'*Q - eye (5)), Inf) < 16*eps);
1431 %! assert (norm (vec (triu (R) - R), Inf) == 0);
1432 %! assert (norm (vec (Q*R - [AA(:,1:2) AA(:,4)]), Inf) < norm (AA)*1e1*eps);
1433 %!
1434 %!test
1435 %! AA = [0.364554 + 0.993117i 0.669818 + 0.510234i 0.426568 + 0.041337i 0.847051 + 0.233291i;
1436 %! 0.049600 + 0.242783i 0.448946 + 0.484022i 0.141155 + 0.074420i 0.446746 + 0.392706i;
1437 %! 0.581922 + 0.657416i 0.581460 + 0.030016i 0.219909 + 0.447288i 0.201144 + 0.069132i;
1438 %! 0.694986 + 0.000571i 0.682327 + 0.841712i 0.807537 + 0.166086i 0.192767 + 0.358098i;
1439 %! 0.945002 + 0.066788i 0.350492 + 0.642638i 0.579629 + 0.048102i 0.600170 + 0.636938i ] * I;
1440 %!
1441 %! [Q,R] = qr (AA);
1442 %! [Q,R] = qrdelete (Q, R, 3);
1443 %! assert (norm (vec (Q'*Q - eye (5)), Inf) < 16*eps);
1444 %! assert (norm (vec (triu (R) - R), Inf) == 0);
1445 %! assert (norm (vec (Q*R - [AA(:,1:2) AA(:,4)]), Inf) < norm (AA)*1e1*eps);
1446 %!
1447 %!test
1448 %! AA = [0.091364 0.613038 0.027504 0.999083;
1449 %! 0.594638 0.425302 0.562834 0.603537;
1450 %! 0.383594 0.291238 0.742073 0.085574;
1451 %! 0.265712 0.268003 0.783553 0.238409;
1452 %! 0.669966 0.743851 0.457255 0.445057 ];
1453 %!
1454 %! [Q,R] = qr (AA);
1455 %! [Q,R] = qrdelete (Q, R, 3, "row");
1456 %! assert (norm (vec (Q'*Q - eye (4)), Inf) < 1e1*eps);
1457 %! assert (norm (vec (triu (R) - R), Inf) == 0);
1458 %! assert (norm (vec (Q*R - [AA(1:2,:);AA(4:5,:)]), Inf) < norm (AA)*1e1*eps);
1459 %!
1460 %!test
1461 %! AA = [0.364554 + 0.993117i 0.669818 + 0.510234i 0.426568 + 0.041337i 0.847051 + 0.233291i;
1462 %! 0.049600 + 0.242783i 0.448946 + 0.484022i 0.141155 + 0.074420i 0.446746 + 0.392706i;
1463 %! 0.581922 + 0.657416i 0.581460 + 0.030016i 0.219909 + 0.447288i 0.201144 + 0.069132i;
1464 %! 0.694986 + 0.000571i 0.682327 + 0.841712i 0.807537 + 0.166086i 0.192767 + 0.358098i;
1465 %! 0.945002 + 0.066788i 0.350492 + 0.642638i 0.579629 + 0.048102i 0.600170 + 0.636938i ] * I;
1466 %!
1467 %! [Q,R] = qr (AA);
1468 %! [Q,R] = qrdelete (Q, R, 3, "row");
1469 %! assert (norm (vec (Q'*Q - eye (4)), Inf) < 1e1*eps);
1470 %! assert (norm (vec (triu (R) - R), Inf) == 0);
1471 %! assert (norm (vec (Q*R - [AA(1:2,:);AA(4:5,:)]), Inf) < norm (AA)*1e1*eps);
1472 
1473 %!test
1474 %! AA = single ([0.091364 0.613038 0.027504 0.999083;
1475 %! 0.594638 0.425302 0.562834 0.603537;
1476 %! 0.383594 0.291238 0.742073 0.085574;
1477 %! 0.265712 0.268003 0.783553 0.238409;
1478 %! 0.669966 0.743851 0.457255 0.445057 ]);
1479 %!
1480 %! [Q,R] = qr (AA);
1481 %! [Q,R] = qrdelete (Q, R, 3);
1482 %! assert (norm (vec (Q'*Q - eye (5,"single")), Inf) < 1e1*eps ("single"));
1483 %! assert (norm (vec (triu (R) - R), Inf) == 0);
1484 %! assert (norm (vec (Q*R - [AA(:,1:2) AA(:,4)]), Inf) < norm (AA)*1e1*eps ("single"));
1485 %!
1486 %!test
1487 %! AA = single ([0.364554 + 0.993117i 0.669818 + 0.510234i 0.426568 + 0.041337i 0.847051 + 0.233291i;
1488 %! 0.049600 + 0.242783i 0.448946 + 0.484022i 0.141155 + 0.074420i 0.446746 + 0.392706i;
1489 %! 0.581922 + 0.657416i 0.581460 + 0.030016i 0.219909 + 0.447288i 0.201144 + 0.069132i;
1490 %! 0.694986 + 0.000571i 0.682327 + 0.841712i 0.807537 + 0.166086i 0.192767 + 0.358098i;
1491 %! 0.945002 + 0.066788i 0.350492 + 0.642638i 0.579629 + 0.048102i 0.600170 + 0.636938i ]) * I;
1492 %!
1493 %! [Q,R] = qr (AA);
1494 %! [Q,R] = qrdelete (Q, R, 3);
1495 %! assert (norm (vec (Q'*Q - eye (5,"single")), Inf) < 1e1*eps ("single"));
1496 %! assert (norm (vec (triu (R) - R), Inf) == 0);
1497 %! assert (norm (vec (Q*R - [AA(:,1:2) AA(:,4)]), Inf) < norm (AA)*1e1*eps ("single"));
1498 %!
1499 %!test
1500 %! AA = single ([0.091364 0.613038 0.027504 0.999083;
1501 %! 0.594638 0.425302 0.562834 0.603537;
1502 %! 0.383594 0.291238 0.742073 0.085574;
1503 %! 0.265712 0.268003 0.783553 0.238409;
1504 %! 0.669966 0.743851 0.457255 0.445057 ]);
1505 %!
1506 %! [Q,R] = qr (AA);
1507 %! [Q,R] = qrdelete (Q, R, 3, "row");
1508 %! assert (norm (vec (Q'*Q - eye (4,"single")), Inf) < 1.5e1*eps ("single"));
1509 %! assert (norm (vec (triu (R) - R), Inf) == 0);
1510 %! assert (norm (vec (Q*R - [AA(1:2,:);AA(4:5,:)]), Inf) < norm (AA)*1e1*eps ("single"));
1511 %!testif HAVE_QRUPDATE
1512 %! ## Same test as above but with more precicision
1513 %! AA = single ([0.091364 0.613038 0.027504 0.999083;
1514 %! 0.594638 0.425302 0.562834 0.603537;
1515 %! 0.383594 0.291238 0.742073 0.085574;
1516 %! 0.265712 0.268003 0.783553 0.238409;
1517 %! 0.669966 0.743851 0.457255 0.445057 ]);
1518 %!
1519 %! [Q,R] = qr (AA);
1520 %! [Q,R] = qrdelete (Q, R, 3, "row");
1521 %! assert (norm (vec (Q'*Q - eye (4,"single")), Inf) < 1e1*eps ("single"));
1522 %! assert (norm (vec (triu (R) - R), Inf) == 0);
1523 %! assert (norm (vec (Q*R - [AA(1:2,:);AA(4:5,:)]), Inf) < norm (AA)*1e1*eps ("single"));
1524 %!
1525 %!test
1526 %! AA = single ([0.364554 + 0.993117i 0.669818 + 0.510234i 0.426568 + 0.041337i 0.847051 + 0.233291i;
1527 %! 0.049600 + 0.242783i 0.448946 + 0.484022i 0.141155 + 0.074420i 0.446746 + 0.392706i;
1528 %! 0.581922 + 0.657416i 0.581460 + 0.030016i 0.219909 + 0.447288i 0.201144 + 0.069132i;
1529 %! 0.694986 + 0.000571i 0.682327 + 0.841712i 0.807537 + 0.166086i 0.192767 + 0.358098i;
1530 %! 0.945002 + 0.066788i 0.350492 + 0.642638i 0.579629 + 0.048102i 0.600170 + 0.636938i ]) * I;
1531 %!
1532 %! [Q,R] = qr (AA);
1533 %! [Q,R] = qrdelete (Q, R, 3, "row");
1534 %! assert (norm (vec (Q'*Q - eye (4,"single")), Inf) < 1e1*eps ("single"));
1535 %! assert (norm (vec (triu (R) - R), Inf) == 0);
1536 %! assert (norm (vec (Q*R - [AA(1:2,:);AA(4:5,:)]), Inf) < norm (AA)*1e1*eps ("single"));
1537 */
1538 
1539 DEFUN_DLD (qrshift, args, ,
1540  doc: /* -*- texinfo -*-
1541 @deftypefn {} {[@var{Q1}, @var{R1}] =} qrshift (@var{Q}, @var{R}, @var{i}, @var{j})
1542 Update a QR factorization given a range of columns to shift in the original factored matrix.
1543 
1544 Given a QR@tie{}factorization of a real or complex matrix
1545 @w{@var{A} = @var{Q}*@var{R}}, @var{Q}@tie{}unitary and
1546 @var{R}@tie{}upper trapezoidal, return the QR@tie{}factorization
1547 of @w{@var{A}(:,p)}, where @w{p} is the permutation @*
1548 @code{p = [1:i-1, shift(i:j, 1), j+1:n]} if @w{@var{i} < @var{j}} @*
1549  or @*
1550 @code{p = [1:j-1, shift(j:i,-1), i+1:n]} if @w{@var{j} < @var{i}}. @*
1551 
1552 @seealso{qr, qrupdate, qrinsert, qrdelete}
1553 @end deftypefn */)
1554 {
1555  if (args.length () != 4)
1556  print_usage ();
1557 
1558  octave_value argq = args(0);
1559  octave_value argr = args(1);
1560  octave_value argi = args(2);
1561  octave_value argj = args(3);
1562 
1563  if (! argq.isnumeric () || ! argr.isnumeric ())
1564  print_usage ();
1565 
1566  if (! check_qr_dims (argq, argr, true))
1567  error ("qrshift: dimensions mismatch");
1568 
1569  octave_idx_type i = argi.idx_type_value ();
1570  octave_idx_type j = argj.idx_type_value ();
1571 
1572  if (! check_index (argi) || ! check_index (argj))
1573  error ("qrshift: invalid index I or J");
1574 
1576 
1577  if (argq.isreal () && argr.isreal ())
1578  {
1579  // all real case
1580  if (argq.is_single_type ()
1581  && argr.is_single_type ())
1582  {
1583  FloatMatrix Q = argq.float_matrix_value ();
1584  FloatMatrix R = argr.float_matrix_value ();
1585 
1586  octave::math::qr<FloatMatrix> fact (Q, R);
1587  fact.shift_cols (i-1, j-1);
1588 
1589  retval = ovl (fact.Q (), get_qr_r (fact));
1590  }
1591  else
1592  {
1593  Matrix Q = argq.matrix_value ();
1594  Matrix R = argr.matrix_value ();
1595 
1596  octave::math::qr<Matrix> fact (Q, R);
1597  fact.shift_cols (i-1, j-1);
1598 
1599  retval = ovl (fact.Q (), get_qr_r (fact));
1600  }
1601  }
1602  else
1603  {
1604  // complex case
1605  if (argq.is_single_type ()
1606  && argr.is_single_type ())
1607  {
1610 
1612  fact.shift_cols (i-1, j-1);
1613 
1614  retval = ovl (fact.Q (), get_qr_r (fact));
1615  }
1616  else
1617  {
1619  ComplexMatrix R = argr.complex_matrix_value ();
1620 
1622  fact.shift_cols (i-1, j-1);
1623 
1624  retval = ovl (fact.Q (), get_qr_r (fact));
1625  }
1626  }
1627 
1628  return retval;
1629 }
1630 
1631 /*
1632 %!test
1633 %! AA = A.';
1634 %! i = 2; j = 4; p = [1:i-1, shift(i:j,-1), j+1:5];
1635 %!
1636 %! [Q,R] = qr (AA);
1637 %! [Q,R] = qrshift (Q, R, i, j);
1638 %! assert (norm (vec (Q'*Q - eye (3)), Inf) < 1e1*eps);
1639 %! assert (norm (vec (triu (R) - R), Inf) == 0);
1640 %! assert (norm (vec (Q*R - AA(:,p)), Inf) < norm (AA)*1e1*eps);
1641 %!
1642 %! j = 2; i = 4; p = [1:j-1, shift(j:i,+1), i+1:5];
1643 %!
1644 %! [Q,R] = qr (AA);
1645 %! [Q,R] = qrshift (Q, R, i, j);
1646 %! assert (norm (vec (Q'*Q - eye (3)), Inf) < 1e1*eps);
1647 %! assert (norm (vec (triu (R) - R), Inf) == 0);
1648 %! assert (norm (vec (Q*R - AA(:,p)), Inf) < norm (AA)*1e1*eps);
1649 %!
1650 %!test
1651 %! AA = Ac.';
1652 %! i = 2; j = 4; p = [1:i-1, shift(i:j,-1), j+1:5];
1653 %!
1654 %! [Q,R] = qr (AA);
1655 %! [Q,R] = qrshift (Q, R, i, j);
1656 %! assert (norm (vec (Q'*Q - eye (3)), Inf) < 1e1*eps);
1657 %! assert (norm (vec (triu (R) - R), Inf) == 0);
1658 %! assert (norm (vec (Q*R - AA(:,p)), Inf) < norm (AA)*1e1*eps);
1659 %!
1660 %! j = 2; i = 4; p = [1:j-1, shift(j:i,+1), i+1:5];
1661 %!
1662 %! [Q,R] = qr (AA);
1663 %! [Q,R] = qrshift (Q, R, i, j);
1664 %! assert (norm (vec (Q'*Q - eye (3)), Inf) < 1e1*eps);
1665 %! assert (norm (vec (triu (R) - R), Inf) == 0);
1666 %! assert (norm (vec (Q*R - AA(:,p)), Inf) < norm (AA)*1e1*eps);
1667 
1668 %!test
1669 %! AA = single (A).';
1670 %! i = 2; j = 4; p = [1:i-1, shift(i:j,-1), j+1:5];
1671 %!
1672 %! [Q,R] = qr (AA);
1673 %! [Q,R] = qrshift (Q, R, i, j);
1674 %! assert (norm (vec (Q'*Q - eye (3,"single")), Inf) < 1e1*eps ("single"));
1675 %! assert (norm (vec (triu (R) - R), Inf) == 0);
1676 %! assert (norm (vec (Q*R - AA(:,p)), Inf) < norm (AA)*1e1*eps ("single"));
1677 %!
1678 %! j = 2; i = 4; p = [1:j-1, shift(j:i,+1), i+1:5];
1679 %!
1680 %! [Q,R] = qr (AA);
1681 %! [Q,R] = qrshift (Q, R, i, j);
1682 %! assert (norm (vec (Q'*Q - eye (3,"single")), Inf) < 1e1*eps ("single"));
1683 %! assert (norm (vec (triu (R) - R), Inf) == 0);
1684 %! assert (norm (vec (Q*R - AA(:,p)), Inf) < norm (AA)*1e1*eps ("single"));
1685 %!
1686 %!test
1687 %! AA = single (Ac).';
1688 %! i = 2; j = 4; p = [1:i-1, shift(i:j,-1), j+1:5];
1689 %!
1690 %! [Q,R] = qr (AA);
1691 %! [Q,R] = qrshift (Q, R, i, j);
1692 %! assert (norm (vec (Q'*Q - eye (3,"single")), Inf) < 1e1*eps ("single"));
1693 %! assert (norm (vec (triu (R) - R), Inf) == 0);
1694 %! assert (norm (vec (Q*R - AA(:,p)), Inf) < norm (AA)*1e1*eps ("single"));
1695 %!
1696 %! j = 2; i = 4; p = [1:j-1, shift(j:i,+1), i+1:5];
1697 %!
1698 %! [Q,R] = qr (AA);
1699 %! [Q,R] = qrshift (Q, R, i, j);
1700 %! assert (norm (vec (Q'*Q - eye (3,"single")), Inf) < 1e1*eps ("single"));
1701 %! assert (norm (vec (triu (R) - R), Inf) == 0);
1702 %! assert (norm (vec (Q*R - AA(:,p)), Inf) < norm (AA)*1e1*eps ("single"));
1703 */
FloatComplexMatrix transpose(void) const
Definition: fCMatrix.h:173
octave_idx_type idx_type_value(bool req_int=false, bool frc_str_conv=false) const
PermMatrix P(void) const
Definition: qrp.h:67
OCTINTERP_API void print_usage(void)
Definition: defun.cc:54
identity matrix If supplied two scalar respectively For allows like xample val
Definition: data.cc:4986
static octave_value get_qr_r(const octave::math::qr< MT > &fact)
Definition: qr.cc:45
for large enough k
Definition: lu.cc:617
bool regular(void) const
Definition: qr.cc:88
void error(const char *fmt,...)
Definition: error.cc:578
u
Definition: lu.cc:138
FloatMatrix float_matrix_value(bool frc_str_conv=false) const
Definition: ov.h:837
int ndims(void) const
Definition: ov.h:478
ComplexMatrix transpose(void) const
Definition: CMatrix.h:168
octave_value arg
Definition: pr-output.cc:3244
string_vector argv
Definition: load-save.cc:648
FloatComplexMatrix float_complex_matrix_value(bool frc_str_conv=false) const
Definition: ov.h:856
Definition: mx-defs.h:79
Matrix transpose(void) const
Definition: dMatrix.h:132
ComplexColumnVector conj(const ComplexColumnVector &a)
Definition: CColVector.cc:215
OCTAVE_EXPORT octave_value_list return the number of command line arguments passed to Octave If called with the optional argument the function xample nargout(@histc)
Definition: ov-usr-fcn.cc:997
octave_idx_type columns(void) const
Definition: ov.h:474
static octave::math::qr< T >::type qr_type(int nargout, bool economy)
Definition: qr.cc:56
bool is_single_type(void) const
Definition: ov.h:651
std::string str
Definition: hash.cc:118
octave_idx_type rows(void) const
Definition: ov.h:472
bool issparse(void) const
Definition: ov.h:730
octave_value retval
Definition: data.cc:6246
Array< octave_idx_type > octave_idx_type_vector_value(bool req_int=false, bool frc_str_conv=false, bool frc_vec_conv=false) const
T Q(void) const
Definition: qr.h:78
idx type
Definition: ov.cc:3114
FloatMatrix transpose(void) const
Definition: fMatrix.h:136
Definition: dMatrix.h:36
void err_wrong_type_arg(const char *name, const char *s)
Definition: errwarn.cc:162
SparseComplexMatrix sparse_complex_matrix_value(bool frc_str_conv=false) const
Definition: ov.h:885
void warning(const char *fmt,...)
Definition: error.cc:801
bool isreal(void) const
Definition: ov.h:703
F77_RET_T const F77_INT const F77_INT const F77_INT F77_DBLE const F77_INT F77_DBLE const F77_INT F77_DBLE * Q
OCTAVE_EXPORT octave_value_list isa nd deftypefn *return ovl(args(0).isinteger())
RV_T Pvec(void) const
SparseMatrix sparse_matrix_value(bool frc_str_conv=false) const
Definition: ov.h:881
args.length() nargin
Definition: file-io.cc:589
bool iscomplex(void) const
Definition: ov.h:710
for i
Definition: data.cc:5264
#define DEFUN_DLD(name, args_name, nargout_name, doc)
Macro to define an at run time dynamically loadable builtin function.
Definition: defun-dld.h:58
ComplexMatrix complex_matrix_value(bool frc_str_conv=false) const
Definition: ov.h:852
T R(void) const
Definition: qr.h:80
If this string is the system will ring the terminal sometimes it is useful to be able to print the original representation of the string
Definition: utils.cc:888
bool isnumeric(void) const
Definition: ov.h:723
Matrix matrix_value(bool frc_str_conv=false) const
Definition: ov.h:834
F77_RET_T const F77_REAL const F77_REAL F77_REAL &F77_RET_T const F77_DBLE const F77_DBLE F77_DBLE &F77_RET_T const F77_DBLE F77_DBLE &F77_RET_T const F77_REAL F77_REAL &F77_RET_T const F77_DBLE * x