123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115 |
- /* 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 <complex.h>
- #include <math.h>
- #include <stdint.h>
- #include <string.h>
- #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");
- }
|