2013-05-14 Richard Biener <rguenther@suse.de>
[official-gcc.git] / libgo / runtime / go-type-float.c
blobe1c03e4284390d78c036a43b8b3aed863cf0d549
1 /* go-type-float.c -- hash and equality float functions.
3 Copyright 2012 The Go Authors. All rights reserved.
4 Use of this source code is governed by a BSD-style
5 license that can be found in the LICENSE file. */
7 #include "runtime.h"
8 #include "go-type.h"
10 /* The 32-bit and 64-bit types. */
12 typedef unsigned int SItype __attribute__ ((mode (SI)));
13 typedef unsigned int DItype __attribute__ ((mode (DI)));
15 /* Hash function for float types. */
17 uintptr_t
18 __go_type_hash_float (const void *vkey, uintptr_t key_size)
20 if (key_size == 4)
22 union
24 unsigned char a[4];
25 float f;
26 SItype si;
27 } uf;
28 float f;
30 __builtin_memcpy (uf.a, vkey, 4);
31 f = uf.f;
32 if (__builtin_isinff (f) || f == 0)
33 return 0;
35 /* NaN != NaN, so the hash code of a NaN is irrelevant. Make it
36 random so that not all NaNs wind up in the same place. */
37 if (__builtin_isnanf (f))
38 return runtime_fastrand1 ();
40 return (uintptr_t) uf.si;
42 else if (key_size == 8)
44 union
46 unsigned char a[8];
47 double d;
48 DItype di;
49 } ud;
50 double d;
52 __builtin_memcpy (ud.a, vkey, 8);
53 d = ud.d;
54 if (__builtin_isinf (d) || d == 0)
55 return 0;
57 if (__builtin_isnan (d))
58 return runtime_fastrand1 ();
60 return (uintptr_t) ud.di;
62 else
63 runtime_throw ("__go_type_hash_float: invalid float size");
66 /* Equality function for float types. */
68 _Bool
69 __go_type_equal_float (const void *vk1, const void *vk2, uintptr_t key_size)
71 if (key_size == 4)
73 union
75 unsigned char a[4];
76 float f;
77 } uf;
78 float f1;
79 float f2;
81 __builtin_memcpy (uf.a, vk1, 4);
82 f1 = uf.f;
83 __builtin_memcpy (uf.a, vk2, 4);
84 f2 = uf.f;
85 return f1 == f2;
87 else if (key_size == 8)
89 union
91 unsigned char a[8];
92 double d;
93 DItype di;
94 } ud;
95 double d1;
96 double d2;
98 __builtin_memcpy (ud.a, vk1, 8);
99 d1 = ud.d;
100 __builtin_memcpy (ud.a, vk2, 8);
101 d2 = ud.d;
102 return d1 == d2;
104 else
105 runtime_throw ("__go_type_equal_float: invalid float size");