#pragma once
#include <vector>
#include "Common/Log.h"
template <class T, int MaxFastSize>
struct TinySet {
~TinySet() { delete slowLookup_; }
inline void insert(const T &t) {
for (int i = 0; i < fastCount_; i++) {
if (fastLookup_[i] == t)
return;
}
if (fastCount_ < MaxFastSize) {
fastLookup_[fastCount_++] = t;
return;
}
insertSlow(t);
}
inline void push_back(const T &t) {
if (fastCount_ < MaxFastSize) {
fastLookup_[fastCount_++] = t;
return;
}
if (!slowLookup_) {
slowLookup_ = new std::vector<T>();
}
slowLookup_->push_back(t);
}
inline T &push_uninitialized() {
if (fastCount_ < MaxFastSize) {
return fastLookup_[fastCount_++];
}
if (!slowLookup_) {
slowLookup_ = new std::vector<T>();
}
T t;
slowLookup_->push_back(t);
return *slowLookup_->back();
}
void reserve(size_t size) {
if (size < MaxFastSize) {
return;
}
if (slowLookup_) {
if (size < MaxFastSize + slowLookup_->capacity()) {
return;
}
slowLookup_->reserve(size - MaxFastSize);
} else {
slowLookup_ = new std::vector<T>();
slowLookup_->reserve(size - MaxFastSize);
}
}
void append(const TinySet<T, MaxFastSize> &other) {
size_t otherSize = other.size();
if (size() + otherSize <= MaxFastSize) {
for (size_t i = 0; i < otherSize; i++) {
fastLookup_[fastCount_ + i] = other.fastLookup_[i];
}
fastCount_ += other.fastCount_;
} else {
for (size_t i = 0; i < otherSize; i++) {
push_back(other[i]);
}
}
}
bool contains(T t) const {
for (int i = 0; i < fastCount_; i++) {
if (fastLookup_[i] == t)
return true;
}
if (slowLookup_) {
for (auto x : *slowLookup_) {
if (x == t)
return true;
}
}
return false;
}
bool contains(const TinySet<T, MaxFastSize> &otherSet) {
for (int i = 0; i < fastCount_; i++) {
if (otherSet.contains(fastLookup_[i]))
return true;
}
if (slowLookup_) {
for (auto x : *slowLookup_) {
if (otherSet.contains(x))
return true;
}
}
return false;
}
void clear() {
delete slowLookup_;
slowLookup_ = nullptr;
fastCount_ = 0;
}
bool empty() const {
return fastCount_ == 0;
}
size_t size() const {
if (!slowLookup_) {
return fastCount_;
} else {
return slowLookup_->size() + MaxFastSize;
}
}
T &operator[] (size_t index) {
if (index < MaxFastSize) {
return fastLookup_[index];
} else {
return (*slowLookup_)[index - MaxFastSize];
}
}
const T &operator[] (size_t index) const {
if (index < MaxFastSize) {
return fastLookup_[index];
} else {
return (*slowLookup_)[index - MaxFastSize];
}
}
const T &back() const {
return (*this)[size() - 1];
}
private:
void insertSlow(T t) {
if (!slowLookup_) {
slowLookup_ = new std::vector<T>();
} else {
for (size_t i = 0; i < slowLookup_->size(); i++) {
if ((*slowLookup_)[i] == t)
return;
}
}
slowLookup_->push_back(t);
}
int fastCount_ = 0;
T fastLookup_[MaxFastSize];
std::vector<T> *slowLookup_ = nullptr;
};
template <class T, int MaxSize>
struct FixedVec {
~FixedVec() {}
inline bool push_back(const T &t) {
if (count_ < MaxSize) {
data_[count_++] = t;
return true;
} else {
return false;
}
}
inline T &push_uninitialized() {
if (count_ < MaxSize) {
return &data_[count_++];
}
_dbg_assert_(false);
return *data_[MaxSize - 1];
}
void pop_back() { count_--; }
T *begin() { return data_; }
T *end() { return data_ + count_; }
const T *begin() const { return data_; }
const T *end() const { return data_ + count_; }
size_t capacity() const { return MaxSize; }
void clear() { count_ = 0; }
bool empty() const { return count_ == 0; }
size_t size() const { return count_; }
bool contains(T t) const {
for (int i = 0; i < count_; i++) {
if (data_[i] == t)
return true;
}
return false;
}
T &operator[] (const size_t index) { return data_[index]; }
const T &operator[] (const size_t index) const { return data_[index]; }
const T &back() const { return (*this)[size() - 1]; }
const T &front() const { return (*this)[0]; }
bool operator == (const FixedVec<T, MaxSize> &other) const {
if (count_ != other.count_)
return false;
for (int i = 0; i < count_; i++) {
if (!(data_[i] == other.data_[i])) {
return false;
}
}
return true;
}
private:
int count_ = 0;
T data_[MaxSize];
};