-
Notifications
You must be signed in to change notification settings - Fork 8
/
auxillary.go
123 lines (110 loc) · 2.62 KB
/
auxillary.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
115
116
117
118
119
120
121
122
123
package gohll
import (
"math"
"math/bits"
)
// encodeHash takes in a 64bit hash and the set precision and outputs a 32bit
// encoded hash for use with the sparseList
func encodeHash(x uint64, p uint8) uint32 {
if sliceUint64(x, 63-p, 39) == 0 {
var result uint32
result = uint32((x >> 32) &^ 0x7f)
w := sliceUint64(x, 63-p, 0) << p
result |= (uint32(bits.LeadingZeros64(w)) << 1)
result |= 1
return result
}
return uint32(x>>32) &^ 0x1
}
// decodeHash takes a 32bit hash which was encoded for use with the sparseList
// and extracts the meaningful metadata from it using the normal mode precision
// (namely it's index and location of it's leading set bit)
func decodeHash(x uint32, p uint8) (uint32, uint8) {
var r uint8
if x&0x1 == 1 {
r = uint8(sliceUint32(x, 6, 1))
} else {
r = uint8(bits.LeadingZeros32(sliceUint32(x, 31-p, 1) << (1 + p)))
}
return getIndex(x, p), r + 1
}
// getIndex returns the normal mode precision (given by p) of an encoded hash
func getIndex(x uint32, p uint8) uint32 {
return sliceUint32(x, 31, 32-p)
}
// getIndexSparse returns the sparse mode index of the encoded hash
func getIndexSparse(x uint32) uint32 {
return x >> 7
}
// linearCounting performs linear counting given the number of registers, m1, and the number
// of empty registers, V
func linearCounting(m1 uint, V int) float64 {
return float64(m1) * math.Log(float64(m1)/float64(V))
}
// estimateBias estimates the amount of bias in a normal mode cardinality query
// with an estimator value of E and a normal mode precision of p
func estimateBias(E float64, p uint8) float64 {
if p > 18 {
return 0.0
}
estimateVector := rawEstimateData[p-4]
N := len(estimateVector)
if E < estimateVector[0] || E > estimateVector[N-1] {
return 0.0
}
biasVector := biasData[p-4]
if estimateVector[0] == E {
return biasVector[0]
}
for i := 1; i < len(estimateVector); i++ {
v := estimateVector[i]
if v == E {
return biasVector[i]
}
if v > E && estimateVector[i-1] < E {
return linearInterpolation(estimateVector[i-1:i+1], biasVector[i-1:i+1], E)
}
}
return 0.0
}
func linearInterpolation(x, y []float64, x0 float64) float64 {
if len(x) != 2 || len(y) != 2 {
return 0.0
}
return y[0] + (y[1]-y[0])*(x0-x[0])/(x[1]-x[0])
}
func threshold(p uint8) float64 {
switch p {
case 4:
return 10
case 5:
return 20
case 6:
return 40
case 8:
return 220
case 7:
return 80
case 9:
return 400
case 10:
return 900
case 11:
return 1800
case 12:
return 3100
case 13:
return 6500
case 14:
return 11500
case 15:
return 20000
case 16:
return 50000
case 17:
return 120000
case 18:
return 350000
}
return 0
}