-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathlink.h
224 lines (191 loc) · 4.16 KB
/
link.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
#pragma once
#include "move.h"
enum class LnType : Char
{
// normal links
SIMPLE, // simple link: link with no transformation
TRANS, // trans link: link with transformation
// ko links
KO_S, // simple ko link: ko link with no transformation
KO_T, // trans ko link: ko link with transformation
// markers
INIT, // init link: for 0-th node
END // end link: for end node
};
typedef const LnType &LnType_I;
typedef LnType &LnType_O, &LnType_IO;
class Link;
typedef const Link &Link_I;
typedef Link &Link_O, &Link_IO;
class Linkp;
typedef const Linkp Linkp_I;
typedef Linkp &Linkp_O, &Linkp_IO;
inline Bool istrans(LnType_I type)
{
return type == LnType::TRANS || type == LnType::KO_T;
}
inline Bool isko(LnType_I type)
{
return type == LnType::KO_S || type == LnType::KO_T;
}
inline LnType rm_trans(LnType_I type)
{
if (type == LnType::TRANS)
return LnType::SIMPLE;
else if (type == LnType::KO_T)
return LnType::KO_S;
}
// short link
class Link : public Move
{
protected:
// basic members
LnType m_type; // link type
Long m_from; // tree index of source node
Long m_to; // tree index of target node
// other members
Trans m_trans; // transformation
Bool m_reso; // if ko links is resolved
public:
Link(): m_reso(false) {}
const LnType &type() const { return m_type; }
const Long &from() const { return m_from; }
const Long &to() const { return m_to; }
const Move &move() const { return *this; }
const Bool isinit() const { return m_type == LnType::INIT; }
const Bool isend() const { return m_type == LnType::END; }
const Bool isko() const { return ::isko(m_type); }
const Bool istrans() const { return ::istrans(m_type); }
void link(LnType_I type, Long_I from, Long_I to, Move_I move)
{
if (::istrans(type))
error("not a simple link!");
m_type = type;
m_from = from;
m_to = to;
Move::operator=(move);
}
void link(LnType_I type, Long_I from, Long_I to, Move_I move, Trans_I trans)
{
if (!::istrans(type))
error("not a trans link!");
m_type = type;
m_from = from;
m_to = to;
m_trans = trans;
Move::operator=(move);
}
void init()
{
m_type = LnType::INIT;
m_from = -1;
m_to = 0;
Move::init();
}
void end(Long_I treeInd)
{
m_type = LnType::INIT;
m_from = treeInd;
m_to = -1;
Move::end();
}
const Trans &trans() const
{
if (!::istrans(m_type))
error("not a trans link!");
return m_trans;
}
Bool resolved() const
{
if (!::isko(m_type))
error("not a ko link!");
return m_reso;
}
void resolve()
{
if (!::isko(m_type))
error("not a ko link!");
m_reso = true;
}
// only support ko/non-ko conversion for now
void convert(LnType_I type)
{
if (::isko(m_type)) {
// from ko link
if (!::isko(type)) {
// to non-ko link
if (m_type == LnType::KO_S) {
m_type = LnType::SIMPLE;
}
else { // m_type == LnType::KO_T
m_type = LnType::TRANS;
}
}
}
else {
// from non-ko link
if (::istrans(m_type)) {
// to ko link
if (m_type == LnType::SIMPLE) {
m_type = LnType::KO_S;
}
else { // m_type == LnType::TRANS
m_type = LnType::KO_T;
}
}
}
error("unsupported conversion");
}
void ko_link_2_link()
{
if (m_type == LnType::KO_S) {
m_type = LnType::SIMPLE;
m_reso = false;
}
else if (m_type == LnType::KO_T) {
m_type = LnType::TRANS;
m_reso = false;
}
else
error("not a ko link");
}
void link_2_ko_link()
{
if (m_type == LnType::SIMPLE) {
m_type = LnType::KO_S;
m_reso = false;
}
else if (m_type == LnType::TRANS) {
m_type = LnType::KO_T;
m_reso = false;
}
else
error("not a ko link");
}
};
class Linkp
{
protected:
// index for Link::m_links
Long m_linkInd;
// all links stored here
static vector<Link> m_links;
public:
Linkp() : m_linkInd(-1) {}
Linkp(Long_I linkInd) : m_linkInd(linkInd) {} // allow Linkp = Long conversion
// create new un-initialized link and return pointer
static Linkp newlink()
{
m_links.emplace_back();
return Linkp(m_links.size() - 1);
}
Link* operator->() const
{
return &m_links[m_linkInd];
}
friend Bool operator==(Linkp_I lhs, Linkp_I rhs);
};
inline Bool operator==(Linkp_I lhs, Linkp_I rhs)
{
return lhs.m_linkInd == rhs.m_linkInd;
}