-
Notifications
You must be signed in to change notification settings - Fork 1
/
utils.go
114 lines (103 loc) · 2.46 KB
/
utils.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
package metrics
import (
"math"
"github.com/ready-steady/sort"
)
var (
infinity = math.Inf(1.0)
)
// Uniform computes the uniform distance between two vectors.
func Uniform(x, y []float64) float64 {
Δ := 0.0
for i := range x {
δ := x[i] - y[i]
if δ < 0.0 {
δ = -δ
}
if δ > Δ {
Δ = δ
}
}
return Δ
}
// CDF calculates an empirical cumulative distribution function. The granularity
// of the function is specified by a set of edges; see Histogram.
func CDF(data, edges []float64) (values []float64) {
bins, _ := Histogram(data, edges)
total := uint(0)
for i, count := range bins {
total += count
bins[i] = total
}
values = make([]float64, len(bins))
for i := range values {
values[i] = float64(bins[i]) / float64(total)
}
return
}
// Edges returns sorted unique elements of a number of data sets, ensuring that
// the first and last elements are -∞ and +∞, respectively.
func Edges(data ...[]float64) []float64 {
count := len(data)
total := 0
for i := 0; i < count; i++ {
total += len(data[i])
}
edges := make([]float64, 1+total+1)
edges[0] = -infinity
for i, j := 0, 1; i < count; i++ {
copy(edges[j:], data[i])
j += len(data[i])
}
edges[1+total] = infinity
return sort.Unique(edges)
}
// Histogram counts the number of points that fall into each of the bins
// specified by a set of edges. For n edges, the number of bins is (n-1). The
// left endpoint of a bin is assumed to belong to the bin while the right one is
// assumed to do not.
func Histogram(data []float64, edges []float64) (bins []uint, total uint) {
bins = make([]uint, len(edges)-1)
for _, x := range data {
if i := find(x, edges); i != -1 {
bins[i]++
total++
}
}
return
}
// PDF calculates an empirical probability density function. The granularity of
// the function is specified by a set of edges; see Histogram.
func PDF(data, edges []float64) (values []float64) {
bins, total := Histogram(data, edges)
values = make([]float64, len(bins))
for i := range values {
values[i] = float64(bins[i]) / float64(total)
}
return
}
func find(x float64, edges []float64) int {
lower, upper := 0, len(edges)-1
if x < edges[lower] {
return -1
}
if x >= edges[upper] {
return -1
}
for upper-lower > 1 {
middle := (upper + lower) / 2
if x >= edges[middle] {
lower = middle
} else {
upper = middle
}
}
return lower
}
func Broadcast(a float64, len int) []float64 {
res := make([]float64, len)
for ii := range res {
res[ii] = a
}
return res
}