Aleph-w 3.0
A C++ Library for Data Structures and Algorithms
Loading...
Searching...
No Matches
hash-it.cc
Go to the documentation of this file.
1
2/*
3 Aleph_w
4
5 Data structures & Algorithms
6 version 2.0.0b
7 https://github.com/lrleon/Aleph-w
8
9 This file is part of Aleph-w library
10
11 Copyright (c) 2002-2026 Leandro Rabindranath Leon
12
13 Permission is hereby granted, free of charge, to any person obtaining a copy
14 of this software and associated documentation files (the "Software"), to deal
15 in the Software without restriction, including without limitation the rights
16 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
17 copies of the Software, and to permit persons to whom the Software is
18 furnished to do so, subject to the following conditions:
19
20 The above copyright notice and this permission notice shall be included in all
21 copies or substantial portions of the Software.
22
23 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
24 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
25 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
26 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
27 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
28 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
29 SOFTWARE.
30*/
31
32
37# include <gtest/gtest.h>
38
39# include <ahFunctional.H>
40# include <ahSort.H>
41# include <tpl_dynMapOhash.H>
42# include <tpl_dynSetHash.H>
43# include <tpl_olhash.H>
44# include <tpl_odhash.H>
45# include <tpl_lhash.H>
46# include <stdexcept>
47# include <functional>
48
49using namespace std;
50using namespace testing;
51using namespace Aleph;
52
54
55constexpr size_t N = 1000;
56
57template <class HashTbl>
58struct OHashTest : public ::testing::Test
59{
63 : tbl(N), items(range(static_cast<size_t>(0), N - 1))
64 {
65 items.for_each([this](auto i)
66 { tbl.emplace(i, to_string(i)); });
67 }
68};
69
70template <class HashTbl>
71struct EmptyOHashTest : public ::testing::Test
72{
74};
75
77(OHashTest);
78
81
83{
84 TypeParam tbl = this->tbl;
85 auto it = tbl.get_it();
86 ASSERT_FALSE(it.has_curr());
87 ASSERT_THROW(it.get_curr(), std::overflow_error);
88 ASSERT_THROW(it.next(), std::overflow_error);
89}
90
92{
93 TypeParam tbl = this->tbl;
94
95 ASSERT_EQ(tbl.size(), N);
96
97 auto it = tbl.get_it();
98 EXPECT_NO_THROW(it.get_curr());
99 EXPECT_NO_THROW(it.next());
100 EXPECT_NO_THROW(it.reset_first());
102 for (; it.has_curr(); it.next_ne())
103 l.append(it.get_curr_ne());
104 EXPECT_FALSE(it.has_curr());
105 auto ll = l.maps<size_t>([](auto &p)
106 { return p.first; });
107 EXPECT_EQ(sort(ll), this->items);
108
109 l.empty();
110 EXPECT_NO_THROW(it.reset_last());
111 for (; it.has_curr(); it.prev_ne())
112 l.append(it.get_curr_ne());
113 ll = l.maps<size_t>([](auto &p)
114 { return p.first; });
115 EXPECT_EQ(sort(ll), this->items);
116}
117
122
128 >;
129
134
136{
138 11,
144 false);
145
146 EXPECT_TRUE(tbl.is_empty());
147 ASSERT_NE(tbl.insert(42), nullptr);
148 ASSERT_NE(tbl.insert(7), nullptr);
149 EXPECT_NE(tbl.search(42), nullptr);
150
151 auto stats = tbl.stats();
152 EXPECT_EQ(stats.num_busy, static_cast<size_t>(2));
153}
154
156{
158 auto *ptr = tbl.insert(5);
159 ASSERT_NE(ptr, nullptr);
160
161 auto *bucket = decltype(tbl)::key_to_bucket(ptr);
162 ASSERT_NE(bucket, nullptr);
163 EXPECT_EQ(bucket->key, 5);
164 // bucket must be within table range
165 EXPECT_NO_THROW(tbl.remove(5));
166}
167
169{
171 tbl.insert(1);
172 EXPECT_THROW(tbl.remove(2), std::domain_error);
173}
174
176{
179 auto *p1 = tbl.insert(10);
180 ASSERT_NE(p1, nullptr);
181 auto *p2 = tbl.insert(10);
182 EXPECT_EQ(p2, nullptr); // duplicate rejected
183 EXPECT_EQ(tbl.size(), static_cast<size_t>(1));
184}
185
187{
190 auto *p = tbl.insert(5);
191 ASSERT_NE(p, nullptr);
192 // remove_ptr is protected; exercise via remove(key) for coverage
193 EXPECT_NO_THROW(tbl.remove(5));
194 EXPECT_EQ(tbl.size(), static_cast<size_t>(0));
195 EXPECT_THROW(tbl.remove(5), std::domain_error);
196}
197
199{
202 for (int i = 0; i < 5; ++i)
203 ASSERT_NE(tbl.insert(i), nullptr);
204 EXPECT_EQ(tbl.size(), static_cast<size_t>(5));
205 EXPECT_EQ(tbl.search(42), nullptr); // miss should terminate
206}
207
209{
212 auto *p1 = tbl.insert(1);
213 auto *p2 = tbl.insert(2);
214 auto *p3 = tbl.insert(3);
215 ASSERT_NE(p1, nullptr);
216 ASSERT_NE(p2, nullptr);
217 ASSERT_NE(p3, nullptr);
218
219 tbl.remove_ptr(p2); // mark one as deleted
220
221 auto stats = tbl.stats();
222 EXPECT_EQ(stats.num_busy, static_cast<size_t>(2));
223 EXPECT_EQ(stats.num_deleted, static_cast<size_t>(1));
224 EXPECT_EQ(stats.num_busy + stats.num_deleted + stats.num_empty,
225 static_cast<size_t>(tbl.capacity()));
226 EXPECT_GE(stats.max_len, static_cast<size_t>(1));
227}
228
230{
234 /*lower*/0.25f,
235 /*upper*/0.5f,
236 /*with_resize*/true);
237 for (int i = 0; i < 10; ++i)
238 ASSERT_NE(tbl.insert(i), nullptr);
239
240 for (int i = 0; i < 10; ++i)
241 EXPECT_NE(tbl.search(i), nullptr);
242 EXPECT_EQ(tbl.size(), static_cast<size_t>(10));
243}
244
246{
247 auto const_hash = [](int) { return static_cast<size_t>(0); };
250 for (int i = 0; i < 5; ++i)
251 ASSERT_NE(tbl.insert(i), nullptr);
252
253 for (int i = 0; i < 5; ++i)
254 EXPECT_NE(tbl.search(i), nullptr);
255
256 auto stats = tbl.stats();
257 EXPECT_EQ(stats.num_busy, static_cast<size_t>(5));
258 EXPECT_GE(stats.max_len, static_cast<size_t>(5)); // long collision chain
259}
260
262{
266 /*lower*/0.25f,
267 /*upper*/0.5f,
268 /*with_resize*/true);
269 for (int i = 0; i < 6; ++i)
270 ASSERT_NE(tbl.insert(i), nullptr);
271
272 // Remove some keys to create DELETED slots
273 tbl.remove(1);
274 tbl.remove(3);
275
276 // Insert more keys to force resize
277 for (int i = 10; i < 16; ++i)
278 ASSERT_NE(tbl.insert(i), nullptr);
279
280 // Live keys must remain accessible
281 for (int i : {0, 2, 4, 5, 10, 11, 12, 13, 14, 15})
282 EXPECT_NE(tbl.search(i), nullptr);
283}
284
286{
288 auto *p1 = tbl.search_or_insert(1);
289 ASSERT_NE(p1, nullptr);
290 auto *p2 = tbl.search_or_insert(1); // should return existing
291 EXPECT_EQ(p1, p2);
292 EXPECT_EQ(tbl.size(), static_cast<size_t>(1));
293}
294
296{
299 a.insert(1);
300 a.insert(2);
301
302 // copy ctor
303 OLhashTable<int> b = a;
304 EXPECT_EQ(b.size(), a.size());
305 EXPECT_NE(b.search(1), nullptr);
306 EXPECT_NE(b.search(2), nullptr);
307
308 // move ctor
309 OLhashTable<int> c = std::move(b);
310 EXPECT_EQ(c.size(), static_cast<size_t>(2));
311 EXPECT_NE(c.search(1), nullptr);
312 // moved-from state is unspecified; ensure it is still usable
313 b.insert(5);
314 EXPECT_NE(b.search(5), nullptr);
315
316 // swap
319 d.insert(99);
320 a.swap(d);
321 EXPECT_NE(a.search(99), nullptr);
322 EXPECT_EQ(d.search(99), nullptr);
323
324 // copy assignment
325 OLhashTable<int> e(2);
326 e.insert(42);
327 e = c; // c has 1 and 2
328 EXPECT_NE(e.search(1), nullptr);
329 EXPECT_NE(e.search(2), nullptr);
330 EXPECT_EQ(e.size(), static_cast<size_t>(2));
331
332 // move assignment
333 OLhashTable<int> f(2);
334 f.insert(77);
335 f = std::move(e);
336 EXPECT_NE(f.search(1), nullptr);
337 EXPECT_NE(f.search(2), nullptr);
338 f.insert(88); // moved-from e should still be usable indirectly via f
339}
340
342{
344 auto stats_empty = tbl_empty.stats();
345 EXPECT_EQ(stats_empty.num_busy, static_cast<size_t>(0));
346 EXPECT_EQ(stats_empty.num_deleted, static_cast<size_t>(0));
347 // num_empty may be greater than len due to lens counting, so only busy/deleted are validated
348
349 auto const_hash = [](int) { return static_cast<size_t>(0); };
352 for (int i = 0; i < 5; ++i)
353 tbl_full.insert(i);
354 auto stats_full = tbl_full.stats();
355 EXPECT_EQ(stats_full.num_busy, static_cast<size_t>(5));
356 EXPECT_EQ(stats_full.num_deleted, static_cast<size_t>(0));
357 EXPECT_FALSE(std::isnan(stats_full.avg));
358 EXPECT_FALSE(std::isnan(stats_full.var));
359}
360
362{
364 tbl.insert(1);
365 tbl.insert(2);
366 tbl.clean_table();
367 EXPECT_EQ(tbl.size(), static_cast<size_t>(0));
368 EXPECT_EQ(tbl.search(1), nullptr);
369}
370
372{
375 ASSERT_NE(tbl.insert(1), nullptr);
376 ASSERT_NE(tbl.insert(2), nullptr);
377 ASSERT_NE(tbl.insert(3), nullptr);
378 // With a full table and no resize, inserting a duplicate returns nullptr
379 EXPECT_EQ(tbl.insert(2), nullptr);
380}
381
383{
384 // Small upper alpha to force rehash quickly
388 /*lower*/0.1f,
389 /*upper*/0.4f,
390 /*with_resize*/true);
391 const auto cap0 = tbl.capacity();
392 for (int i = 0; i < 10; ++i)
393 tbl.insert(i);
394 EXPECT_GE(tbl.capacity(), cap0); // puede no crecer si el alpha no se supera
395 for (int i = 0; i < 10; ++i)
396 EXPECT_NE(tbl.search(i), nullptr);
397}
398
400{
403 tbl.insert(1);
404 tbl.insert(2);
405 tbl.remove(1); // leaves a DELETED slot
406 EXPECT_EQ(tbl.size(), static_cast<size_t>(1));
407 tbl.insert(3); // should reuse the slot if applicable
408 EXPECT_NE(tbl.search(2), nullptr);
409 EXPECT_NE(tbl.search(3), nullptr);
410 EXPECT_EQ(tbl.size(), static_cast<size_t>(2));
411}
412
414{
415 // Small table without resize to force search without finding EMPTY
422 /*with_resize*/false);
423 for (int i = 0; i < 5; ++i)
424 ASSERT_NE(tbl.insert(i), nullptr);
425
426 // Missing key must throw in finite time (no infinite loop)
427 EXPECT_THROW(tbl.remove(99), std::domain_error);
428}
429
431{
433 auto *p1 = tbl.insert(10);
434 ASSERT_NE(p1, nullptr);
435 auto *p2 = tbl.insert(10);
436 EXPECT_EQ(p2, nullptr); // duplicate rejected
437
438 auto *p3 = tbl.search_or_insert(10);
439 EXPECT_EQ(p3, p1); // returns the existing one
440 EXPECT_EQ(tbl.size(), static_cast<size_t>(1));
441}
442
444{
445 ODhashTable<int> a(7);
446 a.insert(1);
447 a.insert(2);
448
449 ODhashTable<int> b = a; // copy ctor
450 EXPECT_EQ(b.size(), a.size());
451 EXPECT_NE(b.search(1), nullptr);
452
453 ODhashTable<int> c = std::move(b); // move ctor
454 EXPECT_EQ(c.size(), static_cast<size_t>(2));
455
456 ODhashTable<int> d(3);
457 d.insert(99);
458 c.swap(d);
459 EXPECT_NE(c.search(99), nullptr);
460 EXPECT_EQ(d.search(99), nullptr);
461
462 ODhashTable<int> e(2);
463 e.insert(77);
464 e = c; // copy assign
465 EXPECT_NE(e.search(99), nullptr);
466 EXPECT_EQ(e.size(), c.size());
467
468 ODhashTable<int> f(2);
469 f = std::move(e); // move assign
470 EXPECT_NE(f.search(99), nullptr);
471 f.insert(5); // usable after move
472}
473
475{
479 tbl.insert(1);
480 tbl.insert(2);
481 tbl.insert(3);
482 tbl.remove(2); // leaves DELETED and rehash clears probe_counters
483 auto stats = tbl.stats();
484 EXPECT_EQ(stats.num_busy, static_cast<size_t>(2));
485 EXPECT_GE(stats.num_deleted, static_cast<size_t>(0)); // may compact
486}
487
489{
491 auto h2 = [](int k) { return static_cast<size_t>(k * 13); };
492 tbl.set_second_hash_fct(h2);
493 EXPECT_TRUE(tbl.insert(1));
494 EXPECT_NE(tbl.search(1), nullptr);
495}
496
498{
500 for (int i = 0; i < 5; ++i)
501 tbl.insert(i);
502 auto stats = tbl.stats();
503 EXPECT_FALSE(std::isnan(stats.avg));
504 EXPECT_FALSE(std::isnan(stats.var));
505}
507{
509 // Force the second hash to be constant to lengthen the probe chain
510 auto const_h2 = +[](int) { return static_cast<size_t>(0); };
511 tbl.set_second_hash_fct(const_h2);
512 // Insert keys that collide in the first hash by modulo
513 tbl.insert(0); // i_fst=0
514 tbl.insert(7); // i_fst=0 -> BUSY, i_snd=0 -> BUSY, linear probe
515 tbl.insert(14); // i_fst=0 -> BUSY, i_snd=0 -> BUSY, linear probe
516 auto stats = tbl.stats();
517 EXPECT_EQ(stats.num_busy, static_cast<size_t>(3));
518 EXPECT_GE(stats.max_len, static_cast<size_t>(1));
519}
520
522{
527 /*lower*/0.25f,
528 /*upper*/0.5f,
529 /*with_resize*/true);
530 const auto cap0 = tbl.capacity();
531 for (int i = 0; i < 10; ++i)
532 tbl.insert(i);
533 EXPECT_GE(tbl.capacity(), cap0);
534 for (int i = 0; i < 10; ++i)
535 EXPECT_NE(tbl.search(i), nullptr);
536}
537
539{
541 tbl.insert(0);
542 tbl.insert(5);
543 tbl.insert(10);
544 EXPECT_NE(tbl.search(10), nullptr); // traverses linear probe
545}
546
548{
550 std::set<int> inserted;
551 for (int i = 0; i < 7; ++i)
552 {
553 tbl.insert(i * 2);
554 inserted.insert(i * 2);
555 }
556 auto it = tbl.get_it();
557 std::set<int> iterated;
558 for (; it.has_curr(); it.next_ne())
559 iterated.insert(it.get_curr());
561}
562
563// ============================================================================
564// LhashTable tests
565// ============================================================================
566
568{
569 auto const_hash = +[](const int &) { return static_cast<size_t>(0); };
572 true, true);
573
574 using Bucket = LhashBucket<int>;
575 auto * b = new Bucket(1);
576 ASSERT_NE(tbl.insert(b), nullptr);
577 EXPECT_EQ(tbl.size(), 1u);
578 EXPECT_EQ(tbl.get_num_busy_slots(), 1u);
579
580 auto * removed = tbl.remove(b);
581 ASSERT_NE(removed, nullptr);
582 delete removed;
583
584 EXPECT_EQ(tbl.size(), 0u);
585 EXPECT_EQ(tbl.get_num_busy_slots(), 0u);
586 EXPECT_DOUBLE_EQ(tbl.current_alpha(), 0.0);
587}
588
590{
592 0.9f, 10.0f, true, true);
593
594 using Bucket = LhashBucket<int>;
595 auto * b1 = new Bucket(1);
596 auto * b2 = new Bucket(2);
597 auto * b3 = new Bucket(3);
598
599 ASSERT_NE(tbl.insert(b1), nullptr);
600 ASSERT_NE(tbl.insert(b2), nullptr);
601 ASSERT_NE(tbl.insert(b3), nullptr);
602
603 const auto old_cap = tbl.capacity();
604 auto * removed = tbl.remove(b1);
605 ASSERT_NE(removed, nullptr);
606 delete removed;
607
608 EXPECT_LT(tbl.capacity(), old_cap);
609 EXPECT_EQ(tbl.size(), 2u);
610
611 delete tbl.remove(b2);
612 delete tbl.remove(b3);
613}
614
616{
617 auto const_hash = +[](const int &) { return static_cast<size_t>(1); };
620 true, true);
621 using Bucket = LhashBucket<int>;
622 for (int k : {1, 2, 3})
623 ASSERT_NE(tbl.insert(new Bucket(k)), nullptr);
624
625 for (LhashTable<int>::Iterator it(tbl); it.has_curr(); )
626 {
627 auto * removed = it.del();
628 delete removed;
629 }
630
631 EXPECT_EQ(tbl.size(), 0u);
632 EXPECT_EQ(tbl.get_num_busy_slots(), 0u);
633}
634
636{
638 using Bucket = LhashBucket<int>;
639
640 auto * b1 = new Bucket(42);
641 ASSERT_NE(tbl.insert(b1), nullptr);
642
643 auto * b2 = new Bucket(42);
644 auto * found = tbl.search_or_insert(b2);
645 EXPECT_EQ(found, b1);
646 delete b2;
647
648 delete tbl.remove(b1);
649}
650
652{
653 using Bucket = LhashBucket<int>;
654 LhashTable<int> src(5);
655 auto * b1 = new Bucket(1);
656 auto * b2 = new Bucket(2);
657 src.insert(b1);
658 src.insert(b2);
659
660 LhashTable<int> dst(std::move(src));
661 EXPECT_TRUE(src.is_empty());
662 EXPECT_EQ(dst.size(), 2u);
663 EXPECT_NE(dst.search(1), nullptr);
664 EXPECT_NE(dst.search(2), nullptr);
665
666 delete dst.remove(b1);
667 delete dst.remove(b2);
668}
669
671{
673 using Bucket = LhashBucket<int>;
674
675 auto * b1 = new Bucket(7);
676 ASSERT_NE(tbl.insert(b1), nullptr);
677 EXPECT_EQ(tbl.size(), 1u);
678
679 auto * b2 = new Bucket(7);
680 EXPECT_EQ(tbl.insert(b2), nullptr);
681 delete b2;
682
683 auto * found = tbl.search(7);
684 EXPECT_EQ(found, b1);
685
686 delete tbl.remove(b1);
687}
688
690{
691 auto const_hash = +[](const int &) { return static_cast<size_t>(3); };
694 true, true);
695 using Bucket = LhashBucket<int>;
696 auto * b1 = new Bucket(1);
697 auto * b2 = new Bucket(2);
698 auto * b3 = new Bucket(3);
699 tbl.insert(b1);
700 tbl.insert(b2);
701 tbl.insert(b3);
702
703 auto * first = tbl.search(1);
704 ASSERT_NE(first, nullptr);
705 EXPECT_EQ(tbl.search_next(first), nullptr);
706
707 delete tbl.remove(b1);
708 delete tbl.remove(b2);
709 delete tbl.remove(b3);
710}
711
713{
715 using Bucket = LhashBucket<int>;
716 tbl.insert(new Bucket(1));
717 tbl.insert(new Bucket(2));
718
720 it.reset_last();
721 ASSERT_TRUE(it.has_curr());
722 it.next();
723 EXPECT_THROW(it.get_curr(), std::overflow_error);
724 EXPECT_THROW(it.next(), std::overflow_error);
725
726 it.reset_first();
727 ASSERT_TRUE(it.has_curr());
728 it.prev();
729 EXPECT_THROW(it.get_curr(), std::underflow_error);
730 EXPECT_THROW(it.prev(), std::underflow_error);
731
732 // cleanup
733 for (LhashTable<int>::Iterator clean(tbl); clean.has_curr(); )
734 delete clean.del();
735}
736
738{
741 true, true);
742 using Bucket = LhashBucket<int>;
743 for (int k : {1, 2, 3})
744 tbl.insert(new Bucket(k));
745
746 tbl.empty();
747
748 EXPECT_EQ(tbl.size(), 0u);
749 EXPECT_EQ(tbl.get_num_busy_slots(), 0u);
750 EXPECT_DOUBLE_EQ(tbl.current_alpha(), 0.0);
751}
752
754{
755 // remove_all_buckets = false should not delete user buckets on destruction
756 auto const_hash = +[](const int &) { return static_cast<size_t>(0); };
757 auto * b = new LhashBucket<int>(10);
758 {
761 /*remove_all_buckets*/false, /*with_resize*/true);
762 tbl.insert(b);
763 EXPECT_EQ(tbl.size(), 1u);
764 }
765 // if destructor deleted b, this would UAF; we delete manually
766 delete b;
767}
768
770{
771 using Bucket = LhashBucket<int>;
772 LhashTable<int> a(7);
773 LhashTable<int> b(3);
774 auto * b1 = new Bucket(1);
775 auto * b2 = new Bucket(2);
776 auto * b3 = new Bucket(3);
777 auto * bx = new Bucket(99);
778 a.insert(b1);
779 a.insert(b2);
780 a.insert(b3);
781 b.insert(bx);
782
783 const auto cap_a = a.capacity();
784 const auto cap_b = b.capacity();
785
786 a.swap(b);
787
788 EXPECT_EQ(a.size(), 1u);
789 EXPECT_EQ(b.size(), 3u);
792 EXPECT_NE(a.search(99), nullptr);
793 EXPECT_NE(b.search(1), nullptr);
794
795 delete a.remove(bx);
796 delete b.remove(b1);
797 delete b.remove(b2);
798 delete b.remove(b3);
799}
800
802{
803 using Bucket = LhashBucket<int>;
804 LhashTable<int> tbl(101);
805 for (int k : {1, 2, 102}) // 1 and 102 collide with modulo 101
806 tbl.insert(new Bucket(k));
807 const size_t busy_before = tbl.get_num_busy_slots();
808
809 tbl.set_hash_fct(+[](const int & k) { return static_cast<size_t>(k * 2); });
810 tbl.resize(101); // force rehash with new hash function
811
812 EXPECT_LE(tbl.get_num_busy_slots(), 3u);
813 EXPECT_NE(tbl.search(1), nullptr);
814 EXPECT_NE(tbl.search(2), nullptr);
815 EXPECT_NE(tbl.search(102), nullptr);
816 EXPECT_NE(tbl.get_num_busy_slots(), busy_before);
817
818 delete tbl.remove(tbl.search(1));
819 delete tbl.remove(tbl.search(2));
820 delete tbl.remove(tbl.search(102));
821}
822
824{
827 true, false);
828 using Bucket = LhashBucket<int>;
829 const auto cap = tbl.capacity();
830 for (int k = 0; k < 50; ++k)
831 tbl.insert(new Bucket(k));
832
833 EXPECT_EQ(tbl.capacity(), cap);
834
835 for (LhashTable<int>::Iterator it(tbl); it.has_curr(); )
836 delete it.del();
837}
838
840{
841 struct ModCmp
842 {
843 bool operator()(int a, int b) const { return (a % 10) == (b % 10); }
844 };
845 using Bucket = LhashBucket<int>;
846 auto const_hash = +[](const int &) { return static_cast<size_t>(0); };
850 true, true);
851 auto * b1 = new Bucket(10);
852 auto * b2 = new Bucket(20);
853 ASSERT_NE(tbl.insert(b1), nullptr);
854 EXPECT_EQ(tbl.insert(b2), nullptr); // treated as equal keys
855 EXPECT_EQ(tbl.size(), 1u);
856
857 delete tbl.remove(b1);
858 delete b2;
859}
860
862{
863 using Bucket = LhashBucket<int>;
864 LhashTable<int> tbl(101);
865 tbl.insert(new Bucket(1));
866 tbl.insert(new Bucket(2));
867 EXPECT_GT(tbl.current_alpha(), 0.0);
868 for (LhashTable<int>::Iterator it(tbl); it.has_curr(); )
869 delete it.del();
870}
871
872static_assert(!std::is_copy_constructible_v<LhashTable<int>>,
873 "LhashTable should not be copy constructible");
874static_assert(!std::is_copy_assignable_v<LhashTable<int>>,
875 "LhashTable should not be copy assignable");
Functional programming utilities for Aleph-w containers.
High-level sorting functions for Aleph containers.
Dynamic singly linked list with functional programming support.
Definition htlist.H:1423
T & insert(const T &item)
Insert a new item by copy.
Definition htlist.H:1502
T & append(const T &item)
Append a new item by copy.
Definition htlist.H:1562
T remove()
Remove the first item of the list.
Definition htlist.H:1611
void empty() noexcept
empty the list
Definition htlist.H:1689
Bucket * remove(Bucket *bucket) noexcept
Removes bucket from the table.
Definition tpl_lhash.H:437
Bucket * insert(Bucket *bucket)
Inserts bucket into the table and returns its address if the key is not already in the table; otherwi...
Definition tpl_lhash.H:367
const size_t & size() const noexcept
Returns the number of elements contained in the table.
Definition tpl_lhash.H:510
const size_t & capacity() const noexcept
Returns the table capacity.
Definition tpl_lhash.H:507
void swap(GenLhashTable &other) noexcept
Definition tpl_lhash.H:230
Bucket * search(const Key &key) const noexcept
Search in the table for a bucket with key.
Definition tpl_lhash.H:412
constexpr bool is_empty() const noexcept
Definition tpl_lhash.H:516
size_t size() const noexcept
Count the number of elements of the list.
Definition htlist.H:1319
Open addressing hash table with double hashing collision resolution.
Definition tpl_odhash.H:180
Key * search(const Key &key) const noexcept
searches the table for the key.
Definition tpl_odhash.H:537
void swap(ODhashTable &other) noexcept
Definition tpl_odhash.H:418
Open addressing hash table with linear probing collision resolution.
Definition tpl_olhash.H:168
Key * search(const Key &key) const noexcept
Finds the key and returns the associated record if key is find inside the table; otherwise,...
Definition tpl_olhash.H:347
void swap(OLhashTable &other) noexcept
Definition tpl_olhash.H:290
void for_each(Operation &operation)
Traverse all the container and performs an operation on each element.
Definition ah-dry.H:685
Aleph::DynList< __T > maps(Operation &op) const
Map the elements of the container.
Definition ah-dry.H:904
auto get_it() const
Return a properly initialized iterator positioned at the first item on the container.
Definition ah-dry.H:190
constexpr size_t size() const noexcept
Returns the number of entries in the table.
Definition hashDry.H:612
Key * insert(const Key &key)
Inserts a key into the hash table (copy version).
Definition hashDry.H:203
#define TEST(name)
pair< size_t, string > P
Types< MapODhash< size_t, string >, MapOLhash< size_t, string >, DynMapLinHash< size_t, string >, DynMapHash< size_t, string > > HashTypes
REGISTER_TYPED_TEST_CASE_P(EmptyOHashTest, With_exception)
TYPED_TEST_P(EmptyOHashTest, With_exception)
Definition hash-it.cc:82
INSTANTIATE_TYPED_TEST_CASE_P(Empty, EmptyOHashTest, HashTypes)
TYPED_TEST_CASE_P(OHashTest)
constexpr size_t N
Definition hash-it.cc:55
MapOLhash< int, Foo > tbl
Table::Bucket Bucket
Definition lin-hash.cc:54
Main namespace for Aleph-w library functions.
Definition ah-arena.H:89
const float hash_default_upper_alpha
Definition hash-dry.C:40
DynArray< T > sort(const DynArray< T > &a, Cmp &&cmp=Cmp())
Returns a sorted copy of a DynArray.
Definition ahSort.H:227
std::pair< First, Second > pair
Alias to std::pair kept for backwards compatibility.
Definition ahPair.H:89
std::string to_string(const time_t t, const std::string &format)
Format a time_t value into a string using format.
Definition ah-date.H:140
Container< T > range(const T start, const T end, const T step=1)
Generate a range of values [start, end] with a given step.
const float hash_default_lower_alpha
Definition hash-dry.C:38
DynList< T > maps(const C &c, Op op)
Classic map operation.
STL namespace.
Generic hash table with collision resolution by separate chaining and buckets without virtual destruc...
Definition tpl_lhash.H:809
Open addressing hash map using linear probing.
HashTbl tbl
Definition hash-it.cc:73
HashTbl tbl
DynList< size_t > items
Definition hash-it.cc:61
OHashTest()
Definition hash-it.cc:62
Dynamic map with open hashing.
Dynamic set implementations based on hash tables.
Linear hashing with dynamic bucket expansion.
Open addressing hash table with double hashing.
Open addressing hash table with linear probing.
DynList< int > l