@@ -115,10 +115,10 @@ DEFUN (qr, args, nargout,
115
115
@deftypefnx {} {@var{R} =} qr (@var{A}) # sparse A
116
116
@deftypefnx {} {@var{X} =} qr (@var{A}, @var{B}) # sparse A
117
117
@deftypefnx {} {[@var{C}, @var{R}] =} qr (@var{A}, @var{B})
118
- @deftypefnx {} {[@dots{}] =} qr (@dots{}, 0)
119
118
@deftypefnx {} {[@dots{}] =} qr (@dots{}, "econ")
120
119
@deftypefnx {} {[@dots{}] =} qr (@dots{}, "vector")
121
120
@deftypefnx {} {[@dots{}] =} qr (@dots{}, "matrix")
121
+ @deftypefnx {} {[@dots{}] =} qr (@dots{}, 0)
122
122
@cindex QR factorization
123
123
Compute the QR@tie{}factorization of @var{A}, using standard @sc{lapack}
124
124
subroutines.
@@ -238,7 +238,7 @@ recommended to request only one return value @var{R}. In that case, the
238
238
computation avoids the construction of @var{Q} and returns a sparse @var{R}
239
239
such that @code{@var{R} = chol (@var{A}' * @var{A})}.
240
240
241
- If @var{A} is dense, an additional matrix @var{B} is supplied and two
241
+ If @var{A} is dense, an additional input matrix @var{B} is supplied, and two
242
242
return values are requested, then @code{qr} returns @var{C}, where
243
243
@code{@var{C} = @var{Q}' * @var{B}}. This allows the least squares
244
244
approximation of @code{@var{A} \ @var{B}} to be calculated as
@@ -271,14 +271,17 @@ matrix. In this case, the defining relationship is:
271
271
The default, however, is to return a permutation matrix and this may be
272
272
explicitly specified by using a final argument of @qcode{"matrix"}.
273
273
274
- If the final argument is the scalar 0 or the string @qcode{"econ"}, an economy
274
+ When the optional argument is the string @qcode{"econ"}, an economy
275
275
factorization is returned. If the original matrix @var{A} has size
276
276
@nospell{MxN} and M > N, then the economy factorization will calculate just N
277
277
rows in @var{R} and N columns in @var{Q} and omit the zeros in @var{R}. If M
278
278
@leq{} N, there is no difference between the economy and standard
279
- factorizations. When calculating an economy factorization and @var{A} is
280
- dense, the output @var{P} is always a vector rather than a matrix. If @var{A}
281
- is sparse, output @var{P} is a sparse permutation matrix.
279
+ factorizations.
280
+
281
+ If the optional argument is the numeric value 0 then @code{qr} acts as if
282
+ the @qcode{"econ"} and @qcode{"vector"} arguments were both given.
283
+ @strong{Warning:} This syntax is accepted, but no longer recommended and may
284
+ be removed in the future. Use @qcode{"econ"} instead.
282
285
283
286
Background: The QR factorization has applications in the solution of least
284
287
squares problems
@@ -315,6 +318,9 @@ orthogonal basis of @code{span (A)}.
315
318
if (nargin < 1 || nargin > 3 )
316
319
print_usage ();
317
320
321
+ if (nargout > 3 )
322
+ error (" qr: too many output arguments" );
323
+
318
324
octave_value_list retval;
319
325
320
326
octave_value arg = args (0 );
@@ -335,6 +341,7 @@ orthogonal basis of @code{span (A)}.
335
341
if (val == 0 )
336
342
{
337
343
economy = true ;
344
+ vector_p = true ;
338
345
have_b = (nargin > 2 );
339
346
}
340
347
else if (nargin == 3 ) // argument 3 should be 0 or a string
@@ -343,32 +350,28 @@ orthogonal basis of @code{span (A)}.
343
350
else if (args (nargin-1 ).is_string ())
344
351
{
345
352
std::string str = args (nargin-1 ).string_value ();
346
- if (str == " vector" )
353
+ if (str == " econ" )
354
+ economy = true ;
355
+ else if (str == " vector" )
347
356
vector_p = true ;
348
- else if (str == " econ" )
349
- {
350
- economy = true ;
351
- have_b = (nargin > 2 );
352
- }
353
357
else if (str != " matrix" )
354
- error (" qr: option string must be 'econ' or 'matrix' or " \
355
- " 'vector', not \" %s\" " , str.c_str ());
358
+ error (" qr: option string must be 'econ' or 'matrix' or 'vector', not \" %s\" " , str.c_str ());
356
359
have_b = (nargin > 2 );
357
360
}
358
- else if (! args (nargin-1 ).is_matrix_type ())
361
+ else if (! args (nargin-1 ).isnumeric ())
359
362
err_wrong_type_arg (" qr" , args (nargin-1 ));
360
363
else if (nargin == 3 ) // should be caught by is_scalar_type or is_string
361
364
print_usage ();
362
365
366
+ if (have_b && ! args (1 ).isnumeric ())
367
+ print_usage ();
368
+
363
369
if (have_b && args (1 ).iscomplex ())
364
370
is_cmplx = true ;
365
371
}
366
372
367
373
if (arg.issparse ())
368
374
{
369
- if (nargout > 3 )
370
- error (" qr: too many output arguments" );
371
-
372
375
if (is_cmplx)
373
376
{
374
377
if (have_b && nargout == 1 )
@@ -399,8 +402,6 @@ orthogonal basis of @code{span (A)}.
399
402
<SparseMatrix, SparseComplexMatrix>
400
403
(arg.sparse_complex_matrix_value (),
401
404
args (1 ).sparse_matrix_value (), info));
402
- else
403
- error (" qr: b is not valid" );
404
405
}
405
406
else if (have_b && nargout == 2 )
406
407
{
@@ -415,7 +416,7 @@ orthogonal basis of @code{span (A)}.
415
416
q (arg.sparse_complex_matrix_value ());
416
417
if (vector_p)
417
418
retval = ovl (q.C (args (1 ).complex_matrix_value (), economy),
418
- q.R (economy), q.E ());
419
+ q.R (economy), q.E (). transpose () );
419
420
else
420
421
retval = ovl (q.C (args (1 ).complex_matrix_value (), economy),
421
422
q.R (economy), q.E_MAT ());
@@ -427,7 +428,8 @@ orthogonal basis of @code{span (A)}.
427
428
math::sparse_qr<SparseComplexMatrix>
428
429
q (arg.sparse_complex_matrix_value ());
429
430
if (vector_p)
430
- retval = ovl (q.Q (economy), q.R (economy), q.E ());
431
+ retval = ovl (q.Q (economy), q.R (economy),
432
+ q.E ().transpose ());
431
433
else
432
434
retval = ovl (q.Q (economy), q.R (economy),
433
435
q.E_MAT ());
@@ -472,8 +474,6 @@ orthogonal basis of @code{span (A)}.
472
474
(arg.sparse_matrix_value (),
473
475
args (1 ).sparse_complex_matrix_value (),
474
476
info));
475
- else
476
- error (" qr: b is not valid" );
477
477
}
478
478
else if (have_b && nargout == 2 )
479
479
{
@@ -488,7 +488,7 @@ orthogonal basis of @code{span (A)}.
488
488
q (arg.sparse_matrix_value ());
489
489
if (vector_p)
490
490
retval = ovl (q.C (args (1 ).matrix_value (), economy),
491
- q.R (economy), q.E ());
491
+ q.R (economy), q.E (). transpose () );
492
492
else
493
493
retval = ovl (q.C (args (1 ).matrix_value (), economy),
494
494
q.R (economy), q.E_MAT ());
@@ -501,7 +501,8 @@ orthogonal basis of @code{span (A)}.
501
501
math::sparse_qr<SparseMatrix>
502
502
q (arg.sparse_matrix_value ());
503
503
if (vector_p)
504
- retval = ovl (q.Q (economy), q.R (economy), q.E ());
504
+ retval = ovl (q.Q (economy), q.R (economy),
505
+ q.E ().transpose ());
505
506
else
506
507
retval = ovl (q.Q (economy), q.R (economy),
507
508
q.E_MAT ());
@@ -524,7 +525,7 @@ orthogonal basis of @code{span (A)}.
524
525
else
525
526
{
526
527
if (have_b && nargout > 2 )
527
- error (" qr: too many output arguments for dense A with B" );
528
+ error (" qr: too many output arguments when called with A and B" );
528
529
529
530
if (arg.is_single_type ())
530
531
{
@@ -565,7 +566,7 @@ orthogonal basis of @code{span (A)}.
565
566
{
566
567
math::qrp<FloatMatrix> fact (m, type);
567
568
568
- if (economy || vector_p)
569
+ if (vector_p)
569
570
retval = ovl (fact.Q (), get_qr_r (fact), fact.Pvec ());
570
571
else
571
572
retval = ovl (fact.Q (), get_qr_r (fact), fact.P ());
@@ -603,7 +604,7 @@ orthogonal basis of @code{span (A)}.
603
604
default :
604
605
{
605
606
math::qrp<FloatComplexMatrix> fact (m, type);
606
- if (economy || vector_p)
607
+ if (vector_p)
607
608
retval = ovl (fact.Q (), get_qr_r (fact), fact.Pvec ());
608
609
else
609
610
retval = ovl (fact.Q (), get_qr_r (fact), fact.P ());
@@ -616,8 +617,7 @@ orthogonal basis of @code{span (A)}.
616
617
{
617
618
if (arg.isreal ())
618
619
{
619
- math::qr<Matrix>::type type
620
- = qr_type<Matrix> (nargout, economy);
620
+ math::qr<Matrix>::type type = qr_type<Matrix> (nargout, economy);
621
621
622
622
Matrix m = arg.matrix_value ();
623
623
@@ -650,7 +650,7 @@ orthogonal basis of @code{span (A)}.
650
650
default :
651
651
{
652
652
math::qrp<Matrix> fact (m, type);
653
- if (economy || vector_p)
653
+ if (vector_p)
654
654
retval = ovl (fact.Q (), get_qr_r (fact), fact.Pvec ());
655
655
else
656
656
retval = ovl (fact.Q (), get_qr_r (fact), fact.P ());
@@ -688,7 +688,7 @@ orthogonal basis of @code{span (A)}.
688
688
default :
689
689
{
690
690
math::qrp<ComplexMatrix> fact (m, type);
691
- if (economy || vector_p)
691
+ if (vector_p)
692
692
retval = ovl (fact.Q (), get_qr_r (fact), fact.Pvec ());
693
693
else
694
694
retval = ovl (fact.Q (), get_qr_r (fact), fact.P ());
@@ -709,8 +709,8 @@ orthogonal basis of @code{span (A)}.
709
709
%! a = [0, 2, 1; 2, 1, 2];
710
710
%!
711
711
%! [q, r] = qr (a);
712
- %! [qe, re] = qr (a, 0 );
713
- %! [qe2, re2] = qr (a, "econ" );
712
+ %! [qe, re] = qr (a, "econ" );
713
+ %! [qe2, re2] = qr (a, 0 );
714
714
%!
715
715
%! assert (q * r, a, sqrt (eps));
716
716
%! assert (qe * re, a, sqrt (eps));
@@ -720,19 +720,19 @@ orthogonal basis of @code{span (A)}.
720
720
%! a = [0, 2, 1; 2, 1, 2];
721
721
%!
722
722
%! [q, r, p] = qr (a); # FIXME: not giving right dimensions.
723
- %! [qe, re, pe] = qr (a, 0 );
724
- %! [qe2, re2, pe2] = qr (a, "econ" );
723
+ %! [qe, re, pe] = qr (a, "econ" );
724
+ %! [qe2, re2, pe2] = qr (a, 0 );
725
725
%!
726
726
%! assert (q * r, a * p, sqrt (eps));
727
- %! assert (qe * re, a(:, pe) , sqrt (eps));
727
+ %! assert (qe * re, a * pe , sqrt (eps));
728
728
%! assert (qe2 * re2, a(:, pe2), sqrt (eps));
729
729
730
730
%!test
731
731
%! a = [0, 2; 2, 1; 1, 2];
732
732
%!
733
733
%! [q, r] = qr (a);
734
- %! [qe, re] = qr (a, 0 );
735
- %! [qe2, re2] = qr (a, "econ" );
734
+ %! [qe, re] = qr (a, "econ" );
735
+ %! [qe2, re2] = qr (a, 0 );
736
736
%!
737
737
%! assert (q * r, a, sqrt (eps));
738
738
%! assert (qe * re, a, sqrt (eps));
@@ -742,11 +742,11 @@ orthogonal basis of @code{span (A)}.
742
742
%! a = [0, 2; 2, 1; 1, 2];
743
743
%!
744
744
%! [q, r, p] = qr (a);
745
- %! [qe, re, pe] = qr (a, 0 );
746
- %! [qe2, re2, pe2] = qr (a, "econ" );
745
+ %! [qe, re, pe] = qr (a, "econ" );
746
+ %! [qe2, re2, pe2] = qr (a, 0 );
747
747
%!
748
748
%! assert (q * r, a * p, sqrt (eps));
749
- %! assert (qe * re, a(:, pe) , sqrt (eps));
749
+ %! assert (qe * re, a * pe , sqrt (eps));
750
750
%! assert (qe2 * re2, a(:, pe2), sqrt (eps));
751
751
752
752
%!test
@@ -800,14 +800,35 @@ orthogonal basis of @code{span (A)}.
800
800
%! assert (qr (sparse (1, 0)), sparse (1, 0))
801
801
%! assert (qr (sparse (0, 1)), sparse (0, 1))
802
802
803
- %!error qr ()
804
- %!error qr ([1, 2; 3, 4], 0, 2)
803
+ %!test <*66488>
804
+ %! ## Orientation of 'p' output
805
+ %! [q, r, p] = qr (eye (3));
806
+ %! assert (size (p), [3, 3]);
807
+ %! [q, r, p] = qr (speye (3));
808
+ %! assert (size (p), [3, 3]);
809
+ %! [q, r, p] = qr (eye (3), 'vector');
810
+ %! assert (size (p), [1, 3]);
811
+ %! [q, r, p] = qr (speye (3), 'vector');
812
+ %! assert (size (p), [1, 3]);
813
+ %! [q, r, p] = qr (eye (3), 'econ');
814
+ %! assert (size (p), [3, 3]);
815
+ %! [q, r, p] = qr (speye (3), 'econ');
816
+ %! assert (size (p), [3, 3]);
817
+ %! [q, r, p] = qr (eye (3), 0);
818
+ %! assert (size (p), [1, 3]);
819
+ %! [q, r, p] = qr (speye (3), 0);
820
+ %! assert (size (p), [1, 3]);
821
+
822
+ ## Test input validation
823
+ %!error <Invalid call> qr ()
824
+ %!error <Invalid call> qr (1,2,3,4)
825
+ %!error <too many output arguments> [a,b,c,d] = qr (1)
805
826
%!error <option string must be .*, not "foo"> qr (magic (3), "foo")
806
- %!error <option string must be .*, not "foo"> qr (magic (3), rand (3, 1), "foo")
807
- %!error <too many output arguments for dense A with B>
808
- %! [q, r, p] = qr (rand (3, 2), rand (3, 1));
809
- %!error <too many output arguments for dense A with B>
810
- %! [q, r, p] = qr (rand (3, 2), rand (3, 1), 0);
827
+ %!error <option string must be .*, not "foo"> qr (magic (3), ones (3, 1), "foo")
828
+ %!error <too many output arguments when called with A and B>
829
+ %! [q, r, p] = qr (ones (3, 2), ones (3, 1));
830
+ %!error <too many output arguments when called with A and B>
831
+ %! [q, r, p] = qr (ones (3, 2), ones (3, 1), 0);
811
832
812
833
%!function retval = __testqr (q, r, a, p)
813
834
%! tol = 100* eps (class (q));
0 commit comments