50struct std::hash<
mde::OperationNode> {
53 std::hash<mde::IndexValue>()(k.
left) ^
54 (std::hash<mde::IndexValue>()(k.
right) << 1);
70template<
typename OrderedSetT,
typename ElementT,
typename PropertyLess>
72 bool operator()(
const OrderedSetT *a,
const OrderedSetT *b)
const {
75 auto cursor_1 = a->begin();
76 const auto &cursor_end_1 = a->end();
77 auto cursor_2 = b->begin();
78 const auto &cursor_end_2 = b->end();
80 while (cursor_1 != cursor_end_1 && cursor_2 != cursor_end_2) {
81 if (less(*cursor_1, *cursor_2)) {
85 if (less(*cursor_2, *cursor_1)) {
93 return a->size() < b->size();
113 for (
const auto &value : *
k) {
136 if (
a->size() !=
b->size()) {
140 if (
a->size() == 0) {
172template<
typename T,
typename Hash,
typename Equal>
178 bool equal(
const T
a,
const T
b)
const {
202#define __MDE_EXCEPT(__msg) AssertError(__msg " [At: " __FILE__ ":" __MDE_STR(__LINE__) "]")
205#define __MDE_ASSERT(__cond, __msg_arg) \
206 { if (!(__cond)) { __MDE_EXCEPT(__msg_arg); } }
208#define __MDE_ASSERT(__cond, __msg_arg)
218template<
typename PropertySetT,
typename PropertyElementT>
220 if (
cont.size() == 1) {
226 typename PropertyElementT::Hash>
k;
231 throw AssertError(
"Supplied property set is not sorted.");
234 if (
k.count(
val) > 0) {
235 throw AssertError(
"Found duplicate key in given container.");
250#ifndef MDE_DISABLE_INTEGRITY_CHECKS
251#define MDE_PROPERTY_SET_INTEGRITY_VALID(__set) \
252 verify_property_set_integrity<PropertySet, PropertyElement>(__set);
254#define MDE_PROPERTY_SET_INTEGRITY_VALID(__set)
274#ifdef MDE_ENABLE_DEBUG
278#define MDE_PROPERTY_SET_INDEX_VALID(__index) { \
279 _Pragma("GCC diagnostic push"); \
280 _Pragma("GCC diagnostic ignored \"-Wtype-limits\"") \
281 if ((__index.value) < 0 || ((__index.value) > property_sets.size() - 1)) { \
282 throw __MDE_EXCEPT("Invalid index supplied"); \
284 _Pragma("GCC diagnostic pop") \
288#define MDE_PROPERTY_SET_PAIR_VALID(__index1, __index2) \
289 MDE_PROPERTY_SET_INDEX_VALID(__index1); \
290 MDE_PROPERTY_SET_INDEX_VALID(__index2);
293#define MDE_PROPERTY_SET_PAIR_UNEQUAL(__index1, __index2) \
294 if ((__index1) == (__index2)) { \
295 throw __MDE_EXCEPT("Equal set condition not handled by caller"); \
300#define MDE_PROPERTY_SET_INDEX_VALID(__index)
301#define MDE_PROPERTY_SET_PAIR_VALID(__index1, __index2)
302#define MDE_PROPERTY_SET_PAIR_UNEQUAL(__index1, __index2)
306#if defined(MDE_ENABLE_PARALLEL) && !defined(MDE_ENABLE_TBB)
307#define MDE_PARALLEL(__x) __x
309#define MDE_PARALLEL(__x)
312#ifdef MDE_ENABLE_EVICTION
313#define MDE_EVICTION(__x) __x
315#define MDE_EVICTION(__x)
327#define MDE_PUSH_ONE(__cont, __val) (__cont).push_back((__val))
339#define MDE_PUSH_RANGE(__cont, __start, __end) (__cont).insert((__cont).end(), (__start), (__end))
349#define MDE_REGISTER_SET_INTERNAL(__set, __cold) register_set<MDE_DISABLE_INTERNAL_INTEGRITY_CHECK>((__set), (__cold))
357template<
typename PropertyT>
382 typename PropertyLess,
383 typename PropertyHash,
384 typename PropertyEqual,
385 typename PropertyPrinter>
430 return PropertyLess()(
value,
b.value);
434 return PropertyEqual()(
value,
b.value);
438 return PropertyPrinter()(
value);
442 os <<
obj.to_string();
448 return PropertyHash()(
p.value);
463 return PropertyEqual()(
a.value,
b.value);
481#define MDE_BINARY_NESTED_OPERATION(__op_name) \
482 struct __NestingOperation_ ## __op_name { \
483 template<typename ArgIndex, typename MDE> \
484 void operator()(ArgIndex &ret, MDE &mde, const ArgIndex &c, const ArgIndex &d) { \
485 ret = mde . __op_name (c, d); \
500#define MDE_PERFORM_BINARY_NESTED_OPERATION(__op_name, __reflist, __arg1, __arg2) \
501 ((__arg1) . template apply<__NestingOperation_ ## __op_name>((__reflist), (__arg2)))
510template<
typename PropertyT,
typename ...ChildT>
527 template<std::
size_t ListIndex>
529 typename std::tuple_element<ListIndex, ChildValueList>::type;
541 typename PropertyLess,
542 typename PropertyHash,
543 typename PropertyEqual,
544 typename PropertyPrinter>
559 const PropertyT &
key,
578 const PropertyT &
key()
const {
598 template<
int ListIndex>
600 return std::get<ListIndex>(_value);
604 return std::get<0>(_value);
628 std::index_sequence<Indices...>)
const {
630 std::get<Indices>(
mde),
631 std::get<Indices>(_value),
648 template<
typename Operation>
657 std::make_index_sequence<num_children>{});
662 return PropertyLess()(_key,
b._key);
666 return PropertyEqual()(_key,
b._key);
671 s << PropertyPrinter()(_key);
674 [&
s](
auto&&...
args) {
675 ((
s <<
args.value <<
' '), ...);
682 os <<
obj.to_string();
688 return PropertyHash()(
p._key);
700 return PropertyEqual()(
a._key,
b._key) && (
a._value ==
b._value);
718template<
typename MapClass>
722 using Key =
typename Map::key_type;
727 using Accessor =
typename Map::const_accessor;
742 data.insert(std::move(
v));
753 typename Map::const_iterator
begin()
const {
757 typename Map::const_iterator
end()
const {
764 for (
auto i :
data) {
765 s <<
" {" <<
i.first <<
" -> " <<
i.second <<
"} \n";
775template<
typename MapClass>
779 using Key =
typename Map::key_type;
790 auto value =
data.find(key);
791 if (value ==
data.end()) {
794 return value->second;
800 data.insert(std::move(
v));
813 typename Map::const_iterator
begin()
const {
817 typename Map::const_iterator
end()
const {
825 for (
auto i : data) {
826 s <<
" {" <<
i.first <<
" -> " <<
i.second <<
"} \n";
844template<
typename K,
typename V>
845using InternalMap = MapAdapter<tbb::concurrent_hash_map<K, V>>;
849template<
typename K,
typename V>
869 size_t equal_hits = 0;
873 size_t subset_hits = 0;
877 size_t empty_hits = 0;
881 size_t cold_misses = 0;
885 size_t edge_misses = 0;
889 s <<
" " <<
"Hits : " << hits <<
"\n"
890 <<
" " <<
"Equal Hits : " << equal_hits <<
"\n"
891 <<
" " <<
"Subset Hits: " << subset_hits <<
"\n"
892 <<
" " <<
"Empty Hits : " << empty_hits <<
"\n"
893 <<
" " <<
"Cold Misses: " << cold_misses <<
"\n"
894 <<
" " <<
"Edge Misses: " << edge_misses <<
"\n";
909#ifdef MDE_ENABLE_PERFORMANCE_METRICS
910#define MDE_PERF_INC(__oper, __category) (perf[__MDE_STR(__oper)] . __category ++)
912#define MDE_PERF_INC(__oper, __category)
917 static constexpr const char* name =
"";
960 static constexpr const char *name = Config::name;
961 static constexpr Size BLOCK_SIZE = Config::BLOCK_SIZE;
962 static constexpr Size BLOCK_MASK = Config::BLOCK_MASK;
963 static constexpr Size BLOCK_SHIFT = Config::BLOCK_SHIFT;
975 return value == EMPTY_SET_VALUE;
979 return value ==
b.value;
983 return value !=
b.value;
987 return value <
b.value;
991 return value >
b.value;
995 return std::to_string(value);
999 os <<
obj.to_string();
1031 typename PropertyElement::Hash>;
1037 typename PropertyElement::FullEqual>;
1062#ifdef MDE_ENABLE_TBB
1080 using RefList =
typename Nesting::MDEReferenceList;
1085#ifdef MDE_ENABLE_PERFORMANCE_METRICS
1092 using Ptr =
typename PtrContainer::pointer;
1103#ifdef MDE_ENABLE_EVICTION
1104 return ptr.get() ==
nullptr;
1110#ifdef MDE_ENABLE_EVICTION
1114 "Tried to evict an already absent property set")
1120 "Tried to reassign when a property set is already present");
1124 void swap(PropertySetHolder &
p) {
1126 "Tried to reassign when a property set is already present");
1128 "Attempted to swap to a null pointer");
1135#if defined(MDE_ENABLE_TBB)
1137 class PropertySetStorage {
1142 mutable tbb::concurrent_vector<PropertySetHolder> data = {};
1154 PropertySetHolder &at_mutable(
const Index &idx)
const {
1155 return data.at(idx.value);
1158 const PropertySetHolder &at(
const Index &idx)
const {
1159 return data.at(idx.value);
1162 Index push_back(PropertySetHolder &&p) {
1163 auto it = data.push_back(std::move(p));
1164 return it - data.begin();
1178#elif defined(MDE_ENABLE_PARALLEL)
1180 class PropertySetStorage {
1185 mutable Vector<Vector<PropertySetHolder>> data = {};
1187 mutable RWMutex mutex;
1188 mutable RWMutex realloc_mutex;
1190 std::atomic<Size> total_elems = 0;
1191 std::atomic<Size> block_base = 0;
1194 PropertySetStorage() {
1196 data.back().reserve(BLOCK_SIZE);
1208 PropertySetHolder &at_mutable(
const Index &idx)
const {
1209 ReadLock m(realloc_mutex);
1210 if (idx.value >= block_base) {
1211 return data.back().at(idx.value & BLOCK_MASK);
1215 .at((idx.value & (~BLOCK_MASK)) >> BLOCK_SHIFT)
1216 .at(idx.value & BLOCK_MASK);
1220 const PropertySetHolder &at(
const Index &idx)
const {
1221 ReadLock m(realloc_mutex);
1222 if (idx.value >= block_base) {
1223 return data.back().at(idx.value & BLOCK_MASK);
1227 .at((idx.value & (~BLOCK_MASK)) >> BLOCK_SHIFT)
1228 .at(idx.value & BLOCK_MASK);
1232 Index push_back(PropertySetHolder &&p) {
1234 __MDE_ASSERT(!data.empty(),
"Internal error: no storage blocks avaialable.");
1235 if (data.back().size() >= BLOCK_SIZE) {
1236 WriteLock r(realloc_mutex);
1238 data.back().reserve(BLOCK_SIZE);
1239 block_base += BLOCK_SIZE;
1241 data.back().push_back(std::move(p));
1243 return Index(total_elems - 1);
1279 return data.at(
idx.value);
1283 return data.at(
idx.value);
1287 data.push_back(std::move(
p));
1288 return data.size() - 1;
1328 subsets.insert({{
b.value,
a.value},
SUPERSET});
1330 subsets.insert({{
a.value,
b.value},
SUBSET});
1338 property_sets.clear();
1339 property_set_map.
clear();
1341 intersections.clear();
1342 differences.clear();
1353 return i.is_empty();
1376 auto i = subsets.find({
a.value,
b.value});
1378 if (!
i.is_present()) {
1402 if (!
result.is_present()) {
1406 property_set_map.
insert(std::make_pair(property_sets.at(
ret).get(),
ret.value));
1411 property_sets.at_mutable(result.get()).swap(new_set);
1412 return Index(result.get());
1436 if (!
result.is_present()) {
1440 property_set_map.
insert(std::make_pair(property_sets.at(
ret).get(),
ret.value));
1446 property_sets.at_mutable(result.get()).swap(new_set);
1448 return Index(result.get());
1468 typename PropertyElement::Hash,
1476 std::sort(
c.begin(),
c.end());
1479 template <
bool disable_
integrity_check = false>
1489 if (!
result.is_present()) {
1494 property_set_map.
insert(std::make_pair(property_sets.at(
ret).get(),
ret.value));
1498 property_sets.at_mutable(result.get()).reassign(new PropertySet(c));
1499 return Index(result.get());
1507 template <
bool disable_
integrity_check = false>
1517 if (!
result.is_present()) {
1522 property_set_map.
insert(std::make_pair(property_sets.at(
ret).get(),
ret.value));
1528 property_sets.at_mutable(result.get()).reassign(new PropertySet(c));
1530 return Index(result.get());
1539 template <
bool disable_
integrity_check = false>
1549 if (!
result.is_present()) {
1554 property_set_map.
insert(std::make_pair(property_sets.at(
ret).get(),
ret.value));
1558 property_sets.at_mutable(result.get()).reassign(new PropertySet(c));
1559 return Index(result.get());
1567 template <
bool disable_
integrity_check = false>
1577 if (!
result.is_present()) {
1582 property_set_map.
insert(std::make_pair(property_sets.at(
ret).get(),
ret.value));
1588 property_sets.at_mutable(result.get()).reassign(new PropertySet(c));
1590 return Index(result.get());
1599 template<
typename Iterator,
bool disable_
integrity_check = false>
1611 if (!
result.is_present()) {
1615 property_set_map.
insert(std::make_pair(property_sets.at(
ret).get(),
ret.value));
1619 property_sets.at_mutable(result.get()).reassign(std::move(new_set));
1620 return Index(result.get());
1628 template<
typename Iterator,
bool disable_
integrity_check = false>
1640 if (!
result.is_present()) {
1644 property_set_map.
insert(std::make_pair(property_sets.at(
ret).get(),
ret.value));
1649 property_sets.at_mutable(result.get()).reassign(std::move(new_set));
1651 return Index(result.get());
1660#ifdef MDE_ENABLE_EVICTION
1661 bool is_evicted(
const Index &index)
const {
1662 return property_sets.at(index.value).is_evicted();
1666#ifdef MDE_ENABLE_EVICTION
1667 void evict_set(
const Index &index) {
1669 "Tried to evict the empty set");
1670 property_sets.at_mutable(index.value).evict();
1683#if defined(MDE_DEBUG) && defined(MDE_ENABLE_EVICTION)
1685 "Tried to access an evicted set");
1687 return *property_sets.at(index.
value).get();
1697 return property_sets.size();
1708 if (index == EMPTY_SET_VALUE) {
1711 return get_value(index).size();
1768 if (is_empty(index)) {
1776 if (equal_key(
i,
p)) {
1783 long int high =
s.size() - 1;
1788 if (equal_key(
s[
mid],
p)) {
1790 }
else if (less_key(
s[
mid],
p)) {
1811 if (is_empty(index)) {
1819 if (equal_key(
i,
prop)) {
1825 std::int64_t
low = 0;
1826 std::int64_t
high =
s.size() - 1;
1832 }
else if (less_key(
s[
mid],
prop)) {
1865 }
else if (is_empty(
_b)) {
1883 auto result = unions.find({
a.value,
b.value});
1909 if constexpr (Nesting::is_nested) {
1932 property_sets.at_mutable(ret).reassign(new PropertySet(std::move(new_set)));
1936 unions.insert({{
a.value,
b.value},
ret.value});
1939 store_subset(
b,
ret);
1940 }
else if (
ret ==
b) {
1941 store_subset(
a,
ret);
1943 store_subset(
a,
ret);
1944 store_subset(
b,
ret);
1972 return set_union(
a, register_set_single(
b));
1991 return Index(EMPTY_SET_VALUE);
1996 return Index(EMPTY_SET_VALUE);
1997 }
else if (is_empty(
b)) {
2002 auto result = differences.find({
a.value,
b.value});
2028 if constexpr (Nesting::is_nested) {
2045 property_sets.at_mutable(ret).reassign(new PropertySet(std::move(new_set)));
2048 differences.insert({{
a.value,
b.value},
ret.value});
2051 store_subset(
ret,
a);
2053 intersections.insert({
2055 std::min(
a.value,
b.value),
2056 std::max(
a.value,
b.value)
2057 }, EMPTY_SET_VALUE});
2085 return set_difference(
a, register_set_single(
b));
2131 if (is_empty(
_a) || is_empty(
_b)) {
2133 return Index(EMPTY_SET_VALUE);
2149 auto result = intersections.find({
a.value,
b.value});
2170 if constexpr (Nesting::is_nested) {
2188 property_sets.at_mutable(ret).reassign(new PropertySet(std::move(new_set)));
2191 intersections.insert({{
a.value,
b.value},
ret.value});
2194 store_subset(
ret,
a);
2195 }
else if (
ret !=
b) {
2196 store_subset(
ret,
b);
2198 store_subset(
ret,
a);
2199 store_subset(
ret,
b);
2257 property_sets.at_mutable(ret).reassign(new PropertySet(std::move(new_set)));
2260 cache.insert(std::make_pair(
s.value,
ret.value));
2284 std::stringstream
s;
2287 s <<
p.to_string() <<
" ";
2295 return property_set_to_string(get_value(
idx));
2298#ifdef MDE_ENABLE_SERIALIZATION
2304 virtual slz::JSON operations_to_json()
const {
2305 slz::JSON ret = slz::JSON::object();
2306 ret[
"unions"] = slz::binary_operation_map_to_json(unions);
2307 ret[
"intersections"] = slz::binary_operation_map_to_json(intersections);
2308 ret[
"differences"] = slz::binary_operation_map_to_json(differences);
2309 ret[
"subsets"] = slz::binary_operation_map_to_json(subsets);
2313 virtual void operations_from_json(
const slz::JSON &obj) {
2314 std::cout << obj.dump() << std::endl;
2315 slz::binary_operation_map_from_json(unions, obj[
"unions"]);
2316 slz::binary_operation_map_from_json(intersections, obj[
"intersections"]);
2317 slz::binary_operation_map_from_json(differences, obj[
"differences"]);
2318 slz::binary_operation_map_from_json(subsets, obj[
"subsets"]);
2321 template<
typename Serializer =
2322 slz::DefaultValueSerializer<PropertyT>>
2323 slz::JSON to_json(Serializer &s)
const {
2324 slz::JSON ret = slz::JSON::object();
2326 if constexpr (Nesting::is_nested) {
2327 ret[
"property_sets"] =
2328 slz::storage_array_to_json_nested(property_sets, s);
2330 ret[
"property_sets"] =
2331 slz::storage_array_to_json(property_sets, s);
2334 ret[
"operations"] = operations_to_json();
2339 template<
typename Serializer =
2340 slz::DefaultValueSerializer<PropertyT>>
2341 slz::JSON to_json()
const {
2342 auto s = Serializer();
2346 template<
typename Serializer =
2347 slz::DefaultValueSerializer<PropertyT>>
2348 void load_from_json(
const slz::JSON &obj, Serializer &s) {
2350 operations_from_json(obj[
"operations"]);
2351 if constexpr (Nesting::is_nested) {
2352 slz::register_storage_from_json_nested(*
this, obj[
"property_sets"], s);
2354 slz::register_storage_from_json(*
this, obj[
"property_sets"], s);
2358 template<
typename Serializer =
2359 slz::DefaultValueSerializer<PropertyT>>
2360 void load_from_json(
const slz::JSON &obj) {
2361 auto s = Serializer();
2362 load_from_json(obj, s);
2371 std::stringstream
s;
2375 s <<
" " <<
"Unions: " <<
"(Count: " << unions.size() <<
")\n";
2376 s << unions.to_string();
2379 s <<
" " <<
"Differences:" <<
"(Count: " << differences.size() <<
")\n";
2380 s << differences.to_string();
2383 s <<
" " <<
"Intersections: " <<
"(Count: " << intersections.size() <<
")\n";
2384 s << intersections.to_string();
2387 s <<
" " <<
"Subsets: " <<
"(Count: " << subsets.size() <<
")\n";
2388 for (
auto i : subsets) {
2389 s <<
" " <<
i.first <<
" -> " << (
i.second ==
SUBSET ?
"sub" :
"sup") <<
"\n";
2393 s <<
" " <<
"PropertySets: " <<
"(Count: " << property_sets.size() <<
")\n";
2394 for (
size_t i = 0;
i < property_sets.size();
i++) {
2396 <<
i <<
" : " << property_set_to_string(*property_sets.at(
i).get()) <<
"\n";
2408#ifdef MDE_ENABLE_PERFORMANCE_METRICS
2417 std::stringstream
s;
2418 s <<
"Performance Profile: \n";
2419 for (
auto &
p : perf) {
2420 s <<
p.first <<
"\n"
2421 <<
p.second.to_string() <<
"\n";
2433#define MDE_PROPERTY_INDEX_VALID(__index) { \
2434 _Pragma("GCC diagnostic push"); \
2435 _Pragma("GCC diagnostic ignored \"-Wtype-limits\"") \
2436 if ((__index.value) < 0 || ((__index.value) > property_list.size() - 1)) { \
2437 throw __MDE_EXCEPT("Invalid index supplied"); \
2439 _Pragma("GCC diagnostic pop") \
2460 typename PropertyHash = DefaultHash<PropertyT>,
2461 typename PropertyEqual = DefaultEqual<PropertyT>,
2462 typename PropertyPrinter = DefaultPrinter<PropertyT>>
2474 return value == EMPTY_SET_VALUE;
2478 return value ==
b.value;
2482 return value !=
b.value;
2486 return value <
b.value;
2490 return value >
b.value;
2494 return std::to_string(value);
2498 os <<
obj.to_string();
2511 return PropertyHash()(*p);
2517 return PropertyEqual()(*
a, *
b);
2544 auto cursor = property_map.find(&
c);
2546 if (
cursor == property_map.end()) {
2549 property_list.push_back(std::move(
new_value));
2551 property_map.insert(std::make_pair(property_list[
ret].get(),
ret));
2558 auto cursor = property_map.find(&
c);
2560 if (
cursor == property_map.end()) {
2563 property_list.push_back(std::move(
new_value));
2565 property_map.insert(std::make_pair(property_list[
ret].get(),
ret));
2579 auto cursor = property_map.find(
c);
2581 if (
cursor == property_map.end()) {
2583 property_list.push_back(std::move(
new_value));
2585 property_map.insert(std::make_pair(property_list[
ret].get(),
ret));
2593 return property_list.size();
2598 return *property_list[
id.value].get();
2607 return property_list[
id.value].get();
2611 std::stringstream
s;
2612 s <<
"Deduplicator Stored Data: "
2613 <<
"(Size = " << property_list.size() <<
") {" << std::endl;
2614 for (
Size i = 0;
i < get_property_count();
i++) {
2615 s <<
" " <<
i <<
": "
2616 << PropertyPrinter()(get_value(
i)) << std::endl;
2618 s <<
"}" << std::endl;
const PropertySetHolder & at(const Index &idx) const
Index push_back(PropertySetHolder &&p)
PropertySetHolder & at_mutable(const Index &idx) const
Retuns a mutable reference to the property set holder at a given set index. This is useful for evicti...
The main MDENode structure. This class can be used as-is with a type or derived for additional functi...
virtual void clear()
Removes all data from the MDE.
static bool less_key(const PropertyElement &a, const PropertyElement &b)
typename Config::PropertyHash PropertyHash
OperationMap< OperationNode > BinaryOperationMap
static bool equal(const PropertyElement &a, const PropertyElement &b)
Equality comparator for operations. You MUST use this instead of directly using anything else like "<...
HashMap< String, OperationPerf > perf
void clear_and_initialize()
Resets state of the MDE to the default.
typename Nesting::MDEReferenceList RefList
SetEqual< PropertySet, PropertyElement, typename PropertyElement::FullEqual > PropertySetFullEqual
static bool less(const PropertyElement &a, const PropertyElement &b)
Less than comparator for operations. You MUST use this instead of directly using anything else like "...
Size size_of(const Index &index) const
Returns the size of the set at index
void store_subset(const Index &a, const Index &b)
Stores index a as the subset of index b if a < b, else stores index a as the superset of index b
bool is_empty(const Index &i) const
MDENode(RefList reflist={})
SubsetRelation is_subset(const Index &a, const Index &b) const
Returns whether we currently know whether a is a subset or a superset of b.
const PropertySet & get_value(const Index &index) const
Gets the actual property set specified by index.
Index register_set(Iterator begin, Iterator end)
friend std::ostream & operator<<(std::ostream &os, const MDENode &obj)
Index register_set(PropertySet &&c, bool &cold)
OperationMap< IndexValue > UnaryOperationMap
void prepare_vector_set(PropertySet &c)
Index register_set(Iterator begin, Iterator end, bool &cold)
typename Config::PropertyPrinter PropertyPrinter
Index set_remove_single_key(const Index &a, const PropertyT &p)
Removes a single element from a given set if the "key" element matches.
Index register_set_single(const PropertyElement &c, bool &cold)
Inserts a (or gets an existing) single-element set into the property set storage, and reports whether...
static bool equal_key(const PropertyElement &a, const PropertyElement &b)
static bool equal_key(const PropertyElement &a, const PropertyT &b)
bool contains(const Index &index, const PropertyElement &prop) const
Determines whether the property set at index contains the element prop or not.
typename Config::PropertyT PropertyT
String property_set_to_string(const Index &idx) const
static String property_set_to_string(const PropertySet &set)
Converts the property set to a string.
static bool less_key(const PropertyElement &a, const PropertyT &b)
SetHash< PropertySet, PropertyElement, typename PropertyElement::Hash > PropertySetHash
String dump_perf() const
Dumps performance information as a string.
Index register_set_single(const PropertyElement &c)
Inserts a (or gets an existing) single-element set into property set storage.
typename Nesting::template PropertyElement< PropertyLess, PropertyHash, PropertyEqual, PropertyPrinter > PropertyElement
String dump() const
Dumps the current state of the MDE to a string.
Index set_insert_single(const Index &a, const PropertyElement &b)
Inserts a single element from a given set (and returns the index of the set). This is a wrapper over ...
Index register_set(const PropertySet &c, bool &cold)
Index register_set(PropertySet &&c)
Size property_set_count() const
Returns the total number of property sets currently in the MDE.
Index set_remove_single(const Index &a, const PropertyElement &b)
Removes a single element from a given set (and returns the index of the set). This is a wrapper over ...
Index set_filter(Index s, std::function< bool(const PropertyElement &)> filter_func, UnaryOperationMap &cache)
Filters a set based on a criterion function. This is supposed to be an abstract filtering mechanism t...
typename Config::PropertyLess PropertyLess
typename Config::PropertyEqual PropertyEqual
OptionalRef< PropertyElement > find_key(const Index &index, const PropertyT &p) const
Finds a property element in the set based on the key provided.
std::vector< PropertyElement > PropertySet
PerformanceStatistics stat
Index register_set(const PropertySet &c)
typename Map::mapped_type MappedType
Optional< MappedType > find(const Key &key) const
Map::const_iterator begin() const
void insert(KeyValuePair &&v)
typename Map::key_type Key
Map::const_iterator end() const
typename Map::value_type KeyValuePair
Describes an optional reference of some type T. The value may either be present or absent.
Describes an optional of some type T. The value may either be present or absent.
static Optional absent()
Explicitly creates an absent value.
#define __MDE_ASSERT(__cond, __msg_arg)
#define MDE_PARALLEL(__x)
#define MDE_PROPERTY_SET_INDEX_VALID(__index)
Check whether the index is a valid index within the property set.
#define MDE_BINARY_NESTED_OPERATION(__op_name)
Declares a struct that enables the recursive/nesting behaviour of an operation.
#define MDE_PROPERTY_SET_INTEGRITY_VALID(__set)
Macro and switch for verify_property_set_integrity inside MDE.
#define MDE_PUSH_ONE(__cont, __val)
Pushes one element to a PropertySet. Use this when implementing operations.
#define MDE_PROPERTY_INDEX_VALID(__index)
#define MDE_REGISTER_SET_INTERNAL(__set, __cold)
Registers a set with behaviours defined for internal processing.
#define MDE_PROPERTY_SET_PAIR_UNEQUAL(__index1, __index2)
Check whether the pair of indexes are unequal. Used for sanity checking.
#define MDE_PERF_INC(__oper, __category)
Increments the invocation count of the given category and operator.
#define MDE_EVICTION(__x)
#define MDE_PROPERTY_SET_PAIR_VALID(__index1, __index2)
Check whether the pair of indexes is a valid within the property set.
#define MDE_PERFORM_BINARY_NESTED_OPERATION(__op_name, __reflist, __arg1, __arg2)
Actually enables the nesting. this must be placed in the operation body where the nested behaviour is...
#define MDE_PUSH_RANGE(__cont, __start, __end)
Pushes a range of elements to a PropertySet using an iterator. Use this when implementing operations.
Any common components go into this file.
#define MDE_DEFAULT_BLOCK_MASK
#define MDE_DEFAULT_BLOCK_SIZE
#define MDE_DEFAULT_BLOCK_SHIFT
#define MDE_SORTED_VECTOR_BINARY_SEARCH_THRESHOLD
SubsetRelation
Used to store a subset relation between two set indices. Because the index pair must be in sorted ord...
MapAdapter< HashMap< K, V > > InternalMap
std::ostream & operator<<(std::ostream &os, const OperationNode &op)
std::hash< T > DefaultHash
InternalMap< T, IndexValue > OperationMap
Enables basic code-based profiling metrics in MDE.
#define __mde_calc_functime(__stat)
Creates a timer object to capture duration of the current function when going out of scope.
Struct that is thrown on an assertion failure.
AssertError(const std::string &message)
Size operator()(const Index &idx) const
Index returned by the class. Being defined inside the class ensures type safety and possible future e...
bool operator<(const Index &b) const
bool operator!=(const Index &b) const
bool operator==(const Index &b) const
friend std::ostream & operator<<(std::ostream &os, const Index &obj)
Index(IndexValue idx=EMPTY_SET_VALUE)
bool operator>(const Index &b) const
Size operator()(const PropertyT *a, const PropertyT *b) const
Size operator()(const PropertyT *p) const
An straightforward deduplicator for scalar values. It does not implement any special operations besid...
Size get_property_count() const
const PropertyT * get_value_ptr(Index id) const
Index register_value(PropertyT &&c)
const PropertyT & get_value(Index id) const
Index register_value(PropertyT &c)
Inserts a (or gets an existing) element into property storage.
std::unordered_map< PropertyT *, IndexValue, PropertyPtrHash, PropertyPtrEqual > PropertyMap
Index register_ptr(PropertyT *c)
DefaultHash< PropertyT > PropertyHash
DefaultPrinter< PropertyT > PropertyPrinter
DefaultEqual< PropertyT > PropertyEqual
DefaultLess< PropertyT > PropertyLess
Size operator()(const Index &idx) const
Index returned by an operation. Being defined inside the class ensures type safety and possible futur...
bool operator<(const Index &b) const
bool operator!=(const Index &b) const
friend std::ostream & operator<<(std::ostream &os, const Index &obj)
bool operator==(const Index &b) const
bool operator>(const Index &b) const
Index(IndexValue idx=EMPTY_SET_VALUE)
UniquePointer< PropertySet > PtrContainer
typename PtrContainer::pointer Ptr
PropertySetHolder(Ptr &&p)
This forces a comparison of both the key and the value instead of only the key. Required in instances...
bool operator()(const PropertyElement &a, const PropertyElement &b) const
Size operator()(const PropertyElement &p) const
Type for the elements for a property set in the nested. The template arguments are for the 'key' type...
const ChildValueListIndexType< ListIndex > & value() const
Gets the first object in the tuple of the nested values.
PropertyT InterfaceValueType
Value type is made available here if required by user.
const ChildValueListIndexType< 0 > & value0() const
bool operator==(const PropertyElement &b) const
const ChildValueList & get_value() const
Gets the nested value. It returns a tuple of values containing indices to each of the nested sets of ...
bool operator<(const PropertyElement &b) const
PropertyT InterfaceKeyType
Key type is made available here if required by user.
PropertyElement apply(const MDEReferenceList &mde, const PropertyElement &arg) const
Performs the "apply" operation on the list of nested children specified by the Operation parameter.
const PropertyT & key() const
Gets the 'key' value. Synonymous with get_key.
friend std::ostream & operator<<(std::ostream &os, const PropertyElement &obj)
const PropertyT & get_key() const
Gets the 'key' value.
void apply_internal(ChildValueList &ret, const MDEReferenceList &mde, const ChildValueList &arg_value, std::index_sequence< Indices... >) const
Actually performs the template "apply" operation. This sets up template syntax to go over each elemen...
PropertyElement(const PropertyT &key, const ChildValueList &value)
Describes the standard nesting structure. Act as "non-leaf" nodes in a tree of nested MDEs.
static constexpr Size num_children
std::tuple< typename ChildT::Index... > ChildValueList
std::tuple< ChildT &... > MDEReferenceList
Reference list. References to all the nested MDEs are presented here.
typename std::tuple_element< ListIndex, ChildValueList >::type ChildValueListIndexType
Gets the type of a particular index in the child value list tuple.
static constexpr bool is_nested
Compile-time value that says this is nested.
This forces a comparison of both the key and the value instead of only the key. Required in instances...
bool operator()(const PropertyElement &a, const PropertyElement &b) const
Size operator()(const PropertyElement &p) const
Base-case type for the elements for a property set. The template arguments are for the 'key' type.
PropertyT InterfaceKeyType
Key type is made available here if required by user.
bool operator<(const PropertyElement &b) const
bool operator==(const PropertyElement &b) const
PropertyT InterfaceValueType
Value type is made available here if required by user.
friend std::ostream & operator<<(std::ostream &os, const PropertyElement &obj)
const PropertyT & get_key() const
Gets the 'key' value.
PropertyElement(const PropertyT &value)
const PropertyT & get_value() const
Gets the nested value. In the base case it simply returns the key.
PropertyElement apply() const
Performs an "apply" operation. In the base case it is an identity operation and does not do anything.
The nesting type for non-nested data structures. Act as "leaf" nodes in a tree of nested MDEs.
std::tuple<> MDEReferenceList
Reference list. In the base case, there are no child MDEs.
static constexpr Size num_children
Compile-time value that says there are no nested children.
std::tuple<> ChildValueList
Child value list. In the base case, there are no child MDEs.
static constexpr bool is_nested
Compile-time value that says this is not nested.
This struct contains the information about the operands of an operation (union, intersection,...
bool operator<(const OperationNode &op) const
std::string to_string() const
bool operator==(const OperationNode &op) const
Operation performance Statistics.
Generic Equality comparator for set types.
bool operator()(const SetT *a, const SetT *b) const
Size operator()(const SetT *k) const
Generic Less-than comparator for set types.
bool operator()(const OrderedSetT *a, const OrderedSetT *b) const
Thrown if code region is unreachable.
Unreachable(const std::string &message="Hit a branch marked as unreachable.")
mde::Size operator()(const mde::OperationNode &k) const