Fix ge() fringe case (#135)

why:
  The point `high(P)` is treated separately and added to the top adjacent
  interval or is treated as a sigle point interval.
This commit is contained in:
Jordan Hrycaj 2022-07-25 15:05:27 +01:00 committed by GitHub
parent 598246620d
commit c020fd80f1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 34 additions and 8 deletions

View File

@ -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)

View File

@ -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