// HashE returns a hash code for an object. // Uses iseq.Hashable.Hash if the interface is implemented. // It special cases Go numbers and strings. // Returns an error if the object is not covered by these cases. func HashE(v interface{}) (uint32, error) { if h, ok := v.(iseq.Hashable); ok { return h.Hash(), nil } switch v := v.(type) { case bool, int, int8, int32, int64: return murmur3.HashUInt64(uint64(reflect.ValueOf(v).Int())), nil case uint, uint8, uint32, uint64: return murmur3.HashUInt64(uint64(reflect.ValueOf(v).Uint())), nil case float32, float64: return murmur3.HashUInt64(math.Float64bits(reflect.ValueOf(v).Float())), nil case nil: return murmur3.HashUInt64(0), nil case string: return murmur3.HashString(v), nil case complex64, complex128: return HashComplex128(v.(complex128)), nil } return 0, errors.New("don't know how to hash") }
// HashComplex128 computes a hash for a complex128 func HashComplex128(c complex128) uint32 { hash := murmur3.MixHash( murmur3.HashUInt64(math.Float64bits(real(c))), murmur3.HashUInt64(math.Float64bits(imag(c)))) return murmur3.Finalize(hash, 2) }