12 #ifndef CPROVER_UTIL_SHARING_MAP_H
13 #define CPROVER_UTIL_SHARING_MAP_H
27 #include <type_traits>
36 #ifdef SM_INTERNAL_CHECKS
37 # define SM_ASSERT(b) INVARIANT(b, "Sharing map internal invariant")
48 #define SHARING_MAPT(type) \
55 type sharing_mapt<keyT, valueT, fail_if_equal, hashT, equalT>
57 #define SHARING_MAPTV(return_type, V) \
65 return_type sharing_mapt<keyT, valueT, fail_if_equal, hashT, equalT>
72 #define SHARING_MAPT2(cv_qualifiers, return_type) \
79 cv_qualifiers typename \
80 sharing_mapt<keyT, valueT, fail_if_equal, hashT, equalT>::return_type \
81 sharing_mapt<keyT, valueT, fail_if_equal, hashT, equalT>
90 #define SHARING_MAPT3(template_parameter, cv_qualifiers, return_type) \
97 template <class template_parameter> \
98 cv_qualifiers typename \
99 sharing_mapt<keyT, valueT, fail_if_equal, hashT, equalT>::return_type \
100 sharing_mapt<keyT, valueT, fail_if_equal, hashT, equalT>
107 #define SHARING_MAPT4(template_parameter, return_type) \
111 bool fail_if_equal, \
114 template <class template_parameter> \
115 return_type sharing_mapt<keyT, valueT, fail_if_equal, hashT, equalT>
186 bool fail_if_equal =
false,
187 typename hashT = std::hash<keyT>,
188 typename equalT = std::equal_to<keyT>>
204 typedef std::vector<key_type>
keyst;
221 typename std::conditional<fail_if_equal, std::equal_to<valueT>, falset>::
250 typedef typename std::conditional<
252 real_value_comparatort,
288 template <
class valueU>
291 template <
class valueU>
296 replace(k, std::forward<valueU>(m));
300 insert(k, std::forward<valueU>(m));
312 template <
class valueU>
346 std::size_t tmp =
num;
384 typedef std::pair<const key_type &, const mapped_type &>
view_itemt;
388 typedef std::vector<view_itemt>
viewt;
505 const bool only_common =
true)
const;
509 const bool only_common =
true)
const;
523 #if !defined(_MSC_VER)
524 struct sharing_map_statst
553 template <
class Iterator>
558 [](
const Iterator it) ->
sharing_mapt & {
return *it; });
569 template <
class Iterator>
597 template <
class valueU>
599 const std::size_t starting_level,
600 const std::size_t key_suffix,
601 const std::size_t bit_last,
627 const std::size_t level,
629 const bool only_common)
const;
635 std::set<const void *> &marked,
636 bool mark =
true)
const;
662 std::stack<const nodet *> stack;
667 const nodet *ip = stack.top();
677 for(
const auto item : m)
679 stack.push(&item.second);
693 for(
const auto &l : ll)
695 f(l.get_key(), l.get_value());
698 }
while(!stack.empty());
702 ::count_unmarked_nodes(
704 std::set<const void *> &marked,
712 std::stack<const nodet *> stack;
717 const nodet *ip = stack.top();
721 const unsigned use_count = ip->
use_count();
723 const void *raw_ptr =
730 if(marked.find(raw_ptr) != marked.end())
737 marked.insert(raw_ptr);
751 for(
const auto item : m)
753 stack.push(&item.second);
772 for(
const auto &l : ll)
777 }
while(!stack.empty());
782 #if !defined(_MSC_VER)
789 std::set<const void *> marked;
790 sharing_map_statst sms;
796 for(Iterator it = begin; it != end; it++)
798 sms.num_nodes += f(it).count_unmarked_nodes(
false, marked,
false);
804 for(Iterator it = begin; it != end; it++)
806 sms.num_unique_nodes += f(it).count_unmarked_nodes(
false, marked,
true);
812 for(Iterator it = begin; it != end; it++)
814 sms.num_leafs += f(it).count_unmarked_nodes(
true, marked,
false);
820 for(Iterator it = begin; it != end; it++)
822 sms.num_unique_leafs += f(it).count_unmarked_nodes(
true, marked,
true);
829 ::get_sharing_stats_map(Iterator begin, Iterator end)
831 return get_sharing_stats<Iterator>(
832 begin, end, [](
const Iterator it) ->
sharing_mapt & {
return it->second; });
854 delta_view.push_back(delta_view_itemt(k, m));
863 const std::size_t level,
865 const bool only_common) const
867 const auto &k = leaf.get_key();
868 std::size_t key =
hash()(k);
870 key >>= level * chunk;
872 const nodet *ip = &inner;
877 std::size_t bit = key & mask;
886 delta_view.push_back({k, leaf.get_value()});
899 if(leaf.shares_with(l2))
902 if(leaf.get_key() == l2.get_key())
904 delta_view.push_back({k, leaf.get_value(), l2.get_value()});
911 delta_view.push_back({k, leaf.get_value()});
922 if(equalT()(leaf.get_key(), ip->
get_key()))
924 delta_view.push_back({k, leaf.get_value(), ip->
get_value()});
926 else if(!only_common)
928 delta_view.push_back({k, leaf.get_value()});
942 const bool only_common) const
953 gather_all(map, delta_view);
959 typedef std::pair<const nodet *, const nodet *> stack_itemt;
960 std::stack<stack_itemt> stack;
962 std::stack<std::size_t> level_stack;
971 if(map.shares_with(other.map))
974 stack.push(stack_itemt(&map, &other.map));
979 const stack_itemt &si = stack.top();
981 const nodet *ip1 = si.first;
982 const nodet *ip2 = si.second;
988 const std::size_t level = level_stack.top();
1002 const nodet &child = item.second;
1011 gather_all(child, delta_view);
1016 stack.push(stack_itemt(&child, p));
1017 level_stack.push(level + 1);
1027 const nodet &child = item.second;
1031 stack.push(stack_itemt(&child, ip2));
1036 level_stack.push(dummy_level);
1049 add_item_if_not_shared(*ip1, *ip2, level, delta_view, only_common);
1057 delta_view.push_back(
1060 else if(!only_common)
1075 if(l1.shares_with(*ip2))
1082 if(equalT()(k1, ip2->
get_key()))
1084 delta_view.push_back({k1, l1.get_value(), ip2->
get_value()});
1086 else if(!only_common)
1088 delta_view.push_back({k1, l1.get_value()});
1105 if(!l1.shares_with(*p))
1108 delta_view.push_back({k1, l1.get_value(), p->
get_value()});
1111 else if(!only_common)
1114 delta_view.push_back({k1, l1.get_value()});
1119 }
while(!stack.empty());
1124 const bool only_common) const
1127 get_delta_view(other, delta_view, only_common);
1135 std::size_t key =
hash()(k);
1141 std::size_t bit = key & mask;
1168 std::size_t key =
hash()(k);
1169 const nodet *ip = ↦
1174 std::size_t bit = key & mask;
1190 return equalT()(ip->
get_key(), k) ? ip :
nullptr;
1207 nodet *del =
nullptr;
1208 std::size_t del_bit = 0;
1210 std::size_t key =
hash()(k);
1215 std::size_t bit = key & mask;
1219 if(m.
size() > 1 || del ==
nullptr)
1250 if(std::next(ll.begin()) == ll.end())
1271 const std::size_t starting_level,
1272 const std::size_t key_suffix,
1273 const std::size_t bit_last,
1284 std::size_t key_existing =
hash()(leaf.
get_key());
1285 key_existing >>= chunk * starting_level;
1288 leaf_kept.
swap(leaf);
1295 std::size_t level = starting_level + 1;
1296 std::size_t key = key_suffix;
1298 key_existing >>= chunk;
1307 std::size_t bit_existing = key_existing & mask;
1308 std::size_t bit = key & mask;
1310 if(bit != bit_existing)
1320 l2.
make_leaf(k, std::forward<valueU>(m));
1329 key_existing >>= chunk;
1332 }
while(level < levels);
1352 std::size_t key =
hash()(k);
1358 std::size_t level = 0;
1362 std::size_t bit = key & mask;
1373 if(level < levels - 1)
1383 child.
place_leaf(k, std::forward<valueU>(m));
1403 migrate(level, key, bit, *ip, k, std::forward<valueU>(m));
1415 child.
place_leaf(k, std::forward<valueU>(m));
1427 nodet &lp = get_leaf_node(k);
1431 "values should not be replaced with equal values to maximize sharing");
1439 nodet &lp = get_leaf_node(k);
1447 "sharing_mapt::update should make some change. Consider using read-only "
1448 "method to check if an update is needed beforehand");
1454 const nodet *lp = get_leaf_node(k);
1469 SHARING_MAPT(
const std::size_t)::mask = 0xffff >> (16 - chunk);
1470 SHARING_MAPT(
const std::size_t)::levels = bits / chunk;