GNU Octave  4.2.1
A high-level interpreted language, primarily intended for numerical computations, mostly compatible with Matlab
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Pages
pinv.cc
Go to the documentation of this file.
1 /*
2 
3 Copyright (C) 1996-2017 John W. Eaton
4 
5 This file is part of Octave.
6 
7 Octave is free software; you can redistribute it and/or modify it
8 under the terms of the GNU General Public License as published by the
9 Free Software Foundation; either version 3 of the License, or (at your
10 option) any later version.
11 
12 Octave is distributed in the hope that it will be useful, but WITHOUT
13 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15 for more details.
16 
17 You should have received a copy of the GNU General Public License
18 along with Octave; see the file COPYING. If not, see
19 <http://www.gnu.org/licenses/>.
20 
21 */
22 
23 #if defined (HAVE_CONFIG_H)
24 # include "config.h"
25 #endif
26 
27 #include "defun.h"
28 #include "error.h"
29 #include "errwarn.h"
30 #include "ovl.h"
31 #include "ops.h"
32 #include "ov-re-diag.h"
33 #include "ov-cx-diag.h"
34 #include "ov-flt-re-diag.h"
35 #include "ov-flt-cx-diag.h"
36 #include "ov-perm.h"
37 
38 DEFUN (pinv, args, ,
39  doc: /* -*- texinfo -*-
40 @deftypefn {} {} pinv (@var{x})
41 @deftypefnx {} {} pinv (@var{x}, @var{tol})
42 Return the pseudoinverse of @var{x}.
43 
44 Singular values less than @var{tol} are ignored.
45 
46 If the second argument is omitted, it is taken to be
47 
48 @example
49 tol = max (size (@var{x})) * sigma_max (@var{x}) * eps,
50 @end example
51 
52 @noindent
53 where @code{sigma_max (@var{x})} is the maximal singular value of @var{x}.
54 @end deftypefn */)
55 {
56  int nargin = args.length ();
57 
58  if (nargin < 1 || nargin > 2)
59  print_usage ();
60 
61  octave_value arg = args(0);
62 
63  if (arg.is_empty ())
64  return ovl (Matrix ());
65 
67 
68  bool isfloat = arg.is_single_type ();
69 
70  if (arg.is_diag_matrix ())
71  {
72  if (isfloat)
73  {
74  float tol = 0.0;
75  if (nargin == 2)
76  tol = args(1).float_value ();
77 
78  if (tol < 0.0)
79  error ("pinv: TOL must be greater than zero");
80 
81  if (arg.is_real_type ())
82  retval = arg.float_diag_matrix_value ().pseudo_inverse (tol);
83  else
84  retval = arg.float_complex_diag_matrix_value ().pseudo_inverse (tol);
85  }
86  else
87  {
88  double tol = 0.0;
89  if (nargin == 2)
90  tol = args(1).double_value ();
91 
92  if (tol < 0.0)
93  error ("pinv: TOL must be greater than zero");
94 
95  if (arg.is_real_type ())
96  retval = arg.diag_matrix_value ().pseudo_inverse (tol);
97  else
98  retval = arg.complex_diag_matrix_value ().pseudo_inverse (tol);
99  }
100  }
101  else if (arg.is_perm_matrix ())
102  {
103  retval = arg.perm_matrix_value ().inverse ();
104  }
105  else if (isfloat)
106  {
107  float tol = 0.0;
108  if (nargin == 2)
109  tol = args(1).float_value ();
110 
111  if (tol < 0.0)
112  error ("pinv: TOL must be greater than zero");
113 
114  if (arg.is_real_type ())
115  {
117 
118  retval = m.pseudo_inverse (tol);
119  }
120  else if (arg.is_complex_type ())
121  {
123 
124  retval = m.pseudo_inverse (tol);
125  }
126  else
127  err_wrong_type_arg ("pinv", arg);
128  }
129  else
130  {
131  double tol = 0.0;
132  if (nargin == 2)
133  tol = args(1).double_value ();
134 
135  if (tol < 0.0)
136  error ("pinv: TOL must be greater than zero");
137 
138  if (arg.is_real_type ())
139  {
140  Matrix m = arg.matrix_value ();
141 
142  retval = m.pseudo_inverse (tol);
143  }
144  else if (arg.is_complex_type ())
145  {
147 
148  retval = m.pseudo_inverse (tol);
149  }
150  else
151  err_wrong_type_arg ("pinv", arg);
152  }
153 
154  return retval;
155 }
156 
157 /*
158 %!shared a, b, tol, hitol, d, u, x, y
159 %! a = reshape (rand*[1:16], 4, 4); # Rank 2 matrix
160 %! b = pinv (a);
161 %! tol = 4e-14;
162 %! hitol = 40*sqrt (eps);
163 %! d = diag ([rand, rand, hitol, hitol]);
164 %! u = rand (4); # Could be singular by freak accident
165 %! x = inv (u)*d*u;
166 %! y = pinv (x, sqrt (eps));
167 %!
168 %!assert (a*b*a, a, tol)
169 %!assert (b*a*b, b, tol)
170 %!assert ((b*a)', b*a, tol)
171 %!assert ((a*b)', a*b, tol)
172 %!assert (x*y*x, x, -hitol)
173 %!assert (y*x*y, y, -hitol)
174 %!assert ((x*y)', x*y, hitol)
175 %!assert ((y*x)', y*x, hitol)
176 
177 ## Clear shared variables
178 %!shared
179 
180 ## Test pinv for Diagonal matrices
181 %!test
182 %! x = diag ([3 2 1 0 -0.5]);
183 %! y = pinv (x);
184 %! assert (typeinfo (y)(1:8), "diagonal");
185 %! assert (isa (y, "double"));
186 %! assert (diag (y), [1/3, 1/2, 1, 0 1/-0.5]');
187 %! y = pinv (x, 1);
188 %! assert (diag (y), [1/3 1/2 1 0 0]');
189 %! y = pinv (x, 2);
190 %! assert (diag (y), [1/3 1/2 0 0 0]');
191 
192 */
FloatComplexDiagMatrix float_complex_diag_matrix_value(bool force=false) const
Definition: ov.h:854
bool is_real_type(void) const
Definition: ov.h:667
FloatComplexMatrix float_complex_matrix_value(bool frc_str_conv=false) const
Definition: ov.h:809
OCTAVE_EXPORT octave_value_list isa nd deftypefn *return ovl(args(0).is_integer_type())
OCTINTERP_API void print_usage(void)
Definition: defun.cc:52
#define DEFUN(name, args_name, nargout_name, doc)
Definition: defun.h:46
void error(const char *fmt,...)
Definition: error.cc:570
bool is_perm_matrix(void) const
Definition: ov.h:575
DiagMatrix pseudo_inverse(double tol=0.0) const
Definition: dDiagMatrix.cc:256
ComplexDiagMatrix pseudo_inverse(double tol=0.0) const
Definition: CDiagMatrix.cc:335
ComplexDiagMatrix complex_diag_matrix_value(bool force=false) const
Definition: ov.h:850
octave_value arg
Definition: pr-output.cc:3440
JNIEnv void * args
Definition: ov-java.cc:67
FloatComplexMatrix pseudo_inverse(float tol=0.0) const
Definition: fCMatrix.cc:938
FloatComplexDiagMatrix pseudo_inverse(float tol=0.0f) const
PermMatrix inverse(void) const
Definition: PermMatrix.cc:123
OCTAVE_EXPORT octave_value_list isfloat
Definition: data.cc:3327
FloatDiagMatrix float_diag_matrix_value(bool force=false) const
Definition: ov.h:847
nd deftypefn *octave_map m
Definition: ov-struct.cc:2058
int nargin
Definition: graphics.cc:10115
bool is_complex_type(void) const
Definition: ov.h:670
octave_value retval
Definition: data.cc:6294
Definition: dMatrix.h:37
Matrix matrix_value(bool frc_str_conv=false) const
Definition: ov.h:787
void err_wrong_type_arg(const char *name, const char *s)
Definition: errwarn.cc:156
DiagMatrix diag_matrix_value(bool force=false) const
Definition: ov.h:844
FloatDiagMatrix pseudo_inverse(float tol=0.0f) const
Definition: fDiagMatrix.cc:256
ComplexMatrix pseudo_inverse(double tol=0.0) const
Definition: CMatrix.cc:936
bool is_empty(void) const
Definition: ov.h:542
ComplexMatrix complex_matrix_value(bool frc_str_conv=false) const
Definition: ov.h:805
FloatMatrix float_matrix_value(bool frc_str_conv=false) const
Definition: ov.h:790
PermMatrix perm_matrix_value(void) const
Definition: ov.h:857
bool is_single_type(void) const
Definition: ov.h:627
bool is_diag_matrix(void) const
Definition: ov.h:572
Matrix pseudo_inverse(double tol=0.0) const
Definition: dMatrix.cc:643
FloatMatrix pseudo_inverse(float tol=0.0) const
Definition: fMatrix.cc:649