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