1 /*
2   HMat-OSS (HMatrix library, open source software)
3 
4   Copyright (C) 2014-2015 Airbus Group SAS
5 
6   This program is free software; you can redistribute it and/or
7   modify it under the terms of the GNU General Public License
8   as published by the Free Software Foundation; either version 2
9   of the License, or (at your option) any later version.
10 
11   This program is distributed in the hope that it will be useful,
12   but WITHOUT ANY WARRANTY; without even the implied warranty of
13   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14   GNU General Public License for more details.
15 
16   You should have received a copy of the GNU General Public License
17   along with this program; if not, write to the Free Software
18   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
19 
20   http://github.com/jeromerobert/hmat-oss
21 */
22 
23 /*! \file
24   \ingroup HMatrix
25   \brief Dense Matrix implementation.
26 */
27 #include "config.h"
28 
29 #ifdef __INTEL_COMPILER
30 #include <mathimf.h>
31 #else
32 #include <cmath>
33 #endif
34 
35 #include "full_matrix.hpp"
36 
37 #include "data_types.hpp"
38 #include "lapack_overloads.hpp"
39 #include "blas_overloads.hpp"
40 #include "lapack_exception.hpp"
41 #include "common/memory_instrumentation.hpp"
42 #include "system_types.h"
43 #include "common/my_assert.h"
44 #include "common/context.hpp"
45 
46 #include <cstring> // memset
47 #include <algorithm> // swap
48 #include <iostream>
49 #include <fstream>
50 #include <cmath>
51 #include <fcntl.h>
52 #include <complex>
53 
54 #include <sys/stat.h>
55 
56 #ifdef HAVE_UNISTD_H
57 #include <unistd.h>
58 #endif
59 
60 #include <stdlib.h>
61 
62 namespace hmat {
63 
64 /** FullMatrix */
65 
66   template<typename T>
FullMatrix(T * _m,const IndexSet * _rows,const IndexSet * _cols,int _lda)67 FullMatrix<T>::FullMatrix(T* _m, const IndexSet*  _rows, const IndexSet*  _cols, int _lda)
68   : data(_m, _rows->size(), _cols->size(), _lda), triUpper_(false), triLower_(false),
69     rows_(_rows), cols_(_cols), pivots(NULL), diagonal(NULL) {
70   assert(rows_);
71   assert(cols_);
72 }
73 
74 template<typename T>
FullMatrix(ScalarArray<T> * s,const IndexSet * _rows,const IndexSet * _cols)75 FullMatrix<T>::FullMatrix(ScalarArray<T> *s, const IndexSet*  _rows, const IndexSet*  _cols)
76   : data(*s), triUpper_(false), triLower_(false),
77     rows_(_rows), cols_(_cols), pivots(NULL), diagonal(NULL) {
78   assert(rows_);
79   assert(cols_);
80   // check the coherency between IndexSet and ScalarArray
81   assert(rows_->size() == s->rows);
82   assert(cols_->size() == s->cols);
83 }
84 
85 template<typename T>
FullMatrix(const IndexSet * _rows,const IndexSet * _cols,bool zeroinit)86 FullMatrix<T>::FullMatrix(const IndexSet*  _rows, const IndexSet*  _cols, bool zeroinit)
87   : data(_rows->size(), _cols->size(), zeroinit), triUpper_(false), triLower_(false),
88     rows_(_rows), cols_(_cols), pivots(NULL), diagonal(NULL) {
89   assert(rows_);
90   assert(cols_);
91 }
92 
~FullMatrix()93 template<typename T> FullMatrix<T>::~FullMatrix() {
94   if (pivots) {
95     free(pivots);
96   }
97   if (diagonal) {
98     delete diagonal;
99   }
100 }
101 
clear()102 template<typename T> void FullMatrix<T>::clear() {
103   data.clear();
104   if (diagonal)
105     diagonal->clear();
106 }
107 
storedZeros() const108 template<typename T> size_t FullMatrix<T>::storedZeros() const {
109   return data.storedZeros();
110 }
111 
scale(T alpha)112 template<typename T> void FullMatrix<T>::scale(T alpha) {
113   data.scale(alpha);
114   if (diagonal)
115     diagonal->scale(alpha);
116 }
117 
transpose()118 template<typename T> void FullMatrix<T>::transpose() {
119   data.transpose();
120   std::swap(rows_, cols_);
121   // std::swap(triUpper_, triLower_) won't work because you can't swap bitfields
122   if (triUpper_) {
123     triUpper_ = false;
124     triLower_ = true;
125   } else if (triLower_) {
126     triLower_ = false;
127     triUpper_ = true;
128   }
129 }
130 
copy(FullMatrix<T> * result) const131 template<typename T> FullMatrix<T>* FullMatrix<T>::copy(FullMatrix<T>* result) const {
132   if(result == NULL)
133     result = new FullMatrix<T>(rows_, cols_, false);
134 
135   data.copy(&result->data);
136   if (diagonal) {
137     if(!result->diagonal)
138       result->diagonal = new Vector<T>(rows());
139     diagonal->copy(result->diagonal);
140   }
141 
142   result->rows_ = rows_;
143   result->cols_ = cols_;
144   result->triLower_ = triLower_;
145   result->triUpper_ = triUpper_;
146   return result;
147 }
148 
copyAndTranspose() const149 template<typename T> FullMatrix<T>* FullMatrix<T>::copyAndTranspose() const {
150   assert(cols_);
151   assert(rows_);
152   FullMatrix<T>* result = new FullMatrix<T>(cols_, rows_);
153   data.copyAndTranspose(&result->data);
154   return result;
155 }
156 
subset(const IndexSet * subRows,const IndexSet * subCols) const157 template<typename T> const FullMatrix<T>* FullMatrix<T>::subset(const IndexSet* subRows,
158                                                                 const IndexSet* subCols) const {
159   assert(subRows->isSubset(*rows_));
160   assert(subCols->isSubset(*cols_));
161   // The offset in the matrix, and not in all the indices
162   int rowsOffset = subRows->offset() - rows_->offset();
163   int colsOffset = subCols->offset() - cols_->offset();
164   ScalarArray<T> sub(data, rowsOffset, subRows->size(), colsOffset, subCols->size());
165   return new FullMatrix<T>(&sub, subRows, subCols);
166 }
167 
168 
169 template<typename T>
gemm(char transA,char transB,T alpha,const FullMatrix<T> * a,const FullMatrix<T> * b,T beta)170 void FullMatrix<T>::gemm(char transA, char transB, T alpha,
171                          const FullMatrix<T>* a, const FullMatrix<T>* b,
172                          T beta) {
173   data.gemm(transA, transB, alpha, &a->data, &b->data, beta);
174 }
175 
176 template<typename T>
multiplyWithDiagOrDiagInv(const Vector<T> * d,bool inverse,Side side)177 void FullMatrix<T>::multiplyWithDiagOrDiagInv(const Vector<T>* d, bool inverse, Side side) {
178   data.multiplyWithDiagOrDiagInv(d, inverse, side);
179 }
180 
181 template<typename T>
ldltDecomposition()182 void FullMatrix<T>::ldltDecomposition() {
183   // Void matrix
184   if (rows() == 0 || cols() == 0) return;
185 
186   HMAT_ASSERT(rows() == cols());
187   diagonal = new Vector<T>(rows());
188   HMAT_ASSERT(diagonal);
189   data.ldltDecomposition(*diagonal);
190 
191   triLower_ = true;
192   assert(!isTriUpper());
193 }
194 
195 template<typename T>
lltDecomposition()196 void FullMatrix<T>::lltDecomposition() {
197   // Void matrix
198   if (rows() == 0 || cols() == 0) return;
199 
200   data.lltDecomposition();
201 
202   triLower_ = true;
203   assert(!isTriUpper());
204 }
205 
206 template<typename T>
luDecomposition()207 void FullMatrix<T>::luDecomposition() {
208   // Void matrix
209   if (rows() == 0 || cols() == 0) return;
210 
211   pivots = (int*) calloc(rows(), sizeof(int));
212   HMAT_ASSERT(pivots);
213   data.luDecomposition(pivots);
214 }
215 
216 template<typename T>
getFactorizationData(Factorization algo) const217 FactorizationData<T> FullMatrix<T>::getFactorizationData(Factorization algo) const {
218   FactorizationData<T> result = { algo, {} };
219   if (algo == Factorization::LU) {
220     HMAT_ASSERT(pivots);
221     result.data.pivots = pivots;
222   } else if (algo == Factorization::LDLT) {
223     HMAT_ASSERT(diagonal);
224     result.data.diagonal = diagonal;
225   }
226   return result;
227 }
228 
229 template<typename T>
solveLowerTriangularLeft(ScalarArray<T> * x,Factorization algo,Diag diag,Uplo uplo) const230 void FullMatrix<T>::solveLowerTriangularLeft(ScalarArray<T>* x, Factorization algo, Diag diag, Uplo uplo) const {
231   // Void matrix
232   if (x->rows == 0 || x->cols == 0) return;
233   FactorizationData<T> context = getFactorizationData(algo);
234   data.solveLowerTriangularLeft(x, context, diag, uplo);
235 }
236 
237 
238 // The resolution of the upper triangular system does not need to
239 //  change the order of columns.
240 //  The pivots are not necessary here, but this helps to check
241 //  the matrix was factorized before.
242 
243 template<typename T>
solveUpperTriangularRight(ScalarArray<T> * x,Factorization algo,Diag diag,Uplo uplo) const244 void FullMatrix<T>::solveUpperTriangularRight(ScalarArray<T>* x, Factorization algo, Diag diag, Uplo uplo) const {
245   // Void matrix
246   if (x->rows == 0 || x->cols == 0) return;
247   FactorizationData<T> context = getFactorizationData(algo);
248   data.solveUpperTriangularRight(x, context, diag, uplo);
249 }
250 
251 template<typename T>
solveUpperTriangularLeft(ScalarArray<T> * x,Factorization algo,Diag diag,Uplo uplo) const252 void FullMatrix<T>::solveUpperTriangularLeft(ScalarArray<T>* x, Factorization algo, Diag diag, Uplo uplo) const {
253   // Void matrix
254   if (x->rows == 0 || x->cols == 0) return;
255   FactorizationData<T> context = getFactorizationData(algo);
256   data.solveUpperTriangularLeft(x, context, diag, uplo);
257 }
258 
259 template<typename T>
solve(ScalarArray<T> * x) const260 void FullMatrix<T>::solve(ScalarArray<T>* x) const {
261   // Void matrix
262   if (x->rows == 0 || x->cols == 0) return;
263   FactorizationData<T> context = getFactorizationData(Factorization::LU);
264   data.solve(x, context);
265 }
266 
267 
268 template<typename T>
inverse()269 void FullMatrix<T>::inverse() {
270   assert(rows() == cols());
271   data.inverse();
272 }
273 
274 
275 template<typename T>
copyMatrixAtOffset(const FullMatrix<T> * a,int rowOffset,int colOffset)276 void FullMatrix<T>::copyMatrixAtOffset(const FullMatrix<T>* a,
277                                        int rowOffset, int colOffset) {
278   data.copyMatrixAtOffset(&a->data, rowOffset, colOffset);
279 }
280 
281 template<typename T>
axpy(T alpha,const FullMatrix<T> * a)282 void FullMatrix<T>::axpy(T alpha, const FullMatrix<T>* a) {
283   data.axpy(alpha, &a->data);
284 }
285 
286 template<typename T>
normSqr() const287 double FullMatrix<T>::normSqr() const {
288   return data.normSqr();
289 }
290 
norm() const291 template<typename T> double FullMatrix<T>::norm() const {
292   return data.norm();
293 }
294 
addRand(double epsilon)295 template<typename T> void FullMatrix<T>::addRand(double epsilon) {
296   DECLARE_CONTEXT;
297   data.addRand(epsilon);
298 }
299 
fromFile(const char * filename)300 template<typename T> void FullMatrix<T>::fromFile(const char * filename) {
301   data.fromFile(filename);
302 }
303 
toFile(const char * filename) const304 template<typename T> void FullMatrix<T>::toFile(const char *filename) const {
305   data.toFile(filename);
306 }
307 
memorySize() const308 template<typename T> size_t FullMatrix<T>::memorySize() const {
309    return data.memorySize();
310 }
311 
checkNan() const312 template<typename T> void FullMatrix<T>::checkNan() const {
313   data.checkNan();
314   if (diagonal)
315     diagonal->checkNan();
316 }
317 
isZero() const318 template<typename T> bool FullMatrix<T>::isZero() const {
319   bool res = data.isZero();
320   if (diagonal)
321     res = res & diagonal->isZero();
322   return res;
323 }
324 
conjugate()325 template<typename T> void FullMatrix<T>::conjugate() {
326   data.conjugate();
327   if (diagonal)
328     diagonal->conjugate();
329 }
330 
description() const331 template<typename T> std::string FullMatrix<T>::description() const {
332     std::ostringstream convert;
333     convert << "FullMatrix " << this->rows_->description() << "x" << this->cols_->description() ;
334     convert << "norm=" << norm();
335     return convert.str();
336 }
337 
338 // the classes declaration
339 template class FullMatrix<S_t>;
340 template class FullMatrix<D_t>;
341 template class FullMatrix<C_t>;
342 template class FullMatrix<Z_t>;
343 
344 }  // end namespace hmat
345