/* 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 #include #include #include #include "runtime.h" #include "go-type.h" /* Hash function for float types. */ uintptr_t __go_type_hash_complex (const void *vkey, uintptr_t key_size) { if (key_size == 8) { const complex float *cfp; complex float cf; float cfr; float cfi; uint64_t fi; cfp = (const complex float *) vkey; cf = *cfp; cfr = crealf (cf); cfi = cimagf (cf); if (isinf (cfr) || isinf (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 (isnan (cfr) || isnan (cfi)) return runtime_fastrand1 (); /* Avoid negative zero. */ if (cfr == 0 && cfi == 0) return 0; else if (cfr == 0) cf = cfi * I; else if (cfi == 0) cf = cfr; memcpy (&fi, &cf, 8); return (uintptr_t) cfi; } else if (key_size == 16) { const complex double *cdp; complex double cd; double cdr; double cdi; uint64_t di[2]; cdp = (const complex double *) vkey; cd = *cdp; cdr = creal (cd); cdi = cimag (cd); if (isinf (cdr) || isinf (cdi)) return 0; if (isnan (cdr) || isnan (cdi)) return runtime_fastrand1 (); /* Avoid negative zero. */ if (cdr == 0 && cdi == 0) return 0; else if (cdr == 0) cd = cdi * I; else if (cdi == 0) cd = cdr; memcpy (&di, &cd, 16); return di[0] ^ di[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) { const complex float *cfp1; const complex float *cfp2; cfp1 = (const complex float *) vk1; cfp2 = (const complex float *) vk2; return *cfp1 == *cfp2; } else if (key_size == 16) { const complex double *cdp1; const complex double *cdp2; cdp1 = (const complex double *) vk1; cdp2 = (const complex double *) vk2; return *cdp1 == *cdp2; } else runtime_throw ("__go_type_equal_complex: invalid complex size"); }