GNU Octave 10.1.0
A high-level interpreted language, primarily intended for numerical computations, mostly compatible with Matlab
 
Loading...
Searching...
No Matches
fCDiagMatrix.cc
Go to the documentation of this file.
1////////////////////////////////////////////////////////////////////////
2//
3// Copyright (C) 1994-2025 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
48bool
50{
51 if (rows () != a.rows () || cols () != a.cols ())
52 return 0;
53
54 return mx_inline_equal (length (), data (), a.data ());
55}
56
57bool
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
360bool
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 = rwdata (); // 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
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
490float
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
501std::ostream&
502operator << (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:563
Array< U, A > map(F fcn) const
Apply function fcn to each element of the Array<T, Alloc>.
Definition Array.h:861
octave_idx_type numel() const
Number of elements in the array.
Definition Array.h:418
octave_idx_type rows() const
Definition DiagArray2.h:86
T dgelem(octave_idx_type i) const
Definition DiagArray2.h:121
octave_idx_type length() const
Definition DiagArray2.h:92
T elem(octave_idx_type r, octave_idx_type c) const
Definition DiagArray2.h:114
octave_idx_type columns() const
Definition DiagArray2.h:88
octave_idx_type cols() const
Definition DiagArray2.h:87
T & dgxelem(octave_idx_type i)
Definition DiagArray2.h:149
const T * data() const
Definition DiagArray2.h:166
T * rwdata()
Definition DiagArray2.h:168
float max() const
float min() const
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
FloatComplexDiagMatrix & fill(float val)
FloatComplexColumnVector column(octave_idx_type i) const
bool operator==(const FloatComplexDiagMatrix &a) const
FloatComplexDiagMatrix & operator+=(const FloatDiagMatrix &a)
bool all_elements_are_real() const
bool operator!=(const FloatComplexDiagMatrix &a) const
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:54
Definition DET.h:38
FloatComplexDiagMatrix conj(const FloatComplexDiagMatrix &a)
std::ostream & operator<<(std::ostream &os, const FloatComplexDiagMatrix &a)
FloatComplexDiagMatrix operator*(const FloatComplexDiagMatrix &a, const FloatDiagMatrix &b)
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)
bool mx_inline_all_real(std::size_t n, const std::complex< T > *x)
bool mx_inline_equal(std::size_t n, const T1 *x, const T2 *y)
std::complex< float > FloatComplex
Definition oct-cmplx.h:34
F77_RET_T len
Definition xerbla.cc:61