Mercurial > octave
view liboctave/array/MatrixType.cc @ 30564:796f54d4ddbf stable
update Octave Project Developers copyright for the new year
In files that have the "Octave Project Developers" copyright notice,
update for 2021.
In all .txi and .texi files except gpl.txi and gpl.texi in the
doc/liboctave and doc/interpreter directories, change the copyright
to "Octave Project Developers", the same as used for other source
files. Update copyright notices for 2022 (not done since 2019). For
gpl.txi and gpl.texi, change the copyright notice to be "Free Software
Foundation, Inc." and leave the date at 2007 only because this file
only contains the text of the GPL, not anything created by the Octave
Project Developers.
Add Paul Thomas to contributors.in.
author | John W. Eaton <jwe@octave.org> |
---|---|
date | Tue, 28 Dec 2021 18:22:40 -0500 |
parents | f3f3e3793fb5 |
children | 597f3ee61a48 |
line wrap: on
line source
//////////////////////////////////////////////////////////////////////// // // Copyright (C) 2006-2022 The Octave Project Developers // // See the file COPYRIGHT.md in the top-level directory of this // distribution or <https://octave.org/copyright/>. // // This file is part of Octave. // // Octave is free software: you can redistribute it and/or modify it // under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // Octave is distributed in the hope that it will be useful, but // WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with Octave; see the file COPYING. If not, see // <https://www.gnu.org/licenses/>. // //////////////////////////////////////////////////////////////////////// #if defined (HAVE_CONFIG_H) # include "config.h" #endif #include <cinttypes> #include <vector> #include "MatrixType.h" #include "dMatrix.h" #include "fMatrix.h" #include "CMatrix.h" #include "fCMatrix.h" #include "dSparse.h" #include "CSparse.h" #include "oct-spparms.h" #include "oct-locbuf.h" static void warn_cached (void) { (*current_liboctave_warning_with_id_handler) ("Octave:matrix-type-info", "using cached matrix type"); } static void warn_invalid (void) { (*current_liboctave_warning_with_id_handler) ("Octave:matrix-type-info", "invalid matrix type"); } static void warn_calculating_sparse_type (void) { (*current_liboctave_warning_with_id_handler) ("Octave:matrix-type-info", "calculating sparse matrix type"); } // FIXME: There is a large code duplication here MatrixType::MatrixType (void) : m_type (MatrixType::Unknown), m_sp_bandden (octave::sparse_params::get_bandden ()), m_bandden (0), m_upper_band (0), m_lower_band (0), m_dense (false), m_full (false), m_nperm (0), m_perm (nullptr) { } MatrixType::MatrixType (const MatrixType& a) : m_type (a.m_type), m_sp_bandden (a.m_sp_bandden), m_bandden (a.m_bandden), m_upper_band (a.m_upper_band), m_lower_band (a.m_lower_band), m_dense (a.m_dense), m_full (a.m_full), m_nperm (a.m_nperm), m_perm (nullptr) { if (m_nperm != 0) { m_perm = new octave_idx_type [m_nperm]; for (octave_idx_type i = 0; i < m_nperm; i++) m_perm[i] = a.m_perm[i]; } } template <typename T> MatrixType::matrix_type matrix_real_probe (const MArray<T>& a) { MatrixType::matrix_type m_type; octave_idx_type nrows = a.rows (); octave_idx_type ncols = a.cols (); const T zero = 0; if (ncols == nrows) { bool upper = true; bool lower = true; bool hermitian = true; // do the checks for lower/upper/hermitian all in one pass. OCTAVE_LOCAL_BUFFER (T, diag, ncols); for (octave_idx_type j = 0; j < ncols && upper; j++) { T d = a.elem (j, j); upper = upper && (d != zero); lower = lower && (d != zero); hermitian = hermitian && (d > zero); diag[j] = d; } for (octave_idx_type j = 0; j < ncols && (upper || lower || hermitian); j++) { for (octave_idx_type i = 0; i < j; i++) { T aij = a.elem (i, j); T aji = a.elem (j, i); lower = lower && (aij == zero); upper = upper && (aji == zero); hermitian = hermitian && (aij == aji && aij*aij < diag[i]*diag[j]); } } if (upper) m_type = MatrixType::Upper; else if (lower) m_type = MatrixType::Lower; else if (hermitian) m_type = MatrixType::Hermitian; else m_type = MatrixType::Full; } else m_type = MatrixType::Rectangular; return m_type; } template <typename T> MatrixType::matrix_type matrix_complex_probe (const MArray<std::complex<T>>& a) { MatrixType::matrix_type m_type = MatrixType::Unknown; octave_idx_type nrows = a.rows (); octave_idx_type ncols = a.cols (); const T zero = 0; // get the real type if (ncols == nrows) { bool upper = true; bool lower = true; bool hermitian = true; // do the checks for lower/upper/hermitian all in one pass. OCTAVE_LOCAL_BUFFER (T, diag, ncols); for (octave_idx_type j = 0; j < ncols && upper; j++) { std::complex<T> d = a.elem (j, j); upper = upper && (d != zero); lower = lower && (d != zero); hermitian = hermitian && (d.real () > zero && d.imag () == zero); diag[j] = d.real (); } for (octave_idx_type j = 0; j < ncols && (upper || lower || hermitian); j++) { for (octave_idx_type i = 0; i < j; i++) { std::complex<T> aij = a.elem (i, j); std::complex<T> aji = a.elem (j, i); lower = lower && (aij == zero); upper = upper && (aji == zero); hermitian = hermitian && (aij == octave::math::conj (aji) && std::norm (aij) < diag[i]*diag[j]); } } if (upper) m_type = MatrixType::Upper; else if (lower) m_type = MatrixType::Lower; else if (hermitian) m_type = MatrixType::Hermitian; else m_type = MatrixType::Full; } else m_type = MatrixType::Rectangular; return m_type; } MatrixType::MatrixType (const Matrix& a) : m_type (MatrixType::Unknown), m_sp_bandden (0), m_bandden (0), m_upper_band (0), m_lower_band (0), m_dense (false), m_full (true), m_nperm (0), m_perm (nullptr) { m_type = matrix_real_probe (a); } MatrixType::MatrixType (const ComplexMatrix& a) : m_type (MatrixType::Unknown), m_sp_bandden (0), m_bandden (0), m_upper_band (0), m_lower_band (0), m_dense (false), m_full (true), m_nperm (0), m_perm (nullptr) { m_type = matrix_complex_probe (a); } MatrixType::MatrixType (const FloatMatrix& a) : m_type (MatrixType::Unknown), m_sp_bandden (0), m_bandden (0), m_upper_band (0), m_lower_band (0), m_dense (false), m_full (true), m_nperm (0), m_perm (nullptr) { m_type = matrix_real_probe (a); } MatrixType::MatrixType (const FloatComplexMatrix& a) : m_type (MatrixType::Unknown), m_sp_bandden (0), m_bandden (0), m_upper_band (0), m_lower_band (0), m_dense (false), m_full (true), m_nperm (0), m_perm (nullptr) { m_type = matrix_complex_probe (a); } template <typename T> MatrixType::MatrixType (const MSparse<T>& a) : m_type (MatrixType::Unknown), m_sp_bandden (0), m_bandden (0), m_upper_band (0), m_lower_band (0), m_dense (false), m_full (false), m_nperm (0), m_perm (nullptr) { octave_idx_type nrows = a.rows (); octave_idx_type ncols = a.cols (); octave_idx_type nm = (ncols < nrows ? ncols : nrows); octave_idx_type nnz = a.nnz (); if (octave::sparse_params::get_key ("spumoni") != 0.) warn_calculating_sparse_type (); m_sp_bandden = octave::sparse_params::get_bandden (); bool maybe_hermitian = false; m_type = MatrixType::Full; if (nnz == nm) { matrix_type tmp_typ = MatrixType::Diagonal; octave_idx_type i; // Maybe the matrix is diagonal for (i = 0; i < nm; i++) { if (a.cidx (i+1) != a.cidx (i) + 1) { tmp_typ = MatrixType::Full; break; } if (a.ridx (i) != i) { tmp_typ = MatrixType::Permuted_Diagonal; break; } } if (tmp_typ == MatrixType::Permuted_Diagonal) { std::vector<bool> found (nrows); for (octave_idx_type j = 0; j < i; j++) found[j] = true; for (octave_idx_type j = i; j < nrows; j++) found[j] = false; for (octave_idx_type j = i; j < nm; j++) { if ((a.cidx (j+1) > a.cidx (j) + 1) || ((a.cidx (j+1) == a.cidx (j) + 1) && found[a.ridx (j)])) { tmp_typ = MatrixType::Full; break; } found[a.ridx (j)] = true; } } m_type = tmp_typ; } if (m_type == MatrixType::Full) { // Search for banded, upper and lower triangular matrices bool singular = false; m_upper_band = 0; m_lower_band = 0; for (octave_idx_type j = 0; j < ncols; j++) { bool zero_on_diagonal = false; if (j < nrows) { zero_on_diagonal = true; for (octave_idx_type i = a.cidx (j); i < a.cidx (j+1); i++) if (a.ridx (i) == j) { zero_on_diagonal = false; break; } } if (zero_on_diagonal) { singular = true; break; } if (a.cidx (j+1) != a.cidx (j)) { octave_idx_type ru = a.ridx (a.cidx (j)); octave_idx_type rl = a.ridx (a.cidx (j+1)-1); if (j - ru > m_upper_band) m_upper_band = j - ru; if (rl - j > m_lower_band) m_lower_band = rl - j; } } if (! singular) { m_bandden = double (nnz) / (double (ncols) * (double (m_lower_band) + double (m_upper_band)) - 0.5 * double (m_upper_band + 1) * double (m_upper_band) - 0.5 * double (m_lower_band + 1) * double (m_lower_band)); if (nrows == ncols && m_sp_bandden != 1. && m_bandden > m_sp_bandden) { if (m_upper_band == 1 && m_lower_band == 1) m_type = MatrixType::Tridiagonal; else m_type = MatrixType::Banded; octave_idx_type nnz_in_band = ((m_upper_band + m_lower_band + 1) * nrows - (1 + m_upper_band) * m_upper_band / 2 - (1 + m_lower_band) * m_lower_band / 2); if (nnz_in_band == nnz) m_dense = true; else m_dense = false; } // If a matrix is Banded but also Upper/Lower, set to the latter. if (m_upper_band == 0) m_type = MatrixType::Lower; else if (m_lower_band == 0) m_type = MatrixType::Upper; if (m_upper_band == m_lower_band && nrows == ncols) maybe_hermitian = true; } if (m_type == MatrixType::Full) { // Search for a permuted triangular matrix, and test if // permutation is singular // FIXME: Perhaps this should be based on a dmperm algorithm? bool found = false; m_nperm = ncols; m_perm = new octave_idx_type [ncols]; for (octave_idx_type i = 0; i < ncols; i++) m_perm[i] = -1; for (octave_idx_type i = 0; i < nm; i++) { found = false; for (octave_idx_type j = 0; j < ncols; j++) { if ((a.cidx (j+1) - a.cidx (j)) > 0 && (a.ridx (a.cidx (j+1)-1) == i)) { m_perm[i] = j; found = true; break; } } if (! found) break; } if (found) { m_type = MatrixType::Permuted_Upper; if (ncols > nrows) { octave_idx_type k = nrows; for (octave_idx_type i = 0; i < ncols; i++) if (m_perm[i] == -1) m_perm[i] = k++; } } else if (a.cidx (nm) == a.cidx (ncols)) { m_nperm = nrows; delete [] m_perm; m_perm = new octave_idx_type [nrows]; OCTAVE_LOCAL_BUFFER (octave_idx_type, tmp, nrows); for (octave_idx_type i = 0; i < nrows; i++) { m_perm[i] = -1; tmp[i] = -1; } for (octave_idx_type j = 0; j < ncols; j++) for (octave_idx_type i = a.cidx (j); i < a.cidx (j+1); i++) m_perm[a.ridx (i)] = j; found = true; for (octave_idx_type i = 0; i < nm; i++) if (m_perm[i] == -1) { found = false; break; } else { tmp[m_perm[i]] = 1; } if (found) { octave_idx_type k = ncols; for (octave_idx_type i = 0; i < nrows; i++) { if (tmp[i] == -1) { if (k < nrows) { m_perm[k++] = i; } else { found = false; break; } } } } if (found) m_type = MatrixType::Permuted_Lower; else { delete [] m_perm; m_nperm = 0; } } else { delete [] m_perm; m_nperm = 0; } } // FIXME: Disable lower under-determined and upper over-determined // problems as being detected, and force to treat as singular // as this seems to cause issues. if (((m_type == MatrixType::Lower || m_type == MatrixType::Permuted_Lower) && nrows > ncols) || ((m_type == MatrixType::Upper || m_type == MatrixType::Permuted_Upper) && nrows < ncols)) { if (m_type == MatrixType::Permuted_Upper || m_type == MatrixType::Permuted_Lower) delete [] m_perm; m_nperm = 0; m_type = MatrixType::Rectangular; } if (m_type == MatrixType::Full && ncols != nrows) m_type = MatrixType::Rectangular; if (maybe_hermitian && (m_type == MatrixType::Full || m_type == MatrixType::Tridiagonal || m_type == MatrixType::Banded)) { bool is_herm = true; // first, check whether the diagonal is positive & extract it ColumnVector diag (ncols); for (octave_idx_type j = 0; is_herm && j < ncols; j++) { is_herm = false; for (octave_idx_type i = a.cidx (j); i < a.cidx (j+1); i++) { if (a.ridx (i) == j) { T d = a.data (i); is_herm = (std::real (d) > 0.0 && std::imag (d) == 0.0); diag(j) = std::real (d); break; } } } // next, check symmetry and 2x2 positiveness for (octave_idx_type j = 0; is_herm && j < ncols; j++) for (octave_idx_type i = a.cidx (j); is_herm && i < a.cidx (j+1); i++) { octave_idx_type k = a.ridx (i); is_herm = k == j; if (is_herm) continue; T d = a.data (i); if (std::norm (d) < diag(j)*diag(k)) { d = octave::math::conj (d); for (octave_idx_type l = a.cidx (k); l < a.cidx (k+1); l++) { if (a.ridx (l) == j) { is_herm = a.data (l) == d; break; } } } } if (is_herm) { if (m_type == MatrixType::Full) m_type = MatrixType::Hermitian; else if (m_type == MatrixType::Banded) m_type = MatrixType::Banded_Hermitian; else m_type = MatrixType::Tridiagonal_Hermitian; } } } } MatrixType::MatrixType (const matrix_type t, bool _full) : m_type (MatrixType::Unknown), m_sp_bandden (octave::sparse_params::get_bandden ()), m_bandden (0), m_upper_band (0), m_lower_band (0), m_dense (false), m_full (_full), m_nperm (0), m_perm (nullptr) { if (t == MatrixType::Unknown || t == MatrixType::Full || t == MatrixType::Diagonal || t == MatrixType::Permuted_Diagonal || t == MatrixType::Upper || t == MatrixType::Lower || t == MatrixType::Tridiagonal || t == MatrixType::Tridiagonal_Hermitian || t == MatrixType::Rectangular) m_type = t; else warn_invalid (); } MatrixType::MatrixType (const matrix_type t, const octave_idx_type np, const octave_idx_type *p, bool _full) : m_type (MatrixType::Unknown), m_sp_bandden (octave::sparse_params::get_bandden ()), m_bandden (0), m_upper_band (0), m_lower_band (0), m_dense (false), m_full (_full), m_nperm (0), m_perm (nullptr) { if ((t == MatrixType::Permuted_Upper || t == MatrixType::Permuted_Lower) && np > 0 && p != nullptr) { m_type = t; m_nperm = np; m_perm = new octave_idx_type [m_nperm]; for (octave_idx_type i = 0; i < m_nperm; i++) m_perm[i] = p[i]; } else warn_invalid (); } MatrixType::MatrixType (const matrix_type t, const octave_idx_type ku, const octave_idx_type kl, bool _full) : m_type (MatrixType::Unknown), m_sp_bandden (octave::sparse_params::get_bandden ()), m_bandden (0), m_upper_band (0), m_lower_band (0), m_dense (false), m_full (_full), m_nperm (0), m_perm (nullptr) { if (t == MatrixType::Banded || t == MatrixType::Banded_Hermitian) { m_type = t; m_upper_band = ku; m_lower_band = kl; } else warn_invalid (); } MatrixType::~MatrixType (void) { if (m_nperm != 0) { delete [] m_perm; } } MatrixType& MatrixType::operator = (const MatrixType& a) { if (this != &a) { m_type = a.m_type; m_sp_bandden = a.m_sp_bandden; m_bandden = a.m_bandden; m_upper_band = a.m_upper_band; m_lower_band = a.m_lower_band; m_dense = a.m_dense; m_full = a.m_full; if (m_nperm) { delete[] m_perm; } if (a.m_nperm != 0) { m_perm = new octave_idx_type [a.m_nperm]; for (octave_idx_type i = 0; i < a.m_nperm; i++) m_perm[i] = a.m_perm[i]; } m_nperm = a.m_nperm; } return *this; } int MatrixType::type (bool quiet) { if (m_type != MatrixType::Unknown && (m_full || m_sp_bandden == octave::sparse_params::get_bandden ())) { if (! quiet && octave::sparse_params::get_key ("spumoni") != 0.) warn_cached (); return m_type; } if (m_type != MatrixType::Unknown && octave::sparse_params::get_key ("spumoni") != 0.) (*current_liboctave_warning_with_id_handler) ("Octave:matrix-type-info", "invalidating matrix type"); m_type = MatrixType::Unknown; return m_type; } int MatrixType::type (const SparseMatrix& a) { if (m_type != MatrixType::Unknown && (m_full || m_sp_bandden == octave::sparse_params::get_bandden ())) { if (octave::sparse_params::get_key ("spumoni") != 0.) warn_cached (); return m_type; } MatrixType tmp_typ (a); m_type = tmp_typ.m_type; m_sp_bandden = tmp_typ.m_sp_bandden; m_bandden = tmp_typ.m_bandden; m_upper_band = tmp_typ.m_upper_band; m_lower_band = tmp_typ.m_lower_band; m_dense = tmp_typ.m_dense; m_full = tmp_typ.m_full; m_nperm = tmp_typ.m_nperm; if (m_nperm != 0) { m_perm = new octave_idx_type [m_nperm]; for (octave_idx_type i = 0; i < m_nperm; i++) m_perm[i] = tmp_typ.m_perm[i]; } return m_type; } int MatrixType::type (const SparseComplexMatrix& a) { if (m_type != MatrixType::Unknown && (m_full || m_sp_bandden == octave::sparse_params::get_bandden ())) { if (octave::sparse_params::get_key ("spumoni") != 0.) warn_cached (); return m_type; } MatrixType tmp_typ (a); m_type = tmp_typ.m_type; m_sp_bandden = tmp_typ.m_sp_bandden; m_bandden = tmp_typ.m_bandden; m_upper_band = tmp_typ.m_upper_band; m_lower_band = tmp_typ.m_lower_band; m_dense = tmp_typ.m_dense; m_full = tmp_typ.m_full; m_nperm = tmp_typ.m_nperm; if (m_nperm != 0) { m_perm = new octave_idx_type [m_nperm]; for (octave_idx_type i = 0; i < m_nperm; i++) m_perm[i] = tmp_typ.m_perm[i]; } return m_type; } int MatrixType::type (const Matrix& a) { if (m_type != MatrixType::Unknown) { if (octave::sparse_params::get_key ("spumoni") != 0.) warn_cached (); return m_type; } MatrixType tmp_typ (a); m_type = tmp_typ.m_type; m_full = tmp_typ.m_full; m_nperm = tmp_typ.m_nperm; if (m_nperm != 0) { m_perm = new octave_idx_type [m_nperm]; for (octave_idx_type i = 0; i < m_nperm; i++) m_perm[i] = tmp_typ.m_perm[i]; } return m_type; } int MatrixType::type (const ComplexMatrix& a) { if (m_type != MatrixType::Unknown) { if (octave::sparse_params::get_key ("spumoni") != 0.) warn_cached (); return m_type; } MatrixType tmp_typ (a); m_type = tmp_typ.m_type; m_full = tmp_typ.m_full; m_nperm = tmp_typ.m_nperm; if (m_nperm != 0) { m_perm = new octave_idx_type [m_nperm]; for (octave_idx_type i = 0; i < m_nperm; i++) m_perm[i] = tmp_typ.m_perm[i]; } return m_type; } int MatrixType::type (const FloatMatrix& a) { if (m_type != MatrixType::Unknown) { if (octave::sparse_params::get_key ("spumoni") != 0.) warn_cached (); return m_type; } MatrixType tmp_typ (a); m_type = tmp_typ.m_type; m_full = tmp_typ.m_full; m_nperm = tmp_typ.m_nperm; if (m_nperm != 0) { m_perm = new octave_idx_type [m_nperm]; for (octave_idx_type i = 0; i < m_nperm; i++) m_perm[i] = tmp_typ.m_perm[i]; } return m_type; } int MatrixType::type (const FloatComplexMatrix& a) { if (m_type != MatrixType::Unknown) { if (octave::sparse_params::get_key ("spumoni") != 0.) warn_cached (); return m_type; } MatrixType tmp_typ (a); m_type = tmp_typ.m_type; m_full = tmp_typ.m_full; m_nperm = tmp_typ.m_nperm; if (m_nperm != 0) { m_perm = new octave_idx_type [m_nperm]; for (octave_idx_type i = 0; i < m_nperm; i++) m_perm[i] = tmp_typ.m_perm[i]; } return m_type; } void MatrixType::info () const { if (octave::sparse_params::get_key ("spumoni") != 0.) { if (m_type == MatrixType::Unknown) (*current_liboctave_warning_with_id_handler) ("Octave:matrix-type-info", "unknown matrix type"); else if (m_type == MatrixType::Diagonal) (*current_liboctave_warning_with_id_handler) ("Octave:matrix-type-info", "diagonal sparse matrix"); else if (m_type == MatrixType::Permuted_Diagonal) (*current_liboctave_warning_with_id_handler) ("Octave:matrix-type-info", "permuted diagonal sparse matrix"); else if (m_type == MatrixType::Upper) (*current_liboctave_warning_with_id_handler) ("Octave:matrix-type-info", "upper triangular matrix"); else if (m_type == MatrixType::Lower) (*current_liboctave_warning_with_id_handler) ("Octave:matrix-type-info", "lower triangular matrix"); else if (m_type == MatrixType::Permuted_Upper) (*current_liboctave_warning_with_id_handler) ("Octave:matrix-type-info", "permuted upper triangular matrix"); else if (m_type == MatrixType::Permuted_Lower) (*current_liboctave_warning_with_id_handler) ("Octave:matrix-type-info", "permuted lower triangular Matrix"); else if (m_type == MatrixType::Banded) (*current_liboctave_warning_with_id_handler) ("Octave:matrix-type-info", "banded sparse matrix %" OCTAVE_IDX_TYPE_FORMAT "-1-" "%" OCTAVE_IDX_TYPE_FORMAT " (density %f)", m_lower_band, m_upper_band, m_bandden); else if (m_type == MatrixType::Banded_Hermitian) (*current_liboctave_warning_with_id_handler) ("Octave:matrix-type-info", "banded hermitian/symmetric sparse matrix %" OCTAVE_IDX_TYPE_FORMAT "-1-%" OCTAVE_IDX_TYPE_FORMAT " (density %f)", m_lower_band, m_upper_band, m_bandden); else if (m_type == MatrixType::Hermitian) (*current_liboctave_warning_with_id_handler) ("Octave:matrix-type-info", "hermitian/symmetric matrix"); else if (m_type == MatrixType::Tridiagonal) (*current_liboctave_warning_with_id_handler) ("Octave:matrix-type-info", "tridiagonal sparse matrix"); else if (m_type == MatrixType::Tridiagonal_Hermitian) (*current_liboctave_warning_with_id_handler) ("Octave:matrix-type-info", "hermitian/symmetric tridiagonal sparse matrix"); else if (m_type == MatrixType::Rectangular) (*current_liboctave_warning_with_id_handler) ("Octave:matrix-type-info", "rectangular/singular matrix"); else if (m_type == MatrixType::Full) (*current_liboctave_warning_with_id_handler) ("Octave:matrix-type-info", "m_full matrix"); } } void MatrixType::mark_as_symmetric (void) { if (m_type == MatrixType::Tridiagonal || m_type == MatrixType::Tridiagonal_Hermitian) m_type = MatrixType::Tridiagonal_Hermitian; else if (m_type == MatrixType::Banded || m_type == MatrixType::Banded_Hermitian) m_type = MatrixType::Banded_Hermitian; else if (m_type == MatrixType::Full || m_type == MatrixType::Hermitian || m_type == MatrixType::Unknown) m_type = MatrixType::Hermitian; else (*current_liboctave_error_handler) ("Can not mark current matrix type as symmetric"); } void MatrixType::mark_as_unsymmetric (void) { if (m_type == MatrixType::Tridiagonal || m_type == MatrixType::Tridiagonal_Hermitian) m_type = MatrixType::Tridiagonal; else if (m_type == MatrixType::Banded || m_type == MatrixType::Banded_Hermitian) m_type = MatrixType::Banded; else if (m_type == MatrixType::Full || m_type == MatrixType::Hermitian || m_type == MatrixType::Unknown) m_type = MatrixType::Full; } void MatrixType::mark_as_permuted (const octave_idx_type np, const octave_idx_type *p) { m_nperm = np; m_perm = new octave_idx_type [m_nperm]; for (octave_idx_type i = 0; i < m_nperm; i++) m_perm[i] = p[i]; if (m_type == MatrixType::Diagonal || m_type == MatrixType::Permuted_Diagonal) m_type = MatrixType::Permuted_Diagonal; else if (m_type == MatrixType::Upper || m_type == MatrixType::Permuted_Upper) m_type = MatrixType::Permuted_Upper; else if (m_type == MatrixType::Lower || m_type == MatrixType::Permuted_Lower) m_type = MatrixType::Permuted_Lower; else (*current_liboctave_error_handler) ("Can not mark current matrix type as symmetric"); } void MatrixType::mark_as_unpermuted (void) { if (m_nperm) { m_nperm = 0; delete [] m_perm; } if (m_type == MatrixType::Diagonal || m_type == MatrixType::Permuted_Diagonal) m_type = MatrixType::Diagonal; else if (m_type == MatrixType::Upper || m_type == MatrixType::Permuted_Upper) m_type = MatrixType::Upper; else if (m_type == MatrixType::Lower || m_type == MatrixType::Permuted_Lower) m_type = MatrixType::Lower; } MatrixType MatrixType::transpose (void) const { MatrixType retval (*this); if (m_type == MatrixType::Upper) retval.m_type = MatrixType::Lower; else if (m_type == MatrixType::Permuted_Upper) retval.m_type = MatrixType::Permuted_Lower; else if (m_type == MatrixType::Lower) retval.m_type = MatrixType::Upper; else if (m_type == MatrixType::Permuted_Lower) retval.m_type = MatrixType::Permuted_Upper; else if (m_type == MatrixType::Banded) { retval.m_upper_band = m_lower_band; retval.m_lower_band = m_upper_band; } return retval; } // Instantiate MatrixType template constructors that we need. template MatrixType::MatrixType (const MSparse<double>&); template MatrixType::MatrixType (const MSparse<Complex>&);