package vector
import (
"bytes"
"encoding/json"
"fmt"
)
const (
chunkBits = 5
nodeSize = 1 << chunkBits
tailMaxLen = nodeSize
chunkMask = nodeSize - 1
)
type Vector interface {
json .Marshaler
Len () int
Index (i int ) (interface {}, bool )
Assoc (i int , val interface {}) Vector
Cons (val interface {}) Vector
Pop () Vector
SubVector (i, j int ) Vector
Iterator () Iterator
}
type Iterator interface {
Elem () interface {}
HasElem () bool
Next ()
}
type vector struct {
count int
height uint
root node
tail []interface {}
}
var Empty Vector = &vector {}
type node *[nodeSize ]interface {}
func newNode () node {
return node (&[nodeSize ]interface {}{})
}
func clone (n node ) node {
a := *n
return node (&a )
}
func nodeFromSlice (s []interface {}) node {
var n [nodeSize ]interface {}
copy (n [:], s )
return &n
}
func (v *vector ) Len () int {
return v .count
}
func (v *vector ) treeSize () int {
if v .count < tailMaxLen {
return 0
}
return ((v .count - 1 ) >> chunkBits ) << chunkBits
}
func (v *vector ) Index (i int ) (interface {}, bool ) {
if i < 0 || i >= v .count {
return nil , false
}
if i >= v .treeSize () {
return v .tail [i &chunkMask ], true
}
n := v .root
for shift := v .height * chunkBits ; shift > 0 ; shift -= chunkBits {
n = n [(i >>shift )&chunkMask ].(node )
}
return n [i &chunkMask ], true
}
func (v *vector ) sliceFor (i int ) []interface {} {
if i >= v .treeSize () {
return v .tail
}
n := v .root
for shift := v .height * chunkBits ; shift > 0 ; shift -= chunkBits {
n = n [(i >>shift )&chunkMask ].(node )
}
return n [:]
}
func (v *vector ) Assoc (i int , val interface {}) Vector {
if i < 0 || i > v .count {
return nil
} else if i == v .count {
return v .Cons (val )
}
if i >= v .treeSize () {
newTail := append ([]interface {}(nil ), v .tail ...)
newTail [i &chunkMask ] = val
return &vector {v .count , v .height , v .root , newTail }
}
return &vector {v .count , v .height , doAssoc (v .height , v .root , i , val ), v .tail }
}
func doAssoc (height uint , n node , i int , val interface {}) node {
m := clone (n )
if height == 0 {
m [i &chunkMask ] = val
} else {
sub := (i >> (height * chunkBits )) & chunkMask
m [sub ] = doAssoc (height -1 , m [sub ].(node ), i , val )
}
return m
}
func (v *vector ) Cons (val interface {}) Vector {
if v .count -v .treeSize () < tailMaxLen {
newTail := make ([]interface {}, len (v .tail )+1 )
copy (newTail , v .tail )
newTail [len (v .tail )] = val
return &vector {v .count + 1 , v .height , v .root , newTail }
}
tailNode := nodeFromSlice (v .tail )
newHeight := v .height
var newRoot node
if (v .count >> chunkBits ) > (1 << (v .height * chunkBits )) {
newRoot = newNode ()
newRoot [0 ] = v .root
newRoot [1 ] = newPath (v .height , tailNode )
newHeight ++
} else {
newRoot = v .pushTail (v .height , v .root , tailNode )
}
return &vector {v .count + 1 , newHeight , newRoot , []interface {}{val }}
}
func (v *vector ) pushTail (height uint , n node , tail node ) node {
if height == 0 {
return tail
}
idx := ((v .count - 1 ) >> (height * chunkBits )) & chunkMask
m := clone (n )
child := n [idx ]
if child == nil {
m [idx ] = newPath (height -1 , tail )
} else {
m [idx ] = v .pushTail (height -1 , child .(node ), tail )
}
return m
}
func newPath (height uint , leaf node ) node {
if height == 0 {
return leaf
}
ret := newNode ()
ret [0 ] = newPath (height -1 , leaf )
return ret
}
func (v *vector ) Pop () Vector {
switch v .count {
case 0 :
return nil
case 1 :
return Empty
}
if v .count -v .treeSize () > 1 {
newTail := make ([]interface {}, len (v .tail )-1 )
copy (newTail , v .tail )
return &vector {v .count - 1 , v .height , v .root , newTail }
}
newTail := v .sliceFor (v .count - 2 )
newRoot := v .popTail (v .height , v .root )
newHeight := v .height
if v .height > 0 && newRoot [1 ] == nil {
newRoot = newRoot [0 ].(node )
newHeight --
}
return &vector {v .count - 1 , newHeight , newRoot , newTail }
}
func (v *vector ) popTail (level uint , n node ) node {
idx := ((v .count - 2 ) >> (level * chunkBits )) & chunkMask
if level > 1 {
newChild := v .popTail (level -1 , n [idx ].(node ))
if newChild == nil && idx == 0 {
return nil
}
m := clone (n )
if newChild == nil {
m [idx ] = nil
} else {
m [idx ] = newChild
}
return m
} else if idx == 0 {
return nil
} else {
m := clone (n )
m [idx ] = nil
return m
}
}
func (v *vector ) SubVector (begin , end int ) Vector {
if begin < 0 || begin > end || end > v .count {
return nil
}
return &subVector {v , begin , end }
}
func (v *vector ) Iterator () Iterator {
return newIterator (v )
}
func (v *vector ) MarshalJSON () ([]byte , error ) {
return marshalJSON (v .Iterator ())
}
type subVector struct {
v *vector
begin int
end int
}
func (s *subVector ) Len () int {
return s .end - s .begin
}
func (s *subVector ) Index (i int ) (interface {}, bool ) {
if i < 0 || s .begin +i >= s .end {
return nil , false
}
return s .v .Index (s .begin + i )
}
func (s *subVector ) Assoc (i int , val interface {}) Vector {
if i < 0 || s .begin +i > s .end {
return nil
} else if s .begin +i == s .end {
return s .Cons (val )
}
return s .v .Assoc (s .begin +i , val ).SubVector (s .begin , s .end )
}
func (s *subVector ) Cons (val interface {}) Vector {
return s .v .Assoc (s .end , val ).SubVector (s .begin , s .end +1 )
}
func (s *subVector ) Pop () Vector {
switch s .Len () {
case 0 :
return nil
case 1 :
return Empty
default :
return s .v .SubVector (s .begin , s .end -1 )
}
}
func (s *subVector ) SubVector (i , j int ) Vector {
return s .v .SubVector (s .begin +i , s .begin +j )
}
func (s *subVector ) Iterator () Iterator {
return newIteratorWithRange (s .v , s .begin , s .end )
}
func (s *subVector ) MarshalJSON () ([]byte , error ) {
return marshalJSON (s .Iterator ())
}
type iterator struct {
v *vector
treeSize int
index int
end int
path []pathEntry
}
type pathEntry struct {
node node
index int
}
func (e pathEntry ) current () interface {} {
return e .node [e .index ]
}
func newIterator (v *vector ) *iterator {
return newIteratorWithRange (v , 0 , v .Len ())
}
func newIteratorWithRange (v *vector , begin , end int ) *iterator {
it := &iterator {v , v .treeSize (), begin , end , nil }
if it .index >= it .treeSize {
return it
}
n := v .root
for shift := v .height * chunkBits ; shift > 0 ; shift -= chunkBits {
idx := (begin >> shift ) & chunkMask
it .path = append (it .path , pathEntry {n , idx })
n = n [idx ].(node )
}
it .path = append (it .path , pathEntry {n , begin & chunkMask })
return it
}
func (it *iterator ) Elem () interface {} {
if it .index >= it .treeSize {
return it .v .tail [it .index -it .treeSize ]
}
return it .path [len (it .path )-1 ].current ()
}
func (it *iterator ) HasElem () bool {
return it .index < it .end
}
func (it *iterator ) Next () {
if it .index +1 >= it .treeSize {
it .index ++
return
}
var i int
for i = len (it .path ) - 1 ; i >= 0 ; i -- {
e := it .path [i ]
if e .index +1 < len (e .node ) {
break
}
}
if i == -1 {
panic ("cannot advance; vector iterator bug" )
}
it .path [i ].index ++
for i ++; i < len (it .path ); i ++ {
it .path [i ] = pathEntry {it .path [i -1 ].current ().(node ), 0 }
}
it .index ++
}
type marshalError struct {
index int
cause error
}
func (err *marshalError ) Error () string {
return fmt .Sprintf ("element %d: %s" , err .index , err .cause )
}
func marshalJSON (it Iterator ) ([]byte , error ) {
var buf bytes .Buffer
buf .WriteByte ('[' )
index := 0
for ; it .HasElem (); it .Next () {
if index > 0 {
buf .WriteByte (',' )
}
elemBytes , err := json .Marshal (it .Elem ())
if err != nil {
return nil , &marshalError {index , err }
}
buf .Write (elemBytes )
index ++
}
buf .WriteByte (']' )
return buf .Bytes (), nil
}