diff --git a/src/karaxdb/btree.nim b/src/karaxdb/btree.nim index e64396f..66e87f9 100644 --- a/src/karaxdb/btree.nim +++ b/src/karaxdb/btree.nim @@ -169,6 +169,83 @@ proc dos(x: Node; kind: CmpKind; key: Key; withKey: proc(k: Key; v: Val)) = for i in followA..followB: dos(x.links[i], kind, key, withKey) +proc don(x: Node; kind: CmpKind; key: Key; withKey: proc(k: Key; v: Val)) = + var stack = @[x] + while stack.len > 0: + let x = stack.pop() + if not x.isInternal: + for j in 0 ..< x.m: + if cmp(x.keys[j], key) =~ kind: + withKey(x.keys[j], x.vals[j]) + else: + # we compute the range of links to follow first, before + # recursing: + var followA = 0 + var followB = -1 + case kind + of CmpKind.eq: + # want: key == 10 + # keys: 0 3 4 5 10 20 + # keys: 20 30 40 + for j in 1..x.m: + if j == x.m or cmp(key, x.keys[j]) < 0: + followA = j-1 + followB = j-1 + break + of CmpKind.le, CmpKind.lt: + # want: key <= 10 or key < 10 + # keys: 0 3 4 5 10 20 + # keys: 20 30 40 + + # Case A: all keys are bigger: + if cmp(key, x.keys[1]) < 0: + # --> use the very first branch + followA = 0 + followB = 0 + else: + # Case B: all keys are smaller --> use all branches is covered too + # by this loop. + for j in 1..= 0: + if followB < 0: followA = j-1 + # if the keys are identical and we require 'lt', we know + # only the left branch is required: + followB = j - ord(kind == CmpKind.lt and cmpRes == 0) + else: + # it's already greater, all others are greater too: + break + of CmpKind.ge, CmpKind.gt: + # want: key >= 10 or key > 10 + # keys: 0 3 4 5 10 20 + # keys: 20 30 40 + + # Case A: all keys are smaller: + if cmp(key, x.keys[x.m-1]) >= 0: + # --> use the very last branch + followA = x.m-1 + followB = x.m-1 + else: + # also covers case B: all keys are bigger --> use all branches + # we find the key that is bigger or equal to ours and from + # then on, follow every branch: + for j in 1.. 5" dos(b1.root, CmpKind.gt, "5", proc(k: Key; v: Val) = echo("k ", k, " = ", v)) + echo "======================================================================" + echo " >= 5" + don(b1.root, CmpKind.ge, "5", proc(k: Key; v: Val) = echo("k ", k, " = ", v)) + echo " <= 5" + don(b1.root, CmpKind.le, "5", proc(k: Key; v: Val) = echo("k ", k, " = ", v)) + + echo " == 5" + don(b1.root, CmpKind.eq, "5", proc(k: Key; v: Val) = echo("k ", k, " = ", v)) + echo " < 5" + don(b1.root, CmpKind.lt, "5", proc(k: Key; v: Val) = echo("k ", k, " = ", v)) + echo " > 5" + don(b1.root, CmpKind.gt, "5", proc(k: Key; v: Val) = echo("k ", k, " = ", v)) + main()