aboutsummaryrefslogtreecommitdiffstats
path: root/gcc-4.9/libgo/runtime/go-type-complex.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-complex.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-complex.c')
-rw-r--r--gcc-4.9/libgo/runtime/go-type-complex.c128
1 files changed, 128 insertions, 0 deletions
diff --git a/gcc-4.9/libgo/runtime/go-type-complex.c b/gcc-4.9/libgo/runtime/go-type-complex.c
new file mode 100644
index 000000000..106024f5c
--- /dev/null
+++ b/gcc-4.9/libgo/runtime/go-type-complex.c
@@ -0,0 +1,128 @@
+/* go-type-complex.c -- hash and equality complex 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 64-bit type. */
+
+typedef unsigned int DItype __attribute__ ((mode (DI)));
+
+/* Hash function for float types. */
+
+uintptr_t
+__go_type_hash_complex (const void *vkey, uintptr_t key_size)
+{
+ if (key_size == 8)
+ {
+ union
+ {
+ unsigned char a[8];
+ __complex float cf;
+ DItype di;
+ } ucf;
+ __complex float cf;
+ float cfr;
+ float cfi;
+
+ __builtin_memcpy (ucf.a, vkey, 8);
+ cf = ucf.cf;
+ cfr = __builtin_crealf (cf);
+ cfi = __builtin_cimagf (cf);
+ if (__builtin_isinff (cfr) || __builtin_isinff (cfi))
+ 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 (cfr) || __builtin_isnanf (cfi))
+ return runtime_fastrand1 ();
+
+ /* Avoid negative zero. */
+ if (cfr == 0 && cfi == 0)
+ return 0;
+ else if (cfr == 0)
+ ucf.cf = cfi * 1.0iF;
+ else if (cfi == 0)
+ ucf.cf = cfr;
+
+ return ucf.di;
+ }
+ else if (key_size == 16)
+ {
+ union
+ {
+ unsigned char a[16];
+ __complex double cd;
+ DItype adi[2];
+ } ucd;
+ __complex double cd;
+ double cdr;
+ double cdi;
+
+ __builtin_memcpy (ucd.a, vkey, 16);
+ cd = ucd.cd;
+ cdr = __builtin_crealf (cd);
+ cdi = __builtin_cimagf (cd);
+ if (__builtin_isinf (cdr) || __builtin_isinf (cdi))
+ return 0;
+
+ if (__builtin_isnan (cdr) || __builtin_isnan (cdi))
+ return runtime_fastrand1 ();
+
+ /* Avoid negative zero. */
+ if (cdr == 0 && cdi == 0)
+ return 0;
+ else if (cdr == 0)
+ ucd.cd = cdi * 1.0i;
+ else if (cdi == 0)
+ ucd.cd = cdr;
+
+ return ucd.adi[0] ^ ucd.adi[1];
+ }
+ else
+ runtime_throw ("__go_type_hash_complex: invalid complex size");
+}
+
+/* Equality function for complex types. */
+
+_Bool
+__go_type_equal_complex (const void *vk1, const void *vk2, uintptr_t key_size)
+{
+ if (key_size == 8)
+ {
+ union
+ {
+ unsigned char a[8];
+ __complex float cf;
+ } ucf;
+ __complex float cf1;
+ __complex float cf2;
+
+ __builtin_memcpy (ucf.a, vk1, 8);
+ cf1 = ucf.cf;
+ __builtin_memcpy (ucf.a, vk2, 8);
+ cf2 = ucf.cf;
+ return cf1 == cf2;
+ }
+ else if (key_size == 16)
+ {
+ union
+ {
+ unsigned char a[16];
+ __complex double cd;
+ } ucd;
+ __complex double cd1;
+ __complex double cd2;
+
+ __builtin_memcpy (ucd.a, vk1, 16);
+ cd1 = ucd.cd;
+ __builtin_memcpy (ucd.a, vk2, 16);
+ cd2 = ucd.cd;
+ return cd1 == cd2;
+ }
+ else
+ runtime_throw ("__go_type_equal_complex: invalid complex size");
+}