#pragma once
namespace bliss {
class Partition;
}
#include <vector>
#include <climits>
#include "bliss/kqueue.hh"
#include "bliss/abstractgraph.hh"
namespace bliss {
class Partition
{
public:
class Cell
{
friend class Partition;
public:
unsigned int length;
unsigned int first;
unsigned int max_ival;
unsigned int max_ival_count;
private:
bool in_splitting_queue;
public:
bool in_neighbour_heap;
Cell* next;
Cell* prev;
Cell* next_nonsingleton;
Cell* prev_nonsingleton;
unsigned int split_level;
bool is_unit() const {return(length == 1); }
bool is_in_splitting_queue() const {return(in_splitting_queue); }
};
private:
class RefInfo {
public:
unsigned int split_cell_first;
int prev_nonsingleton_first;
int next_nonsingleton_first;
};
std::vector<RefInfo> refinement_stack;
class BacktrackInfo {
public:
unsigned int refinement_stack_size;
unsigned int cr_backtrack_point;
};
std::vector<BacktrackInfo> bt_stack;
public:
AbstractGraph* graph;
KQueue<Cell*> splitting_queue;
void splitting_queue_add(Cell* const cell);
Cell* splitting_queue_pop();
bool splitting_queue_is_empty() const;
void splitting_queue_clear();
typedef unsigned int BacktrackPoint;
BacktrackPoint set_backtrack_point();
void goto_backtrack_point(BacktrackPoint p);
Cell* individualize(Cell* const cell,
const unsigned int element);
Cell* aux_split_in_two(Cell* const cell,
const unsigned int first_half_size);
private:
unsigned int N;
Cell* cells;
Cell* free_cells;
unsigned int discrete_cell_count;
public:
Cell* first_cell;
Cell* first_nonsingleton_cell;
unsigned int *elements;
unsigned int *invariant_values;
Cell **element_to_cell_map;
Cell* get_cell(const unsigned int e) const {
assert(e < N);
return element_to_cell_map[e];
}
unsigned int **in_pos;
Partition();
~Partition();
void init(const unsigned int N);
bool is_discrete() const {return(free_cells == 0); }
unsigned int nof_discrete_cells() const {return(discrete_cell_count); }
size_t print(FILE* const fp, const bool add_newline = true) const;
size_t print_signature(FILE* const fp, const bool add_newline = true) const;
Cell *zplit_cell(Cell * const cell, const bool max_ival_info_ok);
void cr_init();
void cr_free();
unsigned int cr_get_level(const unsigned int cell_index) const;
unsigned int cr_split_level(const unsigned int level,
const std::vector<unsigned int>& cells);
void clear_ivs(Cell* const cell);
private:
bool cr_enabled;
class CRCell {
public:
unsigned int level;
CRCell* next;
CRCell** prev_next_ptr;
void detach() {
if(next)
next->prev_next_ptr = prev_next_ptr;
*(prev_next_ptr) = next;
level = UINT_MAX;
next = nullptr;
prev_next_ptr = nullptr;
}
};
CRCell* cr_cells;
CRCell** cr_levels;
class CR_BTInfo {
public:
unsigned int created_trail_index;
unsigned int splitted_level_trail_index;
};
std::vector<unsigned int> cr_created_trail;
std::vector<unsigned int> cr_splitted_level_trail;
std::vector<CR_BTInfo> cr_bt_info;
unsigned int cr_max_level;
void cr_create_at_level(const unsigned int cell_index, unsigned int level);
void cr_create_at_level_trailed(const unsigned int cell_index, unsigned int level);
unsigned int cr_get_backtrack_point();
void cr_goto_backtrack_point(const unsigned int btpoint);
Cell* sort_and_split_cell1(Cell* cell);
Cell* sort_and_split_cell255(Cell* const cell, const unsigned int max_ival);
bool shellsort_cell(Cell* cell);
Cell* split_cell(Cell* const cell);
unsigned int dcs_count[256];
unsigned int dcs_start[256];
void dcs_cumulate_count(const unsigned int max);
};
inline Partition::Cell*
Partition::splitting_queue_pop()
{
assert(!splitting_queue.is_empty());
Cell* const cell = splitting_queue.pop_front();
assert(cell->in_splitting_queue);
cell->in_splitting_queue = false;
return cell;
}
inline bool
Partition::splitting_queue_is_empty() const
{
return splitting_queue.is_empty();
}
inline unsigned int
Partition::cr_get_level(const unsigned int cell_index) const
{
assert(cr_enabled);
assert(cell_index < N);
assert(cr_cells[cell_index].level != UINT_MAX);
return(cr_cells[cell_index].level);
}
}