SparseLibrary  Version 1.6.0
Upscaler.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 Computer Science, KU Leuven, 2012.
31  */
32 
33 
34 #ifndef _H_UPSCALER
35 #define _H_UPSCALER
36 
37 #include "SBDTree.hpp"
38 #include "Triplet.hpp"
39 
40 #include<algorithm>
41 #include<vector>
42 #include<map>
43 
48 template< typename T >
49 class Upscaler : public SBDTree {
50 
51  private:
52 
54  Upscaler() {}
55 
56  protected:
57 
59  std::vector< std::vector< Triplet< T > > > nonzeroes;
60 
62  std::vector< std::vector< bool > > containsPID;
63 
65  class treeIterator {
66  protected:
67 
69  unsigned long int walk;
70 
72  unsigned long int ID;
73 
78  std::vector< bool > processed;
79 
84  std::vector< bool > *p_processed;
85 
88 
89  public:
90 
97  treeIterator( Upscaler< T > *_p, const unsigned long int initial, std::vector< bool > *_pp = NULL ):
98  walk( initial ), ID( initial ), p_processed( _pp ), p( _p ){
99  if( _pp == NULL ) {
100  for( unsigned long int k=0; k<p->size(); ++k )
101  processed.push_back( false );
103  } else {
104  if( p_processed->size() < p->size() )
105  p_processed->resize( p->size() );
106  for( unsigned long int k=0; k<p->size(); ++k )
107  p_processed->operator[]( k ) = false;
108  }
109  p_processed->operator[]( ID ) = true;
110  }
111 
113  unsigned long int position() { return walk; }
114 
116  virtual bool next() {
117  do {
118  const unsigned long int P = p->parent[ walk ];
119  const unsigned long int l = p->left_child[ walk ];
120  const unsigned long int r = p->right_child[ walk ];
121  if( l != NO_SUCH_NODE && !p_processed->operator[]( l ) ) {
122  walk = l;
123  break;
124  } else if( r != NO_SUCH_NODE && !p_processed->operator[]( r ) ) {
125  walk = r;
126  break;
127  } else
128  walk = P;
129  } while( walk != p->parent[ ID ] );
130 
131  if( walk == p->parent[ ID ] )
132  return false; //done
133 
134  assert( !p_processed->operator[]( walk ) );
135  //flag as visited
136  p_processed->operator[]( walk ) = true;
137  //return success
138  return true;
139  }
140  };
141 
144  public:
145 
153  treeInOrderIterator( Upscaler< T > *_p, const unsigned long int initial, std::vector< bool > *_pp = NULL ):
154  treeIterator( _p, initial, _pp ) {
155  this->p_processed->operator[]( this->ID ) = false; //undo pre-order traversal default visit of the top node
156  next(); //assume at least one unprocessed node
157  }
158 
164  virtual bool next() {
165  while( this->walk != this->p->parent[ this->ID ] ) {
166  //run left as far as is possible
167  while( this->p->left_child[ this->walk ] != NO_SUCH_NODE &&
168  !this->p_processed->operator[]( this->p->left_child[ this->walk ] ) )
169  this->walk = this->p->left_child[ this->walk ];
170 
171  //if the current position is already processed
172  if( this->p_processed->operator[]( this->walk ) ) {
173  //if I could not go left, try to go right and repeat
174  if( this->p->right_child[ this->walk ] != NO_SUCH_NODE &&
175  !this->p_processed->operator[]( this->p->right_child[ this->walk ] ) ) {
176  this->walk = this->p->right_child[ this->walk ];
177  } else {
178  //otherwise go up
179  this->walk = this->p->parent[ this->walk ];
180  }
181  } else {
182  //walk is the current one to be processed
183  this->p_processed->operator[]( this->walk ) = true;
184  return true;
185  }
186  }
187  //I am back at the start location and the start location is processed
188  return false;
189  }
190  };
191 
194  public:
195 
203  treePostOrderIterator( Upscaler< T > *_p, const unsigned long int initial, std::vector< bool > *_pp = NULL ):
204  treeIterator( _p, initial, _pp ) {
205  this->p_processed->operator[]( this->ID ) = false; //undo pre-order traversal default visit of the top node
206  next(); //assume at least one unprocessed node
207  }
208 
214  virtual bool next() {
215  while( this->walk != this->p->parent[ this->ID ] ) {
216  //run left as far as is possible
217  while( this->p->left_child[ this->walk ] != NO_SUCH_NODE &&
218  !this->p_processed->operator[]( this->p->left_child[ this->walk ] ) )
219  this->walk = this->p->left_child[ this->walk ];
220 
221  //if there is a right unprocessed child, go there and repeat
222  if( this->p->right_child[ this->walk ] != NO_SUCH_NODE &&
223  !this->p_processed->operator[]( this->p->right_child[ this->walk ] ) )
224  this->walk = this->p->right_child[ this->walk ];
225  else if( !this->p_processed->operator[]( this->walk ) ) {
226  //I cannot go left nor right, but before I go up I should process current node
227  this->p_processed->operator[]( this->walk ) = true;
228  return true;
229  } else {
230  //I cannot go left nor right and current node is processed,
231  //so go up and repeat
232  this->walk = this->p->parent[ this->walk ];
233  }
234  }
235  //I am back at the start location and the start location is processed
236  return false;
237  }
238  };
239 
252  void determineEmpty( const std::vector< Triplet< T > > &nonzeroes, const unsigned long int s,
253  const unsigned long int min_i, const unsigned long int min_j,
254  std::vector< bool > &emptyRows, std::vector< bool > &emptyCols,
255  bool &empty ) {
256  empty = true;
257  for( unsigned long int k = 0; k < nonzeroes.size(); ++k ) {
258  if( nonzeroes[ k ].meta != s ) continue;
259  const unsigned long int i = nonzeroes[ k ].i();
260  const unsigned long int j = nonzeroes[ k ].j();
261  assert( i - min_i < emptyRows.size() );
262  assert( j - min_j < emptyCols.size() );
263  if( emptyRows[ i - min_i ] ) emptyRows[ i - min_i ] = false;
264  if( emptyCols[ j - min_j ] ) emptyCols[ j - min_j ] = false;
265  if( empty ) empty = false;
266  }
267  }
268 
270  void updateMinMax( const unsigned long int walk, const unsigned long int s,
271  unsigned long int &min_i, unsigned long int &max_i,
272  unsigned long int &min_j, unsigned long int &max_j ) {
273  for( unsigned long int k = 0; k < nonzeroes[ walk ].size(); k++ )
274  if( nonzeroes[ walk ][ k ].meta == s ) {
275  const unsigned long int i = nonzeroes[ walk ][ k ].i();
276  const unsigned long int j = nonzeroes[ walk ][ k ].j();
277  if( i < min_i ) min_i = i;
278  if( i > max_i ) max_i = i;
279  if( j < min_j ) min_j = j;
280  if( j > max_j ) max_j = j;
281  }
282  }
283 
288  void determineMinMax( const unsigned long int ID, const unsigned long int s,
289  unsigned long int &min_i, unsigned long int &max_i,
290  unsigned long int &min_j, unsigned long int &max_j ) {
291  //determine range of nonzeroes
292  min_i = min_j = ULONG_MAX;
293  max_i = max_j = 0;
294  //go up
295  unsigned long int walk = ID;
296  for( ; walk != NO_SUCH_NODE; walk = parent[ walk ] ) {
297  updateMinMax( walk, s, min_i, max_i, min_j, max_j );
298  }
299  //go down
300  treeIterator it( this, ID );
301  while( it.next() ) {
302  //I am at a unprocessed node, so do processing
303  updateMinMax( it.position(), s, min_i, max_i, min_j, max_j );
304  }
305  }
306 
308  void addNonzeroes( std::vector< Triplet< T > > &into,
309  const unsigned long int from, const unsigned long int s,
310  const std::map< unsigned long int, unsigned long int > &rowGlobalToLocal,
311  const std::map< unsigned long int, unsigned long int > &colGlobalToLocal ) {
312  for( unsigned long int i=0; i<nonzeroes[ from ].size(); i++ ) {
313  if( nonzeroes[ from ][ i ].meta != s )
314  continue;
315  const unsigned long int old_i = nonzeroes[ from ][ i ].i();
316  const unsigned long int old_j = nonzeroes[ from ][ i ].j();
317  assert( rowGlobalToLocal.find( old_i ) != rowGlobalToLocal.end() );
318  assert( colGlobalToLocal.find( old_j ) != colGlobalToLocal.end() );
319  const unsigned long int new_i = rowGlobalToLocal.find( old_i )->second;
320  const unsigned long int new_j = colGlobalToLocal.find( old_j )->second;
321  into.push_back( Triplet< double >( new_i, new_j, nonzeroes[ from ][ i ].value ) );
322  into.back().meta = s;
323  }
324  }
325 
344  void getSubTree( const unsigned long int ID,
345  const unsigned long int s,
346  std::vector< Triplet< T > > &local_nonzeroes,
347  std::vector< Triplet< T > > &remote_nonzeroes,
348  std::vector< unsigned long int > &upscaled_hierarchy,
349  std::vector< unsigned long int > &upscaled_row_bounds,
350  std::vector< unsigned long int > &upscaled_column_bounds,
351  std::vector< unsigned long int > &rowLocalToGlobal,
352  std::vector< unsigned long int > &columnLocalToGlobal,
353  std::map< unsigned long int, unsigned long int > &rowGlobalToLocal,
354  std::map< unsigned long int, unsigned long int > &colGlobalToLocal ) {
355 
356  //determine range of nonzeroes
357  unsigned long int min_i, min_j, max_i, max_j;
358  determineMinMax( ID, s, min_i, max_i, min_j, max_j );
359 
360  //max should be an exclusive bound
361  max_i++; max_j++;
362 
363  //report global ranges
364  std::cout << "Processor " << s << " has global ranges \t( " << min_i << ", " << max_i << " ) x ( " << min_j << ", " << max_j << " )" << std::endl;
365 
366  //find empty rows and columns
367  std::vector< bool > emptyRows, emptyCols, emptyNodes;
368  for( unsigned long int i = min_i; i < max_i; ++i )
369  emptyRows.push_back( true );
370  for( unsigned long int j = min_j; j < max_j; ++j )
371  emptyCols.push_back( true );
372  for( unsigned long int k = 0; k < size(); k++ )
373  emptyNodes.push_back( true );
374  assert( emptyRows.size() == max_i - min_i );
375  assert( emptyCols.size() == max_j - min_j );
376 
377  //down
378  treeIterator it( this, ID );
379  do {
380  bool empty;
381  determineEmpty( nonzeroes[ it.position() ], s, min_i, min_j, emptyRows, emptyCols, empty );
382  emptyNodes[ it.position() ] = empty;
383  } while( it.next() );
384 
385  //up
386  unsigned long int walk = ID;
387  while( walk != root ) {
388  bool empty;
389  walk = parent[ walk ];
390  determineEmpty( nonzeroes[ walk ], s, min_i, min_j, emptyRows, emptyCols, empty );
391  emptyNodes[ walk ] = empty;
392  }
393 
394  //build local to global, and their inverses
395  for( unsigned long int i = 0; i < max_i - min_i; ++i )
396  if( !emptyRows[ i ] ) {
397  rowGlobalToLocal[ i + min_i ] = rowLocalToGlobal.size();
398  rowLocalToGlobal.push_back( i + min_i );
399  }
400  for( unsigned long int j = 0; j < max_j - min_j; ++j )
401  if( !emptyCols[ j ] ) {
402  colGlobalToLocal[ j + min_j ] = columnLocalToGlobal.size();
403  columnLocalToGlobal.push_back( j + min_j );
404  }
405 
406  //derive lowest and highest index by traversing the subtree
407  unsigned long int lowest_index, highest_index;
408  treeIterator it2( this, ID );
409  lowest_index = ULONG_MAX;
410  highest_index = 0;
411  do {
412  const unsigned long int pos = it2.position();
413  if( emptyNodes[ pos ] ) continue; //ignore empty nodes
414  if( pos < lowest_index ) lowest_index = pos;
415  if( pos > highest_index ) highest_index = pos;
416  } while( it2.next() );
417 
418  //determine number of empty rows and column
419  unsigned long int numEmptyRows, numEmptyCols;
420  numEmptyRows = numEmptyCols = 0;
421  for( unsigned long int i = 0; i < emptyRows.size(); i++ )
422  if( emptyRows[ i ] ) numEmptyRows++;
423  for( unsigned long int j = 0; j < emptyCols.size(); j++ )
424  if( emptyCols[ j ] ) numEmptyCols++;
425 
426  //report local size
427  std::cout << "Processor " << s << " has local size \t" << (max_i-numEmptyRows-min_i) << " x " << (max_j-numEmptyCols-min_j) << std::endl;
428 
429  //determine upscaled hierarchy and boundaries, write local nonzeroes
430  treeInOrderIterator in_it( this, ID );
431  std::map< unsigned long int, unsigned long int >::iterator glob2loc;
432  do {
433  const unsigned long int pos = in_it.position();
434 
435  //do not add out-of-range nodes
436  if( pos < lowest_index || pos > highest_index ) continue;
437 
438  addNonzeroes( local_nonzeroes, pos, s, rowGlobalToLocal, colGlobalToLocal );
439 
440  glob2loc = rowGlobalToLocal.lower_bound( this->r_lo[ pos ] );
441  assert( glob2loc->first >= this->r_lo[ pos ] );
442  upscaled_row_bounds.push_back( glob2loc->second );
443 
444  glob2loc = colGlobalToLocal.lower_bound( this->c_lo[ pos ] );
445  assert( glob2loc->first >= this->c_lo[ pos ] );
446  upscaled_column_bounds.push_back( glob2loc->second );
447 
448  upscaled_hierarchy.push_back ( pos == ID ? 0 : parent[ pos ] - lowest_index );
449  } while( in_it.next() );
450 
451  //insert final boundary points
452  std::vector< unsigned long int >::iterator loc2glob;
453  loc2glob = std::lower_bound( rowLocalToGlobal.begin(), rowLocalToGlobal.end(), this->r_hi[ highest_index ] );
454  upscaled_row_bounds.push_back( loc2glob - rowLocalToGlobal.begin() );
455 
456  loc2glob = std::lower_bound( columnLocalToGlobal.begin(), columnLocalToGlobal.end(), this->c_hi[ highest_index ] );
457  upscaled_column_bounds.push_back( loc2glob - columnLocalToGlobal.begin() );
458 
459  //write non-local nonzeroes
460  walk = parent[ ID ];
461  while( walk != NO_SUCH_NODE ) {
462  addNonzeroes( remote_nonzeroes, walk, s, rowGlobalToLocal, colGlobalToLocal );
463  walk = parent[ walk ];
464  }
465  //done!
466  }
467 
468  public:
469 
471  Upscaler( const std::vector< Triplet< T > > &nonzeroes, const unsigned long int P,
472  std::vector< unsigned long int > &r_hierarchy,
473  std::vector< unsigned long int > &c_hierarchy,
474  std::vector< unsigned long int > &r_bounds,
475  std::vector< unsigned long int > &c_bounds,
476  unsigned long int *row_perm = NULL,
477  unsigned long int *col_perm = NULL,
478  unsigned long int *proc2proc = NULL ) : SBDTree( r_hierarchy, c_hierarchy, r_bounds, c_bounds ) {
479  //limitation check
480  const unsigned long int trueP = r_bounds.size() / 2;
481  if( floor(log2(trueP)) != log2(trueP) && trueP != P ) {
482  std::cout << "P=" << trueP << " is not a power of 2. Current Upscaler cannot handle incomplete binary trees, exiting." << std::endl;
483  exit( 1 );
484  }
485 
486  //we will group nonzeroes and put them in the corresponding SBD tree nodes
487  this->nonzeroes.resize( this->size() );
488  containsPID.resize( this->size() );
489  for( unsigned long int i=0; i<this->size(); ++i )
490  for( unsigned long int s=0; s<P; ++s )
491  containsPID[ i ].push_back( false );
492  //to prevent inserting nonzeroes on at a time in a top-to-bottom way,
493  //construct a boundary-to-node map to speed up finding the correct
494  //internal node for each nonzero (note this is still of asymptotic
495  //complexity O(nnz*log(hierarchy.size()))
496  std::map< unsigned long int, unsigned long int > rowMap, colMap;
497  //walk from back to front so that the correct node index is stored
498  //for empty separators
499  for( unsigned long int i=r_bounds.size()-1; i>0; --i ) {
500  rowMap[ r_bounds[ i ] ] = i - 1;
501  }
502  //note that we identify blocks by their upper corner points!
503  for( unsigned long int j=c_bounds.size()-1; j>0; --j ) {
504  colMap[ c_bounds[ j ] ] = j - 1;
505  }
506  //for each nonzero, find the correct SBD tree spot
507  for( unsigned long int k=0; k<nonzeroes.size(); ++k ) {
508  const unsigned long int i = row_perm == NULL ? nonzeroes[ k ].i() : row_perm[ nonzeroes[ k ].i() ];
509  const unsigned long int j = col_perm == NULL ? nonzeroes[ k ].j() : col_perm[ nonzeroes[ k ].j() ];
510  const unsigned long int s = proc2proc == NULL ? nonzeroes[ k ].meta : proc2proc[ nonzeroes[ k ].meta ];
511  const unsigned long int u = rowMap.upper_bound( i )->second;
512  const unsigned long int v = colMap.upper_bound( j )->second;
513  Triplet< T > newTriplet( i, j, nonzeroes[ k ].value );
514  newTriplet.meta = s;
515  assert( u < r_hierarchy.size() );
516  assert( v < c_hierarchy.size() );
517  assert( r_lo[ u ] <= i && i < r_hi[ u ] );
518  assert( c_lo[ v ] <= j && j < c_hi[ v ] );
519  if( u == v ) {
520  containsPID[ u ][ s ] = true;
521  this->nonzeroes[ u ].push_back( newTriplet );
522  } else if( u == root || v == root ) {
523  containsPID[ root ][ s ] = true;
524  this->nonzeroes[ root ].push_back( newTriplet );
525  } else if( (u && 1) == 1 || (v && 1 ) == 1) {
526  unsigned long int walk = (u && 1) == 1 ? parent[ u ] : parent[ v ];
527  const unsigned long int compare = (u && 1) == 1 ? v : u;
528  while( walk != root && walk != compare )
529  walk = parent[ walk ];
530  containsPID[ walk ][ s ] = true;
531  this->nonzeroes[ walk ].push_back( newTriplet );
532  } else {
533  std::cerr << "Nonzero in two different pure SBD blocks, which is impossible." << std::endl <<
534  "Quitting on account of a bad SBD hierarchy input." << std::endl;
535  exit( EXIT_FAILURE );
536  }
537  }
538 
539  //check
540  unsigned long int newnnz = 0;
541  for( unsigned long int t = 0; t < size(); ++t )
542  newnnz += this->nonzeroes[ t ].size();
543  assert( newnnz = nonzeroes.size() );
544  }
545 
548 
568  void getSubTree( const unsigned long int s,
569  std::vector< Triplet< T > > &local_nonzeroes,
570  std::vector< Triplet< T > > &remote_nonzeroes,
571  std::vector< unsigned long int > &upscaled_hierarchy,
572  std::vector< unsigned long int > &upscaled_row_bounds,
573  std::vector< unsigned long int > &upscaled_column_bounds,
574  std::vector< unsigned long int > &rowLocalToGlobal,
575  std::vector< unsigned long int > &columnLocalToGlobal,
576  std::map< unsigned long int, unsigned long int > &rowGlobalToLocal,
577  std::map< unsigned long int, unsigned long int > &colGlobalToLocal,
578  const unsigned long int P, const unsigned long int Pref ) {
579 
580  //determine which nodes contain nonzeroes belonging to s
581  std::vector< bool > empty;
582  for( unsigned long int i = 0; i < size(); ++i ) empty.push_back( true );
583 
584  //check the nonzeroes themselves
585  for( unsigned long int i = 0; i < size(); ++i ) {
586  for( unsigned long int k = 0; k < nonzeroes[ i ].size(); ++k ) {
587  if( nonzeroes[ i ][ k ].meta == s ) {
588  empty[ i ] = false;
589  break;
590  }
591  }
592  }
593 
594  //if one of my children is nonempty, I am nonempty too
595  treePostOrderIterator post_it( this, this->root );
596  do {
597  const unsigned long int pos = post_it.position();
598  if( this->left_child[ pos ] == NO_SUCH_NODE ) {
599  //if this is a leaf node, do nothing
600  assert( this->right_child[ pos ] == NO_SUCH_NODE );
601  } else {
602  //if this is an internal node, do the above check
603  if( !empty[ this->left_child[ pos ] ] ) {
604  if( empty[ pos ] ) empty[ pos ] = false;
605  } else if( !empty[ this->right_child[ pos ] ] ) {
606  if( empty[ pos ] ) empty[ pos ] = false;
607  }
608  }
609  } while( post_it.next() );
610 
611  //the highest node with two nonempty children will be the new root
612  unsigned long int root = ULONG_MAX;
613  treeIterator pre_it( this, this->root );
614  do {
615  const unsigned long int pos = pre_it.position();
616  if( !empty[ pos ] && //if there is no internal root,
617  this->left_child[ pos ] == NO_SUCH_NODE && //take only the leaf node as
618  this->right_child[ pos ] == NO_SUCH_NODE ) { //root, assuming there is
619  if( root == ULONG_MAX ) //exactly one
620  root = pos;
621  else {
622  std::cout << "There seem to be multiple leaf nodes beloning to target processor, yet there are no shared separators?" << std::endl;
623  exit( 1 );
624  }
625  }
626  if( this->left_child[ pos ] != NO_SUCH_NODE ) {
627  assert( this->right_child[ pos ] != NO_SUCH_NODE );
628  if( !empty[ this->left_child[ pos ] ] &&
629  !empty[ this->right_child[ pos ] ] ) {
630  root = pos;
631  break;
632  }
633  }
634  } while( pre_it.next() );
635 
636  if( root == ULONG_MAX ) {
637  std::cerr << "No root found! Error in hierarchy, exiting..." << std::endl;
638  exit( 1 );
639  }
640 
641  //continue with that node
642  getSubTree( root, s, local_nonzeroes,
643  remote_nonzeroes, upscaled_hierarchy,
644  upscaled_row_bounds, upscaled_column_bounds,
645  rowLocalToGlobal, columnLocalToGlobal,
646  rowGlobalToLocal, colGlobalToLocal );
647  }
648 
650  void readout() {
651  std::cout << "Index: ";
652  for( unsigned long int i=0; i<size(); ++i )
653  std::cout << i << " ";
654  std::cout << std::endl;
655  std::cout << "Hierarchy: ";
656  for( unsigned long int i=0; i<size(); ++i )
657  std::cout << (this->parent[ i ]==NO_SUCH_NODE?0:this->parent[ i ]) << " ";
658  std::cout << std::endl;
659  std::cout << "Left: ";
660  for( unsigned long int i=0; i<size(); ++i )
661  std::cout << (this->left_child[ i ]==NO_SUCH_NODE?0:this->left_child[ i ]) << " ";
662  std::cout << std::endl;
663  std::cout << "Right: ";
664  for( unsigned long int i=0; i<size(); ++i )
665  std::cout << (this->right_child[ i ]==NO_SUCH_NODE?0:this->right_child[ i ]) << " ";
666  std::cout << std::endl;
667  }
668 
669 };
670 
671 #endif
treeInOrderIterator(Upscaler< T > *_p, const unsigned long int initial, std::vector< bool > *_pp=NULL)
Base constructor.
Definition: Upscaler.hpp:153
unsigned long int root
Which node ID corresponds to the root.
Definition: SBDTree.hpp:70
std::vector< std::vector< Triplet< T > > > nonzeroes
All nonzeroes, stored block-by-block.
Definition: Upscaler.hpp:59
unsigned long int * right_child
Array s.t.
Definition: SBDTree.hpp:55
unsigned long int * left_child
Array s.t.
Definition: SBDTree.hpp:52
void updateMinMax(const unsigned long int walk, const unsigned long int s, unsigned long int &min_i, unsigned long int &max_i, unsigned long int &min_j, unsigned long int &max_j)
Determine min/max of nonzeroes owned by processor s inside node walk.
Definition: Upscaler.hpp:270
unsigned long int * c_lo
Array s.t.
Definition: SBDTree.hpp:64
std::vector< bool > * p_processed
Pointer to the `processed'-vector actually used.
Definition: Upscaler.hpp:84
void getSubTree(const unsigned long int s, std::vector< Triplet< T > > &local_nonzeroes, std::vector< Triplet< T > > &remote_nonzeroes, std::vector< unsigned long int > &upscaled_hierarchy, std::vector< unsigned long int > &upscaled_row_bounds, std::vector< unsigned long int > &upscaled_column_bounds, std::vector< unsigned long int > &rowLocalToGlobal, std::vector< unsigned long int > &columnLocalToGlobal, std::map< unsigned long int, unsigned long int > &rowGlobalToLocal, std::map< unsigned long int, unsigned long int > &colGlobalToLocal, const unsigned long int P, const unsigned long int Pref)
Reads out a subtree corresponding to only the nonzeroes owned by processor s, and returns the upscale...
Definition: Upscaler.hpp:568
void getSubTree(const unsigned long int ID, const unsigned long int s, std::vector< Triplet< T > > &local_nonzeroes, std::vector< Triplet< T > > &remote_nonzeroes, std::vector< unsigned long int > &upscaled_hierarchy, std::vector< unsigned long int > &upscaled_row_bounds, std::vector< unsigned long int > &upscaled_column_bounds, std::vector< unsigned long int > &rowLocalToGlobal, std::vector< unsigned long int > &columnLocalToGlobal, std::map< unsigned long int, unsigned long int > &rowGlobalToLocal, std::map< unsigned long int, unsigned long int > &colGlobalToLocal)
Reads out a subtree and returns the upscaled version.
Definition: Upscaler.hpp:344
Upscaler(const std::vector< Triplet< T > > &nonzeroes, const unsigned long int P, std::vector< unsigned long int > &r_hierarchy, std::vector< unsigned long int > &c_hierarchy, std::vector< unsigned long int > &r_bounds, std::vector< unsigned long int > &c_bounds, unsigned long int *row_perm=NULL, unsigned long int *col_perm=NULL, unsigned long int *proc2proc=NULL)
Base constructor.
Definition: Upscaler.hpp:471
unsigned long int * r_lo
Array s.t.
Definition: SBDTree.hpp:58
unsigned long int * c_hi
Array s.t.
Definition: SBDTree.hpp:67
unsigned long int * parent
Array s.t.
Definition: SBDTree.hpp:49
Transforms SBD-structures over q parts into an SBD structure over p parts, with q>p, and q,p both powers of two.
Definition: Upscaler.hpp:49
treeIterator(Upscaler< T > *_p, const unsigned long int initial, std::vector< bool > *_pp=NULL)
Base constructor.
Definition: Upscaler.hpp:97
void readout()
Reads out SBD data and prints to std::cout.
Definition: Upscaler.hpp:650
unsigned long int position()
Definition: Upscaler.hpp:113
virtual bool next()
Definition: Upscaler.hpp:116
virtual bool next()
Moves iterator to next position.
Definition: Upscaler.hpp:214
unsigned long int size()
Gets the number of nodes.
Definition: SBDTree.cpp:222
std::vector< bool > processed
Processed[ i ] is true when this iterator has visited its i-th child.
Definition: Upscaler.hpp:78
unsigned long int * r_hi
Array s.t.
Definition: SBDTree.hpp:61
~Upscaler()
Base deconstructor.
Definition: Upscaler.hpp:547
virtual bool next()
Moves iterator to its next position.
Definition: Upscaler.hpp:164
Same as treeIterator, but does post-order traversal instead of pre-order.
Definition: Upscaler.hpp:193
void determineMinMax(const unsigned long int ID, const unsigned long int s, unsigned long int &min_i, unsigned long int &max_i, unsigned long int &min_j, unsigned long int &max_j)
Determine min/max of nonzeroes owned by processor s, contained in the subtree with root ID...
Definition: Upscaler.hpp:288
Upscaler< T > * p
Class this iterator works on.
Definition: Upscaler.hpp:87
unsigned long int walk
Current position of the iterator.
Definition: Upscaler.hpp:69
void determineEmpty(const std::vector< Triplet< T > > &nonzeroes, const unsigned long int s, const unsigned long int min_i, const unsigned long int min_j, std::vector< bool > &emptyRows, std::vector< bool > &emptyCols, bool &empty)
Determines, given a collection of nonzeroes, which rows and columns nonzeroes owned by s reside on...
Definition: Upscaler.hpp:252
void addNonzeroes(std::vector< Triplet< T > > &into, const unsigned long int from, const unsigned long int s, const std::map< unsigned long int, unsigned long int > &rowGlobalToLocal, const std::map< unsigned long int, unsigned long int > &colGlobalToLocal)
adds nonzeroes from a given node into a given vector
Definition: Upscaler.hpp:308
static const unsigned long int NO_SUCH_NODE
Integer corresponding to non-existing nodes.
Definition: SBDTree.hpp:79
unsigned long int ID
Starting position of the iterator.
Definition: Upscaler.hpp:72
Models a Separated Block Diagonal tree structure.
Definition: SBDTree.hpp:44
A single triplet value.
Definition: Triplet.hpp:52
Pre-order tree iterator.
Definition: Upscaler.hpp:65
treePostOrderIterator(Upscaler< T > *_p, const unsigned long int initial, std::vector< bool > *_pp=NULL)
Base constructor.
Definition: Upscaler.hpp:203
Same as treeIterator, but does in-order traversal instead of pre-order.
Definition: Upscaler.hpp:143
std::vector< std::vector< bool > > containsPID
Keeps track which processes are represented in which blocks.
Definition: Upscaler.hpp:62