SparseLibrary  Version 1.6.0
CRS.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, 2008.
31  */
32 
33 
34 #include "Triplet.hpp"
35 #include "SparseMatrix.hpp"
36 #include <vector>
37 #include <assert.h>
38 
39 //#define _DEBUG
40 
41 #ifndef _H_CRS
42 #define _H_CRS
43 
44 #ifdef _DEBUG
45 #include<iostream>
46 #endif
47 
51 template< typename T >
52 class CRS: public SparseMatrix< T, ULI > {
53 
54  private:
55 
56  protected:
57 
59  ULI* row_start;
60 
62  T* ds;
63 
65  ULI* col_ind;
66 
68  static int compareTriplets( const void * left, const void * right ) {
69  const Triplet< T > one = **( (Triplet< T > **)left );
70  const Triplet< T > two = **( (Triplet< T > **)right );
71  if ( one.j() < two.j() )
72  return -1;
73  if ( one.j() > two.j() )
74  return 1;
75  return 0;
76  }
77 
86  bool find( const ULI col_index, const ULI search_start, const ULI search_end, ULI &ret ) {
87  for( ULI i=search_start; i<search_end; i++ )
88  if( col_ind[ i ] == col_index ) {
89  ret = i;
90  return true;
91  }
92  return false;
93  }
94 
95  public:
96 
98  CRS() {}
99 
104  CRS( std::string file, T zero = 0 ) {
105  this->loadFromFile( file, zero );
106  }
107 
117  CRS( const ULI number_of_nonzeros, const ULI number_of_rows, const ULI number_of_cols, T zero ) {
118  this->nnz = number_of_nonzeros;
119  this->nor = number_of_rows;
120  this->noc = number_of_cols;
121  this->zero_element = zero;
122  row_start = new ULI[ this->nor + 1 ];
123  ds = new T[ this->nnz ];
124  col_ind = new ULI[ this->nnz ];
125  }
126 
130  CRS( CRS< T >& toCopy ) {
131  this->zero_element = toCopy.zero_element;
132  this->nnz = toCopy.nnz;
133  this->nor = toCopy.nor;
134  row_start = new ULI[ this->nor + 1 ];
135  ds = new T[ this->nnz ];
136  col_ind = new ULI[ this->nnz ];
137  for( ULI i=0; i<this->nnz; i++ ) {
138  ds[ i ] = toCopy.ds[ i ];
139  col_ind[ i ] = toCopy.col_ind[ i ];
140  }
141  for( ULI i=0; i<this->nor; i++ )
142  row_start[ i ] = toCopy.row_start[ i ];
143  }
144 
155  CRS( std::vector< Triplet< T > > input, ULI m, ULI n, T zero ) {
156  load( input, m, n, zero );
157  }
158 
160  virtual void load( std::vector< Triplet< T > >& input, ULI m, ULI n, T zero ) {
161  std::cout << "\tLoading in a vector of " << input.size() << " triplets into CRS..." << std::endl;
162 
163  this->zero_element = zero;
164  //find nnz
165  this->nnz = input.size();
166 
167  this->nor = m;
168  this->noc = n;
169 
170  //build better datastructure
171  std::vector< std::vector< Triplet< T >* > > ds( this->nor );
172 
173  //move input there
174  typename std::vector< Triplet< T > >::iterator in_it = input.begin();
175  for( ; in_it != input.end(); ++in_it ) {
176  //Triplet< T >* cur = &(*in_it);
177  const ULI currow = in_it->i();
178  const T value = in_it->value;
179  if( value == this->zero_element ) {
180  this->nnz--;
181  continue;
182  }
183  ds.at( currow ).push_back( &(*in_it) );
184  }
185 
186  //allocate arrays
187  row_start = new ULI[ this->nor + 1 ];
188  this->ds = new T[ this->nnz ];
189  col_ind = new ULI[ this->nnz ];
190 
191  //make CRS
192  ULI index = 0;
193  for( ULI currow = 0; currow < this->nor; currow++ ) {
194  row_start[ currow ] = index;
195  if( ds.at( currow ).size() == 0 ) continue;
196  qsort( &( ds.at( currow )[ 0 ] ), ds.at( currow ).size(), sizeof( Triplet< T >* ), &compareTriplets );
197  typename std::vector< Triplet< T >* >::iterator row_it = ds.at( currow ).begin();
198  for( ; row_it!=ds.at( currow ).end(); row_it++ ) {
199  const Triplet< T > cur = *(*row_it);
200  this->ds[ index ] = cur.value;
201  col_ind[ index ] = cur.j();
202  index++;
203  }
204  }
205  row_start[ this->nor ] = this->nnz;
206  std::cout << "\t" << index << " nonzeroes loaded into CRS structure.\n" << std::endl;
207  assert( index == this->nnz );
208  }
209 
216  T& random_access( ULI i, ULI j ) {
217  ULI found_index;
218  if ( find( j, row_start[ i ], row_start[ i+1 ], found_index ) ) {
219 #ifdef _DEBUG
220  std::cout << "Searched col_ind between " << row_start[ i ] << " and " << row_start[ i + 1 ] << ", found: " << std::endl;
221  std::cout << "Element (" << i << "," << j << ") found on index " << found_index << ", returning " << ds[ found_index ] << std::endl;
222 #endif
223  return ds[ found_index ];
224  } else
225  return this->zero_element;
226  }
227 
229  virtual void getFirstIndexPair( ULI &row, ULI &col ) {
230  row = this->row_start[ 0 ];
231  col = this->col_ind[ 0 ];
232  }
233 
237  virtual void zxa( const T*__restrict__ x, T*__restrict__ z ) {
238  T*__restrict__ ds_p = ds;
239  ULI*__restrict__ col_ind_p = col_ind;
240  ULI row, index;
241  for( row = 0; row < this->nor; row++, x++ ) {
242  for( index = row_start[ row ]; index < row_start[ row + 1 ]; index++ )
243  z[ *col_ind_p++ ] += *ds_p++ * *x;
244  }
245  }
246 
253  virtual void zax( const T*__restrict__ x, T*__restrict__ z ) {
254  T*__restrict__ ds_p = ds;
255  ULI*__restrict__ col_ind_p = col_ind;
256  ULI row, index;
257  for( row = 0; row < this->nor; row++, z++ ) {
258  for( index = row_start[ row ]; index < row_start[ row + 1 ]; index++ )
259  *z += *ds_p++ * x[ *col_ind_p++ ];
260  }
261  }
262 
264  template< size_t k >
265  void ZaX( const T*__restrict__ const *__restrict__ const X, T *__restrict__ const *__restrict__ const Z ) {
266  T*__restrict__ ds_p = ds;
267  ULI*__restrict__ col_ind_p = col_ind;
268  ULI row, index;
269  //local buffer of pointers
270  const T *__restrict__ pDataX[ k ];
271  T *__restrict__ pDataZ[ k ];
272  //fill local pointer buffer
273  for( size_t s = 0; s < k; ++s ) {
274  pDataX[s] = X[s];
275  pDataZ[s] = Z[s];
276  }
277  for( row = 0; row < this->nor; ++row ) {
278  for( index = row_start[ row ]; index < row_start[ row + 1 ]; ++index ) {
279  for( size_t s = 0; s < k; ++s ) {
280  assert( pDataZ[s] >= Z[s] );
281  assert( pDataZ[s] < Z[s]+this->nor );
282  assert( *col_ind_p < this->noc );
283  assert( pDataX[s] == X[s] );
284  *(pDataZ[s]) += *ds_p * pDataX[s][ *col_ind_p ];
285  }
286  ++col_ind_p;
287  ++ds_p;
288  }
289  for( size_t s = 0; s < k; ++s ) {
290  ++(pDataZ[s]);
291  }
292  }
293  }
294 
296  template< size_t k >
297  void ZXa( const T *__restrict__ const *__restrict__ const X, T *__restrict__ const *__restrict__ const Z ) {
298  T*__restrict__ ds_p = ds;
299  ULI*__restrict__ col_ind_p = col_ind;
300  ULI row, index;
301  const T *__restrict__ pDataX[ k ];
302  T *__restrict__ pDataZ[ k ];
303  for( size_t s = 0; s < k; ++s ) {
304  pDataX[s] = X[s];
305  pDataZ[s] = Z[s];
306  }
307  for( row = 0; row < this->nor; ++row ) {
308  for( index = row_start[ row ]; index < row_start[ row + 1 ]; ++index ) {
309  for( size_t s = 0; s < k; ++s ) {
310  pDataZ[s][ *col_ind_p ] += *ds_p * *(pDataX[s]);
311  }
312  ++ds_p;
313  ++col_ind_p;
314  }
315  for( size_t s = 0; s < k; ++s ) {
316  ++(pDataX[s]);
317  }
318  }
319  }
320 
322  ULI* rowJump() { return row_start; }
323 
325  ULI* columnIndices() { return col_ind; }
326 
328  T* values() { return ds; }
329 
331  virtual ~CRS() {
332  delete [] row_start;
333  delete [] ds;
334  delete [] col_ind;
335  }
336 
338  virtual size_t bytesUsed() {
339  return sizeof( ULI ) * ( this->nor + this->nnz ) + sizeof( T ) * this->nnz;
340  }
341 
342 };
343 
344 #undef _DEBUG
345 #endif
346 
ULI nnz
Number of non-zeros.
Definition: SparseMatrix.hpp:58
ULI * columnIndices()
Returns pointer to the column index vector.
Definition: CRS.hpp:325
ULI * row_start
Array keeping track of individual row starting indices.
Definition: CRS.hpp:59
virtual void load(std::vector< Triplet< T > > &input, ULI m, ULI n, T zero)
Definition: CRS.hpp:160
CRS(std::string file, T zero=0)
Base constructor.
Definition: CRS.hpp:104
ULI * col_ind
Array containing the column indeces corresponding to the elements in ds.
Definition: CRS.hpp:65
virtual unsigned long int m()
Queries the number of rows this matrix contains.
Definition: SparseMatrix.hpp:107
virtual void zax(const T *__restrict__ x, T *__restrict__ z)
In-place z=Ax function.
Definition: CRS.hpp:253
ULI * rowJump()
Returns pointer to the row_start vector.
Definition: CRS.hpp:322
The compressed row storage sparse matrix data structure.
Definition: CRS.hpp:52
T * values()
Returns pointer to the matrix nonzeros vector.
Definition: CRS.hpp:328
void loadFromFile(const std::string file, const T zero=0)
Function which loads a matrix from a matrix market file.
Definition: SparseMatrix.hpp:89
Interface common to all sparse matrix storage schemes.
Definition: SparseMatrix.hpp:46
CRS(CRS< T > &toCopy)
Copy constructor.
Definition: CRS.hpp:130
void ZXa(const T *__restrict__ const *__restrict__ const X, T *__restrict__ const *__restrict__ const Z)
Definition: CRS.hpp:297
ULI noc
Number of columns.
Definition: SparseMatrix.hpp:55
virtual void zxa(const T *__restrict__ x, T *__restrict__ z)
In-place z=xA function.
Definition: CRS.hpp:237
T value
Value stored at this triplet.
Definition: Triplet.hpp:95
CRS(const ULI number_of_nonzeros, const ULI number_of_rows, const ULI number_of_cols, T zero)
Base constructor which only initialises the internal arrays.
Definition: CRS.hpp:117
ULI nor
Number of rows.
Definition: SparseMatrix.hpp:52
CRS(std::vector< Triplet< T > > input, ULI m, ULI n, T zero)
Constructor which transforms a collection of input triplets to CRS format.
Definition: CRS.hpp:155
virtual void getFirstIndexPair(ULI &row, ULI &col)
Returns the first nonzero index, per reference.
Definition: CRS.hpp:229
T zero_element
The element considered to be zero.
Definition: SparseMatrix.hpp:63
ULI j() const
Definition: Triplet.hpp:73
T * ds
Array containing the actual nnz non-zeros.
Definition: CRS.hpp:62
void ZaX(const T *__restrict__ const *__restrict__ const X, T *__restrict__ const *__restrict__ const Z)
Definition: CRS.hpp:265
virtual size_t bytesUsed()
Definition: CRS.hpp:338
bool find(const ULI col_index, const ULI search_start, const ULI search_end, ULI &ret)
Helper function which finds a value with a given column index on a given subrange of indices...
Definition: CRS.hpp:86
CRS()
Base constructor.
Definition: CRS.hpp:98
virtual unsigned long int n()
Queries the number of columns this matrix contains.
Definition: SparseMatrix.hpp:115
static int compareTriplets(const void *left, const void *right)
Sorts 1D columnwise.
Definition: CRS.hpp:68
A single triplet value.
Definition: Triplet.hpp:52
virtual ~CRS()
Base deconstructor.
Definition: CRS.hpp:331
T & random_access(ULI i, ULI j)
Method which provides random matrix access to the stored sparse matrix.
Definition: CRS.hpp:216