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
inv.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 "defun.h"
31 #include "error.h"
32 #include "errwarn.h"
33 #include "ovl.h"
34 #include "ops.h"
35 #include "ov-re-diag.h"
36 #include "ov-cx-diag.h"
37 #include "ov-flt-re-diag.h"
38 #include "ov-flt-cx-diag.h"
39 #include "ov-perm.h"
40 
42 
43 DEFUN (inv, args, nargout,
44  doc: /* -*- texinfo -*-
45 @deftypefn {} {@var{x} =} inv (@var{A})
46 @deftypefnx {} {[@var{x}, @var{rcond}] =} inv (@var{A})
47 @deftypefnx {} {[@dots{}] =} inverse (@dots{})
48 Compute the inverse of the square matrix @var{A}.
49 
50 Return an estimate of the reciprocal condition number if requested,
51 otherwise warn of an ill-conditioned matrix if the reciprocal condition
52 number is small.
53 
54 In general it is best to avoid calculating the inverse of a matrix directly.
55 For example, it is both faster and more accurate to solve systems of
56 equations (@var{A}*@math{x} = @math{b}) with
57 @code{@var{y} = @var{A} \ @math{b}}, rather than
58 @code{@var{y} = inv (@var{A}) * @math{b}}.
59 
60 If called with a sparse matrix, then in general @var{x} will be a full
61 matrix requiring significantly more storage. Avoid forming the inverse of a
62 sparse matrix if possible.
63 
64 Programming Note: @code{inverse} is an alias for @code{inv} and can be used
65 interchangeably.
66 @seealso{ldivide, rdivide, pinv}
67 @end deftypefn */)
68 {
69  if (args.length () != 1)
70  print_usage ();
71 
72  octave_value arg = args(0);
73 
74  if (! arg.isnumeric ())
75  err_wrong_type_arg ("inv", arg);
76 
77  if (arg.isempty ())
78  return ovl (Matrix ());
79 
80  if (arg.rows () != arg.columns ())
81  err_square_matrix_required ("inv", "A");
82 
83  octave_value result;
84  octave_idx_type info = 0;
85  double rcond = 0.0;
86  float frcond = 0.0;
87  bool isfloat = arg.is_single_type ();
88 
89  if (arg.is_diag_matrix ())
90  {
91  rcond = 1.0;
92  frcond = 1.0f;
93  if (arg.iscomplex ())
94  {
95  if (isfloat)
96  {
97  result = arg.float_complex_diag_matrix_value ().inverse (info);
98  if (info == -1)
99  frcond = 0.0f;
100  else if (nargout > 1)
101  frcond = arg.float_complex_diag_matrix_value ().rcond ();
102  }
103  else
104  {
105  result = arg.complex_diag_matrix_value ().inverse (info);
106  if (info == -1)
107  rcond = 0.0;
108  else if (nargout > 1)
109  rcond = arg.complex_diag_matrix_value ().rcond ();
110  }
111  }
112  else
113  {
114  if (isfloat)
115  {
116  result = arg.float_diag_matrix_value ().inverse (info);
117  if (info == -1)
118  frcond = 0.0f;
119  else if (nargout > 1)
120  frcond = arg.float_diag_matrix_value ().rcond ();
121  }
122  else
123  {
124  result = arg.diag_matrix_value ().inverse (info);
125  if (info == -1)
126  rcond = 0.0;
127  else if (nargout > 1)
128  rcond = arg.diag_matrix_value ().rcond ();
129  }
130  }
131  }
132  else if (arg.is_perm_matrix ())
133  {
134  info = 0;
135  rcond = 1.0;
136  result = arg.perm_matrix_value ().inverse ();
137  }
138  else if (isfloat)
139  {
140  if (arg.isreal ())
141  {
143 
144  MatrixType mattyp = args(0).matrix_type ();
145  result = m.inverse (mattyp, info, frcond, true, true);
146  args(0).matrix_type (mattyp);
147  }
148  else if (arg.iscomplex ())
149  {
151 
152  MatrixType mattyp = args(0).matrix_type ();
153  result = m.inverse (mattyp, info, frcond, true, true);
154  args(0).matrix_type (mattyp);
155  }
156  }
157  else
158  {
159  if (arg.isreal ())
160  {
161  if (arg.issparse ())
162  {
164 
165  MatrixType mattyp = args(0).matrix_type ();
166  result = m.inverse (mattyp, info, rcond, true, true);
167  args(0).matrix_type (mattyp);
168  }
169  else
170  {
171  Matrix m = arg.matrix_value ();
172 
173  MatrixType mattyp = args(0).matrix_type ();
174  result = m.inverse (mattyp, info, rcond, true, true);
175  args(0).matrix_type (mattyp);
176  }
177  }
178  else if (arg.iscomplex ())
179  {
180  if (arg.issparse ())
181  {
183 
184  MatrixType mattyp = args(0).matrix_type ();
185  result = m.inverse (mattyp, info, rcond, true, true);
186  args(0).matrix_type (mattyp);
187  }
188  else
189  {
191 
192  MatrixType mattyp = args(0).matrix_type ();
193  result = m.inverse (mattyp, info, rcond, true, true);
194  args(0).matrix_type (mattyp);
195  }
196  }
197  else
198  // Shouldn't get here since we checked for suitable arg earlier.
199  // Maybe for some user-defined classes?
200  err_wrong_type_arg ("inv", arg);
201  }
202 
203  octave_value_list retval (nargout > 1 ? 2 : 1);
204 
205  retval(0) = result;
206  if (nargout > 1)
207  retval(1) = (isfloat ? octave_value (frcond) : octave_value (rcond));
208 
209  if (nargout < 2)
210  {
211  bool is_singular;
212 
213  if (isfloat)
214  is_singular = ((frcond + 1.0f == 1.0f) || octave::math::isnan (frcond))
215  && ! arg.is_scalar_type ();
216  else
217  is_singular = ((rcond + 1.0 == 1.0) || octave::math::isnan (rcond))
218  && ! arg.is_scalar_type ();
219 
220  if (info == -1 || is_singular)
221  warn_singular_matrix (isfloat ? frcond : rcond);
222  }
223 
224  return retval;
225 }
226 
227 /*
228 ## Basic test for double/single matrices
229 %!assert (inv ([1, 2; 3, 4]), [-2, 1; 1.5, -0.5], 5*eps)
230 %!test
231 %! [xinv, rcond] = inv ([1,2;3,4]);
232 %! assert (xinv, [-2, 1; 1.5, -0.5], 5*eps);
233 %! assert (isa (rcond, "double"));
234 
235 %!assert (inv (single ([1, 2; 3, 4])), single ([-2, 1; 1.5, -0.5]),
236 %! 5* eps ("single"))
237 %!test
238 %! [xinv, rcond] = inv (single ([1,2;3,4]));
239 %! assert (xinv, single ([-2, 1; 1.5, -0.5]), 5* eps ("single"));
240 %! assert (isa (rcond, "single"));
241 
242 ## Basic test for integer inputs
243 %!assert (inv (int32 (2)), 0.5)
244 %!assert (inv (uint32 (2)), 0.5)
245 %!assert (inv (int64 (2)), 0.5)
246 %!assert (inv (uint64 (2)), 0.5)
247 
248 ## Normal scalar cases
249 %!assert (inv (2), 0.5)
250 %!test
251 %! [xinv, rcond] = inv (2);
252 %! assert (xinv, 0.5);
253 %! assert (rcond, 1);
254 %!assert (inv (single (2)), single (0.5))
255 %!test
256 %! [xinv, rcond] = inv (single (2));
257 %! assert (xinv, single (0.5));
258 %! assert (rcond, single (1));
259 %!assert (inv (complex (1, -1)), 0.5+0.5i)
260 %!test
261 %! [xinv, rcond] = inv (complex (1, -1));
262 %! assert (xinv, 0.5+0.5i);
263 %! assert (rcond, 1);
264 %!assert (inv (complex (single (1), -1)), single (0.5+0.5i))
265 %!test
266 %! [xinv, rcond] = inv (complex (single (1), -1));
267 %! assert (xinv, single (0.5+0.5i));
268 %! assert (rcond, single (1));
269 
270 ## Test special inputs
271 ## Empty matrix
272 %!assert (inv (zeros (2,0)), [])
273 
274 ## Scalar "0"
275 %!assert (inv (0), Inf)
276 %!test
277 %! [xinv, rcond] = inv (0);
278 %! assert (xinv, Inf);
279 %! assert (rcond, 0);
280 %!assert (inv (single (0)), single (Inf))
281 %!test
282 %! [xinv, rcond] = inv (single (0));
283 %! assert (xinv, single (Inf));
284 %! assert (rcond, single (0));
285 %!assert (inv (complex (0, 0)), Inf)
286 %!test
287 %! [xinv, rcond] = inv (complex (0, 0));
288 %! assert (xinv, Inf);
289 %! assert (rcond, 0);
290 %!assert (inv (complex (single (0), 0)), single (Inf))
291 %!test
292 %! [xinv, rcond] = inv (complex (single (0), 0));
293 %! assert (xinv, single (Inf));
294 %! assert (rcond, single (0));
295 ## NOTE: Matlab returns +Inf for -0 input, but it returns -Inf for 1/-0.
296 ## These should be the same, and in Octave they are.
297 %!assert (inv (-0), -Inf)
298 %!test
299 %! [xinv, rcond] = inv (-0);
300 %! assert (xinv, -Inf);
301 %! assert (rcond, 0);
302 
303 ## Scalar "Inf"
304 %!assert (inv (Inf), 0)
305 %!test
306 %! [xinv, rcond] = inv (Inf);
307 %! assert (xinv, 0);
308 %! assert (rcond, 0);
309 %!assert (inv (single (Inf)), single (0))
310 %!test
311 %! [xinv, rcond] = inv (single (Inf));
312 %! assert (xinv, single (0));
313 %! assert (rcond, single (0));
314 %!assert (inv (complex (1, Inf)), 0)
315 %!test
316 %! [xinv, rcond] = inv (complex (1, Inf));
317 %! assert (xinv, 0);
318 %! assert (rcond, 0);
319 %!assert (inv (complex (single (1), Inf)), single (0))
320 %!test
321 %! [xinv, rcond] = inv (complex (single (1), Inf));
322 %! assert (xinv, single (0));
323 %! assert (rcond, single (0));
324 
325 ## Scalar "NaN"
326 %!assert (inv (NaN), NaN)
327 %!test
328 %! [xinv, rcond] = inv (NaN);
329 %! assert (xinv, NaN);
330 %! assert (rcond, NaN);
331 %!assert (inv (single (NaN)), single (NaN))
332 %!test
333 %! [xinv, rcond] = inv (single (NaN));
334 %! assert (xinv, single (NaN));
335 %! assert (rcond, single (NaN));
336 %!assert (inv (complex (1, NaN)), complex (NaN, NaN))
337 %!test
338 %! [xinv, rcond] = inv (complex (1, NaN));
339 %! assert (xinv, complex (NaN, NaN));
340 %! assert (rcond, NaN);
341 %!assert (inv (complex (single (1), NaN)), complex (single (NaN), NaN))
342 %!test
343 %! [xinv, rcond] = inv (complex (single (1), NaN));
344 %! assert (xinv, complex (single (NaN), NaN));
345 %! assert (rcond, single (NaN));
346 
347 ## Matrix special values
348 ## Matrix of all zeroes
349 %!warning <matrix singular> assert (inv (zeros (2,2)), Inf (2,2))
350 %!test
351 %! [xinv, rcond] = inv (zeros (2,2));
352 %! assert (xinv, Inf (2,2));
353 %! assert (rcond, 0);
354 ## Matrix of all Inf
355 %!xtest <65054>
356 %! fail ("A = inv (Inf (2,2))", "warning", "matrix singular");
357 %! assert (A, NaN (2,2));
358 %!xtest <65054>
359 %! [xinv, rcond] = inv (Inf (2,2));
360 %! assert (xinv, NaN (2,2));
361 %! assert (rcond, NaN);
362 ## Matrix of all NaN
363 %!warning <rcond = > assert (inv (NaN (2,2)), NaN (2,2))
364 %!test
365 %! [xinv, rcond] = inv (NaN (2,2));
366 %! assert (xinv, NaN (2,2));
367 %! assert (rcond, NaN);
368 
369 ## Special diagonal matrices
370 %!test
371 %! fail ("A = inv (diag ([1, 0, 1]))", "warning", "matrix singular");
372 %! assert (A, diag ([Inf, Inf, Inf]));
373 
374 ## Special sparse matrices
375 %!testif HAVE_UMFPACK <*56232>
376 %! fail ("A = inv (sparse ([1, 2;0 ,0]))", "warning", "matrix singular");
377 %! assert (A, sparse ([Inf, Inf; 0, 0]));
378 
379 %!testif HAVE_UMFPACK <*56232>
380 %! fail ("A = inv (sparse ([1i, 2;0 ,0]))", "warning", "matrix singular");
381 %! assert (A, sparse ([Inf, Inf; 0, 0]));
382 
383 %!testif HAVE_UMFPACK <*56232>
384 %! fail ("A = inv (sparse ([1, 0, 0; 0, 0, 0; 0, 0, 1]))",
385 %! "warning", "matrix singular");
386 %! assert (A, sparse ([Inf, 0, 0; 0, 0, 0; 0, 0, Inf]));
387 
388 %!error <Invalid call> inv ()
389 %!error <Invalid call> inv ([1, 2; 3, 4], 2)
390 %!error <wrong type argument> inv ("Hello World")
391 %!error <wrong type argument> inv ({1})
392 %!error <wrong type argument> inv (true)
393 %!error <must be a square matrix> inv ([1, 2; 3, 4; 5, 6])
394 %!error <inverse of the null matrix not defined> inv (sparse (2, 2, 0))
395 %!error <inverse of the null matrix not defined> inv (diag ([0, 0]))
396 %!error <inverse of the null matrix not defined> inv (diag (complex ([0, 0])))
397 */
398 
399 DEFALIAS (inverse, inv);
400 
401 OCTAVE_END_NAMESPACE(octave)
double rcond() const
Definition: CDiagMatrix.cc:507
ComplexDiagMatrix inverse(octave_idx_type &info) const
Definition: CDiagMatrix.cc:311
DiagMatrix inverse() const
Definition: dDiagMatrix.cc:227
double rcond() const
Definition: dDiagMatrix.cc:345
FloatComplexDiagMatrix inverse(octave_idx_type &info) const
float rcond() const
Definition: fDiagMatrix.cc:323
FloatDiagMatrix inverse() const
Definition: fDiagMatrix.cc:227
Definition: dMatrix.h:42
PermMatrix inverse() const
Definition: PermMatrix.cc:114
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 is_scalar_type() const
Definition: ov.h:744
bool isreal() const
Definition: ov.h:738
bool isnumeric() const
Definition: ov.h:750
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 DEFALIAS(alias, name)
Macro to define an alias for another existing function name.
Definition: defun.h:160
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
void warn_singular_matrix(double rcond)
bool isnan(bool)
Definition: lo-mappers.h:178
T octave_idx_type m
Definition: mx-inlines.cc:781
return octave_value(v1.char_array_value() . concat(v2.char_array_value(), ra_idx),((a1.is_sq_string()||a2.is_sq_string()) ? '\'' :'"'))
octave_value_list ovl(const OV_Args &... args)
Construct an octave_value_list with less typing.
Definition: ovl.h:219