Fix iterator edge cases for [high(P),high(P)] (#129)

also:
  cascaded `if` in rbtree (for unrelated troubleshooting)
This commit is contained in:
Jordan Hrycaj 2022-07-18 18:56:31 +01:00 committed by GitHub
parent f173efc500
commit 8a9816ac02
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 43 additions and 17 deletions

View File

@ -849,13 +849,17 @@ iterator increasing*[P,S](
## any interval already visited. Intervals not visited yet must not be ## any interval already visited. Intervals not visited yet must not be
## deleted as the loop would become unpredictable. ## deleted as the loop would become unpredictable.
var rc = ds.leftPos.ge(minPt) var rc = ds.leftPos.ge(minPt)
while rc.isOk: if rc.isErr:
let key = rc.value.key if ds.lastHigh:
if high(P) <= rc.value.right and ds.lastHigh: yield Interval[P,S].new(high(P),high(P))
yield Interval[P,S].new(rc.value.left,high(P)) else:
else: while rc.isOk:
yield Interval[P,S].new(rc.value) let key = rc.value.key
rc = ds.leftPos.gt(key) if high(P) <= rc.value.right and ds.lastHigh:
yield Interval[P,S].new(rc.value.left,high(P))
else:
yield Interval[P,S].new(rc.value)
rc = ds.leftPos.gt(key)
iterator decreasing*[P,S]( iterator decreasing*[P,S](
ds: IntervalSetRef[P,S]; ds: IntervalSetRef[P,S];
@ -866,8 +870,10 @@ iterator decreasing*[P,S](
## ##
## See the note at the `increasing()` function comment about deleting items. ## See the note at the `increasing()` function comment about deleting items.
var rc = ds.leftPos.le(maxPt) var rc = ds.leftPos.le(maxPt)
if rc.isErr:
if rc.isOk: if ds.lastHigh:
yield Interval[P,S].new(high(P),high(P))
else:
let key = rc.value.key let key = rc.value.key
# last entry: check for additional point # last entry: check for additional point
if high(P) <= rc.value.right and ds.lastHigh: if high(P) <= rc.value.right and ds.lastHigh:
@ -877,10 +883,10 @@ iterator decreasing*[P,S](
# find the next smaller one # find the next smaller one
rc = ds.leftPos.lt(key) rc = ds.leftPos.lt(key)
while rc.isOk: while rc.isOk:
let key = rc.value.key let key = rc.value.key
yield Interval[P,S].new(rc.value) yield Interval[P,S].new(rc.value)
rc = ds.leftPos.lt(key) rc = ds.leftPos.lt(key)
# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------
# Public interval operators # Public interval operators

View File

@ -119,8 +119,9 @@ proc rbTreeDelete*[C,K](rbt: RbTreeRef[C,K]; key: K): RbResult[C] =
dirY = q.linkLeft.isNil.toDir dirY = q.linkLeft.isNil.toDir
parent.link[dirX] = q.link[dirY]; parent.link[dirX] = q.link[dirY];
# clear node cache if this was the one to be deleted # clear node cache if this was the one to be deleted
if not rbt.cache.isNil and rbt.cmp(rbt.cache.casket,key) == 0: if not rbt.cache.isNil:
rbt.cache = nil if rbt.cmp(rbt.cache.casket,key) == 0:
rbt.cache = nil
q = nil # some hint for the GC to recycle that node q = nil # some hint for the GC to recycle that node
rbt.size.dec rbt.size.dec

View File

@ -31,8 +31,9 @@ proc rbTreeFindEq*[C,K](rbt: RbTreeRef[C,K]; key: K): RbResult[C] =
if rbt.root.isNil: if rbt.root.isNil:
return err(rbEmptyTree) return err(rbEmptyTree)
if not rbt.cache.isNil and rbt.cmp(rbt.cache.casket,key) == 0: if not rbt.cache.isNil:
return ok(rbt.cache.casket) if rbt.cmp(rbt.cache.casket,key) == 0:
return ok(rbt.cache.casket)
var var
q = rbt.root q = rbt.root

View File

@ -177,6 +177,24 @@ suite "IntervalSet: Intervals of FancyPoint entries over FancyScalar":
check br.total.truncate(uint64) == (uHigh - 10000000) + 1 check br.total.truncate(uint64) == (uHigh - 10000000) + 1
check br.verify.isOk check br.verify.isOk
br.clear()
check br.total == 0 and br.chunks == 0
check br.merge(uHigh,uHigh) == 1
block:
var (ivVal, ivSet) = (iv(0,0), false)
for iv in br.increasing:
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:
check ivSet == false
(ivVal, ivSet) = (iv, true)
check ivVal == iv(uHigh,uHigh)
test "Merge disjunct intervals on 1st set": test "Merge disjunct intervals on 1st set":
br.clear() br.clear()
check br.merge( 0, 99) == 100 check br.merge( 0, 99) == 100