#ifndef DENSEMATRIX_H #define DENSEMATRIX_H #include "Matrix.h" #include namespace ATC_matrix { /** * @class DenseMatrix * @brief Class for storing data in a "dense" matrix form */ template class DenseMatrix : public Matrix { public: DenseMatrix(INDEX rows=0, INDEX cols=0, bool z=1): _data(NULL){ _create(rows, cols, z); } DenseMatrix(const DenseMatrix& c) : Matrix(), _data(NULL){ _copy(c); } DenseMatrix(const SparseMatrix& c): Matrix(), _data(NULL){ c.dense_copy(*this);} DenseMatrix(const Matrix& c) : Matrix(), _data(NULL){ _copy(c); } // const SparseMatrix * p = sparse_cast(&c); // (p) ? p->dense_copy(*this) : _copy(c); } ~DenseMatrix() { _delete();} void reset (INDEX rows, INDEX cols, bool zero=true); void reset (const DenseMatrix& c) {_delete(); _copy(c); }; void reset (const SparseMatrix & c) {_delete(); c.dense_copy(*this);}; void reset (const Matrix& c) {_delete(); _copy(c); } void resize(INDEX rows, INDEX cols, bool copy=false); void copy (const T * ptr, INDEX rows, INDEX cols); /** returns transpose(this) * B */ DenseMatrix transMat(const DenseMatrix& B) const; /** returns by element multiply A_ij = this_ij * B_ij */ DenseMatrix mult_by_element(const DenseMatrix& B) const; /** returns by element multiply A_ij = this_ij / B_ij */ DenseMatrix div_by_element(const DenseMatrix& B) const; /** overloaded virtual functions */ //T& operator()(INDEX i, INDEX j) { MICK(i,j) return DATA(i,j); } T& operator()(INDEX i, INDEX j) { MICK(i,j) return DATA(i,j); } T operator()(INDEX i, INDEX j) const { MICK(i,j) return DATA(i,j); } T operator[](INDEX i) const { VICK(i) return _data[i]; } T& operator[](INDEX i) { VICK(i) return _data[i]; } INDEX nRows() const { return _nRows; } INDEX nCols() const { return _nCols; } T * ptr() const { return _data; } void write_restart(FILE *f) const; void from_file(std::string & name); void set_all_elements_to(const T &v); DiagonalMatrix diag() const; DenseMatrix& operator=(const T &v); DenseMatrix& operator=(const Matrix &c); DenseMatrix& operator=(const DenseMatrix &c); DenseMatrix& operator=(const SparseMatrix &c); //* checks if all values are within the prescribed range virtual bool check_range(T min, T max) const; protected: void _set_equal(const Matrix &r); void _delete(); void _create(INDEX rows, INDEX cols, bool zero=false); void _copy(const Matrix &c); T *_data; INDEX _nRows, _nCols; }; //! Computes the cofactor matrix of A. template DenseMatrix adjugate(const Matrix &A, bool symmetric=false); //! Returns a the tensor product of two vectors template DenseMatrix tensor_product(const Vector &a, const Vector &b); //---------------------------------------------------------------------------- // Returns an identity matrix, defaults to 3x3. //---------------------------------------------------------------------------- template DenseMatrix eye(INDEX rows=3, INDEX cols=3) { const double dij[] = {0.0, 1.0}; DENS_MAT I(rows, cols, false); // do not need to pre-zero for (INDEX j=0; j void DenseMatrix::reset(INDEX rows, INDEX cols, bool zero) { if (!this->is_size(rows, cols)) { _delete(); _create(rows, cols); } if (zero) this->zero(); } //---------------------------------------------------------------------------- // resizes the matrix and optionally copies over what still fits //---------------------------------------------------------------------------- template void DenseMatrix::resize(INDEX rows, INDEX cols, bool copy) { if (this->is_size(rows, cols)) return; // if is correct size, done if (!copy) { _delete(); _create(rows, cols); return; } DenseMatrix temp(*this); _delete(); _create(rows, cols); int szi = this->nRows(); int szj = this->nCols(); for (INDEX i = 0; i < szi; i++) for (INDEX j = 0; j < szj; j++) (*this)(i,j) = temp.in_range(i,j) ? temp(i,j) : T(0); } //---------------------------------------------------------------------------- // resizes the matrix and copies data //---------------------------------------------------------------------------- template void DenseMatrix::copy(const T * ptr, INDEX rows, INDEX cols) { resize(rows, cols, false); memcpy(_data, ptr, this->size()*sizeof(T)); } //---------------------------------------------------------------------------- // returns transpose(this) * B //---------------------------------------------------------------------------- template DenseMatrix DenseMatrix::transMat(const DenseMatrix& B) const { DenseMatrix C; MultAB(*this, B, C, true); return C; } //---------------------------------------------------------------------------- // returns this_ij * B_ij //---------------------------------------------------------------------------- template DenseMatrix DenseMatrix::mult_by_element(const DenseMatrix& B) const { DenseMatrix C; C.reset(_nRows,_nCols); if (B.nCols() == _nCols) { int szi = this->nRows(); int szj = this->nCols(); for (INDEX i = 0; i < szi; i++) for (INDEX j = 0; j < szj; j++) C(i,j) = (*this)(i,j)*B(i,j); } else if (B.nCols() == 1) { std::cout << "MULTIPLYING\n"; int szi = this->nRows(); int szj = this->nCols(); for (INDEX i = 0; i < szi; i++) for (INDEX j = 0; j < szj; j++) C(i,j) = (*this)(i,j)*B(i,0); } else { SSCK(B, *this, "DenseMatrix::mult_by_element"); } return C; } //---------------------------------------------------------------------------- // returns this_ij / B_ij //---------------------------------------------------------------------------- template DenseMatrix DenseMatrix::div_by_element(const DenseMatrix& B) const { DenseMatrix C; C.reset(_nRows,_nCols); if (B.nCols() == _nCols) { int szi = this->nRows(); int szj = this->nCols(); for (INDEX i = 0; i < szi; i++) for (INDEX j = 0; j < szj; j++) C(i,j) = (*this)(i,j)/B(i,j); } else if (B.nCols() == 1) { int szi = this->nRows(); int szj = this->nCols(); for (INDEX i = 0; i < szi; i++) for (INDEX j = 0; j < szj; j++) C(i,j) = (*this)(i,j)/B(i,0); } else { SSCK(B, *this, "DenseMatrix::div_by_element"); } return C; } //---------------------------------------------------------------------------- // writes the matrix data to a file //---------------------------------------------------------------------------- template void DenseMatrix::write_restart(FILE *f) const { fwrite(&_nRows, sizeof(INDEX),1,f); fwrite(&_nCols, sizeof(INDEX),1,f); if (this->size()) fwrite(_data, sizeof(T), this->size(), f); } //---------------------------------------------------------------------------- // reads matrix from text file (matrix needs to be sized) //---------------------------------------------------------------------------- template void DenseMatrix::from_file(std::string & name) { GCHK(_nRows == 0,"from_file needs nRows > 0"); GCHK(_nCols == 0,"from_file needs nCols > 0"); std::ifstream in(name.c_str(),std::ifstream::in); const int lineSize = 256; char line[lineSize]; if (! in.good()) gerror(name+" is not available"); in.getline(line,lineSize); // header int szi = this->nRows(); int szj = this->nCols(); for (INDEX i = 0; i < szi; i++) for (INDEX j = 0; j < szj; j++) in >> (*this)(i,j); } //---------------------------------------------------------------------------- // sets all elements to a value (optimized) //---------------------------------------------------------------------------- template inline void DenseMatrix::set_all_elements_to(const T &v) { int sz = this->size(); for (INDEX i = 0; i < sz; i++) _data[i] = v; } //----------------------------------------------------------------------------- // Return a diagonal matrix containing the diagonal entries of this matrix //----------------------------------------------------------------------------- template DiagonalMatrix DenseMatrix::diag() const { DiagonalMatrix D(nRows(), true); // initialized to zero INDEX i; for (i=0; i void DenseMatrix::_delete() { _nRows = _nCols = 0; if (_data){ delete [] _data; _data = NULL; } } //---------------------------------------------------------------------------- // allocates memory for an rows by cols DenseMatrix //---------------------------------------------------------------------------- template void DenseMatrix::_create(INDEX rows, INDEX cols, bool zero) { _nRows=rows; _nCols=cols; _data = (this->size() ? new T [_nCols*_nRows] : NULL); if (zero) this->zero(); } //---------------------------------------------------------------------------- // creates a deep memory copy from a general matrix //---------------------------------------------------------------------------- template void DenseMatrix::_copy(const Matrix &c) { if (!_data || this->size()!=c.size()) { _delete(); _create(c.nRows(), c.nCols()); } else { _nRows = c.nRows(); _nCols = c.nCols(); } memcpy(_data, c.ptr(), c.size()*sizeof(T)); } //---------------------------------------------------------------------------- // sets all elements to a constant //---------------------------------------------------------------------------- template DenseMatrix& DenseMatrix::operator=(const T &v) { this->set_all_elements_to(v); return *this; } //---------------------------------------------------------------------------- // copys c with a deep copy //---------------------------------------------------------------------------- template DenseMatrix& DenseMatrix::operator=(const Matrix &c) { _copy(c); return *this; } //---------------------------------------------------------------------------- // copys c with a deep copy //---------------------------------------------------------------------------- template DenseMatrix& DenseMatrix::operator=(const DenseMatrix &c) { _copy(c); return *this; } //----------------------------------------------------------------------------- // copys c with a deep copy, including zeros //----------------------------------------------------------------------------- template DenseMatrix& DenseMatrix::operator=(const SparseMatrix &c) { _delete(); _create(c.nRows(), c.nCols(), true); SparseMatrix::compress(c); for (INDEX i=0; i x = c.triplet(i); std::cout << "x.i: "<< x.i << "\nx.j: "<< x.j << "\nv.j: "<< x.v << std::endl << std::endl; (*this)(x.i, x.j) = x.v; } return *this; } //---------------------------------------------------------------------------- // general matrix assignment (for densely packed matrices) //---------------------------------------------------------------------------- template void DenseMatrix::_set_equal(const Matrix &r) { this->resize(r.nRows(), r.nCols()); const Matrix *pr = &r; const DenseMatrix *pdd = dynamic_cast*> (pr); if (pdd) this->reset(*pdd); else { std::cout <<"Error in general dense matrix assignment\n"; exit(1); } } //* Returns the transpose of the cofactor matrix of A. //* see http://en.wikipedia.org/wiki/Adjugate_matrix //* symmetric flag only affects cases N>3 template DenseMatrix adjugate(const Matrix &A, bool symmetric) { if (!A.is_square()) gerror("adjugate can only be computed for square matrices."); DenseMatrix C(A.nRows(), A.nRows()); switch (A.nRows()) { case 1: gerror("adjugate must be computed for matrixes of size greater than 1"); case 2: C(0,0) = A(1,1); C(0,1) =-A(0,1); C(1,0) =-A(1,0); C(1,1) = A(0,0); break; case 3: // 3x3 case was tested vs matlab C(0,0) = A(1,1)*A(2,2)-A(1,2)*A(2,1); C(1,0) =-A(1,0)*A(2,2)+A(1,2)*A(2,0); // i+j is odd (reverse sign) C(2,0) = A(1,0)*A(2,1)-A(1,1)*A(2,0); C(0,1) =-A(0,1)*A(2,2)+A(0,2)*A(2,1); // i+j is odd C(1,1) = A(0,0)*A(2,2)-A(0,2)*A(2,0); C(2,1) =-A(0,0)*A(2,1)+A(0,1)*A(2,0); // i+j is odd C(0,2) = A(0,1)*A(1,2)-A(0,2)*A(1,1); C(1,2) =-A(0,0)*A(1,2)+A(0,2)*A(1,0); // i+j is odd C(2,2) = A(0,0)*A(1,1)-A(0,1)*A(1,0); break; default: // this feature is neither tested nor optimal - use at your own risk!!! DenseMatrix m(A.nRows()-1, A.nRows()-1); double sign[] = {1.0, -1.0}; for (INDEX j=0; j=i), mj+(mj>=j)); // skip row i and col j } } if (!symmetric) C(j,i)=det(m)*sign[(i+j)&1]; if (symmetric && i>=j) C(i,j)=C(j,i)=det(m)*sign[(i+j)&1]; } } } return C; } // Returns a the tensor product of two vectors template DenseMatrix tensor_product(const Vector &a, const Vector &b) { DenseMatrix ab(a.size(), b.size(),false); for (INDEX j=0; j DenseMatrix rand(INDEX rows, INDEX cols, int seed=1234) { srand(seed); const double rand_max_inv = 1.0 / double(RAND_MAX); DenseMatrix R(rows, cols, false); for (INDEX i=0; i inline bool DenseMatrix::check_range(T min, T max) const { for (INDEX i = 0; i < this->size(); i++) if ( (_data[i] > max) || (_data[i] < min) ) return false; return true; } } // end namespace #endif