"fmt"
"io"
"log"
+ "math/big"
"net"
"os"
"sync"
s.mu.Unlock()
}
-func idDistance(a, b string) (ret int) {
- if len(a) != 20 {
- panic(a)
- }
- if len(b) != 20 {
- panic(b)
+type distance interface {
+ Cmp(distance) int
+ BitCount() int
+ IsZero() bool
+}
+
+type bigIntDistance struct {
+ *big.Int
+}
+
+// How many bits?
+func bitCount(n *big.Int) int {
+ var count int = 0
+ for _, b := range n.Bytes() {
+ count += int(bitCounts[b])
+ }
+ return count
+}
+
+// The bit counts for each byte value (0 - 255).
+var bitCounts = []int8{
+ // Generated by Java BitCount of all values from 0 to 255
+ 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,
+}
+
+func (me bigIntDistance) BitCount() int {
+ return bitCount(me.Int)
+}
+
+func (me bigIntDistance) Cmp(d distance) int {
+ return me.Int.Cmp(d.(bigIntDistance).Int)
+}
+
+func (me bigIntDistance) IsZero() bool {
+ return me.Int.Cmp(big.NewInt(0)) == 0
+}
+
+type bitCountDistance int
+
+func (me bitCountDistance) BitCount() int { return int(me) }
+
+func (me bitCountDistance) Cmp(rhs distance) int {
+ rhs_ := rhs.(bitCountDistance)
+ if me < rhs_ {
+ return -1
+ } else if me == rhs_ {
+ return 0
+ } else {
+ return 1
}
- for i := 0; i < 20; i++ {
- for j := uint(0); j < 8; j++ {
- ret += int(a[i]>>j&1 ^ b[i]>>j&1)
+}
+
+func (me bitCountDistance) IsZero() bool {
+ return me == 0
+}
+
+func idDistance(a, b string) distance {
+ if true {
+ if len(a) != 20 {
+ panic(a)
}
+ if len(b) != 20 {
+ panic(b)
+ }
+ x := new(big.Int)
+ y := new(big.Int)
+ x.SetBytes([]byte(a))
+ y.SetBytes([]byte(b))
+ dist := new(big.Int)
+ return bigIntDistance{dist.Xor(x, y)}
+ } else {
+ ret := 0
+ for i := 0; i < 20; i++ {
+ for j := uint(0); j < 8; j++ {
+ ret += int(a[i]>>j&1 ^ b[i]>>j&1)
+ }
+ }
+ return bitCountDistance(ret)
}
- return
}
func (s *Server) closestGoodNodes(k int, targetID string) []*Node {