20 #ifndef FST_PARTITION_H_ 21 #define FST_PARTITION_H_ 24 #include <type_traits> 69 static_assert(std::is_signed_v<T> && std::is_integral_v<T>,
70 "T must be a signed integer type");
82 elements_.resize(num_elements);
83 classes_.reserve(num_elements);
90 auto num_classes = classes_.size();
91 classes_.resize(num_classes + 1);
97 classes_.resize(classes_.size() + num_classes);
105 void Add(T element_id, T class_id) {
106 auto &this_element = elements_[element_id];
107 auto &this_class = classes_[class_id];
110 auto no_head = this_class.no_head;
111 if (no_head >= 0) elements_[no_head].prev_element = element_id;
112 this_class.no_head = element_id;
113 this_element.class_id = class_id;
115 this_element.yes = 0;
116 this_element.next_element = no_head;
117 this_element.prev_element = -1;
123 void Move(T element_id, T class_id) {
124 auto elements = &(elements_[0]);
125 auto &element = elements[element_id];
126 auto &old_class = classes_[element.class_id];
130 if (element.prev_element >= 0) {
131 elements[element.prev_element].next_element = element.next_element;
133 old_class.no_head = element.next_element;
135 if (element.next_element >= 0) {
136 elements[element.next_element].prev_element = element.prev_element;
139 Add(element_id, class_id);
145 auto elements = &(elements_[0]);
146 auto &element = elements[element_id];
147 if (element.yes == yes_counter_) {
150 auto class_id = element.class_id;
151 auto &this_class = classes_[class_id];
153 if (element.prev_element >= 0) {
154 elements[element.prev_element].next_element = element.next_element;
156 this_class.no_head = element.next_element;
158 if (element.next_element >= 0) {
159 elements[element.next_element].prev_element = element.prev_element;
162 if (this_class.yes_head >= 0) {
163 elements[this_class.yes_head].prev_element = element_id;
165 visited_classes_.push_back(class_id);
167 element.yes = yes_counter_;
168 element.next_element = this_class.yes_head;
169 element.prev_element = -1;
170 this_class.yes_head = element_id;
171 this_class.yes_size++;
182 template <
class Queue>
184 for (
const auto &visited_class : visited_classes_) {
185 const auto new_class = SplitRefine(visited_class);
186 if (new_class != -1 && queue) queue->Enqueue(new_class);
188 visited_classes_.clear();
193 const T
ClassId(T element_id)
const {
return elements_[element_id].class_id; }
195 const size_t ClassSize(T class_id)
const {
return classes_[class_id].size; }
219 Class() : size(0), yes_size(0), no_head(-1), yes_head(-1) {}
237 T SplitRefine(T class_id) {
238 auto yes_size = classes_[class_id].yes_size;
239 auto size = classes_[class_id].size;
240 auto no_size = size - yes_size;
244 classes_[class_id].no_head = classes_[class_id].yes_head;
245 classes_[class_id].yes_head = -1;
246 classes_[class_id].yes_size = 0;
249 auto new_class_id = classes_.size();
250 classes_.resize(classes_.size() + 1);
251 auto &old_class = classes_[class_id];
252 auto &new_class = classes_[new_class_id];
254 if (no_size < yes_size) {
256 new_class.no_head = old_class.no_head;
257 new_class.size = no_size;
259 old_class.no_head = old_class.yes_head;
260 old_class.yes_head = -1;
261 old_class.size = yes_size;
262 old_class.yes_size = 0;
265 new_class.size = yes_size;
266 new_class.no_head = old_class.yes_head;
268 old_class.size = no_size;
269 old_class.yes_size = 0;
270 old_class.yes_head = -1;
272 auto elements = &(elements_[0]);
274 for (
auto e = new_class.no_head; e >= 0; e = elements[e].next_element) {
275 elements[e].class_id = new_class_id;
282 std::vector<Element> elements_;
284 std::vector<Class> classes_;
286 std::vector<T> visited_classes_;
296 template <
typename T>
302 : partition_(partition),
303 element_id_(partition_.classes_[class_id].no_head),
304 class_id_(class_id) {}
306 bool Done() {
return element_id_ < 0; }
308 const T
Value() {
return element_id_; }
310 void Next() { element_id_ = partition_.elements_[element_id_].next_element; }
312 void Reset() { element_id_ = partition_.classes_[class_id_].no_head; }
323 #endif // FST_PARTITION_H_ const size_t ClassSize(T class_id) const
void SplitOn(T element_id)
void Move(T element_id, T class_id)
void AllocateClasses(T num_classes)
typename Partition< T >::Element Element
const T NumClasses() const
void Initialize(size_t num_elements)
Partition(T num_elements)
const T ClassId(T element_id) const
void Add(T element_id, T class_id)
PartitionIterator(const Partition< T > &partition, T class_id)
void FinalizeSplit(Queue *queue)