1/* { dg-do compile { target { powerpc*-*-* && lp64 } } } */
2/* { dg-skip-if "" { powerpc*-*-darwin* } { "*" } { "" } } */
3/* { dg-require-effective-target powerpc_vsx_ok } */
4/* { dg-options "-mvsx -O2" } */
5
6/* This will run, and someday we should add the support to test whether we are
7   running on VSX hardware.  */
8
9#include <altivec.h>
10#include <stdlib.h>
11
12#ifdef DEBUG
13#include <stdio.h>
14
15static int errors = 0;
16#endif
17
18union args {
19  double scalar[2];
20  vector double vect;
21};
22
23union largs {
24  unsigned long scalar[2];
25  vector bool long vect;
26};
27
28static void
29do_test (union args *expected, union args *got, const char *name)
30{
31  if (expected->scalar[0] != got->scalar[0]
32      || expected->scalar[1] != got->scalar[1])
33    {
34#ifdef DEBUG
35      printf ("%s failed!\n", name);
36      errors++;
37#else
38      abort ();
39#endif
40    }
41}
42
43static void
44do_ltest (union largs *expected, union largs *got, const char *name)
45{
46  if (expected->scalar[0] != got->scalar[0]
47      || expected->scalar[1] != got->scalar[1])
48    {
49#ifdef DEBUG
50      printf ("%s failed!\n", name);
51      errors++;
52#else
53      abort ();
54#endif
55    }
56}
57
58
59/* Vec functions taking a single argument.  */
60static vector double
61vabs (vector double arg)
62{
63  return vec_abs (arg);
64}
65
66static vector double
67vceil (vector double arg)
68{
69  return vec_ceil (arg);
70}
71
72static vector double
73vfloor (vector double arg)
74{
75  return vec_floor (arg);
76}
77
78static vector double
79vnearbyint (vector double arg)
80{
81  return vec_nearbyint (arg);
82}
83
84static vector double
85vrint (vector double arg)
86{
87  return vec_rint (arg);
88}
89
90static vector double
91vsqrt (vector double arg)
92{
93  return vec_sqrt (arg);
94}
95
96/* Single argument tests.  */
97static struct
98{
99  union args result;
100  union args input;
101  vector double (*func) (vector double);
102  const char *name;
103} arg1_tests[] = {
104  /* result		input			function	name */
105  { {  1.0,  2.0 },	{ -1.0,  2.0 },		vabs,		"vabs" },
106  { {  1.0,  2.0 },	{  1.0, -2.0 },		vabs,		"vabs" },
107  { {  2.0,  2.0 },	{  1.1,  1.7 },		vceil,		"vceil" },
108  { { -1.0, -1.0 },	{ -1.1, -1.7 },		vceil,		"vceil" },
109  { { -1.0,  2.0 },	{ -1.5,  1.5 },		vceil,		"vceil" },
110  { {  1.0,  1.0 },	{  1.1,  1.7 },		vfloor,		"vfloor" },
111  { { -2.0, -2.0 },	{ -1.1, -1.7 },		vfloor,		"vfloor" },
112  { { -2.0,  1.0 },	{ -1.5,  1.5 },		vfloor,		"vfloor" },
113  { {  1.0,  2.0 },	{  1.1,  1.7 },		vnearbyint,	"vnearbyint" },
114  { { -1.0, -2.0 },	{ -1.1, -1.7 },		vnearbyint,	"vnearbyint" },
115  { { -2.0,  2.0 },	{ -1.5,  1.5 },		vnearbyint,	"vnearbyint" },
116  { {  1.0,  2.0 },	{  1.1,  1.7 },		vrint,		"vrint" },
117  { { -1.0, -2.0 },	{ -1.1, -1.7 },		vrint,		"vrint" },
118  { { -2.0,  2.0 },	{ -1.5,  1.5 },		vrint,		"vrint" },
119  { {  2.0,  4.0 },	{  4.0, 16.0 },		vsqrt,		"vsqrt" },
120};
121
122static void
123test_arg1 (void)
124{
125  unsigned i;
126
127#ifdef DEBUG
128  printf ("Single argument tests:\n");
129#endif
130
131  for (i = 0; i < sizeof (arg1_tests) / sizeof (arg1_tests[0]); i++)
132    {
133      union args u;
134      u.vect = arg1_tests[i].func (arg1_tests[i].input.vect);
135
136#ifdef DEBUG
137      printf ("test %-16s: expected { %4g, %4g }, got { %4g, %4g }, input { %4g, %4g }\n",
138	      arg1_tests[i].name,
139	      arg1_tests[i].result.scalar[0],
140	      arg1_tests[i].result.scalar[1],
141	      u.scalar[0],
142	      u.scalar[1],
143	      arg1_tests[i].input.scalar[0],
144	      arg1_tests[i].input.scalar[1]);
145#endif
146
147      do_test (&arg1_tests[i].result, &u, arg1_tests[i].name);
148    }
149
150  return;
151}
152
153
154/* Vect functions taking 2 arguments.  */
155static vector double
156vadd (vector double arg1, vector double arg2)
157{
158  return vec_add (arg1, arg2);
159}
160
161static vector double
162vadd2 (vector double arg1, vector double arg2)
163{
164  return arg1 + arg2;
165}
166
167static vector double
168vsub (vector double arg1, vector double arg2)
169{
170  return vec_sub (arg1, arg2);
171}
172
173static vector double
174vsub2 (vector double arg1, vector double arg2)
175{
176  return arg1 - arg2;
177}
178
179static vector double
180vmul (vector double arg1, vector double arg2)
181{
182  return vec_mul (arg1, arg2);
183}
184
185static vector double
186vmul2 (vector double arg1, vector double arg2)
187{
188  return arg1 * arg2;
189}
190
191static vector double
192vdiv (vector double arg1, vector double arg2)
193{
194  return vec_div (arg1, arg2);
195}
196
197static vector double
198vdiv2 (vector double arg1, vector double arg2)
199{
200  return arg1 / arg2;
201}
202
203static vector double
204vmax (vector double arg1, vector double arg2)
205{
206  return vec_max (arg1, arg2);
207}
208
209static vector double
210vmin (vector double arg1, vector double arg2)
211{
212  return vec_min (arg1, arg2);
213}
214
215/* 2 argument tests.  */
216static struct
217{
218  union args result;
219  union args input[2];
220  vector double (*func) (vector double, vector double);
221  const char *name;
222} arg2_tests[] = {
223  /* result */
224  { {  4.0,  6.0 },	{ {  1.0,  2.0 }, {  3.0,  4.0 } },	vadd,	"vadd"  },
225  { {  4.0, -6.0 },	{ {  1.0, -2.0 }, {  3.0, -4.0 } },	vadd,	"vadd"  },
226  { {  4.0,  6.0 },	{ {  1.0,  2.0 }, {  3.0,  4.0 } },	vadd2,	"vadd2" },
227  { {  4.0, -6.0 },	{ {  1.0, -2.0 }, {  3.0, -4.0 } },	vadd2,	"vadd2" },
228  { { -2.0, -2.0 },	{ {  1.0,  2.0 }, {  3.0,  4.0 } },	vsub,	"vsub"  },
229  { { -2.0,  2.0 },	{ {  1.0, -2.0 }, {  3.0, -4.0 } },	vsub,	"vsub"  },
230  { { -2.0, -2.0 },	{ {  1.0,  2.0 }, {  3.0,  4.0 } },	vsub2,	"vsub2" },
231  { { -2.0,  2.0 },	{ {  1.0, -2.0 }, {  3.0, -4.0 } },	vsub2,	"vsub2" },
232  { {  6.0,  4.0 },	{ {  2.0,  8.0 }, {  3.0,  0.5 } },	vmul,	"vmul"  },
233  { {  6.0,  4.0 },	{ {  2.0,  8.0 }, {  3.0,  0.5 } },	vmul2,	"vmul2" },
234  { {  2.0,  0.5 },	{ {  6.0,  4.0 }, {  3.0,  8.0 } },	vdiv,	"vdiv"  },
235  { {  2.0,  0.5 },	{ {  6.0,  4.0 }, {  3.0,  8.0 } },	vdiv2,	"vdiv2" },
236  { {  3.0,  4.0 },	{ {  1.0,  2.0 }, {  3.0,  4.0 } },	vmax,	"vmax"  },
237  { {  1.0,  4.0 },	{ {  1.0, -2.0 }, { -3.0,  4.0 } },	vmax,	"vmax"  },
238  { {  1.0,  2.0 },	{ {  1.0,  2.0 }, {  3.0,  4.0 } },	vmin,	"vmin"  },
239  { { -3.0, -2.0 },	{ {  1.0, -2.0 }, { -3.0,  4.0 } },	vmin,	"vmin"  },
240};
241
242static void
243test_arg2 (void)
244{
245  unsigned i;
246
247#ifdef DEBUG
248  printf ("\nTwo argument tests:\n");
249#endif
250
251  for (i = 0; i < sizeof (arg2_tests) / sizeof (arg2_tests[0]); i++)
252    {
253      union args u;
254      u.vect = arg2_tests[i].func (arg2_tests[i].input[0].vect,
255				   arg2_tests[i].input[1].vect);
256
257#ifdef DEBUG
258      printf ("test %-16s: expected { %4g, %4g }, got { %4g, %4g }, input { %4g, %4g }, { %4g, %4g }\n",
259	      arg2_tests[i].name,
260	      arg2_tests[i].result.scalar[0],
261	      arg2_tests[i].result.scalar[1],
262	      u.scalar[0],
263	      u.scalar[1],
264	      arg2_tests[i].input[0].scalar[0],
265	      arg2_tests[i].input[0].scalar[1],
266	      arg2_tests[i].input[1].scalar[0],
267	      arg2_tests[i].input[1].scalar[1]);
268#endif
269
270      do_test (&arg2_tests[i].result, &u, arg2_tests[i].name);
271    }
272
273  return;
274}
275
276
277/* Comparisons, returnning a boolean vector.  */
278static vector bool long
279vcmpeq (vector double arg1, vector double arg2)
280{
281  return vec_cmpeq (arg1, arg2);
282}
283
284static vector bool long
285vcmplt (vector double arg1, vector double arg2)
286{
287  return vec_cmplt (arg1, arg2);
288}
289
290static vector bool long
291vcmple (vector double arg1, vector double arg2)
292{
293  return vec_cmple (arg1, arg2);
294}
295
296static vector bool long
297vcmpgt (vector double arg1, vector double arg2)
298{
299  return vec_cmpgt (arg1, arg2);
300}
301
302static vector bool long
303vcmpge (vector double arg1, vector double arg2)
304{
305  return vec_cmpge (arg1, arg2);
306}
307
308#define ONE  0xffffffffffffffffUL
309#define ZERO 0x0000000000000000UL
310
311/* comparison tests.  */
312static struct
313{
314  union largs result;
315  union args input[2];
316  vector bool long (*func) (vector double, vector double);
317  const char *name;
318} argcmp_tests[] = {
319  { { ONE,  ZERO }, { {  1.0,  2.0 }, {  1.0, -2.0 } },	vcmpeq,	"vcmpeq" },
320  { { ZERO, ONE  }, { { -1.0,  2.0 }, {  1.0,  2.0 } },	vcmpeq,	"vcmpeq" },
321
322  { { ONE,  ONE  }, { {  1.0, -2.0 }, {  1.0, -2.0 } },	vcmple,	"vcmple" },
323  { { ONE,  ONE  }, { {  1.0, -2.0 }, {  2.0, -1.0 } },	vcmple,	"vcmple" },
324  { { ZERO, ZERO }, { {  2.0, -1.0 }, {  1.0, -2.0 } },	vcmple,	"vcmple" },
325
326  { { ZERO, ZERO }, { {  1.0, -2.0 }, {  1.0, -2.0 } },	vcmplt,	"vcmplt" },
327  { { ONE,  ONE  }, { {  1.0, -2.0 }, {  2.0, -1.0 } },	vcmplt,	"vcmplt" },
328  { { ZERO, ZERO }, { {  2.0, -1.0 }, {  1.0, -2.0 } },	vcmplt,	"vcmplt" },
329
330  { { ZERO, ZERO }, { {  1.0, -2.0 }, {  1.0, -2.0 } },	vcmpgt,	"vcmpgt" },
331  { { ZERO, ZERO }, { {  1.0, -2.0 }, {  2.0, -1.0 } },	vcmpgt,	"vcmpgt" },
332  { { ONE,  ONE  }, { {  2.0, -1.0 }, {  1.0, -2.0 } },	vcmpgt,	"vcmpgt" },
333
334  { { ONE,  ONE  }, { {  1.0, -2.0 }, {  1.0, -2.0 } },	vcmpge,	"vcmpge" },
335  { { ZERO, ZERO }, { {  1.0, -2.0 }, {  2.0, -1.0 } },	vcmpge,	"vcmpge" },
336  { { ONE,  ONE  }, { {  2.0, -1.0 }, {  1.0, -2.0 } },	vcmpge,	"vcmpge" },
337};
338
339static void
340test_argcmp (void)
341{
342  unsigned i;
343
344#ifdef DEBUG
345  printf ("\nComparison tests:\n");
346#endif
347
348  for (i = 0; i < sizeof (argcmp_tests) / sizeof (argcmp_tests[0]); i++)
349    {
350      union largs u;
351      u.vect = argcmp_tests[i].func (argcmp_tests[i].input[0].vect,
352				     argcmp_tests[i].input[1].vect);
353
354#ifdef DEBUG
355      printf ("test %-16s: expected { 0x%016lx, 0x%016lx }, got { 0x%016lx, 0x%016lx }, input { %4g, %4g }, { %4g, %4g }\n",
356	      argcmp_tests[i].name,
357	      argcmp_tests[i].result.scalar[0],
358	      argcmp_tests[i].result.scalar[1],
359	      u.scalar[0],
360	      u.scalar[1],
361	      argcmp_tests[i].input[0].scalar[0],
362	      argcmp_tests[i].input[0].scalar[1],
363	      argcmp_tests[i].input[1].scalar[0],
364	      argcmp_tests[i].input[1].scalar[1]);
365#endif
366
367      do_ltest (&argcmp_tests[i].result, &u, argcmp_tests[i].name);
368    }
369
370  return;
371}
372
373
374int
375main (int argc, char *argv[])
376{
377  test_arg1 ();
378  test_arg2 ();
379  test_argcmp ();
380
381#ifdef DEBUG
382  if (errors)
383    {
384      printf ("There were %d error(s)\n", errors);
385      return errors;
386    }
387  else
388    printf ("There were no errors\n");
389#endif
390
391  return 0;
392}
393