-
Notifications
You must be signed in to change notification settings - Fork 5
/
vector.go
146 lines (120 loc) · 3.32 KB
/
vector.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
package vector
import (
"fmt"
"iter"
"github.com/joetifa2003/mm-go/allocator"
)
// Vector a contiguous growable array type
type Vector[T any] struct {
data []T
len int
alloc allocator.Allocator
}
func createVector[T any](alloc allocator.Allocator, len int, cap int) *Vector[T] {
vector := allocator.Alloc[Vector[T]](alloc)
vector.len = len
vector.data = allocator.AllocMany[T](alloc, cap)
vector.alloc = alloc
return vector
}
// New creates a new empty vector, if args not provided
// it will create an empty vector, if only one arg is provided
// it will init a vector with len and cap equal to the provided arg,
// if two args are provided it will init a vector with len = args[0] cap = args[1]
func New[T any](aloc allocator.Allocator, args ...int) *Vector[T] {
switch len(args) {
case 0:
return createVector[T](aloc, 0, 1)
case 1:
return createVector[T](aloc, args[0], args[0])
default:
return createVector[T](aloc, args[0], args[1])
}
}
// Init initializes a new vector with the T elements provided and sets
// it's len and cap to len(values)
func Init[T any](alloc allocator.Allocator, values ...T) *Vector[T] {
vector := createVector[T](alloc, len(values), len(values))
copy(vector.data, values)
return vector
}
// Push pushes value T to the vector, grows if needed.
func (v *Vector[T]) Push(value T) {
if v.len == v.Cap() {
v.data = allocator.Realloc(v.alloc, v.data, v.Cap()*2)
}
v.data[v.len] = value
v.len++
}
// Pop pops value T from the vector and returns it
func (v *Vector[T]) Pop() T {
v.len--
return v.data[v.len]
}
// Len gets vector length
func (v *Vector[T]) Len() int {
return v.len
}
// Cap gets vector capacity (underling memory length).
func (v *Vector[T]) Cap() int {
return cap(v.data)
}
// Slice gets a slice representing the vector
// CAUTION: don't append to this slice, this is only used
// if you want to loop on the vec elements
func (v *Vector[T]) Slice() []T {
return v.data[:v.len]
}
// Last gets the last element from a vector
func (v *Vector[T]) Last() T {
return v.data[v.len-1]
}
// At gets element T at specified index
func (v *Vector[T]) At(idx int) T {
if idx >= v.len {
panic(fmt.Sprintf("cannot index %d in a vector with length %d", idx, v.len))
}
return v.data[idx]
}
// UnsafeAT gets element T at specified index without bounds checking
func (v *Vector[T]) UnsafeAt(idx int) T {
return v.data[idx]
}
// AtPtr gets element a pointer of T at specified index
func (v *Vector[T]) AtPtr(idx int) *T {
if idx >= v.len {
panic(fmt.Sprintf("cannot index %d in a vector with length %d", idx, v.len))
}
return &v.data[idx]
}
// Set sets element T at specified index
func (v *Vector[T]) Set(idx int, value T) {
if idx >= v.len {
panic(fmt.Sprintf("cannot set %d in a vector with length %d", idx, v.len))
}
v.data[idx] = value
}
// Free deallocats the vector
func (v *Vector[T]) Free() {
allocator.FreeMany[T](v.alloc, v.data)
allocator.Free(v.alloc, v)
}
func (v *Vector[T]) RemoveAt(idx int) T {
if idx >= v.len {
panic(fmt.Sprintf("cannot remove %d in a vector with length %d", idx, v.len))
}
tmp := v.data[idx]
v.data[idx] = v.data[v.len-1]
v.len--
return tmp
}
// Iter iterates over the vector
func (v *Vector[T]) Iter() iter.Seq2[int, T] {
return func(yield func(int, T) bool) {
for i := 0; i < v.len; i++ {
if !yield(i, v.data[i]) {
return
}
}
}
}