aboutsummaryrefslogtreecommitdiffstats
path: root/gcc-4.9/libgo/runtime/go-type-float.c
diff options
context:
space:
mode:
authorBen Cheng <bccheng@google.com>2014-03-25 22:37:19 -0700
committerBen Cheng <bccheng@google.com>2014-03-25 22:37:19 -0700
commit1bc5aee63eb72b341f506ad058502cd0361f0d10 (patch)
treec607e8252f3405424ff15bc2d00aa38dadbb2518 /gcc-4.9/libgo/runtime/go-type-float.c
parent283a0bf58fcf333c58a2a92c3ebbc41fb9eb1fdb (diff)
downloadtoolchain_gcc-1bc5aee63eb72b341f506ad058502cd0361f0d10.tar.gz
toolchain_gcc-1bc5aee63eb72b341f506ad058502cd0361f0d10.tar.bz2
toolchain_gcc-1bc5aee63eb72b341f506ad058502cd0361f0d10.zip
Initial checkin of GCC 4.9.0 from trunk (r208799).
Change-Id: I48a3c08bb98542aa215912a75f03c0890e497dba
Diffstat (limited to 'gcc-4.9/libgo/runtime/go-type-float.c')
-rw-r--r--gcc-4.9/libgo/runtime/go-type-float.c106
1 files changed, 106 insertions, 0 deletions
diff --git a/gcc-4.9/libgo/runtime/go-type-float.c b/gcc-4.9/libgo/runtime/go-type-float.c
new file mode 100644
index 000000000..e1c03e428
--- /dev/null
+++ b/gcc-4.9/libgo/runtime/go-type-float.c
@@ -0,0 +1,106 @@
+/* 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");
+}