diff --git a/stew/interval_set.nim b/stew/interval_set.nim index 38edc33..83c430d 100644 --- a/stew/interval_set.nim +++ b/stew/interval_set.nim @@ -779,7 +779,9 @@ proc ge*[P,S](ds: IntervalSetRef[P,S]; minPt: P): IntervalRc[P,S] = return ok(Interval[P,S].new(rc.value.left, high(P))) return ok(Interval[P,S].new(rc.value)) if ds.lastHigh: - return ok(Interval[P,S].new(high(P),high(P))) + const preHigh = high(P) - scalarOne + if ds.covered(preHigh,preHigh) == scalarZero: + return ok(Interval[P,S].new(high(P),high(P))) err() proc ge*[P,S](ds: IntervalSetRef[P,S]): IntervalRc[P,S] = @@ -793,13 +795,18 @@ proc le*[P,S](ds: IntervalSetRef[P,S]; maxPt: P): IntervalRc[P,S] = if rc.isOk: # only the left end of segment [left,right) is guaranteed to be <= maxPt if rc.value.right - scalarOne <= maxPt: - if high(P) <= maxPt and ds.lastHigh: - # Check for fringe case intervals [a,b] gap [high(P),high(P)] <= maxPt - if rc.value.right < high(P): - return ok(Interval[P,S].new(high(P),high(P))) - # Check for fringe case intervals [a,b] + [high(P),high(P)] <= maxPt + if ds.lastHigh: + if high(P) <= maxPt: + # Check for fringe case intervals [a,b] gap [high(P),high(P)] <= maxPt + if rc.value.right < high(P): + return ok(Interval[P,S].new(high(P),high(P))) + # Check for fringe case intervals [a,b] + [high(P),high(P)] <= maxPt + if high(P) <= rc.value.right: + return ok(Interval[P,S].new(rc.value.left,high(P))) + # So maxPt < high(P) if high(P) <= rc.value.right: - return ok(Interval[P,S].new(rc.value.left,high(P))) + # Now `maxPt` is fully within the inner part of `[left,high(P)]` + return err() return ok(Interval[P,S].new(rc.value)) # find the next smaller one let xc = ds.leftPos.lt(rc.value.key) diff --git a/tests/test_interval_set.nim b/tests/test_interval_set.nim index 2cb6e9b..8b50821 100644 --- a/tests/test_interval_set.nim +++ b/tests/test_interval_set.nim @@ -177,6 +177,7 @@ suite "IntervalSet: Intervals of FancyPoint entries over FancyScalar": check br.total.truncate(uint64) == (uHigh - 10000000) + 1 check br.verify.isOk + test "More edge cases detected and fixed": br.clear() check br.total == 0 and br.chunks == 0 check br.merge(uHigh,uHigh) == 1 @@ -187,7 +188,6 @@ suite "IntervalSet: Intervals of FancyPoint entries over FancyScalar": check ivSet == false (ivVal, ivSet) = (iv, true) check ivVal == iv(uHigh,uHigh) - block: var (ivVal, ivSet) = (iv(0,0), false) for iv in br.decreasing: @@ -200,6 +200,25 @@ suite "IntervalSet: Intervals of FancyPoint entries over FancyScalar": check br.merge(1477152,uHigh) == uHigh - 1477151 check br.merge(1477151,1477151) == 1 + 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) + check br.le(uHigh) == iv(uHigh,uHigh) + check br.le(uHigh-1) == iv(0,99998) + check br.le(uHigh-2) == iv(0,99998) + test "Merge disjunct intervals on 1st set": br.clear() check br.merge( 0, 99) == 100