2012-01-06 22:47:49 +01:00
|
|
|
/* 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;
|
2012-09-22 08:06:31 +02:00
|
|
|
if (__builtin_isinff (f) || f == 0)
|
2012-01-06 22:47:49 +01:00
|
|
|
return 0;
|
2012-09-22 08:06:31 +02:00
|
|
|
|
|
|
|
/* 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 ();
|
|
|
|
|
2012-01-06 22:47:49 +01:00
|
|
|
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;
|
2012-09-22 08:06:31 +02:00
|
|
|
if (__builtin_isinf (d) || d == 0)
|
2012-01-06 22:47:49 +01:00
|
|
|
return 0;
|
2012-09-22 08:06:31 +02:00
|
|
|
|
|
|
|
if (__builtin_isnan (d))
|
|
|
|
return runtime_fastrand1 ();
|
|
|
|
|
2012-01-06 22:47:49 +01:00
|
|
|
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");
|
|
|
|
}
|