1
2
3
4
5 package liveness
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 import (
50 "fmt"
51 "os"
52 "strings"
53 )
54
55 const debugtrace = false
56
57
58 type Interval struct {
59 st, en int
60 }
61
62
63 type Intervals []Interval
64
65 func (i Interval) String() string {
66 return fmt.Sprintf("[%d,%d)", i.st, i.en)
67 }
68
69
70 func imin(i, j int) int {
71 if i < j {
72 return i
73 }
74 return j
75 }
76
77
78 func imax(i, j int) int {
79 if i > j {
80 return i
81 }
82 return j
83 }
84
85
86 func (i Interval) Overlaps(i2 Interval) bool {
87 return (imin(i.en, i2.en) - imax(i.st, i2.st)) > 0
88 }
89
90
91
92 func (i1 Interval) adjacent(i2 Interval) bool {
93 return i1.en == i2.st || i2.en == i1.st
94 }
95
96
97
98 func (i1 *Interval) MergeInto(i2 Interval) error {
99 if !i1.Overlaps(i2) && !i1.adjacent(i2) {
100 return fmt.Errorf("merge method invoked on non-overlapping/non-adjacent")
101 }
102 i1.st = imin(i1.st, i2.st)
103 i1.en = imax(i1.en, i2.en)
104 return nil
105 }
106
107
108
109
110
111
112
113
114
115
116
117
118 type IntervalsBuilder struct {
119 s Intervals
120
121 lidx int
122 }
123
124 func (c *IntervalsBuilder) last() int {
125 return c.lidx - 1
126 }
127
128 func (c *IntervalsBuilder) setLast(x int) {
129 c.lidx = x + 1
130 }
131
132 func (c *IntervalsBuilder) Finish() (Intervals, error) {
133
134
135
136 for i, j := 0, len(c.s)-1; i < j; i, j = i+1, j-1 {
137 c.s[i], c.s[j] = c.s[j], c.s[i]
138 }
139 if err := check(c.s); err != nil {
140 return Intervals{}, err
141 }
142 r := c.s
143 return r, nil
144 }
145
146
147
148
149 func (c *IntervalsBuilder) Live(pos int) error {
150 if pos < 0 {
151 return fmt.Errorf("bad pos, negative")
152 }
153 if c.last() == -1 {
154 c.setLast(pos)
155 if debugtrace {
156 fmt.Fprintf(os.Stderr, "=-= begin lifetime at pos=%d\n", pos)
157 }
158 c.s = append(c.s, Interval{st: pos, en: pos + 1})
159 return nil
160 }
161 if pos >= c.last() {
162 return fmt.Errorf("pos not decreasing")
163 }
164
165 c.s[len(c.s)-1].st = pos
166 c.setLast(pos)
167 return nil
168 }
169
170
171
172
173
174
175
176
177
178 func (c *IntervalsBuilder) Kill(pos int) error {
179 if pos < 0 {
180 return fmt.Errorf("bad pos, negative")
181 }
182 if c.last() == -1 {
183 return nil
184 }
185 if pos >= c.last() {
186 return fmt.Errorf("pos not decreasing")
187 }
188 c.s[len(c.s)-1].st = pos + 1
189
190 c.setLast(-1)
191 if debugtrace {
192 fmt.Fprintf(os.Stderr, "=-= term lifetime at pos=%d\n", pos)
193 }
194 return nil
195 }
196
197
198
199 func check(is Intervals) error {
200 for i := 0; i < len(is); i++ {
201 st := is[i].st
202 en := is[i].en
203 if en <= st {
204 return fmt.Errorf("bad range elem %d:%d, en<=st", st, en)
205 }
206 if i == 0 {
207 continue
208 }
209
210 pst := is[i-1].st
211 pen := is[i-1].en
212 if pst >= st {
213 return fmt.Errorf("range start not ordered %d:%d less than prev %d:%d", st, en,
214 pst, pen)
215 }
216
217 if pen > st {
218 return fmt.Errorf("bad range elem %d:%d overlaps prev %d:%d", st, en,
219 pst, pen)
220 }
221 }
222 return nil
223 }
224
225 func (is *Intervals) String() string {
226 var sb strings.Builder
227 for i := range *is {
228 if i != 0 {
229 sb.WriteString(" ")
230 }
231 sb.WriteString((*is)[i].String())
232 }
233 return sb.String()
234 }
235
236
237
238
239
240
241 type intWithIdx struct {
242 i Interval
243 pairIndex int
244 }
245
246 func (iwi intWithIdx) done() bool {
247 return iwi.pairIndex == -1
248 }
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264 type pairVisitor struct {
265 cur intWithIdx
266 i1pos int
267 i2pos int
268 i1, i2 Intervals
269 }
270
271
272
273
274 func (pv *pairVisitor) init(i1, i2 Intervals) intWithIdx {
275 pv.i1, pv.i2 = i1, i2
276 pv.cur = pv.sel()
277 return pv.cur
278 }
279
280
281
282
283 func (pv *pairVisitor) nxt() intWithIdx {
284 if pv.cur.pairIndex == 0 {
285 pv.i1pos++
286 } else {
287 pv.i2pos++
288 }
289 pv.cur = pv.sel()
290 return pv.cur
291 }
292
293
294
295
296
297 func (pv *pairVisitor) sel() intWithIdx {
298 var c1, c2 intWithIdx
299 if pv.i1pos >= len(pv.i1) {
300 c1.pairIndex = -1
301 } else {
302 c1 = intWithIdx{i: pv.i1[pv.i1pos], pairIndex: 0}
303 }
304 if pv.i2pos >= len(pv.i2) {
305 c2.pairIndex = -1
306 } else {
307 c2 = intWithIdx{i: pv.i2[pv.i2pos], pairIndex: 1}
308 }
309 if c1.pairIndex == -1 {
310 return c2
311 }
312 if c2.pairIndex == -1 {
313 return c1
314 }
315 if c1.i.st <= c2.i.st {
316 return c1
317 }
318 return c2
319 }
320
321
322
323 func (is Intervals) Overlaps(is2 Intervals) bool {
324
325 if len(is) == 0 || len(is2) == 0 {
326 return false
327 }
328 li := len(is)
329 li2 := len(is2)
330
331 if is[li-1].en <= is2[0].st ||
332 is[0].st >= is2[li2-1].en {
333 return false
334 }
335
336
337 var pv pairVisitor
338 first := pv.init(is, is2)
339 for {
340 second := pv.nxt()
341 if second.done() {
342 break
343 }
344 if first.pairIndex == second.pairIndex {
345 first = second
346 continue
347 }
348 if first.i.Overlaps(second.i) {
349 return true
350 }
351 first = second
352 }
353 return false
354 }
355
356
357
358
359 func (is Intervals) Merge(is2 Intervals) Intervals {
360 if len(is) == 0 {
361 return is2
362 } else if len(is2) == 0 {
363 return is
364 }
365
366 var ret Intervals
367 var pv pairVisitor
368 cur := pv.init(is, is2)
369 for {
370 second := pv.nxt()
371 if second.done() {
372 break
373 }
374
375
376
377 if !cur.i.Overlaps(second.i) && !cur.i.adjacent(second.i) {
378 ret = append(ret, cur.i)
379 cur = second
380 continue
381 }
382
383 cur.i.MergeInto(second.i)
384 }
385 ret = append(ret, cur.i)
386 return ret
387 }
388
View as plain text