From c9ef1efcc78ec484ef35b962c60431a80e8ea09f Mon Sep 17 00:00:00 2001 From: Jaremy Creechley Date: Sat, 24 Dec 2022 21:51:42 -0700 Subject: [PATCH 1/7] add vector slice --- src/parazoa.nim | 31 ++++++++++++++++++++++++++++--- tests/test1.nim | 22 ++++++++++++++++++++++ 2 files changed, 50 insertions(+), 3 deletions(-) diff --git a/src/parazoa.nim b/src/parazoa.nim index 018de25..2f4f0e4 100644 --- a/src/parazoa.nim +++ b/src/parazoa.nim @@ -194,6 +194,10 @@ func toMap*[K, V](arr: openArray[(K, V)]): Map[K, V] = m = m.add(k, v) m +proc `[]`[K, V](m: Map[K, V]; key: K): V = + ## get key + m.get(key) + func `$`*[K, V](m: Map[K, V]): string = ## Returns a string representing the `Map` var x = newSeq[string]() @@ -397,7 +401,8 @@ type value: T Vec*[T] = object root: VecNode[T] - shift: int + shift: int16 + start: int16 size: Natural func initVec*[T](): Vec[T] = @@ -505,7 +510,7 @@ func get*[T](v: Vec[T], key: Natural): T = ## Returns the value at `key`, or raises an exception if out of bounds if key < 0 or key >= v.len: raise newException(IndexError, "Index is out of bounds") - get(v.root, v.shift * parazoaBits, key) + get(v.root, v.shift * parazoaBits, key + v.start) func getOrDefault*[T](v: Vec[T], key: Natural, defaultValue: T): T = ## Returns the value at `key`, or `defaultValue` if not found @@ -516,7 +521,7 @@ func getOrDefault*[T](v: Vec[T], key: Natural, defaultValue: T): T = iterator pairs*[T](v: Vec[T]): (Natural, T) = ## Iterates over the indexes and values in the `Vec` - var stack: seq[tuple[parent: VecNode[T], index: int]] = @[(v.root, 0)] + var stack: seq[tuple[parent: VecNode[T], index: int]] = @[(v.root, v.start.int)] var key: Natural = 0 while stack.len > 0: let (parent, index) = stack[stack.len-1] @@ -533,6 +538,8 @@ iterator pairs*[T](v: Vec[T]): (Natural, T) = of Branch: stack.add((node, 0)) of Leaf: + if key >= v.size: + break yield (key, node.value) stack[stack.len-1].index += 1 key += 1 @@ -542,6 +549,18 @@ iterator items*[T](v: Vec[T]): T = for (i, v) in v.pairs: yield v +proc `[]`[T](v: Vec[T]; key: Natural): T = + ## get key + v.get(key) + +proc `[]`[T; U, V: Ordinal](v: Vec[T]; x: HSlice[U, V]): Vec[T] = + ## Returns the value at `key`, or raises an exception if out of bounds + if x.a < 0 or x.a > x.b or x.b > v.size: + raise newException(IndexError, "Index is out of bounds") + result = v + result.start = x.a.int16 + result.size = x.b - x.a + 1 + func `==`*[T](v1: Vec[T], v2: Vec[T]): bool = ## Returns whether the `Vec`s are equal if v1.len != v2.len: @@ -561,6 +580,12 @@ func toVec*[T](arr: openArray[T]): Vec[T] = v = v.add(k) v +func toSeq*[T](v: Vec[T]): seq[T] = + ## Returns a `seq` containing the values in `Vec` + result = newSeqOfCap[T](v.len) + for k in v: + result.add(k) + func `$`*[T](v: Vec[T]): string = ## Returns a string representing the `Vec` var x = newSeq[string]() diff --git a/tests/test1.nim b/tests/test1.nim index 39925c1..4b65cf0 100644 --- a/tests/test1.nim +++ b/tests/test1.nim @@ -11,6 +11,7 @@ test "maps": expect(KeyError): discard m1.get("hello") check m2.get("hello") == "world" + check m2["hello"] == "world" let m3 = m2.add("hello", "goodbye") expect(KeyError): discard m1.get("hello") @@ -134,6 +135,27 @@ test "vecs": check v9.get(49) == "" check v9.shift == 1 +test "vecs slice": + var v1 = initVec[string]() + v1 = v1.add("one") + v1 = v1.add("two") + v1 = v1.add("three") + v1 = v1.add("four") + check v1.len() == 4 + + let s1 = v1[1..2] + check s1.len() == 2 + check s1[0] == "two" + check s1[1] == "three" + check s1.toSeq == @["two", "three"] + + let s2 = v1[1..1] + echo "S2: ", s2 + check s2.len() == 1 + check s2[0] == "two" + check s2.toSeq == @["two"] + + import hashes test "partial hash collisions": From 1252fa54bab50a70bc021babbfeb2c9680068872 Mon Sep 17 00:00:00 2001 From: Jaremy Creechley Date: Sat, 24 Dec 2022 22:01:52 -0700 Subject: [PATCH 2/7] add for set --- src/parazoa.nim | 4 ++++ tests/test1.nim | 1 + 2 files changed, 5 insertions(+) diff --git a/src/parazoa.nim b/src/parazoa.nim index d2fdde5..cbd1265 100644 --- a/src/parazoa.nim +++ b/src/parazoa.nim @@ -394,6 +394,10 @@ func `&`*[T](s1: Set[T], s2: Set[T]): Set[T] = res = res.add(k) res +func `in`*[T](s: Set[T], key: T): bool = + ## Returns whether `key` is inside the `Set` + s.contains(key) + func add*[T](s1: var Set[T], s2: Set[T]) = ## Unites the second `Set` into the first one ## (This sets the var to a new `Set` -- the old `Set` is not mutated) diff --git a/tests/test1.nim b/tests/test1.nim index 866b07e..46d2159 100644 --- a/tests/test1.nim +++ b/tests/test1.nim @@ -68,6 +68,7 @@ test "sets": check not s1.contains("hello") check s2.contains("hello") check s3.contains("goodbye") + check "goodbye" in s3 let s4 = s3.incl("what's") let s5 = s3.excl("what's").excl("asdf") check s1.len == 0 From f0668de5bf769ac68f0c3a9600e1a4b1a8334b76 Mon Sep 17 00:00:00 2001 From: Jaremy Creechley Date: Sat, 24 Dec 2022 22:14:30 -0700 Subject: [PATCH 3/7] remove in --- src/parazoa.nim | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/parazoa.nim b/src/parazoa.nim index cbd1265..d2fdde5 100644 --- a/src/parazoa.nim +++ b/src/parazoa.nim @@ -394,10 +394,6 @@ func `&`*[T](s1: Set[T], s2: Set[T]): Set[T] = res = res.add(k) res -func `in`*[T](s: Set[T], key: T): bool = - ## Returns whether `key` is inside the `Set` - s.contains(key) - func add*[T](s1: var Set[T], s2: Set[T]) = ## Unites the second `Set` into the first one ## (This sets the var to a new `Set` -- the old `Set` is not mutated) From e0eb29e63145eb9d60d485a996a5a3c4aa55e3f7 Mon Sep 17 00:00:00 2001 From: Jaremy Creechley Date: Sun, 25 Dec 2022 14:27:49 -0700 Subject: [PATCH 4/7] add vector delete --- src/parazoa.nim | 23 +++++++++++++++++++++++ tests/test1.nim | 17 +++++++++++++++++ 2 files changed, 40 insertions(+) diff --git a/src/parazoa.nim b/src/parazoa.nim index d2fdde5..a13d0db 100644 --- a/src/parazoa.nim +++ b/src/parazoa.nim @@ -462,6 +462,29 @@ func add*[T](v: Vec[T], value: T): Vec[T] = ## Adds a new value to the `Vec` add(v, v.len, value) +func del[T](res: var Vec[T], node: VecNode[T], level: int, key: Natural) = + let + index = (key shr level) and mask + child = node.nodes[index] + if child == nil: + discard + else: + case child.kind: + of Branch: + let newChild = copyRef(child) + node.nodes[index] = newChild + del(res, newChild, level + parazoaBits, key) + of Leaf: + node.nodes[index ..< ^2] = node.nodes[index+1 ..< ^1] + node.nodes[^1] = nil + res.size -= 1 + +func del*[T](m: Vec[T], key: Natural): Vec[T] = + ## delete node at index + result = m + result.root = copyRef(m.root) + del(result, result.root, 0, key) + func setLen*[T](v: Vec[T], newLen: Natural): Vec[T] = ## Updates the length of `Vec` var res = v diff --git a/tests/test1.nim b/tests/test1.nim index 08b0a13..b47f8f2 100644 --- a/tests/test1.nim +++ b/tests/test1.nim @@ -155,6 +155,18 @@ test "vecs": check v10.add("hello").get(0) == "hello" check v10 == v1 +test "vecs del": + var v1 = initVec[string]() + v1 = v1.add("one") + v1 = v1.add("two") + v1 = v1.add("three") + v1 = v1.add("four") + check v1.len() == 4 + + let v2 = v1.del(2) + check v1.toSeq == @["one", "two", "three", "four"] + check v2.toSeq == @["one", "two", "four"] + test "vecs slice": var v1 = initVec[string]() v1 = v1.add("one") @@ -169,11 +181,16 @@ test "vecs slice": check s1[1] == "three" check s1.toSeq == @["two", "three"] + echo "\nNEW SLICE" let s2 = v1[1..1] check s2.len() == 1 check s2[0] == "two" check s2.toSeq == @["two"] + let v2 = s1.add("five") + echo "s1: ", s1 + echo "v2: ", v2 + import hashes From 9d76d7501450f2385b90986c0bc5937a61981763 Mon Sep 17 00:00:00 2001 From: Jaremy Creechley Date: Sun, 25 Dec 2022 14:28:34 -0700 Subject: [PATCH 5/7] add vector delete --- src/parazoa.nim | 44 ++++++++++++++++++++++---------------------- 1 file changed, 22 insertions(+), 22 deletions(-) diff --git a/src/parazoa.nim b/src/parazoa.nim index a13d0db..c674801 100644 --- a/src/parazoa.nim +++ b/src/parazoa.nim @@ -420,6 +420,28 @@ func len*[T](v: Vec[T]): Natural = ## Returns the number of values in the `Vec` v.size +func del[T](res: var Vec[T], node: VecNode[T], level: int, key: Natural) = + let + index = (key shr level) and mask + child = node.nodes[index] + if child == nil: + discard + else: + case child.kind: + of Branch: + let newChild = copyRef(child) + node.nodes[index] = newChild + del(res, newChild, level + parazoaBits, key) + of Leaf: + node.nodes[index ..< ^2] = node.nodes[index+1 ..< ^1] + node.nodes[^1] = nil + res.size -= 1 + +func del*[T](m: Vec[T], key: Natural): Vec[T] = + ## delete node at index + result = m + result.root = copyRef(m.root) + del(result, result.root, 0, key) func add[T](res: var Vec[T], node: VecNode[T], level: int, key: Natural, value: T) = let index = (key shr level) and mask @@ -462,28 +484,6 @@ func add*[T](v: Vec[T], value: T): Vec[T] = ## Adds a new value to the `Vec` add(v, v.len, value) -func del[T](res: var Vec[T], node: VecNode[T], level: int, key: Natural) = - let - index = (key shr level) and mask - child = node.nodes[index] - if child == nil: - discard - else: - case child.kind: - of Branch: - let newChild = copyRef(child) - node.nodes[index] = newChild - del(res, newChild, level + parazoaBits, key) - of Leaf: - node.nodes[index ..< ^2] = node.nodes[index+1 ..< ^1] - node.nodes[^1] = nil - res.size -= 1 - -func del*[T](m: Vec[T], key: Natural): Vec[T] = - ## delete node at index - result = m - result.root = copyRef(m.root) - del(result, result.root, 0, key) func setLen*[T](v: Vec[T], newLen: Natural): Vec[T] = ## Updates the length of `Vec` From e5901b825708e8887e7c6eb5f82d8536ff31934b Mon Sep 17 00:00:00 2001 From: Jaremy Creechley Date: Sun, 25 Dec 2022 14:51:21 -0700 Subject: [PATCH 6/7] fixup case for adding to slice --- src/parazoa.nim | 7 ++++++- tests/test1.nim | 15 +++++++++++---- 2 files changed, 17 insertions(+), 5 deletions(-) diff --git a/src/parazoa.nim b/src/parazoa.nim index c674801..27afc80 100644 --- a/src/parazoa.nim +++ b/src/parazoa.nim @@ -442,6 +442,7 @@ func del*[T](m: Vec[T], key: Natural): Vec[T] = result = m result.root = copyRef(m.root) del(result, result.root, 0, key) + func add[T](res: var Vec[T], node: VecNode[T], level: int, key: Natural, value: T) = let index = (key shr level) and mask @@ -463,13 +464,15 @@ func add[T](res: var Vec[T], node: VecNode[T], level: int, key: Natural, value: of Leaf: newChild.value = value node.nodes[index] = newChild + res.size.inc() func add*[T](v: Vec[T], key: Natural, value: T): Vec[T] = ## Updates the existing value at `key` if key < 0 or key > v.len: raise newException(IndexError, "Index is out of bounds") + let key = key + v.start var res = v - if key == v.len and key == branchWidth ^ (v.shift + 1): + if key == v.len + v.start and key == branchWidth ^ (v.shift + 1): res.root = VecNode[T](kind: Branch) res.shift = v.shift + 1 res.size = v.len @@ -477,6 +480,8 @@ func add*[T](v: Vec[T], key: Natural, value: T): Vec[T] = res.root.nodes[index] = v.root else: res.root = copyRef(v.root) + for i in 0 ..< res.start: + res.root.nodes[i] = nil add(res, res.root, res.shift * parazoaBits, key, value) res diff --git a/tests/test1.nim b/tests/test1.nim index b47f8f2..30e5805 100644 --- a/tests/test1.nim +++ b/tests/test1.nim @@ -164,9 +164,13 @@ test "vecs del": check v1.len() == 4 let v2 = v1.del(2) - check v1.toSeq == @["one", "two", "three", "four"] check v2.toSeq == @["one", "two", "four"] + let v3 = v2.del(0) + check v3.toSeq == @["two", "four"] + + check v1.toSeq == @["one", "two", "three", "four"] + test "vecs slice": var v1 = initVec[string]() v1 = v1.add("one") @@ -181,16 +185,19 @@ test "vecs slice": check s1[1] == "three" check s1.toSeq == @["two", "three"] - echo "\nNEW SLICE" let s2 = v1[1..1] check s2.len() == 1 check s2[0] == "two" check s2.toSeq == @["two"] let v2 = s1.add("five") - echo "s1: ", s1 - echo "v2: ", v2 + check v2.toSeq == @["two", "three", "five"] + + let v3 = v2.add("six") + check v3.toSeq == @["two", "three", "five", "six"] + check v2.toSeq == @["two", "three", "five"] + check s1.toSeq == @["two", "three"] import hashes From a319c32f981b3007c13ea6ba7b8dbead815ac38b Mon Sep 17 00:00:00 2001 From: Jaremy Creechley Date: Sun, 25 Dec 2022 14:52:02 -0700 Subject: [PATCH 7/7] fixup case for adding to slice --- src/parazoa.nim | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/parazoa.nim b/src/parazoa.nim index 27afc80..7c70a95 100644 --- a/src/parazoa.nim +++ b/src/parazoa.nim @@ -450,7 +450,7 @@ func add[T](res: var Vec[T], node: VecNode[T], level: int, key: Natural, value: if child == nil: if level == 0: node.nodes[index] = VecNode[T](kind: Leaf, value: value) - res.size += 1 + res.size.inc() else: let newChild = VecNode[T](kind: Branch) node.nodes[index] = newChild