SparseLibrary  Version 1.6.0
DD_MATRIX.hpp
1 /*
2  * Copyright (c) 2007-2014, A. N. Yzelman, Utrecht University 2007-2011;
3  * KU Leuven 2011-2014.
4  * R. H. Bisseling, Utrecht University 2007-2014.
5  *
6  * This file is part of the Sparse Library.
7  *
8  * This library was developed under supervision of Prof. dr. Rob H. Bisseling at
9  * Utrecht University, from 2007 until 2011. From 2011-2014, development continued
10  * at KU Leuven, where Prof. dr. Dirk Roose contributed significantly to the ideas
11  * behind the newer parts of the library code.
12  *
13  * The Sparse Library is free software: you can redistribute it and/or modify
14  * it under the terms of the GNU General Public License as published by the
15  * Free Software Foundation, either version 3 of the License, or (at your
16  * option) any later version.
17  *
18  * The Sparse Library is distributed in the hope that it will be useful, but
19  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
20  * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
21  * for more details.
22  *
23  * You should have received a copy of the GNU General Public License along
24  * with the Sparse Library. If not, see <http://www.gnu.org/licenses/>.
25  */
26 
27 
28 /*
29  * File created by:
30  * A. N. Yzelman, Dept. of Mathematics, Utrecht University, 2009.
31  */
32 
33 
34 #include <assert.h>
35 #include <vector>
36 #include "Triplet.hpp"
37 #include "SparseMatrix.hpp"
38 
45 template< typename T, int number_of_diagonals, int diagonal_offsets[] >
46 class DD_MATRIX: public SparseMatrix< T, unsigned long int > {
47 
48  private:
49 
51  typedef unsigned long int ULI;
52 
53  protected:
54 
56  T** nzs;
57 
59  ULI full;
60 
62  ULI d;
63 
66 
68  size_t bytes;
69 
70  public:
71 
74  load( std::vector< Triplet< T > >(), 0, 0, 0 );
75  }
76 
81  DD_MATRIX( std::string file, T zero = 0 ) {
82  loadFromFile( file, zero );
83  }
84 
91  DD_MATRIX( std::vector< Triplet< T > >& input, ULI m, ULI n, T zero ) {
92  load( input, m, n, zero );
93  }
94 
104  DD_MATRIX( T **nonzeroes, ULI m, ULI n, T zero ) {
105  this->zero_element = zero;
106  this->nor = m;
107  this->noc = n;
108  this->nnz = 0;
109 
110  for( ULI k=0; k<number_of_diagonals; k++ ) {
111  if( diagonal_offsets[ k ] < 0 ) {
112  this->nnz += m+diagonal_offsets[ k ] < n ? m+diagonal_offsets[ k ] : n;
113  } else {
114  this->nnz += n-diagonal_offsets[ k ] < m ? m-diagonal_offsets[ k ] : m;
115  }
116  }
117 
118  d = m > n ? m : n;
119  full = m > n ? m-n+1 : n-m+1;
120  nzs = nonzeroes;
121 
122  bytes = 2 * sizeof(ULI) + sizeof(T**);
123  bytes += number_of_diagonals * sizeof(T*);
124  bytes += number_of_diagonals * d * sizeof(T);
125 
126  SELF_ALLOCATED = false;
127  }
128 
130  virtual void load( std::vector< Triplet< T > >& input, const ULI m, const ULI n, const T zero ) {
131 
132  this->zero_element = zero;
133  this->nor = m;
134  this->noc = n;
135  this->nnz = input.size();
136 
137  nzs = new T*[ number_of_diagonals ];
138  bytes = number_of_diagonals * sizeof(T*) + 2 * sizeof(ULI) + sizeof(T**);
139  d = m > n ? m : n;
140  full = m > n ? m-n+1 : n-m+1;
141 
142  //first look which diagonals are populated
143  ULI *diags = new ULI[ m + n - 1 ];
144  for( ULI r=0; r<m+n-1; r++ ) {
145  diags[ r ] = 0;
146  }
147  for( ULI r=0; r<this->nnz; r++ ) {
148  if( input[ r ].value != this->zero_element ) {
149  diags[input[ r ].j()-input[ r ].i()+m-1] = 1;
150  }
151  }
152  ULI nl1 = 0; //number of diagonals populated
153  for( ULI r=0; r<m+n-1; r++ ) {
154  if( diags[ r ] == 1 ) {
155  nl1++;
156  }
157  }
158 
159  //assume perfect human input
160  ULI c = 0;
161  assert( number_of_diagonals == nl1 );
162  for( ULI r=0; r<m+n-1; r++ ) {
163  if( diags[ r ] == 1 ) {
164  assert( static_cast< int >( r ) - static_cast< int >( m ) + 1 == diagonal_offsets[ c++ ] );
165  }
166  }
167 
168  //allocate nzs fully
169  for( ULI r=0; r<number_of_diagonals; r++ ) {
170  ULI curdiag = diagonal_offsets[ r ];
171  const size_t allocLength = curdiag <= full ? d : d-(curdiag-full);
172  nzs[r] = new T[ allocLength ];
173  bytes += allocLength * sizeof(T);
174  }
175 
176  //build diagonal code to nzs-row array
177  for( ULI r=0; r<m+n-1; r++ ) {
178  diags[ r ] = static_cast< ULI >( -1 ); //signal overflow (hopefully)
179  }
180  for( ULI r=0; r<number_of_diagonals; r++ ) {
181  diags[ diagonal_offsets[ r ] + m - 1 ] = r;
182  }
183 
184  for( ULI r=0; r<this->nnz; r++ ) {
185  if( input[ r ].value != this->zero_element ) {
186  ULI cur = input[ r ].j() - input[ r ].i() + m-1; //diagonal code
187  if( input[ r ].i() > input[ r ].j() )
188  nzs[ diags[ cur ] ][ input[ r ].j() ] = input[ r ].value;
189  else
190  nzs[ diags[ cur ] ][ input[ r ].i() ] = input[ r ].value;
191  }
192  }
193 
194  //set self allocation flag
195  SELF_ALLOCATED = true;
196 
197  //clean up
198  delete [] diags;
199 
200  //done
201  }
202 
204  virtual void getFirstIndexPair( unsigned long int &row, unsigned long int &col ) {
205  row = 0;
206  col = 0;
207  }
208 
215  virtual void zxa( const T* x, T* z ) {
216  for( ULI j=0; j<d; j++ ) {
217  //theoretically, a compiler could unroll this inner loop perfectly
218  //and optimise out the if-statements.
219  for( ULI k=0; k<number_of_diagonals; k++ ) {
220  const ULI i = j + diagonal_offsets[ k ];
221  if( i >= this->nor ) continue;
222  if( diagonal_offsets[ k ] < 0 )
223  z[ j ] += nzs[ k ][ j ] * x[ i ];
224  else
225  z[ j ] += nzs[ k ][ i ] * x[ i ];
226  }
227  }
228  }
229 
236  virtual void zax( const T* x, T* z ) {
237  //std::cout << "d= " << d << std::endl;
238  for( ULI i=0; i<d; i++ ) {
239  //theoretically, a compiler could unroll this inner loop perfectly
240  //and optimise out the if-statements.
241  for( ULI k=0; k<number_of_diagonals; k++ ) {
242  const ULI j = i + diagonal_offsets[ k ];
243  //std::cout << "j>=noc: " << j << " >= " << this->noc << std::endl;
244  if( j >= this->noc ) continue;
245  //std::cout << "i,j,k = " << i << "," << j << "," << k << std::endl;
246  if( diagonal_offsets[ k ] < 0 )
247  z[ i ] += nzs[ k ][ j ] * x[ j ];
248  else
249  z[ i ] += nzs[ k ][ i ] * x[ j ];
250  }
251  }
252  }
253 
255  size_t bytesUsed() {
256  return bytes;
257  }
258 
261  if( !SELF_ALLOCATED ) return;
262 
263  for( ULI k = 0; k<number_of_diagonals; k++ )
264  delete [] nzs[ k ];
265  delete [] nzs;
266  }
267 
268 };
269 
unsigned long int nnz
Number of non-zeros.
Definition: SparseMatrix.hpp:58
DD_MATRIX()
Base constructor.
Definition: DD_MATRIX.hpp:73
ULI d
What the main diagonal length is (longest diagonal).
Definition: DD_MATRIX.hpp:62
DD_MATRIX(std::vector< Triplet< T > > &input, ULI m, ULI n, T zero)
Base constructor.
Definition: DD_MATRIX.hpp:91
The dense diagonal matrix scheme; a storage scheme for sparse matrices consisting of only dense diago...
Definition: DD_MATRIX.hpp:46
T ** nzs
The values of the nonzeros.
Definition: DD_MATRIX.hpp:56
~DD_MATRIX()
Base destructor.
Definition: DD_MATRIX.hpp:260
virtual unsigned long int m()
Queries the number of rows this matrix contains.
Definition: SparseMatrix.hpp:107
virtual void load(std::vector< Triplet< T > > &input, const ULI m, const ULI n, const T zero)
Definition: DD_MATRIX.hpp:130
void loadFromFile(const std::string file, const T zero=0)
Function which loads a matrix from a matrix market file.
Definition: SparseMatrix.hpp:89
virtual unsigned long int nzs()
Queries the number of nonzeroes stored in this matrix.
Definition: SparseMatrix.hpp:123
Interface common to all sparse matrix storage schemes.
Definition: SparseMatrix.hpp:46
unsigned long int noc
Number of columns.
Definition: SparseMatrix.hpp:55
size_t bytes
Keeps track of the number of bytes spent for this matrix.
Definition: DD_MATRIX.hpp:68
ULI full
How many full length diagonals this (possible not square matrix) contains.
Definition: DD_MATRIX.hpp:59
virtual void zax(const T *x, T *z)
In-place z=Ax calculation algorithm.
Definition: DD_MATRIX.hpp:236
unsigned long int nor
Number of rows.
Definition: SparseMatrix.hpp:52
T zero_element
The element considered to be zero.
Definition: SparseMatrix.hpp:63
bool SELF_ALLOCATED
Whether or not nzs was allocated by this instance itself.
Definition: DD_MATRIX.hpp:65
virtual void zxa(const T *x, T *z)
In-place z=xA calculation algorithm.
Definition: DD_MATRIX.hpp:215
size_t bytesUsed()
Definition: DD_MATRIX.hpp:255
virtual unsigned long int n()
Queries the number of columns this matrix contains.
Definition: SparseMatrix.hpp:115
DD_MATRIX(std::string file, T zero=0)
Base constructor.
Definition: DD_MATRIX.hpp:81
A single triplet value.
Definition: Triplet.hpp:52
virtual void getFirstIndexPair(unsigned long int &row, unsigned long int &col)
Returns the first nonzero index, per reference.
Definition: DD_MATRIX.hpp:204
DD_MATRIX(T **nonzeroes, ULI m, ULI n, T zero)
Dense diagonal matrix specific constructor.
Definition: DD_MATRIX.hpp:104