pinv.cc

Go to the documentation of this file.
00001 /*
00002 
00003 Copyright (C) 1996-2012 John W. Eaton
00004 
00005 This file is part of Octave.
00006 
00007 Octave is free software; you can redistribute it and/or modify it
00008 under the terms of the GNU General Public License as published by the
00009 Free Software Foundation; either version 3 of the License, or (at your
00010 option) any later version.
00011 
00012 Octave is distributed in the hope that it will be useful, but WITHOUT
00013 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
00014 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
00015 for more details.
00016 
00017 You should have received a copy of the GNU General Public License
00018 along with Octave; see the file COPYING.  If not, see
00019 <http://www.gnu.org/licenses/>.
00020 
00021 */
00022 
00023 #ifdef HAVE_CONFIG_H
00024 #include <config.h>
00025 #endif
00026 
00027 #include "defun-dld.h"
00028 #include "error.h"
00029 #include "gripes.h"
00030 #include "oct-obj.h"
00031 #include "utils.h"
00032 #include "ops.h"
00033 #include "ov-re-diag.h"
00034 #include "ov-cx-diag.h"
00035 #include "ov-flt-re-diag.h"
00036 #include "ov-flt-cx-diag.h"
00037 #include "ov-perm.h"
00038 
00039 DEFUN_DLD (pinv, args, ,
00040   "-*- texinfo -*-\n\
00041 @deftypefn  {Loadable Function} {} pinv (@var{x})\n\
00042 @deftypefnx {Loadable Function} {} pinv (@var{x}, @var{tol})\n\
00043 Return the pseudoinverse of @var{x}.  Singular values less than\n\
00044 @var{tol} are ignored.\n\
00045 \n\
00046 If the second argument is omitted, it is taken to be\n\
00047 \n\
00048 @example\n\
00049 tol = max (size (@var{x})) * sigma_max (@var{x}) * eps,\n\
00050 @end example\n\
00051 \n\
00052 @noindent\n\
00053 where @code{sigma_max (@var{x})} is the maximal singular value of @var{x}.\n\
00054 @end deftypefn")
00055 {
00056   octave_value retval;
00057 
00058   int nargin = args.length ();
00059 
00060   if (nargin < 1 || nargin > 2)
00061     {
00062       print_usage ();
00063       return retval;
00064     }
00065 
00066   octave_value arg = args(0);
00067 
00068   int arg_is_empty = empty_arg ("pinv", arg.rows (), arg.columns ());
00069 
00070   if (arg_is_empty < 0)
00071     return retval;
00072   else if (arg_is_empty > 0)
00073     return octave_value (Matrix ());
00074 
00075   bool isfloat = arg.is_single_type ();
00076 
00077   if (arg.is_diag_matrix ())
00078     {
00079       if (nargin == 2)
00080         warning ("pinv: tol is ignored for diagonal matrices");
00081 
00082       if (arg.is_complex_type ())
00083         {
00084           if (isfloat)
00085             retval = arg.float_complex_diag_matrix_value ().pseudo_inverse ();
00086           else
00087             retval = arg.complex_diag_matrix_value ().pseudo_inverse ();
00088         }
00089       else
00090         {
00091           if (isfloat)
00092             retval = arg.float_diag_matrix_value ().pseudo_inverse ();
00093           else
00094             retval = arg.diag_matrix_value ().pseudo_inverse ();
00095         }
00096     }
00097   else if (arg.is_perm_matrix ())
00098     {
00099       retval = arg.perm_matrix_value ().inverse ();
00100     }
00101   else if (isfloat)
00102     {
00103       float tol = 0.0;
00104       if (nargin == 2)
00105         tol = args(1).float_value ();
00106 
00107       if (error_state)
00108         return retval;
00109 
00110       if (tol < 0.0)
00111         {
00112           error ("pinv: TOL must be greater than zero");
00113           return retval;
00114         }
00115 
00116       if (arg.is_real_type ())
00117         {
00118           FloatMatrix m = arg.float_matrix_value ();
00119 
00120           if (! error_state)
00121             retval = m.pseudo_inverse (tol);
00122         }
00123       else if (arg.is_complex_type ())
00124         {
00125           FloatComplexMatrix m = arg.float_complex_matrix_value ();
00126 
00127           if (! error_state)
00128             retval = m.pseudo_inverse (tol);
00129         }
00130       else
00131         {
00132           gripe_wrong_type_arg ("pinv", arg);
00133         }
00134     }
00135   else
00136     {
00137       double tol = 0.0;
00138       if (nargin == 2)
00139         tol = args(1).double_value ();
00140 
00141       if (error_state)
00142         return retval;
00143 
00144       if (tol < 0.0)
00145         {
00146           error ("pinv: TOL must be greater than zero");
00147           return retval;
00148         }
00149 
00150       if (arg.is_real_type ())
00151         {
00152           Matrix m = arg.matrix_value ();
00153 
00154           if (! error_state)
00155             retval = m.pseudo_inverse (tol);
00156         }
00157       else if (arg.is_complex_type ())
00158         {
00159           ComplexMatrix m = arg.complex_matrix_value ();
00160 
00161           if (! error_state)
00162             retval = m.pseudo_inverse (tol);
00163         }
00164       else
00165         {
00166           gripe_wrong_type_arg ("pinv", arg);
00167         }
00168     }
00169 
00170   return retval;
00171 }
00172 
00173 /*
00174 %!shared a, b, tol, hitol, d, u, x, y
00175 %! a = reshape (rand*[1:16], 4, 4);   ## Rank 2 matrix
00176 %! b = pinv (a);
00177 %! tol = 4e-14;
00178 %! hitol = 40*sqrt (eps);
00179 %! d = diag ([rand, rand, hitol, hitol]);
00180 %! u = rand (4);                      ## Could be singular by freak accident
00181 %! x = inv (u)*d*u;
00182 %! y = pinv (x, sqrt (eps));
00183 %!
00184 %!assert (a*b*a, a, tol)
00185 %!assert (b*a*b, b, tol)
00186 %!assert ((b*a)', b*a, tol)
00187 %!assert ((a*b)', a*b, tol)
00188 %!assert (x*y*x, x, -hitol)
00189 %!assert (y*x*y, y, -hitol)
00190 %!assert ((x*y)', x*y, hitol)
00191 %!assert ((y*x)', y*x, hitol)
00192 */
 All Classes Files Functions Variables Typedefs Enumerations Enumerator Friends Defines