Codebase list golang-github-beorn7-perks / 3a771d9
Merge pull request #3 from mattbostock/avoid_map_iter Avoid iterating on maps Björn Rabenstein authored 6 years ago GitHub committed 6 years ago
1 changed file(s) with 29 addition(s) and 5 deletion(s). Raw diff Collapse all Expand all
7676 // is guaranteed to be within (Quantile±Epsilon).
7777 //
7878 // See http://www.cs.rutgers.edu/~muthu/bquant.pdf for time, space, and error properties.
79 func NewTargeted(targets map[float64]float64) *Stream {
79 func NewTargeted(targetMap map[float64]float64) *Stream {
80 // Convert map to slice to avoid slow iterations on a map.
81 // ƒ is called on the hot path, so converting the map to a slice
82 // beforehand results in significant CPU savings.
83 targets := targetMapToSlice(targetMap)
84
8085 ƒ := func(s *stream, r float64) float64 {
8186 var m = math.MaxFloat64
8287 var f float64
83 for quantile, epsilon := range targets {
84 if quantile*s.n <= r {
85 f = (2 * epsilon * r) / quantile
88 for _, t := range targets {
89 if t.quantile*s.n <= r {
90 f = (2 * t.epsilon * r) / t.quantile
8691 } else {
87 f = (2 * epsilon * (s.n - r)) / (1 - quantile)
92 f = (2 * t.epsilon * (s.n - r)) / (1 - t.quantile)
8893 }
8994 if f < m {
9095 m = f
9398 return m
9499 }
95100 return newStream(ƒ)
101 }
102
103 type target struct {
104 quantile float64
105 epsilon float64
106 }
107
108 func targetMapToSlice(targetMap map[float64]float64) []target {
109 targets := make([]target, 0, len(targetMap))
110
111 for quantile, epsilon := range targetMap {
112 t := target{
113 quantile: quantile,
114 epsilon: epsilon,
115 }
116 targets = append(targets, t)
117 }
118
119 return targets
96120 }
97121
98122 // Stream computes quantiles for a stream of float64s. It is not thread-safe by