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{
210 auto constant_hash = [] (const int &) noexcept -> size_t { return 0u; };
214 auto *p1 = tbl.insert(1);
215 auto *p2 = tbl.insert(2);
216 auto *p3 = tbl.insert(3);
217 ASSERT_NE(p1, nullptr);
218 ASSERT_NE(p2, nullptr);
219 ASSERT_NE(p3, nullptr);
220
221 tbl.remove_ptr(p2); // mark one as deleted
222
223 auto stats = tbl.stats();
224 EXPECT_EQ(stats.num_busy, static_cast<size_t>(2));
225 EXPECT_EQ(stats.num_deleted, static_cast<size_t>(1));
226 EXPECT_EQ(stats.num_busy + stats.num_deleted + stats.num_empty,
227 static_cast<size_t>(tbl.capacity()));
228 EXPECT_GE(stats.max_len, static_cast<size_t>(1));
229}
230
232{
236 /*lower*/0.25f,
237 /*upper*/0.5f,
238 /*with_resize*/true);
239 for (int i = 0; i < 10; ++i)
240 ASSERT_NE(tbl.insert(i), nullptr);
241
242 for (int i = 0; i < 10; ++i)
243 EXPECT_NE(tbl.search(i), nullptr);
244 EXPECT_EQ(tbl.size(), static_cast<size_t>(10));
245}
246
248{
249 auto const_hash = [](int) { return static_cast<size_t>(0); };
252 for (int i = 0; i < 5; ++i)
253 ASSERT_NE(tbl.insert(i), nullptr);
254
255 for (int i = 0; i < 5; ++i)
256 EXPECT_NE(tbl.search(i), nullptr);
257
258 auto stats = tbl.stats();
259 EXPECT_EQ(stats.num_busy, static_cast<size_t>(5));
260 EXPECT_GE(stats.max_len, static_cast<size_t>(5)); // long collision chain
261}
262
264{
268 /*lower*/0.25f,
269 /*upper*/0.5f,
270 /*with_resize*/true);
271 for (int i = 0; i < 6; ++i)
272 ASSERT_NE(tbl.insert(i), nullptr);
273
274 // Remove some keys to create DELETED slots
275 tbl.remove(1);
276 tbl.remove(3);
277
278 // Insert more keys to force resize
279 for (int i = 10; i < 16; ++i)
280 ASSERT_NE(tbl.insert(i), nullptr);
281
282 // Live keys must remain accessible
283 for (int i : {0, 2, 4, 5, 10, 11, 12, 13, 14, 15})
284 EXPECT_NE(tbl.search(i), nullptr);
285}
286
288{
290 auto *p1 = tbl.search_or_insert(1);
291 ASSERT_NE(p1, nullptr);
292 auto *p2 = tbl.search_or_insert(1); // should return existing
293 EXPECT_EQ(p1, p2);
294 EXPECT_EQ(tbl.size(), static_cast<size_t>(1));
295}
296
298{
301 a.insert(1);
302 a.insert(2);
303
304 // copy ctor
305 OLhashTable<int> b = a;
306 EXPECT_EQ(b.size(), a.size());
307 EXPECT_NE(b.search(1), nullptr);
308 EXPECT_NE(b.search(2), nullptr);
309
310 // move ctor
311 OLhashTable<int> c = std::move(b);
312 EXPECT_EQ(c.size(), static_cast<size_t>(2));
313 EXPECT_NE(c.search(1), nullptr);
314 // moved-from state is unspecified; ensure it is still usable
315 b.insert(5);
316 EXPECT_NE(b.search(5), nullptr);
317
318 // swap
321 d.insert(99);
322 a.swap(d);
323 EXPECT_NE(a.search(99), nullptr);
324 EXPECT_EQ(d.search(99), nullptr);
325
326 // copy assignment
327 OLhashTable<int> e(2);
328 e.insert(42);
329 e = c; // c has 1 and 2
330 EXPECT_NE(e.search(1), nullptr);
331 EXPECT_NE(e.search(2), nullptr);
332 EXPECT_EQ(e.size(), static_cast<size_t>(2));
333
334 // move assignment
335 OLhashTable<int> f(2);
336 f.insert(77);
337 f = std::move(e);
338 EXPECT_NE(f.search(1), nullptr);
339 EXPECT_NE(f.search(2), nullptr);
340 f.insert(88); // moved-from e should still be usable indirectly via f
341}
342
344{
346 auto stats_empty = tbl_empty.stats();
347 EXPECT_EQ(stats_empty.num_busy, static_cast<size_t>(0));
348 EXPECT_EQ(stats_empty.num_deleted, static_cast<size_t>(0));
349 // num_empty may be greater than len due to lens counting, so only busy/deleted are validated
350
351 auto const_hash = [](int) { return static_cast<size_t>(0); };
354 for (int i = 0; i < 5; ++i)
355 tbl_full.insert(i);
356 auto stats_full = tbl_full.stats();
357 EXPECT_EQ(stats_full.num_busy, static_cast<size_t>(5));
358 EXPECT_EQ(stats_full.num_deleted, static_cast<size_t>(0));
359 EXPECT_FALSE(std::isnan(stats_full.avg));
360 EXPECT_FALSE(std::isnan(stats_full.var));
361}
362
364{
366 tbl.insert(1);
367 tbl.insert(2);
368 tbl.clean_table();
369 EXPECT_EQ(tbl.size(), static_cast<size_t>(0));
370 EXPECT_EQ(tbl.search(1), nullptr);
371}
372
374{
377 ASSERT_NE(tbl.insert(1), nullptr);
378 ASSERT_NE(tbl.insert(2), nullptr);
379 ASSERT_NE(tbl.insert(3), nullptr);
380 // With a full table and no resize, inserting a duplicate returns nullptr
381 EXPECT_EQ(tbl.insert(2), nullptr);
382}
383
385{
386 // Small upper alpha to force rehash quickly
390 /*lower*/0.1f,
391 /*upper*/0.4f,
392 /*with_resize*/true);
393 const auto cap0 = tbl.capacity();
394 for (int i = 0; i < 10; ++i)
395 tbl.insert(i);
396 EXPECT_GE(tbl.capacity(), cap0); // puede no crecer si el alpha no se supera
397 for (int i = 0; i < 10; ++i)
398 EXPECT_NE(tbl.search(i), nullptr);
399}
400
402{
405 tbl.insert(1);
406 tbl.insert(2);
407 tbl.remove(1); // leaves a DELETED slot
408 EXPECT_EQ(tbl.size(), static_cast<size_t>(1));
409 tbl.insert(3); // should reuse the slot if applicable
410 EXPECT_NE(tbl.search(2), nullptr);
411 EXPECT_NE(tbl.search(3), nullptr);
412 EXPECT_EQ(tbl.size(), static_cast<size_t>(2));
413}
414
416{
417 // Small table without resize to force search without finding EMPTY
424 /*with_resize*/false);
425 for (int i = 0; i < 5; ++i)
426 ASSERT_NE(tbl.insert(i), nullptr);
427
428 // Missing key must throw in finite time (no infinite loop)
429 EXPECT_THROW(tbl.remove(99), std::domain_error);
430}
431
433{
435 auto *p1 = tbl.insert(10);
436 ASSERT_NE(p1, nullptr);
437 auto *p2 = tbl.insert(10);
438 EXPECT_EQ(p2, nullptr); // duplicate rejected
439
440 auto *p3 = tbl.search_or_insert(10);
441 EXPECT_EQ(p3, p1); // returns the existing one
442 EXPECT_EQ(tbl.size(), static_cast<size_t>(1));
443}
444
446{
447 ODhashTable<int> a(7);
448 a.insert(1);
449 a.insert(2);
450
451 ODhashTable<int> b = a; // copy ctor
452 EXPECT_EQ(b.size(), a.size());
453 EXPECT_NE(b.search(1), nullptr);
454
455 ODhashTable<int> c = std::move(b); // move ctor
456 EXPECT_EQ(c.size(), static_cast<size_t>(2));
457
458 ODhashTable<int> d(3);
459 d.insert(99);
460 c.swap(d);
461 EXPECT_NE(c.search(99), nullptr);
462 EXPECT_EQ(d.search(99), nullptr);
463
464 ODhashTable<int> e(2);
465 e.insert(77);
466 e = c; // copy assign
467 EXPECT_NE(e.search(99), nullptr);
468 EXPECT_EQ(e.size(), c.size());
469
470 ODhashTable<int> f(2);
471 f = std::move(e); // move assign
472 EXPECT_NE(f.search(99), nullptr);
473 f.insert(5); // usable after move
474}
475
477{
481 tbl.insert(1);
482 tbl.insert(2);
483 tbl.insert(3);
484 tbl.remove(2); // leaves DELETED and rehash clears probe_counters
485 auto stats = tbl.stats();
486 EXPECT_EQ(stats.num_busy, static_cast<size_t>(2));
487 EXPECT_GE(stats.num_deleted, static_cast<size_t>(0)); // may compact
488}
489
491{
493 auto h2 = [](int k) { return static_cast<size_t>(k * 13); };
495 EXPECT_TRUE(tbl.insert(1));
496 EXPECT_NE(tbl.search(1), nullptr);
497}
498
500{
502 for (int i = 0; i < 5; ++i)
503 tbl.insert(i);
504 auto stats = tbl.stats();
505 EXPECT_FALSE(std::isnan(stats.avg));
506 EXPECT_FALSE(std::isnan(stats.var));
507}
509{
511 // Force the second hash to be constant to lengthen the probe chain
512 auto const_h2 = +[](int) { return static_cast<size_t>(0); };
513 tbl.set_second_hash_fct(const_h2);
514 // Insert keys that collide in the first hash by modulo
515 tbl.insert(0); // i_fst=0
516 tbl.insert(7); // i_fst=0 -> BUSY, i_snd=0 -> BUSY, linear probe
517 tbl.insert(14); // i_fst=0 -> BUSY, i_snd=0 -> BUSY, linear probe
518 auto stats = tbl.stats();
519 EXPECT_EQ(stats.num_busy, static_cast<size_t>(3));
520 EXPECT_GE(stats.max_len, static_cast<size_t>(1));
521}
522
524{
529 /*lower*/0.25f,
530 /*upper*/0.5f,
531 /*with_resize*/true);
532 const auto cap0 = tbl.capacity();
533 for (int i = 0; i < 10; ++i)
534 tbl.insert(i);
535 EXPECT_GE(tbl.capacity(), cap0);
536 for (int i = 0; i < 10; ++i)
537 EXPECT_NE(tbl.search(i), nullptr);
538}
539
541{
543 tbl.insert(0);
544 tbl.insert(5);
545 tbl.insert(10);
546 EXPECT_NE(tbl.search(10), nullptr); // traverses linear probe
547}
548
550{
552 std::set<int> inserted;
553 for (int i = 0; i < 7; ++i)
554 {
555 tbl.insert(i * 2);
556 inserted.insert(i * 2);
557 }
558 auto it = tbl.get_it();
559 std::set<int> iterated;
560 for (; it.has_curr(); it.next_ne())
561 iterated.insert(it.get_curr());
562 EXPECT_EQ(iterated, inserted);
563}
564
565// ============================================================================
566// LhashTable tests
567// ============================================================================
568
570{
571 auto const_hash = +[](const int &) { return static_cast<size_t>(0); };
574 true, true);
575
576 using Bucket = LhashBucket<int>;
577 auto * b = new Bucket(1);
578 ASSERT_NE(tbl.insert(b), nullptr);
579 EXPECT_EQ(tbl.size(), 1u);
580 EXPECT_EQ(tbl.get_num_busy_slots(), 1u);
581
582 auto * removed = tbl.remove(b);
583 ASSERT_NE(removed, nullptr);
584 delete removed;
585
586 EXPECT_EQ(tbl.size(), 0u);
587 EXPECT_EQ(tbl.get_num_busy_slots(), 0u);
588 EXPECT_DOUBLE_EQ(tbl.current_alpha(), 0.0);
589}
590
592{
594 0.9f, 10.0f, true, true);
595
596 using Bucket = LhashBucket<int>;
597 auto * b1 = new Bucket(1);
598 auto * b2 = new Bucket(2);
599 auto * b3 = new Bucket(3);
600
601 ASSERT_NE(tbl.insert(b1), nullptr);
602 ASSERT_NE(tbl.insert(b2), nullptr);
603 ASSERT_NE(tbl.insert(b3), nullptr);
604
605 const auto old_cap = tbl.capacity();
606 auto * removed = tbl.remove(b1);
607 ASSERT_NE(removed, nullptr);
608 delete removed;
609
610 EXPECT_LT(tbl.capacity(), old_cap);
611 EXPECT_EQ(tbl.size(), 2u);
612
613 delete tbl.remove(b2);
614 delete tbl.remove(b3);
615}
616
618{
619 auto const_hash = +[](const int &) { return static_cast<size_t>(1); };
622 true, true);
623 using Bucket = LhashBucket<int>;
624 for (int k : {1, 2, 3})
625 ASSERT_NE(tbl.insert(new Bucket(k)), nullptr);
626
627 for (LhashTable<int>::Iterator it(tbl); it.has_curr(); )
628 {
629 auto * removed = it.del();
630 delete removed;
631 }
632
633 EXPECT_EQ(tbl.size(), 0u);
634 EXPECT_EQ(tbl.get_num_busy_slots(), 0u);
635}
636
638{
640 using Bucket = LhashBucket<int>;
641
642 auto * b1 = new Bucket(42);
643 ASSERT_NE(tbl.insert(b1), nullptr);
644
645 auto * b2 = new Bucket(42);
646 auto * found = tbl.search_or_insert(b2);
647 EXPECT_EQ(found, b1);
648 delete b2;
649
650 delete tbl.remove(b1);
651}
652
654{
655 using Bucket = LhashBucket<int>;
656 LhashTable<int> src(5);
657 auto * b1 = new Bucket(1);
658 auto * b2 = new Bucket(2);
659 src.insert(b1);
660 src.insert(b2);
661
662 LhashTable<int> dst(std::move(src));
663 EXPECT_TRUE(src.is_empty());
664 EXPECT_EQ(dst.size(), 2u);
665 EXPECT_NE(dst.search(1), nullptr);
666 EXPECT_NE(dst.search(2), nullptr);
667
668 delete dst.remove(b1);
669 delete dst.remove(b2);
670}
671
673{
675 using Bucket = LhashBucket<int>;
676
677 auto * b1 = new Bucket(7);
678 ASSERT_NE(tbl.insert(b1), nullptr);
679 EXPECT_EQ(tbl.size(), 1u);
680
681 auto * b2 = new Bucket(7);
682 EXPECT_EQ(tbl.insert(b2), nullptr);
683 delete b2;
684
685 auto * found = tbl.search(7);
686 EXPECT_EQ(found, b1);
687
688 delete tbl.remove(b1);
689}
690
692{
693 auto const_hash = +[](const int &) { return static_cast<size_t>(3); };
696 true, true);
697 using Bucket = LhashBucket<int>;
698 auto * b1 = new Bucket(1);
699 auto * b2 = new Bucket(2);
700 auto * b3 = new Bucket(3);
701 tbl.insert(b1);
702 tbl.insert(b2);
703 tbl.insert(b3);
704
705 auto * first = tbl.search(1);
706 ASSERT_NE(first, nullptr);
707 EXPECT_EQ(tbl.search_next(first), nullptr);
708
709 delete tbl.remove(b1);
710 delete tbl.remove(b2);
711 delete tbl.remove(b3);
712}
713
715{
717 using Bucket = LhashBucket<int>;
718 tbl.insert(new Bucket(1));
719 tbl.insert(new Bucket(2));
720
722 it.reset_last();
723 ASSERT_TRUE(it.has_curr());
724 it.next();
725 EXPECT_THROW(it.get_curr(), std::overflow_error);
726 EXPECT_THROW(it.next(), std::overflow_error);
727
728 it.reset_first();
729 ASSERT_TRUE(it.has_curr());
730 it.prev();
731 EXPECT_THROW(it.get_curr(), std::underflow_error);
732 EXPECT_THROW(it.prev(), std::underflow_error);
733
734 // cleanup
735 for (LhashTable<int>::Iterator clean(tbl); clean.has_curr(); )
736 delete clean.del();
737}
738
740{
743 true, true);
744 using Bucket = LhashBucket<int>;
745 for (int k : {1, 2, 3})
746 tbl.insert(new Bucket(k));
747
748 tbl.empty();
749
750 EXPECT_EQ(tbl.size(), 0u);
751 EXPECT_EQ(tbl.get_num_busy_slots(), 0u);
752 EXPECT_DOUBLE_EQ(tbl.current_alpha(), 0.0);
753}
754
756{
757 // remove_all_buckets = false should not delete user buckets on destruction
758 auto const_hash = +[](const int &) { return static_cast<size_t>(0); };
759 auto * b = new LhashBucket<int>(10);
760 {
763 /*remove_all_buckets*/false, /*with_resize*/true);
764 tbl.insert(b);
765 EXPECT_EQ(tbl.size(), 1u);
766 }
767 // if destructor deleted b, this would UAF; we delete manually
768 delete b;
769}
770
772{
773 using Bucket = LhashBucket<int>;
774 LhashTable<int> a(7);
775 LhashTable<int> b(3);
776 auto * b1 = new Bucket(1);
777 auto * b2 = new Bucket(2);
778 auto * b3 = new Bucket(3);
779 auto * bx = new Bucket(99);
780 a.insert(b1);
781 a.insert(b2);
782 a.insert(b3);
783 b.insert(bx);
784
785 const auto cap_a = a.capacity();
786 const auto cap_b = b.capacity();
787
788 a.swap(b);
789
790 EXPECT_EQ(a.size(), 1u);
791 EXPECT_EQ(b.size(), 3u);
794 EXPECT_NE(a.search(99), nullptr);
795 EXPECT_NE(b.search(1), nullptr);
796
797 delete a.remove(bx);
798 delete b.remove(b1);
799 delete b.remove(b2);
800 delete b.remove(b3);
801}
802
804{
805 using Bucket = LhashBucket<int>;
806 LhashTable<int> tbl(101);
807 for (int k : {1, 2, 102}) // 1 and 102 collide with modulo 101
808 tbl.insert(new Bucket(k));
809 const size_t busy_before = tbl.get_num_busy_slots();
810
811 tbl.set_hash_fct(+[](const int & k) { return static_cast<size_t>(k * 2); });
812 tbl.resize(101); // force rehash with new hash function
813
814 EXPECT_LE(tbl.get_num_busy_slots(), 3u);
815 EXPECT_NE(tbl.search(1), nullptr);
816 EXPECT_NE(tbl.search(2), nullptr);
817 EXPECT_NE(tbl.search(102), nullptr);
818 EXPECT_NE(tbl.get_num_busy_slots(), busy_before);
819
820 delete tbl.remove(tbl.search(1));
821 delete tbl.remove(tbl.search(2));
822 delete tbl.remove(tbl.search(102));
823}
824
826{
829 true, false);
830 using Bucket = LhashBucket<int>;
831 const auto cap = tbl.capacity();
832 for (int k = 0; k < 50; ++k)
833 tbl.insert(new Bucket(k));
834
835 EXPECT_EQ(tbl.capacity(), cap);
836
837 for (LhashTable<int>::Iterator it(tbl); it.has_curr(); )
838 delete it.del();
839}
840
842{
843 struct ModCmp
844 {
845 bool operator()(int a, int b) const { return (a % 10) == (b % 10); }
846 };
847 using Bucket = LhashBucket<int>;
848 auto const_hash = +[](const int &) { return static_cast<size_t>(0); };
852 true, true);
853 auto * b1 = new Bucket(10);
854 auto * b2 = new Bucket(20);
855 ASSERT_NE(tbl.insert(b1), nullptr);
856 EXPECT_EQ(tbl.insert(b2), nullptr); // treated as equal keys
857 EXPECT_EQ(tbl.size(), 1u);
858
859 delete tbl.remove(b1);
860 delete b2;
861}
862
864{
865 using Bucket = LhashBucket<int>;
866 LhashTable<int> tbl(101);
867 tbl.insert(new Bucket(1));
868 tbl.insert(new Bucket(2));
869 EXPECT_GT(tbl.current_alpha(), 0.0);
870 for (LhashTable<int>::Iterator it(tbl); it.has_curr(); )
871 delete it.del();
872}
873
874static_assert(!std::is_copy_constructible_v<LhashTable<int>>,
875 "LhashTable should not be copy constructible");
876static_assert(!std::is_copy_assignable_v<LhashTable<int>>,
877 "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:1155
T & append(const T &item)
Definition htlist.H:1271
void empty() noexcept
empty the list
Definition htlist.H:1389
Bucket * remove(Bucket *bucket) noexcept
Removes bucket from the table.
Definition tpl_lhash.H:454
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:384
const size_t & size() const noexcept
Returns the number of elements contained in the table.
Definition tpl_lhash.H:527
const size_t & capacity() const noexcept
Returns the table capacity.
Definition tpl_lhash.H:524
void swap(GenLhashTable &other) noexcept
Definition tpl_lhash.H:232
Bucket * search(const Key &key) const noexcept
Search in the table for a bucket with key.
Definition tpl_lhash.H:429
constexpr bool is_empty() const noexcept
Definition tpl_lhash.H:533
Open addressing hash table with double hashing collision resolution.
Definition tpl_odhash.H:182
void set_second_hash_fct(Hash_Fct fct) noexcept
Definition tpl_odhash.H:615
Key * search(const Key &key) const noexcept
searches the table for the key.
Definition tpl_odhash.H:543
void swap(ODhashTable &other) noexcept
Definition tpl_odhash.H:420
Open addressing hash table with linear probing collision resolution.
Definition tpl_olhash.H:170
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:353
void swap(OLhashTable &other) noexcept
Definition tpl_olhash.H:296
void for_each(Operation &operation)
Traverse all the container and performs an operation on each element.
Definition ah-dry.H:779
Aleph::DynList< __T > maps(Operation &op) const
Map the elements of the container.
Definition ah-dry.H:1057
constexpr size_t size() const noexcept
Returns the number of entries in the table.
Definition hashDry.H:619
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
Divide_Conquer_DP_Result< Cost > divide_and_conquer_partition_dp(const size_t groups, const size_t n, Transition_Cost_Fn transition_cost, const Cost inf=dp_optimization_detail::default_inf< Cost >())
Optimize partition DP using divide-and-conquer optimization.
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
STL namespace.
Generic hash table with collision resolution by separate chaining and buckets without virtual destruc...
Definition tpl_lhash.H:838
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
static int * k
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