/* HMat-OSS (HMatrix library, open source software) Copyright (C) 2014-2015 Airbus Group SAS This program 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 2 of the License, or (at your option) any later version. This program 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 this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. http://github.com/jeromerobert/hmat-oss */ /*! \file \ingroup HMatrix \brief Dense Matrix implementation. */ #include "config.h" #ifdef __INTEL_COMPILER #include #else #include #endif #include "full_matrix.hpp" #include "data_types.hpp" #include "lapack_overloads.hpp" #include "blas_overloads.hpp" #include "lapack_exception.hpp" #include "common/memory_instrumentation.hpp" #include "system_types.h" #include "common/my_assert.h" #include "common/context.hpp" #include // memset #include // swap #include #include #include #include #include #include #ifdef HAVE_UNISTD_H #include #endif #include namespace hmat { /** FullMatrix */ template FullMatrix::FullMatrix(T* _m, const IndexSet* _rows, const IndexSet* _cols, int _lda) : data(_m, _rows->size(), _cols->size(), _lda), triUpper_(false), triLower_(false), rows_(_rows), cols_(_cols), pivots(NULL), diagonal(NULL) { assert(rows_); assert(cols_); } template FullMatrix::FullMatrix(ScalarArray *s, const IndexSet* _rows, const IndexSet* _cols) : data(*s), triUpper_(false), triLower_(false), rows_(_rows), cols_(_cols), pivots(NULL), diagonal(NULL) { assert(rows_); assert(cols_); // check the coherency between IndexSet and ScalarArray assert(rows_->size() == s->rows); assert(cols_->size() == s->cols); } template FullMatrix::FullMatrix(const IndexSet* _rows, const IndexSet* _cols, bool zeroinit) : data(_rows->size(), _cols->size(), zeroinit), triUpper_(false), triLower_(false), rows_(_rows), cols_(_cols), pivots(NULL), diagonal(NULL) { assert(rows_); assert(cols_); } template FullMatrix::~FullMatrix() { if (pivots) { free(pivots); } if (diagonal) { delete diagonal; } } template void FullMatrix::clear() { data.clear(); if (diagonal) diagonal->clear(); } template size_t FullMatrix::storedZeros() const { return data.storedZeros(); } template void FullMatrix::scale(T alpha) { data.scale(alpha); if (diagonal) diagonal->scale(alpha); } template void FullMatrix::transpose() { data.transpose(); std::swap(rows_, cols_); // std::swap(triUpper_, triLower_) won't work because you can't swap bitfields if (triUpper_) { triUpper_ = false; triLower_ = true; } else if (triLower_) { triLower_ = false; triUpper_ = true; } } template FullMatrix* FullMatrix::copy(FullMatrix* result) const { if(result == NULL) result = new FullMatrix(rows_, cols_, false); data.copy(&result->data); if (diagonal) { if(!result->diagonal) result->diagonal = new Vector(rows()); diagonal->copy(result->diagonal); } result->rows_ = rows_; result->cols_ = cols_; result->triLower_ = triLower_; result->triUpper_ = triUpper_; return result; } template FullMatrix* FullMatrix::copyAndTranspose() const { assert(cols_); assert(rows_); FullMatrix* result = new FullMatrix(cols_, rows_); data.copyAndTranspose(&result->data); return result; } template const FullMatrix* FullMatrix::subset(const IndexSet* subRows, const IndexSet* subCols) const { assert(subRows->isSubset(*rows_)); assert(subCols->isSubset(*cols_)); // The offset in the matrix, and not in all the indices int rowsOffset = subRows->offset() - rows_->offset(); int colsOffset = subCols->offset() - cols_->offset(); ScalarArray sub(data, rowsOffset, subRows->size(), colsOffset, subCols->size()); return new FullMatrix(&sub, subRows, subCols); } template void FullMatrix::gemm(char transA, char transB, T alpha, const FullMatrix* a, const FullMatrix* b, T beta) { data.gemm(transA, transB, alpha, &a->data, &b->data, beta); } template void FullMatrix::multiplyWithDiagOrDiagInv(const Vector* d, bool inverse, Side side) { data.multiplyWithDiagOrDiagInv(d, inverse, side); } template void FullMatrix::ldltDecomposition() { // Void matrix if (rows() == 0 || cols() == 0) return; HMAT_ASSERT(rows() == cols()); diagonal = new Vector(rows()); HMAT_ASSERT(diagonal); data.ldltDecomposition(*diagonal); triLower_ = true; assert(!isTriUpper()); } template void FullMatrix::lltDecomposition() { // Void matrix if (rows() == 0 || cols() == 0) return; data.lltDecomposition(); triLower_ = true; assert(!isTriUpper()); } template void FullMatrix::luDecomposition() { // Void matrix if (rows() == 0 || cols() == 0) return; pivots = (int*) calloc(rows(), sizeof(int)); HMAT_ASSERT(pivots); data.luDecomposition(pivots); } template FactorizationData FullMatrix::getFactorizationData(Factorization algo) const { FactorizationData result = { algo, {} }; if (algo == Factorization::LU) { HMAT_ASSERT(pivots); result.data.pivots = pivots; } else if (algo == Factorization::LDLT) { HMAT_ASSERT(diagonal); result.data.diagonal = diagonal; } return result; } template void FullMatrix::solveLowerTriangularLeft(ScalarArray* x, Factorization algo, Diag diag, Uplo uplo) const { // Void matrix if (x->rows == 0 || x->cols == 0) return; FactorizationData context = getFactorizationData(algo); data.solveLowerTriangularLeft(x, context, diag, uplo); } // The resolution of the upper triangular system does not need to // change the order of columns. // The pivots are not necessary here, but this helps to check // the matrix was factorized before. template void FullMatrix::solveUpperTriangularRight(ScalarArray* x, Factorization algo, Diag diag, Uplo uplo) const { // Void matrix if (x->rows == 0 || x->cols == 0) return; FactorizationData context = getFactorizationData(algo); data.solveUpperTriangularRight(x, context, diag, uplo); } template void FullMatrix::solveUpperTriangularLeft(ScalarArray* x, Factorization algo, Diag diag, Uplo uplo) const { // Void matrix if (x->rows == 0 || x->cols == 0) return; FactorizationData context = getFactorizationData(algo); data.solveUpperTriangularLeft(x, context, diag, uplo); } template void FullMatrix::solve(ScalarArray* x) const { // Void matrix if (x->rows == 0 || x->cols == 0) return; FactorizationData context = getFactorizationData(Factorization::LU); data.solve(x, context); } template void FullMatrix::inverse() { assert(rows() == cols()); data.inverse(); } template void FullMatrix::copyMatrixAtOffset(const FullMatrix* a, int rowOffset, int colOffset) { data.copyMatrixAtOffset(&a->data, rowOffset, colOffset); } template void FullMatrix::axpy(T alpha, const FullMatrix* a) { data.axpy(alpha, &a->data); } template double FullMatrix::normSqr() const { return data.normSqr(); } template double FullMatrix::norm() const { return data.norm(); } template void FullMatrix::addRand(double epsilon) { DECLARE_CONTEXT; data.addRand(epsilon); } template void FullMatrix::fromFile(const char * filename) { data.fromFile(filename); } template void FullMatrix::toFile(const char *filename) const { data.toFile(filename); } template size_t FullMatrix::memorySize() const { return data.memorySize(); } template void FullMatrix::checkNan() const { data.checkNan(); if (diagonal) diagonal->checkNan(); } template bool FullMatrix::isZero() const { bool res = data.isZero(); if (diagonal) res = res & diagonal->isZero(); return res; } template void FullMatrix::conjugate() { data.conjugate(); if (diagonal) diagonal->conjugate(); } template std::string FullMatrix::description() const { std::ostringstream convert; convert << "FullMatrix " << this->rows_->description() << "x" << this->cols_->description() ; convert << "norm=" << norm(); return convert.str(); } // the classes declaration template class FullMatrix; template class FullMatrix; template class FullMatrix; template class FullMatrix; } // end namespace hmat