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
fCDiagMatrix.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 "lo-ieee.h"
35 #include "mx-base.h"
36 #include "mx-inlines.cc"
37 #include "oct-cmplx.h"
38 
39 // FloatComplex Diagonal Matrix class
40 
42  : MDiagArray2<FloatComplex> (a.rows (), a.cols ())
43 {
44  for (octave_idx_type i = 0; i < length (); i++)
45  elem (i, i) = a.elem (i, i);
46 }
47 
48 bool
50 {
51  if (rows () != a.rows () || cols () != a.cols ())
52  return 0;
53 
54  return mx_inline_equal (length (), data (), a.data ());
55 }
56 
57 bool
59 {
60  return !(*this == a);
61 }
62 
65 {
66  for (octave_idx_type i = 0; i < length (); i++)
67  elem (i, i) = val;
68  return *this;
69 }
70 
73 {
74  for (octave_idx_type i = 0; i < length (); i++)
75  elem (i, i) = val;
76  return *this;
77 }
78 
82 {
83  if (beg < 0 || end >= length () || end < beg)
84  (*current_liboctave_error_handler) ("range error for fill");
85 
86  for (octave_idx_type i = beg; i <= end; i++)
87  elem (i, i) = val;
88 
89  return *this;
90 }
91 
95 {
96  if (beg < 0 || end >= length () || end < beg)
97  (*current_liboctave_error_handler) ("range error for fill");
98 
99  for (octave_idx_type i = beg; i <= end; i++)
100  elem (i, i) = val;
101 
102  return *this;
103 }
104 
107 {
109  if (a.numel () != len)
110  (*current_liboctave_error_handler) ("range error for fill");
111 
112  for (octave_idx_type i = 0; i < len; i++)
113  elem (i, i) = a.elem (i);
114 
115  return *this;
116 }
117 
120 {
122  if (a.numel () != len)
123  (*current_liboctave_error_handler) ("range error for fill");
124 
125  for (octave_idx_type i = 0; i < len; i++)
126  elem (i, i) = a.elem (i);
127 
128  return *this;
129 }
130 
133 {
135  if (a.numel () != len)
136  (*current_liboctave_error_handler) ("range error for fill");
137 
138  for (octave_idx_type i = 0; i < len; i++)
139  elem (i, i) = a.elem (i);
140 
141  return *this;
142 }
143 
146 {
148  if (a.numel () != len)
149  (*current_liboctave_error_handler) ("range error for fill");
150 
151  for (octave_idx_type i = 0; i < len; i++)
152  elem (i, i) = a.elem (i);
153 
154  return *this;
155 }
156 
159 {
160  octave_idx_type a_len = a.numel ();
161  if (beg < 0 || beg + a_len >= length ())
162  (*current_liboctave_error_handler) ("range error for fill");
163 
164  for (octave_idx_type i = 0; i < a_len; i++)
165  elem (i+beg, i+beg) = a.elem (i);
166 
167  return *this;
168 }
169 
172  octave_idx_type beg)
173 {
174  octave_idx_type a_len = a.numel ();
175  if (beg < 0 || beg + a_len >= length ())
176  (*current_liboctave_error_handler) ("range error for fill");
177 
178  for (octave_idx_type i = 0; i < a_len; i++)
179  elem (i+beg, i+beg) = a.elem (i);
180 
181  return *this;
182 }
183 
186 {
187  octave_idx_type a_len = a.numel ();
188  if (beg < 0 || beg + a_len >= length ())
189  (*current_liboctave_error_handler) ("range error for fill");
190 
191  for (octave_idx_type i = 0; i < a_len; i++)
192  elem (i+beg, i+beg) = a.elem (i);
193 
194  return *this;
195 }
196 
199  octave_idx_type beg)
200 {
201  octave_idx_type a_len = a.numel ();
202  if (beg < 0 || beg + a_len >= length ())
203  (*current_liboctave_error_handler) ("range error for fill");
204 
205  for (octave_idx_type i = 0; i < a_len; i++)
206  elem (i+beg, i+beg) = a.elem (i);
207 
208  return *this;
209 }
210 
213 {
214  return FloatDiagMatrix (extract_diag ().abs (), rows (), columns ());
215 }
216 
219 {
220  return FloatComplexDiagMatrix (conj (a.extract_diag ()), a.rows (),
221  a.columns ());
222 }
223 
224 // resize is the destructive analog for this one
225 
228  octave_idx_type r2, octave_idx_type c2) const
229 {
230  if (r1 > r2) { std::swap (r1, r2); }
231  if (c1 > c2) { std::swap (c1, c2); }
232 
233  octave_idx_type new_r = r2 - r1 + 1;
234  octave_idx_type new_c = c2 - c1 + 1;
235 
236  FloatComplexMatrix result (new_r, new_c);
237 
238  for (octave_idx_type j = 0; j < new_c; j++)
239  for (octave_idx_type i = 0; i < new_r; i++)
240  result.elem (i, j) = elem (r1+i, c1+j);
241 
242  return result;
243 }
244 
245 // extract row or column i.
246 
249 {
250  octave_idx_type r = rows ();
251  octave_idx_type c = cols ();
252  if (i < 0 || i >= r)
253  (*current_liboctave_error_handler) ("invalid row selection");
254 
255  FloatComplexRowVector retval (c, 0.0);
256  if (r <= c || i < c)
257  retval.elem (i) = elem (i, i);
258 
259  return retval;
260 }
261 
264 {
265  if (! s)
266  (*current_liboctave_error_handler) ("invalid row selection");
267 
268  char c = s[0];
269  if (c == 'f' || c == 'F')
270  return row (static_cast<octave_idx_type> (0));
271  else if (c == 'l' || c == 'L')
272  return row (rows () - 1);
273  else
274  (*current_liboctave_error_handler) ("invalid row selection");
275 }
276 
279 {
280  octave_idx_type r = rows ();
281  octave_idx_type c = cols ();
282  if (i < 0 || i >= c)
283  (*current_liboctave_error_handler) ("invalid column selection");
284 
285  FloatComplexColumnVector retval (r, 0.0);
286  if (r >= c || i < r)
287  retval.elem (i) = elem (i, i);
288 
289  return retval;
290 }
291 
294 {
295  if (! s)
296  (*current_liboctave_error_handler) ("invalid column selection");
297 
298  char c = s[0];
299  if (c == 'f' || c == 'F')
300  return column (static_cast<octave_idx_type> (0));
301  else if (c == 'l' || c == 'L')
302  return column (cols () - 1);
303  else
304  (*current_liboctave_error_handler) ("invalid column selection");
305 }
306 
309 {
310  octave_idx_type info;
311  return inverse (info);
312 }
313 
316 {
317  octave_idx_type r = rows ();
318  octave_idx_type c = cols ();
319  if (r != c)
320  (*current_liboctave_error_handler) ("inverse requires square matrix");
321 
322  FloatComplexDiagMatrix retval (r, c);
323 
324  info = 0;
325  for (octave_idx_type i = 0; i < length (); i++)
326  {
327  if (elem (i, i) == 0.0f)
328  {
329  info = -1;
330  return *this;
331  }
332  else
333  retval.elem (i, i) = 1.0f / elem (i, i);
334  }
335 
336  return retval;
337 }
338 
341 {
342  octave_idx_type r = rows ();
343  octave_idx_type c = cols ();
345 
346  FloatComplexDiagMatrix retval (c, r);
347 
348  for (octave_idx_type i = 0; i < len; i++)
349  {
350  float val = std::abs (elem (i, i));
351  if (val < tol || val == 0.0f)
352  retval.elem (i, i) = 0.0f;
353  else
354  retval.elem (i, i) = 1.0f / elem (i, i);
355  }
356 
357  return retval;
358 }
359 
360 bool
362 {
363  return mx_inline_all_real (length (), data ());
364 }
365 
366 // diagonal matrix by diagonal matrix -> diagonal matrix operations
367 
370 {
371  octave_idx_type r = rows ();
372  octave_idx_type c = cols ();
373 
374  octave_idx_type a_nr = a.rows ();
375  octave_idx_type a_nc = a.cols ();
376 
377  if (r != a_nr || c != a_nc)
378  octave::err_nonconformant ("operator +=", r, c, a_nr, a_nc);
379 
380  if (r == 0 || c == 0)
381  return *this;
382 
383  FloatComplex *d = fortran_vec (); // Ensures only 1 reference to my privates!
384 
385  mx_inline_add2 (length (), d, a.data ());
386  return *this;
387 }
388 
391 {
392  octave_idx_type a_nr = a.rows ();
393  octave_idx_type a_nc = a.cols ();
394 
395  octave_idx_type b_nr = b.rows ();
396  octave_idx_type b_nc = b.cols ();
397 
398  if (a_nc != b_nr)
399  octave::err_nonconformant ("operator *", a_nr, a_nc, b_nr, b_nc);
400 
401  FloatComplexDiagMatrix c (a_nr, b_nc);
402 
403  octave_idx_type len = c.length ();
404  octave_idx_type lenm = (len < a_nc ? len : a_nc);
405 
406  for (octave_idx_type i = 0; i < lenm; i++)
407  c.dgxelem (i) = a.dgelem (i) * b.dgelem (i);
408  for (octave_idx_type i = lenm; i < len; i++)
409  c.dgxelem (i) = 0.0f;
410 
411  return c;
412 }
413 
416 {
417  octave_idx_type a_nr = a.rows ();
418  octave_idx_type a_nc = a.cols ();
419 
420  octave_idx_type b_nr = b.rows ();
421  octave_idx_type b_nc = b.cols ();
422 
423  if (a_nc != b_nr)
424  octave::err_nonconformant ("operator *", a_nr, a_nc, b_nr, b_nc);
425 
426  if (a_nr == 0 || a_nc == 0 || b_nc == 0)
427  return FloatComplexDiagMatrix (a_nr, a_nc, 0.0);
428 
429  FloatComplexDiagMatrix c (a_nr, b_nc);
430 
431  octave_idx_type len = (a_nr < b_nc ? a_nr : b_nc);
432 
433  for (octave_idx_type i = 0; i < len; i++)
434  {
435  float a_element = a.elem (i, i);
436  FloatComplex b_element = b.elem (i, i);
437 
438  c.elem (i, i) = a_element * b_element;
439  }
440 
441  return c;
442 }
443 
446 {
447  octave_idx_type a_nr = a.rows ();
448  octave_idx_type a_nc = a.cols ();
449 
450  octave_idx_type b_nr = b.rows ();
451  octave_idx_type b_nc = b.cols ();
452 
453  if (a_nc != b_nr)
454  octave::err_nonconformant ("operator *", a_nr, a_nc, b_nr, b_nc);
455 
456  if (a_nr == 0 || a_nc == 0 || b_nc == 0)
457  return FloatComplexDiagMatrix (a_nr, a_nc, 0.0);
458 
459  FloatComplexDiagMatrix c (a_nr, b_nc);
460 
461  octave_idx_type len = (a_nr < b_nc ? a_nr : b_nc);
462 
463  for (octave_idx_type i = 0; i < len; i++)
464  {
465  FloatComplex a_element = a.elem (i, i);
466  FloatComplex b_element = b.elem (i, i);
467 
468  c.elem (i, i) = a_element * b_element;
469  }
470 
471  return c;
472 }
473 
474 // other operations
475 
478 {
479  FloatComplexDET det (1.0f);
480  if (rows () != cols ())
481  (*current_liboctave_error_handler) ("determinant requires square matrix");
482 
484  for (octave_idx_type i = 0; i < len; i++)
485  det *= elem (i, i);
486 
487  return det;
488 }
489 
490 float
492 {
493  FloatColumnVector av = extract_diag (0).map<float> (std::abs);
494  float amx = av.max ();
495  float amn = av.min ();
496  return amx == 0 ? 0.0f : amn / amx;
497 }
498 
499 // i/o
500 
501 std::ostream&
502 operator << (std::ostream& os, const FloatComplexDiagMatrix& a)
503 {
504  FloatComplex ZERO (0.0);
505 // int field_width = os.precision () + 7;
506  for (octave_idx_type i = 0; i < a.rows (); i++)
507  {
508  for (octave_idx_type j = 0; j < a.cols (); j++)
509  {
510  if (i == j)
511  os << ' ' /* setw (field_width) */ << a.elem (i, i);
512  else
513  os << ' ' /* setw (field_width) */ << ZERO;
514  }
515  os << "\n";
516  }
517  return os;
518 }
T & elem(octave_idx_type n)
Size of the specified dimension.
Definition: Array.h:562
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
T * fortran_vec()
Definition: DiagArray2.h:171
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
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
float max() const
Definition: fColVector.cc:261
float min() const
Definition: fColVector.cc:245
FloatDiagMatrix abs() const
FloatComplexMatrix extract(octave_idx_type r1, octave_idx_type c1, octave_idx_type r2, octave_idx_type c2) const
FloatComplexDiagMatrix pseudo_inverse(float tol=0.0f) const
FloatComplexColumnVector extract_diag(octave_idx_type k=0) const
Definition: fCDiagMatrix.h:144
FloatComplexDiagMatrix & fill(float val)
Definition: fCDiagMatrix.cc:64
FloatComplexColumnVector column(octave_idx_type i) const
bool operator==(const FloatComplexDiagMatrix &a) const
Definition: fCDiagMatrix.cc:49
FloatComplexDiagMatrix & operator+=(const FloatDiagMatrix &a)
bool all_elements_are_real() const
bool operator!=(const FloatComplexDiagMatrix &a) const
Definition: fCDiagMatrix.cc:58
FloatComplexDET determinant() const
FloatComplexRowVector row(octave_idx_type i) const
FloatComplexDiagMatrix inverse() const
FloatComplexDiagMatrix()=default
Template for two dimensional diagonal array with math operators.
Definition: MDiagArray2.h:56
Definition: DET.h:39
FloatComplexDiagMatrix conj(const FloatComplexDiagMatrix &a)
std::ostream & operator<<(std::ostream &os, const FloatComplexDiagMatrix &a)
FloatComplexDiagMatrix operator*(const FloatComplexDiagMatrix &a, const FloatDiagMatrix &b)
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
F77_RET_T const F77_DBLE const F77_DBLE F77_DBLE * d
void mx_inline_add2(std::size_t n, R *r, const X *x)
Definition: mx-inlines.cc:127
bool mx_inline_all_real(std::size_t n, const std::complex< T > *x)
Definition: mx-inlines.cc:312
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
std::complex< float > FloatComplex
Definition: oct-cmplx.h:34
F77_RET_T len
Definition: xerbla.cc:61