Importing Upstream version 4.8.2
[platform/upstream/gcc48.git] / libgo / runtime / go-type-complex.c
1 /* go-type-complex.c -- hash and equality complex functions.
2
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.  */
6
7 #include "runtime.h"
8 #include "go-type.h"
9
10 /* The 64-bit type.  */
11
12 typedef unsigned int DItype __attribute__ ((mode (DI)));
13
14 /* Hash function for float types.  */
15
16 uintptr_t
17 __go_type_hash_complex (const void *vkey, uintptr_t key_size)
18 {
19   if (key_size == 8)
20     {
21       union
22       {
23         unsigned char a[8];
24         __complex float cf;
25         DItype di;
26       } ucf;
27       __complex float cf;
28       float cfr;
29       float cfi;
30
31       __builtin_memcpy (ucf.a, vkey, 8);
32       cf = ucf.cf;
33       cfr = __builtin_crealf (cf);
34       cfi = __builtin_cimagf (cf);
35       if (__builtin_isinff (cfr) || __builtin_isinff (cfi))
36         return 0;
37
38       /* NaN != NaN, so the hash code of a NaN is irrelevant.  Make it
39          random so that not all NaNs wind up in the same place.  */
40       if (__builtin_isnanf (cfr) || __builtin_isnanf (cfi))
41         return runtime_fastrand1 ();
42
43       /* Avoid negative zero.  */
44       if (cfr == 0 && cfi == 0)
45         return 0;
46       else if (cfr == 0)
47         ucf.cf = cfi * 1.0iF;
48       else if (cfi == 0)
49         ucf.cf = cfr;
50
51       return ucf.di;
52     }
53   else if (key_size == 16)
54     {
55       union
56       {
57         unsigned char a[16];
58         __complex double cd;
59         DItype adi[2];
60       } ucd;
61       __complex double cd;
62       double cdr;
63       double cdi;
64
65       __builtin_memcpy (ucd.a, vkey, 16);
66       cd = ucd.cd;
67       cdr = __builtin_crealf (cd);
68       cdi = __builtin_cimagf (cd);
69       if (__builtin_isinf (cdr) || __builtin_isinf (cdi))
70         return 0;
71
72       if (__builtin_isnan (cdr) || __builtin_isnan (cdi))
73         return runtime_fastrand1 ();
74
75       /* Avoid negative zero.  */
76       if (cdr == 0 && cdi == 0)
77         return 0;
78       else if (cdr == 0)
79         ucd.cd = cdi * 1.0i;
80       else if (cdi == 0)
81         ucd.cd = cdr;
82
83       return ucd.adi[0] ^ ucd.adi[1];
84     }
85   else
86     runtime_throw ("__go_type_hash_complex: invalid complex size");
87 }
88
89 /* Equality function for complex types.  */
90
91 _Bool
92 __go_type_equal_complex (const void *vk1, const void *vk2, uintptr_t key_size)
93 {
94   if (key_size == 8)
95     {
96       union
97       {
98         unsigned char a[8];
99         __complex float cf;
100       } ucf;
101       __complex float cf1;
102       __complex float cf2;
103
104       __builtin_memcpy (ucf.a, vk1, 8);
105       cf1 = ucf.cf;
106       __builtin_memcpy (ucf.a, vk2, 8);
107       cf2 = ucf.cf;
108       return cf1 == cf2;
109     }
110   else if (key_size == 16)
111     {
112       union
113       {
114         unsigned char a[16];
115         __complex double cd;
116       } ucd;
117       __complex double cd1;
118       __complex double cd2;
119
120       __builtin_memcpy (ucd.a, vk1, 16);
121       cd1 = ucd.cd;
122       __builtin_memcpy (ucd.a, vk2, 16);
123       cd2 = ucd.cd;
124       return cd1 == cd2;
125     }
126   else
127     runtime_throw ("__go_type_equal_complex: invalid complex size");
128 }