GNU Octave  9.1.0
A high-level interpreted language, primarily intended for numerical computations, mostly compatible with Matlab
MatrixType.cc
Go to the documentation of this file.
1 ////////////////////////////////////////////////////////////////////////
2 //
3 // Copyright (C) 2006-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 <cinttypes>
31 #include <vector>
32 
33 #include "MatrixType.h"
34 #include "dMatrix.h"
35 #include "fMatrix.h"
36 #include "CMatrix.h"
37 #include "fCMatrix.h"
38 #include "dSparse.h"
39 #include "CSparse.h"
40 #include "oct-spparms.h"
41 #include "oct-locbuf.h"
42 
43 static void
44 warn_cached ()
45 {
46  (*current_liboctave_warning_with_id_handler)
47  ("Octave:matrix-type-info", "using cached matrix type");
48 }
49 
50 static void
51 warn_invalid ()
52 {
53  (*current_liboctave_warning_with_id_handler)
54  ("Octave:matrix-type-info", "invalid matrix type");
55 }
56 
57 static void
58 warn_calculating_sparse_type ()
59 {
60  (*current_liboctave_warning_with_id_handler)
61  ("Octave:matrix-type-info", "calculating sparse matrix type");
62 }
63 
64 // FIXME: There is a large code duplication here
65 
67  : m_type (MatrixType::Unknown),
68  m_sp_bandden (octave::sparse_params::get_bandden ()),
69  m_bandden (0), m_upper_band (0), m_lower_band (0),
70  m_dense (false), m_full (false), m_nperm (0), m_perm (nullptr) { }
71 
73  : m_type (a.m_type), m_sp_bandden (a.m_sp_bandden), m_bandden (a.m_bandden),
74  m_upper_band (a.m_upper_band), m_lower_band (a.m_lower_band),
75  m_dense (a.m_dense), m_full (a.m_full),
76  m_nperm (a.m_nperm), m_perm (nullptr)
77 {
78  if (m_nperm != 0)
79  {
80  m_perm = new octave_idx_type [m_nperm];
81  for (octave_idx_type i = 0; i < m_nperm; i++)
82  m_perm[i] = a.m_perm[i];
83  }
84 }
85 
86 template <typename T>
89 {
91  octave_idx_type nrows = a.rows ();
92  octave_idx_type ncols = a.cols ();
93 
94  const T zero = 0;
95 
96  if (ncols == nrows)
97  {
98  bool upper = true;
99  bool lower = true;
100  bool hermitian = true;
101 
102  // do the checks for lower/upper/hermitian all in one pass.
103  OCTAVE_LOCAL_BUFFER (T, diag, ncols);
104 
105  for (octave_idx_type j = 0;
106  j < ncols && upper; j++)
107  {
108  T d = a.elem (j, j);
109  upper = upper && (d != zero);
110  lower = lower && (d != zero);
111  hermitian = hermitian && (d > zero);
112  diag[j] = d;
113  }
114 
115  for (octave_idx_type j = 0;
116  j < ncols && (upper || lower || hermitian); j++)
117  {
118  for (octave_idx_type i = 0; i < j; i++)
119  {
120  T aij = a.elem (i, j);
121  T aji = a.elem (j, i);
122  lower = lower && (aij == zero);
123  upper = upper && (aji == zero);
124  hermitian = hermitian && (aij == aji
125  && aij*aij < diag[i]*diag[j]);
126  }
127  }
128 
129  if (upper)
130  m_type = MatrixType::Upper;
131  else if (lower)
132  m_type = MatrixType::Lower;
133  else if (hermitian)
134  m_type = MatrixType::Hermitian;
135  else
136  m_type = MatrixType::Full;
137  }
138  else
139  m_type = MatrixType::Rectangular;
140 
141  return m_type;
142 }
143 
144 template <typename T>
146 matrix_complex_probe (const MArray<std::complex<T>>& a)
147 {
149  octave_idx_type nrows = a.rows ();
150  octave_idx_type ncols = a.cols ();
151 
152  const T zero = 0;
153  // get the real type
154 
155  if (ncols == nrows)
156  {
157  bool upper = true;
158  bool lower = true;
159  bool hermitian = true;
160 
161  // do the checks for lower/upper/hermitian all in one pass.
162  OCTAVE_LOCAL_BUFFER (T, diag, ncols);
163 
164  for (octave_idx_type j = 0;
165  j < ncols && upper; j++)
166  {
167  std::complex<T> d = a.elem (j, j);
168  upper = upper && (d != zero);
169  lower = lower && (d != zero);
170  hermitian = hermitian && (d.real () > zero && d.imag () == zero);
171  diag[j] = d.real ();
172  }
173 
174  for (octave_idx_type j = 0;
175  j < ncols && (upper || lower || hermitian); j++)
176  {
177  for (octave_idx_type i = 0; i < j; i++)
178  {
179  std::complex<T> aij = a.elem (i, j);
180  std::complex<T> aji = a.elem (j, i);
181  lower = lower && (aij == zero);
182  upper = upper && (aji == zero);
183  hermitian = hermitian && (aij == octave::math::conj (aji)
184  && std::norm (aij) < diag[i]*diag[j]);
185  }
186  }
187 
188  if (upper)
189  m_type = MatrixType::Upper;
190  else if (lower)
191  m_type = MatrixType::Lower;
192  else if (hermitian)
193  m_type = MatrixType::Hermitian;
194  else
195  m_type = MatrixType::Full;
196  }
197  else
198  m_type = MatrixType::Rectangular;
199 
200  return m_type;
201 }
202 
204  : m_type (MatrixType::Unknown),
205  m_sp_bandden (0), m_bandden (0), m_upper_band (0), m_lower_band (0),
206  m_dense (false), m_full (true), m_nperm (0), m_perm (nullptr)
207 {
208  m_type = matrix_real_probe (a);
209 }
210 
212  : m_type (MatrixType::Unknown),
213  m_sp_bandden (0), m_bandden (0), m_upper_band (0), m_lower_band (0),
214  m_dense (false), m_full (true), m_nperm (0), m_perm (nullptr)
215 {
216  m_type = matrix_complex_probe (a);
217 }
218 
220  : m_type (MatrixType::Unknown),
221  m_sp_bandden (0), m_bandden (0), m_upper_band (0), m_lower_band (0),
222  m_dense (false), m_full (true), m_nperm (0), m_perm (nullptr)
223 {
224  m_type = matrix_real_probe (a);
225 }
226 
228  : m_type (MatrixType::Unknown),
229  m_sp_bandden (0), m_bandden (0), m_upper_band (0), m_lower_band (0),
230  m_dense (false), m_full (true), m_nperm (0), m_perm (nullptr)
231 {
232  m_type = matrix_complex_probe (a);
233 }
234 
235 
236 template <typename T>
238  : m_type (MatrixType::Unknown),
239  m_sp_bandden (0), m_bandden (0), m_upper_band (0), m_lower_band (0),
240  m_dense (false), m_full (false), m_nperm (0), m_perm (nullptr)
241 {
242  octave_idx_type nrows = a.rows ();
243  octave_idx_type ncols = a.cols ();
244  octave_idx_type nm = (ncols < nrows ? ncols : nrows);
245  octave_idx_type nnz = a.nnz ();
246 
247  if (octave::sparse_params::get_key ("spumoni") != 0.)
248  warn_calculating_sparse_type ();
249 
250  m_sp_bandden = octave::sparse_params::get_bandden ();
251  bool maybe_hermitian = false;
252  m_type = MatrixType::Full;
253 
254  if (nnz == nm)
255  {
257  octave_idx_type i;
258  // Maybe the matrix is diagonal
259  for (i = 0; i < nm; i++)
260  {
261  if (a.cidx (i+1) != a.cidx (i) + 1)
262  {
263  tmp_typ = MatrixType::Full;
264  break;
265  }
266  if (a.ridx (i) != i)
267  {
269  break;
270  }
271  }
272 
273  if (tmp_typ == MatrixType::Permuted_Diagonal)
274  {
275  std::vector<bool> found (nrows);
276 
277  for (octave_idx_type j = 0; j < i; j++)
278  found[j] = true;
279  for (octave_idx_type j = i; j < nrows; j++)
280  found[j] = false;
281 
282  for (octave_idx_type j = i; j < nm; j++)
283  {
284  if ((a.cidx (j+1) > a.cidx (j) + 1)
285  || ((a.cidx (j+1) == a.cidx (j) + 1) && found[a.ridx (j)]))
286  {
287  tmp_typ = MatrixType::Full;
288  break;
289  }
290  found[a.ridx (j)] = true;
291  }
292  }
293  m_type = tmp_typ;
294  }
295 
296  if (m_type == MatrixType::Full)
297  {
298  // Search for banded, upper and lower triangular matrices
299  bool singular = false;
300  m_upper_band = 0;
301  m_lower_band = 0;
302  for (octave_idx_type j = 0; j < ncols; j++)
303  {
304  bool zero_on_diagonal = false;
305  if (j < nrows)
306  {
307  zero_on_diagonal = true;
308  for (octave_idx_type i = a.cidx (j); i < a.cidx (j+1); i++)
309  if (a.ridx (i) == j)
310  {
311  zero_on_diagonal = false;
312  break;
313  }
314  }
315 
316  if (zero_on_diagonal)
317  {
318  singular = true;
319  break;
320  }
321 
322  if (a.cidx (j+1) != a.cidx (j))
323  {
324  octave_idx_type ru = a.ridx (a.cidx (j));
325  octave_idx_type rl = a.ridx (a.cidx (j+1)-1);
326 
327  if (j - ru > m_upper_band)
328  m_upper_band = j - ru;
329 
330  if (rl - j > m_lower_band)
331  m_lower_band = rl - j;
332  }
333  }
334 
335  if (! singular)
336  {
337  m_bandden = double (nnz) /
338  (double (ncols) * (double (m_lower_band) +
339  double (m_upper_band)) -
340  0.5 * double (m_upper_band + 1) * double (m_upper_band) -
341  0.5 * double (m_lower_band + 1) * double (m_lower_band));
342 
343  if (nrows == ncols && m_sp_bandden != 1. && m_bandden > m_sp_bandden)
344  {
345  if (m_upper_band == 1 && m_lower_band == 1)
346  m_type = MatrixType::Tridiagonal;
347  else
348  m_type = MatrixType::Banded;
349 
350  octave_idx_type nnz_in_band
351  = ((m_upper_band + m_lower_band + 1) * nrows
352  - (1 + m_upper_band) * m_upper_band / 2
353  - (1 + m_lower_band) * m_lower_band / 2);
354 
355  if (nnz_in_band == nnz)
356  m_dense = true;
357  else
358  m_dense = false;
359  }
360 
361  // If a matrix is Banded but also Upper/Lower, set to the latter.
362  if (m_upper_band == 0)
363  m_type = MatrixType::Lower;
364  else if (m_lower_band == 0)
365  m_type = MatrixType::Upper;
366 
367  if (m_upper_band == m_lower_band && nrows == ncols)
368  maybe_hermitian = true;
369  }
370 
371  if (m_type == MatrixType::Full)
372  {
373  // Search for a permuted triangular matrix, and test if
374  // permutation is singular
375 
376  // FIXME: Perhaps this should be based on a dmperm algorithm?
377  bool found = false;
378 
379  m_nperm = ncols;
380  m_perm = new octave_idx_type [ncols];
381 
382  for (octave_idx_type i = 0; i < ncols; i++)
383  m_perm[i] = -1;
384 
385  for (octave_idx_type i = 0; i < nm; i++)
386  {
387  found = false;
388 
389  for (octave_idx_type j = 0; j < ncols; j++)
390  {
391  if ((a.cidx (j+1) - a.cidx (j)) > 0
392  && (a.ridx (a.cidx (j+1)-1) == i))
393  {
394  m_perm[i] = j;
395  found = true;
396  break;
397  }
398  }
399 
400  if (! found)
401  break;
402  }
403 
404  if (found)
405  {
407  if (ncols > nrows)
408  {
409  octave_idx_type k = nrows;
410  for (octave_idx_type i = 0; i < ncols; i++)
411  if (m_perm[i] == -1)
412  m_perm[i] = k++;
413  }
414  }
415  else if (a.cidx (nm) == a.cidx (ncols))
416  {
417  m_nperm = nrows;
418  delete [] m_perm;
419  m_perm = new octave_idx_type [nrows];
420  OCTAVE_LOCAL_BUFFER (octave_idx_type, tmp, nrows);
421 
422  for (octave_idx_type i = 0; i < nrows; i++)
423  {
424  m_perm[i] = -1;
425  tmp[i] = -1;
426  }
427 
428  for (octave_idx_type j = 0; j < ncols; j++)
429  for (octave_idx_type i = a.cidx (j); i < a.cidx (j+1); i++)
430  m_perm[a.ridx (i)] = j;
431 
432  found = true;
433  for (octave_idx_type i = 0; i < nm; i++)
434  if (m_perm[i] == -1)
435  {
436  found = false;
437  break;
438  }
439  else
440  {
441  tmp[m_perm[i]] = 1;
442  }
443 
444  if (found)
445  {
446  octave_idx_type k = ncols;
447  for (octave_idx_type i = 0; i < nrows; i++)
448  {
449  if (tmp[i] == -1)
450  {
451  if (k < nrows)
452  {
453  m_perm[k++] = i;
454  }
455  else
456  {
457  found = false;
458  break;
459  }
460  }
461  }
462  }
463 
464  if (found)
466  else
467  {
468  delete [] m_perm;
469  m_nperm = 0;
470  }
471  }
472  else
473  {
474  delete [] m_perm;
475  m_nperm = 0;
476  }
477  }
478 
479  // FIXME: Disable lower under-determined and upper over-determined
480  // problems as being detected, and force to treat as singular
481  // as this seems to cause issues.
482  if (((m_type == MatrixType::Lower
483  || m_type == MatrixType::Permuted_Lower)
484  && nrows > ncols)
485  || ((m_type == MatrixType::Upper
486  || m_type == MatrixType::Permuted_Upper)
487  && nrows < ncols))
488  {
489  if (m_type == MatrixType::Permuted_Upper
490  || m_type == MatrixType::Permuted_Lower)
491  delete [] m_perm;
492  m_nperm = 0;
493  m_type = MatrixType::Rectangular;
494  }
495 
496  if (m_type == MatrixType::Full && ncols != nrows)
497  m_type = MatrixType::Rectangular;
498 
499  if (maybe_hermitian && (m_type == MatrixType::Full
500  || m_type == MatrixType::Tridiagonal
501  || m_type == MatrixType::Banded))
502  {
503  bool is_herm = true;
504 
505  // first, check whether the diagonal is positive & extract it
506  ColumnVector diag (ncols);
507 
508  for (octave_idx_type j = 0; is_herm && j < ncols; j++)
509  {
510  is_herm = false;
511  for (octave_idx_type i = a.cidx (j); i < a.cidx (j+1); i++)
512  {
513  if (a.ridx (i) == j)
514  {
515  T d = a.data (i);
516  is_herm = (std::real (d) > 0.0
517  && std::imag (d) == 0.0);
518  diag(j) = std::real (d);
519  break;
520  }
521  }
522  }
523 
524  // next, check symmetry and 2x2 positiveness
525 
526  for (octave_idx_type j = 0; is_herm && j < ncols; j++)
527  for (octave_idx_type i = a.cidx (j); is_herm && i < a.cidx (j+1); i++)
528  {
529  octave_idx_type k = a.ridx (i);
530  is_herm = k == j;
531  if (is_herm)
532  continue;
533 
534  T d = a.data (i);
535  if (std::norm (d) < diag(j)*diag(k))
536  {
537  d = octave::math::conj (d);
538  for (octave_idx_type l = a.cidx (k); l < a.cidx (k+1); l++)
539  {
540  if (a.ridx (l) == j)
541  {
542  is_herm = a.data (l) == d;
543  break;
544  }
545  }
546  }
547  }
548 
549  if (is_herm)
550  {
551  if (m_type == MatrixType::Full)
552  m_type = MatrixType::Hermitian;
553  else if (m_type == MatrixType::Banded)
555  else
557  }
558  }
559  }
560 }
561 
562 
563 MatrixType::MatrixType (const matrix_type t, bool _full)
564  : m_type (MatrixType::Unknown),
565  m_sp_bandden (octave::sparse_params::get_bandden ()),
566  m_bandden (0), m_upper_band (0), m_lower_band (0),
567  m_dense (false), m_full (_full), m_nperm (0), m_perm (nullptr)
568 {
569  if (t == MatrixType::Unknown || t == MatrixType::Full
571  || t == MatrixType::Upper || t == MatrixType::Lower
573  || t == MatrixType::Rectangular)
574  m_type = t;
575  else
576  warn_invalid ();
577 }
578 
580  const octave_idx_type *p, bool _full)
581  : m_type (MatrixType::Unknown),
582  m_sp_bandden (octave::sparse_params::get_bandden ()),
583  m_bandden (0), m_upper_band (0), m_lower_band (0),
584  m_dense (false), m_full (_full), m_nperm (0), m_perm (nullptr)
585 {
587  && np > 0 && p != nullptr)
588  {
589  m_type = t;
590  m_nperm = np;
591  m_perm = new octave_idx_type [m_nperm];
592  for (octave_idx_type i = 0; i < m_nperm; i++)
593  m_perm[i] = p[i];
594  }
595  else
596  warn_invalid ();
597 }
598 
600  const octave_idx_type kl, bool _full)
601  : m_type (MatrixType::Unknown),
602  m_sp_bandden (octave::sparse_params::get_bandden ()),
603  m_bandden (0), m_upper_band (0), m_lower_band (0),
604  m_dense (false), m_full (_full), m_nperm (0), m_perm (nullptr)
605 {
607  {
608  m_type = t;
609  m_upper_band = ku;
610  m_lower_band = kl;
611  }
612  else
613  warn_invalid ();
614 }
615 
617 {
618  if (m_nperm != 0)
619  {
620  delete [] m_perm;
621  }
622 }
623 
624 MatrixType&
626 {
627  if (this != &a)
628  {
629  m_type = a.m_type;
630  m_sp_bandden = a.m_sp_bandden;
631  m_bandden = a.m_bandden;
632  m_upper_band = a.m_upper_band;
633  m_lower_band = a.m_lower_band;
634  m_dense = a.m_dense;
635  m_full = a.m_full;
636 
637  if (m_nperm)
638  {
639  delete[] m_perm;
640  }
641 
642  if (a.m_nperm != 0)
643  {
644  m_perm = new octave_idx_type [a.m_nperm];
645  for (octave_idx_type i = 0; i < a.m_nperm; i++)
646  m_perm[i] = a.m_perm[i];
647  }
648 
649  m_nperm = a.m_nperm;
650  }
651 
652  return *this;
653 }
654 
655 int
656 MatrixType::type (bool quiet)
657 {
658  if (m_type != MatrixType::Unknown
659  && (m_full || m_sp_bandden == octave::sparse_params::get_bandden ()))
660  {
661  if (! quiet && octave::sparse_params::get_key ("spumoni") != 0.)
662  warn_cached ();
663 
664  return m_type;
665  }
666 
667  if (m_type != MatrixType::Unknown
668  && octave::sparse_params::get_key ("spumoni") != 0.)
669  (*current_liboctave_warning_with_id_handler)
670  ("Octave:matrix-type-info", "invalidating matrix type");
671 
672  m_type = MatrixType::Unknown;
673 
674  return m_type;
675 }
676 
677 int
679 {
680  if (m_type != MatrixType::Unknown
681  && (m_full || m_sp_bandden == octave::sparse_params::get_bandden ()))
682  {
683  if (octave::sparse_params::get_key ("spumoni") != 0.)
684  warn_cached ();
685 
686  return m_type;
687  }
688 
689  MatrixType tmp_typ (a);
690  m_type = tmp_typ.m_type;
691  m_sp_bandden = tmp_typ.m_sp_bandden;
692  m_bandden = tmp_typ.m_bandden;
693  m_upper_band = tmp_typ.m_upper_band;
694  m_lower_band = tmp_typ.m_lower_band;
695  m_dense = tmp_typ.m_dense;
696  m_full = tmp_typ.m_full;
697  m_nperm = tmp_typ.m_nperm;
698 
699  if (m_nperm != 0)
700  {
701  m_perm = new octave_idx_type [m_nperm];
702  for (octave_idx_type i = 0; i < m_nperm; i++)
703  m_perm[i] = tmp_typ.m_perm[i];
704  }
705 
706  return m_type;
707 }
708 
709 int
711 {
712  if (m_type != MatrixType::Unknown
713  && (m_full || m_sp_bandden == octave::sparse_params::get_bandden ()))
714  {
715  if (octave::sparse_params::get_key ("spumoni") != 0.)
716  warn_cached ();
717 
718  return m_type;
719  }
720 
721  MatrixType tmp_typ (a);
722  m_type = tmp_typ.m_type;
723  m_sp_bandden = tmp_typ.m_sp_bandden;
724  m_bandden = tmp_typ.m_bandden;
725  m_upper_band = tmp_typ.m_upper_band;
726  m_lower_band = tmp_typ.m_lower_band;
727  m_dense = tmp_typ.m_dense;
728  m_full = tmp_typ.m_full;
729  m_nperm = tmp_typ.m_nperm;
730 
731  if (m_nperm != 0)
732  {
733  m_perm = new octave_idx_type [m_nperm];
734  for (octave_idx_type i = 0; i < m_nperm; i++)
735  m_perm[i] = tmp_typ.m_perm[i];
736  }
737 
738  return m_type;
739 }
740 
741 int
743 {
744  if (m_type != MatrixType::Unknown)
745  {
746  if (octave::sparse_params::get_key ("spumoni") != 0.)
747  warn_cached ();
748 
749  return m_type;
750  }
751 
752  MatrixType tmp_typ (a);
753  m_type = tmp_typ.m_type;
754  m_full = tmp_typ.m_full;
755  m_nperm = tmp_typ.m_nperm;
756 
757  if (m_nperm != 0)
758  {
759  m_perm = new octave_idx_type [m_nperm];
760  for (octave_idx_type i = 0; i < m_nperm; i++)
761  m_perm[i] = tmp_typ.m_perm[i];
762  }
763 
764  return m_type;
765 }
766 
767 int
769 {
770  if (m_type != MatrixType::Unknown)
771  {
772  if (octave::sparse_params::get_key ("spumoni") != 0.)
773  warn_cached ();
774 
775  return m_type;
776  }
777 
778  MatrixType tmp_typ (a);
779  m_type = tmp_typ.m_type;
780  m_full = tmp_typ.m_full;
781  m_nperm = tmp_typ.m_nperm;
782 
783  if (m_nperm != 0)
784  {
785  m_perm = new octave_idx_type [m_nperm];
786  for (octave_idx_type i = 0; i < m_nperm; i++)
787  m_perm[i] = tmp_typ.m_perm[i];
788  }
789 
790  return m_type;
791 }
792 
793 int
795 {
796  if (m_type != MatrixType::Unknown)
797  {
798  if (octave::sparse_params::get_key ("spumoni") != 0.)
799  warn_cached ();
800 
801  return m_type;
802  }
803 
804  MatrixType tmp_typ (a);
805  m_type = tmp_typ.m_type;
806  m_full = tmp_typ.m_full;
807  m_nperm = tmp_typ.m_nperm;
808 
809  if (m_nperm != 0)
810  {
811  m_perm = new octave_idx_type [m_nperm];
812  for (octave_idx_type i = 0; i < m_nperm; i++)
813  m_perm[i] = tmp_typ.m_perm[i];
814  }
815 
816  return m_type;
817 }
818 
819 int
821 {
822  if (m_type != MatrixType::Unknown)
823  {
824  if (octave::sparse_params::get_key ("spumoni") != 0.)
825  warn_cached ();
826 
827  return m_type;
828  }
829 
830  MatrixType tmp_typ (a);
831  m_type = tmp_typ.m_type;
832  m_full = tmp_typ.m_full;
833  m_nperm = tmp_typ.m_nperm;
834 
835  if (m_nperm != 0)
836  {
837  m_perm = new octave_idx_type [m_nperm];
838  for (octave_idx_type i = 0; i < m_nperm; i++)
839  m_perm[i] = tmp_typ.m_perm[i];
840  }
841 
842  return m_type;
843 }
844 
845 void
847 {
848  if (octave::sparse_params::get_key ("spumoni") != 0.)
849  {
850  if (m_type == MatrixType::Unknown)
851  (*current_liboctave_warning_with_id_handler)
852  ("Octave:matrix-type-info", "unknown matrix type");
853  else if (m_type == MatrixType::Diagonal)
854  (*current_liboctave_warning_with_id_handler)
855  ("Octave:matrix-type-info", "diagonal sparse matrix");
856  else if (m_type == MatrixType::Permuted_Diagonal)
857  (*current_liboctave_warning_with_id_handler)
858  ("Octave:matrix-type-info", "permuted diagonal sparse matrix");
859  else if (m_type == MatrixType::Upper)
860  (*current_liboctave_warning_with_id_handler)
861  ("Octave:matrix-type-info", "upper triangular matrix");
862  else if (m_type == MatrixType::Lower)
863  (*current_liboctave_warning_with_id_handler)
864  ("Octave:matrix-type-info", "lower triangular matrix");
865  else if (m_type == MatrixType::Permuted_Upper)
866  (*current_liboctave_warning_with_id_handler)
867  ("Octave:matrix-type-info", "permuted upper triangular matrix");
868  else if (m_type == MatrixType::Permuted_Lower)
869  (*current_liboctave_warning_with_id_handler)
870  ("Octave:matrix-type-info", "permuted lower triangular Matrix");
871  else if (m_type == MatrixType::Banded)
872  (*current_liboctave_warning_with_id_handler)
873  ("Octave:matrix-type-info",
874  "banded sparse matrix %" OCTAVE_IDX_TYPE_FORMAT "-1-"
875  "%" OCTAVE_IDX_TYPE_FORMAT " (density %f)",
876  m_lower_band, m_upper_band, m_bandden);
877  else if (m_type == MatrixType::Banded_Hermitian)
878  (*current_liboctave_warning_with_id_handler)
879  ("Octave:matrix-type-info",
880  "banded hermitian/symmetric sparse matrix %" OCTAVE_IDX_TYPE_FORMAT
881  "-1-%" OCTAVE_IDX_TYPE_FORMAT " (density %f)",
882  m_lower_band, m_upper_band, m_bandden);
883  else if (m_type == MatrixType::Hermitian)
884  (*current_liboctave_warning_with_id_handler)
885  ("Octave:matrix-type-info", "hermitian/symmetric matrix");
886  else if (m_type == MatrixType::Tridiagonal)
887  (*current_liboctave_warning_with_id_handler)
888  ("Octave:matrix-type-info", "tridiagonal sparse matrix");
889  else if (m_type == MatrixType::Tridiagonal_Hermitian)
890  (*current_liboctave_warning_with_id_handler)
891  ("Octave:matrix-type-info",
892  "hermitian/symmetric tridiagonal sparse matrix");
893  else if (m_type == MatrixType::Rectangular)
894  (*current_liboctave_warning_with_id_handler)
895  ("Octave:matrix-type-info", "rectangular/singular matrix");
896  else if (m_type == MatrixType::Full)
897  (*current_liboctave_warning_with_id_handler)
898  ("Octave:matrix-type-info", "m_full matrix");
899  }
900 }
901 
902 void
904 {
905  if (m_type == MatrixType::Tridiagonal
908  else if (m_type == MatrixType::Banded
909  || m_type == MatrixType::Banded_Hermitian)
911  else if (m_type == MatrixType::Full || m_type == MatrixType::Hermitian
912  || m_type == MatrixType::Unknown)
913  m_type = MatrixType::Hermitian;
914  else
916  ("Can not mark current matrix type as symmetric");
917 }
918 
919 void
921 {
922  if (m_type == MatrixType::Tridiagonal
924  m_type = MatrixType::Tridiagonal;
925  else if (m_type == MatrixType::Banded
926  || m_type == MatrixType::Banded_Hermitian)
927  m_type = MatrixType::Banded;
928  else if (m_type == MatrixType::Full || m_type == MatrixType::Hermitian
929  || m_type == MatrixType::Unknown)
930  m_type = MatrixType::Full;
931 }
932 
933 void
935  const octave_idx_type *p)
936 {
937  m_nperm = np;
938  m_perm = new octave_idx_type [m_nperm];
939  for (octave_idx_type i = 0; i < m_nperm; i++)
940  m_perm[i] = p[i];
941 
942  if (m_type == MatrixType::Diagonal
943  || m_type == MatrixType::Permuted_Diagonal)
945  else if (m_type == MatrixType::Upper || m_type == MatrixType::Permuted_Upper)
947  else if (m_type == MatrixType::Lower || m_type == MatrixType::Permuted_Lower)
949  else
951  ("Can not mark current matrix type as symmetric");
952 }
953 
954 void
956 {
957  if (m_nperm)
958  {
959  m_nperm = 0;
960  delete [] m_perm;
961  }
962 
963  if (m_type == MatrixType::Diagonal
964  || m_type == MatrixType::Permuted_Diagonal)
965  m_type = MatrixType::Diagonal;
966  else if (m_type == MatrixType::Upper || m_type == MatrixType::Permuted_Upper)
967  m_type = MatrixType::Upper;
968  else if (m_type == MatrixType::Lower || m_type == MatrixType::Permuted_Lower)
969  m_type = MatrixType::Lower;
970 }
971 
974 {
975  MatrixType retval (*this);
976  if (m_type == MatrixType::Upper)
977  retval.m_type = MatrixType::Lower;
978  else if (m_type == MatrixType::Permuted_Upper)
979  retval.m_type = MatrixType::Permuted_Lower;
980  else if (m_type == MatrixType::Lower)
981  retval.m_type = MatrixType::Upper;
982  else if (m_type == MatrixType::Permuted_Lower)
983  retval.m_type = MatrixType::Permuted_Upper;
984  else if (m_type == MatrixType::Banded)
985  {
986  retval.m_upper_band = m_lower_band;
987  retval.m_lower_band = m_upper_band;
988  }
989 
990  return retval;
991 }
992 
993 // Instantiate MatrixType template constructors that we need.
994 
995 template MatrixType::MatrixType (const MSparse<double>&);
996 template MatrixType::MatrixType (const MSparse<Complex>&);
ComplexColumnVector conj(const ComplexColumnVector &a)
Definition: CColVector.cc:217
MatrixType::matrix_type matrix_real_probe(const MArray< T > &a)
Definition: MatrixType.cc:88
MatrixType::matrix_type matrix_complex_probe(const MArray< std::complex< T >> &a)
Definition: MatrixType.cc:146
T & elem(octave_idx_type n)
Size of the specified dimension.
Definition: Array.h:562
octave_idx_type rows() const
Definition: Array.h:459
octave_idx_type cols() const
Definition: Array.h:469
Template for N-dimensional array classes with like-type math operators.
Definition: MArray.h:63
void mark_as_unsymmetric()
Definition: MatrixType.cc:920
@ Tridiagonal_Hermitian
Definition: MatrixType.h:53
@ Permuted_Lower
Definition: MatrixType.h:48
@ Banded_Hermitian
Definition: MatrixType.h:51
@ Permuted_Diagonal
Definition: MatrixType.h:44
@ Permuted_Upper
Definition: MatrixType.h:47
void mark_as_permuted(const octave_idx_type np, const octave_idx_type *p)
Definition: MatrixType.cc:934
void mark_as_unpermuted()
Definition: MatrixType.cc:955
MatrixType & operator=(const MatrixType &a)
Definition: MatrixType.cc:625
void mark_as_symmetric()
Definition: MatrixType.cc:903
void info() const
Definition: MatrixType.cc:846
MatrixType transpose() const
Definition: MatrixType.cc:973
int type(bool quiet=true)
Definition: MatrixType.cc:656
Definition: dMatrix.h:42
octave_idx_type cols() const
Definition: Sparse.h:352
octave_idx_type * cidx()
Definition: Sparse.h:596
T * data()
Definition: Sparse.h:574
octave_idx_type * ridx()
Definition: Sparse.h:583
octave_idx_type nnz() const
Actual number of nonzero terms.
Definition: Sparse.h:339
octave_idx_type rows() const
Definition: Sparse.h:351
ColumnVector real(const ComplexColumnVector &a)
Definition: dColVector.cc:137
ColumnVector imag(const ComplexColumnVector &a)
Definition: dColVector.cc:143
double norm(const ColumnVector &v)
Definition: graphics.cc:5547
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
#define OCTAVE_LOCAL_BUFFER(T, buf, size)
Definition: oct-locbuf.h:44