snapshot.
This commit is contained in:
parent
472d04b3fa
commit
814470733e
10 changed files with 187 additions and 54 deletions
14
sequence/array.go
Normal file
14
sequence/array.go
Normal 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]
|
||||||
|
}
|
|
@ -1,4 +1,4 @@
|
||||||
package util
|
package sequence
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
|
@ -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())
|
||||||
}
|
}
|
|
@ -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)}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
package util
|
package sequence
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"testing"
|
"testing"
|
||||||
|
|
41
sequence/linear.go
Normal file
41
sequence/linear.go
Normal 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
21
sequence/random.go
Normal 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()
|
||||||
|
}
|
|
@ -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]
|
|
||||||
}
|
|
||||||
|
|
|
@ -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())
|
||||||
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
package util
|
package sequence
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"time"
|
"time"
|
||||||
|
|
Loading…
Reference in a new issue