/* 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"); }