21 #ifndef FST_BI_TABLE_H_ 22 #define FST_BI_TABLE_H_ 28 #include <type_traits> 29 #include <unordered_set> 35 #include <unordered_map> 36 #include <unordered_set> 64 template <
class I,
class T,
class H,
class E = std::equal_to<T>>
72 entry2id_(table_size, hash_func_, hash_equal_) {
73 if (table_size) id2entry_.reserve(table_size);
77 : hash_func_(table.hash_func_),
78 hash_equal_(table.hash_equal_),
79 entry2id_(table.entry2id_.begin(), table.entry2id_.end(),
80 table.entry2id_.size(), hash_func_, hash_equal_),
81 id2entry_(table.id2entry_) {}
83 I
FindId(
const T &entry,
bool insert =
true) {
85 const auto it = entry2id_.find(entry);
86 return it == entry2id_.end() ? -1 : it->second - 1;
88 I &id_ref = entry2id_[entry];
90 id2entry_.push_back(entry);
91 id_ref = id2entry_.size();
96 const T &
FindEntry(I s)
const {
return id2entry_[s]; }
98 I
Size()
const {
return id2entry_.size(); }
109 std::unordered_map<T, I, H, E> entry2id_;
110 std::vector<T> id2entry_;
117 template <
class K,
class H,
class E, HSType HS>
118 struct HashSet :
public std::unordered_set<K, H, E, PoolAllocator<K>> {
120 using Base = std::unordered_set<K, H, E, PoolAllocator<K>>;
132 template <
class I,
class T,
class H,
class E = std::equal_to<T>,
135 static_assert(HS ==
HS_STL || HS == HS_FLAT,
"Unsupported hash set type");
138 friend class HashFunc;
139 friend class HashEqual;
146 compact_hash_func_(*this),
147 compact_hash_equal_(*this),
148 keys_(table_size, compact_hash_func_, compact_hash_equal_) {
149 if (table_size) id2entry_.reserve(table_size);
153 : hash_func_(table.hash_func_),
154 hash_equal_(table.hash_equal_),
155 compact_hash_func_(*this),
156 compact_hash_equal_(*this),
157 id2entry_(table.id2entry_),
158 keys_(table.keys_.begin(), table.keys_.end(), table.keys_.size(),
159 compact_hash_func_, compact_hash_equal_) {}
161 I
FindId(
const T &entry,
bool insert =
true) {
162 current_entry_ = &entry;
164 auto [iter, was_inserted] = keys_.insert(kCurrentKey);
165 if (!was_inserted)
return *iter;
168 I key = id2entry_.size();
169 const_cast<I &
>(*iter) = key;
170 id2entry_.push_back(entry);
173 const auto it = keys_.find(kCurrentKey);
174 return it == keys_.end() ? -1 : *it;
179 I
Size()
const {
return id2entry_.size(); }
183 if (n < 0 || n >= id2entry_.size()) {
186 }
else if (n == id2entry_.size() - 1) {
193 I key = id2entry_.size() - 1;
195 id2entry_.pop_back();
202 static_assert(std::is_signed_v<I>,
"I must be a signed type");
206 static constexpr I kCurrentKey = -1;
212 size_t operator()(I k)
const {
213 if (k >= kCurrentKey) {
214 return (ht_->hash_func_)(ht_->Key2Entry(k));
228 bool operator()(I k1, I k2)
const {
231 }
else if (k1 >= kCurrentKey && k2 >= kCurrentKey) {
232 return (ht_->hash_equal_)(ht_->Key2Entry(k1), ht_->Key2Entry(k2));
244 const T &Key2Entry(I k)
const {
245 if (k == kCurrentKey) {
246 return *current_entry_;
254 HashFunc compact_hash_func_;
255 HashEqual compact_hash_equal_;
256 std::vector<T> id2entry_;
258 const T *current_entry_;
265 template <
class I,
class T,
class FP>
269 explicit VectorBiTable(
const FP &fp = FP(),
size_t table_size = 0) : fp_(fp) {
270 if (table_size) id2entry_.reserve(table_size);
274 : fp_(table.fp_), fp2id_(table.fp2id_), id2entry_(table.id2entry_) {}
276 I
FindId(
const T &entry,
bool insert =
true) {
277 ssize_t fp = (fp_)(entry);
278 if (fp >= fp2id_.size()) fp2id_.resize(fp + 1);
279 I &id_ref = fp2id_[fp];
282 id2entry_.push_back(entry);
283 id_ref = id2entry_.size();
293 I
Size()
const {
return id2entry_.size(); }
299 std::vector<I> fp2id_;
300 std::vector<T> id2entry_;
308 template <
class I,
class T,
class S,
class FP,
class H, HSType HS = HS_FLAT>
311 friend class HashFunc;
312 friend class HashEqual;
315 const H &h = H(),
size_t vector_size = 0,
316 size_t entry_size = 0)
322 keys_(0, hash_func_, hash_equal_) {
323 if (vector_size) fp2id_.reserve(vector_size);
324 if (entry_size) id2entry_.reserve(entry_size);
328 : selector_(table.s_),
331 id2entry_(table.id2entry_),
332 fp2id_(table.fp2id_),
335 keys_(table.keys_.size(), hash_func_, hash_equal_) {
336 keys_.insert(table.keys_.begin(), table.keys_.end());
339 I
FindId(
const T &entry,
bool insert =
true) {
340 if ((selector_)(entry)) {
341 uint64_t fp = (fp_)(entry);
342 if (fp2id_.size() <= fp) fp2id_.resize(fp + 1, 0);
343 if (fp2id_[fp] == 0) {
345 id2entry_.push_back(entry);
346 fp2id_[fp] = id2entry_.size();
351 return fp2id_[fp] - 1;
353 current_entry_ = &entry;
354 const auto it = keys_.find(kCurrentKey);
355 if (it == keys_.end()) {
357 I key = id2entry_.size();
358 id2entry_.push_back(entry);
372 I
Size()
const {
return id2entry_.size(); }
378 const H &
Hash()
const {
return h_; }
381 static constexpr I kCurrentKey = -1;
387 size_t operator()(I k)
const {
388 if (k >= kCurrentKey) {
389 return (ht_->h_)(ht_->Key2Entry(k));
403 bool operator()(I k1, I k2)
const {
404 if (k1 >= kCurrentKey && k2 >= kCurrentKey) {
405 return ht_->Key2Entry(k1) == ht_->Key2Entry(k2);
417 const T &Key2Entry(I k)
const {
418 if (k == kCurrentKey) {
419 return *current_entry_;
429 std::vector<T> id2entry_;
430 std::vector<I> fp2id_;
435 HashEqual hash_equal_;
437 const T *current_entry_;
444 template <
class I,
class T,
class F>
449 I
FindId(
const T &entry,
bool insert =
true) {
450 I &id_ref = entry2id_[entry];
453 id2entry_.push_back(entry);
454 id_ref = id2entry_.size() + first_;
462 const T &
FindEntry(I s)
const {
return id2entry_[s - first_]; }
464 I
Size()
const {
return id2entry_.size(); }
467 auto &ref = id2entry_[s - first_];
468 entry2id_.erase(ref);
470 while (!id2entry_.empty() && id2entry_.front() == empty_entry_) {
471 id2entry_.pop_front();
477 std::unordered_map<T, I, F> entry2id_;
478 std::deque<T> id2entry_;
479 const T empty_entry_;
485 #endif // FST_BI_TABLE_H_
VectorHashBiTable(const VectorHashBiTable< I, T, S, FP, H, HS > &table)
I FindId(const T &entry, bool insert=true)
const T & FindEntry(I s) const
const T & FindEntry(I s) const
const S & Selector() const
I FindId(const T &entry, bool insert=true)
VectorBiTable(const FP &fp=FP(), size_t table_size=0)
const FP & Fingerprint() const
const T & FindEntry(I s) const
VectorHashBiTable(const S &s=S(), const FP &fp=FP(), const H &h=H(), size_t vector_size=0, size_t entry_size=0)
HashBiTable(const HashBiTable< I, T, H, E > &table)
const T & FindEntry(I s) const
const FP & Fingerprint() const
HashBiTable(size_t table_size=0, const H &h=H(), const E &e=E())
I FindId(const T &entry, bool insert=true)
VectorBiTable(const VectorBiTable< I, T, FP > &table)
I FindId(const T &entry, bool insert=true)
const T & FindEntry(I s) const
CompactHashBiTable(size_t table_size=0, const H &h=H(), const E &e=E())
CompactHashBiTable(const CompactHashBiTable &table)
I FindId(const T &entry, bool insert=true)