1 ## Copyright (C) 2000-2012 Paul Kienzle
3 ## This file is part of Octave.
5 ## Octave is free software; you can redistribute it and/or modify it
6 ## under the terms of the GNU General Public License as published by
7 ## the Free Software Foundation; either version 3 of the License, or (at
8 ## your option) any later version.
10 ## Octave is distributed in the hope that it will be useful, but
11 ## WITHOUT ANY WARRANTY; without even the implied warranty of
12 ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 ## General Public License for more details.
15 ## You should have received a copy of the GNU General Public License
16 ## along with Octave; see the file COPYING. If not, see
17 ## <http://www.gnu.org/licenses/>.
20 ## @deftypefn {Function File} {} rref (@var{A})
21 ## @deftypefnx {Function File} {} rref (@var{A}, @var{tol})
22 ## @deftypefnx {Function File} {[@var{r}, @var{k}] =} rref (@dots{})
23 ## Return the reduced row echelon form of @var{A}. @var{tol} defaults
24 ## to @code{eps * max (size (@var{A})) * norm (@var{A}, inf)}.
26 ## Called with two return arguments, @var{k} returns the vector of
27 ## "bound variables", which are those columns on which elimination
28 ## has been performed.
32 ## Author: Paul Kienzle <pkienzle@users.sf.net>
33 ## (based on an anonymous source from the public domain)
35 function [A, k] = rref (A, tol)
37 if (nargin < 1 || nargin > 2)
42 error ("rref: expecting matrix argument");
45 [rows, cols] = size (A);
48 if (isa (A, "single"))
49 tol = eps ("single") * max (rows, cols) * norm (A, inf ("single"));
51 tol = eps * max (rows, cols) * norm (A, inf);
55 used = zeros (1, cols);
59 [m, pivot] = max (abs (A(r:rows,c)));
60 pivot = r + pivot - 1;
63 ## Skip column c, making sure the approximately zero terms are
65 A (r:rows, c) = zeros (rows-r+1, 1);
67 ## keep track of bound variables
70 ## Swap current row and pivot row
71 A ([pivot, r], c:cols) = A ([r, pivot], c:cols);
73 ## Normalize pivot row
74 A (r, c:cols) = A (r, c:cols) / A (r, c);
76 ## Eliminate the current column
77 ridx = [1:r-1, r+1:rows];
78 A (ridx, c:cols) = A (ridx, c:cols) - A (ridx, c) * A(r, c:cols);
93 %! assert(r, [1], 2e-8);
94 %! assert(k, [1], 2e-8);
99 %! assert(rank(a), rank(r), 2e-8);
100 %! assert(r, eye(2), 2e-8);
101 %! assert(k == [1, 2] || k == [2, 1]);
105 %! a = [1 3; 4 5; 7 9];
107 %! assert(rank(a), rank(r), 2e-8);
108 %! assert(r, eye(3)(:,1:2), 2e-8);
109 %! assert(k, [1 2], 2e-8);
112 %! a = [1 2 3; 2 4 6; 7 2 0];
114 %! assert(rank(a), rank(r), 2e-8);
115 %! assert(r, [1 0 (3-7/2); 0 1 (7/4); 0 0 0], 2e-8);
116 %! assert(k, [1 2], 2e-8);
119 %! a = [1 2 1; 2 4 2.01; 2 4 2.1];
121 %! [r k] = rref(a, tol);
122 %! assert(rank(a, tol), rank(r, tol), 2e-8);
124 %! [r k] = rref(a, tol);
125 %! assert(rank(a, tol), rank(r, tol), 2e-8);