inv.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 "ops.h"
00032 #include "ov-re-diag.h"
00033 #include "ov-cx-diag.h"
00034 #include "ov-flt-re-diag.h"
00035 #include "ov-flt-cx-diag.h"
00036 #include "ov-perm.h"
00037 #include "utils.h"
00038 
00039 DEFUN_DLD (inv, args, nargout,
00040   "-*- texinfo -*-\n\
00041 @deftypefn  {Loadable Function} {@var{x} =} inv (@var{A})\n\
00042 @deftypefnx {Loadable Function} {[@var{x}, @var{rcond}] =} inv (@var{A})\n\
00043 Compute the inverse of the square matrix @var{A}.  Return an estimate\n\
00044 of the reciprocal condition number if requested, otherwise warn of an\n\
00045 ill-conditioned matrix if the reciprocal condition number is small.\n\
00046 \n\
00047 In general it is best to avoid calculating the inverse of a matrix\n\
00048 directly.  For example, it is both faster and more accurate to solve\n\
00049 systems of equations (@var{A}*@math{x} = @math{b}) with\n\
00050 @code{@var{y} = @var{A} \\ @math{b}}, rather than\n\
00051 @code{@var{y} = inv (@var{A}) * @math{b}}.\n\
00052 \n\
00053 If called with a sparse matrix, then in general @var{x} will be a full\n\
00054 matrix requiring significantly more storage.  Avoid forming the inverse\n\
00055 of a sparse matrix if possible.\n\
00056 @seealso{ldivide, rdivide}\n\
00057 @end deftypefn")
00058 {
00059   octave_value_list retval;
00060 
00061   int nargin = args.length ();
00062 
00063   if (nargin != 1)
00064     {
00065       print_usage ();
00066       return retval;
00067     }
00068 
00069   octave_value arg = args(0);
00070 
00071   octave_idx_type nr = arg.rows ();
00072   octave_idx_type nc = arg.columns ();
00073 
00074   int arg_is_empty = empty_arg ("inverse", nr, nc);
00075 
00076   if (arg_is_empty < 0)
00077     return retval;
00078   else if (arg_is_empty > 0)
00079     return octave_value (Matrix ());
00080 
00081   if (nr != nc)
00082     {
00083       gripe_square_matrix_required ("inverse");
00084       return retval;
00085     }
00086 
00087   octave_value result;
00088   octave_idx_type info;
00089   double rcond = 0.0;
00090   float frcond = 0.0;
00091   bool isfloat = arg.is_single_type ();
00092 
00093   if (arg.is_diag_matrix ())
00094     {
00095       rcond = 1.0;
00096       frcond = 1.0f;
00097       if (arg.is_complex_type ())
00098         {
00099           if (isfloat)
00100             {
00101               result = arg.float_complex_diag_matrix_value ().inverse (info);
00102               if (nargout > 1)
00103                 frcond = arg.float_complex_diag_matrix_value ().rcond ();
00104             }
00105           else
00106             {
00107               result = arg.complex_diag_matrix_value ().inverse (info);
00108               if (nargout > 1)
00109                 rcond = arg.complex_diag_matrix_value ().rcond ();
00110             }
00111         }
00112       else
00113         {
00114           if (isfloat)
00115             {
00116               result = arg.float_diag_matrix_value ().inverse (info);
00117               if (nargout > 1)
00118                 frcond = arg.float_diag_matrix_value ().rcond ();
00119             }
00120           else
00121             {
00122               result = arg.diag_matrix_value ().inverse (info);
00123               if (nargout > 1)
00124                 rcond = arg.diag_matrix_value ().rcond ();
00125             }
00126         }
00127     }
00128   else if (arg.is_perm_matrix ())
00129     {
00130       rcond = 1.0;
00131       info = 0;
00132       result = arg.perm_matrix_value ().inverse ();
00133     }
00134   else if (isfloat)
00135     {
00136       if (arg.is_real_type ())
00137         {
00138           FloatMatrix m = arg.float_matrix_value ();
00139           if (! error_state)
00140             {
00141               MatrixType mattyp = args(0).matrix_type ();
00142               result = m.inverse (mattyp, info, frcond, 1);
00143               args(0).matrix_type (mattyp);
00144             }
00145         }
00146       else if (arg.is_complex_type ())
00147         {
00148           FloatComplexMatrix m = arg.float_complex_matrix_value ();
00149           if (! error_state)
00150             {
00151               MatrixType mattyp = args(0).matrix_type ();
00152               result = m.inverse (mattyp, info, frcond, 1);
00153               args(0).matrix_type (mattyp);
00154             }
00155         }
00156     }
00157   else
00158     {
00159       if (arg.is_real_type ())
00160         {
00161           if (arg.is_sparse_type ())
00162             {
00163               SparseMatrix m = arg.sparse_matrix_value ();
00164               if (! error_state)
00165                 {
00166                   MatrixType mattyp = args(0).matrix_type ();
00167                   result = m.inverse (mattyp, info, rcond, 1);
00168                   args(0).matrix_type (mattyp);
00169                 }
00170             }
00171           else
00172             {
00173               Matrix m = arg.matrix_value ();
00174               if (! error_state)
00175                 {
00176                   MatrixType mattyp = args(0).matrix_type ();
00177                   result = m.inverse (mattyp, info, rcond, 1);
00178                   args(0).matrix_type (mattyp);
00179                 }
00180             }
00181         }
00182       else if (arg.is_complex_type ())
00183         {
00184           if (arg.is_sparse_type ())
00185             {
00186               SparseComplexMatrix m = arg.sparse_complex_matrix_value ();
00187               if (! error_state)
00188                 {
00189                   MatrixType mattyp = args(0).matrix_type ();
00190                   result = m.inverse (mattyp, info, rcond, 1);
00191                   args(0).matrix_type (mattyp);
00192                 }
00193             }
00194           else
00195             {
00196               ComplexMatrix m = arg.complex_matrix_value ();
00197               if (! error_state)
00198                 {
00199                   MatrixType mattyp = args(0).matrix_type ();
00200                   result = m.inverse (mattyp, info, rcond, 1);
00201                   args(0).matrix_type (mattyp);
00202                 }
00203             }
00204         }
00205       else
00206         gripe_wrong_type_arg ("inv", arg);
00207     }
00208 
00209   if (! error_state)
00210     {
00211       if (nargout > 1)
00212         retval(1) = isfloat ? octave_value (frcond) : octave_value (rcond);
00213 
00214       retval(0) = result;
00215 
00216       volatile double xrcond = rcond;
00217       xrcond += 1.0;
00218       if (nargout < 2 && (info == -1 || xrcond == 1.0))
00219         warning ("inverse: matrix singular to machine precision, rcond = %g",
00220                  rcond);
00221     }
00222 
00223   return retval;
00224 }
00225 
00226 /*
00227 
00228 %!assert(inv ([1, 2; 3, 4]), [-2, 1; 1.5, -0.5], sqrt (eps))
00229 %!assert(inv (single([1, 2; 3, 4])), single([-2, 1; 1.5, -0.5]), sqrt (eps ('single')))
00230 
00231 %!error <Invalid call to inv> inv ();
00232 %!error <Invalid call to inv> inv ([1, 2; 3, 4], 2);
00233 %!error inv ([1, 2; 3, 4; 5, 6]);
00234 
00235  */
00236 
00237 // FIXME -- this should really be done with an alias, but
00238 // alias_builtin() won't do the right thing if we are actually using
00239 // dynamic linking.
00240 
00241 DEFUN_DLD (inverse, args, nargout,
00242   "-*- texinfo -*-\n\
00243 @deftypefn  {Loadable Function} {@var{x} =} inverse (@var{A})\n\
00244 @deftypefnx {Loadable Function} {[@var{x}, @var{rcond}] =} inverse (@var{A})\n\
00245 Compute the inverse of the square matrix @var{A}.\n\
00246 \n\
00247 This is an alias for @code{inv}.\n\
00248 @seealso{inv}\n\
00249 @end deftypefn")
00250 {
00251   return Finv (args, nargout);
00252 }
 All Classes Files Functions Variables Typedefs Enumerations Enumerator Friends Defines