...
1 package teststat
2
3 import (
4 "math"
5 "math/rand"
6
7 "github.com/go-kit/kit/metrics"
8 )
9
10
11
12
13
14
15
16
17
18 func PopulateNormalHistogram(h metrics.Histogram, seed int) {
19 r := rand.New(rand.NewSource(int64(seed)))
20 for i := 0; i < Count; i++ {
21 sample := r.NormFloat64()*float64(Stdev) + float64(Mean)
22 if sample < 0 {
23 sample = 0
24 }
25 h.Observe(sample)
26 }
27 }
28
29 func normalQuantiles() (p50, p90, p95, p99 float64) {
30 return nvq(50), nvq(90), nvq(95), nvq(99)
31 }
32
33 func nvq(quantile int) float64 {
34
35 return float64(Mean) + float64(Stdev)*math.Sqrt2*erfinv(2*(float64(quantile)/100)-1)
36 }
37
38 func erfinv(y float64) float64 {
39
40 if y < -1.0 || y > 1.0 {
41 panic("invalid input")
42 }
43
44 var (
45 a = [4]float64{0.886226899, -1.645349621, 0.914624893, -0.140543331}
46 b = [4]float64{-2.118377725, 1.442710462, -0.329097515, 0.012229801}
47 c = [4]float64{-1.970840454, -1.624906493, 3.429567803, 1.641345311}
48 d = [2]float64{3.543889200, 1.637067800}
49 )
50
51 const y0 = 0.7
52 var x, z float64
53
54 if math.Abs(y) == 1.0 {
55 x = -y * math.Log(0.0)
56 } else if y < -y0 {
57 z = math.Sqrt(-math.Log((1.0 + y) / 2.0))
58 x = -(((c[3]*z+c[2])*z+c[1])*z + c[0]) / ((d[1]*z+d[0])*z + 1.0)
59 } else {
60 if y < y0 {
61 z = y * y
62 x = y * (((a[3]*z+a[2])*z+a[1])*z + a[0]) / ((((b[3]*z+b[3])*z+b[1])*z+b[0])*z + 1.0)
63 } else {
64 z = math.Sqrt(-math.Log((1.0 - y) / 2.0))
65 x = (((c[3]*z+c[2])*z+c[1])*z + c[0]) / ((d[1]*z+d[0])*z + 1.0)
66 }
67 x -= (math.Erf(x) - y) / (2.0 / math.SqrtPi * math.Exp(-x*x))
68 x -= (math.Erf(x) - y) / (2.0 / math.SqrtPi * math.Exp(-x*x))
69 }
70
71 return x
72 }
73
View as plain text