GNU Octave  9.1.0
A high-level interpreted language, primarily intended for numerical computations, mostly compatible with Matlab
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