@@ -20,10 +20,100 @@ namespace meevax
20
20
{
21
21
inline namespace kernel
22
22
{
23
+ struct box : public virtual pair // (value . unit)
24
+ {
25
+ auto unbox () -> object &
26
+ {
27
+ return first;
28
+ }
29
+
30
+ auto unbox () const -> object const &
31
+ {
32
+ return first;
33
+ }
34
+
35
+ auto set (object const & x) -> object const &
36
+ {
37
+ return first = x;
38
+ }
39
+ };
40
+
41
+ auto find (let const & b) -> object const &
42
+ {
43
+ if (let x = b.as <box>().unbox (); x.is <box>())
44
+ {
45
+ return b.as <box>().set (find (x));
46
+ }
47
+ else
48
+ {
49
+ return b;
50
+ }
51
+ }
52
+
53
+ /*
54
+ Efficient Nondestructive Equality Checking for Trees and Graphs
55
+ */
56
+ auto union_find (object const & x, object const & y, std::unordered_map<object, object> & forest)
57
+ {
58
+ using rank = std::uint32_t ;
59
+
60
+ if (auto iterator_x = forest.find (x); iterator_x != forest.end ())
61
+ {
62
+ if (auto iterator_y = forest.find (y); iterator_y != forest.end ())
63
+ {
64
+ if (let root_x = find (iterator_x->second ),
65
+ root_y = find (iterator_y->second ); eq (root_x, root_y))
66
+ {
67
+ return true ;
68
+ }
69
+ else
70
+ {
71
+ if (auto rank_x = root_x.as <box>().unbox ().as <rank>(),
72
+ rank_y = root_y.as <box>().unbox ().as <rank>(); rank_x > rank_y)
73
+ {
74
+ root_x.as <box>().set (make<rank>(rank_x + rank_y));
75
+ root_y.as <box>().set (root_x);
76
+ }
77
+ else
78
+ {
79
+ root_x.as <box>().set (root_y);
80
+ root_y.as <box>().set (make<rank>(rank_x + rank_y));
81
+ }
82
+ }
83
+ }
84
+ else
85
+ {
86
+ forest.emplace (y, find (iterator_x->second ));
87
+ }
88
+ }
89
+ else
90
+ {
91
+ if (auto iterator_y = forest.find (y); iterator_y != forest.end ())
92
+ {
93
+ forest.emplace (x, find (iterator_y->second ));
94
+ }
95
+ else
96
+ {
97
+ let const b = make<box>(make<rank>(1 ));
98
+ forest.emplace (x, b);
99
+ forest.emplace (y, b);
100
+ }
101
+ }
102
+
103
+ return false ;
104
+ }
105
+
106
+ auto equal (object const & x, object const & y, std::unordered_map<object, object> & forest) -> bool
107
+ {
108
+ return eqv (x, y) or (x.is <pair>() and
109
+ y.is <pair>() and (union_find (x, y, forest) or (equal (car (x), car (y), forest) and
110
+ equal (cdr (x), cdr (y), forest))));
111
+ }
112
+
23
113
auto equal (object const & x, object const & y) -> bool
24
114
{
25
- return eqv (x, y) or std::equal (x. cbegin (), x. cend (),
26
- y. cbegin () , y. cend (), equal );
115
+ auto forest = std::unordered_map<object, object>();
116
+ return equal (x , y, forest );
27
117
}
28
118
} // namespace kernel
29
119
} // namespace meevax
0 commit comments