SparseLibrary  Version 1.6.0
BICRS.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 Mathematic, Utrecht University, 2008.
31  */
32 
33 
34 #include "SparseMatrix.hpp"
35 #include <assert.h>
36 #include <iostream>
37 
38 //Set when in debug mode
39 //#define _DEBUG
40 
41 #ifndef _H_BICRS
42 #define _H_BICRS
43 
57 template< typename _t_value, typename _i_value=LI >
58 class BICRS: public SparseMatrix< _t_value, ULI > {
59 
60  protected:
61 
63  ULI r_start;
64 
66  ULI c_start;
67 
69  ULI r_end;
70 
72  ULI c_end;
73 
75  ULI jumps;
76 
78  _i_value* r_inc;
79 
81  _i_value* c_inc;
82 
84  _t_value* vals;
85 
87  _i_value ntt;
88 
89  public:
90 
92  virtual ~BICRS() {
93  delete [] r_inc;
94  delete [] c_inc;
95  delete [] vals;
96  }
97 
99  BICRS() {}
100 
105  BICRS( std::string file, _t_value zero = 0 ) {
106  this->loadFromFile( file, zero );
107  }
108 
120  BICRS( _i_value* row, _i_value* col, _t_value* val, ULI m, ULI n, ULI nz, _t_value zero ) {
121  this->load( row, col, val, m, n, nz, zero );
122  }
123 
127  BICRS( std::vector< Triplet< _t_value > >& input, ULI m, ULI n, _t_value zero = 0 ) {
128  this->load( input, m, n, zero );
129  }
130 
137  virtual void load( std::vector< Triplet< _t_value > >& input, ULI m, ULI n, _t_value zero ) {
138  ULI nz = input.size();
139  _i_value* row = new _i_value[ nz ];
140  _i_value* col = new _i_value[ nz ];
141  _t_value* val = new _t_value[ nz ];
142  unsigned long int c = 0;
143  typename std::vector< Triplet< _t_value > >::iterator it = input.begin();
144  for( ; it!=input.end(); it++, c++ ) {
145  row[ c ] = (*it).i();
146  col[ c ] = (*it).j();
147  val[ c ] = (*it).value;
148  }
149  load( row, col, val, m, n, nz, zero );
150  assert( vals != val );
151  delete [] row;
152  delete [] col;
153  delete [] val;
154  }
155 
157  void load( _i_value* row, _i_value* col, _t_value* val, ULI m, ULI n, ULI nz, _t_value zero ) {
158 #ifdef _DEBUG
159  std::cerr << "Warning: _DEBUG flag set." << std::endl;
160 #endif
161  this->zero_element = zero;
162  this->nnz = nz;
163  this->nor = m;
164  this->noc = n;
165  this->ntt = n;
166  jumps = 0;
167  if( nz == 0 ) {
168  r_inc = c_inc = NULL;
169  vals = NULL;
170  return; //done
171  }
172  _i_value prevrow = row[ 0 ];
173  for( unsigned long int i=1; i<this->nnz; i++ ) {
174  if( row[ i ] != prevrow )
175  jumps++;
176  prevrow = row[ i ];
177  }
178 #ifdef _DEBUG
179  std::cout << jumps << " row jumps found." << std::endl;
180 #endif
181  r_inc = new _i_value[ jumps + 1 ];
182  c_inc = new _i_value[ this->nnz ];
183  vals = new _t_value[ this->nnz ];
184  for( unsigned long int i=0; i<this->nnz; ++i ) vals[i] = val[i];
185 
186  r_start = row[ 0 ];
187  prevrow = row[ 0 ];
188  c_start = col[ 0 ];
189  int prevcol = col[ 0 ];
190  r_end = row[ nz - 1 ];
191  c_end = col[ nz - 1 ];
192 
193 #ifdef _DEBUG
194  std::cout << "c_inc: " << prevcol << std::endl;
195  std::cout << "r_inc: " << prevrow << std::endl;
196 #endif
197  int c = 0;
198  for( unsigned long int i=1; i<this->nnz; i++ ) {
199  this->c_inc[ i-1 ] = col[ i ] - prevcol;
200  if( row[ i ] != prevrow ) {
201  this->c_inc[ i-1 ] += ntt;
202  this->r_inc[ c++ ] = row[ i ] - prevrow;
203 #ifdef _DEBUG
204  std::cout << "c_inc: " << ntt << std::endl;
205  std::cout << "r_inc: " << row[ i ] - prevrow << std::endl;
206 #endif
207  prevrow = row[ i ];
208  }
209 #ifdef _DEBUG
210  else
211  std::cout << "c_inc: " << col[ i ] - prevcol << std::endl;
212 #endif
213  prevcol = col[ i ];
214  }
215  //overflow so to signal end of matrix
216  c_inc[ this->nnz - 1 ] = ntt;
217  //initialise last row jump to zero (prevent undefined jump)
218  r_inc[ c ] = 0;
219 
220 #ifdef _DEBUG
221  std::cout << "Construction done." << std::endl;
222 #endif
223  }
224 
226  virtual void getFirstIndexPair( ULI &row, ULI &col ) {
227  row = this->r_start;
228  col = this->c_start;
229  }
230 
236  virtual void zxa( const _t_value*__restrict__ x_p, _t_value*__restrict__ y_p ) {
237  const _t_value * y = y_p;
238  _i_value *__restrict__ c_inc_p = c_inc;
239  _i_value *__restrict__ r_inc_p = r_inc;
240  _t_value *__restrict__ v_p = vals;
241 
242 #ifndef NDEBUG
243  const _t_value * x = x_p;
244  const _t_value * const x_end = x+this->nor;
245  const _i_value *__restrict__ const c_inc_end = c_inc+this->nnz+1;
246 #endif
247  const _t_value * const y_end = y+this->noc;
248  const _t_value *__restrict__ const v_end = vals+this->nnz;
249 
250  y_p += this->c_start;
251  x_p += this->r_start;
252  while( v_p < v_end ) {
253  assert( y_p >= y );
254  assert( y_p < y_end );
255  assert( v_p >= vals );
256  assert( v_p < v_end );
257  assert( x_p >= x );
258  assert( x_p < x_end );
259  assert( c_inc_p >= c_inc );
260  assert( c_inc_p < c_inc_end );
261  assert( r_inc_p >= r_inc );
262  while( y_p < y_end ) {
263 #ifdef _DEBUG
264  std::cout << (x_p-x) << "," << (y_p-y) << " next increment: " << (*(c_inc_p+1))<< std::endl;
265 #endif
266  *y_p += *v_p++ * *x_p;
267  y_p += *c_inc_p++;
268  }
269  y_p -= ntt;
270  x_p += *r_inc_p++;
271  }
272  }
273 
279  virtual void zax( const _t_value*__restrict__ x_p, _t_value*__restrict__ y_p ) {
280  const _t_value * x = x_p;
281  _i_value *__restrict__ c_inc_p = c_inc;
282  _i_value *__restrict__ r_inc_p = r_inc;
283  _t_value *__restrict__ v_p = vals;
284 
285 #ifndef NDEBUG
286  const _t_value * y = y_p;
287  const _t_value * const y_end = y+this->nor;
288  const _i_value *__restrict__ const c_inc_end = c_inc+this->nnz;
289 #endif
290  const _t_value * const x_end = x+this->noc;
291  const _t_value *__restrict__ const v_end = vals+this->nnz;
292 
293  x_p += c_start;
294  y_p += r_start;
295  while( v_p < v_end ) {
296  assert( y_p >= y );
297  assert( y_p < y_end );
298  assert( v_p >= vals );
299  assert( v_p < v_end );
300  assert( x_p >= x );
301  assert( x_p < x_end );
302  assert( c_inc_p >= c_inc );
303  assert( c_inc_p < c_inc_end );
304  assert( r_inc_p >= r_inc );
305  while( x_p < x_end ) {
306 #ifdef _DEBUG
307  std::cout << (y_p-y) << "," << (x_p-x) << " next increment: " << (*(c_inc_p+1))<< std::endl;
308 #endif
309  *y_p += *v_p++ * *x_p;
310  x_p += *c_inc_p++;
311  }
312  x_p -= ntt;
313  y_p += *r_inc_p++;
314  }
315  }
316 
322  virtual void zax_fb( _t_value*__restrict__ x_f, _t_value*__restrict__ y_f ) {
323  const _t_value * x = x_f;
324  _i_value *__restrict__ c_inc_f = c_inc;
325  _i_value *__restrict__ r_inc_f = r_inc;
326  _i_value *__restrict__ c_inc_b = c_inc+this->nnz - 1;
327  _i_value *__restrict__ r_inc_b = r_inc+this->jumps;
328  _t_value *__restrict__ v_f = vals;
329  _t_value *__restrict__ v_b = vals+this->nnz - 1;
330  _t_value *__restrict__ x_b = x_f + this->noc - 1;
331  _t_value *__restrict__ y_b = y_f + this->nor - 1;
332 #ifndef NDEBUG
333  const _t_value * y = y_f;
334  const _t_value * const y_end = y+this->nor;
335  const _i_value *__restrict__ const c_inc_end = c_inc+this->nnz;
336 #endif
337  const _t_value * const x_end = x+this->noc;
338  const _t_value *__restrict__ const v_end = vals+this->nnz;
339 
340  x_f += c_start;
341  y_f += r_start;
342  x_b += c_end;
343  y_b += r_end;
344  while( v_f < v_end && v_b >= vals ) {
345  assert( y_f >= y );
346  assert( y_f < y_end );
347  assert( y_b >= y );
348  assert( y_b < y_end );
349  assert( v_f >= vals );
350  assert( v_f < v_end );
351  assert( v_b >= vals );
352  assert( v_b < v_end );
353  assert( x_f >= x );
354  assert( x_f < x_end );
355  assert( x_b >= x );
356  assert( x_b < x_end );
357  assert( c_inc_f >= c_inc );
358  assert( c_inc_f < c_inc_end );
359  assert( c_inc_b >= c_inc );
360  assert( c_inc_b < c_inc_end );
361  assert( r_inc_b >= r_inc );
362  assert( r_inc_f >= r_inc );
363 #ifdef _DEBUG
364  std::cout << (y_p-y) << "," << (x_p-x) << " next increment: " << (*(c_inc_p+1))<< std::endl;
365 #endif
366  *y_f += *v_f++ * *x_f;
367  x_f += *c_inc_f++;
368  if( x_f >= x_end ) {
369  x_f -= ntt;
370  y_f += *r_inc_f++;
371  }
372  if( v_b < v_f ) break;
373  *y_b += *v_b-- * *x_b;
374  x_b -= *c_inc_b--;
375  if( x_b < x ) {
376  x_b += ntt;
377  y_b -= *r_inc_b++;
378  }
379  }
380  }
381 
382  virtual size_t bytesUsed() {
383  return sizeof( ULI ) * 4 + sizeof( _i_value ) * ( this->nnz + jumps + 1 ) + sizeof( _t_value ) * this->nnz;
384  }
385 };
386 
387 #endif
388 
ULI nnz
Number of non-zeros.
Definition: SparseMatrix.hpp:58
ULI c_end
Stores the column end position.
Definition: BICRS.hpp:72
virtual void zxa(const _t_value *__restrict__ x_p, _t_value *__restrict__ y_p)
Calculates y=xA, but does not allocate y itself.
Definition: BICRS.hpp:236
ULI c_start
Stores the column start position.
Definition: BICRS.hpp:66
virtual size_t bytesUsed()
Function to query the amount of storage required by this sparse matrix.
Definition: BICRS.hpp:382
Bi-directional Incremental Compressed Row Storage scheme.
Definition: BICRS.hpp:58
virtual void zax_fb(_t_value *__restrict__ x_f, _t_value *__restrict__ y_f)
Calculates y=Ax, but does not allocate y itself.
Definition: BICRS.hpp:322
virtual unsigned long int m()
Queries the number of rows this matrix contains.
Definition: SparseMatrix.hpp:107
BICRS()
Base constructor.
Definition: BICRS.hpp:99
virtual ~BICRS()
Base deconstructor.
Definition: BICRS.hpp:92
void loadFromFile(const std::string file, const _t_valuezero=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
BICRS(std::vector< Triplet< _t_value > > &input, ULI m, ULI n, _t_value zero=0)
Base constructor.
Definition: BICRS.hpp:127
ULI noc
Number of columns.
Definition: SparseMatrix.hpp:55
ULI r_start
Stores the row start position.
Definition: BICRS.hpp:63
void load(_i_value *row, _i_value *col, _t_value *val, ULI m, ULI n, ULI nz, _t_value zero)
Definition: BICRS.hpp:157
virtual void load(std::vector< Triplet< _t_value > > &input, ULI m, ULI n, _t_value zero)
This function will rewrite the std::vector< Triplet > structure to one suitable for the other load fu...
Definition: BICRS.hpp:137
BICRS(_i_value *row, _i_value *col, _t_value *val, ULI m, ULI n, ULI nz, _t_value zero)
Base constructor.
Definition: BICRS.hpp:120
_i_value * r_inc
Stores the row jumps; size is at maximum the number of nonzeros.
Definition: BICRS.hpp:78
ULI nor
Number of rows.
Definition: SparseMatrix.hpp:52
virtual void zax(const _t_value *__restrict__ x_p, _t_value *__restrict__ y_p)
Calculates y=Ax, but does not allocate y itself.
Definition: BICRS.hpp:279
virtual void getFirstIndexPair(ULI &row, ULI &col)
Returns the first nonzero index, per reference.
Definition: BICRS.hpp:226
_i_value * c_inc
Stores the column jumps; size is exactly the number of nonzeros.
Definition: BICRS.hpp:81
_t_value zero_element
The element considered to be zero.
Definition: SparseMatrix.hpp:63
BICRS(std::string file, _t_value zero=0)
Base constructor.
Definition: BICRS.hpp:105
virtual unsigned long int n()
Queries the number of columns this matrix contains.
Definition: SparseMatrix.hpp:115
_t_value * vals
Stores the values of the individual nonzeros.
Definition: BICRS.hpp:84
A single triplet value.
Definition: Triplet.hpp:52
_i_value ntt
Caches n times two.
Definition: BICRS.hpp:87
ULI jumps
Stores the number of row jumps.
Definition: BICRS.hpp:75
ULI r_end
Stores the row end position.
Definition: BICRS.hpp:69