2013-12-28 23:56:48 -08:00
|
|
|
package ostat
|
|
|
|
|
|
|
|
import (
|
2014-01-01 16:10:19 -08:00
|
|
|
"fmt"
|
2013-12-28 23:56:48 -08:00
|
|
|
"math"
|
|
|
|
"testing"
|
|
|
|
)
|
|
|
|
|
2013-12-29 00:48:20 -08:00
|
|
|
const tolerance = 1e-7
|
|
|
|
|
2013-12-28 23:56:48 -08:00
|
|
|
func TestInsert(t *testing.T) {
|
2013-12-29 00:48:20 -08:00
|
|
|
tests := []struct {
|
|
|
|
samples []float64
|
|
|
|
min float64
|
|
|
|
max float64
|
|
|
|
mean float64
|
|
|
|
pvariance, svariance float64
|
|
|
|
pstdev, sstdev float64
|
|
|
|
}{
|
|
|
|
{
|
|
|
|
min: math.Inf(1),
|
|
|
|
max: math.Inf(-1),
|
|
|
|
},
|
|
|
|
{
|
|
|
|
samples: []float64{4, 7, 13, 16},
|
|
|
|
min: 4,
|
|
|
|
max: 16,
|
|
|
|
mean: 10.0,
|
|
|
|
pvariance: 22.5,
|
|
|
|
pstdev: math.Sqrt(22.5),
|
|
|
|
svariance: 30,
|
|
|
|
sstdev: math.Sqrt(30.0),
|
|
|
|
},
|
|
|
|
{
|
|
|
|
samples: []float64{10e8 + 4, 10e8 + 7, 10e8 + 13, 10e8 + 16},
|
|
|
|
min: 10e8 + 4,
|
|
|
|
max: 10e8 + 16,
|
|
|
|
mean: 10e8 + 10.0,
|
|
|
|
pvariance: 22.5,
|
|
|
|
pstdev: math.Sqrt(22.5),
|
|
|
|
svariance: 30,
|
|
|
|
sstdev: math.Sqrt(30.0),
|
|
|
|
},
|
|
|
|
{
|
|
|
|
samples: []float64{10e9 + 4, 10e9 + 7, 10e9 + 13, 10e9 + 16},
|
|
|
|
min: 10e9 + 4,
|
|
|
|
max: 10e9 + 16,
|
|
|
|
mean: 10e9 + 10.0,
|
|
|
|
pvariance: 22.5,
|
|
|
|
pstdev: math.Sqrt(22.5),
|
|
|
|
svariance: 30,
|
|
|
|
sstdev: math.Sqrt(30.0),
|
|
|
|
},
|
|
|
|
{
|
|
|
|
|
|
|
|
samples: []float64{119., 480., 900., -561., 664., -652., 549., -342., -754., 983., -485., 6., 572., 683., -111., 400., -179., 60., 142., 253., -330., -886., -120., 590., 465., -374., 299., -32., -794., -107., -531., -649., -877., 114., 179., 704., 508., -210., -128., 147., 654., -251., -337., 643., 865., 530., 535., 534., 528., -115., -645., 55., -584., 104., -556., 496., -863., 483., 145., 578., 318., -611., 290., 178., -25., -792., -45., 221., -172., 491., 911., 904., 523., 778., -484., 230., -897., -97., 316., -255., -749., -737., 709., -74., 48., 839., 428., -560., -613., -639., 371., 948., -966., -802., -618., -753., 835., -372., -492., 89.},
|
|
|
|
min: -966.0,
|
|
|
|
max: 983.0,
|
|
|
|
mean: 21.68,
|
|
|
|
pvariance: 293082.29760000011,
|
|
|
|
pstdev: 541.3707579838424,
|
|
|
|
svariance: 296042.72484848,
|
|
|
|
sstdev: 544.0980838493,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
samples: []float64{36.22727273, -8., -0.79775281, -1.14772727, 29.03333333, -19.53571429, 0.49090909, -0.41666667, -25.92, -10.77464789, 67.71428571, -39.28571429, 10.05154639, -46., 7.91891892, -9.92, -10.30769231, -11.20634921, 13.85, -9.19565217, -16.9, -2.725, 14.32142857, -18.64285714, 9.70238095, 5.92307692, 15.15789474, 8.22368421, 3.56179775, 5.87368421, -16.68, -104.57142857, 6.42352941, -5.14893617, -4.925, -13.31818182, 7.81538462, -5.01492537, -15.35483871, 7.08421053, -4.47777778, 7.97727273, 10.09574468, 10.56521739, 7.67777778, -57.5, 9.03773585, -2.0989011, 12.34482759, -85.5, -107., -4.89473684, 0.90217391, 13.2, 7.31111111, -1.98611111, -7.3375, 9.80722892, -5.88043478, -404., 47.33333333, 16.85416667, -3.06410256, -72.85714286, 29.08333333, 13.58333333, -11.84615385, -14.36363636, 10.25373134, 3.92207792, 11.14634146, -16.15151515, -10.16363636, 13.13513514, -4.55223881, 14.45, 44.88888889, 5.36781609, 1.29591837, 176.5, 18.95652174, 1.85416667, 8.4125, -168.33333333, 2.97590361, 5.45555556, 5.20930233, -7.11764706, 26.53846154, -16.94285714, 17.18181818, 32.86666667, -22.375, 10.14285714, -51.625, -20.72916667, 0.4516129, -5.47058824, -17.81818182, 9.},
|
|
|
|
min: -404.0,
|
|
|
|
max: 176.5,
|
|
|
|
mean: -6.5472287624739636,
|
|
|
|
pvariance: 2864.1893930503825,
|
|
|
|
pstdev: 53.518122099438266,
|
|
|
|
svariance: 2893.1205990296,
|
|
|
|
sstdev: 53.787736511491,
|
|
|
|
},
|
2013-12-28 23:56:48 -08:00
|
|
|
}
|
2013-12-29 00:48:20 -08:00
|
|
|
|
|
|
|
for _, test := range tests {
|
|
|
|
ps := NewPopulationStat()
|
|
|
|
ss := NewSampleStat()
|
|
|
|
for _, i := range test.samples {
|
|
|
|
ps.Push(i)
|
|
|
|
ss.Push(i)
|
|
|
|
}
|
|
|
|
if ps.Min != ss.Min {
|
|
|
|
t.Errorf("Mins don't match")
|
|
|
|
}
|
|
|
|
if ps.Max != ss.Max {
|
|
|
|
t.Errorf("Maxs don't match")
|
|
|
|
}
|
|
|
|
if ps.Min != test.min {
|
|
|
|
t.Errorf("incorrectly calculated min: %f != %f", ps.Min, test.min)
|
|
|
|
}
|
|
|
|
if ps.Max != test.max {
|
|
|
|
t.Errorf("incorrectly calculated max: %f != %f", ps.Max, test.max)
|
|
|
|
}
|
|
|
|
|
2014-01-01 10:46:34 -08:00
|
|
|
if ps.Mean() != ss.Mean() {
|
2013-12-29 00:48:20 -08:00
|
|
|
t.Errorf("Means don't match")
|
|
|
|
}
|
2014-01-01 10:46:34 -08:00
|
|
|
if math.Abs(ps.Mean()-test.mean) > tolerance {
|
|
|
|
t.Errorf("incorrect mean: %f != %f", ps.Mean(), test.mean)
|
2013-12-29 00:48:20 -08:00
|
|
|
}
|
|
|
|
|
2014-01-01 10:46:34 -08:00
|
|
|
if math.Abs(ps.Variance()-test.pvariance) > tolerance {
|
|
|
|
t.Errorf("incorrect variance: %f != %f", ps.Variance(), test.pvariance)
|
2013-12-29 00:48:20 -08:00
|
|
|
}
|
2014-01-01 10:46:34 -08:00
|
|
|
if math.Abs(ps.StdDev()-test.pstdev) > tolerance {
|
|
|
|
t.Errorf("incorrect stdev: %f != %f", ps.StdDev(), test.pstdev)
|
2013-12-29 00:48:20 -08:00
|
|
|
}
|
|
|
|
|
2014-01-01 10:46:34 -08:00
|
|
|
if math.Abs(ss.Variance()-test.svariance) > tolerance {
|
|
|
|
t.Errorf("incorrect variance: %f != %f", ss.Variance(), test.svariance)
|
2013-12-29 00:48:20 -08:00
|
|
|
}
|
2014-01-01 10:46:34 -08:00
|
|
|
if math.Abs(ss.StdDev()-test.sstdev) > tolerance {
|
|
|
|
t.Errorf("incorrect stdev: %f != %f", ss.StdDev(), test.sstdev)
|
2013-12-29 00:48:20 -08:00
|
|
|
}
|
2013-12-28 23:56:48 -08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestEmpty(t *testing.T) {
|
2013-12-29 00:48:20 -08:00
|
|
|
ps := NewSampleStat()
|
2014-01-01 10:46:34 -08:00
|
|
|
if ps.Mean() != 0.0 {
|
2013-12-28 23:56:48 -08:00
|
|
|
t.Errorf("failure to notify the running stat was empty")
|
|
|
|
}
|
2014-01-01 10:46:34 -08:00
|
|
|
if ps.Variance() != 0.0 {
|
2013-12-28 23:56:48 -08:00
|
|
|
t.Errorf("failure to notify the running stat was empty")
|
|
|
|
}
|
2014-01-01 10:46:34 -08:00
|
|
|
if ps.StdDev() != 0.0 {
|
2013-12-28 23:56:48 -08:00
|
|
|
t.Errorf("failure to notify the running stat was empty")
|
|
|
|
}
|
|
|
|
}
|
2014-01-01 10:46:34 -08:00
|
|
|
|
2014-01-01 12:00:15 -08:00
|
|
|
func TestMidStreamStat(t *testing.T) {
|
|
|
|
ps := OnlineStat{
|
2014-01-01 10:46:34 -08:00
|
|
|
n: 3,
|
|
|
|
mean: 8,
|
|
|
|
m2: 21 * 3,
|
2014-01-01 12:00:15 -08:00
|
|
|
typ: Population,
|
|
|
|
}
|
|
|
|
rps := MidStreamStat(3, 8, 4.5825756949558, 4, 13, Population)
|
|
|
|
if math.Abs(ps.Mean()-rps.Mean()) > tolerance {
|
|
|
|
t.Errorf("Incorrect Mean Calc: %f %f", ps.Mean(), rps.Mean())
|
|
|
|
}
|
|
|
|
if math.Abs(ps.Variance()-rps.Variance()) > tolerance {
|
|
|
|
t.Errorf("Incorrect Variance Calc: %f %f", ps.Variance(), rps.Variance())
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// probably spent too much time gathering this data and hard-coding it all in
|
|
|
|
// here. Alas, this test is to verify that we can start a stat mid-stream, if
|
|
|
|
// given the right info at the outset.
|
|
|
|
func TestMidStreamStatWithData(t *testing.T) {
|
|
|
|
ps := NewPopulationStat()
|
|
|
|
first := []float64{7633., 8550., -7874., 586., 7488., 839., 8379., 8716.,
|
|
|
|
-9612., -4309., -3923., -9159., 8131., 7392., -1587., 2004.,
|
|
|
|
7975., -6135., -3863., 686., -7862., 1707., -7967., -9421.,
|
|
|
|
-5618., 2419., -8948., -184., 4450., 7189., 3150., -1879.,
|
|
|
|
-6845., -8551., 5629., -6370., 4949., 6865., 118., 2302.,
|
|
|
|
-4406., 8384., 5643., -7794., 5752., -1361., 6765., 6258.,
|
|
|
|
5602., -4659., 8268., 2154., 345., 123., 7843., -9841.,
|
|
|
|
2889., -3665., 6545., -2164., -8135., 8377., 7645., 9759.,
|
|
|
|
601., 5924., 3348., -3217., 5076., -9145., -2973., 6195.,
|
|
|
|
-8138., -1093., -1432., 813., -6668., -8527., -8646., -670.,
|
|
|
|
-940., -911., 1717., -1388., -786., 2819., 6902., -8566.,
|
|
|
|
4684., 4809., -4446., -806., 3805., -7975., 1138., 518.,
|
|
|
|
-3416., -1797., -2625., -3202.}
|
|
|
|
|
|
|
|
var n int
|
|
|
|
var val float64
|
|
|
|
for n, val = range first {
|
|
|
|
ps.Push(val)
|
|
|
|
}
|
|
|
|
mss := MidStreamStat(
|
|
|
|
uint64(n+1),
|
|
|
|
83.590000000000003,
|
|
|
|
5722.0924356305177,
|
|
|
|
-9841.0,
|
|
|
|
9759.0,
|
|
|
|
Population,
|
|
|
|
)
|
|
|
|
mean1 := 83.590000000000003
|
|
|
|
variance1 := 32742341.841899995
|
|
|
|
min1 := -9841.0
|
|
|
|
max1 := 9759.0
|
|
|
|
|
|
|
|
if math.Abs(ps.Mean()-mean1) > tolerance {
|
|
|
|
t.Errorf("mean: %f != %f", ps.Mean(), mean1)
|
|
|
|
}
|
|
|
|
if math.Abs(mss.Mean()-mean1) > tolerance {
|
|
|
|
t.Errorf("mean: %f != %f", mss.Mean(), mean1)
|
|
|
|
}
|
|
|
|
if math.Abs(ps.Variance()-variance1) > tolerance {
|
|
|
|
t.Errorf("mean: %f != %f", ps.Variance(), variance1)
|
|
|
|
}
|
|
|
|
if math.Abs(mss.Variance()-variance1) > tolerance {
|
|
|
|
t.Errorf("mean: %f != %f", mss.Variance(), variance1)
|
|
|
|
}
|
|
|
|
if (ps.Min != mss.Min) || (mss.Min != min1) {
|
|
|
|
t.Errorf("min: %f != %f != %f", mss.Min, mss.Min, min1)
|
|
|
|
}
|
|
|
|
if (ps.Max != mss.Max) || (mss.Max != max1) {
|
|
|
|
t.Errorf("max: %f != %f != %f", mss.Max, mss.Max, max1)
|
|
|
|
}
|
|
|
|
|
|
|
|
second := []float64{-3.87000000e+02, -4.26800000e+03,
|
|
|
|
-1.39900000e+03, 2.00300000e+03, 1.53100000e+03,
|
|
|
|
-7.91000000e+02, 4.27300000e+03, 4.22100000e+03,
|
|
|
|
-4.84400000e+03, -3.09100000e+03, 4.69300000e+03,
|
|
|
|
4.69100000e+03, -9.78700000e+03, -8.23900000e+03,
|
|
|
|
2.60100000e+03, -9.01100000e+03, 4.32700000e+03,
|
|
|
|
4.62500000e+03, -1.67800000e+03, -9.76300000e+03,
|
|
|
|
-9.26700000e+03, -5.80800000e+03, -2.41400000e+03,
|
|
|
|
-6.62900000e+03, 3.99500000e+03, 6.71800000e+03,
|
|
|
|
-5.48500000e+03, 1.91300000e+03, -2.21000000e+03,
|
|
|
|
6.29400000e+03, 9.35500000e+03, -3.24800000e+03,
|
|
|
|
4.58200000e+03, -2.91000000e+02, 1.42500000e+03,
|
|
|
|
-1.13700000e+03, 5.16900000e+03, -8.36700000e+03,
|
|
|
|
-5.49500000e+03, 8.93000000e+02, 9.74800000e+03,
|
|
|
|
-8.50100000e+03, 6.47000000e+02, -4.93800000e+03,
|
|
|
|
-2.31800000e+03, -5.39100000e+03, 4.55000000e+02,
|
|
|
|
9.62000000e+02, -4.39000000e+02, 3.18100000e+03,
|
|
|
|
7.39500000e+03, -3.16100000e+03, 6.31400000e+03,
|
|
|
|
9.47500000e+03, 3.73500000e+03, 9.48000000e+03,
|
|
|
|
-4.14700000e+03, -2.48000000e+02, 2.94000000e+02,
|
|
|
|
-9.95100000e+03, 3.82500000e+03, -1.03700000e+03,
|
|
|
|
7.33200000e+03, 9.97800000e+03, -3.36200000e+03,
|
|
|
|
9.67200000e+03, 5.62600000e+03, -1.93000000e+02,
|
|
|
|
-3.41300000e+03, -1.50000000e+01, -2.96000000e+03,
|
|
|
|
-5.14800000e+03, 8.41900000e+03, -9.07900000e+03,
|
|
|
|
7.37500000e+03, -7.05400000e+03, -8.59400000e+03,
|
|
|
|
2.66900000e+03, -7.37600000e+03, -6.99500000e+03,
|
|
|
|
2.81800000e+03, 2.87700000e+03, 1.83000000e+02,
|
|
|
|
-9.27100000e+03, 5.83400000e+03, 3.00000000e+00,
|
|
|
|
-6.02700000e+03, 7.78600000e+03, 1.64700000e+03,
|
|
|
|
-5.96500000e+03, -8.60000000e+02, -3.67700000e+03,
|
|
|
|
-6.36600000e+03, -2.06000000e+02, -5.33600000e+03,
|
|
|
|
-2.31000000e+02, -6.70300000e+03, -4.87900000e+03,
|
|
|
|
5.27600000e+03, 9.12600000e+03}
|
|
|
|
|
|
|
|
for _, val = range second {
|
|
|
|
ps.Push(val)
|
|
|
|
mss.Push(val)
|
|
|
|
}
|
|
|
|
|
|
|
|
mean2 := -118.25
|
|
|
|
variance2 := 31713809.697500002
|
|
|
|
min2 := -9951.0
|
|
|
|
max2 := 9978.0
|
|
|
|
|
|
|
|
if math.Abs(ps.Mean()-mean2) > tolerance {
|
|
|
|
t.Errorf("mean: %f != %f", ps.Mean(), mean2)
|
|
|
|
}
|
|
|
|
if math.Abs(mss.Mean()-mean2) > tolerance {
|
|
|
|
t.Errorf("mean: %f != %f", mss.Mean(), mean2)
|
|
|
|
}
|
|
|
|
|
|
|
|
if math.Abs(ps.Variance()-variance2) > tolerance {
|
|
|
|
t.Errorf("mean: %f != %f", ps.Variance(), variance2)
|
|
|
|
}
|
|
|
|
if math.Abs(mss.Variance()-variance2) > tolerance {
|
|
|
|
t.Errorf("mean: %f != %f", mss.Variance(), variance2)
|
|
|
|
}
|
|
|
|
|
|
|
|
if (ps.Min != mss.Min) || (mss.Min != min2) {
|
|
|
|
t.Errorf("min: %f != %f != %f", mss.Min, mss.Min, min2)
|
|
|
|
}
|
|
|
|
if (ps.Max != mss.Max) || (mss.Max != max2) {
|
|
|
|
t.Errorf("max: %f != %f != %f", mss.Max, mss.Max, max2)
|
2014-01-01 10:46:34 -08:00
|
|
|
}
|
|
|
|
}
|
2014-01-01 16:10:19 -08:00
|
|
|
|
|
|
|
func TestString(t *testing.T) {
|
|
|
|
ps := NewPopulationStat()
|
|
|
|
for _, v := range []float64{1, 1, 2, 2} {
|
|
|
|
ps.Push(v)
|
|
|
|
}
|
|
|
|
expected := "{n:4 min:1 max:2 mean:1.5 variance:0.25 stdDev:0.5}"
|
|
|
|
if fmt.Sprint(ps) != expected {
|
|
|
|
t.Errorf("failed to generate correct string")
|
|
|
|
}
|
|
|
|
}
|