diff options
author | EuAndreh <eu@euandre.org> | 2025-01-22 07:44:09 -0300 |
---|---|---|
committer | EuAndreh <eu@euandre.org> | 2025-01-22 07:51:07 -0300 |
commit | 342945dc4ff166517fb89e38f28e027e3b71f8c8 (patch) | |
tree | fb63c8bf13121c3a98b0eb73551ff548a566b8cf /src/pds.go | |
parent | tests/pds.go: Init removal of "testing" usage (diff) | |
download | pds-342945dc4ff166517fb89e38f28e027e3b71f8c8.tar.gz pds-342945dc4ff166517fb89e38f28e027e3b71f8c8.tar.xz |
s/List/Vector/g
Diffstat (limited to 'src/pds.go')
-rw-r--r-- | src/pds.go | 403 |
1 files changed, 210 insertions, 193 deletions
@@ -4,7 +4,7 @@ // // Immutable collections provide an efficient, safe way to share collections // of data while minimizing locks. The collections in this package provide -// List, Map, and SortedMap implementations. These act similarly to slices +// Vector, Map, and SortedMap implementations. These act similarly to slices // and maps, respectively, except that altering a collection returns a new // copy of the collection with that change. // @@ -16,9 +16,9 @@ // // # Collection Types // -// The List type provides an API similar to Go slices. They allow appending, +// The Vector type provides an API similar to Go slices. They allow appending, // prepending, and updating of elements. Elements can also be fetched by index -// or iterated over using a ListIterator. +// or iterated over using a VectorIterator. // // The Map & SortedMap types provide an API similar to Go maps. They allow // values to be assigned to unique keys and allow for the deletion of keys. @@ -50,20 +50,20 @@ import ( "strings" ) -// List is a dense, ordered, indexed collections. They are analogous to slices -// in Go. They can be updated by appending to the end of the list, prepending -// values to the beginning of the list, or updating existing indexes in the -// list. -type List[T any] struct { - root listNode[T] // root node +// Vector is a dense, ordered, indexed collections. They are analogous to slices +// in Go. They can be updated by appending to the end of the vector, prepending +// values to the beginning of the vector, or updating existing indexes in the +// vector. +type Vector[T any] struct { + root vectorNode[T] // root node origin int // offset to zero index element size int // total number of elements in use } -// NewList returns a new empty instance of List. -func NewList[T any](values ...T) *List[T] { - l := &List[T]{ - root: &listLeafNode[T]{}, +// NewVector returns a new empty instance of Vector. +func NewVector[T any](values ...T) *Vector[T] { + l := &Vector[T]{ + root: &vectorLeafNode[T]{}, } for _, value := range values { l.append(value, true) @@ -71,41 +71,47 @@ func NewList[T any](values ...T) *List[T] { return l } -// clone returns a copy of the list. -func (l *List[T]) clone() *List[T] { +// clone returns a copy of the vector. +func (l *Vector[T]) clone() *Vector[T] { other := *l return &other } -// Len returns the number of elements in the list. -func (l *List[T]) Len() int { +// Len returns the number of elements in the vector. +func (l *Vector[T]) Len() int { return l.size } // cap returns the total number of possible elements for the current depth. -func (l *List[T]) cap() int { - return 1 << (l.root.depth() * listNodeBits) +func (l *Vector[T]) cap() int { + return 1 << (l.root.depth() * vectorNodeBits) } // Get returns the value at the given index. Similar to slices, this method will -// panic if index is below zero or is greater than or equal to the list size. -func (l *List[T]) Get(index int) T { +// panic if index is below zero or is greater than or equal to the vector size. +func (l *Vector[T]) Get(index int) T { if index < 0 || index >= l.size { - panic(fmt.Sprintf("immutable.List.Get: index %d out of bounds", index)) + panic(fmt.Sprintf( + "immutable.Vector.Get: index %d out of bounds", + index, + )) } return l.root.get(l.origin + index) } -// Set returns a new list with value set at index. Similar to slices, this +// Set returns a new vector with value set at index. Similar to slices, this // method will panic if index is below zero or if the index is greater than -// or equal to the list size. -func (l *List[T]) Set(index int, value T) *List[T] { +// or equal to the vector size. +func (l *Vector[T]) Set(index int, value T) *Vector[T] { return l.set(index, value, false) } -func (l *List[T]) set(index int, value T, mutable bool) *List[T] { +func (l *Vector[T]) set(index int, value T, mutable bool) *Vector[T] { if index < 0 || index >= l.size { - panic(fmt.Sprintf("immutable.List.Set: index %d out of bounds", index)) + panic(fmt.Sprintf( + "immutable.Vector.Set: index %d out of bounds", + index, + )) } other := l if !mutable { @@ -115,20 +121,20 @@ func (l *List[T]) set(index int, value T, mutable bool) *List[T] { return other } -// Append returns a new list with value added to the end of the list. -func (l *List[T]) Append(value T) *List[T] { +// Append returns a new vector with value added to the end of the vector. +func (l *Vector[T]) Append(value T) *Vector[T] { return l.append(value, false) } -func (l *List[T]) append(value T, mutable bool) *List[T] { +func (l *Vector[T]) append(value T, mutable bool) *Vector[T] { other := l if !mutable { other = l.clone() } - // Expand list to the right if no slots remain. + // Expand vector to the right if no slots remain. if other.size+other.origin >= l.cap() { - newRoot := &listBranchNode[T]{d: other.root.depth() + 1} + newRoot := &vectorBranchNode[T]{d: other.root.depth() + 1} newRoot.children[0] = other.root other.root = newRoot } @@ -139,23 +145,25 @@ func (l *List[T]) append(value T, mutable bool) *List[T] { return other } -// Prepend returns a new list with value(s) added to the beginning of the list. -func (l *List[T]) Prepend(value T) *List[T] { +// Prepend returns a new vector with value(s) added to the beginning of the +// vector. +func (l *Vector[T]) Prepend(value T) *Vector[T] { return l.prepend(value, false) } -func (l *List[T]) prepend(value T, mutable bool) *List[T] { +func (l *Vector[T]) prepend(value T, mutable bool) *Vector[T] { other := l if !mutable { other = l.clone() } - // Expand list to the left if no slots remain. + // Expand vector to the left if no slots remain. if other.origin == 0 { - newRoot := &listBranchNode[T]{d: other.root.depth() + 1} - newRoot.children[listNodeSize-1] = other.root + newRoot := &vectorBranchNode[T]{d: other.root.depth() + 1} + newRoot.children[vectorNodeSize-1] = other.root other.root = newRoot - other.origin += (listNodeSize - 1) << (other.root.depth() * listNodeBits) + other.origin += (vectorNodeSize - 1) << + ((other.root.depth() * vectorNodeBits)) } // Increase size and move origin back. Update first element to value. @@ -165,28 +173,31 @@ func (l *List[T]) prepend(value T, mutable bool) *List[T] { return other } -// Slice returns a new list of elements between start index and end index. +// Slice returns a new vector of elements between start index and end index. // Similar to slices, this method will panic if start or end are below zero or -// greater than the list size. A panic will also occur if start is greater than -// end. +// greater than the vector size. A panic will also occur if start is greater +// than end. // // Unlike Go slices, references to inaccessible elements will be automatically // removed so they can be garbage collected. -func (l *List[T]) Slice(start, end int) *List[T] { +func (l *Vector[T]) Slice(start, end int) *Vector[T] { return l.slice(start, end, false) } -func (l *List[T]) slice(start, end int, mutable bool) *List[T] { +func (l *Vector[T]) slice(start, end int, mutable bool) *Vector[T] { // Panics similar to Go slices. if start < 0 || start > l.size { - panic(fmt.Sprintf("immutable.List.Slice: start index %d out of bounds", start)) + panic(fmt.Sprintf( + "immutable.Vector.Slice: start index %d out of bounds", + start, + )) } else if end < 0 || end > l.size { - panic(fmt.Sprintf("immutable.List.Slice: end index %d out of bounds", end)) + panic(fmt.Sprintf("immutable.Vector.Slice: end index %d out of bounds", end)) } else if start > end { - panic(fmt.Sprintf("immutable.List.Slice: invalid slice index: [%d:%d]", start, end)) + panic(fmt.Sprintf("immutable.Vector.Slice: invalid slice index: [%d:%d]", start, end)) } - // Return the same list if the start and end are the entire range. + // Return the same vector if the start and end are the entire range. if start == 0 && end == l.size { return l } @@ -203,15 +214,16 @@ func (l *List[T]) slice(start, end int, mutable bool) *List[T] { // Contract tree while the start & end are in the same child node. for other.root.depth() > 1 { - i := (other.origin >> (other.root.depth() * listNodeBits)) & listNodeMask - j := ((other.origin + other.size - 1) >> (other.root.depth() * listNodeBits)) & listNodeMask + i := (other.origin >> (other.root.depth() * vectorNodeBits)) & vectorNodeMask + j := ((other.origin + other.size - 1) >> (other.root.depth() * vectorNodeBits)) & vectorNodeMask if i != j { break // branch contains at least two nodes, exit } - // Replace the current root with the single child & update origin offset. - other.origin -= i << (other.root.depth() * listNodeBits) - other.root = other.root.(*listBranchNode[T]).children[i] + // Replace the current root with the single child & update + // origin offset. + other.origin -= i << (other.root.depth() * vectorNodeBits) + other.root = other.root.(*vectorBranchNode[T]).children[i] } // Ensure all references are removed before start & after end. @@ -221,133 +233,138 @@ func (l *List[T]) slice(start, end int, mutable bool) *List[T] { return other } -// Iterator returns a new iterator for this list positioned at the first index. -func (l *List[T]) Iterator() *ListIterator[T] { - itr := &ListIterator[T]{list: l} +// Iterator returns a new iterator for this vector positioned at the first +// index. +func (l *Vector[T]) Iterator() *VectorIterator[T] { + itr := &VectorIterator[T]{vector: l} itr.First() return itr } -// ListBuilder represents an efficient builder for creating new Lists. -type ListBuilder[T any] struct { - list *List[T] // current state +// VectorBuilder represents an efficient builder for creating new Vectors. +type VectorBuilder[T any] struct { + vector *Vector[T] // current state } -// NewListBuilder returns a new instance of ListBuilder. -func NewListBuilder[T any]() *ListBuilder[T] { - return &ListBuilder[T]{list: NewList[T]()} +// NewVectorBuilder returns a new instance of VectorBuilder. +func NewVectorBuilder[T any]() *VectorBuilder[T] { + return &VectorBuilder[T]{vector: NewVector[T]()} } -// List returns the current copy of the list. -// The builder should not be used again after the list after this call. -func (b *ListBuilder[T]) List() *List[T] { - assert(b.list != nil, "immutable.ListBuilder.List(): duplicate call to fetch list") - list := b.list - b.list = nil - return list +// Vector returns the current copy of the vector. +// The builder should not be used again after the vector after this call. +func (b *VectorBuilder[T]) Vector() *Vector[T] { + assert(b.vector != nil, "immutable.VectorBuilder.Vector(): duplicate call to fetch vector") + vector := b.vector + b.vector = nil + return vector } -// Len returns the number of elements in the underlying list. -func (b *ListBuilder[T]) Len() int { - assert(b.list != nil, "immutable.ListBuilder: builder invalid after List() invocation") - return b.list.Len() +// Len returns the number of elements in the underlying vector. +func (b *VectorBuilder[T]) Len() int { + assert(b.vector != nil, "immutable.VectorBuilder: builder invalid after Vector() invocation") + return b.vector.Len() } // Get returns the value at the given index. Similar to slices, this method will -// panic if index is below zero or is greater than or equal to the list size. -func (b *ListBuilder[T]) Get(index int) T { - assert(b.list != nil, "immutable.ListBuilder: builder invalid after List() invocation") - return b.list.Get(index) +// panic if index is below zero or is greater than or equal to the vector size. +func (b *VectorBuilder[T]) Get(index int) T { + assert(b.vector != nil, "immutable.VectorBuilder: builder invalid after Vector() invocation") + return b.vector.Get(index) } // Set updates the value at the given index. Similar to slices, this method will // panic if index is below zero or if the index is greater than or equal to the -// list size. -func (b *ListBuilder[T]) Set(index int, value T) { - assert(b.list != nil, "immutable.ListBuilder: builder invalid after List() invocation") - b.list = b.list.set(index, value, true) +// vector size. +func (b *VectorBuilder[T]) Set(index int, value T) { + assert(b.vector != nil, "immutable.VectorBuilder: builder invalid after Vector() invocation") + b.vector = b.vector.set(index, value, true) } -// Append adds value to the end of the list. -func (b *ListBuilder[T]) Append(value T) { - assert(b.list != nil, "immutable.ListBuilder: builder invalid after List() invocation") - b.list = b.list.append(value, true) +// Append adds value to the end of the vector. +func (b *VectorBuilder[T]) Append(value T) { + assert(b.vector != nil, "immutable.VectorBuilder: builder invalid after Vector() invocation") + b.vector = b.vector.append(value, true) } -// Prepend adds value to the beginning of the list. -func (b *ListBuilder[T]) Prepend(value T) { - assert(b.list != nil, "immutable.ListBuilder: builder invalid after List() invocation") - b.list = b.list.prepend(value, true) +// Prepend adds value to the beginning of the vector. +func (b *VectorBuilder[T]) Prepend(value T) { + assert(b.vector != nil, "immutable.VectorBuilder: builder invalid after Vector() invocation") + b.vector = b.vector.prepend(value, true) } -// Slice updates the list with a sublist of elements between start and end index. -// See List.Slice() for more details. -func (b *ListBuilder[T]) Slice(start, end int) { - assert(b.list != nil, "immutable.ListBuilder: builder invalid after List() invocation") - b.list = b.list.slice(start, end, true) +// Slice updates the vector with a subvector of elements between start and end +// index. +// See Vector.Slice() for more details. +func (b *VectorBuilder[T]) Slice(start, end int) { + assert(b.vector != nil, "immutable.VectorBuilder: builder invalid after Vector() invocation") + b.vector = b.vector.slice(start, end, true) } -// Iterator returns a new iterator for the underlying list. -func (b *ListBuilder[T]) Iterator() *ListIterator[T] { - assert(b.list != nil, "immutable.ListBuilder: builder invalid after List() invocation") - return b.list.Iterator() +// Iterator returns a new iterator for the underlying vector. +func (b *VectorBuilder[T]) Iterator() *VectorIterator[T] { + assert(b.vector != nil, "immutable.VectorBuilder: builder invalid after Vector() invocation") + return b.vector.Iterator() } -// Constants for bit shifts used for levels in the List trie. +// Constants for bit shifts used for levels in the Vector trie. const ( - listNodeBits = 5 - listNodeSize = 1 << listNodeBits - listNodeMask = listNodeSize - 1 + vectorNodeBits = 5 + vectorNodeSize = 1 << vectorNodeBits + vectorNodeMask = vectorNodeSize - 1 ) -// listNode represents either a branch or leaf node in a List. -type listNode[T any] interface { +// vectorNode represents either a branch or leaf node in a Vector. +type vectorNode[T any] interface { depth() uint get(index int) T - set(index int, v T, mutable bool) listNode[T] + set(index int, v T, mutable bool) vectorNode[T] containsBefore(index int) bool containsAfter(index int) bool - deleteBefore(index int, mutable bool) listNode[T] - deleteAfter(index int, mutable bool) listNode[T] + deleteBefore(index int, mutable bool) vectorNode[T] + deleteAfter(index int, mutable bool) vectorNode[T] } -// newListNode returns a leaf node for depth zero, otherwise returns a branch node. -func newListNode[T any](depth uint) listNode[T] { +// newVectorNode returns a leaf node for depth zero, otherwise returns a branch +// node. +func newVectorNode[T any](depth uint) vectorNode[T] { if depth == 0 { - return &listLeafNode[T]{} + return &vectorLeafNode[T]{} } - return &listBranchNode[T]{d: depth} + return &vectorBranchNode[T]{d: depth} } -// listBranchNode represents a branch of a List tree at a given depth. -type listBranchNode[T any] struct { +// vectorBranchNode represents a branch of a Vector tree at a given depth. +type vectorBranchNode[T any] struct { d uint // depth - children [listNodeSize]listNode[T] + children [vectorNodeSize]vectorNode[T] } // depth returns the depth of this branch node from the leaf. -func (n *listBranchNode[T]) depth() uint { return n.d } +func (n *vectorBranchNode[T]) depth() uint { return n.d } // get returns the child node at the segment of the index for this depth. -func (n *listBranchNode[T]) get(index int) T { - idx := (index >> (n.d * listNodeBits)) & listNodeMask +func (n *vectorBranchNode[T]) get(index int) T { + idx := (index >> (n.d * vectorNodeBits)) & vectorNodeMask return n.children[idx].get(index) } -// set recursively updates the value at index for each lower depth from the node. -func (n *listBranchNode[T]) set(index int, v T, mutable bool) listNode[T] { - idx := (index >> (n.d * listNodeBits)) & listNodeMask +// set recursively updates the value at index for each lower depth from the +// node. +func (n *vectorBranchNode[T]) set(index int, v T, mutable bool) vectorNode[T] { + idx := (index >> (n.d * vectorNodeBits)) & vectorNodeMask - // Find child for the given value in the branch. Create new if it doesn't exist. + // Find child for the given value in the branch. Create new if it + // doesn't exist. child := n.children[idx] if child == nil { - child = newListNode[T](n.depth() - 1) + child = newVectorNode[T](n.depth() - 1) } // Return a copy of this branch with the new child. - var other *listBranchNode[T] + var other *vectorBranchNode[T] if mutable { other = n } else { @@ -359,8 +376,8 @@ func (n *listBranchNode[T]) set(index int, v T, mutable bool) listNode[T] { } // containsBefore returns true if non-nil values exists between [0,index). -func (n *listBranchNode[T]) containsBefore(index int) bool { - idx := (index >> (n.d * listNodeBits)) & listNodeMask +func (n *vectorBranchNode[T]) containsBefore(index int) bool { + idx := (index >> (n.d * vectorNodeBits)) & vectorNodeMask // Quickly check if any direct children exist before this segment of the index. for i := 0; i < idx; i++ { @@ -376,9 +393,9 @@ func (n *listBranchNode[T]) containsBefore(index int) bool { return false } -// containsAfter returns true if non-nil values exists between (index,listNodeSize). -func (n *listBranchNode[T]) containsAfter(index int) bool { - idx := (index >> (n.d * listNodeBits)) & listNodeMask +// containsAfter returns true if non-nil values exists between (index,vectorNodeSize). +func (n *vectorBranchNode[T]) containsAfter(index int) bool { + idx := (index >> (n.d * vectorNodeBits)) & vectorNodeMask // Quickly check if any direct children exist after this segment of the index. for i := idx + 1; i < len(n.children); i++ { @@ -395,23 +412,23 @@ func (n *listBranchNode[T]) containsAfter(index int) bool { } // deleteBefore returns a new node with all elements before index removed. -func (n *listBranchNode[T]) deleteBefore(index int, mutable bool) listNode[T] { +func (n *vectorBranchNode[T]) deleteBefore(index int, mutable bool) vectorNode[T] { // Ignore if no nodes exist before the given index. if !n.containsBefore(index) { return n } // Return a copy with any nodes prior to the index removed. - idx := (index >> (n.d * listNodeBits)) & listNodeMask + idx := (index >> (n.d * vectorNodeBits)) & vectorNodeMask - var other *listBranchNode[T] + var other *vectorBranchNode[T] if mutable { other = n for i := 0; i < idx; i++ { n.children[i] = nil } } else { - other = &listBranchNode[T]{d: n.d} + other = &vectorBranchNode[T]{d: n.d} copy(other.children[idx:][:], n.children[idx:][:]) } @@ -422,23 +439,23 @@ func (n *listBranchNode[T]) deleteBefore(index int, mutable bool) listNode[T] { } // deleteBefore returns a new node with all elements before index removed. -func (n *listBranchNode[T]) deleteAfter(index int, mutable bool) listNode[T] { +func (n *vectorBranchNode[T]) deleteAfter(index int, mutable bool) vectorNode[T] { // Ignore if no nodes exist after the given index. if !n.containsAfter(index) { return n } // Return a copy with any nodes after the index removed. - idx := (index >> (n.d * listNodeBits)) & listNodeMask + idx := (index >> (n.d * vectorNodeBits)) & vectorNodeMask - var other *listBranchNode[T] + var other *vectorBranchNode[T] if mutable { other = n for i := idx + 1; i < len(n.children); i++ { n.children[i] = nil } } else { - other = &listBranchNode[T]{d: n.d} + other = &vectorBranchNode[T]{d: n.d} copy(other.children[:idx+1], n.children[:idx+1]) } @@ -448,25 +465,25 @@ func (n *listBranchNode[T]) deleteAfter(index int, mutable bool) listNode[T] { return other } -// listLeafNode represents a leaf node in a List. -type listLeafNode[T any] struct { - children [listNodeSize]T +// vectorLeafNode represents a leaf node in a Vector. +type vectorLeafNode[T any] struct { + children [vectorNodeSize]T // bitset with ones at occupied positions, position 0 is the LSB occupied uint32 } // depth always returns 0 for leaf nodes. -func (n *listLeafNode[T]) depth() uint { return 0 } +func (n *vectorLeafNode[T]) depth() uint { return 0 } // get returns the value at the given index. -func (n *listLeafNode[T]) get(index int) T { - return n.children[index&listNodeMask] +func (n *vectorLeafNode[T]) get(index int) T { + return n.children[index&vectorNodeMask] } // set returns a copy of the node with the value at the index updated to v. -func (n *listLeafNode[T]) set(index int, v T, mutable bool) listNode[T] { - idx := index & listNodeMask - var other *listLeafNode[T] +func (n *vectorLeafNode[T]) set(index int, v T, mutable bool) vectorNode[T] { + idx := index & vectorNodeMask + var other *vectorLeafNode[T] if mutable { other = n } else { @@ -479,26 +496,26 @@ func (n *listLeafNode[T]) set(index int, v T, mutable bool) listNode[T] { } // containsBefore returns true if non-nil values exists between [0,index). -func (n *listLeafNode[T]) containsBefore(index int) bool { - idx := index & listNodeMask +func (n *vectorLeafNode[T]) containsBefore(index int) bool { + idx := index & vectorNodeMask return bits.TrailingZeros32(n.occupied) < idx } -// containsAfter returns true if non-nil values exists between (index,listNodeSize). -func (n *listLeafNode[T]) containsAfter(index int) bool { - idx := index & listNodeMask +// containsAfter returns true if non-nil values exists between (index,vectorNodeSize). +func (n *vectorLeafNode[T]) containsAfter(index int) bool { + idx := index & vectorNodeMask lastSetPos := 31 - bits.LeadingZeros32(n.occupied) return lastSetPos > idx } // deleteBefore returns a new node with all elements before index removed. -func (n *listLeafNode[T]) deleteBefore(index int, mutable bool) listNode[T] { +func (n *vectorLeafNode[T]) deleteBefore(index int, mutable bool) vectorNode[T] { if !n.containsBefore(index) { return n } - idx := index & listNodeMask - var other *listLeafNode[T] + idx := index & vectorNodeMask + var other *vectorLeafNode[T] if mutable { other = n var empty T @@ -506,7 +523,7 @@ func (n *listLeafNode[T]) deleteBefore(index int, mutable bool) listNode[T] { other.children[i] = empty } } else { - other = &listLeafNode[T]{occupied: n.occupied} + other = &vectorLeafNode[T]{occupied: n.occupied} copy(other.children[idx:][:], n.children[idx:][:]) } // Set the first idx bits to 0. @@ -515,13 +532,13 @@ func (n *listLeafNode[T]) deleteBefore(index int, mutable bool) listNode[T] { } // deleteAfter returns a new node with all elements after index removed. -func (n *listLeafNode[T]) deleteAfter(index int, mutable bool) listNode[T] { +func (n *vectorLeafNode[T]) deleteAfter(index int, mutable bool) vectorNode[T] { if !n.containsAfter(index) { return n } - idx := index & listNodeMask - var other *listLeafNode[T] + idx := index & vectorNodeMask + var other *vectorLeafNode[T] if mutable { other = n var empty T @@ -529,7 +546,7 @@ func (n *listLeafNode[T]) deleteAfter(index int, mutable bool) listNode[T] { other.children[i] = empty } } else { - other = &listLeafNode[T]{occupied: n.occupied} + other = &vectorLeafNode[T]{occupied: n.occupied} copy(other.children[:idx+1][:], n.children[:idx+1][:]) } // Set bits after idx to 0. idx < 31 because n.containsAfter(index) == true. @@ -537,55 +554,55 @@ func (n *listLeafNode[T]) deleteAfter(index int, mutable bool) listNode[T] { return other } -// ListIterator represents an ordered iterator over a list. -type ListIterator[T any] struct { - list *List[T] // source list +// VectorIterator represents an ordered iterator over a vector. +type VectorIterator[T any] struct { + vector *Vector[T] // source vector index int // current index position - stack [32]listIteratorElem[T] // search stack + stack [32]vectorIteratorElem[T] // search stack depth int // stack depth } // Done returns true if no more elements remain in the iterator. -func (itr *ListIterator[T]) Done() bool { - return itr.index < 0 || itr.index >= itr.list.Len() +func (itr *VectorIterator[T]) Done() bool { + return itr.index < 0 || itr.index >= itr.vector.Len() } // First positions the iterator on the first index. -// If source list is empty then no change is made. -func (itr *ListIterator[T]) First() { - if itr.list.Len() != 0 { +// If source vector is empty then no change is made. +func (itr *VectorIterator[T]) First() { + if itr.vector.Len() != 0 { itr.Seek(0) } } // Last positions the iterator on the last index. -// If source list is empty then no change is made. -func (itr *ListIterator[T]) Last() { - if n := itr.list.Len(); n != 0 { +// If source vector is empty then no change is made. +func (itr *VectorIterator[T]) Last() { + if n := itr.vector.Len(); n != 0 { itr.Seek(n - 1) } } -// Seek moves the iterator position to the given index in the list. +// Seek moves the iterator position to the given index in the vector. // Similar to Go slices, this method will panic if index is below zero or if -// the index is greater than or equal to the list size. -func (itr *ListIterator[T]) Seek(index int) { +// the index is greater than or equal to the vector size. +func (itr *VectorIterator[T]) Seek(index int) { // Panic similar to Go slices. - if index < 0 || index >= itr.list.Len() { - panic(fmt.Sprintf("immutable.ListIterator.Seek: index %d out of bounds", index)) + if index < 0 || index >= itr.vector.Len() { + panic(fmt.Sprintf("immutable.VectorIterator.Seek: index %d out of bounds", index)) } itr.index = index // Reset to the bottom of the stack at seek to the correct position. - itr.stack[0] = listIteratorElem[T]{node: itr.list.root} + itr.stack[0] = vectorIteratorElem[T]{node: itr.vector.root} itr.depth = 0 itr.seek(index) } // Next returns the current index and its value & moves the iterator forward. // Returns an index of -1 if the there are no more elements to return. -func (itr *ListIterator[T]) Next() (index int, value T) { +func (itr *VectorIterator[T]) Next() (index int, value T) { // Exit immediately if there are no elements remaining. var empty T if itr.Done() { @@ -594,7 +611,7 @@ func (itr *ListIterator[T]) Next() (index int, value T) { // Retrieve current index & value. elem := &itr.stack[itr.depth] - index, value = itr.index, elem.node.(*listLeafNode[T]).children[elem.index] + index, value = itr.index, elem.node.(*vectorLeafNode[T]).children[elem.index] // Increase index. If index is at the end then return immediately. itr.index++ @@ -603,7 +620,7 @@ func (itr *ListIterator[T]) Next() (index int, value T) { } // Move up stack until we find a node that has remaining position ahead. - for ; itr.depth > 0 && itr.stack[itr.depth].index >= listNodeSize-1; itr.depth-- { + for ; itr.depth > 0 && itr.stack[itr.depth].index >= vectorNodeSize-1; itr.depth-- { } // Seek to correct position from current depth. @@ -614,7 +631,7 @@ func (itr *ListIterator[T]) Next() (index int, value T) { // Prev returns the current index and value and moves the iterator backward. // Returns an index of -1 if the there are no more elements to return. -func (itr *ListIterator[T]) Prev() (index int, value T) { +func (itr *VectorIterator[T]) Prev() (index int, value T) { // Exit immediately if there are no elements remaining. var empty T if itr.Done() { @@ -623,7 +640,7 @@ func (itr *ListIterator[T]) Prev() (index int, value T) { // Retrieve current index & value. elem := &itr.stack[itr.depth] - index, value = itr.index, elem.node.(*listLeafNode[T]).children[elem.index] + index, value = itr.index, elem.node.(*vectorLeafNode[T]).children[elem.index] // Decrease index. If index is past the beginning then return immediately. itr.index-- @@ -643,26 +660,26 @@ func (itr *ListIterator[T]) Prev() (index int, value T) { // seek positions the stack to the given index from the current depth. // Elements and indexes below the current depth are assumed to be correct. -func (itr *ListIterator[T]) seek(index int) { +func (itr *VectorIterator[T]) seek(index int) { // Iterate over each level until we reach a leaf node. for { elem := &itr.stack[itr.depth] - elem.index = ((itr.list.origin + index) >> (elem.node.depth() * listNodeBits)) & listNodeMask + elem.index = ((itr.vector.origin + index) >> (elem.node.depth() * vectorNodeBits)) & vectorNodeMask switch node := elem.node.(type) { - case *listBranchNode[T]: + case *vectorBranchNode[T]: child := node.children[elem.index] - itr.stack[itr.depth+1] = listIteratorElem[T]{node: child} + itr.stack[itr.depth+1] = vectorIteratorElem[T]{node: child} itr.depth++ - case *listLeafNode[T]: + case *vectorLeafNode[T]: return } } } -// listIteratorElem represents the node and it's child index within the stack. -type listIteratorElem[T any] struct { - node listNode[T] +// vectorIteratorElem represents the node and it's child index within the stack. +type vectorIteratorElem[T any] struct { + node vectorNode[T] index int } @@ -940,7 +957,7 @@ func (n *mapArrayNode[K, V]) set(key K, value V, shift uint, keyHash uint32, h H } // Update existing entry if a match is found. - // Otherwise append to the end of the element list if it doesn't exist. + // Otherwise append to the end of the element vector if it doesn't exist. var other mapArrayNode[K, V] if idx != -1 { other.entries = make([]mapEntry[K, V], len(n.entries)) @@ -1059,7 +1076,7 @@ func (n *mapBitmapIndexedNode[K, V]) set(key K, value V, shift uint, keyHash uin } // If node exists at given slot then overwrite it with new node. - // Otherwise expand the node list and insert new node into appropriate position. + // Otherwise expand the node vector and insert new node into appropriate position. other := &mapBitmapIndexedNode[K, V]{bitmap: n.bitmap | bit} if exists { other.nodes = make([]mapNode[K, V], len(n.nodes)) @@ -1113,7 +1130,7 @@ func (n *mapBitmapIndexedNode[K, V]) delete(key K, shift uint, keyHash uint32, h return n } - // Return copy with bit removed from bitmap and node removed from node list. + // Return copy with bit removed from bitmap and node removed from node vector. other := &mapBitmapIndexedNode[K, V]{bitmap: n.bitmap ^ bit, nodes: make([]mapNode[K, V], len(n.nodes)-1)} copy(other.nodes[:idx], n.nodes[:idx]) copy(other.nodes[idx:], n.nodes[idx+1:]) @@ -2691,7 +2708,7 @@ func (s SortedSetBuilder[T]) Len() int { } // SortedSet returns the current copy of the set. -// The builder should not be used again after the list after this call. +// The builder should not be used again after the vector after this call. func (s SortedSetBuilder[T]) SortedSet() SortedSet[T] { assert(s.s != nil, "immutable.SortedSetBuilder.SortedSet(): duplicate call to fetch sorted set") set := s.s |