det.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 "DET.h"
00028 
00029 #include "defun-dld.h"
00030 #include "error.h"
00031 #include "gripes.h"
00032 #include "oct-obj.h"
00033 #include "utils.h"
00034 #include "ops.h"
00035 
00036 #include "ov-re-mat.h"
00037 #include "ov-cx-mat.h"
00038 #include "ov-flt-re-mat.h"
00039 #include "ov-flt-cx-mat.h"
00040 #include "ov-re-diag.h"
00041 #include "ov-cx-diag.h"
00042 #include "ov-flt-re-diag.h"
00043 #include "ov-flt-cx-diag.h"
00044 #include "ov-perm.h"
00045 
00046 #define MAYBE_CAST(VAR, CLASS) \
00047   const CLASS *VAR = arg.type_id () == CLASS::static_type_id () ? \
00048    dynamic_cast<const CLASS *> (&arg.get_rep ()) : 0
00049 
00050 DEFUN_DLD (det, args, nargout,
00051   "-*- texinfo -*-\n\
00052 @deftypefn  {Loadable Function} {} det (@var{A})\n\
00053 @deftypefnx {Loadable Function} {[@var{d}, @var{rcond}] =} det (@var{A})\n\
00054 Compute the determinant of @var{A}.\n\
00055 \n\
00056 Return an estimate of the reciprocal condition number if requested.\n\
00057 \n\
00058 Routines from @sc{lapack} are used for full matrices and code from\n\
00059 @sc{umfpack} is used for sparse matrices.\n\
00060 \n\
00061 The determinant should not be used to check a matrix for singularity.\n\
00062 For that, use any of the condition number functions: @code{cond},\n\
00063 @code{condest}, @code{rcond}.\n\
00064 @seealso{cond, condest, rcond}\n\
00065 @end deftypefn")
00066 {
00067   octave_value_list retval;
00068 
00069   int nargin = args.length ();
00070 
00071   if (nargin != 1)
00072     {
00073       print_usage ();
00074       return retval;
00075     }
00076 
00077   octave_value arg = args(0);
00078 
00079   octave_idx_type nr = arg.rows ();
00080   octave_idx_type nc = arg.columns ();
00081 
00082   if (nr == 0 && nc == 0)
00083     {
00084       retval(0) = 1.0;
00085       return retval;
00086     }
00087 
00088   int arg_is_empty = empty_arg ("det", nr, nc);
00089   if (arg_is_empty < 0)
00090     return retval;
00091   if (arg_is_empty > 0)
00092     return octave_value (Matrix (1, 1, 1.0));
00093 
00094 
00095   if (nr != nc)
00096     {
00097       gripe_square_matrix_required ("det");
00098       return retval;
00099     }
00100 
00101   bool isfloat = arg.is_single_type ();
00102 
00103   if (arg.is_diag_matrix ())
00104     {
00105       if (arg.is_complex_type ())
00106         {
00107           if (isfloat)
00108             {
00109               retval(0) = arg.float_complex_diag_matrix_value ().determinant ().value ();
00110               if (nargout > 1)
00111                 retval(1) = arg.float_complex_diag_matrix_value ().rcond ();
00112             }
00113           else
00114             {
00115               retval(0) = arg.complex_diag_matrix_value ().determinant ().value ();
00116               if (nargout > 1)
00117                 retval(1) = arg.complex_diag_matrix_value ().rcond ();
00118             }
00119         }
00120       else
00121         {
00122           if (isfloat)
00123             {
00124               retval(0) = arg.float_diag_matrix_value ().determinant ().value ();
00125               if (nargout > 1)
00126                 retval(1) = arg.float_diag_matrix_value ().rcond ();
00127             }
00128           else
00129             {
00130               retval(0) = arg.diag_matrix_value ().determinant ().value ();
00131               if (nargout > 1)
00132                 retval(1) = arg.diag_matrix_value ().rcond ();
00133             }
00134         }
00135     }
00136   else if (arg.is_perm_matrix ())
00137     {
00138       retval(0) = static_cast<double> (arg.perm_matrix_value ().determinant ());
00139       if (nargout > 1)
00140         retval(1) = 1.0;
00141     }
00142   else if (arg.is_single_type ())
00143     {
00144       if (arg.is_real_type ())
00145         {
00146           octave_idx_type info;
00147           float rcond = 0.0;
00148           // Always compute rcond, so we can detect numerically
00149           // singular matrices.
00150           FloatMatrix m = arg.float_matrix_value ();
00151           if (! error_state)
00152             {
00153               MAYBE_CAST (rep, octave_float_matrix);
00154               MatrixType mtype = rep ? rep -> matrix_type () : MatrixType ();
00155               FloatDET det = m.determinant (mtype, info, rcond);
00156               retval(1) = rcond;
00157               retval(0) = info == -1 ? static_cast<float>(0.0) : det.value ();
00158               if (rep) rep->matrix_type (mtype);
00159             }
00160         }
00161       else if (arg.is_complex_type ())
00162         {
00163           octave_idx_type info;
00164           float rcond = 0.0;
00165           // Always compute rcond, so we can detect numerically
00166           // singular matrices.
00167           FloatComplexMatrix m = arg.float_complex_matrix_value ();
00168           if (! error_state)
00169             {
00170               MAYBE_CAST (rep, octave_float_complex_matrix);
00171               MatrixType mtype = rep ? rep -> matrix_type () : MatrixType ();
00172               FloatComplexDET det = m.determinant (mtype, info, rcond);
00173               retval(1) = rcond;
00174               retval(0) = info == -1 ? FloatComplex (0.0) : det.value ();
00175               if (rep) rep->matrix_type (mtype);
00176             }
00177         }
00178     }
00179   else
00180     {
00181       if (arg.is_real_type ())
00182         {
00183           octave_idx_type info;
00184           double rcond = 0.0;
00185           // Always compute rcond, so we can detect numerically
00186           // singular matrices.
00187           if (arg.is_sparse_type ())
00188             {
00189               SparseMatrix m = arg.sparse_matrix_value ();
00190               if (! error_state)
00191                 {
00192                   DET det = m.determinant (info, rcond);
00193                   retval(1) = rcond;
00194                   retval(0) = info == -1 ? 0.0 : det.value ();
00195                 }
00196             }
00197           else
00198             {
00199               Matrix m = arg.matrix_value ();
00200               if (! error_state)
00201                 {
00202                   MAYBE_CAST (rep, octave_matrix);
00203                   MatrixType mtype = rep ? rep -> matrix_type () : MatrixType ();
00204                   DET det = m.determinant (mtype, info, rcond);
00205                   retval(1) = rcond;
00206                   retval(0) = info == -1 ? 0.0 : det.value ();
00207                   if (rep) rep->matrix_type (mtype);
00208                 }
00209             }
00210         }
00211       else if (arg.is_complex_type ())
00212         {
00213           octave_idx_type info;
00214           double rcond = 0.0;
00215           // Always compute rcond, so we can detect numerically
00216           // singular matrices.
00217           if (arg.is_sparse_type ())
00218             {
00219               SparseComplexMatrix m = arg.sparse_complex_matrix_value ();
00220               if (! error_state)
00221                 {
00222                   ComplexDET det = m.determinant (info, rcond);
00223                   retval(1) = rcond;
00224                   retval(0) = info == -1 ? Complex (0.0) : det.value ();
00225                 }
00226             }
00227           else
00228             {
00229               ComplexMatrix m = arg.complex_matrix_value ();
00230               if (! error_state)
00231                 {
00232                   MAYBE_CAST (rep, octave_complex_matrix);
00233                   MatrixType mtype = rep ? rep -> matrix_type () : MatrixType ();
00234                   ComplexDET det = m.determinant (mtype, info, rcond);
00235                   retval(1) = rcond;
00236                   retval(0) = info == -1 ? Complex (0.0) : det.value ();
00237                   if (rep) rep->matrix_type (mtype);
00238                 }
00239             }
00240         }
00241       else
00242         gripe_wrong_type_arg ("det", arg);
00243     }
00244   return retval;
00245 }
00246 
00247 /*
00248 
00249 %!assert(det ([1, 2; 3, 4]), -2, 10 * eps);
00250 %!assert(det (single([1, 2; 3, 4])), single(-2), 10 * eps ('single'));
00251 %!error <Invalid call to det> det ();
00252 %!error <Invalid call to det> det (1, 2);
00253 %!error det ([1, 2; 3, 4; 5, 6]);
00254 
00255 */
 All Classes Files Functions Variables Typedefs Enumerations Enumerator Friends Defines