diff options
author | Andreas Rumpf <rumpf_a@web.de> | 2019-04-19 18:02:33 +0200 |
---|---|---|
committer | Andreas Rumpf <rumpf_a@web.de> | 2019-04-19 18:02:43 +0200 |
commit | 44ec66bd484e7cf952c20493a30cf1b29d49e3ca (patch) | |
tree | dbd670461a31b0a2a052aa63f7692251318da873 /tests/destructor | |
parent | bc7d1de7fd17d0cc2fe9895fda3a21f3aec3b891 (diff) | |
download | Nim-44ec66bd484e7cf952c20493a30cf1b29d49e3ca.tar.gz |
fixes #11053
Diffstat (limited to 'tests/destructor')
-rw-r--r-- | tests/destructor/towned_binary_tree.nim | 92 |
1 files changed, 92 insertions, 0 deletions
diff --git a/tests/destructor/towned_binary_tree.nim b/tests/destructor/towned_binary_tree.nim new file mode 100644 index 000000000..372b1d3d8 --- /dev/null +++ b/tests/destructor/towned_binary_tree.nim @@ -0,0 +1,92 @@ +discard """ + cmd: '''nim c --newruntime $file''' + output: '''331665 +allocs 0''' +""" + +# bug #11053 + +import random + +type Node = ref object + x, y: int32 + left, right: owned Node + +proc newNode(x: int32): owned Node = + result = Node(x: x, y: rand(high int32).int32) + +proc merge(lower, greater: owned Node): owned Node = + if lower.isNil: + result = greater + elif greater.isNil: + result = lower + elif lower.y < greater.y: + lower.right = merge(lower.right, greater) + result = lower + else: + greater.left = merge(lower, greater.left) + result = greater + +proc splitBinary(orig: owned Node, value: int32): (owned Node, owned Node) = + if orig.isNil: + result = (nil, nil) + elif orig.x < value: + let splitPair = splitBinary(orig.right, value) + orig.right = splitPair[0] + result = (orig, splitPair[1]) + else: + let splitPair = splitBinary(orig.left, value) + orig.left = splitPair[1] + result = (splitPair[0], orig) + +proc merge3(lower, equal, greater: owned Node): owned Node = + merge(merge(lower, equal), greater) + +proc split(orig: owned Node, value: int32): tuple[lower, equal, greater: owned Node] = + let + (lower, equalGreater) = splitBinary(orig, value) + (equal, greater) = splitBinary(equalGreater, value + 1) + result = (lower, equal, greater) + +type Tree = object + root: owned Node + +proc hasValue(self: var Tree, x: int32): bool = + let splited = split(move self.root, x) + result = not splited.equal.isNil + self.root = merge3(splited.lower, splited.equal, splited.greater) + +proc insert(self: var Tree, x: int32) = + var splited = split(move self.root, x) + if splited.equal.isNil: + splited.equal = newNode(x) + self.root = merge3(splited.lower, splited.equal, splited.greater) + +proc erase(self: var Tree, x: int32) = + let splited = split(move self.root, x) + self.root = merge(splited.lower, splited.greater) + +proc main() = + var + tree = Tree() + cur = 5'i32 + res = 0 + + for i in 1 ..< 1000000: + let a = i mod 3 + cur = (cur * 57 + 43) mod 10007 + case a: + of 0: + tree.insert(cur) + of 1: + tree.erase(cur) + of 2: + if tree.hasValue(cur): + res += 1 + else: + discard + echo res + +when isMainModule: + main() + echo "allocs ", allocs |