blob: e1c03e4284390d78c036a43b8b3aed863cf0d549 [file] [log] [blame]
/* 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");
}