blob: dcc88b1f3a4c64c26b0f15cea8befbe612a11a1a [file] [log] [blame]
/* { dg-do run { target lp64 } } */
/* { dg-skip-if "" { powerpc*-*-darwin* } } */
/* { dg-require-effective-target powerpc_vsx_ok } */
/* { dg-options "-mvsx -O2" } */
/* This will run, and someday we should add the support to test whether we are
running on VSX hardware. */
#include <altivec.h>
#include <stdlib.h>
#ifdef DEBUG
#include <stdio.h>
static int errors = 0;
#endif
union args_d {
double scalar[2];
vector double vect;
};
union args_f {
float scalar[4];
vector float vect;
};
union largs {
unsigned long scalar[2];
vector bool long vect;
};
static void
do_test_d (union args_d *expected, union args_d *got, const char *name)
{
if (expected->scalar[0] != got->scalar[0]
|| expected->scalar[1] != got->scalar[1])
{
#ifdef DEBUG
printf ("%s failed!\n", name);
errors++;
#else
abort ();
#endif
}
}
static void
do_test_f (union args_f *expected, union args_f *got, const char *name)
{
if (expected->scalar[0] != got->scalar[0]
|| expected->scalar[1] != got->scalar[1]
|| expected->scalar[2] != got->scalar[2]
|| expected->scalar[3] != got->scalar[3])
{
#ifdef DEBUG
printf ("%s failed!\n", name);
errors++;
#else
abort ();
#endif
}
}
static void
do_ltest (union largs *expected, union largs *got, const char *name)
{
if (expected->scalar[0] != got->scalar[0]
|| expected->scalar[1] != got->scalar[1])
{
#ifdef DEBUG
printf ("%s failed!\n", name);
errors++;
#else
abort ();
#endif
}
}
/* Vec functions taking a single argument. */
static vector double
vabs (vector double arg)
{
return vec_abs (arg);
}
static vector double
vceil_d (vector double arg)
{
return vec_ceil (arg);
}
static vector float
vceil_f (vector float arg)
{
return vec_ceil (arg);
}
static vector double
vfloor_d (vector double arg)
{
return vec_floor (arg);
}
static vector float
vfloor_f (vector float arg)
{
return vec_floor (arg);
}
static vector double
vnearbyint_d (vector double arg)
{
return vec_nearbyint (arg);
}
static vector float
vnearbyint_f (vector float arg)
{
return vec_nearbyint (arg);
}
static vector float
vrint_f (vector float arg)
{
return vec_rint (arg);
}
static vector double
vrint_d (vector double arg)
{
return vec_rint (arg);
}
static vector float
vsqrt_f (vector float arg)
{
return vec_sqrt (arg);
}
static vector double
vsqrt_d (vector double arg)
{
return vec_sqrt (arg);
}
/* Single argument tests with double args */
static struct
{
union args_d result;
union args_d input;
vector double (*func) (vector double);
const char *name;
} arg1_tests_d[] = {
/* result input function name */
{ { 1.0, 2.0 }, { -1.0, 2.0 }, vabs, "vabs" },
{ { 1.0, 2.0 }, { 1.0, -2.0 }, vabs, "vabs" },
{ { 2.0, 2.0 }, { 1.1, 1.7 }, vceil_d, "vceil_d" },
{ { -1.0, -1.0 }, { -1.1, -1.7 }, vceil_d, "vceil_d" },
{ { -1.0, 2.0 }, { -1.5, 1.5 }, vceil_d, "vceil_d" },
{ { 1.0, 1.0 }, { 1.1, 1.7 }, vfloor_d, "vfloor_d" },
{ { -2.0, -2.0 }, { -1.1, -1.7 }, vfloor_d, "vfloor_d" },
{ { -2.0, 1.0 }, { -1.5, 1.5 }, vfloor_d, "vfloor_d" },
{ { 1.0, 2.0 }, { 1.1, 1.7 }, vnearbyint_d, "vnearbyint_d" },
{ { -1.0, -2.0 }, { -1.1, -1.7 }, vnearbyint_d, "vnearbyint_d" },
{ { -2.0, 2.0 }, { -1.5, 1.5 }, vnearbyint_d, "vnearbyint_d" },
{ { 1.0, 2.0 }, { 1.1, 1.7 }, vrint_d, "vrint_d" },
{ { -1.0, -2.0 }, { -1.1, -1.7 }, vrint_d, "vrint_d" },
{ { -2.0, 2.0 }, { -1.5, 1.5 }, vrint_d, "vrint_d" },
{ { 2.0, 4.0 }, { 4.0, 16.0 }, vsqrt_d, "vsqrt_d" },
};
static void
test_arg1_d (void)
{
unsigned i;
#ifdef DEBUG
printf ("\nSingle argument tests with double args:\n");
#endif
for (i = 0; i < sizeof (arg1_tests_d) / sizeof (arg1_tests_d[0]); i++)
{
union args_d u;
u.vect = arg1_tests_d[i].func (arg1_tests_d[i].input.vect);
#ifdef DEBUG
printf ("test %-16s: expected { %4g, %4g }, got { %4g, %4g }, input { %4g, %4g }\n",
arg1_tests_d[i].name,
arg1_tests_d[i].result.scalar[0],
arg1_tests_d[i].result.scalar[1],
u.scalar[0],
u.scalar[1],
arg1_tests_d[i].input.scalar[0],
arg1_tests_d[i].input.scalar[1]);
#endif
do_test_d (&arg1_tests_d[i].result, &u, arg1_tests_d[i].name);
}
return;
}
/* Single argument tests with float args. */
static struct
{
union args_f result;
union args_f input;
vector float (*func) (vector float);
const char *name;
} arg1_tests_f[] = {
/* result input function name */
{ { 2.0, 2.0, 3.0, 3.0 }, { 1.05, 1.1, 2.2, 2.3 }, vceil_f, "vceil_f" },
{ { -1.0, -1.0, -2.0, -2.0 }, { -1.1, -1.7, -2.1, -2.4 }, vceil_f, "vceil_f" },
{ { 1.0, 1.0, 2.0, 2.0 }, { 1.05, 1.1, 2.2, 2.3 }, vfloor_f, "vfloor_f" },
{ { -2.0, -2.0, -3.0, -3.0 }, { -1.1, -1.7, -2.1, -2.4 }, vfloor_f, "vfloor_f" },
{ { 1.0, 2.0, -3.0, 3.0 }, { 1.1, 1.7, -3.1, 3.1 }, vnearbyint_f, "vnearbyint_f" },
{ { -1.0, -2.0, -3.0, 3.0 }, { -1.1, -1.7, -2.9, 2.9 }, vnearbyint_f, "vnearbyint_f" },
{ { -2.0, 2.0, -3.0, 3.0 }, { -1.5, 1.5, -2.55, 3.49 }, vnearbyint_f, "vnearbyint_f" },
{ { 10.0, 18.0, 30.0, 40.0 }, { 10.1, 17.7, 30.0, 40.01 }, vrint_f, "vrint_f" },
{ { -11.0, -18.0, -30.0, -40.0 }, { -11.1, -17.7, -30.0, -40.01 }, vrint_f, "vrint_f" },
{ { 2.0, 4.0 }, { 4.0, 16.0 }, vsqrt_f, "vsqrt_f" },
};
static void
test_arg1_f (void)
{
unsigned i;
#ifdef DEBUG
printf ("\nSingle argument tests with float args:\n");
#endif
for (i = 0; i < sizeof (arg1_tests_f) / sizeof (arg1_tests_f[0]); i++)
{
union args_f u;
u.vect = arg1_tests_f[i].func (arg1_tests_f[i].input.vect);
#ifdef DEBUG
printf ("test %-16s: expected { %4g, %4g, %4g, %4g }, got { %4g, %4g, %4g, %4g }, input { %4g, %4g, %4g, %4g }\n",
arg1_tests_f[i].name,
arg1_tests_f[i].result.scalar[0],
arg1_tests_f[i].result.scalar[1],
arg1_tests_f[i].result.scalar[2],
arg1_tests_f[i].result.scalar[3],
u.scalar[0],
u.scalar[1],
u.scalar[2],
u.scalar[3],
arg1_tests_f[i].input.scalar[0],
arg1_tests_f[i].input.scalar[1],
arg1_tests_f[i].input.scalar[2],
arg1_tests_f[i].input.scalar[3]);
#endif
do_test_f (&arg1_tests_f[i].result, &u, arg1_tests_f[i].name);
}
return;
}
/* Vect functions taking 2 arguments. */
static vector double
vadd (vector double arg1, vector double arg2)
{
return vec_add (arg1, arg2);
}
static vector double
vadd2 (vector double arg1, vector double arg2)
{
return arg1 + arg2;
}
static vector double
vsub (vector double arg1, vector double arg2)
{
return vec_sub (arg1, arg2);
}
static vector double
vsub2 (vector double arg1, vector double arg2)
{
return arg1 - arg2;
}
static vector double
vmul (vector double arg1, vector double arg2)
{
return vec_mul (arg1, arg2);
}
static vector double
vmul2 (vector double arg1, vector double arg2)
{
return arg1 * arg2;
}
static vector double
vdiv (vector double arg1, vector double arg2)
{
return vec_div (arg1, arg2);
}
static vector double
vdiv2 (vector double arg1, vector double arg2)
{
return arg1 / arg2;
}
static vector double
vmax (vector double arg1, vector double arg2)
{
return vec_max (arg1, arg2);
}
static vector double
vmin (vector double arg1, vector double arg2)
{
return vec_min (arg1, arg2);
}
/* 2 argument tests. */
static struct
{
union args_d result;
union args_d input[2];
vector double (*func) (vector double, vector double);
const char *name;
} arg2_tests[] = {
/* result */
{ { 4.0, 6.0 }, { { 1.0, 2.0 }, { 3.0, 4.0 } }, vadd, "vadd" },
{ { 4.0, -6.0 }, { { 1.0, -2.0 }, { 3.0, -4.0 } }, vadd, "vadd" },
{ { 4.0, 6.0 }, { { 1.0, 2.0 }, { 3.0, 4.0 } }, vadd2, "vadd2" },
{ { 4.0, -6.0 }, { { 1.0, -2.0 }, { 3.0, -4.0 } }, vadd2, "vadd2" },
{ { -2.0, -2.0 }, { { 1.0, 2.0 }, { 3.0, 4.0 } }, vsub, "vsub" },
{ { -2.0, 2.0 }, { { 1.0, -2.0 }, { 3.0, -4.0 } }, vsub, "vsub" },
{ { -2.0, -2.0 }, { { 1.0, 2.0 }, { 3.0, 4.0 } }, vsub2, "vsub2" },
{ { -2.0, 2.0 }, { { 1.0, -2.0 }, { 3.0, -4.0 } }, vsub2, "vsub2" },
{ { 6.0, 4.0 }, { { 2.0, 8.0 }, { 3.0, 0.5 } }, vmul, "vmul" },
{ { 6.0, 4.0 }, { { 2.0, 8.0 }, { 3.0, 0.5 } }, vmul2, "vmul2" },
{ { 2.0, 0.5 }, { { 6.0, 4.0 }, { 3.0, 8.0 } }, vdiv, "vdiv" },
{ { 2.0, 0.5 }, { { 6.0, 4.0 }, { 3.0, 8.0 } }, vdiv2, "vdiv2" },
{ { 3.0, 4.0 }, { { 1.0, 2.0 }, { 3.0, 4.0 } }, vmax, "vmax" },
{ { 1.0, 4.0 }, { { 1.0, -2.0 }, { -3.0, 4.0 } }, vmax, "vmax" },
{ { 1.0, 2.0 }, { { 1.0, 2.0 }, { 3.0, 4.0 } }, vmin, "vmin" },
{ { -3.0, -2.0 }, { { 1.0, -2.0 }, { -3.0, 4.0 } }, vmin, "vmin" },
};
static void
test_arg2 (void)
{
unsigned i;
#ifdef DEBUG
printf ("\nTwo argument tests:\n");
#endif
for (i = 0; i < sizeof (arg2_tests) / sizeof (arg2_tests[0]); i++)
{
union args_d u;
u.vect = arg2_tests[i].func (arg2_tests[i].input[0].vect,
arg2_tests[i].input[1].vect);
#ifdef DEBUG
printf ("test %-16s: expected { %4g, %4g }, got { %4g, %4g }, input { %4g, %4g }, { %4g, %4g }\n",
arg2_tests[i].name,
arg2_tests[i].result.scalar[0],
arg2_tests[i].result.scalar[1],
u.scalar[0],
u.scalar[1],
arg2_tests[i].input[0].scalar[0],
arg2_tests[i].input[0].scalar[1],
arg2_tests[i].input[1].scalar[0],
arg2_tests[i].input[1].scalar[1]);
#endif
do_test_d (&arg2_tests[i].result, &u, arg2_tests[i].name);
}
return;
}
/* Comparisons, returnning a boolean vector. */
static vector bool long
vcmpeq (vector double arg1, vector double arg2)
{
return vec_cmpeq (arg1, arg2);
}
static vector bool long
vcmplt (vector double arg1, vector double arg2)
{
return vec_cmplt (arg1, arg2);
}
static vector bool long
vcmple (vector double arg1, vector double arg2)
{
return vec_cmple (arg1, arg2);
}
static vector bool long
vcmpgt (vector double arg1, vector double arg2)
{
return vec_cmpgt (arg1, arg2);
}
static vector bool long
vcmpge (vector double arg1, vector double arg2)
{
return vec_cmpge (arg1, arg2);
}
#define ONE 0xffffffffffffffffUL
#define ZERO 0x0000000000000000UL
/* comparison tests. */
static struct
{
union largs result;
union args_d input[2];
vector bool long (*func) (vector double, vector double);
const char *name;
} argcmp_tests[] = {
{ { ONE, ZERO }, { { 1.0, 2.0 }, { 1.0, -2.0 } }, vcmpeq, "vcmpeq" },
{ { ZERO, ONE }, { { -1.0, 2.0 }, { 1.0, 2.0 } }, vcmpeq, "vcmpeq" },
{ { ONE, ONE }, { { 1.0, -2.0 }, { 1.0, -2.0 } }, vcmple, "vcmple" },
{ { ONE, ONE }, { { 1.0, -2.0 }, { 2.0, -1.0 } }, vcmple, "vcmple" },
{ { ZERO, ZERO }, { { 2.0, -1.0 }, { 1.0, -2.0 } }, vcmple, "vcmple" },
{ { ZERO, ZERO }, { { 1.0, -2.0 }, { 1.0, -2.0 } }, vcmplt, "vcmplt" },
{ { ONE, ONE }, { { 1.0, -2.0 }, { 2.0, -1.0 } }, vcmplt, "vcmplt" },
{ { ZERO, ZERO }, { { 2.0, -1.0 }, { 1.0, -2.0 } }, vcmplt, "vcmplt" },
{ { ZERO, ZERO }, { { 1.0, -2.0 }, { 1.0, -2.0 } }, vcmpgt, "vcmpgt" },
{ { ZERO, ZERO }, { { 1.0, -2.0 }, { 2.0, -1.0 } }, vcmpgt, "vcmpgt" },
{ { ONE, ONE }, { { 2.0, -1.0 }, { 1.0, -2.0 } }, vcmpgt, "vcmpgt" },
{ { ONE, ONE }, { { 1.0, -2.0 }, { 1.0, -2.0 } }, vcmpge, "vcmpge" },
{ { ZERO, ZERO }, { { 1.0, -2.0 }, { 2.0, -1.0 } }, vcmpge, "vcmpge" },
{ { ONE, ONE }, { { 2.0, -1.0 }, { 1.0, -2.0 } }, vcmpge, "vcmpge" },
};
static void
test_argcmp (void)
{
unsigned i;
#ifdef DEBUG
printf ("\nComparison tests:\n");
#endif
for (i = 0; i < sizeof (argcmp_tests) / sizeof (argcmp_tests[0]); i++)
{
union largs u;
u.vect = argcmp_tests[i].func (argcmp_tests[i].input[0].vect,
argcmp_tests[i].input[1].vect);
#ifdef DEBUG
printf ("test %-16s: expected { 0x%016lx, 0x%016lx }, got { 0x%016lx, 0x%016lx }, input { %4g, %4g }, { %4g, %4g }\n",
argcmp_tests[i].name,
argcmp_tests[i].result.scalar[0],
argcmp_tests[i].result.scalar[1],
u.scalar[0],
u.scalar[1],
argcmp_tests[i].input[0].scalar[0],
argcmp_tests[i].input[0].scalar[1],
argcmp_tests[i].input[1].scalar[0],
argcmp_tests[i].input[1].scalar[1]);
#endif
do_ltest (&argcmp_tests[i].result, &u, argcmp_tests[i].name);
}
return;
}
int
main (int argc, char *argv[])
{
test_arg1_f ();
test_arg1_d ();
test_arg2 ();
test_argcmp ();
#ifdef DEBUG
if (errors)
{
printf ("There were %d error(s)\n", errors);
return errors;
}
else
printf ("There were no errors\n");
#endif
return 0;
}