github.com/egonelbre/exp@v0.0.0-20240430123955-ed1d3aa93911/niterator/unrollreverse/iterator.go (about) 1 package unrollreverse 2 3 import ( 4 "io" 5 6 "github.com/egonelbre/exp/niterator/shape" 7 ) 8 9 type Index struct { 10 Track uint32 11 Shape uint32 12 Stride uint32 13 } 14 15 type Iterator struct { 16 *shape.AP 17 18 Track [4]Index 19 NextIndex uint32 20 Done bool 21 } 22 23 func NewIterator(ap *shape.AP) *Iterator { 24 track := [4]Index{} 25 for i := range ap.Shape { 26 track[3-i].Shape = uint32(ap.Shape[i]) 27 track[3-i].Stride = uint32(ap.Stride[i]) 28 } 29 30 return &Iterator{ 31 AP: ap, 32 Track: track, 33 } 34 } 35 36 func (it *Iterator) IsDone() bool { 37 return it.Done 38 } 39 40 func (it *Iterator) Next() (int, error) { 41 if it.Done { 42 return 0, io.EOF 43 } 44 45 next := it.NextIndex 46 result := int(next) 47 48 x := &it.Track[0] 49 x.Track++ 50 if x.Track < x.Shape { 51 next += x.Stride 52 it.NextIndex = next 53 return result, nil 54 } 55 x.Track = 0 56 next -= (x.Shape - 1) * x.Stride 57 58 x = &it.Track[1] 59 x.Track++ 60 if x.Track < x.Shape { 61 next += x.Stride 62 it.NextIndex = next 63 return result, nil 64 } 65 x.Track = 0 66 next -= (x.Shape - 1) * x.Stride 67 68 x = &it.Track[2] 69 x.Track++ 70 if x.Track < x.Shape { 71 next += x.Stride 72 it.NextIndex = next 73 return result, nil 74 } 75 x.Track = 0 76 next -= (x.Shape - 1) * x.Stride 77 78 x = &it.Track[3] 79 x.Track++ 80 if x.Track < x.Shape { 81 next += x.Stride 82 it.NextIndex = next 83 return result, nil 84 } 85 it.Done = true 86 it.NextIndex = next 87 88 return result, nil 89 }