LatticeHashForest
Loading...
Searching...
No Matches
lhf.hpp
Go to the documentation of this file.
1
6#ifndef LHF_HPP
7#define LHF_HPP
8
9#include <cstddef>
10#include <iostream>
11#include <memory>
12#include <sstream>
13#include <stdexcept>
14#include <tuple>
15#include <utility>
16#include <vector>
17#include <map>
18#include <unordered_map>
19#include <set>
20#include <unordered_set>
21#include <functional>
22#include <algorithm>
23#include <string>
24
25#include "lhf_config.hpp"
26#include "profiling.hpp"
27
28namespace lhf {
29
30#ifdef LHF_ENABLE_DEBUG
31#define LHF_DEBUG(x) { x };
32#else
33#define LHF_DEBUG(x)
34#endif
35
36template<typename T>
37using UniquePointer = std::unique_ptr<T>;
38
39template<typename T>
40using Vector = std::vector<T>;
41
42template<typename K, typename V>
43using HashMap = std::unordered_map<K, V>;
44
45template<typename K, typename V>
46using OrderedMap = std::map<K, V>;
47
48template<typename T>
49using HashSet = std::unordered_set<T>;
50
51template<typename T>
52using OrderedSet = std::set<T>;
53
54using String = std::string;
55
56using IndexValue = std::size_t;
57
58template<typename T>
59using DefaultLess = std::less<T>;
60
61template<typename T>
62using DefaultHash = std::hash<T>;
63
64template<typename T>
65using DefaultEqual = std::equal_to<T>;
66
67template<typename T>
70 std::stringstream s;
71 s << x;
72 return s.str();
73 }
74};
75
79struct AbsentValueAccessError : public std::invalid_argument {
80 AbsentValueAccessError(const std::string &message):
81 std::invalid_argument(message.c_str()) {}
82};
83
90template<typename T>
91class Optional {
92 const T *value = nullptr;
93 Optional(): value(nullptr) {}
94
95public:
96 Optional(const T &value): value(value) {}
97
99 static Optional absent() {
100 return Optional();
101 }
102
104 bool is_present() {
105 return value != nullptr;
106 }
107
109 const T &get() {
110 if (value) {
111 return value;
112 } else {
113 throw AbsentValueAccessError("Tried to access an absent value. "
114 "A check is likely missing.");
115 }
116 }
117};
118
129
130
131// The index of the empty set. The first set that will ever be inserted
132// in the property set value storage is the empty set.
133static const constexpr std::size_t EMPTY_SET_VALUE = 0;
134
147template<typename T, typename Hash = DefaultHash<T>>
148inline std::size_t compose_hash(const std::size_t prev, T next) {
149 return prev ^ (Hash()(next) + 0x9e3779b9 + (prev << 6) + (prev >> 2));
150}
151
159
160 std::string to_string() const {
161 std::stringstream s;
162 s << "(" << left << "," << right << ")";
163 return s.str();
164 }
165
166 bool operator<(const OperationNode &op) const {
167 return (left < op.left) || (right < op.right);
168 }
169
170 bool operator==(const OperationNode &op) const {
171 return (left == op.left) && (right == op.right);
172 }
173};
174
175inline std::ostream &operator<<(std::ostream &os, const OperationNode &op) {
176 return os << op.to_string();
177}
178
179};
180
181/************************** START GLOBAL NAMESPACE ****************************/
182
183template <>
184struct std::hash<lhf::OperationNode> {
185 std::size_t operator()(const lhf::OperationNode& k) const {
186 return
187 std::hash<lhf::IndexValue>()(k.left) ^
188 (std::hash<lhf::IndexValue>()(k.right) << 1);
189 }
190};
191
192/************************** END GLOBAL NAMESPACE ******************************/
193
194namespace lhf {
195
204template<typename OrderedSetT, typename ElementT, typename PropertyLess>
205struct SetLess {
206 bool operator()(const OrderedSetT *a, const OrderedSetT *b) const {
207 PropertyLess less;
208
209 auto cursor_1 = a->begin();
210 const auto &cursor_end_1 = a->end();
211 auto cursor_2 = b->begin();
212 const auto &cursor_end_2 = b->end();
213
214 while (cursor_1 != cursor_end_1 && cursor_2 != cursor_end_2) {
215 if (less(*cursor_1, *cursor_2)) {
216 return true;
217 }
218
219 if (less(*cursor_2, *cursor_1)) {
220 return false;
221 }
222
223 cursor_1++;
224 cursor_2++;
225 }
226
227 return a->size() < b->size();
228 }
229};
230
239template<
240 typename SetT,
241 typename ElementT,
242 typename PropertyEqual = DefaultEqual<ElementT>>
243struct SetEqual {
244 inline bool operator()(const SetT *a, const SetT *b) const {
245 PropertyEqual eq;
246 if (a->size() != b->size()) {
247 return false;
248 }
249
250 if (a->size() == 0) {
251 return true;
252 }
253
254 auto cursor_1 = a->begin();
255 const auto &cursor_end_1 = a->end();
256 auto cursor_2 = b->begin();
257
258 while (cursor_1 != cursor_end_1) {
259 if (!eq(*cursor_1, *cursor_2)) {
260 return false;
261 }
262
263 cursor_1++;
264 cursor_2++;
265 }
266
267 return true;
268 }
269};
270
279template<
280 typename SetT,
281 typename ElementT,
282 typename ElementHash = DefaultHash<ElementT>>
283struct SetHash {
284 std::size_t operator()(const SetT *k) const {
285 // Adapted from boost::hash_combine
286 size_t hash_value = 0;
287 for (const auto &value : *k) {
288 hash_value = compose_hash<ElementT, ElementHash>(hash_value, value);
289 }
290
291 return hash_value;
292 }
293};
294
298struct AssertError : public std::invalid_argument {
299 AssertError(const std::string &message):
300 std::invalid_argument(message.c_str()) {}
301};
302
306struct Unreachable : public std::runtime_error {
307 Unreachable(const std::string &message = "Hit a branch marked as unreachable."):
308 std::runtime_error(message.c_str()) {}
309};
310
311#define ____LHF__STR(x) #x
312#define __LHF_STR(x) ____LHF__STR(x)
313#define __LHF_EXCEPT(x) AssertError(x " [At: " __FILE__ ":" __LHF_STR(__LINE__) "]")
314
321template<typename PropertySetT, typename PropertyElementT>
322static inline void verify_property_set_integrity(const PropertySetT &cont) {
323 if (cont.size() == 1) {
324 return;
325 }
326
327 std::unordered_set<
328 PropertyElementT,
329 typename PropertyElementT::Hash> k;
330 const PropertyElementT *prev_val = nullptr;
331
332 for (const PropertyElementT &val : cont) {
333 if (prev_val && !(*prev_val < val)) {
334 throw AssertError("Supplied property set is not sorted.");
335 }
336
337 if (k.count(val) > 0) {
338 throw AssertError("Found duplicate key in given container.");
339 } else {
340 k.insert(val);
341 }
342
343 prev_val = &val;
344 }
345}
346
353#ifndef LHF_DISABLE_INTEGRITY_CHECKS
354#define LHF_PROPERTY_SET_INTEGRITY_VALID(__set) \
355 verify_property_set_integrity<PropertySet, PropertyElement>(__set);
356#else
357#define LHF_PROPERTY_SET_INTEGRITY_VALID(__set)
358#endif
359
360
377#ifdef LHF_ENABLE_DEBUG
378
381#define LHF_PROPERTY_SET_INDEX_VALID(__index) { \
382 _Pragma("GCC diagnostic push"); \
383 _Pragma("GCC diagnostic ignored \"-Wtype-limits\"") \
384 if ((__index.value) < 0 || ((__index.value) > property_sets.size() - 1)) { \
385 throw __LHF_EXCEPT("Invalid index supplied"); \
386 } \
387 _Pragma("GCC diagnostic pop") \
388}
389
391#define LHF_PROPERTY_SET_PAIR_VALID(__index1, __index2) \
392 LHF_PROPERTY_SET_INDEX_VALID(__index1); \
393 LHF_PROPERTY_SET_INDEX_VALID(__index2);
394
396#define LHF_PROPERTY_SET_PAIR_UNEQUAL(__index1, __index2) \
397 if ((__index1) == (__index2)) { \
398 throw __LHF_EXCEPT("Equal set condition not handled by caller"); \
399 }
400
401#else
402
403#define LHF_PROPERTY_SET_INDEX_VALID(__index)
404#define LHF_PROPERTY_SET_PAIR_VALID(__index1, __index2)
405#define LHF_PROPERTY_SET_PAIR_UNEQUAL(__index1, __index2)
406
407#endif
408
418#define LHF_PUSH_ONE(__cont, __val) (__cont).push_back((__val))
419
430#define LHF_PUSH_RANGE(__cont, __start, __end) (__cont).insert((__cont).end(), (__start), (__end))
431
432
440#define LHF_REGISTER_SET_INTERNAL(__set, __cold) register_set<LHF_DISABLE_INTERNAL_INTEGRITY_CHECK>((__set), (__cold))
441
448template<typename PropertyT>
451 static constexpr bool is_nested = false;
452
454 static constexpr std::size_t num_children = 0;
455
457 struct Empty {
458 Empty() {}
459 };
460
463
466
476 template<
477 typename PropertyLess,
478 typename PropertyHash,
479 typename PropertyEqual,
480 typename PropertyPrinter>
483 using InterfaceKeyType = PropertyT;
484
486 using InterfaceValueType = PropertyT;
487
488 PropertyT value;
489
490 PropertyElement(const PropertyT &value): value(value) {}
491
497 const PropertyT &get_key() const {
498 return value;
499 }
500
507 const PropertyT &get_value() const {
508 return value;
509 }
510
518 return *this;
519 }
520
521 bool operator<(const PropertyElement &b) const {
522 return PropertyLess()(value, b.value);
523 }
524
525 bool operator==(const PropertyElement &b) const {
526 return PropertyEqual()(value, b.value);
527 }
528
530 return PropertyPrinter()(value);
531 }
532
533 struct Hash {
534 std::size_t operator()(const PropertyElement &p) const {
535 return PropertyHash()(p.value);
536 }
537 };
538
548 struct FullEqual {
549 bool operator()(const PropertyElement &a, const PropertyElement &b) const {
550 return PropertyEqual()(a.value, b.value);
551 }
552 };
553 };
554
555};
556
567#define LHF_BINARY_NESTED_OPERATION(__op_name) \
568 struct __NestingOperation_ ## __op_name { \
569 template<typename ArgIndex, typename LHF> \
570 void operator()(ArgIndex &ret, LHF &lhf, const ArgIndex &c, const ArgIndex &d) { \
571 ret = lhf . __op_name (c, d); \
572 } \
573 };
574
586#define LHF_PERFORM_BINARY_NESTED_OPERATION(__op_name, __reflist, __arg1, __arg2) \
587 ((__arg1) . template apply<__NestingOperation_ ## __op_name>((__reflist), (__arg2)))
588
596template<typename PropertyT, typename ...ChildT>
599 static constexpr bool is_nested = true;
600
603 static constexpr std::size_t num_children = sizeof...(ChildT);
604
606 using LHFReferenceList = std::tuple<ChildT&...>;
607
610 using ChildValueList = std::tuple<typename ChildT::Index...>;
611
621 template<
622 typename PropertyLess,
623 typename PropertyHash,
624 typename PropertyEqual,
625 typename PropertyPrinter>
628 using InterfaceKeyType = PropertyT;
629
631 using InterfaceValueType = PropertyT;
632
633 PropertyT key;
635
637 const PropertyT &key,
638 const ChildValueList &value):
639 key(key),
640 value(value) {}
641
647 const PropertyT &get_key() const {
648 return key;
649 }
650
651
659 const ChildValueList &get_value() const {
660 return value;
661 }
662
679 template <typename Operation, std::size_t... Indices>
681 ChildValueList &ret,
682 const LHFReferenceList &lhf,
683 const ChildValueList &arg_value,
684 std::index_sequence<Indices...>) const {
685 ((Operation()(std::get<Indices>(ret),
686 std::get<Indices>(lhf),
687 std::get<Indices>(value),
688 std::get<Indices>(arg_value)
689 )), ...);
690 }
691
704 template<typename Operation>
706 const LHFReferenceList &lhf,
707 const PropertyElement &arg) const {
708 ChildValueList ret;
709 apply_internal<Operation>(
710 ret,
711 lhf,
712 arg.value,
713 std::make_index_sequence<num_children>{});
714 return PropertyElement(key, ret);
715 }
716
717 bool operator<(const PropertyElement &b) const {
718 return PropertyLess()(key, b.key);
719 }
720
721 bool operator==(const PropertyElement &b) const {
722 return PropertyEqual()(key, b.key);
723 }
724
726 std::stringstream s;
727 s << PropertyPrinter()(key);
728 s << " -> [ ";
729 std::apply(
730 [&s](auto&&... args) {
731 ((s << args.value << ' '), ...);
732 }, value);
733 s << "]";
734 return s.str();
735 }
736
737 friend std::ostream& operator<<(std::ostream& os, const PropertyElement& obj) {
738 os << obj.to_string();
739 return os;
740 }
741
742 struct Hash {
743 std::size_t operator()(const PropertyElement &p) const {
744 return PropertyHash()(p.key);
745 }
746 };
747
754 struct FullEqual {
755 bool operator()(const PropertyElement &a, const PropertyElement &b) const {
756 return PropertyEqual()(a.key, b.key) && (a.value == b.value);
757 }
758 };
759 };
760};
761
767 size_t hits = 0;
768
770 size_t equal_hits = 0;
771
774 size_t subset_hits = 0;
775
778 size_t empty_hits = 0;
779
782 size_t cold_misses = 0;
783
786 size_t edge_misses = 0;
787
789 std::stringstream s;
790 s << " " << "Hits : " << hits << "\n"
791 << " " << "Equal Hits : " << equal_hits << "\n"
792 << " " << "Subset Hits: " << subset_hits << "\n"
793 << " " << "Empty Hits : " << empty_hits << "\n"
794 << " " << "Cold Misses: " << cold_misses << "\n"
795 << " " << "Edge Misses: " << edge_misses << "\n";
796 return s.str();
797 }
798};
799
810#ifdef LHF_ENABLE_PERFORMANCE_METRICS
811#define LHF_PERF_INC(__oper, __category) (perf[__LHF_STR(__oper)] . __category ++)
812#else
813#define LHF_PERF_INC(__oper, __category)
814#endif
815
816
835template <
836 typename PropertyT,
837 typename PropertyLess = DefaultLess<PropertyT>,
838 typename PropertyHash = DefaultHash<PropertyT>,
839 typename PropertyEqual = DefaultEqual<PropertyT>,
840 typename PropertyPrinter = DefaultPrinter<PropertyT>,
841 typename Nesting = NestingNone<PropertyT>>
843public:
848 struct Index {
850
851 Index(IndexValue idx = EMPTY_SET_VALUE): value(idx) {}
852
853 bool is_empty() const {
854 return value == EMPTY_SET_VALUE;
855 }
856
857 bool operator==(const Index &b) const {
858 return value == b.value;
859 }
860
861 bool operator!=(const Index &b) const {
862 return value != b.value;
863 }
864
865 bool operator<(const Index &b) const {
866 return value < b.value;
867 }
868
869 bool operator>(const Index &b) const {
870 return value > b.value;
871 }
872
874 return std::to_string(value);
875 }
876
877 friend std::ostream& operator<<(std::ostream& os, const Index& obj) {
878 os << obj.to_string();
879 return os;
880 }
881
882 struct Hash {
883 std::size_t operator()(const Index &idx) const {
884 return DefaultHash<IndexValue>()(idx.value);
885 }
886 };
887 };
888
894 typename Nesting::template PropertyElement<
895 PropertyLess,
896 PropertyHash,
897 PropertyEqual,
898 PropertyPrinter>;
899
904 using PropertySet = std::vector<PropertyElement>;
905
930 std::unordered_map<
931 const PropertySet *, IndexValue,
932 SetHash<
935 typename PropertyElement::Hash>,
936 SetEqual<
939 typename PropertyElement::FullEqual>>;
940
943 using RefList = typename Nesting::LHFReferenceList;
944
945protected:
947
948#ifdef LHF_ENABLE_PERFORMANCE_METRICS
951#endif
952
953 // The property set storage array.
955
956 // The property set -> Index in storage array mapping.
958
963
973 SubsetRelation is_subset(const Index &a, const Index &b) const {
975 auto i = subsets.find({a.value, b.value});
976
977 if (i == subsets.end()) {
978 return UNKNOWN;
979 } else {
980 return i->second;
981 }
982 }
983
991 void store_subset(const Index &a, const Index &b) {
995
996 // We need to maintain the operation pair in index-order here as well.
997 if (a > b) {
998 subsets.insert({{b.value, a.value}, SUPERSET});
999 } else {
1000 subsets.insert({{a.value, b.value}, SUBSET});
1001 }
1002 }
1003
1004public:
1006 // INSERT EMPTY SET AT INDEX 0
1007 register_set({ });
1008 }
1009
1010 inline bool is_empty(const Index &i) const {
1011 return i.is_empty();
1012 }
1013
1026
1029
1030 auto cursor = property_set_map.find(new_set.get());
1031
1032 if (cursor == property_set_map.end()) {
1033 LHF_PERF_INC(property_sets, cold_misses);
1034 property_sets.push_back(std::move(new_set));
1035 IndexValue ret = property_sets.size() - 1;
1036 property_set_map.insert(std::make_pair(property_sets[ret].get(), ret));
1037 return Index(ret);
1038 }
1039
1041 return Index(cursor->second);
1042 }
1043
1056
1059
1060 auto cursor = property_set_map.find(new_set.get());
1061
1062 if (cursor == property_set_map.end()) {
1063 LHF_PERF_INC(property_sets, cold_misses);
1064 property_sets.push_back(std::move(new_set));
1065 IndexValue ret = property_sets.size() - 1;
1066 property_set_map.insert(std::make_pair(property_sets[ret].get(), ret));
1067 cold = true;
1068 return Index(ret);
1069 }
1070
1072 cold = false;
1073 return Index(cursor->second);
1074 }
1075
1085 std::unordered_set<
1087 typename PropertyElement::Hash,
1088 typename PropertyElement::FullEqual> deduplicator;
1089
1090 for (auto &i : c) {
1091 deduplicator.insert(i);
1092 }
1093
1094 c.assign(deduplicator.begin(), deduplicator.end());
1095 std::sort(c.begin(), c.end());
1096 }
1097
1108 template <bool disable_integrity_check = false>
1111
1112 if (!disable_integrity_check) {
1114 }
1115
1116 auto cursor = property_set_map.find(&c);
1117
1118 if (cursor == property_set_map.end()) {
1119 LHF_PERF_INC(property_sets, cold_misses);
1121 property_sets.push_back(std::move(new_set));
1122 IndexValue ret = property_sets.size() - 1;
1123 property_set_map.insert(std::make_pair(property_sets[ret].get(), ret));
1124 return Index(ret);
1125 }
1126
1128 return Index(cursor->second);
1129 }
1130
1143 template <bool disable_integrity_check = false>
1144 Index register_set(const PropertySet &c, bool &cold) {
1146
1147 if (!disable_integrity_check) {
1149 }
1150
1151 auto cursor = property_set_map.find(&c);
1152
1153 if (cursor == property_set_map.end()) {
1154 LHF_PERF_INC(property_sets, cold_misses);
1156 property_sets.push_back(std::move(new_set));
1157 IndexValue ret = property_sets.size() - 1;
1158 property_set_map.insert(std::make_pair(property_sets[ret].get(), ret));
1159 cold = true;
1160 return Index(ret);
1161 }
1162
1164 cold = false;
1165 return Index(cursor->second);
1166 }
1167
1168 template <bool disable_integrity_check = false>
1171
1172 if (!disable_integrity_check) {
1174 }
1175
1176 auto cursor = property_set_map.find(&c);
1177 if (cursor == property_set_map.end()) {
1178 LHF_PERF_INC(property_sets, cold_misses);
1180 property_sets.push_back(std::move(new_set));
1181 IndexValue ret = property_sets.size() - 1;
1182 property_set_map.insert(std::make_pair(property_sets[ret].get(), ret));
1183 return Index(ret);
1184 }
1185
1187 return Index(cursor->second);
1188 }
1189
1190 template <bool disable_integrity_check = false>
1191 Index register_set(PropertySet &&c, bool &cold) {
1193
1194 if (!disable_integrity_check) {
1196 }
1197
1198 auto cursor = property_set_map.find(&c);
1199 if (cursor == property_set_map.end()) {
1200 LHF_PERF_INC(property_sets, cold_misses);
1202 property_sets.push_back(std::move(new_set));
1203 IndexValue ret = property_sets.size() - 1;
1204 property_set_map.insert(std::make_pair(property_sets[ret].get(), ret));
1205 cold = true;
1206 return Index(ret);
1207 }
1208
1210 cold = false;
1211 return Index(cursor->second);
1212 }
1213
1221 inline const PropertySet &get_value(const Index &index) const {
1223 return *property_sets[index.value].get();
1224 }
1225
1232 inline std::size_t property_set_count() const {
1233 return property_sets.size();
1234 }
1235
1243 inline std::size_t size_of(const Index &index) const {
1244 if (index == EMPTY_SET_VALUE) {
1245 return 0;
1246 } else {
1247 return get_value(index).size();
1248 }
1249 }
1250
1260 static inline bool less(const PropertyElement &a, const PropertyElement &b) {
1261 return a < b;
1262 }
1263
1264 static inline bool less_key(const PropertyElement &a, const PropertyT &b) {
1265 return a.get_key() < b;
1266 }
1267
1277 static inline bool equal(const PropertyElement &a, const PropertyElement &b) {
1278 return a == b;
1279 }
1280
1281 static inline bool equal_key(const PropertyElement &a, const PropertyT &b) {
1282 return a.get_key() == b;
1283 }
1284
1295 inline Optional<PropertyElement> find_key(const Index &index, const PropertyT &p) const {
1296 if (is_empty(index)) {
1298 }
1299
1300 const PropertySet &s = get_value(index);
1301
1303 for (PropertyElement i : s) {
1304 if (equal(i, p)) {
1305 return i;
1306 }
1307 }
1308 } else {
1309 // Binary search implementation
1310 std::size_t low = 0;
1311 std::size_t high = s.size() - 1;
1312
1313 while (low <= high) {
1314 std::size_t mid = low + (high - low) / 2;
1315
1316 if (equal_key(s[mid], p)) {
1317 return true;
1318 } else if (less_key(s[mid], p)) {
1319 low = mid + 1;
1320 } else {
1321 high = mid - 1;
1322 }
1323 }
1324 }
1325
1327 }
1328
1338 inline bool contains(const Index &index, const PropertyElement &prop) const {
1339 if (is_empty(index)) {
1340 return false;
1341 }
1342
1343 const PropertySet &s = get_value(index);
1344
1346 for (PropertyElement i : s) {
1347 if (equal(i, prop)) {
1348 return true;
1349 }
1350 }
1351 } else {
1352 // Binary search implementation
1353 std::size_t low = 0;
1354 std::size_t high = s.size() - 1;
1355
1356 while (low <= high) {
1357 std::size_t mid = low + (high - low) / 2;
1358
1359 if (equal(s[mid], prop)) {
1360 return true;
1361 } else if (less(s[mid], prop)) {
1362 low = mid + 1;
1363 } else {
1364 high = mid - 1;
1365 }
1366 }
1367 }
1368
1369 return false;
1370 }
1371
1382 Index set_union(const Index &_a, const Index &_b) {
1385
1386 if (_a == _b) {
1387 LHF_PERF_INC(unions, equal_hits);
1388 return Index(_a);
1389 }
1390
1391 if (is_empty(_a)) {
1392 LHF_PERF_INC(unions, empty_hits);
1393 return Index(_b);
1394 } else if (is_empty(_b)) {
1395 LHF_PERF_INC(unions,empty_hits);
1396 return Index(_a);
1397 }
1398
1399 const Index &a = std::min(_a, _b);
1400 const Index &b = std::max(_a, _b);
1401
1402 SubsetRelation r = is_subset(a, b);
1403
1404 if (r == SUBSET) {
1405 LHF_PERF_INC(unions, subset_hits);
1406 return Index(b);
1407 } else if (r == SUPERSET) {
1408 LHF_PERF_INC(unions, subset_hits);
1409 return Index(a);
1410 }
1411
1412 auto cursor = unions.find({a.value, b.value});
1413
1414 if (cursor == unions.end()) {
1415 PropertySet new_set;
1416 const PropertySet &first = get_value(a);
1417 const PropertySet &second = get_value(b);
1418
1419 // The union implementation here is adapted from the example
1420 // suggested implementation provided of std::set_union from
1421 // cppreference.com
1422 auto cursor_1 = first.begin();
1423 const auto &cursor_end_1 = first.end();
1424 auto cursor_2 = second.begin();
1425 const auto &cursor_end_2 = second.end();
1426
1427 while (cursor_1 != cursor_end_1) {
1428 if (cursor_2 == cursor_end_2) {
1429 LHF_PUSH_RANGE(new_set, cursor_1, cursor_end_1);
1430 break;
1431 }
1432
1433 if (less(*cursor_2, *cursor_1)) {
1434 LHF_PUSH_ONE(new_set, *cursor_2);
1435 cursor_2++;
1436 } else {
1437 if (!(less(*cursor_1, *cursor_2))) {
1438 if constexpr (Nesting::is_nested) {
1439 PropertyElement new_elem =
1441 set_union, reflist, *cursor_1, *cursor_2);
1442 LHF_PUSH_ONE(new_set, new_elem);
1443 } else {
1444 LHF_PUSH_ONE(new_set, *cursor_1);
1445 }
1446 cursor_2++;
1447 } else {
1448 LHF_PUSH_ONE(new_set, *cursor_1);
1449 }
1450 cursor_1++;
1451 }
1452 }
1453
1454 LHF_PUSH_RANGE(new_set, cursor_2, cursor_end_2);
1455
1456 bool cold = false;
1457 Index ret = LHF_REGISTER_SET_INTERNAL(std::move(new_set), cold);
1458
1459 unions.insert({{a.value, b.value}, ret.value});
1460
1461
1462 if (ret == a) {
1463 store_subset(b, ret);
1464 } else if (ret == b) {
1465 store_subset(a, ret);
1466 } else {
1467 store_subset(a, ret);
1468 store_subset(b, ret);
1469 }
1470
1471 if (cold) {
1472 LHF_PERF_INC(unions, cold_misses);
1473 } else {
1474 LHF_PERF_INC(unions, edge_misses);
1475 }
1476 return Index(ret);
1477 }
1478
1479 LHF_PERF_INC(unions, hits);
1480 return Index(cursor->second);
1481 }
1482
1494 return set_union(a, register_set_single(b));
1495 }
1496
1507 Index set_difference(const Index &a, const Index &b) {
1510
1511 if (a == b) {
1512 LHF_PERF_INC(differences, equal_hits);
1513 return Index(EMPTY_SET_VALUE);
1514 }
1515
1516 if (is_empty(a)) {
1517 LHF_PERF_INC(differences, empty_hits);
1518 return Index(EMPTY_SET_VALUE);
1519 } else if (is_empty(b)) {
1520 LHF_PERF_INC(differences, empty_hits);
1521 return Index(a);
1522 }
1523
1524 auto cursor = differences.find({a.value, b.value});
1525
1526 if (cursor == differences.end()) {
1527 PropertySet new_set;
1528 const PropertySet &first = get_value(a);
1529 const PropertySet &second = get_value(b);
1530
1531 // The difference implementation here is adapted from the example
1532 // suggested implementation provided of std::set_difference from
1533 // cppreference.com
1534 auto cursor_1 = first.begin();
1535 const auto &cursor_end_1 = first.end();
1536 auto cursor_2 = second.begin();
1537 const auto &cursor_end_2 = second.end();
1538
1539 while (cursor_1 != cursor_end_1) {
1540 if (cursor_2 == cursor_end_2) {
1541 LHF_PUSH_RANGE(new_set, cursor_1, cursor_end_1);
1542 break;
1543 }
1544
1545 if (less(*cursor_1, *cursor_2)) {
1546 LHF_PUSH_ONE(new_set, *cursor_1);
1547 cursor_1++;
1548 } else {
1549 if (!(less(*cursor_2, *cursor_1))) {
1550 if constexpr (Nesting::is_nested) {
1551 PropertyElement new_elem =
1553 set_difference, reflist, *cursor_1, *cursor_2);
1554 LHF_PUSH_ONE(new_set, new_elem);
1555 }
1556 cursor_1++;
1557 }
1558 cursor_2++;
1559 }
1560 }
1561
1562 bool cold = false;
1563 Index ret = LHF_REGISTER_SET_INTERNAL(std::move(new_set), cold);
1564 differences.insert({{a.value, b.value}, ret.value});
1565
1566 if (ret != a) {
1567 store_subset(ret, a);
1568 } else {
1569 intersections.insert({
1570 {
1571 std::min(a.value, b.value),
1572 std::max(a.value, b.value)
1573 }, EMPTY_SET_VALUE});
1574 }
1575
1576 if (cold) {
1577 LHF_PERF_INC(differences, cold_misses);
1578 } else {
1579 LHF_PERF_INC(differences, edge_misses);
1580 }
1581
1582 return Index(ret);
1583 }
1584
1586 return Index(cursor->second);
1587 }
1588
1600 return set_difference(a, register_set_single(b));
1601 }
1602
1612 Index set_remove_single_key(const Index &a, const PropertyT &p) {
1613 PropertySet new_set;
1614 const PropertySet &first = get_value(a);
1615
1616 auto cursor_1 = first.begin();
1617 const auto &cursor_end_1 = first.end();
1618
1619 for (;cursor_1 != cursor_end_1; cursor_1++) {
1620 if (!PropertyEqual()(cursor_1->get_key(), p)) {
1621 LHF_PUSH_ONE(new_set, *cursor_1);
1622 }
1623 }
1624 return register_set<true>(std::move(new_set));
1625 }
1626
1637 Index set_intersection(const Index &_a, const Index &_b) {
1640
1641 if (_a == _b) {
1642 LHF_PERF_INC(intersections, equal_hits);
1643 return Index(_a);
1644 }
1645
1646 if (is_empty(_a) || is_empty(_b)) {
1647 LHF_PERF_INC(intersections, empty_hits);
1648 return Index(EMPTY_SET_VALUE);
1649 }
1650
1651 const Index &a = std::min(_a, _b);
1652 const Index &b = std::max(_a, _b);
1653
1654 SubsetRelation r = is_subset(a, b);
1655
1656 if (r == SUBSET) {
1657 LHF_PERF_INC(intersections, subset_hits);
1658 return Index(a);
1659 } else if (r == SUPERSET) {
1660 LHF_PERF_INC(intersections, subset_hits);
1661 return Index(b);
1662 }
1663
1664 auto cursor = intersections.find({a.value, b.value});
1665
1666 if (cursor == intersections.end()) {
1667 PropertySet new_set;
1668 const PropertySet &first = get_value(a);
1669 const PropertySet &second = get_value(b);
1670
1671 // The intersection implementation here is adapted from the example
1672 // suggested implementation provided for std::set_intersection from
1673 // cppreference.com
1674 auto cursor_1 = first.begin();
1675 const auto &cursor_end_1 = first.end();
1676 auto cursor_2 = second.begin();
1677 const auto &cursor_end_2 = second.end();
1678
1679 while (cursor_1 != cursor_end_1 && cursor_2 != cursor_end_2)
1680 {
1681 if (less(*cursor_1,*cursor_2)) {
1682 cursor_1++;
1683 } else {
1684 if (!(less(*cursor_2, *cursor_1))) {
1685 if constexpr (Nesting::is_nested) {
1686 PropertyElement new_elem =
1688 LHF_PUSH_ONE(new_set, new_elem);
1689 } else {
1690 LHF_PUSH_ONE(new_set, *cursor_1);
1691 }
1692 cursor_1++;
1693 }
1694 cursor_2++;
1695 }
1696 }
1697
1698 bool cold = false;
1699 Index ret = LHF_REGISTER_SET_INTERNAL(std::move(new_set), cold);
1700 intersections.insert({{a.value, b.value}, ret.value});
1701
1702 if (ret != a) {
1703 store_subset(ret, a);
1704 } else if (ret != b) {
1705 store_subset(ret, b);
1706 } else {
1707 store_subset(ret, a);
1708 store_subset(ret, b);
1709 }
1710
1711 if (cold) {
1712 LHF_PERF_INC(intersections, cold_misses);
1713 } else {
1714 LHF_PERF_INC(intersections, edge_misses);
1715 }
1716 return Index(ret);
1717 }
1718
1720 return Index(cursor->second);
1721 }
1722
1723
1744 Index s,
1745 std::function<bool(const PropertyT &)> filter_func,
1749
1750 if (is_empty(s)) {
1751 return s;
1752 }
1753
1754 auto cursor = cache.find(s);
1755
1756 if (cursor == cache.end()) {
1757 PropertySet new_set;
1758 for (PropertyT value : get_value(s)) {
1759 if (filter_func(value)) {
1760 LHF_PUSH_ONE(new_set, value);
1761 }
1762 }
1763
1764 bool cold;
1765 Index new_index = LHF_REGISTER_SET_INTERNAL(std::move(new_set), cold);
1766
1767 cache.insert({s, new_index.value});
1768
1769 if (cold) {
1770 LHF_PERF_INC(filter, cold_misses);
1771 } else {
1772 LHF_PERF_INC(filter, edge_misses);
1773 }
1774
1775 return Index(new_index);
1776 }
1777
1778 LHF_PERF_INC(filter, hits);
1779 return Index(cursor->second);
1780 }
1781
1790 std::stringstream s;
1791 s << "{ ";
1792 for (const PropertyElement &p : set) {
1793 s << p.to_string() << " ";
1794 }
1795 s << "}";
1796
1797 return s.str();
1798 }
1799
1801 return property_set_to_string(get_value(idx));
1802 }
1803
1809 String dump() const {
1810 std::stringstream s;
1811 s << "{\n";
1812
1813 s << " " << "Unions: " << "(Count: " << unions.size() << ")\n";
1814 for (auto i : unions) {
1815 s << " {" << i.first << " -> " << i.second << "} \n";
1816 }
1817
1818 s << "\n";
1819 s << " " << "Differences:" << "(Count: " << differences.size() << ")\n";
1820 for (auto i : differences) {
1821 s << " {" << i.first << " -> " << i.second << "} \n";
1822 }
1823
1824 s << "\n";
1825 s << " " << "Intersections: " << "(Count: " << intersections.size() << ")\n";
1826 for (auto i : intersections) {
1827 s << " {" << i.first << " -> " << i.second << "} \n";
1828 }
1829
1830 s << "\n";
1831 s << " " << "Subsets: " << "(Count: " << subsets.size() << ")\n";
1832 for (auto i : subsets) {
1833 s << " " << i.first << " -> " << (i.second == SUBSET ? "sub" : "sup") << "\n";
1834 }
1835
1836 s << "\n";
1837 s << " " << "PropertySets: " << "(Count: " << property_set_map.size() << ")\n";
1838 for (size_t i = 0; i < property_sets.size(); i++) {
1839 s << " "
1840 << i << " : " << property_set_to_string(*property_sets[i].get()) << "\n";
1841 }
1842 s << "}\n";
1843 return s.str();
1844 }
1845
1846 friend std::ostream& operator<<(std::ostream& os, const LatticeHashForest& obj) {
1847 os << obj.dump();
1848 return os;
1849 }
1850
1851#ifdef LHF_ENABLE_PERFORMANCE_METRICS
1860 std::stringstream s;
1861 s << "Performance Profile: \n";
1862 for (auto &p : perf) {
1863 s << p.first << "\n"
1864 << p.second.to_string() << "\n";
1865 }
1866 s << stat.dump();
1867 return s.str();
1868 }
1869#endif
1870
1871}; // END LatticeHashForest
1872
1887template <
1888 typename PropertyT,
1889 typename PropertyLess = DefaultLess<PropertyT>,
1890 typename PropertyHash = DefaultHash<PropertyT>,
1891 typename PropertyEqual = DefaultEqual<PropertyT>,
1892 typename PropertyPrinter = DefaultPrinter<PropertyT>>
1898 struct Index {
1900
1901 Index(IndexValue idx = EMPTY_SET_VALUE): value(idx) {}
1902
1903 bool empty() const {
1904 return value == EMPTY_SET_VALUE;
1905 }
1906
1907 bool operator==(const Index &b) const {
1908 return value == b.value;
1909 }
1910
1911 bool operator!=(const Index &b) const {
1912 return value != b.value;
1913 }
1914
1915 bool operator<(const Index &b) const {
1916 return value < b.value;
1917 }
1918
1919 bool operator>(const Index &b) const {
1920 return value > b.value;
1921 }
1922 };
1923
1924
1926 std::unordered_map<
1927 PropertyT *, IndexValue,
1928 PropertyHash,
1929 PropertyEqual>;
1930
1931 // The property storage array.
1933
1934 // The property -> Index in storage array mapping.
1936
1947 Index register_value(const PropertyT &c) {
1948
1949 UniquePointer<PropertyT> new_value =
1950 UniquePointer<PropertyT>(new PropertyT{c});
1951
1952 auto cursor = property_map.find(new_value.get());
1953
1954 if (cursor == property_map.end()) {
1955 // LHF_PERF_INC(property_sets, cold_misses);
1956 property_list.push_back(std::move(new_value));
1957 IndexValue ret = property_list.size() - 1;
1958 property_map.insert(std::make_pair(property_list[ret].get(), ret));
1959 return Index(ret);
1960 }
1961
1962 // LHF_PERF_INC(property_sets, hits);
1963 return Index(cursor->second);
1964 }
1965
1966};
1967
1968}; // END NAMESPACE
1969
1970#endif
The main LatticeHashForest structure. This class can be used as-is with a type or derived for additio...
Definition lhf.hpp:842
typename Nesting::template PropertyElement< PropertyLess, PropertyHash, PropertyEqual, PropertyPrinter > PropertyElement
Definition lhf.hpp:898
HashMap< String, OperationPerf > perf
Definition lhf.hpp:950
Index register_set(PropertySet &&c)
Definition lhf.hpp:1169
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 ...
Definition lhf.hpp:1493
HashMap< OperationNode, IndexValue > BinaryOperationMap
Definition lhf.hpp:942
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 ...
Definition lhf.hpp:1599
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
Definition lhf.hpp:991
Index register_set(const PropertySet &c)
Inserts a (or gets an existing) set into property set storage.
Definition lhf.hpp:1109
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 "...
Definition lhf.hpp:1260
BinaryOperationMap unions
Definition lhf.hpp:959
BinaryOperationMap intersections
Definition lhf.hpp:960
String property_set_to_string(const Index &idx)
Definition lhf.hpp:1800
BinaryOperationMap differences
Definition lhf.hpp:961
Index set_intersection(const Index &_a, const Index &_b)
Calculates, or returns a cached result of the intersection of a and b
Definition lhf.hpp:1637
PropertySetMap property_set_map
Definition lhf.hpp:957
String dump() const
Dumps the current state of the LHF to a string.
Definition lhf.hpp:1809
Index register_set(const PropertySet &c, bool &cold)
Inserts a (or gets an existing) set into property set storage, and reports whether this set was alrea...
Definition lhf.hpp:1144
std::size_t size_of(const Index &index) const
Returns the size of the set at index
Definition lhf.hpp:1243
Index register_set(PropertySet &&c, bool &cold)
Definition lhf.hpp:1191
std::unordered_map< const PropertySet *, IndexValue, SetHash< PropertySet, PropertyElement, typename PropertyElement::Hash >, SetEqual< PropertySet, PropertyElement, typename PropertyElement::FullEqual > > PropertySetMap
Definition lhf.hpp:939
HashMap< OperationNode, SubsetRelation > subsets
Definition lhf.hpp:962
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.
Definition lhf.hpp:973
String dump_perf() const
Dumps a performance information.
Definition lhf.hpp:1859
Index set_filter(Index s, std::function< bool(const PropertyT &)> filter_func, HashMap< IndexValue, IndexValue > &cache)
Filters a set based on a criterion function. This is supposed to be an abstract filtering mechanism t...
Definition lhf.hpp:1743
static String property_set_to_string(const PropertySet &set)
Converts the property set to a string.
Definition lhf.hpp:1789
Index set_union(const Index &_a, const Index &_b)
Calculates, or returns a cached result of the union of a and b
Definition lhf.hpp:1382
bool is_empty(const Index &i) const
Definition lhf.hpp:1010
Vector< UniquePointer< PropertySet > > property_sets
Definition lhf.hpp:954
Index register_set_single(const PropertyElement &c)
Inserts a (or gets an existing) single-element set into property set storage.
Definition lhf.hpp:1024
static bool less_key(const PropertyElement &a, const PropertyT &b)
Definition lhf.hpp:1264
std::vector< PropertyElement > PropertySet
Definition lhf.hpp:904
static bool equal(const PropertyElement &a, const PropertyElement &b)
Equality comparator for operations. You MUST use this instead of directly using anything else like "<...
Definition lhf.hpp:1277
const PropertySet & get_value(const Index &index) const
Gets the actual property set specified by index.
Definition lhf.hpp:1221
static bool equal_key(const PropertyElement &a, const PropertyT &b)
Definition lhf.hpp:1281
PerformanceStatistics stat
Definition lhf.hpp:949
Optional< PropertyElement > find_key(const Index &index, const PropertyT &p) const
Finds a property element in the set based on the key provided.
Definition lhf.hpp:1295
Index set_difference(const Index &a, const Index &b)
Calculates, or returns a cached result of the difference of a from b
Definition lhf.hpp:1507
LatticeHashForest(RefList reflist={})
Definition lhf.hpp:1005
typename Nesting::LHFReferenceList RefList
Definition lhf.hpp:943
Index set_remove_single_key(const Index &a, const PropertyT &p)
Removes a single element from a given set if the "key" element matches.
Definition lhf.hpp:1612
bool contains(const Index &index, const PropertyElement &prop) const
Determines whether the property set at index contains the element prop or not.
Definition lhf.hpp:1338
friend std::ostream & operator<<(std::ostream &os, const LatticeHashForest &obj)
Definition lhf.hpp:1846
HashMap< IndexValue, IndexValue > UnaryOperationMap
Definition lhf.hpp:941
void prepare_vector_set(PropertySet &c)
Definition lhf.hpp:1084
std::size_t property_set_count() const
Returns the total number of property sets currently in the LHF.
Definition lhf.hpp:1232
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...
Definition lhf.hpp:1054
Describes an optional value of some type T. The value may either be present or absent.
Definition lhf.hpp:91
Optional(const T &value)
Definition lhf.hpp:96
static Optional absent()
Explicitly creates an absent value.
Definition lhf.hpp:99
const T & get()
Gets the underlying value. Throws an exception if it is absent.
Definition lhf.hpp:109
bool is_present()
Informs if the value is present.
Definition lhf.hpp:104
#define LHF_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...
Definition lhf.hpp:586
#define LHF_PROPERTY_SET_INDEX_VALID(__index)
Check whether the index is a valid index within the property set.
Definition lhf.hpp:381
#define LHF_PROPERTY_SET_INTEGRITY_VALID(__set)
Macro and switch for verify_property_set_integrity inside LHF.
Definition lhf.hpp:354
#define LHF_PUSH_RANGE(__cont, __start, __end)
Pushes a range of elements to a PropertySet using an iterator. Use this when implementing operations.
Definition lhf.hpp:430
#define LHF_PERF_INC(__oper, __category)
Increments the invocation count of the given category and operator.
Definition lhf.hpp:811
#define LHF_PROPERTY_SET_PAIR_UNEQUAL(__index1, __index2)
Check whether the pair of indexes are unequal. Used for sanity checking.
Definition lhf.hpp:396
#define LHF_PROPERTY_SET_PAIR_VALID(__index1, __index2)
Check whether the pair of indexes is a valid within the property set.
Definition lhf.hpp:391
#define LHF_PUSH_ONE(__cont, __val)
Pushes one element to a PropertySet. Use this when implementing operations.
Definition lhf.hpp:418
#define LHF_BINARY_NESTED_OPERATION(__op_name)
Declares a struct that enables the recursive/nesting behaviour of an operation.
Definition lhf.hpp:567
#define LHF_REGISTER_SET_INTERNAL(__set, __cold)
Registers a set with behaviours defined for internal processing.
Definition lhf.hpp:440
Any configurable constants go into this file.
#define LHF_SORTED_VECTOR_BINARY_SEARCH_THRESHOLD
Definition lhf_config.hpp:9
Definition lhf.hpp:28
std::size_t IndexValue
Definition lhf.hpp:56
std::vector< T > Vector
Definition lhf.hpp:40
std::ostream & operator<<(std::ostream &os, const OperationNode &op)
Definition lhf.hpp:175
std::equal_to< T > DefaultEqual
Definition lhf.hpp:65
std::size_t compose_hash(const std::size_t prev, T next)
Composes a preexisting hash with another variable. Useful for Hashing containers. Adapted from boost:...
Definition lhf.hpp:148
std::set< T > OrderedSet
Definition lhf.hpp:52
std::unordered_map< K, V > HashMap
Definition lhf.hpp:43
std::unordered_set< T > HashSet
Definition lhf.hpp:49
std::map< K, V > OrderedMap
Definition lhf.hpp:46
std::unique_ptr< T > UniquePointer
Definition lhf.hpp:37
std::hash< T > DefaultHash
Definition lhf.hpp:62
SubsetRelation
Used to store a subset relation between two set indices. Because the index pair must be in sorted ord...
Definition lhf.hpp:124
@ UNKNOWN
Definition lhf.hpp:125
@ SUBSET
Definition lhf.hpp:126
@ SUPERSET
Definition lhf.hpp:127
std::less< T > DefaultLess
Definition lhf.hpp:59
std::string String
Definition lhf.hpp:54
Enables basic code-based profiling metrics in LHF.
#define __lhf_calc_functime(__stat)
Creates a timer object to capture duration of the current function when going out of scope.
Thrown if an Optional is accessed when the value is absent.
Definition lhf.hpp:79
AbsentValueAccessError(const std::string &message)
Definition lhf.hpp:80
Struct that is thrown on an assertion failure.
Definition lhf.hpp:298
AssertError(const std::string &message)
Definition lhf.hpp:299
Index returned by an operation. The struct ensures type safety and possible future extensions.
Definition lhf.hpp:1898
bool operator>(const Index &b) const
Definition lhf.hpp:1919
bool operator!=(const Index &b) const
Definition lhf.hpp:1911
bool empty() const
Definition lhf.hpp:1903
bool operator==(const Index &b) const
Definition lhf.hpp:1907
Index(IndexValue idx=EMPTY_SET_VALUE)
Definition lhf.hpp:1901
bool operator<(const Index &b) const
Definition lhf.hpp:1915
An LHF-like structure for scalar values. It does not implement any special operations besides dedupli...
Definition lhf.hpp:1893
Index register_value(const PropertyT &c)
Inserts a (or gets an existing) element into property storage.
Definition lhf.hpp:1947
Vector< UniquePointer< PropertyT > > property_list
Definition lhf.hpp:1932
PropertyMap property_map
Definition lhf.hpp:1935
std::unordered_map< PropertyT *, IndexValue, PropertyHash, PropertyEqual > PropertyMap
Definition lhf.hpp:1929
String operator()(T x)
Definition lhf.hpp:69
std::size_t operator()(const Index &idx) const
Definition lhf.hpp:883
Index returned by an operation. The struct ensures type safety and possible future extensions.
Definition lhf.hpp:848
bool operator<(const Index &b) const
Definition lhf.hpp:865
bool operator!=(const Index &b) const
Definition lhf.hpp:861
friend std::ostream & operator<<(std::ostream &os, const Index &obj)
Definition lhf.hpp:877
bool operator>(const Index &b) const
Definition lhf.hpp:869
Index(IndexValue idx=EMPTY_SET_VALUE)
Definition lhf.hpp:851
String to_string() const
Definition lhf.hpp:873
bool operator==(const Index &b) const
Definition lhf.hpp:857
This forces a comparison of both the key and the value instead of only the key. Required in instances...
Definition lhf.hpp:754
bool operator()(const PropertyElement &a, const PropertyElement &b) const
Definition lhf.hpp:755
std::size_t operator()(const PropertyElement &p) const
Definition lhf.hpp:743
Type for the elements for a property set in the nested. The template arguments are for the 'key' type...
Definition lhf.hpp:626
void apply_internal(ChildValueList &ret, const LHFReferenceList &lhf, 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...
Definition lhf.hpp:680
PropertyElement(const PropertyT &key, const ChildValueList &value)
Definition lhf.hpp:636
PropertyT InterfaceKeyType
Key type is made available here if required by user.
Definition lhf.hpp:628
PropertyT InterfaceValueType
Value type is made available here if required by user.
Definition lhf.hpp:631
const PropertyT & get_key() const
Gets the 'key' value.
Definition lhf.hpp:647
bool operator<(const PropertyElement &b) const
Definition lhf.hpp:717
const ChildValueList & get_value() const
Gets the nested value. It returns a tuple of values containing indices to each of the nested sets of ...
Definition lhf.hpp:659
friend std::ostream & operator<<(std::ostream &os, const PropertyElement &obj)
Definition lhf.hpp:737
PropertyElement apply(const LHFReferenceList &lhf, const PropertyElement &arg) const
Performs the "apply" operation on the list of nested children specified by the Operation parameter.
Definition lhf.hpp:705
bool operator==(const PropertyElement &b) const
Definition lhf.hpp:721
Describes the standard nesting structure. Act as "non-leaf" nodes in a tree of nested LHFs.
Definition lhf.hpp:597
std::tuple< typename ChildT::Index... > ChildValueList
Definition lhf.hpp:610
std::tuple< ChildT &... > LHFReferenceList
Reference list. References to all the nested LHFs are presented here.
Definition lhf.hpp:606
static constexpr bool is_nested
Compile-time value that says this is nested.
Definition lhf.hpp:599
static constexpr std::size_t num_children
Definition lhf.hpp:603
Placeholder value to mark the reference lists and value lists as empty.
Definition lhf.hpp:457
This forces a comparison of both the key and the value instead of only the key. Required in instances...
Definition lhf.hpp:548
bool operator()(const PropertyElement &a, const PropertyElement &b) const
Definition lhf.hpp:549
std::size_t operator()(const PropertyElement &p) const
Definition lhf.hpp:534
Base-case type for the elements for a property set. The template arguments are for the 'key' type.
Definition lhf.hpp:481
PropertyElement(const PropertyT &value)
Definition lhf.hpp:490
PropertyT InterfaceValueType
Value type is made available here if required by user.
Definition lhf.hpp:486
bool operator==(const PropertyElement &b) const
Definition lhf.hpp:525
const PropertyT & get_key() const
Gets the 'key' value.
Definition lhf.hpp:497
bool operator<(const PropertyElement &b) const
Definition lhf.hpp:521
PropertyElement apply() const
Performs an "apply" operation. In the base case it is an identity operation and does not do anything.
Definition lhf.hpp:517
PropertyT InterfaceKeyType
Key type is made available here if required by user.
Definition lhf.hpp:483
const PropertyT & get_value() const
Gets the nested value. In the base case it simply returns the key.
Definition lhf.hpp:507
The nesting type for non-nested data structures. Act as "leaf" nodes in a tree of nested LHFs.
Definition lhf.hpp:449
static constexpr std::size_t num_children
Compile-time value that says there are no nested children.
Definition lhf.hpp:454
static constexpr bool is_nested
Compile-time value that says this is not nested.
Definition lhf.hpp:451
This struct contains the information about the operands of an operation (union, intersection,...
Definition lhf.hpp:156
IndexValue right
Definition lhf.hpp:158
std::string to_string() const
Definition lhf.hpp:160
bool operator<(const OperationNode &op) const
Definition lhf.hpp:166
IndexValue left
Definition lhf.hpp:157
bool operator==(const OperationNode &op) const
Definition lhf.hpp:170
Operation performance Statistics.
Definition lhf.hpp:765
String to_string() const
Definition lhf.hpp:788
size_t empty_hits
Definition lhf.hpp:778
size_t equal_hits
Number of equal hits (both arguments consist of the same set)
Definition lhf.hpp:770
size_t hits
Number of direct hits (operation pair in map)
Definition lhf.hpp:767
size_t subset_hits
Definition lhf.hpp:774
size_t edge_misses
Definition lhf.hpp:786
size_t cold_misses
Definition lhf.hpp:782
Utility class for enabling code-based profiling.
Definition profiling.hpp:22
Generic Equality comparator for set types.
Definition lhf.hpp:243
bool operator()(const SetT *a, const SetT *b) const
Definition lhf.hpp:244
Hasher for set types.
Definition lhf.hpp:283
std::size_t operator()(const SetT *k) const
Definition lhf.hpp:284
Generic Less-than comparator for set types.
Definition lhf.hpp:205
bool operator()(const OrderedSetT *a, const OrderedSetT *b) const
Definition lhf.hpp:206
Thrown if code region is unreachable.
Definition lhf.hpp:306
Unreachable(const std::string &message="Hit a branch marked as unreachable.")
Definition lhf.hpp:307
std::size_t operator()(const lhf::OperationNode &k) const
Definition lhf.hpp:185