snapshot.

This commit is contained in:
Will Charczuk 2017-04-29 21:12:39 -07:00
parent 472d04b3fa
commit 814470733e
10 changed files with 187 additions and 54 deletions

14
sequence/array.go Normal file
View File

@ -0,0 +1,14 @@
package sequence
// Array is a wrapper for an array of floats that implements `ValuesProvider`.
type Array []float64
// Len returns the value provider length.
func (a Array) Len() int {
return len(a)
}
// GetValue returns the value at a given index.
func (a Array) GetValue(index int) float64 {
return a[index]
}

View File

@ -1,4 +1,4 @@
package util package sequence
import ( import (
"fmt" "fmt"

View File

@ -1,4 +1,4 @@
package util package sequence
import ( import (
"testing" "testing"
@ -6,10 +6,10 @@ import (
"github.com/blendlabs/go-assert" "github.com/blendlabs/go-assert"
) )
func TestValueBuffer(t *testing.T) { func TestBuffer(t *testing.T) {
assert := assert.New(t) assert := assert.New(t)
buffer := NewValueBuffer() buffer := NewBuffer()
buffer.Enqueue(1) buffer.Enqueue(1)
assert.Equal(1, buffer.Len()) assert.Equal(1, buffer.Len())
@ -100,10 +100,10 @@ func TestValueBuffer(t *testing.T) {
assert.Zero(buffer.PeekBack()) assert.Zero(buffer.PeekBack())
} }
func TestRingBufferClear(t *testing.T) { func TestBufferClear(t *testing.T) {
assert := assert.New(t) assert := assert.New(t)
buffer := NewValueBuffer() buffer := NewBuffer()
buffer.Enqueue(1) buffer.Enqueue(1)
buffer.Enqueue(1) buffer.Enqueue(1)
buffer.Enqueue(1) buffer.Enqueue(1)
@ -121,10 +121,10 @@ func TestRingBufferClear(t *testing.T) {
assert.Zero(buffer.PeekBack()) assert.Zero(buffer.PeekBack())
} }
func TestRingBufferAsSlice(t *testing.T) { func TestBufferArray(t *testing.T) {
assert := assert.New(t) assert := assert.New(t)
buffer := NewValueBuffer() buffer := NewBuffer()
buffer.Enqueue(1) buffer.Enqueue(1)
buffer.Enqueue(2) buffer.Enqueue(2)
buffer.Enqueue(3) buffer.Enqueue(3)
@ -140,10 +140,10 @@ func TestRingBufferAsSlice(t *testing.T) {
assert.Equal(5, contents[4]) assert.Equal(5, contents[4])
} }
func TestRingBufferEach(t *testing.T) { func TestBufferEach(t *testing.T) {
assert := assert.New(t) assert := assert.New(t)
buffer := NewValueBuffer() buffer := NewBuffer()
for x := 1; x < 17; x++ { for x := 1; x < 17; x++ {
buffer.Enqueue(float64(x)) buffer.Enqueue(float64(x))
@ -159,10 +159,10 @@ func TestRingBufferEach(t *testing.T) {
assert.Equal(16, called) assert.Equal(16, called)
} }
func TestNewValueBuffer(t *testing.T) { func TestNewBuffer(t *testing.T) {
assert := assert.New(t) assert := assert.New(t)
empty := NewValueBuffer() empty := NewBuffer()
assert.NotNil(empty) assert.NotNil(empty)
assert.Zero(empty.Len()) assert.Zero(empty.Len())
assert.Equal(valueBufferDefaultCapacity, empty.Capacity()) assert.Equal(valueBufferDefaultCapacity, empty.Capacity())
@ -170,13 +170,24 @@ func TestNewValueBuffer(t *testing.T) {
assert.Zero(empty.PeekBack()) assert.Zero(empty.PeekBack())
} }
func TestNewValueBufferWithValues(t *testing.T) { func TestNewBufferWithValues(t *testing.T) {
assert := assert.New(t) assert := assert.New(t)
values := NewValueBuffer(1, 2, 3, 4) values := NewBuffer(1, 2, 3, 4, 5)
assert.NotNil(values) assert.NotNil(values)
assert.Equal(4, values.Len()) assert.Equal(5, values.Len())
assert.Equal(valueBufferDefaultCapacity, values.Capacity()) assert.Equal(valueBufferDefaultCapacity, values.Capacity())
assert.Equal(1, values.Peek()) assert.Equal(1, values.Peek())
assert.Equal(4, values.PeekBack()) assert.Equal(5, values.PeekBack())
}
func TestBufferGrowth(t *testing.T) {
assert := assert.New(t)
values := NewBuffer(1, 2, 3, 4, 5)
for i := 0; i < 1<<10; i++ {
values.Enqueue(float64(i))
}
assert.Equal(1<<10-1, values.PeekBack())
} }

View File

@ -1,4 +1,4 @@
package util package sequence
import ( import (
"math/rand" "math/rand"
@ -18,7 +18,7 @@ type generate struct {
} }
// Values produces an array of floats from [start,end] by optional steps. // Values produces an array of floats from [start,end] by optional steps.
func (g generate) Values(start, end float64, steps ...float64) Sequence { func (g generate) Values(start, end float64, steps ...float64) Seq {
var values []float64 var values []float64
step := 1.0 step := 1.0
if len(steps) > 0 { if len(steps) > 0 {
@ -34,22 +34,22 @@ func (g generate) Values(start, end float64, steps ...float64) Sequence {
values = append(values, x) values = append(values, x)
} }
} }
return Sequence{Array(values)} return Seq{Array(values)}
} }
// Random generates a fixed length sequence of random values between (0, scale). // Random generates a fixed length sequence of random values between (0, scale).
func (g generate) RandomValues(samples int, scale float64) Sequence { func (g generate) RandomValues(samples int, scale float64) Seq {
values := make([]float64, samples) values := make([]float64, samples)
for x := 0; x < samples; x++ { for x := 0; x < samples; x++ {
values[x] = g.rnd.Float64() * scale values[x] = g.rnd.Float64() * scale
} }
return Sequence{Array(values)} return Seq{Array(values)}
} }
// Random generates a fixed length sequence of random values with a given average, above and below that average by (-scale, scale) // Random generates a fixed length sequence of random values with a given average, above and below that average by (-scale, scale)
func (g generate) RandomValuesWithAverage(samples int, average, scale float64) Sequence { func (g generate) RandomValuesWithAverage(samples int, average, scale float64) Seq {
values := make([]float64, samples) values := make([]float64, samples)
for x := 0; x < samples; x++ { for x := 0; x < samples; x++ {
@ -57,5 +57,5 @@ func (g generate) RandomValuesWithAverage(samples int, average, scale float64) S
values[x] = average + jitter values[x] = average + jitter
} }
return Sequence{Array(values)} return Seq{Array(values)}
} }

View File

@ -1,4 +1,4 @@
package util package sequence
import ( import (
"testing" "testing"

41
sequence/linear.go Normal file
View File

@ -0,0 +1,41 @@
package sequence
// NewLinear returns a new linear generator.
func NewLinear() *Linear {
return &Linear{}
}
// Linear is a stepwise generator.
type Linear struct {
offset float64
limit float64
step float64
}
// Len returns the number of elements in the sequence.
func (lg Linear) Len() int {
return int((lg.limit - lg.offset) / lg.step)
}
// GetValue returns the value at a given index.
func (lg Linear) GetValue(index int) float64 {
return lg.offset + (float64(index) * lg.step)
}
// WithOffset sets the offset and returns the linear generator.
func (lg *Linear) WithOffset(offset float64) *Linear {
lg.offset = offset
return lg
}
// WithLimit sets the step and returns the linear generator.
func (lg *Linear) WithLimit(limit float64) *Linear {
lg.limit = limit
return lg
}
// WithStep sets the step and returns the linear generator.
func (lg *Linear) WithStep(step float64) *Linear {
lg.step = step
return lg
}

21
sequence/random.go Normal file
View File

@ -0,0 +1,21 @@
package sequence
import "math/rand"
type Random struct {
rnd *rand.Rand
scale *float64
average *float64
len int
}
func (r *Random) Len() int {
return r.len
}
func (r *Random) GetValue(_ int) float64 {
if r.scale != nil {
return r.rnd.Float64() * *r.scale
}
return r.rnd.Float64()
}

View File

@ -1,20 +1,20 @@
package util package sequence
import "math" import "math"
// SequenceProvider is a provider for values for a sequence. // Provider is a provider for values for a sequence.
type SequenceProvider interface { type Provider interface {
Len() int Len() int
GetValue(int) float64 GetValue(int) float64
} }
// Sequence is a utility wrapper for sequence providers. // Seq is a utility wrapper for sequence providers.
type Sequence struct { type Seq struct {
SequenceProvider Provider
} }
// Each applies the `mapfn` to all values in the value provider. // Each applies the `mapfn` to all values in the value provider.
func (s Sequence) Each(mapfn func(int, float64)) { func (s Seq) Each(mapfn func(int, float64)) {
for i := 0; i < s.Len(); i++ { for i := 0; i < s.Len(); i++ {
mapfn(i, s.GetValue(i)) mapfn(i, s.GetValue(i))
} }
@ -22,29 +22,62 @@ func (s Sequence) Each(mapfn func(int, float64)) {
// Map applies the `mapfn` to all values in the value provider, // Map applies the `mapfn` to all values in the value provider,
// returning a new sequence. // returning a new sequence.
func (s Sequence) Map(mapfn func(i int, v float64) float64) Sequence { func (s Seq) Map(mapfn func(i int, v float64) float64) Seq {
output := make([]float64, s.Len()) output := make([]float64, s.Len())
for i := 0; i < s.Len(); i++ { for i := 0; i < s.Len(); i++ {
mapfn(i, s.GetValue(i)) mapfn(i, s.GetValue(i))
} }
return Sequence{Array(output)} return Seq{Array(output)}
} }
// Average returns the float average of the values in the buffer. // FoldLeft collapses a sequence from left to right.
func (s Sequence) Average() float64 { func (s Seq) FoldLeft(mapfn func(i int, v0, v float64) float64) (v0 float64) {
if s.Len() == 0 {
return 0
}
v0 = s.GetValue(0)
for i := 1; i < s.Len(); i++ {
v0 = mapfn(i, v0, s.GetValue(i))
}
return
}
// FoldRight collapses a sequence from right to left.
func (s Seq) FoldRight(mapfn func(i int, v0, v float64) float64) (v0 float64) {
if s.Len() == 0 {
return 0
}
for i := s.Len() - 1; i >= 0; i-- {
v0 = mapfn(i, v0, s.GetValue(i))
}
return
}
// Sum adds all the elements of a series together.
func (s Seq) Sum() (accum float64) {
if s.Len() == 0 { if s.Len() == 0 {
return 0 return 0
} }
var accum float64
for i := 0; i < s.Len(); i++ { for i := 0; i < s.Len(); i++ {
accum += s.GetValue(i) accum += s.GetValue(i)
} }
return accum / float64(s.Len()) return
}
// Average returns the float average of the values in the buffer.
func (s Seq) Average() float64 {
if s.Len() == 0 {
return 0
}
return s.Sum() / float64(s.Len())
} }
// Variance computes the variance of the buffer. // Variance computes the variance of the buffer.
func (s Sequence) Variance() float64 { func (s Seq) Variance() float64 {
if s.Len() == 0 { if s.Len() == 0 {
return 0 return 0
} }
@ -60,23 +93,10 @@ func (s Sequence) Variance() float64 {
} }
// StdDev returns the standard deviation. // StdDev returns the standard deviation.
func (s Sequence) StdDev() float64 { func (s Seq) StdDev() float64 {
if s.Len() == 0 { if s.Len() == 0 {
return 0 return 0
} }
return math.Pow(s.Variance(), 0.5) return math.Pow(s.Variance(), 0.5)
} }
// Array is a wrapper for an array of floats that implements `ValuesProvider`.
type Array []float64
// Len returns the value provider length.
func (a Array) Len() int {
return len(a)
}
// GetValue returns the value at a given index.
func (a Array) GetValue(index int) float64 {
return a[index]
}

View File

@ -1 +1,27 @@
package util package sequence
import (
"testing"
assert "github.com/blendlabs/go-assert"
)
func TestSequenceEach(t *testing.T) {
assert := assert.New(t)
values := Seq{Array([]float64{1, 2, 3, 4})}
values.Each(func(i int, v float64) {
assert.Equal(i, v)
})
}
func TestSequenceMap(t *testing.T) {
assert := assert.New(t)
values := Seq{Array([]float64{1, 2, 3, 4})}
mapped := values.Map(func(i int, v float64) float64 {
assert.Equal(i, v)
return v * 2
})
assert.Equal(4, mapped.Len())
}

View File

@ -1,4 +1,4 @@
package util package sequence
import ( import (
"time" "time"