mirror of https://github.com/golang/go.git
parent
c93aab36ac
commit
88e331099d
|
|
@ -359,26 +359,11 @@ func appendT(h *Hash, v reflect.Value) {
|
|||
return
|
||||
case reflect.Complex64, reflect.Complex128:
|
||||
c := v.Complex()
|
||||
var buf [8]byte
|
||||
byteorder.LePutUint64(buf[:], math.Float64bits(real(c)))
|
||||
h.Write(buf[:])
|
||||
byteorder.LePutUint64(buf[:], math.Float64bits(imag(c)))
|
||||
h.Write(buf[:])
|
||||
h.float64(real(c))
|
||||
h.float64(imag(c))
|
||||
return
|
||||
case reflect.Float32, reflect.Float64:
|
||||
f := v.Float()
|
||||
if f == 0 {
|
||||
h.WriteByte(0)
|
||||
return
|
||||
}
|
||||
var buf [8]byte
|
||||
if f != f {
|
||||
byteorder.LePutUint64(buf[:], randUint64())
|
||||
h.Write(buf[:])
|
||||
return
|
||||
}
|
||||
byteorder.LePutUint64(buf[:], math.Float64bits(f))
|
||||
h.Write(buf[:])
|
||||
h.float64(v.Float())
|
||||
return
|
||||
case reflect.Bool:
|
||||
h.WriteByte(btoi(v.Bool()))
|
||||
|
|
@ -395,6 +380,22 @@ func appendT(h *Hash, v reflect.Value) {
|
|||
panic(fmt.Errorf("hash/maphash: %s not comparable", v.Type().String()))
|
||||
}
|
||||
|
||||
func (h *Hash) float64(f float64) {
|
||||
if f == 0 {
|
||||
h.WriteByte(0)
|
||||
return
|
||||
}
|
||||
var buf [8]byte
|
||||
if f != f {
|
||||
byteorder.LePutUint64(buf[:], randUint64())
|
||||
h.Write(buf[:])
|
||||
return
|
||||
}
|
||||
byteorder.LePutUint64(buf[:], math.Float64bits(f))
|
||||
h.Write(buf[:])
|
||||
return
|
||||
}
|
||||
|
||||
func btoi(b bool) byte {
|
||||
if b {
|
||||
return 1
|
||||
|
|
|
|||
|
|
@ -94,8 +94,6 @@ func mix(a, b uint64) uint64 {
|
|||
return hi ^ lo
|
||||
}
|
||||
|
||||
var strTyp = reflect.TypeFor[string]()
|
||||
|
||||
func comparableF[T comparable](h *Hash, v T) {
|
||||
vv := reflect.ValueOf(v)
|
||||
appendT(h, vv)
|
||||
|
|
|
|||
|
|
@ -48,21 +48,15 @@ func comparableF[T comparable](h *Hash, v T) {
|
|||
t := abi.TypeFor[T]()
|
||||
ptr := unsafe.Pointer(&v)
|
||||
l := t.Size()
|
||||
k := t.Kind()
|
||||
if k == abi.String {
|
||||
s := ((*string)(ptr))
|
||||
h.WriteString(*s)
|
||||
if t.TFlag&abi.TFlagRegularMemory != 0 {
|
||||
h.Write(unsafe.Slice((*byte)(ptr), l))
|
||||
return
|
||||
}
|
||||
if t.TFlag&abi.TFlagRegularMemory == 0 {
|
||||
// Note: if T like struct {s string}
|
||||
// str value equal but ptr not equal,
|
||||
// if think of it as a contiguous piece of memory,
|
||||
// hash it, that happen v1 == v2
|
||||
// Comparable(s, v1) != Comparable(s, v2).
|
||||
vv := reflect.ValueOf(v)
|
||||
appendT(h, vv)
|
||||
return
|
||||
}
|
||||
h.Write(unsafe.Slice((*byte)(ptr), l))
|
||||
// Note: if T like struct {s string}
|
||||
// str value equal but ptr not equal,
|
||||
// if think of it as a contiguous piece of memory,
|
||||
// hash it, that happen v1 == v2
|
||||
// Comparable(s, v1) != Comparable(s, v2).
|
||||
vv := reflect.ValueOf(v)
|
||||
appendT(h, vv)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -227,13 +227,19 @@ func TestComparable(t *testing.T) {
|
|||
testComparable(t, uintptr(12))
|
||||
testComparable(t, any("s"))
|
||||
testComparable(t, "s")
|
||||
testComparable(t, true)
|
||||
testComparable(t, new(float64))
|
||||
testComparable(t, float64(9))
|
||||
testComparable(t, complex128(9i+1))
|
||||
testComparable(t, struct{}{})
|
||||
testComparable(t, struct {
|
||||
i int
|
||||
u uint
|
||||
b bool
|
||||
f float64
|
||||
}{i: 9, f: 9.9})
|
||||
p *int
|
||||
a any
|
||||
}{i: 9, u: 1, b: true, f: 9.9, p: new(int), a: 1})
|
||||
type S struct {
|
||||
s string
|
||||
}
|
||||
|
|
@ -246,11 +252,21 @@ func TestComparable(t *testing.T) {
|
|||
t.Fatalf("unexpected two heapStr value not equal")
|
||||
}
|
||||
testComparable(t, s1, s2)
|
||||
testComparable(t, s1.s, s2.s)
|
||||
testComparable(t, float32(0), negativeZero[float32]())
|
||||
testComparable(t, float64(0), negativeZero[float64]())
|
||||
testComparableNoEqual(t, math.NaN(), math.NaN())
|
||||
testComparableNoEqual(t, [2]string{"a", ""}, [2]string{"", "a"})
|
||||
testComparableNoEqual(t, any(struct{ x int }{x: 1}), any(struct {
|
||||
x int
|
||||
s string
|
||||
}{x: 1}))
|
||||
}
|
||||
|
||||
func testComparableNoEqual[T comparable](t *testing.T, v1, v2 T) {
|
||||
seed := MakeSeed()
|
||||
if Comparable(seed, math.NaN()) == Comparable(seed, math.NaN()) {
|
||||
t.Fatalf("Comparable(seed, NaN) == Comparable(seed, NaN)")
|
||||
if Comparable(seed, v1) == Comparable(seed, v2) {
|
||||
t.Fatalf("Comparable(seed, %v) == Comparable(seed, %v)", v1, v2)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -291,13 +307,17 @@ func testComparable[T comparable](t *testing.T, v T, v2 ...T) {
|
|||
})
|
||||
}
|
||||
|
||||
var use byte
|
||||
|
||||
//go:noinline
|
||||
func stackGrow(dep int) {
|
||||
if dep == 0 {
|
||||
return
|
||||
}
|
||||
var local [1024]byte
|
||||
_ = local
|
||||
// make sure local is allocated on the stack.
|
||||
local[randUint64()%1024] = byte(randUint64())
|
||||
use = local[randUint64()%1024]
|
||||
stackGrow(dep - 1)
|
||||
}
|
||||
|
||||
|
|
@ -307,13 +327,19 @@ func TestWriteComparable(t *testing.T) {
|
|||
testWriteComparable(t, uintptr(12))
|
||||
testWriteComparable(t, any("s"))
|
||||
testWriteComparable(t, "s")
|
||||
testComparable(t, true)
|
||||
testWriteComparable(t, new(float64))
|
||||
testWriteComparable(t, float64(9))
|
||||
testWriteComparable(t, complex128(9i+1))
|
||||
testWriteComparable(t, struct{}{})
|
||||
testWriteComparable(t, struct {
|
||||
i int
|
||||
u uint
|
||||
b bool
|
||||
f float64
|
||||
}{i: 9, f: 9.9})
|
||||
p *int
|
||||
a any
|
||||
}{i: 9, u: 1, b: true, f: 9.9, p: new(int), a: 1})
|
||||
type S struct {
|
||||
s string
|
||||
}
|
||||
|
|
@ -326,17 +352,28 @@ func TestWriteComparable(t *testing.T) {
|
|||
t.Fatalf("unexpected two heapStr value not equal")
|
||||
}
|
||||
testWriteComparable(t, s1, s2)
|
||||
testWriteComparable(t, s1.s, s2.s)
|
||||
testWriteComparable(t, float32(0), negativeZero[float32]())
|
||||
testWriteComparable(t, float64(0), negativeZero[float64]())
|
||||
testWriteComparableNoEqual(t, math.NaN(), math.NaN())
|
||||
testWriteComparableNoEqual(t, [2]string{"a", ""}, [2]string{"", "a"})
|
||||
testWriteComparableNoEqual(t, any(struct{ x int }{x: 1}), any(struct {
|
||||
x int
|
||||
s string
|
||||
}{x: 1}))
|
||||
}
|
||||
|
||||
func testWriteComparableNoEqual[T comparable](t *testing.T, v1, v2 T) {
|
||||
seed := MakeSeed()
|
||||
h1 := Hash{}
|
||||
h2 := Hash{}
|
||||
h1.seed, h2.seed = seed, seed
|
||||
WriteComparable(&h1, math.NaN())
|
||||
WriteComparable(&h2, math.NaN())
|
||||
WriteComparable(&h1, v1)
|
||||
WriteComparable(&h2, v2)
|
||||
if h1.Sum64() == h2.Sum64() {
|
||||
t.Fatalf("WriteComparable(seed, NaN) == WriteComparable(seed, NaN)")
|
||||
t.Fatalf("WriteComparable(seed, %v) == WriteComparable(seed, %v)", v1, v2)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func testWriteComparable[T comparable](t *testing.T, v T, v2 ...T) {
|
||||
|
|
|
|||
Loading…
Reference in New Issue