GNU Octave  4.4.1
A high-level interpreted language, primarily intended for numerical computations, mostly compatible with Matlab
CDiagMatrix.cc
Go to the documentation of this file.
1 /*
2 
3 Copyright (C) 1994-2018 John W. Eaton
4 Copyright (C) 2009 VZLU Prague
5 
6 This file is part of Octave.
7 
8 Octave is free software: you can redistribute it and/or modify it
9 under the terms of the GNU General Public License as published by
10 the Free Software Foundation, either version 3 of the License, or
11 (at your option) any later version.
12 
13 Octave is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
17 
18 You should have received a copy of the GNU General Public License
19 along with Octave; see the file COPYING. If not, see
20 <https://www.gnu.org/licenses/>.
21 
22 */
23 
24 #if defined (HAVE_CONFIG_H)
25 # include "config.h"
26 #endif
27 
28 #include <iostream>
29 
30 #include "Array-util.h"
31 #include "lo-error.h"
32 #include "lo-ieee.h"
33 #include "mx-base.h"
34 #include "mx-inlines.cc"
35 #include "oct-cmplx.h"
36 
37 // Complex Diagonal Matrix class
38 
40  : MDiagArray2<Complex> (a.rows (), a.cols ())
41 {
42  for (octave_idx_type i = 0; i < length (); i++)
43  elem (i, i) = a.elem (i, i);
44 }
45 
46 bool
48 {
49  if (rows () != a.rows () || cols () != a.cols ())
50  return 0;
51 
52  return mx_inline_equal (length (), data (), a.data ());
53 }
54 
55 bool
57 {
58  return !(*this == a);
59 }
60 
63 {
64  for (octave_idx_type i = 0; i < length (); i++)
65  elem (i, i) = val;
66  return *this;
67 }
68 
71 {
72  for (octave_idx_type i = 0; i < length (); i++)
73  elem (i, i) = val;
74  return *this;
75 }
76 
79 {
80  if (beg < 0 || end >= length () || end < beg)
81  (*current_liboctave_error_handler) ("range error for fill");
82 
83  for (octave_idx_type i = beg; i <= end; i++)
84  elem (i, i) = val;
85 
86  return *this;
87 }
88 
92 {
93  if (beg < 0 || end >= length () || end < beg)
94  (*current_liboctave_error_handler) ("range error for fill");
95 
96  for (octave_idx_type i = beg; i <= end; i++)
97  elem (i, i) = val;
98 
99  return *this;
100 }
101 
104 {
105  octave_idx_type len = length ();
106  if (a.numel () != len)
107  (*current_liboctave_error_handler) ("range error for fill");
108 
109  for (octave_idx_type i = 0; i < len; i++)
110  elem (i, i) = a.elem (i);
111 
112  return *this;
113 }
114 
117 {
118  octave_idx_type len = length ();
119  if (a.numel () != len)
120  (*current_liboctave_error_handler) ("range error for fill");
121 
122  for (octave_idx_type i = 0; i < len; i++)
123  elem (i, i) = a.elem (i);
124 
125  return *this;
126 }
127 
130 {
131  octave_idx_type len = length ();
132  if (a.numel () != len)
133  (*current_liboctave_error_handler) ("range error for fill");
134 
135  for (octave_idx_type i = 0; i < len; i++)
136  elem (i, i) = a.elem (i);
137 
138  return *this;
139 }
140 
143 {
144  octave_idx_type len = length ();
145  if (a.numel () != len)
146  (*current_liboctave_error_handler) ("range error for fill");
147 
148  for (octave_idx_type i = 0; i < len; i++)
149  elem (i, i) = a.elem (i);
150 
151  return *this;
152 }
153 
156 {
157  octave_idx_type a_len = a.numel ();
158  if (beg < 0 || beg + a_len >= length ())
159  (*current_liboctave_error_handler) ("range error for fill");
160 
161  for (octave_idx_type i = 0; i < a_len; i++)
162  elem (i+beg, i+beg) = a.elem (i);
163 
164  return *this;
165 }
166 
169 {
170  octave_idx_type a_len = a.numel ();
171  if (beg < 0 || beg + a_len >= length ())
172  (*current_liboctave_error_handler) ("range error for fill");
173 
174  for (octave_idx_type i = 0; i < a_len; i++)
175  elem (i+beg, i+beg) = a.elem (i);
176 
177  return *this;
178 }
179 
182 {
183  octave_idx_type a_len = a.numel ();
184  if (beg < 0 || beg + a_len >= length ())
185  (*current_liboctave_error_handler) ("range error for fill");
186 
187  for (octave_idx_type i = 0; i < a_len; i++)
188  elem (i+beg, i+beg) = a.elem (i);
189 
190  return *this;
191 }
192 
195 {
196  octave_idx_type a_len = a.numel ();
197  if (beg < 0 || beg + a_len >= length ())
198  (*current_liboctave_error_handler) ("range error for fill");
199 
200  for (octave_idx_type i = 0; i < a_len; i++)
201  elem (i+beg, i+beg) = a.elem (i);
202 
203  return *this;
204 }
205 
208 {
209  return DiagMatrix (extract_diag ().abs (), rows (), columns ());
210 }
211 
214 {
215  return ComplexDiagMatrix (conj (a.extract_diag ()), a.rows (), a.columns ());
216 }
217 
218 // resize is the destructive analog for this one
219 
222  octave_idx_type r2, octave_idx_type c2) const
223 {
224  if (r1 > r2) { std::swap (r1, r2); }
225  if (c1 > c2) { std::swap (c1, c2); }
226 
227  octave_idx_type new_r = r2 - r1 + 1;
228  octave_idx_type new_c = c2 - c1 + 1;
229 
230  ComplexMatrix result (new_r, new_c);
231 
232  for (octave_idx_type j = 0; j < new_c; j++)
233  for (octave_idx_type i = 0; i < new_r; i++)
234  result.elem (i, j) = elem (r1+i, c1+j);
235 
236  return result;
237 }
238 
239 // extract row or column i.
240 
243 {
244  octave_idx_type r = rows ();
245  octave_idx_type c = cols ();
246  if (i < 0 || i >= r)
247  (*current_liboctave_error_handler) ("invalid row selection");
248 
249  ComplexRowVector retval (c, 0.0);
250  if (r <= c || (r > c && i < c))
251  retval.elem (i) = elem (i, i);
252 
253  return retval;
254 }
255 
258 {
259  if (! s)
260  (*current_liboctave_error_handler) ("invalid row selection");
261 
262  char c = *s;
263  if (c == 'f' || c == 'F')
264  return row (static_cast<octave_idx_type>(0));
265  else if (c == 'l' || c == 'L')
266  return row (rows () - 1);
267  else
268  (*current_liboctave_error_handler) ("invalid row selection");
269 }
270 
273 {
274  octave_idx_type r = rows ();
275  octave_idx_type c = cols ();
276  if (i < 0 || i >= c)
277  (*current_liboctave_error_handler) ("invalid column selection");
278 
279  ComplexColumnVector retval (r, 0.0);
280  if (r >= c || (r < c && i < r))
281  retval.elem (i) = elem (i, i);
282 
283  return retval;
284 }
285 
288 {
289  if (! s)
290  (*current_liboctave_error_handler) ("invalid column selection");
291 
292  char c = *s;
293  if (c == 'f' || c == 'F')
294  return column (static_cast<octave_idx_type>(0));
295  else if (c == 'l' || c == 'L')
296  return column (cols () - 1);
297  else
298  (*current_liboctave_error_handler) ("invalid column selection");
299 }
300 
303 {
304  octave_idx_type info;
305  return inverse (info);
306 }
307 
310 {
311  octave_idx_type r = rows ();
312  octave_idx_type c = cols ();
313  if (r != c)
314  (*current_liboctave_error_handler) ("inverse requires square matrix");
315 
317 
318  info = 0;
319  for (octave_idx_type i = 0; i < length (); i++)
320  {
321  if (elem (i, i) == 0.0)
322  {
323  info = -1;
324  return *this;
325  }
326  else
327  retval.elem (i, i) = 1.0 / elem (i, i);
328  }
329 
330  return retval;
331 }
332 
335 {
336  octave_idx_type r = rows ();
337  octave_idx_type c = cols ();
338  octave_idx_type len = length ();
339 
341 
342  for (octave_idx_type i = 0; i < len; i++)
343  {
344  double val = std::abs (elem (i, i));
345  if (val < tol || val == 0.0)
346  retval.elem (i, i) = 0.0;
347  else
348  retval.elem (i, i) = 1.0 / elem (i, i);
349  }
350 
351  return retval;
352 }
353 
354 bool
356 {
357  return mx_inline_all_real (length (), data ());
358 }
359 
360 // diagonal matrix by diagonal matrix -> diagonal matrix operations
361 
364 {
365  octave_idx_type r = rows ();
366  octave_idx_type c = cols ();
367 
368  octave_idx_type a_nr = a.rows ();
369  octave_idx_type a_nc = a.cols ();
370 
371  if (r != a_nr || c != a_nc)
372  octave::err_nonconformant ("operator +=", r, c, a_nr, a_nc);
373 
374  if (r == 0 || c == 0)
375  return *this;
376 
377  Complex *d = fortran_vec (); // Ensures only one reference to my privates!
378 
379  mx_inline_add2 (length (), d, a.data ());
380  return *this;
381 }
382 
385 {
386  octave_idx_type a_nr = a.rows ();
387  octave_idx_type a_nc = a.cols ();
388 
389  octave_idx_type b_nr = b.rows ();
390  octave_idx_type b_nc = b.cols ();
391 
392  if (a_nc != b_nr)
393  octave::err_nonconformant ("operator *", a_nr, a_nc, b_nr, b_nc);
394 
396 
397  octave_idx_type len = c.length ();
398  octave_idx_type lenm = (len < a_nc ? len : a_nc);
399 
400  for (octave_idx_type i = 0; i < lenm; i++)
401  c.dgxelem (i) = a.dgelem (i) * b.dgelem (i);
402  for (octave_idx_type i = lenm; i < len; i++)
403  c.dgxelem (i) = 0.0;
404 
405  return c;
406 }
407 
410 {
411  octave_idx_type a_nr = a.rows ();
412  octave_idx_type a_nc = a.cols ();
413 
414  octave_idx_type b_nr = b.rows ();
415  octave_idx_type b_nc = b.cols ();
416 
417  if (a_nc != b_nr)
418  octave::err_nonconformant ("operator *", a_nr, a_nc, b_nr, b_nc);
419 
420  if (a_nr == 0 || a_nc == 0 || b_nc == 0)
421  return ComplexDiagMatrix (a_nr, a_nc, 0.0);
422 
424 
425  octave_idx_type len = (a_nr < b_nc ? a_nr : b_nc);
426 
427  for (octave_idx_type i = 0; i < len; i++)
428  {
429  double a_element = a.elem (i, i);
430  Complex b_element = b.elem (i, i);
431 
432  c.elem (i, i) = a_element * b_element;
433  }
434 
435  return c;
436 }
437 
440 {
441  octave_idx_type a_nr = a.rows ();
442  octave_idx_type a_nc = a.cols ();
443 
444  octave_idx_type b_nr = b.rows ();
445  octave_idx_type b_nc = b.cols ();
446 
447  if (a_nc != b_nr)
448  octave::err_nonconformant ("operator *", a_nr, a_nc, b_nr, b_nc);
449 
450  if (a_nr == 0 || a_nc == 0 || b_nc == 0)
451  return ComplexDiagMatrix (a_nr, a_nc, 0.0);
452 
454 
455  octave_idx_type len = (a_nr < b_nc ? a_nr : b_nc);
456 
457  for (octave_idx_type i = 0; i < len; i++)
458  {
459  Complex a_element = a.elem (i, i);
460  Complex b_element = b.elem (i, i);
461 
462  c.elem (i, i) = a_element * b_element;
463  }
464 
465  return c;
466 }
467 
468 // other operations
469 
472 {
473  ComplexDET det (1.0);
474  if (rows () != cols ())
475  (*current_liboctave_error_handler) ("determinant requires square matrix");
476 
477  octave_idx_type len = length ();
478  for (octave_idx_type i = 0; i < len; i++)
479  det *= elem (i, i);
480 
481  return det;
482 }
483 
484 double
486 {
487  ColumnVector av = extract_diag (0).map<double> (std::abs);
488  double amx = av.max ();
489  double amn = av.min ();
490  return amx == 0 ? 0.0 : amn / amx;
491 }
492 
493 // i/o
494 
495 std::ostream&
496 operator << (std::ostream& os, const ComplexDiagMatrix& a)
497 {
498  Complex ZERO (0.0);
499 // int field_width = os.precision () + 7;
500  for (octave_idx_type i = 0; i < a.rows (); i++)
501  {
502  for (octave_idx_type j = 0; j < a.cols (); j++)
503  {
504  if (i == j)
505  os << ' ' /* setw (field_width) */ << a.elem (i, i);
506  else
507  os << ' ' /* setw (field_width) */ << ZERO;
508  }
509  os << "\n";
510  }
511  return os;
512 }
octave_idx_type rows(void) const
Definition: Array.h:404
void mx_inline_add2(size_t n, R *r, const X *x)
Definition: mx-inlines.cc:125
std::ostream & operator<<(std::ostream &os, const ComplexDiagMatrix &a)
Definition: CDiagMatrix.cc:496
identity matrix If supplied two scalar respectively For allows like xample val
Definition: data.cc:4986
ComplexDiagMatrix conj(const ComplexDiagMatrix &a)
Definition: CDiagMatrix.cc:213
OCTAVE_NORETURN liboctave_error_handler current_liboctave_error_handler
Definition: lo-error.c:38
ComplexColumnVector extract_diag(octave_idx_type k=0) const
Definition: CDiagMatrix.h:136
const Complex * fortran_vec(void) const
Definition: DiagArray2.h:169
octave_idx_type b_nr
Definition: sylvester.cc:76
static T abs(T x)
Definition: pr-output.cc:1696
octave_idx_type rows(void) const
Definition: DiagArray2.h:87
nd example oindent opens the file binary numeric values will be read assuming they are stored in IEEE format with the least significant bit and then converted to the native representation Opening a file that is already open simply opens it again and returns a separate file id It is not an error to open a file several though writing to the same file through several different file ids may produce unexpected results The possible values of text mode reading and writing automatically converts linefeeds to the appropriate line end character for the you may append a you must also open the file in binary mode The parameter conversions are currently only supported for and permissions will be set to and then everything is written in a single operation This is very efficient and improves performance c
Definition: file-io.cc:587
s
Definition: file-io.cc:2729
double min(void) const
Definition: dColVector.cc:243
octave_idx_type a_nc
Definition: sylvester.cc:74
Complex elem(octave_idx_type r, octave_idx_type c) const
Definition: DiagArray2.h:115
F77_RET_T const F77_REAL const F77_REAL F77_REAL &F77_RET_T const F77_DBLE const F77_DBLE F77_DBLE &F77_RET_T const F77_DBLE F77_DBLE &F77_RET_T const F77_REAL F77_REAL &F77_RET_T const F77_DBLE const F77_DBLE F77_DBLE * d
Template for two dimensional diagonal array with math operators.
Definition: MDiagArray2.h:32
ComplexDiagMatrix operator*(const ComplexDiagMatrix &a, const DiagMatrix &b)
Definition: CDiagMatrix.cc:384
octave_idx_type cols(void) const
Definition: Array.h:412
calling an anonymous function involves an overhead quite comparable to the overhead of an m file function Passing a handle to a built in function is because the interpreter is not involved in the internal loop For a
Definition: cellfun.cc:400
bool swap
Definition: load-save.cc:738
bool mx_inline_all_real(size_t n, const std::complex< T > *x)
Definition: mx-inlines.cc:308
bool all_elements_are_real(void) const
Definition: CDiagMatrix.cc:355
ComplexDiagMatrix pseudo_inverse(double tol=0.0) const
Definition: CDiagMatrix.cc:334
octave_idx_type length(void) const
Definition: DiagArray2.h:93
octave_idx_type cols(void) const
Definition: DiagArray2.h:88
octave_idx_type a_nr
Definition: sylvester.cc:73
DiagMatrix abs(void) const
Definition: CDiagMatrix.cc:207
double rcond(void) const
Definition: CDiagMatrix.cc:485
ComplexDiagMatrix & operator+=(const DiagMatrix &a)
Definition: CDiagMatrix.cc:363
Definition: DET.h:34
void err_nonconformant(const char *op, octave_idx_type op1_len, octave_idx_type op2_len)
octave_value retval
Definition: data.cc:6246
bool operator==(const ComplexDiagMatrix &a) const
Definition: CDiagMatrix.cc:47
bool operator!=(const ComplexDiagMatrix &a) const
Definition: CDiagMatrix.cc:56
ComplexDiagMatrix(void)
Definition: CDiagMatrix.h:48
With real return the complex result
Definition: data.cc:3260
ComplexDiagMatrix inverse(void) const
Definition: CDiagMatrix.cc:302
Array< U > map(F fcn) const
Apply function fcn to each element of the Array<T>.
Definition: Array.h:764
octave_idx_type b_nc
Definition: sylvester.cc:77
ComplexDiagMatrix & fill(double val)
Definition: CDiagMatrix.cc:62
ComplexMatrix extract(octave_idx_type r1, octave_idx_type c1, octave_idx_type r2, octave_idx_type c2) const
Definition: CDiagMatrix.cc:221
double max(void) const
Definition: dColVector.cc:259
b
Definition: cellfun.cc:400
octave_idx_type columns(void) const
Definition: DiagArray2.h:89
for i
Definition: data.cc:5264
ComplexRowVector row(octave_idx_type i) const
Definition: CDiagMatrix.cc:242
ComplexColumnVector column(octave_idx_type i) const
Definition: CDiagMatrix.cc:272
std::complex< double > Complex
Definition: oct-cmplx.h:31
bool mx_inline_equal(size_t n, const T1 *x, const T2 *y)
Definition: mx-inlines.cc:569
ComplexDET determinant(void) const
Definition: CDiagMatrix.cc:471
octave::stream os
Definition: file-io.cc:627
const Complex * data(void) const
Definition: DiagArray2.h:167