SparseLibrary  Version 1.6.0
ZZ_ICRS.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 "SparseMatrix.hpp"
35 #include "Triplet.hpp"
36 #include <assert.h>
37 #include <vector>
38 #include <algorithm>
39 
40 //#define _DEBUG
41 
42 #ifndef _H_ZZ_ICRS
43 #define _H_ZZ_ICRS
44 
45 //#define _UNSIGNED
46 
47 //#ifdef _DEBUG
48 #include<iostream>
49 //#endif
50 
54 template< typename T >
55 #ifdef _UNSIGNED
56 class ZZ_ICRS: public SparseMatrix< T, ULI > {
57 #else
58 class ZZ_ICRS: public SparseMatrix< T, LI > {
59 #endif
60 
61  private:
62 
63 #ifdef _UNSIGNED
64 
65  typedef ULI myULI;
66 #else
67 
68  typedef LI myULI;
69 #endif
70 
71  protected:
72 
74  size_t jumps;
75 
77  T* ds;
78 
80  myULI* c_ind;
81 
83  myULI* r_ind;
84 
86  static bool compareTriplets( const Triplet< T >& one, const Triplet< T >& two ) {
87  if( one.i() < two.i() )
88  return true;
89  if ( one.i() > two.i() )
90  return false;
91  return one.j() < two.j();
92  }
93 
94  public:
95 
97  ZZ_ICRS() {}
98 
103  ZZ_ICRS( std::string file, T zero = 0 ) {
104  this->loadFromFile( file, zero );
105  }
106 
116  ZZ_ICRS( const myULI number_of_nonzeros, const myULI number_of_rows, const myULI number_of_cols, T zero ):
117  SparseMatrix< T, ULI >( number_of_nonzeros, number_of_rows, number_of_cols, zero ) {
118  ds = new T[ this->nnz ];
119  c_ind = new myULI[ this->nnz ];
120  r_ind = new myULI[ this->nnz ];
121  }
122 
127  ZZ_ICRS( ZZ_ICRS< T >& toCopy ) {
128  this->zero_element = toCopy.zero_element;
129  this->nnz = toCopy.nnz;
130  this->noc = toCopy.noc;
131  this->nor = toCopy.nor;
132  ds = new T[ this->nnz ];
133  c_ind = new myULI[ this->nnz ];
134  r_ind = new myULI[ this->nnz ];
135  for( myULI i=0; i<this->nnz; i = i + 1 ) {
136  ds[ i ] = toCopy.ds[ i ];
137  c_ind[ i ]= toCopy.c_ind[ i ];
138  r_ind[ i ] = toCopy.r_ind[ i ];
139  }
140  }
141 
152  ZZ_ICRS( std::vector< Triplet< T > >& input, const myULI m, const myULI n, const T zero ) {
153  load( input, m, n, zero );
154  }
155 
157  virtual void load( std::vector< Triplet< T > >& input, const myULI m, const myULI n, const T zero ) {
158  this->zero_element = zero;
159 
160  this->nor = m;
161  this->noc = n;
162 
163  typename std::vector< Triplet< T > >::iterator in_it;
164 
165  //WARNING: this->noc*this->nor typically overflows on 32 bits!
166  // immediately start recording differences
167  // instead of trying to directly calculate
168  // the index as i*this->noc+j.
169 
170  sort( input.begin(), input.end(), compareTriplets );
171 
172  //filter out zeros and count the number of row jumps
173  std::vector< myULI > r_ind_temp;
174  typename std::vector< Triplet< T > >::iterator it = input.begin();
175  unsigned long int prev_row = (*it).i();
176  r_ind_temp.push_back( prev_row );
177  it++;
178  for( ; it!=input.end(); it++ ) {
179  if( (*it).i() > prev_row ) {
180  r_ind_temp.push_back( (*it).i() - prev_row );
181  prev_row = (*it).i();
182  }
183  }
184  this->nnz = input.size();
185 
186  //allocate arrays
187  jumps = r_ind_temp.size();
188  ds = new T[ this->nnz ];
189  c_ind = new myULI[ this->nnz + 1 ];
190  r_ind = new myULI[ jumps + 1 ];
191 
192  //set last entry
193  c_ind[ this->nnz ] = this->noc;
194  //r_ind does not have to be set; altough the last element is read, it is actually never used.
195 
196  //copy row-jump vector
197  for( myULI i=0; i<static_cast< myULI >( r_ind_temp.size() ); i++ )
198  r_ind[ i ] = r_ind_temp[ i ];
199 
200  //make ICRS
201  myULI prev_col = 0;
202  prev_row = 0;
203 
204  for( myULI i=0; i<this->nnz; ++i ) {
205  const Triplet< T > cur = input[ i ];
206  const unsigned long int currow = cur.i();
207  const unsigned long int curcol = cur.j();
208  if( currow == prev_row ) {
209  c_ind[ i ] = curcol - prev_col;
210  ds[ i ] = cur.value;
211  prev_col = curcol;
212  } else {
213  prev_row = currow;
214  myULI stop = i;
215  myULI j = i;
216 
217  while( j < this->nnz && input[ j ].i() == static_cast< unsigned long int >( currow ) )
218  j++; //go to next row
219  //ULI next = j; //where the next row starts, OR next = j = this->nnz // unused
220  j--; // j now points at last element at new row
221 
222  //process the first new element
223  ds[ i ] = input[ j ].value;
224  c_ind[ i ] = this->noc + ( input[ j ].j() - prev_col );
225  prev_col = input[ j ].j();
226 
227  i++; //go to next indices
228  j--;
229 
230  for( ; j>=stop; j-- ) { //reversively add the rest to data structure
231  ds[ i ] = input[ j ].value;
232  c_ind[ i ] = prev_col - input[ j ].j();
233  prev_col = input[ j ].j();
234  i++; //increment target index
235  }
236 
237  if( i >= this->nnz ) break;
238 
239  //at this point, the reverse row is completely added
240  //and i should be at the next row index.
241 #ifdef _UNSIGNED
242  c_ind[ i ] = this->noc + input[ i ].j();
243 #else
244  c_ind[ i ] = this->noc + ( prev_col - input[ i ].j() );
245 #endif
246 
247  ds[ i ] = input[ i ].value;
248  prev_col = input[ i ].j();
249  prev_row = input[ i ].i();
250  }
251  }
252  }
253 
255  virtual void getFirstIndexPair( myULI &row, myULI &col ) {
256  row = static_cast< unsigned long int >( this->r_ind[ 0 ] );
257  col = static_cast< unsigned long int >( this->c_ind[ 0 ] );
258  }
259 
266  virtual void zxa( const T*__restrict__ pDataX, T*__restrict__ pDataZ ) {
267 
268  //get some pointers
269  T *__restrict__ pDataA = ds;
270  myULI *__restrict__ pIncRow = r_ind;
271  myULI *__restrict__ pIncCol = c_ind;
272  const T * const pDataZbeg = pDataZ;
273  const T * const pDataZend = pDataZ + this->noc;
274  const T *__restrict__ const pDataAend = ds + this->nnz;
275  //const T * const pDataXbeg = pDataX;
276  //const T * const pDataXend = pDataX + this->nor;
277 
278  //should be optimised out by compiler when NDEBUG is defined
279  myULI rowshadow = 0;
280 
281  //go to first column
282  pDataZ += *pIncCol;
283  pIncCol++;
284 
285  //walk through all matrix entries
286  while( pDataA < pDataAend ) {
287 
288  //jump to correct row
289  pDataX += *pIncRow;
290  rowshadow += *pIncRow;
291 
292  //walk left-to-right
293  while( pDataZ < pDataZend ) {
294 
295  *pDataZ += *pDataA * *pDataX;
296  pDataA++;
297  pDataZ += *pIncCol ;
298  pIncCol++;
299 
300  }
301 
302  //check if there is no more data
303  if( pDataA >= pDataAend ) break;
304 
305  //jump to correct row and column
306  pDataZ -= this->noc ;
307  pIncRow++;
308  pDataX += *pIncRow ;
309  rowshadow+=*pIncRow;
310  assert( rowshadow >= 0 );
311  assert( rowshadow < this->nor );
312 
313  //walk right-to-left
314  while( pDataZbeg <= pDataZ ) {
315 
316  *pDataZ += *pDataA * *pDataX;
317  pDataA++;
318  pDataZ -= *pIncCol ;
319  pIncCol++;
320 
321  }
322 
323  //jump to crrect column
324  pDataZ += this->noc;
325 
326  //set row increment pointer to crrect location
327  pIncRow++;
328 
329  }
330 
331  }
332 
333 
340  virtual void zax( const T*__restrict__ pDataX, T*__restrict__ pDataZ ) {
341 
342  //get some pointers
343  T *__restrict__ pDataA = ds;
344  myULI *__restrict__ pIncRow = r_ind;
345  myULI *__restrict__ pIncCol = c_ind;
346  const T * const pDataXbeg = pDataX;
347  const T * const pDataXend = pDataX + this->noc;
348  const T *__restrict__ const pDataAend = ds + this->nnz;
349 
350  //should be optimised out by compiler when NDEBUG is defined
351  myULI rowshadow = 0;
352 
353  //go to first column
354  pDataX += *pIncCol;
355  pIncCol++;
356 
357  //walk through all matrix entries
358  while( pDataA < pDataAend ) {
359 
360  //jump to correct row
361  pDataZ += *pIncRow;
362  rowshadow += *pIncRow;
363 
364  //walk left-to-right
365  while( pDataX < pDataXend ) {
366 
367  *pDataZ += *pDataA * *pDataX;
368  pDataA++;
369  pDataX += *pIncCol ;
370  pIncCol++;
371 
372  }
373 
374  //check if there is no more data
375  if( pDataA >= pDataAend ) break;
376 
377  //jump to correct row and column
378  pDataX -= this->noc ;
379  pIncRow++;
380  pDataZ += *pIncRow ;
381  rowshadow+=*pIncRow;
382  assert( rowshadow >= 0 );
383  assert( rowshadow < this->nor );
384 
385  //walk right-to-left
386  while( pDataXbeg <= pDataX ) {
387 
388  *pDataZ += *pDataA * *pDataX;
389  pDataA++;
390  pDataX -= *pIncCol ;
391  pIncCol++;
392 
393  }
394 
395  //jump to crrect column
396  pDataX += this->noc;
397 
398  //set row increment pointer to crrect location
399  pIncRow++;
400 
401  }
402 
403  }
404 
405  virtual size_t bytesUsed() {
406  return sizeof( myULI ) * ( this->nnz + jumps + 1 ) + sizeof( T ) * this->nnz;
407  }
408 
411  delete [] ds;
412  delete [] c_ind;
413  delete [] r_ind;
414  }
415 
416 };
417 
418 #endif
419 
LI nnz
Number of non-zeros.
Definition: SparseMatrix.hpp:58
ZZ_ICRS(ZZ_ICRS< T > &toCopy)
Copy constructor.
Definition: ZZ_ICRS.hpp:127
virtual void zxa(const T *__restrict__ pDataX, T *__restrict__ pDataZ)
In-place z=xA multiplication algorithm.
Definition: ZZ_ICRS.hpp:266
ULI i() const
Definition: Triplet.hpp:70
ZZ_ICRS(const myULI number_of_nonzeros, const myULI number_of_rows, const myULI number_of_cols, T zero)
Base constructor which only initialises the internal arrays.
Definition: ZZ_ICRS.hpp:116
virtual void zax(const T *__restrict__ pDataX, T *__restrict__ pDataZ)
In-place z=Ax multiplication algorithm.
Definition: ZZ_ICRS.hpp:340
static bool compareTriplets(const Triplet< T > &one, const Triplet< T > &two)
Comparison function used for sorting input data.
Definition: ZZ_ICRS.hpp:86
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 myULI m, const myULI n, const T zero)
Definition: ZZ_ICRS.hpp:157
size_t jumps
The number of row jumps.
Definition: ZZ_ICRS.hpp:74
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
The zig-zag incremental compressed row storage sparse matrix data structure.
Definition: ZZ_ICRS.hpp:58
virtual size_t bytesUsed()
Function to query the amount of storage required by this sparse matrix.
Definition: ZZ_ICRS.hpp:405
myULI * c_ind
Array containing the column jumps.
Definition: ZZ_ICRS.hpp:80
LI noc
Number of columns.
Definition: SparseMatrix.hpp:55
~ZZ_ICRS()
Base deconstructor.
Definition: ZZ_ICRS.hpp:410
ZZ_ICRS(std::vector< Triplet< T > > &input, const myULI m, const myULI n, const T zero)
Constructor which transforms a collection of input triplets to CRS format.
Definition: ZZ_ICRS.hpp:152
ZZ_ICRS(std::string file, T zero=0)
Base constructor.
Definition: ZZ_ICRS.hpp:103
T value
Value stored at this triplet.
Definition: Triplet.hpp:95
T * ds
Array containing the actual this->nnz non-zeros.
Definition: ZZ_ICRS.hpp:77
LI nor
Number of rows.
Definition: SparseMatrix.hpp:52
T zero_element
The element considered to be zero.
Definition: SparseMatrix.hpp:63
ULI j() const
Definition: Triplet.hpp:73
ZZ_ICRS()
Base constructor.
Definition: ZZ_ICRS.hpp:97
myULI * r_ind
Array containing the row jumps.
Definition: ZZ_ICRS.hpp:83
virtual unsigned long int n()
Queries the number of columns this matrix contains.
Definition: SparseMatrix.hpp:115
virtual void getFirstIndexPair(myULI &row, myULI &col)
Returns the first nonzero index, per reference.
Definition: ZZ_ICRS.hpp:255
A single triplet value.
Definition: Triplet.hpp:52