GNU Octave  9.1.0
A high-level interpreted language, primarily intended for numerical computations, mostly compatible with Matlab
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
det.cc
Go to the documentation of this file.
1 ////////////////////////////////////////////////////////////////////////
2 //
3 // Copyright (C) 1996-2024 The Octave Project Developers
4 //
5 // See the file COPYRIGHT.md in the top-level directory of this
6 // distribution or <https://octave.org/copyright/>.
7 //
8 // This file is part of Octave.
9 //
10 // Octave is free software: you can redistribute it and/or modify it
11 // under the terms of the GNU General Public License as published by
12 // the Free Software Foundation, either version 3 of the License, or
13 // (at your option) any later version.
14 //
15 // Octave is distributed in the hope that it will be useful, but
16 // WITHOUT ANY WARRANTY; without even the implied warranty of
17 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 // GNU General Public License for more details.
19 //
20 // You should have received a copy of the GNU General Public License
21 // along with Octave; see the file COPYING. If not, see
22 // <https://www.gnu.org/licenses/>.
23 //
24 ////////////////////////////////////////////////////////////////////////
25 
26 #if defined (HAVE_CONFIG_H)
27 # include "config.h"
28 #endif
29 
30 #include "DET.h"
31 
32 #include "defun.h"
33 #include "error.h"
34 #include "errwarn.h"
35 #include "ovl.h"
36 #include "ops.h"
37 
38 #include "ov-re-mat.h"
39 #include "ov-cx-mat.h"
40 #include "ov-flt-re-mat.h"
41 #include "ov-flt-cx-mat.h"
42 #include "ov-re-diag.h"
43 #include "ov-cx-diag.h"
44 #include "ov-flt-re-diag.h"
45 #include "ov-flt-cx-diag.h"
46 #include "ov-perm.h"
47 
49 
50 #define MAYBE_CAST(VAR, CLASS) \
51  const CLASS *VAR = (arg.type_id () == CLASS::static_type_id () \
52  ? dynamic_cast<const CLASS *> (&arg.get_rep ()) \
53  : nullptr)
54 
55 DEFUN (det, args, nargout,
56  doc: /* -*- texinfo -*-
57 @deftypefn {} {@var{d} =} det (@var{A})
58 @deftypefnx {} {[@var{d}, @var{rcond}] =} det (@var{A})
59 Compute the determinant of @var{A}.
60 
61 Return an estimate of the reciprocal condition number if requested.
62 
63 Programming Notes: Routines from @sc{lapack} are used for full matrices and
64 code from @sc{umfpack} is used for sparse matrices.
65 
66 The determinant should not be used to check a matrix for singularity.
67 For that, use any of the condition number functions: @code{cond},
68 @code{condest}, @code{rcond}.
69 @seealso{cond, condest, rcond}
70 @end deftypefn */)
71 {
72  if (args.length () != 1)
73  print_usage ();
74 
75  octave_value arg = args(0);
76 
77  if (arg.isempty ())
78  return ovl (1.0);
79 
80  if (arg.rows () != arg.columns ())
81  err_square_matrix_required ("det", "A");
82 
83  octave_value_list retval (2);
84 
85  bool isfloat = arg.is_single_type ();
86 
87  if (arg.is_diag_matrix ())
88  {
89  if (nargout <= 1)
90  retval.resize (1);
91 
92  if (arg.iscomplex ())
93  {
94  if (isfloat)
95  {
96  retval(0) = arg.float_complex_diag_matrix_value ()
97  .determinant ().value ();
98  if (nargout > 1)
99  retval(1) = arg.float_complex_diag_matrix_value ().rcond ();
100  }
101  else
102  {
103  retval(0) = arg.complex_diag_matrix_value ()
104  .determinant ().value ();
105  if (nargout > 1)
106  retval(1) = arg.complex_diag_matrix_value ().rcond ();
107  }
108  }
109  else
110  {
111  if (isfloat)
112  {
113  retval(0) = arg.float_diag_matrix_value ()
114  .determinant ().value ();
115  if (nargout > 1)
116  retval(1) = arg.float_diag_matrix_value ().rcond ();
117  }
118  else
119  {
120  retval(0) = arg.diag_matrix_value ().determinant ().value ();
121  if (nargout > 1)
122  retval(1) = arg.diag_matrix_value ().rcond ();
123  }
124  }
125  }
126  else if (arg.is_perm_matrix ())
127  {
128  if (nargout <= 1)
129  retval.resize (1);
130 
131  retval(0) = static_cast<double> (arg.perm_matrix_value ().determinant ());
132  if (nargout > 1)
133  retval(1) = 1.0;
134  }
135  else if (arg.is_single_type ())
136  {
137  if (arg.isreal ())
138  {
139  octave_idx_type info;
140  float rcond = 0.0;
141  // Always compute rcond, so we can detect singular matrices.
143 
145  MatrixType mtype = (rep ? rep -> matrix_type () : MatrixType ());
146  FloatDET det = m.determinant (mtype, info, rcond);
147  retval(0) = (info == -1 ? 0.0f : det.value ());
148  retval(1) = rcond;
149  if (rep)
150  rep->matrix_type (mtype);
151  }
152  else if (arg.iscomplex ())
153  {
154  octave_idx_type info;
155  float rcond = 0.0;
156  // Always compute rcond, so we can detect singular matrices.
158 
160  MatrixType mtype = (rep ? rep -> matrix_type () : MatrixType ());
161  FloatComplexDET det = m.determinant (mtype, info, rcond);
162  retval(0) = (info == -1 ? FloatComplex (0.0) : det.value ());
163  retval(1) = rcond;
164  if (rep)
165  rep->matrix_type (mtype);
166  }
167  }
168  else
169  {
170  if (arg.isreal ())
171  {
172  octave_idx_type info;
173  double rcond = 0.0;
174  // Always compute rcond, so we can detect singular matrices.
175  if (arg.issparse ())
176  {
178 
179  DET det = m.determinant (info, rcond);
180  retval(0) = (info == -1 ? 0.0 : det.value ());
181  retval(1) = rcond;
182  }
183  else
184  {
185  Matrix m = arg.matrix_value ();
186 
187  MAYBE_CAST (rep, octave_matrix);
188  MatrixType mtype = (rep ? rep -> matrix_type ()
189  : MatrixType ());
190  DET det = m.determinant (mtype, info, rcond);
191  retval(0) = (info == -1 ? 0.0 : det.value ());
192  retval(1) = rcond;
193  if (rep)
194  rep->matrix_type (mtype);
195  }
196  }
197  else if (arg.iscomplex ())
198  {
199  octave_idx_type info;
200  double rcond = 0.0;
201  // Always compute rcond, so we can detect singular matrices.
202  if (arg.issparse ())
203  {
205 
206  ComplexDET det = m.determinant (info, rcond);
207  retval(0) = (info == -1 ? Complex (0.0) : det.value ());
208  retval(1) = rcond;
209  }
210  else
211  {
213 
215  MatrixType mtype = (rep ? rep -> matrix_type ()
216  : MatrixType ());
217  ComplexDET det = m.determinant (mtype, info, rcond);
218  retval(0) = (info == -1 ? Complex (0.0) : det.value ());
219  retval(1) = rcond;
220  if (rep)
221  rep->matrix_type (mtype);
222  }
223  }
224  else
225  err_wrong_type_arg ("det", arg);
226  }
227 
228  return retval;
229 }
230 
231 /*
232 %!assert (det ([1, 2; 3, 4]), -2, 10*eps)
233 %!assert (det (single ([1, 2; 3, 4])), single (-2), 10* eps ("single"))
234 %!assert (det (eye (2000)), 1)
235 %!error det ()
236 %!error det (1, 2)
237 %!error <must be a square matrix> det ([1, 2; 3, 4; 5, 6])
238 */
239 
240 OCTAVE_END_NAMESPACE(octave)
ComplexDET determinant() const
Definition: CDiagMatrix.cc:493
double rcond() const
Definition: CDiagMatrix.cc:507
double rcond() const
Definition: dDiagMatrix.cc:345
DET determinant() const
Definition: dDiagMatrix.cc:331
FloatComplexDET determinant() const
float rcond() const
Definition: fDiagMatrix.cc:323
FloatDET determinant() const
Definition: fDiagMatrix.cc:309
Definition: dMatrix.h:42
octave_idx_type determinant() const
Definition: PermMatrix.cc:120
Definition: DET.h:39
T value() const
Definition: DET.h:65
void resize(octave_idx_type n, const octave_value &rfv=octave_value())
Definition: ovl.h:117
bool is_diag_matrix() const
Definition: ov.h:631
SparseMatrix sparse_matrix_value(bool frc_str_conv=false) const
Definition: ov.h:900
DiagMatrix diag_matrix_value(bool force=false) const
Definition: ov.h:910
octave_idx_type rows() const
Definition: ov.h:545
bool isreal() const
Definition: ov.h:738
FloatDiagMatrix float_diag_matrix_value(bool force=false) const
Definition: ov.h:913
ComplexMatrix complex_matrix_value(bool frc_str_conv=false) const
Definition: ov.h:871
FloatComplexDiagMatrix float_complex_diag_matrix_value(bool force=false) const
Definition: ov.h:920
bool is_perm_matrix() const
Definition: ov.h:634
bool is_single_type() const
Definition: ov.h:698
bool isempty() const
Definition: ov.h:601
bool issparse() const
Definition: ov.h:753
ComplexDiagMatrix complex_diag_matrix_value(bool force=false) const
Definition: ov.h:916
FloatMatrix float_matrix_value(bool frc_str_conv=false) const
Definition: ov.h:856
bool iscomplex() const
Definition: ov.h:741
octave_idx_type columns() const
Definition: ov.h:547
Matrix matrix_value(bool frc_str_conv=false) const
Definition: ov.h:853
FloatComplexMatrix float_complex_matrix_value(bool frc_str_conv=false) const
Definition: ov.h:875
PermMatrix perm_matrix_value() const
Definition: ov.h:923
SparseComplexMatrix sparse_complex_matrix_value(bool frc_str_conv=false) const
Definition: ov.h:904
OCTAVE_BEGIN_NAMESPACE(octave) static octave_value daspk_fcn
void print_usage(void)
Definition: defun-int.h:72
#define DEFUN(name, args_name, nargout_name, doc)
Macro to define a builtin function.
Definition: defun.h:56
#define MAYBE_CAST(VAR, CLASS)
Definition: det.cc:50
void err_square_matrix_required(const char *fcn, const char *name)
Definition: errwarn.cc:122
void err_wrong_type_arg(const char *name, const char *s)
Definition: errwarn.cc:166
T octave_idx_type m
Definition: mx-inlines.cc:781
std::complex< double > Complex
Definition: oct-cmplx.h:33
std::complex< float > FloatComplex
Definition: oct-cmplx.h:34
octave_value_list ovl(const OV_Args &... args)
Construct an octave_value_list with less typing.
Definition: ovl.h:219