Thanks to visit codestin.com
Credit goes to gist.github.com

Skip to content

Instantly share code, notes, and snippets.

@ewmoore
Last active December 15, 2015 16:19
Show Gist options
  • Select an option

  • Save ewmoore/5288394 to your computer and use it in GitHub Desktop.

Select an option

Save ewmoore/5288394 to your computer and use it in GitHub Desktop.
Sanity Checks for c99 complex math functions.
#include <fenv.h>
#include <float.h>
#include <stdio.h>
#include <math.h>
#include <complex.h>
#ifdef FLOAT
#define TYPE float
#define SUFFIX f
#define EPS FLT_EPSILON
#else
#ifdef DOUBLE
#define TYPE double
#define SUFFIX
#define EPS DBL_EPSILON
#else
#ifdef LONGDOUBLE
#define TYPE long double
#define SUFFIX l
#define EPS LDBL_EPSILON
#else
#error "Define FLOAT or DOUBLE or LONGDOUBLE"
#endif
#endif
#endif
const double NZERO = -1.0 * 0.0;
const float NZEROf = -1.0 * 0.0;
#define STRINGIZE_INT(A) #A
#define STRINGIZE(A) STRINGIZE_INT(A)
#define CONCAT(A, B) A ## B
#define ADDSUFFIX_INT(A, B) CONCAT(A, B)
#define ADDSUFFIX(A) ADDSUFFIX_INT(A, SUFFIX)
#define TEST_PRINTF(func, x, e, r) printf("%d: " STRINGIZE(func) STRINGIZE(SUFFIX) "(%.16e + %.16ej): expected: %.16e + %.16ej: received: %.16e + %.16ej\n", __LINE__, ADDSUFFIX(creal)(x), ADDSUFFIX(cimag)(x), ADDSUFFIX(creal)(e), ADDSUFFIX(cimag)(e), ADDSUFFIX(creal)(r), ADDSUFFIX(cimag)(r))
#define TEST(func, xr, xi, er, ei) \
do { \
TYPE complex x = ADDSUFFIX(cpack)(xr, xi); \
TYPE complex e = ADDSUFFIX(cpack)(er, ei); \
TYPE complex r = ADDSUFFIX(func)(x); \
if (!ADDSUFFIX(cisclose)(r, e)) { \
ret = 0; \
TEST_PRINTF(func, x, e, r); \
} \
} \
while(0)
#define TEST_UNSPECIFIED2(func, xr, xi, er1, ei1, er2, ei2) \
do { \
TYPE complex x = ADDSUFFIX(cpack)(xr, xi); \
TYPE complex e1 = ADDSUFFIX(cpack)(er1, ei1); \
TYPE complex e2 = ADDSUFFIX(cpack)(er2, ei2); \
TYPE complex r = ADDSUFFIX(func)(x); \
if (!ADDSUFFIX(cisclose)(r, e1) && !ADDSUFFIX(cisclose)(r, e2)) { \
ret = 0; \
TEST_PRINTF(func, x, e1, r); \
printf("or"); \
TEST_PRINTF(func, x, e2, r); \
} \
} \
while(0)
#define TEST_UNSPECIFIED4(func, xr, xi, er1, ei1, er2, ei2, er3, ei3, er4, ei4)\
do { \
TYPE complex x = ADDSUFFIX(cpack)(xr, xi); \
TYPE complex e1 = ADDSUFFIX(cpack)(er1, ei1); \
TYPE complex e2 = ADDSUFFIX(cpack)(er2, ei2); \
TYPE complex e3 = ADDSUFFIX(cpack)(er3, ei3); \
TYPE complex e4 = ADDSUFFIX(cpack)(er4, ei4); \
TYPE complex r = func(x); \
if (!ADDSUFFIX(cisclose)(r, e1) && !ADDSUFFIX(cisclose)(r, e2) \
&& !ADDSUFFIX(cisclose)(r, e3) && !ADDSUFFIX(cisclose)(r, e4)) { \
ret = 0; \
TEST_PRINTF(func, x, e1, r); \
printf("or"); \
TEST_PRINTF(func, x, e2, r); \
printf("or"); \
TEST_PRINTF(func, x, e3, r); \
printf("or"); \
TEST_PRINTF(func, x, e4, r); \
} \
} \
while(0)
#define TEST_RAISES(func, xr, xi, er, ei, fpe) \
do { \
int except; \
TYPE complex r; \
TYPE complex x = ADDSUFFIX(cpack)(xr, xi); \
TYPE complex e = ADDSUFFIX(cpack)(er, ei); \
feclearexcept(FE_ALL_EXCEPT); \
r = ADDSUFFIX(func)(x); \
except = fetestexcept(fpe); \
if (!(except & fpe && ADDSUFFIX(cisclose)(r, e))) { \
ret = 0; \
TEST_PRINTF(func, x, e, r); \
} \
} \
while(0)
double complex cpack(double r, double i)
{
union {
double complex z;
double a[2];
} z1;
z1.a[0] = r;
z1.a[1] = i;
return z1.z;
}
float complex cpackf(float r, float i)
{
union {
float complex z;
float a[2];
} z1;
z1.a[0] = r;
z1.a[1] = i;
return z1.z;
}
long double complex cpackl(long double r, long double i)
{
union {
long double complex z;
long double a[2];
} z1;
z1.a[0] = r;
z1.a[1] = i;
return z1.z;
}
int isclose(double a, double b)
{
double atol = 0.0;
double rtol = 1e-12;
double signa = copysign(1.0, a);
double signb = copysign(1.0, b);
if (isfinite(a) && isfinite(b)) {
return (fabs(a - b) <= (atol + rtol*fabs(b))) && (signa == signb);
}
else if (isinf(a) && isinf(b)) {
return (signa == signb);
}
else {
return (isnan(a) && isnan(b));
}
}
int isclosef(float a, float b)
{
float atol = 0.0;
float rtol = 1e-5;
if (isfinite(a) && isfinite(b)) {
return (fabsf(a - b) <= (atol + rtol*fabsf(b))) && (copysignf(1.0, a) == copysignf(1.0, b));
}
else if (isinf(a) && isinf(b)) {
return (signbit(a) == signbit(b));
}
else {
return (isnan(a) && isnan(b));
}
}
int isclosel(long double a, long double b)
{
long double atol = 0.0;
long double rtol = 1e-12;
if (isfinite(a) && isfinite(b)) {
return (fabsl(a - b) <= (atol + rtol*fabsl(b))) && (copysignl(1.0, a) == copysignl(1.0, b));
}
else if (isinf(a) && isinf(b)) {
return (signbit(a) == signbit(b));
}
else {
return (isnan(a) && isnan(b));
}
}
int cisclose(double complex a, double complex b)
{
double ar = creal(a);
double ai = cimag(a);
double br = creal(b);
double bi = cimag(b);
return isclose(ar, br) && isclose(ai, bi);
}
int cisclosef(float complex a, float complex b)
{
float ar = crealf(a);
float ai = cimagf(a);
float br = crealf(b);
float bi = cimagf(b);
return isclosef(ar, br) && isclose(ai, bi);
}
int cisclosel(long double complex a, long double complex b)
{
long double ar = creall(a);
long double ai = cimagl(a);
long double br = creall(b);
long double bi = cimagl(b);
return isclosel(ar, br) && isclosel(ai, bi);
}
/*
int check_branch_cut(double complex (*func)(double complex), double complex x0, double complex dx, double re_sign, double im_sign, int sig_zero_ok)
{
double scale = DBL_EPSILON * 1e3;
double atol = 1e-4;
double complex y0 = func(x0);
double complex yp = func(x0 + dx*scale*cabs(x0)/cabs(dx));
double complex ym = func(x0 - dx*scale*cabs(x0)/cabs(dx));
if (fabs(creal(y0) - creal(yp)) >= atol)
return 0;
if (fabs(cimag(y0) - cimag(yp)) >= atol)
return 0;
if (fabs(creal(y0) - re_sign*creal(ym)) >= atol)
return 0;
if (fabs(cimag(y0) - im_sign*cimag(ym)) >= atol)
return 0;
if (sig_zero_ok) {
return 0;
}
return 1;
}
*/
typedef TYPE complex (*complexfunc)(TYPE complex);
typedef TYPE (*realfunc)(TYPE);
int check_near_crossover(complexfunc cfunc)
{
const TYPE x = 1e-3;
const int rpnt[] = {-1, -1, -1, 0, 0, 1, 1, 1};
const int ipnt[] = {-1, 0, 1, -1, 1, -1, 0, -1};
const int npnt = sizeof(rpnt) / sizeof(int);
const int dr[] = {1, 0, 1};
const int di[] = {0, 1, 1};
const int ndr = sizeof(dr) / sizeof(int);
int k, j;
int ret = 1;
TYPE drj, dij, diff;
TYPE complex zp, zm, czp, czm;
for (j = 0; j < ndr; j++) {
drj = 2 * x * dr[j] * EPS;
dij = 2 * x * di[j] * EPS;
for (k = 0; k < npnt; k++) {
zp = ADDSUFFIX(cpack)(x*rpnt[k] + drj, x*ipnt[k] + dij);
zm = ADDSUFFIX(cpack)(x*rpnt[k] - drj, x*ipnt[k] - dij);
czp = cfunc(zp);
czm = cfunc(zm);
diff = ADDSUFFIX(cabs)(czp - czm);
if ( diff > 2*EPS || czp == czm) {
printf("Loss of precision near crossover: j = %d, k = %d\n", j, k);
printf("zp = (%.16e + %.16ej) -> (%.16e + %.16ej)\n", ADDSUFFIX(creal)(zp), ADDSUFFIX(cimag)(zp), ADDSUFFIX(creal)(czp), ADDSUFFIX(cimag)(czp));
printf("zm = (%.16e + %.16ej) -> (%.16e + %.16ej)\n", ADDSUFFIX(creal)(zm), ADDSUFFIX(cimag)(zm), ADDSUFFIX(creal)(czm), ADDSUFFIX(cimag)(czm));
printf("diff = %.16e, exact match = %d\n", diff, czp == czm);
ret = 0;
}
}
}
return 1;
}
int foo(complexfunc cfunc, realfunc rfunc, int real, TYPE x)
{
TYPE num = rfunc(x);
TYPE den;
TYPE complex z;
if (real == 1) {
z = ADDSUFFIX(cpack)(x, 0);
z = cfunc(z);
den = ADDSUFFIX(creal)(z);
}
else {
z = ADDSUFFIX(cpack)(0, x);
z = cfunc(z);
den = ADDSUFFIX(cimag)(z);
}
return ADDSUFFIX(fabs)(num/den - 1);
}
int check_loss_of_precision(complexfunc cfunc, realfunc rfunc, int real)
{
const int n_series = 200;
const int n_basic = 10;
const TYPE rtol = 2*EPS;
const TYPE xsb = -20;
const TYPE xse = -3.001;
const TYPE dxs = (xse - xsb) / n_series;
const TYPE xbb = -2.999;
const TYPE xbe = 0;
const TYPE dxb = (xbe - xbb) / n_basic;
TYPE x, ratio;
int k;
int ret = 1;
for(k = 0; k < n_series; k++) {
x = ADDSUFFIX(pow)(10.0, xsb + k*dxs);
ratio = foo(cfunc, rfunc, real, x);
if (ratio > rtol) {
printf("Loss of precision:\n");
printf("x = %.16e\n", x);
printf("ratio = %.16e\n", ratio);
ret = 0;
}
}
for(k = 0; k < n_basic; k++) {
x = ADDSUFFIX(pow)(10.0, xbb + k*dxb);
ratio = foo(cfunc, rfunc, real, x);
if (ratio > rtol) {
printf("Loss of precision:\n");
printf("x = %.16e\n", x);
printf("ratio = %.16e\n", ratio);
ret = 0;
return 0;
}
}
return 1;
}
int test_cacos()
{
int ret = 1;
/* cacos(conj(z)) = conj(cacos(z)) */
TEST(cacos, 0, 0, M_PI_2, NZERO);
TEST(cacos, 0, NZERO, M_PI_2, 0);
TEST(cacos, NZERO, 0, M_PI_2, NZERO);
TEST(cacos, NZERO, NZERO, M_PI_2, 0);
TEST(cacos, 0, NAN, M_PI_2, NAN);
TEST(cacos, NZERO, NAN, M_PI_2, NAN);
TEST(cacos, 2.0, INFINITY, M_PI_2, -INFINITY);
TEST(cacos, 2.0, -INFINITY, M_PI_2, INFINITY);
/* can raise FE_INVALID or not */
TEST(cacos, 2.0, NAN, NAN, NAN);
TEST(cacos, -INFINITY, 2.0, M_PI, -INFINITY);
TEST(cacos, -INFINITY, -2.0, M_PI, INFINITY);
TEST(cacos, INFINITY, 2.0, 0, -INFINITY);
TEST(cacos, INFINITY, -2.0, 0, INFINITY);
TEST(cacos, -INFINITY, INFINITY, 0.75 * M_PI, -INFINITY);
TEST(cacos, -INFINITY, -INFINITY, 0.75 * M_PI, INFINITY);
TEST(cacos, INFINITY, INFINITY, 0.25 * M_PI, -INFINITY);
TEST(cacos, INFINITY, -INFINITY, 0.25 * M_PI, -INFINITY);
/* sign of imaginary part is unspecified. */
TEST_UNSPECIFIED2(cacos, INFINITY, NAN, NAN, INFINITY, NAN, -INFINITY);
TEST_UNSPECIFIED2(cacos, -INFINITY, NAN, NAN, INFINITY, NAN, -INFINITY);
/* can raise FE_INVALID or not */
TEST(cacos, NAN, 2.0, NAN, NAN);
TEST(cacos, NAN, -2.0, NAN, NAN);
TEST(cacos, NAN, INFINITY, NAN, -INFINITY);
TEST(cacos, NAN, -INFINITY, NAN, INFINITY);
TEST(cacos, NAN, NAN, NAN, NAN);
return ret;
}
int test_casin()
{
int ret = 1;
/* casin(conj(z)) = conj(casin(z)) and casin is odd */
TEST(casin, 0, 0, 0, 0);
TEST(casin, 0, NZERO, 0, NZERO);
TEST(casin, NZERO, 0, NZERO, 0);
TEST(casin, NZERO, NZERO, NZERO, NZERO);
TEST(casin, -INFINITY, 2.0, -M_PI_2, INFINITY);
TEST(casin, INFINITY, 2.0, M_PI_2, INFINITY);
TEST(casin, -INFINITY, -2.0, -M_PI_2, -INFINITY);
TEST(casin, INFINITY, -2.0, M_PI_2, -INFINITY);
/* can raise FE_INVALID or not */
TEST(casin, NAN, -2.0, NAN, NAN);
TEST(casin, NAN, 2.0, NAN, NAN);
TEST(casin, -2.0, INFINITY, NZERO, INFINITY);
TEST(casin, 2.0, INFINITY, 0, INFINITY);
TEST(casin, -2.0, -INFINITY, NZERO, -INFINITY);
TEST(casin, 2.0, -INFINITY, 0, -INFINITY);
TEST(casin, -INFINITY, INFINITY, -0.25*M_PI, INFINITY);
TEST(casin, INFINITY, INFINITY, 0.25*M_PI, INFINITY);
TEST(casin, -INFINITY, -INFINITY, -0.25*M_PI, -INFINITY);
TEST(casin, INFINITY, -INFINITY, 0.25*M_PI, -INFINITY);
TEST(casin, NAN, INFINITY, NAN, INFINITY);
TEST(casin, NAN, -INFINITY, NAN, -INFINITY);
TEST(casin, 0, NAN, 0, NAN);
TEST(casin, NZERO, NAN, NZERO, NAN);
/* can raise FE_INVALID or not */
TEST(casin, -2.0, NAN, NAN, NAN);
TEST(casin, 2.0, NAN, NAN, NAN);
/* sign of real part is unspecified */
TEST_UNSPECIFIED2(casin, -INFINITY, NAN, NAN, INFINITY, NAN, -INFINITY);
TEST_UNSPECIFIED2(casin, INFINITY, NAN, NAN, INFINITY, NAN, -INFINITY);
TEST(casin, NAN, NAN, NAN, NAN);
/*
* loss of precision
*/
if (!check_loss_of_precision(ADDSUFFIX(casin), ADDSUFFIX(asinh), 0)) {
printf("loss of precision: casin\n");
ret = 0;
}
TEST(casin, 1e-5, 1e-5, 9.999999999666666667e-6, 1.0000000000333333333e-5);
if (!check_near_crossover(ADDSUFFIX(casin))) {
printf("loss of precision near crossover: casin\n");
ret = 0;
}
return ret;
}
int test_catan()
{
int ret = 1;
/* catan(conj(z)) = conj(catan(z)) and catan is odd */
TEST(catan, 0, 0, 0, 0);
TEST(catan, 0, NZERO, 0, NZERO);
TEST(catan, NZERO, 0, NZERO, 0);
TEST(catan, NZERO, NZERO, NZERO, NZERO);
TEST(catan, NAN, 0, NAN, 0);
TEST(catan, NAN, NZERO, NAN, NZERO);
TEST_RAISES(catan, NZERO, 1, NZERO, INFINITY, FE_DIVBYZERO);
TEST_RAISES(catan, 0, 1, 0, INFINITY, FE_DIVBYZERO);
TEST_RAISES(catan, NZERO, -1, NZERO, -INFINITY, FE_DIVBYZERO);
TEST_RAISES(catan, 0, -1, 0, -INFINITY, FE_DIVBYZERO);
TEST(catan, -INFINITY, 2.0, -M_PI_2, 0);
TEST(catan, INFINITY, 2.0, M_PI_2, 0);
TEST(catan, -INFINITY, -2.0, -M_PI_2, NZERO);
TEST(catan, INFINITY, -2.0, M_PI_2, NZERO);
/* can raise FE_INVALID or not */
TEST(catan, NAN, -2.0, NAN, NAN);
TEST(catan, NAN, 2.0, NAN, NAN);
TEST(catan, -2.0, INFINITY, -M_PI_2, 0);
TEST(catan, 2.0, INFINITY, M_PI_2, 0);
TEST(catan, -2.0, -INFINITY, -M_PI_2, NZERO);
TEST(catan, 2.0, -INFINITY, M_PI_2, NZERO);
TEST(catan, -INFINITY, INFINITY, -M_PI_2, 0);
TEST(catan, INFINITY, INFINITY, M_PI_2, 0);
TEST(catan, -INFINITY, -INFINITY, -M_PI_2, NZERO);
TEST(catan, INFINITY, -INFINITY, M_PI_2, NZERO);
TEST(catan, NAN, INFINITY, NAN, 0);
TEST(catan, NAN, -INFINITY, NAN, NZERO);
/* can raise FE_INVALID or not */
TEST(catan, -2.0, NAN, NAN, NAN);
TEST(catan, 2.0, NAN, NAN, NAN);
/* sign of real part is unspecified */
TEST_UNSPECIFIED2(catan, -INFINITY, NAN, -M_PI_2, 0, -M_PI_2, NZERO);
TEST_UNSPECIFIED2(catan, INFINITY, NAN, M_PI_2, 0, M_PI_2, NZERO);
TEST(catan, NAN, NAN, NAN, NAN);
/*
* loss of precision
*/
if(!check_loss_of_precision(ADDSUFFIX(catan), ADDSUFFIX(atanh), 0)) {
printf("loss of precision: catan\n");
ret = 0;
}
TEST(catan, 1e-5, 1e-5, 1.000000000066666666e-5, 9.999999999333333333e-6);
if (!check_near_crossover(ADDSUFFIX(catan))) {
printf("loss of precision near crossover: catan\n");
ret = 0;
}
return ret;
}
int test_cacosh()
{
int ret = 1;
/* cacosh(conj(z)) = conj(cacosh(z)) */
TEST(cacosh, 0, 0, 0, M_PI_2);
TEST(cacosh, 0, NZERO, 0, -M_PI_2);
TEST(cacosh, NZERO, 0, 0, M_PI_2);
TEST(cacosh, NZERO, NZERO, 0, -M_PI_2);
TEST(cacosh, 2.0, INFINITY, INFINITY, M_PI_2);
TEST(cacosh, 2.0, -INFINITY, INFINITY, -M_PI_2);
/* can raise FE_INVALID or not */
TEST(cacosh, 2.0, NAN, NAN, NAN);
TEST(cacosh, -INFINITY, 2.0, INFINITY, M_PI);
TEST(cacosh, -INFINITY, -2.0, INFINITY, -M_PI);
TEST(cacosh, INFINITY, 2.0, INFINITY, 0);
TEST(cacosh, INFINITY, -2.0, INFINITY, NZERO);
TEST(cacosh, -INFINITY, INFINITY, INFINITY, 0.75*M_PI);
TEST(cacosh, -INFINITY, -INFINITY, INFINITY, -0.75*M_PI);
TEST(cacosh, INFINITY, INFINITY, INFINITY, 0.25*M_PI);
TEST(cacosh, INFINITY, -INFINITY, INFINITY, -0.25*M_PI);
TEST(cacosh, INFINITY, NAN, INFINITY, NAN);
TEST(cacosh, -INFINITY, NAN, INFINITY, NAN);
/* can raise FE_INVALID or not */
TEST(cacosh, NAN, 2.0, NAN, NAN);
TEST(cacosh, NAN, -2.0, NAN, NAN);
TEST(cacosh, NAN, INFINITY, INFINITY, NAN);
TEST(cacosh, NAN, -INFINITY, INFINITY, NAN);
TEST(cacosh, NAN, NAN, NAN, NAN);
return ret;
}
int test_casinh()
{
int ret = 1;
/* casinh(conj(z)) = conj(casinh(z)) and casinh is odd */
TEST(casinh, 0, 0, 0, 0);
TEST(casinh, 0, NZERO, 0, NZERO);
TEST(casinh, NZERO, 0, NZERO, 0);
TEST(casinh, NZERO, NZERO, NZERO, NZERO);
TEST(casinh, 2.0, INFINITY, INFINITY, M_PI_2);
TEST(casinh, 2.0, -INFINITY, INFINITY, -M_PI_2);
TEST(casinh, -2.0, INFINITY, -INFINITY, M_PI_2);
TEST(casinh, -2.0, -INFINITY, -INFINITY, -M_PI_2);
/* can raise FE_INVALID or not */
TEST(casinh, 2.0, NAN, NAN, NAN);
TEST(casinh, -2.0, NAN, NAN, NAN);
TEST(casinh, INFINITY, 2.0, INFINITY, 0);
TEST(casinh, INFINITY, -2.0, INFINITY, NZERO);
TEST(casinh, -INFINITY, 2.0, -INFINITY, 0);
TEST(casinh, -INFINITY, -2.0, -INFINITY, NZERO);
TEST(casinh, INFINITY, INFINITY, INFINITY, 0.25*M_PI);
TEST(casinh, INFINITY, -INFINITY, INFINITY, -0.25*M_PI);
TEST(casinh, -INFINITY, INFINITY, -INFINITY, 0.25*M_PI);
TEST(casinh, -INFINITY, -INFINITY, -INFINITY, -0.25*M_PI);
TEST(casinh, INFINITY, NAN, INFINITY, NAN);
TEST(casinh, -INFINITY, NAN, -INFINITY, NAN);
TEST(casinh, NAN, 0, NAN, 0);
TEST(casinh, NAN, NZERO, NAN, NZERO);
/* can raise FE_INVALID or not */
TEST(casinh, NAN, 2.0, NAN, NAN);
TEST(casinh, NAN, -2.0, NAN, NAN);
/* sign of real part is unspecified */
TEST_UNSPECIFIED2(casinh, NAN, INFINITY, INFINITY, NAN, -INFINITY, NAN);
TEST_UNSPECIFIED2(casinh, NAN, -INFINITY, INFINITY, NAN, -INFINITY, NAN);
TEST(casinh, NAN, NAN, NAN, NAN);
/*
* loss of precision
*/
if(check_loss_of_precision(ADDSUFFIX(casinh), ADDSUFFIX(asinh), 1)) {
printf("loss of precision: casinh\n");
ret = 0;
}
TEST(casinh, 1e-5, 1e-5, 1.0000000000333333333e-5, 9.999999999666666667e-6);
if (!check_near_crossover(ADDSUFFIX(casinh))) {
printf("loss of precision near crossover: casinh\n");
ret = 0;
}
return ret;
}
int test_catanh()
{
int ret = 1;
/* catanh(conj(z)) = conj(catanh(z)) and catanh is odd */
TEST(catanh, 0, 0, 0, 0);
TEST(catanh, 0, NZERO, 0, NZERO);
TEST(catanh, NZERO, 0, NZERO, 0);
TEST(catanh, NZERO, NZERO, NZERO, NZERO);
TEST(catanh, 0, NAN, 0, NAN);
TEST(catanh, NZERO, NAN, NZERO, NAN);
TEST_RAISES(catanh, 1, 0, INFINITY, 0, FE_DIVBYZERO);
TEST_RAISES(catanh, 1, NZERO, INFINITY, NZERO, FE_DIVBYZERO);
TEST_RAISES(catanh, -1, 0, -INFINITY, 0, FE_DIVBYZERO);
TEST_RAISES(catanh, -1, NZERO, -INFINITY, NZERO, FE_DIVBYZERO);
TEST(catanh, 2.0, INFINITY, 0, M_PI_2);
TEST(catanh, 2.0, -INFINITY, 0, -M_PI_2);
TEST(catanh, -2.0, INFINITY, NZERO, M_PI_2);
TEST(catanh, -2.0, -INFINITY, NZERO, -M_PI_2);
/* can raise FE_INVALID or not */
TEST(catanh, 2.0, NAN, NAN, NAN);
TEST(catanh, -2.0, NAN, NAN, NAN);
TEST(catanh, INFINITY, 2.0, 0, M_PI_2);
TEST(catanh, INFINITY, -2.0, 0, -M_PI_2);
TEST(catanh, -INFINITY, 2.0, NZERO, M_PI_2);
TEST(catanh, -INFINITY, -2.0, NZERO, -M_PI_2);
TEST(catanh, INFINITY, INFINITY, 0, M_PI_2);
TEST(catanh, INFINITY, -INFINITY, 0, -M_PI_2);
TEST(catanh, -INFINITY, INFINITY, NZERO, M_PI_2);
TEST(catanh, -INFINITY, -INFINITY, NZERO, -M_PI_2);
TEST(catanh, INFINITY, NAN, 0, NAN);
TEST(catanh, -INFINITY, NAN, NZERO, NAN);
/* can raise FE_INVALID or not */
TEST(catanh, NAN, 2.0, NAN, NAN);
TEST(catanh, NAN, -2.0, NAN, NAN);
/* sign of real part is unspecified */
TEST_UNSPECIFIED2(catanh, NAN, INFINITY, 0, M_PI_2, NZERO, M_PI_2);
TEST_UNSPECIFIED2(catanh, NAN, -INFINITY, 0, -M_PI_2, NZERO, -M_PI_2);
/* TEST(catanh, NAN, INFINITY, 0, M_PI_2); */
TEST(catanh, NAN, NAN, NAN, NAN);
/*
* loss of precision
*/
if(check_loss_of_precision(ADDSUFFIX(catanh), ADDSUFFIX(atanh), 1)) {
printf("loss of precision: catanh\n");
ret = 0;
}
TEST(catanh, 1e-5, 1e-5, 9.999999999333333333e-6, 1.000000000066666666e-5);
if (!check_near_crossover(ADDSUFFIX(catanh))) {
printf("loss of precision near crossover: casinh\n");
ret = 0;
}
return ret;
}
int test_ccos()
{
int ret = 1;
/* ccos(conj(z)) = conj(ccos(z)) and ccos is even */
TEST(ccos, NZERO, 0, 1, 0);
TEST(ccos, 0, 0, 1, NZERO);
TEST(ccos, NZERO, NZERO, 1, NZERO);
TEST(ccos, 0, NZERO, 1, 0);
/* sign of imaginary part is unspecified */
TEST_RAISES(ccos, -INFINITY, 0, NAN, 0, FE_INVALID);
/* sign of imaginary part is unspecified */
TEST_UNSPECIFIED2(ccos, NAN, 0, NAN, 0, NAN, NZERO);
TEST_UNSPECIFIED2(ccos, NAN, NZERO, NAN, 0, NAN, NZERO);
TEST_RAISES(ccos, -INFINITY, 2.0, NAN, NAN, FE_INVALID);
TEST_RAISES(ccos, INFINITY, 2.0, NAN, NAN, FE_INVALID);
TEST_RAISES(ccos, -INFINITY, -2.0, NAN, NAN, FE_INVALID);
TEST_RAISES(ccos, INFINITY, -2.0, NAN, NAN, FE_INVALID);
/* can raise FE_INVALID or not */
TEST(ccos, NAN, 2.0, NAN, NAN);
TEST(ccos, NAN, -2.0, NAN, NAN);
TEST(ccos, NZERO, INFINITY, INFINITY, 0);
TEST(ccos, 0, INFINITY, INFINITY, NZERO);
TEST(ccos, NZERO, -INFINITY, INFINITY, NZERO);
TEST(ccos, 0, -INFINITY, INFINITY, 0);
TEST(ccos, -1.0, INFINITY, INFINITY, INFINITY);
TEST(ccos, 1.0, INFINITY, INFINITY, -INFINITY);
TEST(ccos, -1.0, -INFINITY, INFINITY, -INFINITY);
TEST(ccos, 1.0, -INFINITY, INFINITY, INFINITY);
TEST(ccos, -2.0, INFINITY, -INFINITY, INFINITY);
TEST(ccos, 2.0, INFINITY, -INFINITY, -INFINITY);
TEST(ccos, -2.0, -INFINITY, -INFINITY, -INFINITY);
TEST(ccos, 2.0, -INFINITY, -INFINITY, INFINITY);
TEST(ccos, -4.0, INFINITY, -INFINITY, -INFINITY);
TEST(ccos, 4.0, INFINITY, -INFINITY, INFINITY);
TEST(ccos, -4.0, -INFINITY, -INFINITY, INFINITY);
TEST(ccos, 4.0, -INFINITY, -INFINITY, -INFINITY);
TEST(ccos, -5.0, INFINITY, INFINITY, -INFINITY);
TEST(ccos, 5.0, INFINITY, INFINITY, INFINITY);
TEST(ccos, -5.0, -INFINITY, INFINITY, INFINITY);
TEST(ccos, 5.0, -INFINITY, INFINITY, -INFINITY);
/* sign of real part is unspecified */
TEST_RAISES(ccos, -INFINITY, INFINITY, INFINITY, NAN, FE_INVALID);
TEST(ccos, NAN, INFINITY, INFINITY, NAN);
TEST(ccos, NAN, -INFINITY, INFINITY, NAN);
/* sign of imaginary part is unspecified */
TEST_UNSPECIFIED2(ccos, 0, NAN, NAN, 0, NAN, NZERO);
TEST_UNSPECIFIED2(ccos, NZERO, NAN, NAN, 0, NAN, NZERO);
/* can raise FE_INVALID or not */
TEST(ccos, -2.0, NAN, NAN, NAN);
TEST(ccos, 2.0, NAN, NAN, NAN);
TEST(ccos, NAN, NAN, NAN, NAN);
return ret;
}
int test_csin()
{
int ret = 1;
/* csin(conj(z)) = conj(csin(z)) and csin is odd */
TEST(csin, 0, 0, 0, 0);
TEST(csin, 0, NZERO, 0, NZERO);
TEST(csin, NZERO, 0, NZERO, 0);
TEST(csin, NZERO, NZERO, NZERO, NZERO);
/* sign of imaginary part is unspecified */
TEST_RAISES(csin, -INFINITY, 0, NAN, 0, FE_INVALID);
/* sign of imaginary part is unspecified */
TEST_UNSPECIFIED2(csin, NAN, 0, NAN, 0, NAN, NZERO);
TEST_UNSPECIFIED2(csin, NAN, NZERO, NAN, 0, NAN, NZERO);
TEST_RAISES(csin, -INFINITY, 2.0, NAN, NAN, FE_INVALID);
TEST_RAISES(csin, INFINITY, 2.0, NAN, NAN, FE_INVALID);
TEST_RAISES(csin, -INFINITY, -2.0, NAN, NAN, FE_INVALID);
TEST_RAISES(csin, INFINITY, -2.0, NAN, NAN, FE_INVALID);
/* can raise FE_INVALID or not */
TEST(csin, NAN, 2.0, NAN, NAN);
TEST(csin, NAN, -2.0, NAN, NAN);
TEST(csin, NZERO, INFINITY, NZERO, INFINITY);
TEST(csin, 0, INFINITY, 0, INFINITY);
TEST(csin, NZERO, -INFINITY, NZERO, -INFINITY);
TEST(csin, 0, -INFINITY, 0, -INFINITY);
TEST(csin, -1.0, INFINITY, -INFINITY, INFINITY);
TEST(csin, 1.0, INFINITY, INFINITY, INFINITY);
TEST(csin, -1.0, -INFINITY, -INFINITY, -INFINITY);
TEST(csin, 1.0, -INFINITY, INFINITY, -INFINITY);
TEST(csin, -2.0, INFINITY, -INFINITY, -INFINITY);
TEST(csin, 2.0, INFINITY, INFINITY, -INFINITY);
TEST(csin, -2.0, -INFINITY, -INFINITY, INFINITY);
TEST(csin, 2.0, -INFINITY, INFINITY, INFINITY);
TEST(csin, -4.0, INFINITY, INFINITY, -INFINITY);
TEST(csin, 4.0, INFINITY, -INFINITY, -INFINITY);
TEST(csin, -4.0, -INFINITY, INFINITY, INFINITY);
TEST(csin, 4.0, -INFINITY, -INFINITY, INFINITY);
TEST(csin, -5.0, INFINITY, INFINITY, INFINITY);
TEST(csin, 5.0, INFINITY, -INFINITY, INFINITY);
TEST(csin, -5.0, -INFINITY, INFINITY, -INFINITY);
TEST(csin, 5.0, -INFINITY, -INFINITY, -INFINITY);
/* sign of imaginary part is unspecified */
TEST_RAISES(csin, -INFINITY, INFINITY, NAN, INFINITY, FE_INVALID);
/* sign of imaginary part is unspecified */
TEST_UNSPECIFIED2(csin, NAN, INFINITY, NAN, INFINITY, NAN, -INFINITY);
TEST_UNSPECIFIED2(csin, NAN, -INFINITY, NAN, INFINITY, NAN, -INFINITY);
TEST(csin, 0, NAN, 0, NAN);
TEST(csin, NZERO, NAN, NZERO, NAN);
/* can raise FE_INVALID or not */
TEST(csin, -2.0, NAN, NAN, NAN);
TEST(csin, 2.0, NAN, NAN, NAN);
TEST(csin, NAN, NAN, NAN, NAN);
return ret;
}
int test_ctan()
{
int ret = 1;
/* ctan(conj(z)) = conj(ctan(z)) and ctan is odd */
TEST(ctan, 0, 0, 0, 0);
TEST(ctan, 0, NZERO, 0, NZERO);
TEST(ctan, NZERO, 0, NZERO, 0);
TEST(ctan, NZERO, NZERO, NZERO, NZERO);
TEST_RAISES(ctan, -INFINITY, 2.0, NAN, NAN, FE_INVALID);
TEST_RAISES(ctan, -INFINITY, -2.0, NAN, NAN, FE_INVALID);
/* can raise FE_INVALID or not */
TEST(ctan, NAN, 2.0, NAN, NAN);
TEST(ctan, NAN, -2.0, NAN, NAN);
TEST(ctan, -1.0, INFINITY, NZERO, 1.0);
TEST(ctan, 1.0, INFINITY, 0, 1.0);
TEST(ctan, -1.0, -INFINITY, NZERO, -1.0);
TEST(ctan, 1.0, -INFINITY, 0, -1.0);
TEST(ctan, -2.0, INFINITY, 0, 1);
TEST(ctan, 2.0, INFINITY, NZERO, 1);
TEST(ctan, -2.0, -INFINITY, 0, -1);
TEST(ctan, 2.0, -INFINITY, NZERO, -1);
/* sign of real part is unspecified */
TEST_UNSPECIFIED2(ctan, INFINITY, INFINITY, 0, 1, NZERO, 1);
TEST_UNSPECIFIED2(ctan, -INFINITY, INFINITY, 0, 1, NZERO, 1);
TEST_UNSPECIFIED2(ctan, INFINITY, -INFINITY, 0, -1, NZERO, -1);
TEST_UNSPECIFIED2(ctan, -INFINITY, -INFINITY, 0, -1, NZERO, -1);
/* sign of real part is unspecified */
TEST_UNSPECIFIED2(ctan, NAN, INFINITY, 0, 1, NZERO, 1);
TEST_UNSPECIFIED2(ctan, NAN, -INFINITY, 0, -1, NZERO, -1);
TEST(ctan, 0, NAN, 0, NAN);
TEST(ctan, NZERO, NAN, NZERO, NAN);
/* can raise FE_INVALID or not */
TEST(ctan, 2.0, NAN, NAN, NAN);
TEST(ctan, -2.0, NAN, NAN, NAN);
TEST(ctan, NAN, NAN, NAN, NAN);
return ret;
}
int test_ccosh()
{
int ret = 1;
/* ccosh(conj(z)) = conj(ccosh(z)) and ccosh is even */
TEST(ccosh, 0, 0, 1, 0);
TEST(ccosh, 0, NZERO, 1, NZERO);
TEST(ccosh, NZERO, 0, 1, NZERO);
TEST(ccosh, NZERO, NZERO, 1, 0);
/* sign of imaginary part is unspecified */
TEST_RAISES(ccosh, 0, INFINITY, NAN, 0, FE_INVALID);
/* sign of imaginary part is unspecified */
TEST_UNSPECIFIED2(ccosh, 0, NAN, NAN, 0, NAN, NZERO);
TEST_UNSPECIFIED2(ccosh, NZERO, NAN, NAN, 0, NAN, NZERO);
TEST_RAISES(ccosh, 2.0, INFINITY, NAN, NAN, FE_INVALID);
TEST_RAISES(ccosh, 2.0, -INFINITY, NAN, NAN, FE_INVALID);
TEST_RAISES(ccosh, -2.0, INFINITY, NAN, NAN, FE_INVALID);
TEST_RAISES(ccosh, -2.0, -INFINITY, NAN, NAN, FE_INVALID);
/* can raise FE_INVALID or not */
TEST(ccosh, 2.0, NAN, NAN, NAN);
TEST(ccosh, -2.0, NAN, NAN, NAN);
TEST(ccosh, INFINITY, 0, INFINITY, 0);
TEST(ccosh, INFINITY, NZERO, INFINITY, NZERO);
TEST(ccosh, -INFINITY, 0, INFINITY, NZERO);
TEST(ccosh, -INFINITY, NZERO, INFINITY, 0);
TEST(ccosh, INFINITY, 1.0, INFINITY, INFINITY);
TEST(ccosh, INFINITY, -1.0, INFINITY, -INFINITY);
TEST(ccosh, -INFINITY, 1.0, INFINITY, -INFINITY);
TEST(ccosh, -INFINITY, -1.0, INFINITY, INFINITY);
TEST(ccosh, INFINITY, 2.0, -INFINITY, INFINITY);
TEST(ccosh, INFINITY, -2.0, -INFINITY, -INFINITY);
TEST(ccosh, -INFINITY, 2.0, -INFINITY, -INFINITY);
TEST(ccosh, -INFINITY, -2.0, -INFINITY, INFINITY);
TEST(ccosh, INFINITY, 4.0, -INFINITY, -INFINITY);
TEST(ccosh, INFINITY, -4.0, -INFINITY, INFINITY);
TEST(ccosh, -INFINITY, 4.0, -INFINITY, INFINITY);
TEST(ccosh, -INFINITY, -4.0, -INFINITY, -INFINITY);
TEST(ccosh, INFINITY, 5.0, INFINITY, -INFINITY);
TEST(ccosh, INFINITY, -5.0, INFINITY, INFINITY);
TEST(ccosh, -INFINITY, 5.0, INFINITY, INFINITY);
TEST(ccosh, -INFINITY, -5.0, INFINITY, -INFINITY);
/* sign of real part is unspecified */
TEST_RAISES(ccosh, INFINITY, INFINITY, INFINITY, NAN, FE_INVALID);
TEST(ccosh, INFINITY, NAN, INFINITY, NAN);
TEST(ccosh, -INFINITY, NAN, INFINITY, NAN);
/* sign of imaginary part is unspecified */
TEST_UNSPECIFIED2(ccosh, NAN, 0, NAN, 0, NAN, NZERO);
TEST_UNSPECIFIED2(ccosh, NAN, NZERO, NAN, 0, NAN, NZERO);
/* can raise FE_INVALID or not */
TEST(ccosh, NAN, 2.0, NAN, NAN);
TEST(ccosh, NAN, -2.0, NAN, NAN);
TEST(ccosh, NAN, NAN, NAN, NAN);
return ret;
}
int test_csinh()
{
int ret = 1;
/* csinh(conj(z)) = conj(csinh(z)) and csinh is odd */
TEST(csinh, 0, 0, 0, 0);
TEST(csinh, 0, NZERO, 0, NZERO);
TEST(csinh, NZERO, 0, NZERO, 0);
TEST(csinh, NZERO, NZERO, NZERO, NZERO);
/* sign of real part is unspecified */
TEST_RAISES(csinh, 0, INFINITY, 0, NAN, FE_INVALID);
/* sign of real part is unspecified */
TEST_UNSPECIFIED2(csinh, 0, NAN, 0, NAN, NZERO, NAN);
TEST_UNSPECIFIED2(csinh, NZERO, NAN, 0, NAN, NZERO, NAN);
TEST_RAISES(csinh, 2.0, INFINITY, NAN, NAN, FE_INVALID);
TEST_RAISES(csinh, 2.0, -INFINITY, NAN, NAN, FE_INVALID);
TEST_RAISES(csinh, -2.0, INFINITY, NAN, NAN, FE_INVALID);
TEST_RAISES(csinh, -2.0, -INFINITY, NAN, NAN, FE_INVALID);
/* can raise FE_INVALID or not */
TEST(csinh, 2.0, NAN, NAN, NAN);
TEST(csinh, -2.0, NAN, NAN, NAN);
TEST(csinh, INFINITY, 0, INFINITY, 0);
TEST(csinh, INFINITY, NZERO, INFINITY, NZERO);
TEST(csinh, -INFINITY, 0, -INFINITY, 0);
TEST(csinh, -INFINITY, NZERO, -INFINITY, NZERO);
TEST(csinh, INFINITY, 1.0, INFINITY, INFINITY);
TEST(csinh, INFINITY, -1.0, INFINITY, -INFINITY);
TEST(csinh, -INFINITY, 1.0, -INFINITY, INFINITY);
TEST(csinh, -INFINITY, -1.0, -INFINITY, -INFINITY);
TEST(csinh, INFINITY, 2.0, -INFINITY, INFINITY);
TEST(csinh, INFINITY, -2.0, -INFINITY, -INFINITY);
TEST(csinh, -INFINITY, 2.0, INFINITY, INFINITY);
TEST(csinh, -INFINITY, -2.0, INFINITY, -INFINITY);
TEST(csinh, INFINITY, 4.0, -INFINITY, -INFINITY);
TEST(csinh, INFINITY, -4.0, -INFINITY, INFINITY);
TEST(csinh, -INFINITY, 4.0, INFINITY, -INFINITY);
TEST(csinh, -INFINITY, -4.0, INFINITY, INFINITY);
TEST(csinh, INFINITY, 5.0, INFINITY, -INFINITY);
TEST(csinh, INFINITY, -5.0, INFINITY, INFINITY);
TEST(csinh, -INFINITY, 5.0, -INFINITY, -INFINITY);
TEST(csinh, -INFINITY, -5.0, -INFINITY, INFINITY);
/* sign of real part is unspecified */
TEST_RAISES(csinh, INFINITY, INFINITY, INFINITY, NAN, FE_INVALID);
/* sign of real part is unspecified */
TEST_UNSPECIFIED2(csinh, INFINITY, NAN, INFINITY, NAN, -INFINITY, NAN);
TEST_UNSPECIFIED2(csinh, -INFINITY, NAN, INFINITY, NAN, -INFINITY, NAN);
TEST(csinh, NAN, 0, NAN, 0);
TEST(csinh, NAN, NZERO, NAN, NZERO);
/* can raise FE_INVALID or not */
TEST(csinh, NAN, 2.0, NAN, NAN);
TEST(csinh, NAN, -2.0, NAN, NAN);
TEST(csinh, NAN, NAN, NAN, NAN);
return ret;
}
int test_ctanh()
{
int ret = 1;
/* ctanh(conj(z)) = conj(ctanh(z)) and ctanh is odd */
TEST(ctanh, 0, 0, 0, 0);
TEST(ctanh, 0, NZERO, 0, NZERO);
TEST(ctanh, NZERO, 0, NZERO, 0);
TEST(ctanh, NZERO, NZERO, NZERO, NZERO);
TEST_RAISES(ctanh, 2.0, INFINITY, NAN, NAN, FE_INVALID);
TEST_RAISES(ctanh, -2.0, INFINITY, NAN, NAN, FE_INVALID);
/* can raise FE_INVALID or not */
TEST(ctanh, 2.0, NAN, NAN, NAN);
TEST(ctanh, -2.0, NAN, NAN, NAN);
TEST(ctanh, INFINITY, 1.0, 1.0, 0);
TEST(ctanh, INFINITY, -1.0, 1.0, NZERO);
TEST(ctanh, -INFINITY, 1.0, -1.0, 0);
TEST(ctanh, -INFINITY, -1.0, -1.0, NZERO);
TEST(ctanh, INFINITY, 2.0, 1.0, NZERO);
TEST(ctanh, INFINITY, -2.0, 1.0, 0);
TEST(ctanh, -INFINITY, 2.0, -1.0, NZERO);
TEST(ctanh, -INFINITY, -2.0, -1.0, 0);
/* sign of imaginary part is unspecified */
TEST_UNSPECIFIED2(ctanh, INFINITY, INFINITY, 1, 0, 1, NZERO);
TEST_UNSPECIFIED2(ctanh, INFINITY, -INFINITY, 1, 0, 1, NZERO);
TEST_UNSPECIFIED2(ctanh, -INFINITY, INFINITY, -1, 0, -1, NZERO);
TEST_UNSPECIFIED2(ctanh, -INFINITY, -INFINITY, -1, 0, -1, NZERO);
/* sign of imaginary part is unspecified */
TEST_UNSPECIFIED2(ctanh, INFINITY, NAN, 1, 0, 1, NZERO);
TEST_UNSPECIFIED2(ctanh, -INFINITY, NAN, -1, 0, -1, NZERO);
TEST(ctanh, NAN, 0, NAN, 0);
TEST(ctanh, NAN, NZERO, NAN, NZERO);
/* can raise FE_INVALID or not */
TEST(ctanh, NAN, 2.0, NAN, NAN);
TEST(ctanh, NAN, -2.0, NAN, NAN);
TEST(ctanh, NAN, NAN, NAN, NAN);
return ret;
}
int test_cexp()
{
int ret = 1;
/* cexp(conj(z)) = conj(cexp(z)) */
TEST(cexp, 0, 0, 1, 0);
TEST(cexp, 0, NZERO, 1, NZERO);
TEST(cexp, NZERO, 0, 1, 0);
TEST(cexp, NZERO, NZERO, 1, NZERO);
TEST_RAISES(cexp, 2.0, INFINITY, NAN, NAN, FE_INVALID);
TEST_RAISES(cexp, 2.0, -INFINITY, NAN, NAN, FE_INVALID);
/* can raise FE_INVALID or not */
TEST(cexp, 42.0, NAN, NAN, NAN);
TEST(cexp, INFINITY, 0, INFINITY, 0);
TEST(cexp, INFINITY, NZERO, INFINITY, NZERO);
TEST(cexp, -INFINITY, 1.0, 0, 0);
TEST(cexp, -INFINITY, -1.0, 0, NZERO);
TEST(cexp, -INFINITY, 2.0, NZERO, 0);
TEST(cexp, -INFINITY, -2.0, NZERO, NZERO);
TEST(cexp, -INFINITY, 4.0, NZERO, NZERO);
TEST(cexp, -INFINITY, -4.0, NZERO, 0);
TEST(cexp, -INFINITY, 5.0, 0, NZERO);
TEST(cexp, -INFINITY, -5.0, 0, 0);
TEST(cexp, INFINITY, 1.0, INFINITY, INFINITY);
TEST(cexp, INFINITY, -1.0, INFINITY, -INFINITY);
TEST(cexp, INFINITY, 2.0, -INFINITY, INFINITY);
TEST(cexp, INFINITY, -2.0, -INFINITY, -INFINITY);
TEST(cexp, INFINITY, 4.0, -INFINITY, -INFINITY);
TEST(cexp, INFINITY, -4.0, -INFINITY, INFINITY);
TEST(cexp, INFINITY, 5.0, INFINITY, -INFINITY);
TEST(cexp, INFINITY, -5.0, INFINITY, INFINITY);
/* signs of both parts are unspecified */
TEST_UNSPECIFIED4(cexp, -INFINITY, INFINITY, 0, 0, NZERO, 0, 0, NZERO, NZERO, NZERO);
TEST_UNSPECIFIED4(cexp, -INFINITY, -INFINITY, 0, 0, NZERO, 0, 0, NZERO, NZERO, NZERO);
/* sign of real part is unspecifed */
TEST_RAISES(cexp, INFINITY, INFINITY, INFINITY, NAN, FE_INVALID);
/* signs of both parts are unspecified */
TEST_UNSPECIFIED4(cexp, -INFINITY, NAN, 0, 0, NZERO, 0, 0, NZERO, NZERO, NZERO);
/* sign of real part is unspecified */
TEST_UNSPECIFIED2(cexp, INFINITY, NAN, INFINITY, NAN, -INFINITY, NAN);
TEST(cexp, NAN, 0, NAN, 0);
TEST(cexp, NAN, NZERO, NAN, NZERO);
/* can raise FE_INVALID or not */
TEST(cexp, NAN, 2.0, NAN, NAN);
TEST(cexp, NAN, -2.0, NAN, NAN);
TEST(cexp, NAN, NAN, NAN, NAN);
return ret;
}
int test_clog()
{
int ret = 1;
/* clog(conj(z)) = conj(clog(z)) */
TEST_RAISES(clog, NZERO, 0, -INFINITY, M_PI, FE_DIVBYZERO);
TEST_RAISES(clog, NZERO, NZERO, -INFINITY, -M_PI, FE_DIVBYZERO);
TEST_RAISES(clog, 0, 0, -INFINITY, 0, FE_DIVBYZERO);
TEST_RAISES(clog, 0, NZERO, -INFINITY, NZERO, FE_DIVBYZERO);
TEST(clog, 2.0, INFINITY, INFINITY, M_PI_2);
TEST(clog, 2.0, -INFINITY, INFINITY, -M_PI_2);
/* can raise FE_INVALID or not */
TEST(clog, 2.0, NAN, NAN, NAN);
TEST(clog, -INFINITY, 2.0, INFINITY, M_PI);
TEST(clog, -INFINITY, -2.0, INFINITY, -M_PI);
TEST(clog, INFINITY, 2.0, INFINITY, 0);
TEST(clog, INFINITY, -2.0, INFINITY, NZERO);
TEST(clog, -INFINITY, INFINITY, INFINITY, 0.75 * M_PI);
TEST(clog, -INFINITY, -INFINITY, INFINITY, -0.75 * M_PI);
TEST(clog, INFINITY, INFINITY, INFINITY, 0.25 * M_PI);
TEST(clog, INFINITY, -INFINITY, INFINITY, -0.25 * M_PI);
TEST(clog, INFINITY, NAN, INFINITY, NAN);
TEST(clog, -INFINITY, NAN, INFINITY, NAN);
/* can raise FE_INVALID or not */
TEST(clog, NAN, 2.0, NAN, NAN);
TEST(clog, NAN, -2.0, NAN, NAN);
TEST(clog, NAN, INFINITY, INFINITY, NAN);
TEST(clog, NAN, -INFINITY, INFINITY, NAN);
TEST(clog, NAN, NAN, NAN, NAN);
return ret;
}
int test_cpow()
{
int ret = 1;
/* there are _no_ annex G values for cpow. */
return ret;
}
int test_csqrt()
{
int ret = 1;
/* csqrt(conj(z)) = conj(csqrt(z)) */
TEST(csqrt, 0, 0, 0, 0);
TEST(csqrt, 0, NZERO, 0, NZERO);
TEST(csqrt, NZERO, 0, 0, 0);
TEST(csqrt, NZERO, NZERO, 0, NZERO);
TEST(csqrt, 2.0, INFINITY, INFINITY, INFINITY);
TEST(csqrt, 2.0, -INFINITY, INFINITY, -INFINITY);
TEST(csqrt, NAN, INFINITY, INFINITY, INFINITY);
TEST(csqrt, NAN, -INFINITY, INFINITY, -INFINITY);
TEST(csqrt, INFINITY, INFINITY, INFINITY, INFINITY);
TEST(csqrt, INFINITY, -INFINITY, INFINITY, -INFINITY);
TEST(csqrt, -INFINITY, INFINITY, INFINITY, INFINITY);
TEST(csqrt, -INFINITY, -INFINITY, INFINITY, -INFINITY);
/* can raise FE_INVALID or not */
TEST(csqrt, 2.0, NAN, NAN, NAN);
TEST(csqrt, -INFINITY, 2.0, 0, INFINITY);
TEST(csqrt, -INFINITY, -2.0, 0, -INFINITY);
TEST(csqrt, INFINITY, 2.0, INFINITY, 0);
TEST(csqrt, INFINITY, -2.0, INFINITY, NZERO);
/* sign of imaginary part is unspecified */
TEST_UNSPECIFIED2(csqrt, -INFINITY, NAN, NAN, INFINITY, NAN, -INFINITY);
TEST(csqrt, INFINITY, NAN, INFINITY, NAN);
/* can raise FE_INVALID or not */
TEST(csqrt, NAN, 2.0, NAN, NAN);
TEST(csqrt, NAN, -2.0, NAN, NAN);
TEST(csqrt, NAN, NAN, NAN, NAN);
return ret;
}
int main(int argc, char** argv)
{
printf("cacos: %d\n\n", test_cacos());
printf("casin: %d\n\n", test_casin());
printf("catan: %d\n\n", test_catan());
printf("cacosh: %d\n\n", test_cacosh());
printf("casinh: %d\n\n", test_casinh());
printf("catanh: %d\n\n", test_catanh());
printf("ccos: %d\n\n", test_ccos());
printf("csin: %d\n\n", test_csin());
printf("ctan: %d\n\n", test_ctan());
printf("ccosh: %d\n\n", test_ccosh());
printf("csinh: %d\n\n", test_csinh());
printf("ctanh: %d\n\n", test_ctanh());
printf("cexp: %d\n\n", test_cexp());
printf("clog: %d\n\n", test_clog());
printf("cpow, %d\n\n", test_cpow());
printf("csqrt: %d\n\n", test_csqrt());
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment