mirror of git://gcc.gnu.org/git/gcc.git
				
				
				
			
		
			
				
	
	
		
			121 lines
		
	
	
		
			2.6 KiB
		
	
	
	
		
			C
		
	
	
	
			
		
		
	
	
			121 lines
		
	
	
		
			2.6 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");
 | |
| }
 | |
| 
 | |
| const FuncVal __go_type_hash_complex_descriptor =
 | |
|   { (void *) __go_type_hash_complex };
 | |
| 
 | |
| /* 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");
 | |
| }
 | |
| 
 | |
| const FuncVal __go_type_equal_complex_descriptor =
 | |
|   { (void *) __go_type_equal_complex };
 |