35 #include "SparseMatrix.hpp"
36 #include "HilbertTriplet.hpp"
37 #include "HilbertTripletCompare.hpp"
38 #include "Triplet.hpp"
45 #ifndef _H_BLOCKHILBERT
46 #define _H_BLOCKHILBERT
51 template<
typename T >
74 static const signed char DS = 2;
80 std::vector< HilbertTriplet< std::vector< Triplet < T > > > >
hilbert;
97 const unsigned long int blocki,
const unsigned long int blockj,
98 const unsigned char depth ) {
100 typename std::vector< Triplet< T > >::iterator it = input.begin();
101 unsigned long int row, col;
102 unsigned long int rl = it->i();
103 unsigned long int rh = it->i();
104 unsigned long int cl = it->j();
105 unsigned long int ch = it->j();
107 for( ; it != input.end(); ++it ) {
108 if( rl > it->i() ) rl = it->i();
109 if( rh < it->i() ) rh = it->i();
110 if( cl > it->j() ) cl = it->j();
111 if( ch < it->j() ) ch = it->j();
120 assert( row <= (
unsigned long int)(this->
nor) );
121 assert( col <= (
unsigned long int)(this->
noc) );
124 const unsigned long int row_lo = rl;
125 const unsigned long int col_lo = cl;
126 const unsigned long int row_hi = rh;
127 const unsigned long int col_hi = ch;
130 unsigned long int re = 0;
131 unsigned long int ce = 0;
132 unsigned long int *rows =
new unsigned long int[ row ];
133 unsigned long int *cols =
new unsigned long int[ col ];
134 for(
unsigned long int i=0; i<row; i++ ) rows[ i ] = 0;
135 for(
unsigned long int j=0; j<col; j++ ) cols[ j ] = 0;
137 for( ; it != input.end(); ++it ) {
138 rows[ it->i()-rl ]++;
139 cols[ it->j()-cl ]++;
141 for(
unsigned long int i=1; i<row; i++ ) {
142 if( rows[i] == 0 ) re++;
143 rows[ i ] += rows[i-1];
145 for(
unsigned long int j=1; j<col; j++ ) {
146 if( cols[j] == 0 ) ce++;
147 cols[ j ] += cols[j-1];
162 const unsigned long int half = input.size() / 2;
167 unsigned long int rs, cs;
168 unsigned long int rm, cm;
173 if( rows[ rm ] < half ) { rs = (rm - rl); rl = rm; }
174 else if( rows[ rm ] > half ) { rs = (rh - rm); rh = rm; }
176 if( cols[ cm ] < half ) { cs = (cm - cl); cl = cm; }
177 else if( cols[ cm ] > half ) { cs = (ch - cm); ch = cm; }
179 if( rs == 0 && cs == 0 )
break;
185 if( rm - row_lo == 0 && row_hi - rm > 1 ) rm++;
186 if( row_hi - rm == 0 && rm - row_lo > 1 ) rm--;
187 if( cm - col_lo == 0 && col_hi - cm > 1 ) cm++;
188 if( col_hi - cm == 0 && cm - col_lo > 1 ) cm--;
192 if( rows[ rm ] > half ) rs = rows[ rm ] - half;
193 else rs = half - rows[ rm ];
194 if( cols[ cm ] > half ) cs = cols[ cm ] - half;
195 else cs = half - cols[ cm ];
196 if ( rs > cs ) dir = 1;
197 else if( cs > rs ) dir = 0;
198 else dir = rand() % 2;
202 if( col_hi - cm == 0 || cm - col_lo == 0 ) {
209 if( row_hi - rm == 0 || rm - row_lo == 0 ) {
217 std::vector< Triplet< T > > t1, t2;
219 for( ; it != input.end(); ++it ) {
222 if( it->j() > cm+col_lo ) t2.push_back( *it );
223 else t1.push_back( *it );
225 if( it->i() > rm+row_lo ) t2.push_back( *it );
226 else t1.push_back( *it );
235 const unsigned long int new_i = dir ? blocki | (1<<(
MAX_DEPTH-depth-1)) : blocki;
236 const unsigned long int new_j =!dir ? blockj | (1<<(
MAX_DEPTH-depth-1)) : blockj;
239 build.push_back( p1 );
241 build.push_back( p2 );
248 if( t1.size() == 0 || t2.size() == 0 )
return 0;
260 std::vector< char > go;
261 go.reserve( build.size() );
262 for(
unsigned long int i=0; i<build.size(); ++i ) go.push_back( 1 );
263 unsigned char depth = 0;
265 std::vector< HilbertTriplet< std::vector< Triplet< T > > > > replace;
266 std::vector< char > replace_go;
267 replace_go.reserve( 2*build.size() );
268 assert( build.size() == go.size() );
269 for(
unsigned long int i=0; i<build.size(); i++ )
271 char ret =
bisect( replace, build[i].value, build[i].i(), build[i].j(), depth );
273 replace_go.push_back( 1 );
274 replace_go.push_back( 1 );
276 replace_go.push_back( 0 );
279 replace.push_back( build[i] );
280 replace_go.push_back( 0 );
283 if( replace.size() == build.size() ) flag = 0;
300 const unsigned long int nnz = input.size();
304 std::vector< HilbertTriplet< std::vector< Triplet< T > > > > ret;
310 std::cout <<
"\t Bisection created " << ret.size() <<
" submatrices," << std::endl;
313 unsigned long int sum = 0;
314 typename std::vector< HilbertTriplet< std::vector< Triplet< T > > > >::iterator it = ret.begin();
315 for( ; it != ret.end(); ++it ) {
316 sum += it->value.size();
319 std::cout <<
"\t storing a total of " << sum <<
" nonzeroes." << std::endl;
321 assert( nnz == sum );
330 const unsigned long int blocks = blockm * blockn;
331 std::cout <<
"\tMaking " << blockm <<
" by " << blockn <<
" submatrices" << std::endl;
332 std::cout <<
"\tyielding a total of " << blocks <<
" blocks. " << std::endl;
333 std::vector< HilbertTriplet< std::vector< Triplet< T > > > > ret;
334 for(
unsigned long int i=0; i<blocks; i++ )
336 typename std::vector< Triplet< T > >::iterator it = input.begin();
337 for( ; it != input.end(); ++it ) {
338 const unsigned long int blocki = it->i() /
BLOCK_M;
339 const unsigned long int blockj = it->j() /
BLOCK_N;
340 ret[ blockn * blocki + blockj ].value.push_back( *it );
348 if( left.i() == right.i() && left.j() == right.j() )
return true;
350 const std::vector< unsigned long int > h_one = left.getHilbert();
351 const std::vector< unsigned long int > h_two = right.getHilbert();
353 unsigned long int max = h_one.size();
354 bool max_is_one =
true;
355 if ( h_two.size() < max ) { max = h_two.size(); max_is_one =
false; }
356 for(
unsigned long int i=0; i<max; i++ )
357 if( h_one[ i ] != h_two[ i ] )
358 return h_one[ i ] < h_two[ i ];
360 std::cout <<
"expand, ";
363 left.morePrecision( this->
nor, this->
noc );
365 right.morePrecision( this->
nor, this->
noc );
367 return cmp( left, right );
381 std::cout <<
"left: " << left <<
", right: " << right << std::endl;
383 if(
hilbert[left].getHilbert().size() > minexp ) minexp =
hilbert[left].getHilbert().size();
384 if(
hilbert[right].getHilbert().size() > minexp ) minexp =
hilbert[right].getHilbert().size();
386 if ( left == right )
return left;
387 if ( left+1 == right )
return right;
389 if (
cmp(
hilbert[ right ], x ) )
return right+1;
391 ULI mid =
static_cast< unsigned long int >( ( left + right ) / 2 );
393 std::cout <<
"mid: " << mid << std::endl;
396 return find( x, left, mid, minexp );
398 return find( x, mid, right, minexp );
436 load( input, m, n, zero );
451 load( input, m, n, zero );
460 this->
nnz = input.size();
462 std::cout << std::endl <<
"Loading into *experimental* block hilbert structure." << std::endl;
465 std::cout <<
"\tUsing bisection to create blocks" << std::endl;
468 std::cout <<
"\tUsing fixed block sizes..." << std::endl;
472 std::cout <<
"\tGetting Hilbert coordinates" << std::endl;
473 typename std::vector< HilbertTriplet< std::vector< Triplet< T > > > >::iterator it =
hilbert.begin();
474 for( ; it!=
hilbert.end(); ++it )
475 it->calculateHilbertCoordinate();
476 std::cout <<
"\tUsing std::sort to get a Hilbert ordering on the sparse blocks" << std::endl;
481 for( ULI i=0; i<this->
nnz; i++ ) {
482 for( ULI j=0; j<
hilbert[i].getHilbert().size(); j++ )
483 std::cout <<
hilbert[i].getHilbert()[j] <<
",";
484 std::cout << std::endl;
488 std::cout <<
"\tLoading into HBICRS..." << std::endl;
489 std::vector< std::vector< Triplet< T > > > hierarchy;
491 for( ; it!=
hilbert.end(); ++it ) hierarchy.push_back( it->value );
492 signed char *hierarchy_datatype =
new signed char[ hierarchy.size() ];
493 for(
unsigned long int i=0; i<hierarchy.size(); i++ ) hierarchy_datatype[i] =
DS;
495 delete [] hierarchy_datatype;
497 std::cout <<
"BlockHilbert structure ready!" << std::endl;
512 virtual void zxa(
const T* x, T* z ) {
523 virtual void zax(
const T* x, T* z ) {
virtual ~BlockHilbert()
Base deconstructor.
Definition: BlockHilbert.hpp:404
LI nnz
Number of non-zeros.
Definition: SparseMatrix.hpp:58
BlockHilbert(std::string file, T zero=0, char bisect=0)
Base constructor.
Definition: BlockHilbert.hpp:421
static const ULI BLOCK_M
Minimum number of rows in a block.
Definition: BlockHilbert.hpp:62
Hilbert-coordinate-aware triplet.
Definition: HilbertTriplet.hpp:46
BlockHilbert()
Base constructor.
Definition: BlockHilbert.hpp:410
static const signed char DS
Which data structure to use for each block.
Definition: BlockHilbert.hpp:74
virtual unsigned long int m()
Queries the number of rows this matrix contains.
Definition: SparseMatrix.hpp:107
char bisection
Whether we use fixed block grid or a bisection-based grid.
Definition: BlockHilbert.hpp:59
char bisect(std::vector< HilbertTriplet< std::vector< Triplet< T > > > > &build, std::vector< Triplet< T > > &input, const unsigned long int blocki, const unsigned long int blockj, const unsigned char depth)
Recursive bisection, leaf case.
Definition: BlockHilbert.hpp:95
Class-comparator of HilbertTriplet.
Definition: HilbertTripletCompare.hpp:41
virtual void zax(const _t_value *__restrict__ x_p, _t_value *__restrict__ y_p)
Calculates y=Ax, but does not allocate y itself.
Definition: HBICRS.hpp:379
virtual size_t bytesUsed()
Function to query the amount of storage required by this sparse matrix.
Definition: BlockHilbert.hpp:527
The Block Hilbert triplet scheme.
Definition: BlockHilbert.hpp:52
virtual void zxa(const T *x, T *z)
Calculates z=xA.
Definition: BlockHilbert.hpp:512
std::vector< HilbertTriplet< std::vector< Triplet< T > > > > hilbert
Vector storing the block indices and their Hilbert coordinates.
Definition: BlockHilbert.hpp:80
std::vector< HilbertTriplet< std::vector< Triplet< T > > > > buildBlocks(std::vector< Triplet< T > > &input)
Builds block array by ordering them in fixed-size sparse submatrices.
Definition: BlockHilbert.hpp:327
ULI minexp
Minimum number of expansions.
Definition: BlockHilbert.hpp:77
bool cmp(HilbertTriplet< std::vector< Triplet< T > > > &left, HilbertTriplet< std::vector< Triplet< T > > > &right)
HilbertCoordinate comparison function.
Definition: BlockHilbert.hpp:346
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 void zax(const T *x, T *z)
Calculates z=Ax.
Definition: BlockHilbert.hpp:523
Interface common to all sparse matrix storage schemes.
Definition: SparseMatrix.hpp:46
LI noc
Number of columns.
Definition: SparseMatrix.hpp:55
BlockHilbert(std::vector< Triplet< T > > &input, LI m, LI n, char bisect, T zero)
Base constructor.
Definition: BlockHilbert.hpp:449
static const ULI MAX_DEPTH
Maximum depth of bisection.
Definition: BlockHilbert.hpp:71
unsigned long int find(HilbertTriplet< std::vector< Triplet< T > > > &x, ULI &left, ULI &right, ULI &minexp)
Binary search for finding a given triplet in a given range.
Definition: BlockHilbert.hpp:379
virtual void getFirstIndexPair(LI &row, LI &col)
Returns the first nonzero index, per reference.
Definition: BlockHilbert.hpp:501
HBICRS< T > * ds
The actual data structure.
Definition: BlockHilbert.hpp:83
static const ULI BLOCK_N
Minimum number of columns in a block.
Definition: BlockHilbert.hpp:65
LI nor
Number of rows.
Definition: SparseMatrix.hpp:52
virtual void zxa(const _t_value *__restrict__ x_p, _t_value *__restrict__ y_p)
Calculates y=xA, but does not allocate y itself.
Definition: HBICRS.hpp:320
T zero_element
The element considered to be zero.
Definition: SparseMatrix.hpp:63
void bisect(std::vector< HilbertTriplet< std::vector< Triplet< T > > > > &build)
Automatically performs recursive bisection on the input nonzeroes to achieve sparse blocking...
Definition: BlockHilbert.hpp:258
static const ULI MAX_BLOCKS
Maximum number of blocks.
Definition: BlockHilbert.hpp:68
virtual unsigned long int n()
Queries the number of columns this matrix contains.
Definition: SparseMatrix.hpp:115
A single triplet value.
Definition: Triplet.hpp:52
std::vector< HilbertTriplet< std::vector< Triplet< T > > > > buildBisectionBlocks(std::vector< Triplet< T > > &input)
Builds block array by bisection.
Definition: BlockHilbert.hpp:298
virtual void load(std::vector< Triplet< T > > &input, const LI m, const LI n, const T zero)
Definition: BlockHilbert.hpp:455
BlockHilbert(std::vector< Triplet< T > > &input, LI m, LI n, T zero)
Base constructor.
Definition: BlockHilbert.hpp:434
virtual size_t bytesUsed()
Function to query the amount of storage required by this sparse matrix.
Definition: HBICRS.hpp:434
virtual void getFirstIndexPair(LI &i, LI &j)
Definition: HBICRS.hpp:310