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