github.com/MontFerret/ferret@v0.18.0/pkg/runtime/expressions/vector.go (about) 1 package expressions 2 3 import ( 4 "math" 5 6 "github.com/MontFerret/ferret/pkg/runtime/core" 7 "github.com/MontFerret/ferret/pkg/runtime/values" 8 ) 9 10 // Vector TODO: Finish and add unit tests 11 type Vector struct { 12 slices map[int][]core.Value 13 capacity int 14 current int 15 } 16 17 func NewVector(capacity int) *Vector { 18 el := new(Vector) 19 el.slices = make(map[int][]core.Value) 20 el.capacity = capacity 21 el.current = -1 22 23 return el 24 } 25 26 func (vec *Vector) Push(value core.Value) *Vector { 27 slice := vec.getCurrentSlice() 28 slice[len(slice)] = value 29 30 return vec 31 } 32 33 func (vec *Vector) Get(index int) core.Value { 34 var sliceIndex int 35 var itemIndex int 36 37 // if it's within a capacity 38 if index < vec.capacity { 39 sliceIndex = 0 40 itemIndex = index 41 } else { 42 sliceIndex = int(math.Floor(float64(index / vec.capacity))) 43 itemIndex = index % vec.capacity 44 } 45 46 // if out of range 47 if sliceIndex >= len(vec.slices) { 48 return values.None 49 } 50 51 return vec.slices[sliceIndex][itemIndex] 52 } 53 54 func (vec *Vector) ForEach(predicate func(item core.Value, index int)) { 55 if len(vec.slices) == 0 { 56 return 57 } 58 59 lastIndex := vec.capacity * len(vec.slices) 60 61 for i := 0; i <= lastIndex; i++ { 62 itemIndex := i % vec.capacity 63 sliceIndex := int(math.Floor(float64(i / vec.capacity))) 64 65 predicate(vec.slices[sliceIndex][itemIndex], i) 66 } 67 } 68 69 func (vec *Vector) ToSlice() []core.Value { 70 out := make([]core.Value, vec.capacity*len(vec.slices)) 71 72 if len(vec.slices) == 0 { 73 return out 74 } 75 76 lastIndex := vec.capacity * len(vec.slices) 77 78 for i := 0; i <= lastIndex; i++ { 79 itemIndex := i % vec.capacity 80 sliceIndex := int(math.Floor(float64(i / vec.capacity))) 81 82 out[i] = vec.slices[sliceIndex][itemIndex] 83 } 84 85 return out 86 } 87 88 func (vec *Vector) getCurrentSlice() []core.Value { 89 if vec.current < 0 { 90 return vec.newSlice() 91 } 92 93 current := vec.slices[vec.current] 94 95 if len(current) < vec.capacity { 96 return current 97 } 98 99 return vec.newSlice() 100 } 101 102 func (vec *Vector) newSlice() []core.Value { 103 slice := make([]core.Value, 0, vec.capacity) 104 105 vec.current++ 106 vec.slices[vec.current] = slice 107 108 return slice 109 }