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
dDiagMatrix.cc
Go to the documentation of this file.
1 ////////////////////////////////////////////////////////////////////////
2 //
3 // Copyright (C) 1994-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 <ostream>
31 
32 #include "Array-util.h"
33 #include "lo-error.h"
34 #include "mx-base.h"
35 #include "mx-inlines.cc"
36 #include "oct-cmplx.h"
37 
38 // Diagonal Matrix class.
39 
40 bool
42 {
43  if (rows () != a.rows () || cols () != a.cols ())
44  return 0;
45 
46  return mx_inline_equal (length (), data (), a.data ());
47 }
48 
49 bool
51 {
52  return !(*this == a);
53 }
54 
56 DiagMatrix::fill (double val)
57 {
58  for (octave_idx_type i = 0; i < length (); i++)
59  elem (i, i) = val;
60  return *this;
61 }
62 
65 {
66  if (beg < 0 || end >= length () || end < beg)
67  (*current_liboctave_error_handler) ("range error for fill");
68 
69  for (octave_idx_type i = beg; i <= end; i++)
70  elem (i, i) = val;
71 
72  return *this;
73 }
74 
77 {
79  if (a.numel () != len)
80  (*current_liboctave_error_handler) ("range error for fill");
81 
82  for (octave_idx_type i = 0; i < len; i++)
83  elem (i, i) = a.elem (i);
84 
85  return *this;
86 }
87 
90 {
92  if (a.numel () != len)
93  (*current_liboctave_error_handler) ("range error for fill");
94 
95  for (octave_idx_type i = 0; i < len; i++)
96  elem (i, i) = a.elem (i);
97 
98  return *this;
99 }
100 
101 DiagMatrix&
103 {
104  octave_idx_type a_len = a.numel ();
105  if (beg < 0 || beg + a_len >= length ())
106  (*current_liboctave_error_handler) ("range error for fill");
107 
108  for (octave_idx_type i = 0; i < a_len; i++)
109  elem (i+beg, i+beg) = a.elem (i);
110 
111  return *this;
112 }
113 
114 DiagMatrix&
116 {
117  octave_idx_type a_len = a.numel ();
118  if (beg < 0 || beg + a_len >= length ())
119  (*current_liboctave_error_handler) ("range error for fill");
120 
121  for (octave_idx_type i = 0; i < a_len; i++)
122  elem (i+beg, i+beg) = a.elem (i);
123 
124  return *this;
125 }
126 
129 {
130  return DiagMatrix (extract_diag ().abs (), rows (), columns ());
131 }
132 
135 {
136  return DiagMatrix (real (a.extract_diag ()), a.rows (), a.cols ());
137 }
138 
141 {
142  return DiagMatrix (imag (a.extract_diag ()), a.rows (), a.cols ());
143 }
144 
145 Matrix
147  octave_idx_type r2, octave_idx_type c2) const
148 {
149  if (r1 > r2) { std::swap (r1, r2); }
150  if (c1 > c2) { std::swap (c1, c2); }
151 
152  octave_idx_type new_r = r2 - r1 + 1;
153  octave_idx_type new_c = c2 - c1 + 1;
154 
155  Matrix result (new_r, new_c);
156 
157  for (octave_idx_type j = 0; j < new_c; j++)
158  for (octave_idx_type i = 0; i < new_r; i++)
159  result.elem (i, j) = elem (r1+i, c1+j);
160 
161  return result;
162 }
163 
164 // extract row or column i.
165 
166 RowVector
168 {
169  octave_idx_type r = rows ();
170  octave_idx_type c = cols ();
171  if (i < 0 || i >= r)
172  (*current_liboctave_error_handler) ("invalid row selection");
173 
174  RowVector retval (c, 0.0);
175  if (r <= c || i < c)
176  retval.elem (i) = elem (i, i);
177 
178  return retval;
179 }
180 
181 RowVector
182 DiagMatrix::row (char *s) const
183 {
184  if (! s)
185  (*current_liboctave_error_handler) ("invalid row selection");
186 
187  char c = s[0];
188  if (c == 'f' || c == 'F')
189  return row (static_cast<octave_idx_type> (0));
190  else if (c == 'l' || c == 'L')
191  return row (rows () - 1);
192  else
193  (*current_liboctave_error_handler) ("invalid row selection");
194 }
195 
198 {
199  octave_idx_type r = rows ();
200  octave_idx_type c = cols ();
201  if (i < 0 || i >= c)
202  (*current_liboctave_error_handler) ("invalid column selection");
203 
204  ColumnVector retval (r, 0.0);
205  if (r >= c || i < r)
206  retval.elem (i) = elem (i, i);
207 
208  return retval;
209 }
210 
212 DiagMatrix::column (char *s) const
213 {
214  if (! s)
215  (*current_liboctave_error_handler) ("invalid column selection");
216 
217  char c = s[0];
218  if (c == 'f' || c == 'F')
219  return column (static_cast<octave_idx_type> (0));
220  else if (c == 'l' || c == 'L')
221  return column (cols () - 1);
222  else
223  (*current_liboctave_error_handler) ("invalid column selection");
224 }
225 
228 {
229  octave_idx_type info;
230  return inverse (info);
231 }
232 
235 {
236  octave_idx_type r = rows ();
237  octave_idx_type c = cols ();
238  if (r != c)
239  (*current_liboctave_error_handler) ("inverse requires square matrix");
240 
241  DiagMatrix retval (r, c);
242 
243  info = 0;
244  octave_idx_type len = r; // alias for readability
245  octave_idx_type z_count = 0; // zeros
246  octave_idx_type nz_count = 0; // nonzeros
247  for (octave_idx_type i = 0; i < len; i++)
248  {
249  if (xelem (i, i) == 0.0)
250  {
251  z_count++;
252  if (nz_count > 0)
253  break;
254  }
255  else
256  {
257  nz_count++;
258  if (z_count > 0)
259  break;
260  retval.elem (i, i) = 1.0 / xelem (i, i);
261  }
262  }
263  if (nz_count == 0)
264  {
265  (*current_liboctave_error_handler)
266  ("inverse of the null matrix not defined");
267  }
268  else if (z_count > 0)
269  {
270  info = -1;
271  element_type *data = retval.fortran_vec ();
273  }
274 
275  return retval;
276 }
277 
279 DiagMatrix::pseudo_inverse (double tol) const
280 {
281  octave_idx_type r = rows ();
282  octave_idx_type c = cols ();
284 
285  DiagMatrix retval (c, r);
286 
287  for (octave_idx_type i = 0; i < len; i++)
288  {
289  double val = std::abs (elem (i, i));
290  if (val < tol || val == 0.0)
291  retval.elem (i, i) = 0.0;
292  else
293  retval.elem (i, i) = 1.0 / elem (i, i);
294  }
295 
296  return retval;
297 }
298 
299 // diagonal matrix by diagonal matrix -> diagonal matrix operations
300 
301 // diagonal matrix by diagonal matrix -> diagonal matrix operations
302 
304 operator * (const DiagMatrix& a, const DiagMatrix& b)
305 {
306  octave_idx_type a_nr = a.rows ();
307  octave_idx_type a_nc = a.cols ();
308 
309  octave_idx_type b_nr = b.rows ();
310  octave_idx_type b_nc = b.cols ();
311 
312  if (a_nc != b_nr)
313  octave::err_nonconformant ("operator *", a_nr, a_nc, b_nr, b_nc);
314 
315  DiagMatrix c (a_nr, b_nc);
316 
317  octave_idx_type len = c.length ();
318  octave_idx_type lenm = (len < a_nc ? len : a_nc);
319 
320  for (octave_idx_type i = 0; i < lenm; i++)
321  c.dgxelem (i) = a.dgelem (i) * b.dgelem (i);
322  for (octave_idx_type i = lenm; i < len; i++)
323  c.dgxelem (i) = 0.0;
324 
325  return c;
326 }
327 
328 // other operations
329 
330 DET
332 {
333  DET det (1.0);
334  if (rows () != cols ())
335  (*current_liboctave_error_handler) ("determinant requires square matrix");
336 
338  for (octave_idx_type i = 0; i < len; i++)
339  det *= elem (i, i);
340 
341  return det;
342 }
343 
344 double
346 {
347  ColumnVector av = extract_diag (0).map<double> (fabs);
348  double amx = av.max ();
349  double amn = av.min ();
350  return amx == 0 ? 0.0 : amn / amx;
351 }
352 
353 std::ostream&
354 operator << (std::ostream& os, const DiagMatrix& a)
355 {
356 // int field_width = os.precision () + 7;
357 
358  for (octave_idx_type i = 0; i < a.rows (); i++)
359  {
360  for (octave_idx_type j = 0; j < a.cols (); j++)
361  {
362  if (i == j)
363  os << ' ' /* setw (field_width) */ << a.elem (i, i);
364  else
365  os << ' ' /* setw (field_width) */ << 0.0;
366  }
367  os << "\n";
368  }
369  return os;
370 }
#define Inf
Definition: Faddeeva.cc:260
T & elem(octave_idx_type n)
Size of the specified dimension.
Definition: Array.h:562
T element_type
Definition: Array.h:230
Array< U, A > map(F fcn) const
Apply function fcn to each element of the Array<T, Alloc>.
Definition: Array.h:859
octave_idx_type numel() const
Number of elements in the array.
Definition: Array.h:414
double min() const
Definition: dColVector.cc:245
double max() const
Definition: dColVector.cc:261
ComplexColumnVector extract_diag(octave_idx_type k=0) const
Definition: CDiagMatrix.h:140
octave_idx_type rows() const
Definition: DiagArray2.h:89
T dgelem(octave_idx_type i) const
Definition: DiagArray2.h:124
octave_idx_type length() const
Definition: DiagArray2.h:95
T elem(octave_idx_type r, octave_idx_type c) const
Definition: DiagArray2.h:117
T & dgxelem(octave_idx_type i)
Definition: DiagArray2.h:152
T xelem(octave_idx_type r, octave_idx_type c) const
Definition: DiagArray2.h:147
octave_idx_type columns() const
Definition: DiagArray2.h:91
octave_idx_type cols() const
Definition: DiagArray2.h:90
const T * data() const
Definition: DiagArray2.h:169
DiagMatrix inverse() const
Definition: dDiagMatrix.cc:227
DiagMatrix abs() const
Definition: dDiagMatrix.cc:128
RowVector row(octave_idx_type i) const
Definition: dDiagMatrix.cc:167
double rcond() const
Definition: dDiagMatrix.cc:345
Matrix extract(octave_idx_type r1, octave_idx_type c1, octave_idx_type r2, octave_idx_type c2) const
Definition: dDiagMatrix.cc:146
DiagMatrix & fill(double val)
Definition: dDiagMatrix.cc:56
DiagMatrix pseudo_inverse(double tol=0.0) const
Definition: dDiagMatrix.cc:279
ColumnVector extract_diag(octave_idx_type k=0) const
Definition: dDiagMatrix.h:107
bool operator!=(const DiagMatrix &a) const
Definition: dDiagMatrix.cc:50
DiagMatrix()=default
DET determinant() const
Definition: dDiagMatrix.cc:331
bool operator==(const DiagMatrix &a) const
Definition: dDiagMatrix.cc:41
ColumnVector column(octave_idx_type i) const
Definition: dDiagMatrix.cc:197
Definition: dMatrix.h:42
Definition: DET.h:39
DiagMatrix real(const ComplexDiagMatrix &a)
Definition: dDiagMatrix.cc:134
DiagMatrix imag(const ComplexDiagMatrix &a)
Definition: dDiagMatrix.cc:140
std::ostream & operator<<(std::ostream &os, const DiagMatrix &a)
Definition: dDiagMatrix.cc:354
DiagMatrix operator*(const DiagMatrix &a, const DiagMatrix &b)
Definition: dDiagMatrix.cc:304
void err_nonconformant(const char *op, octave_idx_type op1_len, octave_idx_type op2_len)
OCTAVE_NORETURN liboctave_error_handler current_liboctave_error_handler
Definition: lo-error.c:41
bool mx_inline_equal(std::size_t n, const T1 *x, const T2 *y)
Definition: mx-inlines.cc:577
T * r
Definition: mx-inlines.cc:781
F77_RET_T len
Definition: xerbla.cc:61