mirror of git://gcc.gnu.org/git/gcc.git
				
				
				
			
		
			
				
	
	
		
			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");
 | 
						|
}
 |