/* Copyright 2013 IST Austria
Contributed by: Jan Reininghaus
This file is part of PHAT.
PHAT is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
PHAT is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with PHAT. If not, see . */
#pragma once
#include
namespace phat {
class vector_heap {
protected:
std::vector< dimension > dims;
std::vector< column > matrix;
std::vector< index > inserts_since_last_prune;
mutable thread_local_storage< column > temp_column_buffer;
protected:
void _prune( index idx )
{
column& col = matrix[ idx ];
column& temp_col = temp_column_buffer();
temp_col.clear();
index max_index = _pop_max_index( col );
while( max_index != -1 ) {
temp_col.push_back( max_index );
max_index = _pop_max_index( col );
}
col = temp_col;
std::reverse( col.begin( ), col.end( ) );
std::make_heap( col.begin( ), col.end( ) );
inserts_since_last_prune[ idx ] = 0;
}
index _pop_max_index( index idx )
{
return _pop_max_index( matrix[ idx ] );
}
index _pop_max_index( column& col ) const
{
if( col.empty( ) )
return -1;
else {
index max_element = col.front( );
std::pop_heap( col.begin( ), col.end( ) );
col.pop_back( );
while( !col.empty( ) && col.front( ) == max_element ) {
std::pop_heap( col.begin( ), col.end( ) );
col.pop_back( );
if( col.empty( ) )
return -1;
else {
max_element = col.front( );
std::pop_heap( col.begin( ), col.end( ) );
col.pop_back( );
}
}
return max_element;
}
}
public:
// overall number of cells in boundary_matrix
index _get_num_cols( ) const
{
return (index)matrix.size( );
}
void _set_num_cols( index nr_of_columns )
{
dims.resize( nr_of_columns );
matrix.resize( nr_of_columns );
inserts_since_last_prune.assign( nr_of_columns, 0 );
}
// dimension of given index
dimension _get_dim( index idx ) const
{
return dims[ idx ];
}
void _set_dim( index idx, dimension dim )
{
dims[ idx ] = dim;
}
// replaces(!) content of 'col' with boundary of given index
void _get_col( index idx, column& col ) const
{
temp_column_buffer( ) = matrix[ idx ];
index max_index = _pop_max_index( temp_column_buffer() );
while( max_index != -1 ) {
col.push_back( max_index );
max_index = _pop_max_index( temp_column_buffer( ) );
}
std::reverse( col.begin( ), col.end( ) );
}
void _set_col( index idx, const column& col )
{
matrix[ idx ] = col;
std::make_heap( matrix[ idx ].begin( ), matrix[ idx ].end( ) );
}
// true iff boundary of given idx is empty
bool _is_empty( index idx ) const
{
return _get_max_index( idx ) == -1;
}
// largest row index of given column idx (new name for lowestOne())
index _get_max_index( index idx ) const
{
column& col = const_cast< column& >( matrix[ idx ] );
index max_element = _pop_max_index( col );
col.push_back( max_element );
std::push_heap( col.begin( ), col.end( ) );
return max_element;
}
// removes the maximal index of a column
void _remove_max( index idx )
{
_pop_max_index( idx );
}
// clears given column
void _clear( index idx )
{
matrix[ idx ].clear( );
}
// syncronizes all data structures (essential for openmp stuff)
void _sync( ) {}
// adds column 'source' to column 'target'
void _add_to( index source, index target )
{
for( index idx = 0; idx < (index)matrix[ source ].size( ); idx++ ) {
matrix[ target ].push_back( matrix[ source ][ idx ] );
std::push_heap( matrix[ target ].begin(), matrix[ target ].end() );
}
inserts_since_last_prune[ target ] += matrix[ source ].size();
if( 2 * inserts_since_last_prune[ target ] > ( index )matrix[ target ].size() )
_prune( target );
}
// finalizes given column
void _finalize( index idx ) {
_prune( idx );
}
};
}