1/* Copyright (C) 2010  Free Software Foundation.
2
3   Verify that folding of built-in cproj is correctly performed by the
4   compiler.
5
6   Origin: Kaveh R. Ghazi,  April 9, 2010.  */
7
8/* { dg-do link } */
9/* { dg-add-options ieee } */
10
11/* All references to link_error should go away at compile-time.  The
12   argument is the __LINE__ number.  It appears in the tree dump file
13   and aids in debugging should any of the tests fail.  */
14extern void link_error(int);
15
16#define CPROJ(X) __builtin_cproj(X)
17#define CPROJF(X) __builtin_cprojf(X)
18#define CPROJL(X) __builtin_cprojl(X)
19#ifndef __SPU__
20#define INF __builtin_inff()
21#else
22#define INF __builtin_inf()
23#endif
24#define I 1i
25#define CPSGN(X,Y) __builtin_copysignf((X),(Y))
26#define CIMAG(X) __builtin_cimagf(X)
27#define CREAL(X) __builtin_crealf(X)
28
29/* Check that the signs of the real and/or imaginary parts of two
30   complex numbers match.  */
31#define CKSGN(X,Y) (CKSGN_R(X,Y) || CKSGN_I(X,Y))
32#define CKSGN_R(X,Y) (CPSGN(1,CREAL(X)) != CPSGN(1,CREAL(Y)))
33#define CKSGN_I(X,Y) (CPSGN(1,CIMAG(X)) != CPSGN(1,CIMAG(Y)))
34
35/* Test that (cproj(X) == ZERO+Inf) and that the signs of the
36   imaginary parts match.  ZERO is +/- 0i.  */
37#ifndef __SPU__
38#define TEST_CST_INF(X,ZERO) do { \
39  if (CPROJF(X) != ZERO+INF || CKSGN_I(CPROJF(X),ZERO+INF)) \
40    link_error(__LINE__); \
41  if (CPROJ(X) != ZERO+INF || CKSGN_I(CPROJ(X),ZERO+INF)) \
42    link_error(__LINE__); \
43  if (CPROJL(X) != ZERO+INF || CKSGN_I(CPROJL(X),ZERO+INF)) \
44    link_error(__LINE__); \
45} while (0)
46#else
47#define TEST_CST_INF(X,ZERO) do { \
48  if (CPROJ(X) != ZERO+INF || CKSGN_I(CPROJ(X),ZERO+INF)) \
49    link_error(__LINE__); \
50  if (CPROJL(X) != ZERO+INF || CKSGN_I(CPROJL(X),ZERO+INF)) \
51    link_error(__LINE__); \
52} while (0)
53#endif
54
55/* Test that (cproj(X) == X) for all finite (X).  */
56#define TEST_CST(X) do { \
57  if (CPROJF(X) != (X) || CKSGN(CPROJF(X),(X))) \
58    link_error(__LINE__); \
59} while (0)
60
61/* Test that cproj(X + I*INF) -> (ZERO + INF), where ZERO is +-0i.
62   NEG is either blank or a minus sign when ZERO is negative.  */
63#ifndef __SPU__
64#define TEST_IMAG_INF(NEG,ZERO) do { \
65  if (CPROJF(f+I*NEG INF) != ZERO+INF \
66      || CKSGN_I (CPROJF(f+I*NEG INF), ZERO+INF)) \
67    link_error(__LINE__); \
68  if (CPROJ(d+I*NEG INF) != ZERO+INF \
69      || CKSGN_I (CPROJ(d+I*NEG INF), ZERO+INF)) \
70    link_error(__LINE__); \
71  if (CPROJL(ld+I*NEG INF) != ZERO+INF \
72      || CKSGN_I (CPROJL(ld+I*NEG INF), ZERO+INF)) \
73    link_error(__LINE__); \
74} while (0)
75#else
76#define TEST_IMAG_INF(NEG,ZERO) do { \
77  if (CPROJ(d+I*NEG INF) != ZERO+INF \
78      || CKSGN_I (CPROJ(d+I*NEG INF), ZERO+INF)) \
79    link_error(__LINE__); \
80  if (CPROJL(ld+I*NEG INF) != ZERO+INF \
81      || CKSGN_I (CPROJL(ld+I*NEG INF), ZERO+INF)) \
82    link_error(__LINE__); \
83} while (0)
84#endif
85
86/* Like TEST_IMAG_INF, but check that side effects are honored.  */
87#ifndef __SPU__
88#define TEST_IMAG_INF_SIDE_EFFECT(NEG,ZERO) do { \
89  int side = 4; \
90  if (CPROJF(++side+I*NEG INF) != ZERO+INF \
91      || CKSGN_I (CPROJF(++side+I*NEG INF), ZERO+INF)) \
92    link_error(__LINE__); \
93  if (CPROJ(++side+I*NEG INF) != ZERO+INF \
94      || CKSGN_I (CPROJ(++side+I*NEG INF), ZERO+INF)) \
95    link_error(__LINE__); \
96  if (CPROJL(++side+I*NEG INF) != ZERO+INF \
97      || CKSGN_I (CPROJL(++side+I*NEG INF), ZERO+INF)) \
98    link_error(__LINE__); \
99  if (side != 10) \
100    link_error(__LINE__); \
101} while (0)
102#else
103#define TEST_IMAG_INF_SIDE_EFFECT(NEG,ZERO) do { \
104  int side = 4; \
105  if (CPROJ(++side+I*NEG INF) != ZERO+INF \
106      || CKSGN_I (CPROJ(++side+I*NEG INF), ZERO+INF)) \
107    link_error(__LINE__); \
108  if (CPROJL(++side+I*NEG INF) != ZERO+INF \
109      || CKSGN_I (CPROJL(++side+I*NEG INF), ZERO+INF)) \
110    link_error(__LINE__); \
111  if (side != 8) \
112    link_error(__LINE__); \
113} while (0)
114#endif
115
116/* Test that cproj(INF, POSITIVE) -> INF+0i.  NEG is either blank or a
117   minus sign to test negative INF.  */
118#ifndef __SPU__
119#define TEST_REAL_INF(NEG) do { \
120  __real cf = NEG INF; \
121  __imag cf = (x ? 4 : 5); \
122  if (CPROJF(cf) != INF \
123      || CKSGN_I (CPROJF(cf), INF)) \
124    link_error(__LINE__); \
125  __real cd = NEG INF; \
126  __imag cd = (x ? 4 : 5); \
127  if (CPROJ(cd) != INF \
128      || CKSGN_I (CPROJ(cd), INF)) \
129    link_error(__LINE__); \
130  __real cld = NEG INF; \
131  __imag cld = (x ? 4 : 5); \
132  if (CPROJL(cld) != INF \
133      || CKSGN_I (CPROJL(cld), INF)) \
134    link_error(__LINE__); \
135} while (0)
136#else
137#define TEST_REAL_INF(NEG) do { \
138  __real cd = NEG INF; \
139  __imag cd = (x ? 4 : 5); \
140  if (CPROJ(cd) != INF \
141      || CKSGN_I (CPROJ(cd), INF)) \
142    link_error(__LINE__); \
143  __real cld = NEG INF; \
144  __imag cld = (x ? 4 : 5); \
145  if (CPROJL(cld) != INF \
146      || CKSGN_I (CPROJL(cld), INF)) \
147    link_error(__LINE__); \
148} while (0)
149#endif
150
151/* Like TEST_REAL_INF, but check that side effects are honored.  */
152#ifndef __SPU__
153#define TEST_REAL_INF_SIDE_EFFECT(NEG) do { \
154  int side = -9; \
155  __real cf = NEG INF; \
156  __imag cf = (x ? 4 : 5); \
157  if (CPROJF((++side,cf)) != INF \
158      || CKSGN_I (CPROJF((++side,cf)), INF)) \
159    link_error(__LINE__); \
160  __real cd = NEG INF; \
161  __imag cd = (x ? 4 : 5); \
162  if (CPROJ((++side,cd)) != INF \
163      || CKSGN_I (CPROJ((++side,cd)), INF)) \
164    link_error(__LINE__); \
165  __real cld = NEG INF; \
166  __imag cld = (x ? 4 : 5); \
167  if (CPROJL((++side,cld)) != INF \
168      || CKSGN_I (CPROJL((++side,cld)), INF)) \
169    link_error(__LINE__); \
170  if (side != -3) \
171    link_error(__LINE__); \
172} while (0)
173#else
174#define TEST_REAL_INF_SIDE_EFFECT(NEG) do { \
175  int side = -9; \
176  __real cd = NEG INF; \
177  __imag cd = (x ? 4 : 5); \
178  if (CPROJ((++side,cd)) != INF \
179      || CKSGN_I (CPROJ((++side,cd)), INF)) \
180    link_error(__LINE__); \
181  __real cld = NEG INF; \
182  __imag cld = (x ? 4 : 5); \
183  if (CPROJL((++side,cld)) != INF \
184      || CKSGN_I (CPROJL((++side,cld)), INF)) \
185    link_error(__LINE__); \
186  if (side != -5) \
187    link_error(__LINE__); \
188} while (0)
189#endif
190
191void foo (_Complex long double cld, _Complex double cd, _Complex float cf,
192	  long double ld, double d, float f, int x)
193{
194  TEST_CST_INF (INF+0I, 0);
195  TEST_CST_INF (INF-0I, -0.FI);
196  TEST_CST_INF (INF+4I, 0);
197  TEST_CST_INF (INF-4I, -0.FI);
198  TEST_CST_INF (-INF+0I, 0);
199  TEST_CST_INF (-INF-0I, -0.FI);
200  TEST_CST_INF (-INF+4I, 0);
201  TEST_CST_INF (-INF-4I, -0.FI);
202
203  TEST_CST_INF (0+I*INF, 0);
204  TEST_CST_INF (0-I*INF, -0.FI);
205  TEST_CST_INF (23+I*INF, 0);
206  TEST_CST_INF (23-I*INF, -0.FI);
207  TEST_CST_INF (-0.F+I*INF, 0);
208  TEST_CST_INF (-0.F-I*INF, -0.FI);
209  TEST_CST_INF (-23+I*INF, 0);
210  TEST_CST_INF (-23-I*INF, -0.FI);
211
212  TEST_CST_INF (INF+I*INF, 0);
213  TEST_CST_INF (INF-I*INF, -0.FI);
214  TEST_CST_INF (-INF+I*INF, 0);
215  TEST_CST_INF (-INF-I*INF, -0.FI);
216
217  TEST_CST (0);
218  TEST_CST (-0.F);
219  TEST_CST (0-0.FI);
220  TEST_CST (-0.F-0.FI);
221
222  TEST_CST (22+3I);
223  TEST_CST (22-3I);
224  TEST_CST (-22+3I);
225  TEST_CST (-22-3I);
226
227  TEST_IMAG_INF (,0.FI);
228  TEST_IMAG_INF (-,-0.FI);
229
230#ifdef __OPTIMIZE__
231  TEST_REAL_INF( );
232  TEST_REAL_INF(-);
233
234  TEST_IMAG_INF_SIDE_EFFECT (,0.FI);
235  TEST_IMAG_INF_SIDE_EFFECT (-,-0.FI);
236
237  TEST_REAL_INF_SIDE_EFFECT( );
238  TEST_REAL_INF_SIDE_EFFECT(-);
239#endif
240
241  return;
242}
243
244int main (void)
245{
246  return 0;
247}
248