@@ -535,10 +535,22 @@ class sharing_mapt
535
535
return lp;
536
536
}
537
537
538
+ innert *migrate (
539
+ const std::size_t i,
540
+ const std::size_t key_suffix,
541
+ const std::size_t bit_last,
542
+ innert &inner);
543
+
538
544
void iterate(
539
545
const innert &n,
540
546
std::function<void (const key_type &k, const mapped_type &m)> f) const ;
541
547
548
+ void add_item_if_not_shared (
549
+ const innert &container,
550
+ const innert &inner,
551
+ delta_viewt &delta_view,
552
+ const bool only_common) const ;
553
+
542
554
void gather_all (const innert &n, delta_viewt &delta_view) const ;
543
555
544
556
bool is_singular (const leaf_listt &ll) const
@@ -592,8 +604,7 @@ ::iterate(
592
604
593
605
for (const auto &item : m)
594
606
{
595
- const innert *i = &item.second ;
596
- stack.push (i);
607
+ stack.push (&item.second );
597
608
}
598
609
}
599
610
else
@@ -664,8 +675,7 @@ ::count_unmarked_nodes(
664
675
665
676
for (const auto &item : m)
666
677
{
667
- const innert *i = &item.second ;
668
- stack.push (i);
678
+ stack.push (&item.second );
669
679
}
670
680
}
671
681
else
@@ -779,6 +789,73 @@ ::gather_all(const innert &n, delta_viewt &delta_view) const
779
789
iterate(n, f);
780
790
}
781
791
792
+ SHARING_MAPT (void )::add_item_if_not_shared(
793
+ const innert &container,
794
+ const innert &inner,
795
+ delta_viewt &delta_view,
796
+ const bool only_common) const
797
+ {
798
+ SM_ASSERT (!container.empty ());
799
+ SM_ASSERT (!inner.empty ());
800
+
801
+ std::stack<const innert *> stack;
802
+ stack.push (&inner);
803
+
804
+ do
805
+ {
806
+ const innert *ip = stack.top ();
807
+ stack.pop ();
808
+
809
+ SM_ASSERT (!ip->empty ());
810
+
811
+ if (ip->is_internal ())
812
+ {
813
+ const to_mapt &m = ip->get_to_map ();
814
+ SM_ASSERT (!m.empty ());
815
+
816
+ for (const auto &item : m)
817
+ {
818
+ const innert *i = &item.second ;
819
+ stack.push (i);
820
+ }
821
+ }
822
+ else
823
+ {
824
+ SM_ASSERT (ip->is_container ());
825
+
826
+ if (ip->shares_with (container))
827
+ return ;
828
+
829
+ const leaft &l1 = container.get_container ().front ();
830
+
831
+ const leaf_listt &ll = ip->get_container ();
832
+ SM_ASSERT (!ll.empty ());
833
+
834
+ for (const auto &l : ll)
835
+ {
836
+ if (l1.shares_with (l))
837
+ return ;
838
+
839
+ if (l1.get_key () == l.get_key ())
840
+ {
841
+ // element is in both maps and not shared
842
+ delta_view.push_back (
843
+ {true , l1.get_key (), l1.get_value (), l.get_value ()});
844
+ return ;
845
+ }
846
+ }
847
+ }
848
+ }
849
+ while (!stack.empty ());
850
+
851
+ // element is only in first map
852
+ if (!only_common)
853
+ {
854
+ const leaft &l1 = container.get_container ().front ();
855
+ delta_view.push_back ({false , l1.get_key (), l1.get_value (), dummy});
856
+ }
857
+ }
858
+
782
859
SHARING_MAPT (void )
783
860
::get_delta_view(
784
861
const sharing_mapt &other,
@@ -840,8 +917,10 @@ ::get_delta_view(
840
917
for (const auto &item : ip1->get_to_map ())
841
918
{
842
919
const innert &child = item.second ;
843
- SM_ASSERT (!child.shares_with (*ip2));
844
- stack.push (stack_itemt (&child, ip2));
920
+ if (!child.shares_with (*ip2))
921
+ {
922
+ stack.push (stack_itemt (&child, ip2));
923
+ }
845
924
}
846
925
847
926
continue ;
@@ -880,12 +959,7 @@ ::get_delta_view(
880
959
{
881
960
SM_ASSERT (is_singular (ip1->get_container ()));
882
961
883
- for (const auto &item : ip2->get_to_map ())
884
- {
885
- const innert &child = item.second ;
886
- SM_ASSERT (!ip1->shares_with (child));
887
- stack.push (stack_itemt (ip1, &child));
888
- }
962
+ add_item_if_not_shared (*ip1, *ip2, delta_view, only_common);
889
963
890
964
continue ;
891
965
}
@@ -903,11 +977,13 @@ ::get_delta_view(
903
977
{
904
978
if (!l1.shares_with (*p))
905
979
{
980
+ SM_ASSERT (other.has_key (k1));
906
981
delta_view.push_back ({k1, l1.get_value (), p->get_value ()});
907
982
}
908
983
}
909
984
else if (!only_common)
910
985
{
986
+ SM_ASSERT (!other.has_key (k1));
911
987
delta_view.push_back ({k1, l1.get_value ()});
912
988
}
913
989
}
@@ -917,21 +993,28 @@ ::get_delta_view(
917
993
918
994
SHARING_MAPT2 (, innert *)::get_container_node(const key_type &k)
919
995
{
996
+ SM_ASSERT (has_key (k));
997
+
920
998
std::size_t key = hash ()(k);
921
999
innert *ip = ↦
1000
+ SM_ASSERT (ip->is_internal ());
922
1001
923
1002
for (std::size_t i = 0 ; i < steps; i++)
924
1003
{
925
1004
std::size_t bit = key & mask;
926
1005
927
1006
ip = ip->add_child (bit);
1007
+ SM_ASSERT (ip != nullptr );
1008
+ SM_ASSERT (!ip->empty ());
1009
+
1010
+ if (ip->is_container ())
1011
+ return ip;
928
1012
929
1013
key >>= chunk;
930
1014
}
931
1015
932
- SM_ASSERT (ip->is_container ());
933
-
934
- return ip;
1016
+ UNREACHABLE;
1017
+ return nullptr ;
935
1018
}
936
1019
937
1020
SHARING_MAPT2 (const , innert *)::get_container_node(const key_type &k) const
@@ -942,24 +1025,33 @@ SHARING_MAPT2(const, innert *)::get_container_node(const key_type &k) const
942
1025
std::size_t key = hash ()(k);
943
1026
const innert *ip = ↦
944
1027
1028
+ SM_ASSERT (ip->is_defined_internal ());
1029
+
945
1030
for (std::size_t i = 0 ; i < steps; i++)
946
1031
{
947
1032
std::size_t bit = key & mask;
948
1033
949
1034
ip = ip->find_child (bit);
1035
+
950
1036
if (ip == nullptr )
951
1037
return nullptr ;
952
1038
1039
+ SM_ASSERT (!ip->empty ());
1040
+
1041
+ if (ip->is_container ())
1042
+ return ip;
1043
+
953
1044
key >>= chunk;
954
1045
}
955
1046
956
- SM_ASSERT (ip->is_defined_container ());
957
-
958
- return ip;
1047
+ UNREACHABLE;
1048
+ return nullptr ;
959
1049
}
960
1050
961
1051
SHARING_MAPT (void )::erase(const key_type &k)
962
1052
{
1053
+ SM_ASSERT (has_key (k));
1054
+
963
1055
innert *del = nullptr ;
964
1056
std::size_t del_bit = 0 ;
965
1057
@@ -980,6 +1072,9 @@ SHARING_MAPT(void)::erase(const key_type &k)
980
1072
981
1073
ip = ip->add_child (bit);
982
1074
1075
+ if (ip->is_defined_container ())
1076
+ break ;
1077
+
983
1078
key >>= chunk;
984
1079
}
985
1080
@@ -1001,13 +1096,136 @@ SHARING_MAPT(void)::erase(const key_type &k)
1001
1096
num--;
1002
1097
}
1003
1098
1099
+ SHARING_MAPT2 (, innert *)::migrate(
1100
+ const std::size_t step,
1101
+ const std::size_t key_suffix,
1102
+ const std::size_t bit_last,
1103
+ innert &inner)
1104
+ {
1105
+ SM_ASSERT (step < steps - 1 );
1106
+ SM_ASSERT (inner.is_defined_internal ());
1107
+
1108
+ const innert &child = *inner.find_child (bit_last);
1109
+ SM_ASSERT (child.is_defined_container ());
1110
+
1111
+ const leaf_listt &ll = child.get_container ();
1112
+
1113
+ // Only containers at the bottom can contain more than two elements
1114
+ SM_ASSERT (is_singular (ll));
1115
+
1116
+ const leaft &leaf = ll.front ();
1117
+ std::size_t key_existing = hash ()(leaf.get_key ());
1118
+
1119
+ key_existing >>= chunk * step;
1120
+
1121
+ // Copy the container
1122
+ innert container_copy (child);
1123
+
1124
+ // Delete existing container
1125
+ inner.remove_child (bit_last);
1126
+
1127
+ // Add internal node
1128
+ innert *ip = inner.add_child (bit_last);
1129
+ SM_ASSERT (ip->empty ());
1130
+
1131
+ // Find place for both elements
1132
+
1133
+ std::size_t i = step + 1 ;
1134
+ std::size_t key = key_suffix;
1135
+
1136
+ key_existing >>= chunk;
1137
+ key >>= chunk;
1138
+
1139
+ SM_ASSERT (i < steps);
1140
+
1141
+ do
1142
+ {
1143
+ std::size_t bit_existing = key_existing & mask;
1144
+ std::size_t bit = key & mask;
1145
+
1146
+ if (bit != bit_existing)
1147
+ {
1148
+ // Place found
1149
+
1150
+ innert *cp2 = ip->add_child (bit_existing);
1151
+ cp2->swap (container_copy);
1152
+
1153
+ innert *cp1 = ip->add_child (bit);
1154
+ return cp1;
1155
+ }
1156
+
1157
+ SM_ASSERT (bit == bit_existing);
1158
+ ip = ip->add_child (bit);
1159
+
1160
+ key >>= chunk;
1161
+ key_existing >>= chunk;
1162
+
1163
+ i++;
1164
+ } while (i < steps);
1165
+
1166
+ leaft leaf_copy (as_const (&container_copy)->get_container ().front ());
1167
+ ip->get_container ().push_front (leaf_copy);
1168
+
1169
+ return ip;
1170
+ }
1171
+
1004
1172
SHARING_MAPT4 (valueU, void )
1005
1173
::insert(const key_type &k, valueU &&m)
1006
1174
{
1007
- innert *cp = get_container_node (k);
1008
- SM_ASSERT (cp != nullptr );
1175
+ SM_ASSERT (!has_key (k));
1176
+
1177
+ std::size_t key = hash ()(k);
1178
+ innert *ip = ↦
1179
+
1180
+ // The root cannot be a container node
1181
+ SM_ASSERT (ip->is_internal ());
1182
+
1183
+ for (std::size_t i = 0 ; i < steps; i++)
1184
+ {
1185
+ std::size_t bit = key & mask;
1186
+
1187
+ SM_ASSERT (ip != nullptr );
1188
+ SM_ASSERT (ip->is_internal ());
1189
+ SM_ASSERT (i == 0 || !ip->empty ());
1190
+
1191
+ innert *child = ip->add_child (bit);
1192
+
1193
+ // Place is unoccupied
1194
+ if (child->empty ())
1195
+ {
1196
+ // Create container and insert leaf
1197
+ child->place_leaf (k, std::forward<valueU>(m));
1198
+
1199
+ SM_ASSERT (child->is_defined_container ());
1200
+
1201
+ num++;
1202
+
1203
+ return ;
1204
+ }
1205
+
1206
+ if (child->is_container () && i < steps - 1 )
1207
+ {
1208
+ // Migrate the elements downwards
1209
+ innert *cp = migrate (i, key, bit, *ip);
1210
+
1211
+ cp->place_leaf (k, std::forward<valueU>(m));
1212
+
1213
+ num++;
1214
+
1215
+ return ;
1216
+ }
1217
+
1218
+ SM_ASSERT (i == steps - 1 || child->is_defined_internal ());
1219
+
1220
+ ip = child;
1221
+ key >>= chunk;
1222
+ }
1223
+
1224
+ SM_ASSERT (ip->is_defined_container ());
1225
+
1226
+ // Add to the bottom container
1227
+ ip->place_leaf (k, std::forward<valueU>(m));
1009
1228
1010
- cp->place_leaf (k, std::forward<valueU>(m));
1011
1229
num++;
1012
1230
}
1013
1231
0 commit comments