Last active
December 15, 2015 16:19
-
-
Save ewmoore/5288394 to your computer and use it in GitHub Desktop.
Sanity Checks for c99 complex math functions.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #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