mirror of git://gcc.gnu.org/git/gcc.git
				
				
				
			
		
			
				
	
	
		
			107 lines
		
	
	
		
			2.1 KiB
		
	
	
	
		
			C
		
	
	
	
			
		
		
	
	
			107 lines
		
	
	
		
			2.1 KiB
		
	
	
	
		
			C
		
	
	
	
/* go-type-float.c -- hash and equality float 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 "runtime.h"
 | 
						|
#include "go-type.h"
 | 
						|
 | 
						|
/* The 32-bit and 64-bit types.  */
 | 
						|
 | 
						|
typedef unsigned int SItype __attribute__ ((mode (SI)));
 | 
						|
typedef unsigned int DItype __attribute__ ((mode (DI)));
 | 
						|
 | 
						|
/* Hash function for float types.  */
 | 
						|
 | 
						|
uintptr_t
 | 
						|
__go_type_hash_float (const void *vkey, uintptr_t key_size)
 | 
						|
{
 | 
						|
  if (key_size == 4)
 | 
						|
    {
 | 
						|
      union
 | 
						|
      {
 | 
						|
	unsigned char a[4];
 | 
						|
	float f;
 | 
						|
	SItype si;
 | 
						|
      } uf;
 | 
						|
      float f;
 | 
						|
 | 
						|
      __builtin_memcpy (uf.a, vkey, 4);
 | 
						|
      f = uf.f;
 | 
						|
      if (__builtin_isinff (f) || f == 0)
 | 
						|
	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 (__builtin_isnanf (f))
 | 
						|
	return runtime_fastrand1 ();
 | 
						|
 | 
						|
      return (uintptr_t) uf.si;
 | 
						|
    }
 | 
						|
  else if (key_size == 8)
 | 
						|
    {
 | 
						|
      union
 | 
						|
      {
 | 
						|
	unsigned char a[8];
 | 
						|
	double d;
 | 
						|
	DItype di;
 | 
						|
      } ud;
 | 
						|
      double d;
 | 
						|
 | 
						|
      __builtin_memcpy (ud.a, vkey, 8);
 | 
						|
      d = ud.d;
 | 
						|
      if (__builtin_isinf (d) || d == 0)
 | 
						|
	return 0;
 | 
						|
 | 
						|
      if (__builtin_isnan (d))
 | 
						|
	return runtime_fastrand1 ();
 | 
						|
 | 
						|
      return (uintptr_t) ud.di;
 | 
						|
    }
 | 
						|
  else
 | 
						|
    runtime_throw ("__go_type_hash_float: invalid float size");
 | 
						|
}
 | 
						|
 | 
						|
/* Equality function for float types.  */
 | 
						|
 | 
						|
_Bool
 | 
						|
__go_type_equal_float (const void *vk1, const void *vk2, uintptr_t key_size)
 | 
						|
{
 | 
						|
  if (key_size == 4)
 | 
						|
    {
 | 
						|
      union
 | 
						|
      {
 | 
						|
	unsigned char a[4];
 | 
						|
	float f;
 | 
						|
      } uf;
 | 
						|
      float f1;
 | 
						|
      float f2;
 | 
						|
 | 
						|
      __builtin_memcpy (uf.a, vk1, 4);
 | 
						|
      f1 = uf.f;
 | 
						|
      __builtin_memcpy (uf.a, vk2, 4);
 | 
						|
      f2 = uf.f;
 | 
						|
      return f1 == f2;
 | 
						|
    }
 | 
						|
  else if (key_size == 8)
 | 
						|
    {
 | 
						|
      union
 | 
						|
      {
 | 
						|
	unsigned char a[8];
 | 
						|
	double d;
 | 
						|
	DItype di;
 | 
						|
      } ud;
 | 
						|
      double d1;
 | 
						|
      double d2;
 | 
						|
 | 
						|
      __builtin_memcpy (ud.a, vk1, 8);
 | 
						|
      d1 = ud.d;
 | 
						|
      __builtin_memcpy (ud.a, vk2, 8);
 | 
						|
      d2 = ud.d;
 | 
						|
      return d1 == d2;
 | 
						|
    }
 | 
						|
  else
 | 
						|
    runtime_throw ("__go_type_equal_float: invalid float size");
 | 
						|
}
 |