/* go-type-float.c -- hash and equality float functions. Copyright 2012 The Go Authors. All rights reserved. Use of this source code is governed by a BSD-style license that can be found in the LICENSE file. */ #include "runtime.h" #include "go-type.h" /* The 32-bit and 64-bit types. */ typedef unsigned int SItype __attribute__ ((mode (SI))); typedef unsigned int DItype __attribute__ ((mode (DI))); /* Hash function for float types. */ uintptr_t __go_type_hash_float (const void *vkey, uintptr_t key_size) { if (key_size == 4) { union { unsigned char a[4]; float f; SItype si; } uf; float f; __builtin_memcpy (uf.a, vkey, 4); f = uf.f; if (__builtin_isinff (f) || f == 0) return 0; /* NaN != NaN, so the hash code of a NaN is irrelevant. Make it random so that not all NaNs wind up in the same place. */ if (__builtin_isnanf (f)) return runtime_fastrand1 (); return (uintptr_t) uf.si; } else if (key_size == 8) { union { unsigned char a[8]; double d; DItype di; } ud; double d; __builtin_memcpy (ud.a, vkey, 8); d = ud.d; if (__builtin_isinf (d) || d == 0) return 0; if (__builtin_isnan (d)) return runtime_fastrand1 (); return (uintptr_t) ud.di; } else runtime_throw ("__go_type_hash_float: invalid float size"); } /* Equality function for float types. */ _Bool __go_type_equal_float (const void *vk1, const void *vk2, uintptr_t key_size) { if (key_size == 4) { union { unsigned char a[4]; float f; } uf; float f1; float f2; __builtin_memcpy (uf.a, vk1, 4); f1 = uf.f; __builtin_memcpy (uf.a, vk2, 4); f2 = uf.f; return f1 == f2; } else if (key_size == 8) { union { unsigned char a[8]; double d; DItype di; } ud; double d1; double d2; __builtin_memcpy (ud.a, vk1, 8); d1 = ud.d; __builtin_memcpy (ud.a, vk2, 8); d2 = ud.d; return d1 == d2; } else runtime_throw ("__go_type_equal_float: invalid float size"); }