@@ -26,6 +26,8 @@ void expect(bool must_be_true) {
26
26
__usearch_raise_runtime_error (" Failed!" );
27
27
}
28
28
29
+ template <typename value_at> void expect_eq (value_at a, value_at b) { expect (a == b); }
30
+
29
31
/* *
30
32
* @brief Convinience wrapper combining combined allocation and construction of an index.
31
33
*/
@@ -637,8 +639,71 @@ template <typename key_at, typename slot_at> void test_strings() {
637
639
}
638
640
}
639
641
642
+ /* *
643
+ * @brief Tests replacing and updating entries in index_dense_gt to ensure consistency after modifications.
644
+ */
645
+ template <typename key_at, typename slot_at> void test_replacing_update () {
646
+
647
+ using vector_key_t = key_at;
648
+ using slot_t = slot_at;
649
+
650
+ using index_punned_t = index_dense_gt<vector_key_t , slot_t >;
651
+ metric_punned_t metric (1 , metric_kind_t ::l2sq_k, scalar_kind_t ::f32_k);
652
+ auto index_result = index_punned_t::make (metric);
653
+ expect (bool (index_result));
654
+ index_punned_t & index = index_result.index ;
655
+
656
+ // Reserve space for 3 entries
657
+ index.reserve (3 );
658
+ auto as_ptr = [](float v) {
659
+ static float value;
660
+ value = v;
661
+ return &value;
662
+ };
663
+
664
+ // Add 3 entries
665
+ index.add (42 , as_ptr (1 .1f ));
666
+ index.add (43 , as_ptr (2 .1f ));
667
+ index.add (44 , as_ptr (3 .1f ));
668
+ expect_eq<std::size_t >(index.size (), 3 );
669
+
670
+ // Assert initial state
671
+ auto initial_search = index.search (as_ptr (1 .0f ), 3 );
672
+ expect_eq<std::size_t >(initial_search.size (), 3 );
673
+ expect_eq<vector_key_t >(initial_search[0 ].member .key , 42 );
674
+ expect_eq<vector_key_t >(initial_search[1 ].member .key , 43 );
675
+ expect_eq<vector_key_t >(initial_search[2 ].member .key , 44 );
676
+
677
+ // Replace the second entry
678
+ index.remove (43 );
679
+ index.add (43 , as_ptr (2 .2f ));
680
+ expect_eq<std::size_t >(index.size (), 3 );
681
+
682
+ // Assert state after replacing second entry
683
+ auto post_second_replacement = index.search (as_ptr (1 .0f ), 3 );
684
+ expect_eq<std::size_t >(post_second_replacement.size (), 3 );
685
+ expect_eq<vector_key_t >(post_second_replacement[0 ].member .key , 42 );
686
+ expect_eq<vector_key_t >(post_second_replacement[1 ].member .key , 43 );
687
+ expect_eq<vector_key_t >(post_second_replacement[2 ].member .key , 44 );
688
+
689
+ // Replace the first entry
690
+ index.remove (42 );
691
+ index.add (42 , as_ptr (1 .2f ));
692
+ expect_eq<std::size_t >(index.size (), 3 );
693
+
694
+ // Assert state after replacing first entry
695
+ auto final_search = index.search (as_ptr (1 .0f ), 3 , 0 );
696
+ expect_eq<std::size_t >(final_search.size (), 3 );
697
+ expect_eq<vector_key_t >(final_search[0 ].member .key , 42 );
698
+ expect_eq<vector_key_t >(final_search[1 ].member .key , 43 );
699
+ expect_eq<vector_key_t >(final_search[2 ].member .key , 44 );
700
+ }
701
+
640
702
int main (int , char **) {
641
703
704
+ // Weird corner cases
705
+ test_replacing_update<std::int64_t , std::uint32_t >();
706
+
642
707
// Exact search without constructing indexes.
643
708
// Great for validating the distance functions.
644
709
std::printf (" Testing exact search\n " );
0 commit comments