...
1
16
17
18
19
20
21
22
23
24
25 package ristretto
26
27 import (
28 "fmt"
29 "math/rand"
30 "time"
31 )
32
33
34
35
36
37 type cmSketch struct {
38 rows [cmDepth]cmRow
39 seed [cmDepth]uint64
40 mask uint64
41 }
42
43 const (
44
45 cmDepth = 4
46 )
47
48 func newCmSketch(numCounters int64) *cmSketch {
49 if numCounters == 0 {
50 panic("cmSketch: bad numCounters")
51 }
52
53 numCounters = next2Power(numCounters)
54 sketch := &cmSketch{mask: uint64(numCounters - 1)}
55
56 source := rand.New(rand.NewSource(time.Now().UnixNano()))
57 for i := 0; i < cmDepth; i++ {
58 sketch.seed[i] = source.Uint64()
59 sketch.rows[i] = newCmRow(numCounters)
60 }
61 return sketch
62 }
63
64
65 func (s *cmSketch) Increment(hashed uint64) {
66 for i := range s.rows {
67 s.rows[i].increment((hashed ^ s.seed[i]) & s.mask)
68 }
69 }
70
71
72 func (s *cmSketch) Estimate(hashed uint64) int64 {
73 min := byte(255)
74 for i := range s.rows {
75 val := s.rows[i].get((hashed ^ s.seed[i]) & s.mask)
76 if val < min {
77 min = val
78 }
79 }
80 return int64(min)
81 }
82
83
84 func (s *cmSketch) Reset() {
85 for _, r := range s.rows {
86 r.reset()
87 }
88 }
89
90
91 func (s *cmSketch) Clear() {
92 for _, r := range s.rows {
93 r.clear()
94 }
95 }
96
97
98 type cmRow []byte
99
100 func newCmRow(numCounters int64) cmRow {
101 return make(cmRow, numCounters/2)
102 }
103
104 func (r cmRow) get(n uint64) byte {
105 return byte(r[n/2]>>((n&1)*4)) & 0x0f
106 }
107
108 func (r cmRow) increment(n uint64) {
109
110 i := n / 2
111
112 s := (n & 1) * 4
113
114 v := (r[i] >> s) & 0x0f
115
116 if v < 15 {
117 r[i] += 1 << s
118 }
119 }
120
121 func (r cmRow) reset() {
122
123 for i := range r {
124 r[i] = (r[i] >> 1) & 0x77
125 }
126 }
127
128 func (r cmRow) clear() {
129
130 for i := range r {
131 r[i] = 0
132 }
133 }
134
135 func (r cmRow) string() string {
136 s := ""
137 for i := uint64(0); i < uint64(len(r)*2); i++ {
138 s += fmt.Sprintf("%02d ", (r[(i/2)]>>((i&1)*4))&0x0f)
139 }
140 s = s[:len(s)-1]
141 return s
142 }
143
144
145 func next2Power(x int64) int64 {
146 x--
147 x |= x >> 1
148 x |= x >> 2
149 x |= x >> 4
150 x |= x >> 8
151 x |= x >> 16
152 x |= x >> 32
153 x++
154 return x
155 }
156
View as plain text