whatcanGOwrong
This commit is contained in:
@@ -0,0 +1,91 @@
|
||||
package internal
|
||||
|
||||
import "math/bits"
|
||||
|
||||
// Deque implements a double ended queue.
|
||||
type Deque[T any] struct {
|
||||
elems []T
|
||||
read, write uint64
|
||||
mask uint64
|
||||
}
|
||||
|
||||
// Reset clears the contents of the deque while retaining the backing buffer.
|
||||
func (dq *Deque[T]) Reset() {
|
||||
var zero T
|
||||
|
||||
for i := dq.read; i < dq.write; i++ {
|
||||
dq.elems[i&dq.mask] = zero
|
||||
}
|
||||
|
||||
dq.read, dq.write = 0, 0
|
||||
}
|
||||
|
||||
func (dq *Deque[T]) Empty() bool {
|
||||
return dq.read == dq.write
|
||||
}
|
||||
|
||||
// Push adds an element to the end.
|
||||
func (dq *Deque[T]) Push(e T) {
|
||||
dq.Grow(1)
|
||||
dq.elems[dq.write&dq.mask] = e
|
||||
dq.write++
|
||||
}
|
||||
|
||||
// Shift returns the first element or the zero value.
|
||||
func (dq *Deque[T]) Shift() T {
|
||||
var zero T
|
||||
|
||||
if dq.Empty() {
|
||||
return zero
|
||||
}
|
||||
|
||||
index := dq.read & dq.mask
|
||||
t := dq.elems[index]
|
||||
dq.elems[index] = zero
|
||||
dq.read++
|
||||
return t
|
||||
}
|
||||
|
||||
// Pop returns the last element or the zero value.
|
||||
func (dq *Deque[T]) Pop() T {
|
||||
var zero T
|
||||
|
||||
if dq.Empty() {
|
||||
return zero
|
||||
}
|
||||
|
||||
dq.write--
|
||||
index := dq.write & dq.mask
|
||||
t := dq.elems[index]
|
||||
dq.elems[index] = zero
|
||||
return t
|
||||
}
|
||||
|
||||
// Grow the deque's capacity, if necessary, to guarantee space for another n
|
||||
// elements.
|
||||
func (dq *Deque[T]) Grow(n int) {
|
||||
have := dq.write - dq.read
|
||||
need := have + uint64(n)
|
||||
if need < have {
|
||||
panic("overflow")
|
||||
}
|
||||
if uint64(len(dq.elems)) >= need {
|
||||
return
|
||||
}
|
||||
|
||||
// Round up to the new power of two which is at least 8.
|
||||
// See https://jameshfisher.com/2018/03/30/round-up-power-2/
|
||||
capacity := 1 << (64 - bits.LeadingZeros64(need-1))
|
||||
if capacity < 8 {
|
||||
capacity = 8
|
||||
}
|
||||
|
||||
elems := make([]T, have, capacity)
|
||||
pivot := dq.read & dq.mask
|
||||
copied := copy(elems, dq.elems[pivot:])
|
||||
copy(elems[copied:], dq.elems[:pivot])
|
||||
|
||||
dq.elems = elems[:capacity]
|
||||
dq.mask = uint64(capacity) - 1
|
||||
dq.read, dq.write = 0, have
|
||||
}
|
||||
Reference in New Issue
Block a user