This repository has been archived by the owner on Sep 23, 2018. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 10
/
Copy pathpopcount.go
134 lines (111 loc) · 3.52 KB
/
popcount.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
124
125
126
127
128
129
130
131
132
133
134
//
// Package hamming distance calculations in Go
//
// https://github.com/steakknife/hamming
//
// Copyright © 2014, 2015, 2016, 2018 Barry Allard
//
// MIT license
//
package hamming
import "strconv"
// References: check out Hacker's Delight, about p. 70
func table() [256]uint8 {
return [256]uint8{
0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4,
1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8,
}
}
// CountBitsByteAlt table-less, branch-free implementation
func CountBitsByteAlt(x byte) int {
x = (x & 0x55) + ((x >> 1) & 0x55)
x = (x & 0x33) + ((x >> 2) & 0x33)
return int((x & 0x0f) + ((x >> 4) & 0x0f))
}
// CountBitsInt8 count 1's in x
func CountBitsInt8(x int8) int { return CountBitsByte(byte(x)) }
// CountBitsInt16 count 1's in x
func CountBitsInt16(x int16) int { return CountBitsUint16(uint16(x)) }
// CountBitsInt32 count 1's in x
func CountBitsInt32(x int32) int { return CountBitsUint32(uint32(x)) }
// CountBitsInt64 count 1's in x
func CountBitsInt64(x int64) int { return CountBitsUint64(uint64(x)) }
// CountBitsInt count 1's in x
func CountBitsInt(x int) int { return CountBitsUint(uint(x)) }
// CountBitsByte count 1's in x
func CountBitsByte(x byte) int { return CountBitsUint8(x) }
// CountBitsRune count 1's in x
func CountBitsRune(x rune) int { return CountBitsInt32(x) }
// CountBitsUint8 count 1's in x
func CountBitsUint8(x uint8) int { return int(table()[x]) }
// CountBitsUint16 count 1's in x
func CountBitsUint16(x uint16) int {
return int(table()[x&0xFF] + table()[(x>>8)&0xFF])
}
const (
m1d uint32 = 0x55555555
m2d = 0x33333333
m4d = 0x0f0f0f0f
)
// CountBitsUint32 count 1's in x
func CountBitsUint32(x uint32) int {
x -= ((x >> 1) & m1d)
x = (x & m2d) + ((x >> 2) & m2d)
x = (x + (x >> 4)) & m4d
x += x >> 8
x += x >> 16
return int(x & 0x3f)
}
const (
m1q uint64 = 0x5555555555555555
m2q = 0x3333333333333333
m4q = 0x0f0f0f0f0f0f0f0f
hq = 0x0101010101010101
)
// CountBitsUint64 count 1's in x
func CountBitsUint64(x uint64) int {
// put count of each 2 bits into those 2 bits
x -= (x >> 1) & m1q
// put count of each 4 bits into those 4 bits
x = (x & m2q) + ((x >> 2) & m2q)
// put count of each 8 bits into those 8 bits
x = (x + (x >> 4)) & m4q
// returns left 8 bits of x + (x<<8) + (x<<16) + (x<<24) + ...
return int((x * hq) >> 56)
}
// CountBitsUint64Alt count 1's in x
func CountBitsUint64Alt(x uint64) int {
return CountBitsUint32(uint32(x>>32)) + CountBitsUint32(uint32(x))
}
// CountBitsUintReference count 1's in x
func CountBitsUintReference(x uint) int {
c := 0
for x != 0 {
x &= x - 1
c++
}
return c
}
// CountBitsUint count 1's in x
func CountBitsUint(x uint) int {
if strconv.IntSize == 64 {
return CountBitsUint64(uint64(x))
} else if strconv.IntSize == 32 {
return CountBitsUint32(uint32(x))
}
panic("strconv.IntSize must be 32 or 64 bits")
}