OSDN Git Service

runtime: Save all registers on stack for GC scan.
[pf3gnuchains/gcc-fork.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           || __builtin_isnanf (cfr) || __builtin_isnanf (cfi))
37         return 0;
38
39       /* Avoid negative zero.  */
40       if (cfr == 0 && cfi == 0)
41         return 0;
42       else if (cfr == 0)
43         ucf.cf = cfi * 1.0iF;
44       else if (cfi == 0)
45         ucf.cf = cfr;
46
47       return ucf.di;
48     }
49   else if (key_size == 16)
50     {
51       union
52       {
53         unsigned char a[16];
54         __complex double cd;
55         DItype adi[2];
56       } ucd;
57       __complex double cd;
58       double cdr;
59       double cdi;
60
61       __builtin_memcpy (ucd.a, vkey, 16);
62       cd = ucd.cd;
63       cdr = __builtin_crealf (cd);
64       cdi = __builtin_cimagf (cd);
65       if (__builtin_isinf (cdr) || __builtin_isinf (cdi)
66           || __builtin_isnan (cdr) || __builtin_isnan (cdi))
67         return 0;
68
69       /* Avoid negative zero.  */
70       if (cdr == 0 && cdi == 0)
71         return 0;
72       else if (cdr == 0)
73         ucd.cd = cdi * 1.0i;
74       else if (cdi == 0)
75         ucd.cd = cdr;
76
77       return ucd.adi[0] ^ ucd.adi[1];
78     }
79   else
80     runtime_throw ("__go_type_hash_complex: invalid complex size");
81 }
82
83 /* Equality function for complex types.  */
84
85 _Bool
86 __go_type_equal_complex (const void *vk1, const void *vk2, uintptr_t key_size)
87 {
88   if (key_size == 8)
89     {
90       union
91       {
92         unsigned char a[8];
93         __complex float cf;
94       } ucf;
95       __complex float cf1;
96       __complex float cf2;
97
98       __builtin_memcpy (ucf.a, vk1, 8);
99       cf1 = ucf.cf;
100       __builtin_memcpy (ucf.a, vk2, 8);
101       cf2 = ucf.cf;
102       return cf1 == cf2;
103     }
104   else if (key_size == 16)
105     {
106       union
107       {
108         unsigned char a[16];
109         __complex double cd;
110       } ucd;
111       __complex double cd1;
112       __complex double cd2;
113
114       __builtin_memcpy (ucd.a, vk1, 16);
115       cd1 = ucd.cd;
116       __builtin_memcpy (ucd.a, vk2, 16);
117       cd2 = ucd.cd;
118       return cd1 == cd2;
119     }
120   else
121     runtime_throw ("__go_type_equal_complex: invalid complex size");
122 }