Aleph-w 3.0
A C++ Library for Data Structures and Algorithms
Loading...
Searching...
No Matches
patricia_trie_test.cc
Go to the documentation of this file.
1/*
2 Aleph_w
3
4 Data structures & Algorithms
5 https://github.com/lrleon/Aleph-w
6
7 This file is part of Aleph-w library
8
9 Copyright (c) 2002-2026 Leandro Rabindranath Leon
10
11 Permission is hereby granted, free of charge, to any person obtaining a copy
12 of this software and associated documentation files (the "Software"), to deal
13 in the Software without restriction, including without limitation the rights
14 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
15 copies of the Software, and to permit persons to whom the Software is
16 furnished to do so, subject to the following conditions:
17
18 The above copyright notice and this permission notice shall be included in all
19 copies or substantial portions of the Software.
20
21 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
22 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
24 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
26 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
27 SOFTWARE.
28*/
29
34#include <prefix-tree.H>
35#include <tpl_patricia_trie.H>
36#include <tpl_radix_tree.H>
37
38#include <gtest/gtest.h>
39
40#include <algorithm>
41#include <cstdint>
42#include <limits>
43#include <map>
44#include <memory>
45#include <random>
46#include <set>
47#include <string>
48#include <type_traits>
49#include <vector>
50
51using namespace Aleph;
52
53namespace
54{
55template <typename T>
56std::vector<T> to_sorted_vector(const Array<T> & a)
57{
58 std::vector<T> out;
59 out.reserve(a.size());
60 for (const auto & item : a)
61 out.push_back(item);
62 std::sort(out.begin(), out.end());
63 return out;
64}
65
66template <typename T>
67std::vector<T> to_vector(const std::set<T> & s)
68{
69 return std::vector<T>(s.begin(), s.end());
70}
71
72template <typename K, typename V>
73std::vector<K> keys_of(const std::map<K, V> & m)
74{
75 std::vector<K> out;
76 out.reserve(m.size());
77 for (const auto & kv : m)
78 out.push_back(kv.first);
79 return out;
80}
81
82std::vector<std::string> to_vector(const DynArray<std::string> & a)
83{
84 std::vector<std::string> out;
85 a.for_each([&out] (const std::string & s) { out.push_back(s); });
86 return out;
87}
88
89std::vector<std::string> sorted(std::vector<std::string> v)
90{
91 std::sort(v.begin(), v.end());
92 return v;
93}
94
95std::string encode_bits(const std::uint16_t key)
96{
97 std::string out;
99 for (size_t bit = 0; bit < PatriciaSet<std::uint16_t>::bit_width; ++bit)
100 {
101 const auto shift = PatriciaSet<std::uint16_t>::bit_width - 1 - bit;
102 out.push_back(((key >> shift) & std::uint16_t{1}) ? '1' : '0');
103 }
104 return out;
105}
106
107std::vector<std::string> encoded_words(const std::set<std::uint16_t> & keys)
108{
109 std::vector<std::string> out;
110 out.reserve(keys.size());
111 for (const auto key : keys)
112 out.push_back(encode_bits(key));
113 std::sort(out.begin(), out.end());
114 return out;
115}
116
117std::vector<std::string> encoded_words(const std::vector<std::uint16_t> & keys)
118{
119 std::vector<std::string> out;
120 out.reserve(keys.size());
121 for (const auto key : keys)
122 out.push_back(encode_bits(key));
123 std::sort(out.begin(), out.end());
124 return out;
125}
126
127std::vector<std::string> encoded_words_with_prefix(const std::set<std::uint16_t> & keys,
128 const std::string & prefix)
129{
130 std::vector<std::string> out;
131 for (const auto key : keys)
132 {
133 const std::string encoded = encode_bits(key);
134 if (encoded.starts_with(prefix))
135 out.push_back(encoded);
136 }
137 std::sort(out.begin(), out.end());
138 return out;
139}
140} // namespace
141
142static_assert(std::is_move_constructible_v<PatriciaSet<unsigned>>);
143static_assert(std::is_copy_constructible_v<PatriciaSet<unsigned>>);
144static_assert(std::is_move_constructible_v<PatriciaMap<unsigned, int>>);
145static_assert(std::is_copy_constructible_v<PatriciaMap<unsigned, int>>);
146static_assert(std::is_move_constructible_v<
148static_assert(not std::is_copy_constructible_v<
150
160
171
181
183{
185 const unsigned max = std::numeric_limits<unsigned>::max();
186 const unsigned high = 1U << (PatriciaSet<unsigned>::bit_width - 1);
187
188 EXPECT_TRUE(s.insert(0));
190 EXPECT_TRUE(s.insert(high));
191
192 EXPECT_TRUE(s.contains(0));
194 EXPECT_TRUE(s.contains(high));
195 EXPECT_FALSE(s.contains(high - 1));
196 EXPECT_EQ(s.size(), 3U);
198}
199
201{
203 for (unsigned key : {9U, 1U, 17U, 3U, 0U})
204 ASSERT_TRUE(s.insert(key));
205
206 EXPECT_EQ(to_sorted_vector(s.keys()), (std::vector<unsigned>{0, 1, 3, 9, 17}));
208}
209
219
229
231{
233 ASSERT_TRUE(s.insert(0b1000));
234 ASSERT_TRUE(s.insert(0b1001));
235 ASSERT_TRUE(s.insert(0b1100));
236 ASSERT_TRUE(s.insert(0b1101));
237
238 EXPECT_TRUE(s.erase(0b1001));
239 EXPECT_FALSE(s.contains(0b1001));
240 EXPECT_TRUE(s.contains(0b1000));
241 EXPECT_TRUE(s.contains(0b1100));
242 EXPECT_TRUE(s.contains(0b1101));
243 EXPECT_EQ(s.size(), 3U);
245}
246
260
277
291
312
314{
316 ASSERT_TRUE(a.insert(5));
317 ASSERT_TRUE(a.insert(6));
318
320 ASSERT_TRUE(b.insert(99));
321
322 b = std::move(a);
323 EXPECT_TRUE(a.is_empty()); // NOLINT(bugprone-use-after-move): documented
325 EXPECT_FALSE(b.contains(99));
326 EXPECT_TRUE(b.contains(5));
327 EXPECT_TRUE(b.contains(6));
329}
330
332{
334 ASSERT_TRUE(s.insert(5));
335 ASSERT_TRUE(s.insert(6));
336
338 s = alias;
339 EXPECT_TRUE(s.contains(5));
340 EXPECT_TRUE(s.contains(6));
341 EXPECT_EQ(s.size(), 2U);
343
344 s = std::move(alias); // NOLINT(bugprone-use-after-move): deliberate self-move
345 EXPECT_TRUE(s.contains(5));
346 EXPECT_TRUE(s.contains(6));
347 EXPECT_EQ(s.size(), 2U);
349}
350
352{
354 std::set<std::uint32_t> reference;
355 std::mt19937 rng(0x5eed1234U);
356 std::uniform_int_distribution<std::uint32_t> key_dist(0, 4095);
357 std::uniform_int_distribution<int> op_dist(0, 2);
358
359 for (int step = 0; step < 20000; ++step)
360 {
361 const std::uint32_t key = key_dist(rng);
362 const int op = op_dist(rng);
363 if (op == 0)
364 EXPECT_EQ(subject.insert(key), reference.insert(key).second);
365 else if (op == 1)
366 EXPECT_EQ(subject.erase(key), reference.erase(key) != 0);
367 else
368 EXPECT_EQ(subject.contains(key), reference.contains(key));
369
370 ASSERT_EQ(subject.size(), reference.size()) << "step " << step;
371 ASSERT_TRUE(subject.check_invariants()) << "step " << step;
372 }
373
374 EXPECT_EQ(to_sorted_vector(subject.keys()), to_vector(reference));
375}
376
378{
382 std::set<std::uint16_t> reference;
383
384 std::mt19937 rng(0xC017B175U);
385 std::uniform_int_distribution<unsigned> key_dist(
386 0, std::numeric_limits<std::uint16_t>::max());
387
388 for (int iter = 0; iter < 5000; ++iter)
389 {
390 const auto key = static_cast<std::uint16_t>(key_dist(rng));
391 const std::string encoded = encode_bits(key);
392 const bool expected_inserted = reference.insert(key).second;
393
395 << "Patricia disagreement inserting " << key;
397 << "RadixTree disagreement inserting " << encoded;
399 << "Prefix_Tree disagreement inserting " << encoded;
400
401 ASSERT_EQ(patricia.size(), reference.size());
402 ASSERT_EQ(radix.size(), reference.size());
403 ASSERT_EQ(prefix_tree.count(), reference.size());
404 ASSERT_TRUE(patricia.check_invariants()) << "Patricia invariant at " << iter;
405 ASSERT_TRUE(radix.verify()) << "RadixTree invariant at " << iter;
406 }
407
408 for (int iter = 0; iter < 1000; ++iter)
409 {
410 const auto key = static_cast<std::uint16_t>(key_dist(rng));
411 const std::string encoded = encode_bits(key);
412 const bool expected = reference.contains(key);
413 ASSERT_EQ(patricia.contains(key), expected)
414 << "Patricia contains disagreement for " << key;
415 ASSERT_EQ(radix.contains(encoded), expected)
416 << "RadixTree contains disagreement for " << encoded;
418 << "Prefix_Tree contains disagreement for " << encoded;
419 }
420
421 const auto expected_all = encoded_words(reference);
422 EXPECT_EQ(to_sorted_vector(radix.keys_with_prefix("")), expected_all);
424
425 std::vector<std::uint16_t> patricia_keys = to_sorted_vector(patricia.keys());
426 EXPECT_EQ(patricia_keys, to_vector(reference));
427
428 std::uniform_int_distribution<size_t> prefix_len_dist(
430 for (int iter = 0; iter < 500; ++iter)
431 {
432 const auto key = static_cast<std::uint16_t>(key_dist(rng));
433 const std::string probe = encode_bits(key);
434 const std::string prefix = probe.substr(0, prefix_len_dist(rng));
435 const auto expected = encoded_words_with_prefix(reference, prefix);
436
437 EXPECT_EQ(to_sorted_vector(radix.keys_with_prefix(prefix)), expected)
438 << "RadixTree prefix disagreement for " << prefix;
439 EXPECT_EQ(sorted(to_vector(prefix_tree.words_with_prefix(prefix))), expected)
440 << "Prefix_Tree prefix disagreement for " << prefix;
441
442 std::set<std::uint16_t> patricia_reference;
443 for (const auto stored : patricia.keys())
444 if (encode_bits(stored).starts_with(prefix))
447 << "Patricia scan prefix disagreement for " << prefix;
448 }
449}
450
452{
455 EXPECT_EQ(m.size(), 0U);
457 EXPECT_EQ(m.find(0), nullptr);
458 EXPECT_TRUE(m.keys().is_empty());
459 EXPECT_TRUE(m.check_invariants());
460}
461
463{
465 EXPECT_TRUE(m.insert(42, 100));
467 ASSERT_NE(m.find(42), nullptr);
468 EXPECT_EQ(*m.find(42), 100);
471 EXPECT_TRUE(m.check_invariants());
472}
473
475{
477 ASSERT_TRUE(m.insert(7, 1));
478 EXPECT_FALSE(m.insert(7, 2));
479 ASSERT_NE(m.find(7), nullptr);
480 EXPECT_EQ(*m.find(7), 1);
481 EXPECT_EQ(m.size(), 1U);
482 EXPECT_TRUE(m.check_invariants());
483}
484
486{
488 ASSERT_TRUE(m.insert(7, std::make_unique<int>(1)));
489
490 auto duplicate = std::make_unique<int>(2);
491 EXPECT_FALSE(m.insert(7, std::move(duplicate)));
492 ASSERT_NE(duplicate, nullptr);
493 EXPECT_EQ(*duplicate, 2);
494 ASSERT_NE(m.find(7), nullptr);
495 ASSERT_NE(*m.find(7), nullptr);
496 EXPECT_EQ(**m.find(7), 1);
497 EXPECT_TRUE(m.check_invariants());
498}
499
501{
503 m.insert_or_assign(10, "ten");
504 ASSERT_NE(m.find(10), nullptr);
505 EXPECT_EQ(*m.find(10), "ten");
506
507 m.insert_or_assign(10, "diez");
508 ASSERT_NE(m.find(10), nullptr);
509 EXPECT_EQ(*m.find(10), "diez");
510
511 m.insert_or_assign(11, "once");
512 ASSERT_NE(m.find(11), nullptr);
513 EXPECT_EQ(*m.find(11), "once");
514 EXPECT_EQ(m.size(), 2U);
515 EXPECT_TRUE(m.check_invariants());
516}
517
519{
521 ASSERT_TRUE(m.insert(1, 10));
522 int * slot = m.find(1);
523 ASSERT_NE(slot, nullptr);
524 *slot = 20;
525
526 const auto & cm = m;
527 ASSERT_NE(cm.find(1), nullptr);
528 EXPECT_EQ(*cm.find(1), 20);
529 EXPECT_TRUE(m.check_invariants());
530}
531
533{
535 ASSERT_TRUE(m.insert(0b1000, 8));
536 ASSERT_TRUE(m.insert(0b1001, 9));
537 ASSERT_TRUE(m.insert(0b1100, 12));
538 ASSERT_TRUE(m.insert(0b1101, 13));
539
540 EXPECT_TRUE(m.erase(0b1001));
541 EXPECT_FALSE(m.contains(0b1001));
542 ASSERT_NE(m.find(0b1000), nullptr);
543 ASSERT_NE(m.find(0b1100), nullptr);
544 ASSERT_NE(m.find(0b1101), nullptr);
545 EXPECT_EQ(*m.find(0b1000), 8);
546 EXPECT_EQ(*m.find(0b1100), 12);
547 EXPECT_EQ(*m.find(0b1101), 13);
548 EXPECT_EQ(m.size(), 3U);
549 EXPECT_TRUE(m.check_invariants());
550}
551
553{
555 ASSERT_TRUE(m.insert(1, 10));
556 ASSERT_TRUE(m.insert(2, 20));
557 m.clear();
558
562 EXPECT_TRUE(m.keys().is_empty());
563 EXPECT_TRUE(m.check_invariants());
564}
565
567{
569 ASSERT_TRUE(a.insert(1, "one"));
570 ASSERT_TRUE(a.insert(8, "eight"));
571
573 ASSERT_NE(b.find(1), nullptr);
574 ASSERT_NE(b.find(8), nullptr);
575 EXPECT_EQ(*b.find(1), "one");
576 EXPECT_EQ(*b.find(8), "eight");
577
578 b.insert_or_assign(1, "uno");
579 EXPECT_EQ(*a.find(1), "one");
580 EXPECT_EQ(*b.find(1), "uno");
583}
584
586{
588 ASSERT_TRUE(a.insert(5, 50));
589 ASSERT_TRUE(a.insert(6, 60));
590
591 PatriciaMap<unsigned, int> b(std::move(a));
594 ASSERT_NE(b.find(5), nullptr);
595 ASSERT_NE(b.find(6), nullptr);
596 EXPECT_EQ(*b.find(5), 50);
597 EXPECT_EQ(*b.find(6), 60);
599}
600
602{
604 ASSERT_TRUE(a.insert(1, "one"));
605 ASSERT_TRUE(a.insert(8, "eight"));
606
608 ASSERT_TRUE(b.insert(99, "old"));
609
610 b = a;
611 ASSERT_NE(b.find(1), nullptr);
612 ASSERT_NE(b.find(8), nullptr);
613 EXPECT_EQ(*b.find(1), "one");
614 EXPECT_EQ(*b.find(8), "eight");
615 EXPECT_FALSE(b.contains(99));
616
617 b.insert_or_assign(1, "uno");
618 EXPECT_EQ(*a.find(1), "one");
619 EXPECT_EQ(*b.find(1), "uno");
622}
623
625{
627 ASSERT_TRUE(a.insert(5, 50));
628 ASSERT_TRUE(a.insert(6, 60));
629
631 ASSERT_TRUE(b.insert(99, 990));
632
633 b = std::move(a);
634 EXPECT_TRUE(a.is_empty()); // NOLINT(bugprone-use-after-move): documented
636 EXPECT_FALSE(b.contains(99));
637 ASSERT_NE(b.find(5), nullptr);
638 ASSERT_NE(b.find(6), nullptr);
639 EXPECT_EQ(*b.find(5), 50);
640 EXPECT_EQ(*b.find(6), 60);
642}
643
645{
647 ASSERT_TRUE(m.insert(5, "five"));
648 ASSERT_TRUE(m.insert(6, "six"));
649
651 m = alias;
652 ASSERT_NE(m.find(5), nullptr);
653 ASSERT_NE(m.find(6), nullptr);
654 EXPECT_EQ(*m.find(5), "five");
655 EXPECT_EQ(*m.find(6), "six");
656 EXPECT_EQ(m.size(), 2U);
657 EXPECT_TRUE(m.check_invariants());
658
659 m = std::move(alias); // NOLINT(bugprone-use-after-move): deliberate self-move
660 ASSERT_NE(m.find(5), nullptr);
661 ASSERT_NE(m.find(6), nullptr);
662 EXPECT_EQ(*m.find(5), "five");
663 EXPECT_EQ(*m.find(6), "six");
664 EXPECT_EQ(m.size(), 2U);
665 EXPECT_TRUE(m.check_invariants());
666}
667
669{
671 std::map<std::uint32_t, int> reference;
672 std::mt19937 rng(0x0BADC0DEU);
673 std::uniform_int_distribution<std::uint32_t> key_dist(0, 4095);
674 std::uniform_int_distribution<int> value_dist(-10000, 10000);
675 std::uniform_int_distribution<int> op_dist(0, 3);
676
677 for (int step = 0; step < 10000; ++step)
678 {
679 const std::uint32_t key = key_dist(rng);
680 const int value = value_dist(rng);
681 const int op = op_dist(rng);
682
683 if (op == 0)
684 EXPECT_EQ(subject.insert(key, value),
685 reference.emplace(key, value).second);
686 else if (op == 1)
687 {
688 subject.insert_or_assign(key, value);
689 reference[key] = value;
690 }
691 else if (op == 2)
692 EXPECT_EQ(subject.erase(key), reference.erase(key) != 0);
693 else
694 {
695 const int * subject_value = subject.find(key);
696 const auto reference_it = reference.find(key);
697 ASSERT_EQ(subject_value != nullptr, reference_it != reference.end())
698 << "find presence disagreement at step " << step;
699 if (subject_value != nullptr)
701 << "find value disagreement at step " << step;
702 }
703
704 ASSERT_EQ(subject.size(), reference.size()) << "step " << step;
705 ASSERT_TRUE(subject.check_invariants()) << "step " << step;
706 }
707
708 EXPECT_EQ(to_sorted_vector(subject.keys()), keys_of(reference));
709 for (const auto & kv : reference)
710 {
711 ASSERT_NE(subject.find(kv.first), nullptr);
712 EXPECT_EQ(*subject.find(kv.first), kv.second);
713 }
714}
715
717{
721 std::map<std::uint16_t, int> reference;
722
723 std::mt19937 rng(0xFACEB00CU);
724 std::uniform_int_distribution<unsigned> key_dist(
725 0, std::numeric_limits<std::uint16_t>::max());
726 std::uniform_int_distribution<int> value_dist(-5000, 5000);
727
728 for (int iter = 0; iter < 3000; ++iter)
729 {
730 const auto key = static_cast<std::uint16_t>(key_dist(rng));
731 const std::string encoded = encode_bits(key);
732 const int value = value_dist(rng);
733
734 if ((iter % 3) == 0)
735 {
736 const bool expected_inserted = reference.emplace(key, value).second;
738 << "PatriciaMap disagreement inserting " << key;
740 << "RadixTree disagreement inserting " << encoded;
742 << "Prefix_Tree disagreement inserting " << encoded;
743 }
744 else
745 {
746 const bool was_absent = not reference.contains(key);
747 reference[key] = value;
748 patricia.insert_or_assign(key, value);
749 radix.insert_or_assign(encoded, value);
750 if (was_absent)
751 ASSERT_TRUE(prefix_tree.insert_word(encoded))
752 << "Prefix_Tree missed new key " << encoded;
753 else
755 << "Prefix_Tree lost existing key " << encoded;
756 }
757
758 ASSERT_EQ(patricia.size(), reference.size());
759 ASSERT_EQ(radix.size(), reference.size());
760 ASSERT_EQ(prefix_tree.count(), reference.size());
761 ASSERT_TRUE(patricia.check_invariants()) << "PatriciaMap invariant at "
762 << iter;
763 ASSERT_TRUE(radix.verify()) << "RadixTree invariant at " << iter;
764 }
765
766 for (const auto & kv : reference)
767 {
768 const std::string encoded = encode_bits(kv.first);
769 ASSERT_NE(patricia.find(kv.first), nullptr);
770 ASSERT_NE(radix.find(encoded), nullptr);
772 EXPECT_EQ(*patricia.find(kv.first), kv.second);
773 EXPECT_EQ(*radix.find(encoded), kv.second);
774 }
775
776 const auto expected_all = encoded_words(keys_of(reference));
777 EXPECT_EQ(to_sorted_vector(radix.keys_with_prefix("")), expected_all);
779 EXPECT_EQ(to_sorted_vector(patricia.keys()), keys_of(reference));
780
781 std::uniform_int_distribution<size_t> prefix_len_dist(
783 for (int iter = 0; iter < 300; ++iter)
784 {
785 const auto key = static_cast<std::uint16_t>(key_dist(rng));
786 const std::string probe = encode_bits(key);
787 const std::string prefix = probe.substr(0, prefix_len_dist(rng));
788 std::set<std::uint16_t> reference_keys;
789 for (const auto & kv : reference)
790 if (encode_bits(kv.first).starts_with(prefix))
791 reference_keys.insert(kv.first);
793
794 EXPECT_EQ(to_sorted_vector(radix.keys_with_prefix(prefix)), expected)
795 << "RadixTree prefix disagreement for " << prefix;
796 EXPECT_EQ(sorted(to_vector(prefix_tree.words_with_prefix(prefix))), expected)
797 << "Prefix_Tree prefix disagreement for " << prefix;
798 }
799}
size_t size_t int32_t value
Definition ca-c-api.h:116
size_t size_t int32_t * out
Definition ca-c-api.h:120
Simple dynamic array with automatic resizing and functional operations.
Definition tpl_array.H:138
constexpr size_t size() const noexcept
Return the number of elements stored in the stack.
Definition tpl_array.H:365
constexpr bool is_empty() const noexcept
Checks if the container is empty.
Definition tpl_array.H:359
constexpr bool contains(const Key &key) const noexcept
Alias for has().
Definition hashDry.H:425
Compressed bitwise map for unsigned integral keys.
bool check_invariants() const noexcept
Verify structural invariants recursively.
bool insert(const Key key, const Value &value)
Insert key with a copy of value, only if key is absent.
void insert_or_assign(const Key key, Value value)
Insert key or overwrite the mapped value if key exists.
const Value * find(const Key key) const noexcept
Look up key.
bool contains(const Key key) const noexcept
Check whether key is stored.
bool is_empty() const noexcept
Check whether the map has no key-value pairs.
Compressed bitwise set for unsigned integral keys.
bool check_invariants() const noexcept
Verify structural invariants recursively.
size_t size() const noexcept
Return the number of stored keys.
bool insert(const Key key)
Insert key if absent.
bool erase(const Key key) noexcept
Remove key if present.
void clear() noexcept
Remove every key from the set.
bool is_empty() const noexcept
Check whether the set has no keys.
bool contains(const Key key) const noexcept
Check whether key is stored.
Array< Key > keys() const
Return all stored keys.
Owning prefix tree wrapper.
Compressed prefix tree mapping std::basic_string<Char> keys to values of type T.
Minimal std::expected-style result type for C++20.
void for_each(Operation &operation)
Traverse all the container and performs an operation on each element.
Definition ah-dry.H:796
constexpr size_t size() const noexcept
Returns the number of entries in the table.
Definition hashDry.H:619
void clear()
Empties the container.
Definition hashDry.H:614
constexpr bool is_empty() const noexcept
Checks if the table is empty.
Definition hashDry.H:624
DynList< Key > keys() const
Returns a list containing all keys in the table.
Definition hashDry.H:904
Key * insert(const Key &key)
Inserts a key into the hash table (copy version).
Definition hashDry.H:203
Key & find(const Key &key)
Finds a key and returns a reference to it.
Definition hashDry.H:438
#define TEST(name)
static mt19937 rng
__gmp_expr< typename __gmp_resolve_expr< T, V >::value_type, __gmp_binary_expr< __gmp_expr< T, U >, __gmp_expr< V, W >, __gmp_max_function > > max(const __gmp_expr< T, U > &expr1, const __gmp_expr< V, W > &expr2)
Definition gmpfrxx.h:4121
size_t blossom_maximum_cardinality_matching(const GT &g, DynDlist< typename GT::Arc * > &matching, SA sa=SA())
Alias of compute_maximum_cardinality_general_matching().
Definition Blossom.H:466
Main namespace for Aleph-w library functions.
Definition ah-arena.H:89
static void prefix(Node *root, DynList< Node * > &acc)
std::vector< typename C::Item_Type > to_vector(const C &c)
Convert a container to a std::vector.
Definition ah-convert.H:238
Trie (prefix tree) implementation.
static std::vector< std::string > to_sorted_vector(const DynArray< std::string > &words)
FooMap m(5, fst_unit_pair_hash, snd_unit_pair_hash)
int keys[]
PATRICIA/crit-bit set and map for fixed-width unsigned integer keys.
Compressed prefix tree (Aleph::RadixTree) mapping string keys to values.