GNU Octave  3.8.0
A high-level interpreted language, primarily intended for numerical computations, mostly compatible with Matlab
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Pages
fCDiagMatrix.cc
Go to the documentation of this file.
1 // DiagMatrix manipulations.
2 /*
3 
4 Copyright (C) 1994-2013 John W. Eaton
5 Copyright (C) 2009 VZLU Prague
6 
7 This file is part of Octave.
8 
9 Octave is free software; you can redistribute it and/or modify it
10 under the terms of the GNU General Public License as published by the
11 Free Software Foundation; either version 3 of the License, or (at your
12 option) any later version.
13 
14 Octave is distributed in the hope that it will be useful, but WITHOUT
15 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
16 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
17 for more details.
18 
19 You should have received a copy of the GNU General Public License
20 along with Octave; see the file COPYING. If not, see
21 <http://www.gnu.org/licenses/>.
22 
23 */
24 
25 #ifdef HAVE_CONFIG_H
26 #include <config.h>
27 #endif
28 
29 #include <iostream>
30 
31 #include "Array-util.h"
32 #include "lo-error.h"
33 #include "lo-ieee.h"
34 #include "mx-base.h"
35 #include "mx-inlines.cc"
36 #include "oct-cmplx.h"
37 
38 // FloatComplex Diagonal Matrix class
39 
41  : MDiagArray2<FloatComplex> (a.rows (), a.cols ())
42 {
43  for (octave_idx_type i = 0; i < length (); i++)
44  elem (i, i) = a.elem (i, i);
45 }
46 
47 bool
49 {
50  if (rows () != a.rows () || cols () != a.cols ())
51  return 0;
52 
53  return mx_inline_equal (length (), data (), a.data ());
54 }
55 
56 bool
58 {
59  return !(*this == a);
60 }
61 
64 {
65  for (octave_idx_type i = 0; i < length (); i++)
66  elem (i, i) = val;
67  return *this;
68 }
69 
72 {
73  for (octave_idx_type i = 0; i < length (); i++)
74  elem (i, i) = val;
75  return *this;
76 }
77 
81 {
82  if (beg < 0 || end >= length () || end < beg)
83  {
84  (*current_liboctave_error_handler) ("range error for fill");
85  return *this;
86  }
87 
88  for (octave_idx_type i = beg; i <= end; i++)
89  elem (i, i) = val;
90 
91  return *this;
92 }
93 
97 {
98  if (beg < 0 || end >= length () || end < beg)
99  {
100  (*current_liboctave_error_handler) ("range error for fill");
101  return *this;
102  }
103 
104  for (octave_idx_type i = beg; i <= end; i++)
105  elem (i, i) = val;
106 
107  return *this;
108 }
109 
112 {
113  octave_idx_type len = length ();
114  if (a.length () != len)
115  {
116  (*current_liboctave_error_handler) ("range error for fill");
117  return *this;
118  }
119 
120  for (octave_idx_type i = 0; i < len; i++)
121  elem (i, i) = a.elem (i);
122 
123  return *this;
124 }
125 
128 {
129  octave_idx_type len = length ();
130  if (a.length () != len)
131  {
132  (*current_liboctave_error_handler) ("range error for fill");
133  return *this;
134  }
135 
136  for (octave_idx_type i = 0; i < len; i++)
137  elem (i, i) = a.elem (i);
138 
139  return *this;
140 }
141 
144 {
145  octave_idx_type len = length ();
146  if (a.length () != len)
147  {
148  (*current_liboctave_error_handler) ("range error for fill");
149  return *this;
150  }
151 
152  for (octave_idx_type i = 0; i < len; i++)
153  elem (i, i) = a.elem (i);
154 
155  return *this;
156 }
157 
160 {
161  octave_idx_type len = length ();
162  if (a.length () != len)
163  {
164  (*current_liboctave_error_handler) ("range error for fill");
165  return *this;
166  }
167 
168  for (octave_idx_type i = 0; i < len; i++)
169  elem (i, i) = a.elem (i);
170 
171  return *this;
172 }
173 
176 {
177  octave_idx_type a_len = a.length ();
178  if (beg < 0 || beg + a_len >= length ())
179  {
180  (*current_liboctave_error_handler) ("range error for fill");
181  return *this;
182  }
183 
184  for (octave_idx_type i = 0; i < a_len; i++)
185  elem (i+beg, i+beg) = a.elem (i);
186 
187  return *this;
188 }
189 
192  octave_idx_type beg)
193 {
194  octave_idx_type a_len = a.length ();
195  if (beg < 0 || beg + a_len >= length ())
196  {
197  (*current_liboctave_error_handler) ("range error for fill");
198  return *this;
199  }
200 
201  for (octave_idx_type i = 0; i < a_len; i++)
202  elem (i+beg, i+beg) = a.elem (i);
203 
204  return *this;
205 }
206 
209 {
210  octave_idx_type a_len = a.length ();
211  if (beg < 0 || beg + a_len >= length ())
212  {
213  (*current_liboctave_error_handler) ("range error for fill");
214  return *this;
215  }
216 
217  for (octave_idx_type i = 0; i < a_len; i++)
218  elem (i+beg, i+beg) = a.elem (i);
219 
220  return *this;
221 }
222 
225  octave_idx_type beg)
226 {
227  octave_idx_type a_len = a.length ();
228  if (beg < 0 || beg + a_len >= length ())
229  {
230  (*current_liboctave_error_handler) ("range error for fill");
231  return *this;
232  }
233 
234  for (octave_idx_type i = 0; i < a_len; i++)
235  elem (i+beg, i+beg) = a.elem (i);
236 
237  return *this;
238 }
239 
242 {
243  return FloatDiagMatrix (extract_diag ().abs (), rows (), columns ());
244 }
245 
248 {
249  return FloatComplexDiagMatrix (conj (a.extract_diag ()), a.rows (),
250  a.columns ());
251 }
252 
253 // resize is the destructive analog for this one
254 
258 {
259  if (r1 > r2) { std::swap (r1, r2); }
260  if (c1 > c2) { std::swap (c1, c2); }
261 
262  octave_idx_type new_r = r2 - r1 + 1;
263  octave_idx_type new_c = c2 - c1 + 1;
264 
265  FloatComplexMatrix result (new_r, new_c);
266 
267  for (octave_idx_type j = 0; j < new_c; j++)
268  for (octave_idx_type i = 0; i < new_r; i++)
269  result.elem (i, j) = elem (r1+i, c1+j);
270 
271  return result;
272 }
273 
274 // extract row or column i.
275 
278 {
279  octave_idx_type r = rows ();
280  octave_idx_type c = cols ();
281  if (i < 0 || i >= r)
282  {
283  (*current_liboctave_error_handler) ("invalid row selection");
284  return FloatComplexRowVector ();
285  }
286 
287  FloatComplexRowVector retval (c, 0.0);
288  if (r <= c || (r > c && i < c))
289  retval.elem (i) = elem (i, i);
290 
291  return retval;
292 }
293 
296 {
297  if (! s)
298  {
299  (*current_liboctave_error_handler) ("invalid row selection");
300  return FloatComplexRowVector ();
301  }
302 
303  char c = *s;
304  if (c == 'f' || c == 'F')
305  return row (static_cast<octave_idx_type>(0));
306  else if (c == 'l' || c == 'L')
307  return row (rows () - 1);
308  else
309  {
310  (*current_liboctave_error_handler) ("invalid row selection");
311  return FloatComplexRowVector ();
312  }
313 }
314 
317 {
318  octave_idx_type r = rows ();
319  octave_idx_type c = cols ();
320  if (i < 0 || i >= c)
321  {
322  (*current_liboctave_error_handler) ("invalid column selection");
323  return FloatComplexColumnVector ();
324  }
325 
326  FloatComplexColumnVector retval (r, 0.0);
327  if (r >= c || (r < c && i < r))
328  retval.elem (i) = elem (i, i);
329 
330  return retval;
331 }
332 
335 {
336  if (! s)
337  {
338  (*current_liboctave_error_handler) ("invalid column selection");
339  return FloatComplexColumnVector ();
340  }
341 
342  char c = *s;
343  if (c == 'f' || c == 'F')
344  return column (static_cast<octave_idx_type>(0));
345  else if (c == 'l' || c == 'L')
346  return column (cols () - 1);
347  else
348  {
349  (*current_liboctave_error_handler) ("invalid column selection");
350  return FloatComplexColumnVector ();
351  }
352 }
353 
356 {
357  octave_idx_type info;
358  return inverse (info);
359 }
360 
363 {
364  octave_idx_type r = rows ();
365  octave_idx_type c = cols ();
366  if (r != c)
367  {
368  (*current_liboctave_error_handler) ("inverse requires square matrix");
369  return FloatComplexDiagMatrix ();
370  }
371 
372  FloatComplexDiagMatrix retval (r, c);
373 
374  info = 0;
375  for (octave_idx_type i = 0; i < length (); i++)
376  {
377  if (elem (i, i) == static_cast<float> (0.0))
378  {
379  info = -1;
380  return *this;
381  }
382  else
383  retval.elem (i, i) = static_cast<float> (1.0) / elem (i, i);
384  }
385 
386  return retval;
387 }
388 
391 {
392  octave_idx_type r = rows ();
393  octave_idx_type c = cols ();
394  octave_idx_type len = length ();
395 
396  FloatComplexDiagMatrix retval (c, r);
397 
398  for (octave_idx_type i = 0; i < len; i++)
399  {
400  if (elem (i, i) != 0.0f)
401  retval.elem (i, i) = 1.0f / elem (i, i);
402  else
403  retval.elem (i, i) = 0.0f;
404  }
405 
406  return retval;
407 }
408 
409 bool
411 {
412  return mx_inline_all_real (length (), data ());
413 }
414 
415 // diagonal matrix by diagonal matrix -> diagonal matrix operations
416 
419 {
420  octave_idx_type r = rows ();
421  octave_idx_type c = cols ();
422 
423  octave_idx_type a_nr = a.rows ();
424  octave_idx_type a_nc = a.cols ();
425 
426  if (r != a_nr || c != a_nc)
427  {
428  gripe_nonconformant ("operator +=", r, c, a_nr, a_nc);
429  return *this;
430  }
431 
432  if (r == 0 || c == 0)
433  return *this;
434 
435  FloatComplex *d = fortran_vec (); // Ensures only 1 reference to my privates!
436 
437  mx_inline_add2 (length (), d, a.data ());
438  return *this;
439 }
440 
443 {
444  octave_idx_type a_nr = a.rows ();
445  octave_idx_type a_nc = a.cols ();
446 
447  octave_idx_type b_nr = b.rows ();
448  octave_idx_type b_nc = b.cols ();
449 
450  if (a_nc != b_nr)
451  gripe_nonconformant ("operator *", a_nr, a_nc, b_nr, b_nc);
452 
453  FloatComplexDiagMatrix c (a_nr, b_nc);
454 
455  octave_idx_type len = c.length (), lenm = len < a_nc ? len : a_nc;
456 
457  for (octave_idx_type i = 0; i < lenm; i++)
458  c.dgxelem (i) = a.dgelem (i) * b.dgelem (i);
459  for (octave_idx_type i = lenm; i < len; i++)
460  c.dgxelem (i) = 0.0f;
461 
462  return c;
463 }
464 
467 {
468  octave_idx_type a_nr = a.rows ();
469  octave_idx_type a_nc = a.cols ();
470 
471  octave_idx_type b_nr = b.rows ();
472  octave_idx_type b_nc = b.cols ();
473 
474  if (a_nc != b_nr)
475  {
476  gripe_nonconformant ("operator *", a_nr, a_nc, b_nr, b_nc);
477  return FloatComplexDiagMatrix ();
478  }
479 
480  if (a_nr == 0 || a_nc == 0 || b_nc == 0)
481  return FloatComplexDiagMatrix (a_nr, a_nc, 0.0);
482 
483  FloatComplexDiagMatrix c (a_nr, b_nc);
484 
485  octave_idx_type len = a_nr < b_nc ? a_nr : b_nc;
486 
487  for (octave_idx_type i = 0; i < len; i++)
488  {
489  float a_element = a.elem (i, i);
490  FloatComplex b_element = b.elem (i, i);
491 
492  c.elem (i, i) = a_element * b_element;
493  }
494 
495  return c;
496 }
497 
500 {
501  octave_idx_type a_nr = a.rows ();
502  octave_idx_type a_nc = a.cols ();
503 
504  octave_idx_type b_nr = b.rows ();
505  octave_idx_type b_nc = b.cols ();
506 
507  if (a_nc != b_nr)
508  {
509  gripe_nonconformant ("operator *", a_nr, a_nc, b_nr, b_nc);
510  return FloatComplexDiagMatrix ();
511  }
512 
513  if (a_nr == 0 || a_nc == 0 || b_nc == 0)
514  return FloatComplexDiagMatrix (a_nr, a_nc, 0.0);
515 
516  FloatComplexDiagMatrix c (a_nr, b_nc);
517 
518  octave_idx_type len = a_nr < b_nc ? a_nr : b_nc;
519 
520  for (octave_idx_type i = 0; i < len; i++)
521  {
522  FloatComplex a_element = a.elem (i, i);
523  FloatComplex b_element = b.elem (i, i);
524 
525  c.elem (i, i) = a_element * b_element;
526  }
527 
528  return c;
529 }
530 
531 // other operations
532 
535 {
536  FloatComplexDET det (1.0f);
537  if (rows () != cols ())
538  {
539  (*current_liboctave_error_handler) ("determinant requires square matrix");
540  det = FloatComplexDET (0.0);
541  }
542  else
543  {
544  octave_idx_type len = length ();
545  for (octave_idx_type i = 0; i < len; i++)
546  det *= elem (i, i);
547  }
548 
549  return det;
550 }
551 
552 float
554 {
555  FloatColumnVector av = extract_diag (0).map<float> (std::abs);
556  float amx = av.max (), amn = av.min ();
557  return amx == 0 ? 0.0f : amn / amx;
558 }
559 
560 // i/o
561 
562 std::ostream&
563 operator << (std::ostream& os, const FloatComplexDiagMatrix& a)
564 {
565  FloatComplex ZERO (0.0);
566 // int field_width = os.precision () + 7;
567  for (octave_idx_type i = 0; i < a.rows (); i++)
568  {
569  for (octave_idx_type j = 0; j < a.cols (); j++)
570  {
571  if (i == j)
572  os << " " /* setw (field_width) */ << a.elem (i, i);
573  else
574  os << " " /* setw (field_width) */ << ZERO;
575  }
576  os << "\n";
577  }
578  return os;
579 }