Merge pull request #5 from gammazero/new-func

New func to specify minimum capacity
This commit is contained in:
Andrew J. Gillis 2019-05-15 01:55:11 -07:00 committed by GitHub
commit 50f5fc498a
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 76 additions and 7 deletions

View file

@ -1,10 +1,10 @@
language: go
go:
- "1.8"
- "1.9"
- "1.10"
- "1.11"
- "1.12"
- "tip"
before_script:

View file

@ -6,10 +6,11 @@ const minCapacity = 16
// Deque represents a single instance of the deque data structure.
type Deque struct {
buf []interface{}
head int
tail int
count int
buf []interface{}
head int
tail int
count int
minCap int
}
// Len returns the number of elements currently stored in the queue.
@ -178,6 +179,21 @@ func (q *Deque) Rotate(n int) {
}
}
// SetMinCapacity sets a minimum capacity of 2^minCapacityExp. If the value of
// the minimum capacity is less than or equal to the minimum allowed, then
// capacity is set to the minimum allowed. This may be called at anytime to
// set a new minimum capacity.
//
// Setting a larger minimum capacity may be used to prevent resizing when the
// number of stored items changes frequently across a wide range.
func (q *Deque) SetMinCapacity(minCapacityExp uint) {
if 1<<minCapacityExp > minCapacity {
q.minCap = 1 << minCapacityExp
} else {
q.minCap = minCapacity
}
}
// prev returns the previous buffer position wrapping around buffer.
func (q *Deque) prev(i int) int {
return (i - 1) & (len(q.buf) - 1) // bitwise modulus
@ -191,7 +207,10 @@ func (q *Deque) next(i int) int {
// growIfFull resizes up if the buffer is full.
func (q *Deque) growIfFull() {
if len(q.buf) == 0 {
q.buf = make([]interface{}, minCapacity)
if q.minCap == 0 {
q.minCap = minCapacity
}
q.buf = make([]interface{}, q.minCap)
return
}
if q.count == len(q.buf) {
@ -201,7 +220,7 @@ func (q *Deque) growIfFull() {
// shrinkIfExcess resize down if the buffer 1/4 full.
func (q *Deque) shrinkIfExcess() {
if len(q.buf) > minCapacity && (q.count<<2) == len(q.buf) {
if len(q.buf) > q.minCap && (q.count<<2) == len(q.buf) {
q.resize()
}
}

View file

@ -480,6 +480,30 @@ func TestRemoveOutOfRangePanics(t *testing.T) {
})
}
func TestSetMinCapacity(t *testing.T) {
var q Deque
exp := uint(8)
q.SetMinCapacity(exp)
q.PushBack("A")
if q.minCap != 1<<exp {
t.Fatal("wrong minimum capacity")
}
if len(q.buf) != 1<<exp {
t.Fatal("wrong buffer size")
}
q.PopBack()
if q.minCap != 1<<exp {
t.Fatal("wrong minimum capacity")
}
if len(q.buf) != 1<<exp {
t.Fatal("wrong buffer size")
}
q.SetMinCapacity(0)
if q.minCap != minCapacity {
t.Fatal("wrong minimum capacity")
}
}
func assertPanics(t *testing.T, name string, f func()) {
defer func() {
if r := recover(); r == nil {
@ -558,6 +582,31 @@ func BenchmarkRemove(b *testing.B) {
}
}
func BenchmarkYoyo(b *testing.B) {
var q Deque
for i := 0; i < b.N; i++ {
for j := 0; j < 65536; j++ {
q.PushBack(j)
}
for j := 0; j < 65536; j++ {
q.PopFront()
}
}
}
func BenchmarkYoyoFixed(b *testing.B) {
var q Deque
q.SetMinCapacity(16)
for i := 0; i < b.N; i++ {
for j := 0; j < 65536; j++ {
q.PushBack(j)
}
for j := 0; j < 65536; j++ {
q.PopFront()
}
}
}
// insert is used to insert an element into the middle of the queue, before the
// element at the specified index. insert(0,e) is the same as PushFront(e) and
// insert(Len(),e) is the same as PushBack(e). Complexity is constant plus

1
go.mod Normal file
View file

@ -0,0 +1 @@
module github.com/gammazero/deque