From a812fd3faedc794678009dcf3c14571c1e284a25 Mon Sep 17 00:00:00 2001 From: Jordan Hrycaj Date: Tue, 2 Aug 2022 09:08:17 +0100 Subject: [PATCH] Retrive envelop interval for point (#136) --- stew/interval_set.nim | 15 +++++++++++++++ tests/test_interval_set.nim | 28 ++++++++++++++++++++++++---- 2 files changed, 39 insertions(+), 4 deletions(-) diff --git a/stew/interval_set.nim b/stew/interval_set.nim index fad7fad..0c83923 100644 --- a/stew/interval_set.nim +++ b/stew/interval_set.nim @@ -825,6 +825,21 @@ proc le*[P,S](ds: IntervalSetRef[P,S]): IntervalRc[P,S] = ds.le(high(P)) +proc envelope*[P,S](ds: IntervalSetRef[P,S]; pt: P): IntervalRc[P,S] = + ## Find the interval that contains the argument point `pt` (if any) + let rc = ds.leftPos.le(pt) + if rc.isOk: + if ds.lastHigh and high(P) <= rc.value.right: + # This interval ranges `[left,high(P)]`, so `pt` is certainly contained + return ok(Interval[P,S].new(rc.value.left,high(P))) + if pt < rc.value.right: + return ok(Interval[P,S].new(rc.value)) + # Otherwise: interval `[left,right)` ends before `pt` + if ds.lastHigh and high(P) <= pt: + return ok(Interval[P,S].new(high(P),high(P))) + err() + + proc delete*[P,S](ds: IntervalSetRef[P,S]; minPt: P): IntervalRc[P,S] = ## Find the interval `[minPt,maxPt]` for some point `maxPt` in the interval ## set `ds` and remove it from `ds`. The function returns the deleted diff --git a/tests/test_interval_set.nim b/tests/test_interval_set.nim index 8b50821..7ead9ad 100644 --- a/tests/test_interval_set.nim +++ b/tests/test_interval_set.nim @@ -102,6 +102,9 @@ proc le(br: FancyRanges; start: uint64): Result[FancyInterval,void] = proc ge(br: FancyRanges; start: uint64): Result[FancyInterval,void] = br.ge(start.to(FancyPoint)) +proc envelope(br: FancyRanges; start: uint64): Result[FancyInterval,void] = + br.envelope(start.to(FancyPoint)) + proc iv(left, right: uint64): FancyInterval = FancyInterval.new(left.to(FancyPoint), right.to(FancyPoint)) @@ -202,16 +205,12 @@ suite "IntervalSet: Intervals of FancyPoint entries over FancyScalar": br.clear() # from blockchain snap sync odd behaviour check br.merge(0,uHigh) == 0 - check br.chunks == 1 - check br.total == 0 check br.ge(1000) == ivError check 0 < br.reduce(99999,uHigh-1) check br.ge(1000) == iv(uHigh,uHigh) br.clear() check br.merge(0,uHigh) == 0 - check br.chunks == 1 - check br.total == 0 check br.le(uHigh) == iv(0,uHigh) check br.le(uHigh-1) == ivError check 0 < br.reduce(99999,uHigh-1) @@ -219,6 +218,27 @@ suite "IntervalSet: Intervals of FancyPoint entries over FancyScalar": check br.le(uHigh-1) == iv(0,99998) check br.le(uHigh-2) == iv(0,99998) + test "Interval envelopes": + br.clear() + check br.merge(0,uHigh) == 0 + check br.ge(1000) == ivError + check br.le(1000) == ivError + check br.envelope(1000) == iv(0,uHigh) + + check 0 < br.reduce(1000,1000) + check br.envelope(1000) == ivError + + check 0 < br.reduce(uHigh,uHigh) + check br.envelope(2000) == iv(1001,uHigh-1) + check br.envelope(uHigh-1) == iv(1001,uHigh-1) + + check 0 < br.merge(0,uHigh) # actually == 2 + check 0 < br.reduce(uHigh-1,uHigh-1) + check br.envelope(uHigh-1) == ivError + check br.envelope(uHigh-2) == iv(0,uHigh-2) + check br.ge(uHigh) == iv(uHigh,uHigh) + check br.envelope(uHigh) == iv(uHigh,uHigh) + test "Merge disjunct intervals on 1st set": br.clear() check br.merge( 0, 99) == 100