93c521ea9c
This includes the use of __complex and __builtin_ functions where unprefixed entities would suffice, and the use of a union for bit-casting between types. From-SVN: r211036
115 lines
2.5 KiB
C
115 lines
2.5 KiB
C
/* 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");
|
|
}
|