Last active
December 15, 2015 16:19
-
-
Save ewmoore/5288394 to your computer and use it in GitHub Desktop.
Revisions
-
ewmoore revised this gist
Oct 1, 2013 . 1 changed file with 677 additions and 601 deletions.There are no files selected for viewing
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 charactersOriginal file line number Diff line number Diff line change @@ -8,22 +8,37 @@ #define TYPE float #define SUFFIX f #define EPS FLT_EPSILON #define CLOSE_ATOL 3 #define CLOSE_RTOL 1e-5 #define FMT "%.8e" #define NPY_PI_2 1.570796326794896619231321691639751442f #define NPY_PI 3.141592653589793238462643383279502884f #define NPY_LOG2E 1.442695040888963407359924681001892137f #define NPY_SQRT2 1.414213562373095048801688724209698079f #else #ifdef DOUBLE #define TYPE double #define SUFFIX #define EPS DBL_EPSILON #define CLOSE_ATOL 0 #define CLOSE_RTOL 1e-12 #define FMT "%.16e" #define NPY_PI_2 1.570796326794896619231321691639751442 #define NPY_PI 3.141592653589793238462643383279502884 #define NPY_LOG2E 1.442695040888963407359924681001892137 #define NPY_SQRT2 1.414213562373095048801688724209698079 #else #ifdef LONGDOUBLE #define TYPE long double #define SUFFIX l #define EPS 50*LDBL_EPSILON #define CLOSE_ATOL 0 #define CLOSE_RTOL 1e-12 #define FMT "%.18Le" #define NPY_PI_2 1.570796326794896619231321691639751442L #define NPY_PI 3.141592653589793238462643383279502884L #define NPY_LOG2E 1.442695040888963407359924681001892137L #define NPY_SQRT2 1.414213562373095048801688724209698079L #else #error "Define FLOAT or DOUBLE or LONGDOUBLE" #endif @@ -39,127 +54,191 @@ const TYPE NZERO = -1.0 * 0.0; #define ADDSUFFIX_INT(A, B) CONCAT(A, B) #define ADDSUFFIX(A) ADDSUFFIX_INT(A, SUFFIX) #define TEST_PRINTF(func, xr, xi, er, ei, rr, ri) \ printf("%d: " STRINGIZE(func) STRINGIZE(SUFFIX) "(" FMT " + " FMT "j): " \ "expected: " FMT " + " FMT "j: received: " FMT " + " FMT "j\n", \ __LINE__, xr, xi, er, ei, rr, ri) #define TEST_INT(func, xr, xi, er, ei, rtest, itest) \ do { \ TYPE dxr = xr; \ TYPE dxi = xi; \ TYPE der = er; \ TYPE dei = ei; \ TYPE complex x = cpack(dxr, dxi); \ TYPE complex r = ADDSUFFIX(func)(x); \ TYPE rr = ADDSUFFIX(creal)(r); \ TYPE ri = ADDSUFFIX(cimag)(r); \ if (!(rtest(rr, der) && itest(ri, dei))) { \ ret = 0; \ TEST_PRINTF(func, dxr, dxi, der, dei, rr, ri); \ } \ } \ while(0) #define TEST_EE(func, xr, xi, er, ei) \ TEST_INT(func, xr, xi, er, ei, isequal, isequal) #define TEST_EC(func, xr, xi, er, ei) \ TEST_INT(func, xr, xi, er, ei, isequal, isclose) #define TEST_CE(func, xr, xi, er, ei) \ TEST_INT(func, xr, xi, er, ei, isclose, isequal) #define TEST_CC(func, xr, xi, er, ei) \ TEST_INT(func, xr, xi, er, ei, isclose, isclose) #define TEST_UNSPECIFIED2(func, xr, xi, er1, ei1, er2, ei2) \ do { \ TYPE dxr = xr; \ TYPE dxi = xi; \ TYPE der1 = er1; \ TYPE dei1 = ei1; \ TYPE der2 = er2; \ TYPE dei2 = ei2; \ TYPE complex x = cpack(dxr, dxi); \ TYPE complex r = ADDSUFFIX(func)(x); \ TYPE rr = ADDSUFFIX(creal)(r); \ TYPE ri = ADDSUFFIX(cimag)(r); \ if (!((isequal(rr, der1) && isequal(ri, dei1)) || \ (isequal(rr, der2) && isequal(ri, dei2)))) { \ ret = 0; \ TEST_PRINTF(func, dxr, dxi, der1, dei1, rr, ri); \ printf("or"); \ TEST_PRINTF(func, dxr, dxi, der2, dei2, rr, ri); \ } \ } \ while(0) #define TEST_UNSPECIFIED4(func, xr, xi, er1, ei1, er2, ei2, er3, ei3, er4, ei4)\ do { \ TYPE dxr = xr; \ TYPE dxi = xi; \ TYPE der1 = er1; \ TYPE dei1 = ei1; \ TYPE der2 = er2; \ TYPE dei2 = ei2; \ TYPE der3 = er3; \ TYPE dei3 = ei3; \ TYPE der4 = er4; \ TYPE dei4 = ei4; \ TYPE complex x = cpack(dxr, dxi); \ TYPE complex r = func(x); \ TYPE rr = ADDSUFFIX(creal)(r); \ TYPE ri = ADDSUFFIX(cimag)(r); \ if (!((isequal(rr, der1) && isequal(ri, dei1)) || \ (isequal(rr, der2) && isequal(ri, dei2)) || \ (isequal(rr, der3) && isequal(ri, dei3)) || \ (isequal(rr, der4) && isequal(ri, dei4)))) { \ ret = 0; \ TEST_PRINTF(func, dxr, dxi, der1, dei1, rr, ri); \ printf("or"); \ TEST_PRINTF(func, dxr, dxi, der2, dei2, rr, ri); \ printf("or"); \ TEST_PRINTF(func, dxr, dxi, der3, dei3, rr, ri); \ printf("or"); \ TEST_PRINTF(func, dxr, dxi, der4, dei4, rr, ri); \ } \ } \ while(0) #define TEST_CPOW_INT(xr, xi, yr, yi, er, ei, test) \ do { \ TYPE dxr = xr; \ TYPE dxi = xi; \ TYPE dyr = yr; \ TYPE dyi = yi; \ TYPE der = er; \ TYPE dei = ei; \ TYPE complex x = cpack(xr, xi); \ TYPE complex y = cpack(yr, yi); \ TYPE complex r = ADDSUFFIX(cpow)(x, y); \ TYPE rr = ADDSUFFIX(creal)(r); \ TYPE ri = ADDSUFFIX(cimag)(r); \ if (!(test(rr, der) && test(ri, dei))) { \ ret = 0; \ printf("%d: " STRINGIZE(cpow) STRINGIZE(SUFFIX) "(" FMT " + " FMT \ "j, " FMT " + " FMT "j): expected: " FMT " + " FMT \ "j: received: " FMT " + " FMT "j\n", __LINE__, dxr, dxi, \ dyr, dyi, der, dei, rr, ri); \ } \ } \ while(0) #define TEST_CPOW_EE(xr, xi, yr, yi, er, ei) \ TEST_CPOW_INT(xr, xi, yr, yi, er, ei, isequal) #define TEST_CPOW_CC(xr, xi, yr, yi, er, ei) \ TEST_CPOW_INT(xr, xi, yr, yi, er, ei, isclose) #define TEST_RAISES(func, xr, xi, er, ei, fpe) \ do { \ int except; \ TYPE dxr = xr; \ TYPE dxi = xi; \ TYPE der = er; \ TYPE dei = ei; \ TYPE complex r; \ TYPE complex x = cpack(xr, xi); \ TYPE rr, ri; \ feclearexcept(FE_ALL_EXCEPT); \ r = ADDSUFFIX(func)(x); \ except = fetestexcept(fpe); \ rr = ADDSUFFIX(creal)(r); \ ri = ADDSUFFIX(cimag)(r); \ if (!(except & fpe && isequal(rr, der) && isequal(ri, dei))) { \ ret = 0; \ TEST_PRINTF(func, dxr, dxi, der, dei, rr, ri); \ } \ } \ while(0) #define TEST_RAISES_UNSPECIFIED2(func, xr, xi, er1, ei1, er2, ei2, fpe) \ do { \ int except; \ TYPE dxr = xr; \ TYPE dxi = xi; \ TYPE der1 = er1; \ TYPE dei1 = ei1; \ TYPE der2 = er2; \ TYPE dei2 = ei2; \ TYPE complex r; \ TYPE complex x = cpack(xr, xi); \ TYPE rr, ri; \ feclearexcept(FE_ALL_EXCEPT); \ r = ADDSUFFIX(func)(x); \ except = fetestexcept(fpe); \ rr = ADDSUFFIX(creal)(r); \ ri = ADDSUFFIX(cimag)(r); \ if (!(except & fpe && ((isequal(rr, der1) && isequal(ri, dei1)) \ || (isequal(rr, der2) && isequal(ri, dei2))))) {\ ret = 0; \ TEST_PRINTF(func, dxr, dxi, der1, dei1, rr, ri); \ printf("or"); \ TEST_PRINTF(func, dxr, dxi, der2, dei2, rr, ri); \ } \ } \ while(0) #define TEST_BRANCH_CUT(func, xr, xi, dxr, dxi, rsign, isign, cksignzero) \ do { \ TYPE vxr = xr; \ TYPE vxi = xi; \ TYPE vdxr = dxr; \ TYPE vdxi = dxi; \ int vrsign = rsign; \ int visign = isign; \ int vcksignzero = cksignzero; \ TYPE complex x = cpack(vxr, vxi); \ TYPE complex dx = cpack(vdxr, vdxi); \ int q = check_branch_cut(ADDSUFFIX(func), x, dx, \ vrsign, visign, vcksignzero); \ if (!q) { \ ret = 0; \ printf(STRINGIZE(func) STRINGIZE(SUFFIX) ": branch cut failure: " \ "x = " FMT " + " FMT "j, dx = " FMT " + " FMT "j, rsign = %d, " \ "isign = %d, check_sign_zero = %d\n", vxr, vxi, \ vdxr, vdxi, vrsign, visign, vcksignzero); \ } \ } \ while(0) @@ -193,34 +272,32 @@ int isclose(TYPE a, TYPE b) const TYPE atol = CLOSE_ATOL; const TYPE rtol = CLOSE_RTOL; if (isfinite(a) && isfinite(b)) { return (ADDSUFFIX(fabs)(a - b) <= (atol + rtol*ADDSUFFIX(fabs)(b))); } return 0; } int isequal(TYPE a, TYPE b) { if (isfinite(a) && isfinite(b)) { if (a == 0 && b == 0) { TYPE signa = ADDSUFFIX(copysign)(1.0, a); TYPE signb = ADDSUFFIX(copysign)(1.0, b); return signa == signb; } else { return a == b; } } else if (isnan(a) && isnan(b)) { return 1; } else {/* infs */ return a == b; } } typedef TYPE complex (*complexfunc)(TYPE complex); typedef TYPE (*realfunc)(TYPE); @@ -308,18 +385,18 @@ int check_near_crossover(complexfunc cfunc, const char* fname) if ( diff > 2*EPS || czp == czm) { printf(fname); printf(": Loss of precision: j = %d, k = %d\n", j, k); printf("zp = (" FMT " + " FMT "j) -> (" FMT " + " FMT "j)\n", \ ADDSUFFIX(creal)(zp), ADDSUFFIX(cimag)(zp), \ ADDSUFFIX(creal)(czp), ADDSUFFIX(cimag)(czp)); printf("zm = (" FMT " + " FMT "j) -> (" FMT " + " FMT "j)\n", \ ADDSUFFIX(creal)(zm), ADDSUFFIX(cimag)(zm), \ ADDSUFFIX(creal)(czm), ADDSUFFIX(cimag)(czm)); printf("diff = " FMT ", exact match = %d\n", diff, czp == czm); ret = 0; } } } return ret; } int clp_internal(complexfunc cfunc, realfunc rfunc, int real, TYPE x) @@ -366,8 +443,8 @@ int check_loss_of_precision(complexfunc cfunc, realfunc rfunc, int real, if (ratio > rtol) { printf(fname); printf(": Loss of precision vs real:\n"); printf("x = " FMT "\n", x); printf("ratio = " FMT "\n", ratio); ret = 0; } } @@ -378,8 +455,8 @@ int check_loss_of_precision(complexfunc cfunc, realfunc rfunc, int real, if (ratio > rtol) { printf(fname); printf(": Loss of precision vs. real:\n"); printf("x = " FMT "\n", x); printf("ratio = " FMT "\n", ratio); ret = 0; } } @@ -391,52 +468,52 @@ int test_cacos() { int ret = 1; /* cacos(conj(z)) = conj(cacos(z)) */ TEST_CE(cacos, 0, 0, NPY_PI_2, NZERO); TEST_CE(cacos, 0, NZERO, NPY_PI_2, 0); TEST_CE(cacos, NZERO, 0, NPY_PI_2, NZERO); TEST_CE(cacos, NZERO, NZERO, NPY_PI_2, 0); TEST_CE(cacos, 0, NAN, NPY_PI_2, NAN); TEST_CE(cacos, NZERO, NAN, NPY_PI_2, NAN); TEST_CE(cacos, 2.0, INFINITY, NPY_PI_2, -INFINITY); TEST_CE(cacos, 2.0, -INFINITY, NPY_PI_2, INFINITY); /* can raise FE_INVALID or not */ TEST_EE(cacos, 2.0, NAN, NAN, NAN); TEST_CE(cacos, -INFINITY, 2.0, NPY_PI, -INFINITY); TEST_CE(cacos, -INFINITY, -2.0, NPY_PI, INFINITY); TEST_EE(cacos, INFINITY, 2.0, 0, -INFINITY); TEST_EE(cacos, INFINITY, -2.0, 0, INFINITY); TEST_CE(cacos, -INFINITY, INFINITY, 0.75 * NPY_PI, -INFINITY); TEST_CE(cacos, -INFINITY, -INFINITY, 0.75 * NPY_PI, INFINITY); TEST_CE(cacos, INFINITY, INFINITY, 0.25 * NPY_PI, -INFINITY); TEST_CE(cacos, INFINITY, -INFINITY, 0.25 * NPY_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_EE(cacos, NAN, 2.0, NAN, NAN); TEST_EE(cacos, NAN, -2.0, NAN, NAN); TEST_EE(cacos, NAN, INFINITY, NAN, -INFINITY); TEST_EE(cacos, NAN, -INFINITY, NAN, INFINITY); TEST_EE(cacos, NAN, NAN, NAN, NAN); TEST_BRANCH_CUT(cacos, -2, 0, 0, 1, 1, -1, 1); TEST_BRANCH_CUT(cacos, 2, 0, 0, -1, 1, -1, 1); TEST_BRANCH_CUT(cacos, 0, -2, 1, 0, 1, 1, 1); TEST_BRANCH_CUT(cacos, 0, 2, 1, 0, 1, 1, 1); TEST_CC(cacos, 0.5, 0.0, ADDSUFFIX(acos)(0.5), 0.0); return ret; } @@ -448,56 +525,56 @@ int test_casin() int ret = 1; /* casin(conj(z)) = conj(casin(z)) and casin is odd */ TEST_EE(casin, 0, 0, 0, 0); TEST_EE(casin, 0, NZERO, 0, NZERO); TEST_EE(casin, NZERO, 0, NZERO, 0); TEST_EE(casin, NZERO, NZERO, NZERO, NZERO); TEST_CE(casin, -INFINITY, 2.0, -NPY_PI_2, INFINITY); TEST_CE(casin, INFINITY, 2.0, NPY_PI_2, INFINITY); TEST_CE(casin, -INFINITY, -2.0, -NPY_PI_2, -INFINITY); TEST_CE(casin, INFINITY, -2.0, NPY_PI_2, -INFINITY); /* can raise FE_INVALID or not */ TEST_EE(casin, NAN, -2.0, NAN, NAN); TEST_EE(casin, NAN, 2.0, NAN, NAN); TEST_EE(casin, -2.0, INFINITY, NZERO, INFINITY); TEST_EE(casin, 2.0, INFINITY, 0, INFINITY); TEST_EE(casin, -2.0, -INFINITY, NZERO, -INFINITY); TEST_EE(casin, 2.0, -INFINITY, 0, -INFINITY); TEST_CE(casin, -INFINITY, INFINITY, -0.25*NPY_PI, INFINITY); TEST_CE(casin, INFINITY, INFINITY, 0.25*NPY_PI, INFINITY); TEST_CE(casin, -INFINITY, -INFINITY, -0.25*NPY_PI, -INFINITY); TEST_CE(casin, INFINITY, -INFINITY, 0.25*NPY_PI, -INFINITY); TEST_EE(casin, NAN, INFINITY, NAN, INFINITY); TEST_EE(casin, NAN, -INFINITY, NAN, -INFINITY); TEST_EE(casin, 0, NAN, 0, NAN); TEST_EE(casin, NZERO, NAN, NZERO, NAN); /* can raise FE_INVALID or not */ TEST_EE(casin, -2.0, NAN, NAN, NAN); TEST_EE(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_EE(casin, NAN, NAN, NAN, NAN); TEST_LOSS_OF_PRECISION(casin, asin, 0); TEST_CC(casin, 1e-5, 1e-5, 9.999999999666666667e-6, 1.0000000000333333333e-5); TEST_BRANCH_CUT(casin, -2, 0, 0, 1, 1, -1, 1); TEST_BRANCH_CUT(casin, 2, 0, 0, -1, 1, -1, 1); TEST_BRANCH_CUT(casin, 0, -2, 1, 0, 1, 1, 1); TEST_BRANCH_CUT(casin, 0, 2, 1, 0, 1, 1, 1); TEST_CC(casin, 0.5, 0, ADDSUFFIX(asin)(0.5), 0); return ret; } @@ -508,61 +585,61 @@ int test_catan() { int ret = 1; /* catan(conj(z)) = conj(catan(z)) and catan is odd */ TEST_EE(catan, 0, 0, 0, 0); TEST_EE(catan, 0, NZERO, 0, NZERO); TEST_EE(catan, NZERO, 0, NZERO, 0); TEST_EE(catan, NZERO, NZERO, NZERO, NZERO); TEST_EE(catan, NAN, 0, NAN, 0); TEST_EE(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_CE(catan, -INFINITY, 2.0, -NPY_PI_2, 0); TEST_CE(catan, INFINITY, 2.0, NPY_PI_2, 0); TEST_CE(catan, -INFINITY, -2.0, -NPY_PI_2, NZERO); TEST_CE(catan, INFINITY, -2.0, NPY_PI_2, NZERO); /* can raise FE_INVALID or not */ TEST_EE(catan, NAN, -2.0, NAN, NAN); TEST_EE(catan, NAN, 2.0, NAN, NAN); TEST_CE(catan, -2.0, INFINITY, -NPY_PI_2, 0); TEST_CE(catan, 2.0, INFINITY, NPY_PI_2, 0); TEST_CE(catan, -2.0, -INFINITY, -NPY_PI_2, NZERO); TEST_CE(catan, 2.0, -INFINITY, NPY_PI_2, NZERO); TEST_CE(catan, -INFINITY, INFINITY, -NPY_PI_2, 0); TEST_CE(catan, INFINITY, INFINITY, NPY_PI_2, 0); TEST_CE(catan, -INFINITY, -INFINITY, -NPY_PI_2, NZERO); TEST_CE(catan, INFINITY, -INFINITY, NPY_PI_2, NZERO); TEST_EE(catan, NAN, INFINITY, NAN, 0); TEST_EE(catan, NAN, -INFINITY, NAN, NZERO); /* can raise FE_INVALID or not */ TEST_EE(catan, -2.0, NAN, NAN, NAN); TEST_EE(catan, 2.0, NAN, NAN, NAN); /* sign of real part is unspecified */ TEST_UNSPECIFIED2(catan, -INFINITY, NAN, -NPY_PI_2, 0, -NPY_PI_2, NZERO); TEST_UNSPECIFIED2(catan, INFINITY, NAN, NPY_PI_2, 0, NPY_PI_2, NZERO); TEST_EE(catan, NAN, NAN, NAN, NAN); TEST_LOSS_OF_PRECISION(catan, atan, 0); TEST_CC(catan, 1e-5, 1e-5, 1.000000000066666666e-5, 9.999999999333333333e-6); TEST_BRANCH_CUT(catan, 0, -2, 1, 0, -1, 1, 1); TEST_BRANCH_CUT(catan, 0, 2, -1, 0, -1, 1, 1); TEST_BRANCH_CUT(catan, -2, 0, 0, 1, 1, 1, 1); TEST_BRANCH_CUT(catan, 2, 0, 0, 1, 1, 1, 1); TEST_CC(catan, 0.5, 0, ADDSUFFIX(catan)(0.5), 0); return ret; } @@ -573,49 +650,49 @@ int test_cacosh() { int ret = 1; /* cacosh(conj(z)) = conj(cacosh(z)) */ TEST_EC(cacosh, 0, 0, 0, NPY_PI_2); TEST_EC(cacosh, 0, NZERO, 0, -NPY_PI_2); TEST_EC(cacosh, NZERO, 0, 0, NPY_PI_2); TEST_EC(cacosh, NZERO, NZERO, 0, -NPY_PI_2); TEST_EC(cacosh, 2.0, INFINITY, INFINITY, NPY_PI_2); TEST_EC(cacosh, 2.0, -INFINITY, INFINITY, -NPY_PI_2); /* can raise FE_INVALID or not */ TEST_EE(cacosh, 2.0, NAN, NAN, NAN); TEST_EC(cacosh, -INFINITY, 2.0, INFINITY, NPY_PI); TEST_EC(cacosh, -INFINITY, -2.0, INFINITY, -NPY_PI); TEST_EE(cacosh, INFINITY, 2.0, INFINITY, 0); TEST_EE(cacosh, INFINITY, -2.0, INFINITY, NZERO); TEST_EC(cacosh, -INFINITY, INFINITY, INFINITY, 0.75*NPY_PI); TEST_EC(cacosh, -INFINITY, -INFINITY, INFINITY, -0.75*NPY_PI); TEST_EC(cacosh, INFINITY, INFINITY, INFINITY, 0.25*NPY_PI); TEST_EC(cacosh, INFINITY, -INFINITY, INFINITY, -0.25*NPY_PI); TEST_EE(cacosh, INFINITY, NAN, INFINITY, NAN); TEST_EE(cacosh, -INFINITY, NAN, INFINITY, NAN); /* can raise FE_INVALID or not */ TEST_EE(cacosh, NAN, 2.0, NAN, NAN); TEST_EE(cacosh, NAN, -2.0, NAN, NAN); TEST_EE(cacosh, NAN, INFINITY, INFINITY, NAN); TEST_EE(cacosh, NAN, -INFINITY, INFINITY, NAN); TEST_EE(cacosh, NAN, NAN, NAN, NAN); TEST_BRANCH_CUT(cacosh, -1, 0, 0, 1, 1, -1, 1); TEST_BRANCH_CUT(cacosh, 0.5, 0, 0, 1, 1, -1, 1); TEST_BRANCH_CUT(cacosh, 0, -2, 1, 0, 1, 1, 1); TEST_BRANCH_CUT(cacosh, 0, 2, 1, 0, 1, 1, 1); TEST_BRANCH_CUT(cacosh, 2, 0, 0, 1, 1, 1, 1); TEST_CC(cacosh, 1.5, 0, ADDSUFFIX(acosh)(1.5), 0); return ret; } #endif @@ -625,57 +702,57 @@ int test_casinh() { int ret = 1; /* casinh(conj(z)) = conj(casinh(z)) and casinh is odd */ TEST_EE(casinh, 0, 0, 0, 0); TEST_EE(casinh, 0, NZERO, 0, NZERO); TEST_EE(casinh, NZERO, 0, NZERO, 0); TEST_EE(casinh, NZERO, NZERO, NZERO, NZERO); TEST_EC(casinh, 2.0, INFINITY, INFINITY, NPY_PI_2); TEST_EC(casinh, 2.0, -INFINITY, INFINITY, -NPY_PI_2); TEST_EC(casinh, -2.0, INFINITY, -INFINITY, NPY_PI_2); TEST_EC(casinh, -2.0, -INFINITY, -INFINITY, -NPY_PI_2); /* can raise FE_INVALID or not */ TEST_EE(casinh, 2.0, NAN, NAN, NAN); TEST_EE(casinh, -2.0, NAN, NAN, NAN); TEST_EE(casinh, INFINITY, 2.0, INFINITY, 0); TEST_EE(casinh, INFINITY, -2.0, INFINITY, NZERO); TEST_EE(casinh, -INFINITY, 2.0, -INFINITY, 0); TEST_EE(casinh, -INFINITY, -2.0, -INFINITY, NZERO); TEST_EC(casinh, INFINITY, INFINITY, INFINITY, 0.25*NPY_PI); TEST_EC(casinh, INFINITY, -INFINITY, INFINITY, -0.25*NPY_PI); TEST_EC(casinh, -INFINITY, INFINITY, -INFINITY, 0.25*NPY_PI); TEST_EC(casinh, -INFINITY, -INFINITY, -INFINITY, -0.25*NPY_PI); TEST_EE(casinh, INFINITY, NAN, INFINITY, NAN); TEST_EE(casinh, -INFINITY, NAN, -INFINITY, NAN); TEST_EE(casinh, NAN, 0, NAN, 0); TEST_EE(casinh, NAN, NZERO, NAN, NZERO); /* can raise FE_INVALID or not */ TEST_EE(casinh, NAN, 2.0, NAN, NAN); TEST_EE(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_EE(casinh, NAN, NAN, NAN, NAN); TEST_LOSS_OF_PRECISION(casinh, asinh, 1); TEST_CC(casinh, 1e-5, 1e-5, 1.0000000000333333333e-5, 9.999999999666666667e-6); TEST_BRANCH_CUT(casinh, 0, -2, -1, 0, -1, 1, 1); TEST_BRANCH_CUT(casinh, 0, 2, 1, 0, -1, 1, 1); TEST_BRANCH_CUT(casinh, -2, 0, 0, 1, 1, 1, 1); TEST_BRANCH_CUT(casinh, 2, 0, 0, 1, 1, 1, 1); TEST_BRANCH_CUT(casinh, 0, 0, 1, 0, 1, 1, 1); TEST_CC(casinh, 0.5, 0, ADDSUFFIX(asinh)(0.5), 0); return ret; } @@ -686,63 +763,63 @@ int test_catanh() { int ret = 1; /* catanh(conj(z)) = conj(catanh(z)) and catanh is odd */ TEST_EE(catanh, 0, 0, 0, 0); TEST_EE(catanh, 0, NZERO, 0, NZERO); TEST_EE(catanh, NZERO, 0, NZERO, 0); TEST_EE(catanh, NZERO, NZERO, NZERO, NZERO); TEST_EE(catanh, 0, NAN, 0, NAN); TEST_EE(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_EC(catanh, 2.0, INFINITY, 0, NPY_PI_2); TEST_EC(catanh, 2.0, -INFINITY, 0, -NPY_PI_2); TEST_EC(catanh, -2.0, INFINITY, NZERO, NPY_PI_2); TEST_EC(catanh, -2.0, -INFINITY, NZERO, -NPY_PI_2); /* can raise FE_INVALID or not */ TEST_EE(catanh, 2.0, NAN, NAN, NAN); TEST_EE(catanh, -2.0, NAN, NAN, NAN); TEST_EC(catanh, INFINITY, 2.0, 0, NPY_PI_2); TEST_EC(catanh, INFINITY, -2.0, 0, -NPY_PI_2); TEST_EC(catanh, -INFINITY, 2.0, NZERO, NPY_PI_2); TEST_EC(catanh, -INFINITY, -2.0, NZERO, -NPY_PI_2); TEST_EC(catanh, INFINITY, INFINITY, 0, NPY_PI_2); TEST_EC(catanh, INFINITY, -INFINITY, 0, -NPY_PI_2); TEST_EC(catanh, -INFINITY, INFINITY, NZERO, NPY_PI_2); TEST_EC(catanh, -INFINITY, -INFINITY, NZERO, -NPY_PI_2); TEST_EE(catanh, INFINITY, NAN, 0, NAN); TEST_EE(catanh, -INFINITY, NAN, NZERO, NAN); /* can raise FE_INVALID or not */ TEST_EE(catanh, NAN, 2.0, NAN, NAN); TEST_EE(catanh, NAN, -2.0, NAN, NAN); /* sign of real part is unspecified */ TEST_UNSPECIFIED2(catanh, NAN, INFINITY, 0, NPY_PI_2, NZERO, NPY_PI_2); TEST_UNSPECIFIED2(catanh, NAN, -INFINITY, 0, -NPY_PI_2, NZERO, -NPY_PI_2); /* TEST(catanh, NAN, INFINITY, 0, NPY_PI_2); */ TEST_EE(catanh, NAN, NAN, NAN, NAN); TEST_LOSS_OF_PRECISION(catanh, atanh, 1); TEST_CC(catanh, 1e-5, 1e-5, 9.999999999333333333e-6, 1.000000000066666666e-5); TEST_BRANCH_CUT(catanh, -2, 0, 0, 1, 1, -1, 1); TEST_BRANCH_CUT(catanh, 2, 0, 0, -1, 1, -1, 1); TEST_BRANCH_CUT(catanh, 0, -2, 1, 0, 1, 1, 1); TEST_BRANCH_CUT(catanh, 0, 2, 1, 0, 1, 1, 1); TEST_BRANCH_CUT(catanh, 0, 0, 0, 1, 1, 1, 1); TEST_CC(catanh, 0.5, 0, ADDSUFFIX(atanh)(0.5), 0); return ret; } @@ -753,10 +830,10 @@ int test_ccos() { int ret = 1; /* ccos(conj(z)) = conj(ccos(z)) and ccos is even */ TEST_EE(ccos, NZERO, 0, 1, 0); TEST_EE(ccos, 0, 0, 1, NZERO); TEST_EE(ccos, NZERO, NZERO, 1, NZERO); TEST_EE(ccos, 0, NZERO, 1, 0); /* sign of imaginary part is unspecified */ TEST_RAISES_UNSPECIFIED2(ccos, -INFINITY, 0, NAN, 0, \ @@ -772,49 +849,49 @@ int test_ccos() TEST_RAISES(ccos, INFINITY, -2.0, NAN, NAN, FE_INVALID); /* can raise FE_INVALID or not */ TEST_EE(ccos, NAN, 2.0, NAN, NAN); TEST_EE(ccos, NAN, -2.0, NAN, NAN); TEST_EE(ccos, NZERO, INFINITY, INFINITY, 0); TEST_EE(ccos, 0, INFINITY, INFINITY, NZERO); TEST_EE(ccos, NZERO, -INFINITY, INFINITY, NZERO); TEST_EE(ccos, 0, -INFINITY, INFINITY, 0); TEST_EE(ccos, -1.0, INFINITY, INFINITY, INFINITY); TEST_EE(ccos, 1.0, INFINITY, INFINITY, -INFINITY); TEST_EE(ccos, -1.0, -INFINITY, INFINITY, -INFINITY); TEST_EE(ccos, 1.0, -INFINITY, INFINITY, INFINITY); TEST_EE(ccos, -2.0, INFINITY, -INFINITY, INFINITY); TEST_EE(ccos, 2.0, INFINITY, -INFINITY, -INFINITY); TEST_EE(ccos, -2.0, -INFINITY, -INFINITY, -INFINITY); TEST_EE(ccos, 2.0, -INFINITY, -INFINITY, INFINITY); TEST_EE(ccos, -4.0, INFINITY, -INFINITY, -INFINITY); TEST_EE(ccos, 4.0, INFINITY, -INFINITY, INFINITY); TEST_EE(ccos, -4.0, -INFINITY, -INFINITY, INFINITY); TEST_EE(ccos, 4.0, -INFINITY, -INFINITY, -INFINITY); TEST_EE(ccos, -5.0, INFINITY, INFINITY, -INFINITY); TEST_EE(ccos, 5.0, INFINITY, INFINITY, INFINITY); TEST_EE(ccos, -5.0, -INFINITY, INFINITY, INFINITY); TEST_EE(ccos, 5.0, -INFINITY, INFINITY, -INFINITY); /* sign of real part is unspecified */ TEST_RAISES_UNSPECIFIED2(ccos, -INFINITY, INFINITY, INFINITY, NAN, \ -INFINITY, NAN, FE_INVALID); TEST_EE(ccos, NAN, INFINITY, INFINITY, NAN); TEST_EE(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_EE(ccos, -2.0, NAN, NAN, NAN); TEST_EE(ccos, 2.0, NAN, NAN, NAN); TEST_EE(ccos, NAN, NAN, NAN, NAN); TEST_CC(ccos, 0.5, 0, ADDSUFFIX(cos)(0.5), 0); return ret; } @@ -825,10 +902,10 @@ int test_csin() { int ret = 1; /* csin(conj(z)) = conj(csin(z)) and csin is odd */ TEST_EE(csin, 0, 0, 0, 0); TEST_EE(csin, 0, NZERO, 0, NZERO); TEST_EE(csin, NZERO, 0, NZERO, 0); TEST_EE(csin, NZERO, NZERO, NZERO, NZERO); /* sign of imaginary part is unspecified */ TEST_RAISES_UNSPECIFIED2(csin, -INFINITY, 0, NAN, 0, \ @@ -844,30 +921,30 @@ int test_csin() TEST_RAISES(csin, INFINITY, -2.0, NAN, NAN, FE_INVALID); /* can raise FE_INVALID or not */ TEST_EE(csin, NAN, 2.0, NAN, NAN); TEST_EE(csin, NAN, -2.0, NAN, NAN); TEST_EE(csin, NZERO, INFINITY, NZERO, INFINITY); TEST_EE(csin, 0, INFINITY, 0, INFINITY); TEST_EE(csin, NZERO, -INFINITY, NZERO, -INFINITY); TEST_EE(csin, 0, -INFINITY, 0, -INFINITY); TEST_EE(csin, -1.0, INFINITY, -INFINITY, INFINITY); TEST_EE(csin, 1.0, INFINITY, INFINITY, INFINITY); TEST_EE(csin, -1.0, -INFINITY, -INFINITY, -INFINITY); TEST_EE(csin, 1.0, -INFINITY, INFINITY, -INFINITY); TEST_EE(csin, -2.0, INFINITY, -INFINITY, -INFINITY); TEST_EE(csin, 2.0, INFINITY, INFINITY, -INFINITY); TEST_EE(csin, -2.0, -INFINITY, -INFINITY, INFINITY); TEST_EE(csin, 2.0, -INFINITY, INFINITY, INFINITY); TEST_EE(csin, -4.0, INFINITY, INFINITY, -INFINITY); TEST_EE(csin, 4.0, INFINITY, -INFINITY, -INFINITY); TEST_EE(csin, -4.0, -INFINITY, INFINITY, INFINITY); TEST_EE(csin, 4.0, -INFINITY, -INFINITY, INFINITY); TEST_EE(csin, -5.0, INFINITY, INFINITY, INFINITY); TEST_EE(csin, 5.0, INFINITY, -INFINITY, INFINITY); TEST_EE(csin, -5.0, -INFINITY, INFINITY, -INFINITY); TEST_EE(csin, 5.0, -INFINITY, -INFINITY, -INFINITY); /* sign of imaginary part is unspecified */ TEST_RAISES_UNSPECIFIED2(csin, -INFINITY, INFINITY, NAN, INFINITY, \ @@ -877,16 +954,16 @@ int test_csin() TEST_UNSPECIFIED2(csin, NAN, INFINITY, NAN, INFINITY, NAN, -INFINITY); TEST_UNSPECIFIED2(csin, NAN, -INFINITY, NAN, INFINITY, NAN, -INFINITY); TEST_EE(csin, 0, NAN, 0, NAN); TEST_EE(csin, NZERO, NAN, NZERO, NAN); /* can raise FE_INVALID or not */ TEST_EE(csin, -2.0, NAN, NAN, NAN); TEST_EE(csin, 2.0, NAN, NAN, NAN); TEST_EE(csin, NAN, NAN, NAN, NAN); TEST_CC(csin, 0.5, 0, ADDSUFFIX(sin)(0.5), 0); return ret; } @@ -897,26 +974,26 @@ int test_ctan() { int ret = 1; /* ctan(conj(z)) = conj(ctan(z)) and ctan is odd */ TEST_EE(ctan, 0, 0, 0, 0); TEST_EE(ctan, 0, NZERO, 0, NZERO); TEST_EE(ctan, NZERO, 0, NZERO, 0); TEST_EE(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_EE(ctan, NAN, 2.0, NAN, NAN); TEST_EE(ctan, NAN, -2.0, NAN, NAN); TEST_EE(ctan, -1.0, INFINITY, NZERO, 1.0); TEST_EE(ctan, 1.0, INFINITY, 0, 1.0); TEST_EE(ctan, -1.0, -INFINITY, NZERO, -1.0); TEST_EE(ctan, 1.0, -INFINITY, 0, -1.0); TEST_EE(ctan, -2.0, INFINITY, 0, 1); TEST_EE(ctan, 2.0, INFINITY, NZERO, 1); TEST_EE(ctan, -2.0, -INFINITY, 0, -1); TEST_EE(ctan, 2.0, -INFINITY, NZERO, -1); /* sign of real part is unspecified */ TEST_UNSPECIFIED2(ctan, INFINITY, INFINITY, 0, 1, NZERO, 1); @@ -928,19 +1005,19 @@ int test_ctan() TEST_UNSPECIFIED2(ctan, NAN, INFINITY, 0, 1, NZERO, 1); TEST_UNSPECIFIED2(ctan, NAN, -INFINITY, 0, -1, NZERO, -1); TEST_EE(ctan, 0, NAN, 0, NAN); TEST_EE(ctan, NZERO, NAN, NZERO, NAN); /* can raise FE_INVALID or not */ TEST_EE(ctan, 2.0, NAN, NAN, NAN); TEST_EE(ctan, -2.0, NAN, NAN, NAN); TEST_EE(ctan, NAN, NAN, NAN, NAN); TEST_CC(ctan, 0.5, 0, ADDSUFFIX(tan)(0.5), 0); TEST_CC(ctan, 0, 1000, 0, 1); TEST_CC(ctan, 0, -1000, 0, -1); return ret; } @@ -951,10 +1028,10 @@ int test_ccosh() { int ret = 1; /* ccosh(conj(z)) = conj(ccosh(z)) and ccosh is even */ TEST_EE(ccosh, 0, 0, 1, 0); TEST_EE(ccosh, 0, NZERO, 1, NZERO); TEST_EE(ccosh, NZERO, 0, 1, NZERO); TEST_EE(ccosh, NZERO, NZERO, 1, 0); /* sign of imaginary part is unspecified */ TEST_RAISES_UNSPECIFIED2(ccosh, 0, INFINITY, NAN, 0, \ @@ -970,49 +1047,49 @@ int test_ccosh() TEST_RAISES(ccosh, -2.0, -INFINITY, NAN, NAN, FE_INVALID); /* can raise FE_INVALID or not */ TEST_EE(ccosh, 2.0, NAN, NAN, NAN); TEST_EE(ccosh, -2.0, NAN, NAN, NAN); TEST_EE(ccosh, INFINITY, 0, INFINITY, 0); TEST_EE(ccosh, INFINITY, NZERO, INFINITY, NZERO); TEST_EE(ccosh, -INFINITY, 0, INFINITY, NZERO); TEST_EE(ccosh, -INFINITY, NZERO, INFINITY, 0); TEST_EE(ccosh, INFINITY, 1.0, INFINITY, INFINITY); TEST_EE(ccosh, INFINITY, -1.0, INFINITY, -INFINITY); TEST_EE(ccosh, -INFINITY, 1.0, INFINITY, -INFINITY); TEST_EE(ccosh, -INFINITY, -1.0, INFINITY, INFINITY); TEST_EE(ccosh, INFINITY, 2.0, -INFINITY, INFINITY); TEST_EE(ccosh, INFINITY, -2.0, -INFINITY, -INFINITY); TEST_EE(ccosh, -INFINITY, 2.0, -INFINITY, -INFINITY); TEST_EE(ccosh, -INFINITY, -2.0, -INFINITY, INFINITY); TEST_EE(ccosh, INFINITY, 4.0, -INFINITY, -INFINITY); TEST_EE(ccosh, INFINITY, -4.0, -INFINITY, INFINITY); TEST_EE(ccosh, -INFINITY, 4.0, -INFINITY, INFINITY); TEST_EE(ccosh, -INFINITY, -4.0, -INFINITY, -INFINITY); TEST_EE(ccosh, INFINITY, 5.0, INFINITY, -INFINITY); TEST_EE(ccosh, INFINITY, -5.0, INFINITY, INFINITY); TEST_EE(ccosh, -INFINITY, 5.0, INFINITY, INFINITY); TEST_EE(ccosh, -INFINITY, -5.0, INFINITY, -INFINITY); /* sign of real part is unspecified */ TEST_RAISES_UNSPECIFIED2(ccosh, INFINITY, INFINITY, INFINITY, NAN, \ -INFINITY, NAN, FE_INVALID); TEST_EE(ccosh, INFINITY, NAN, INFINITY, NAN); TEST_EE(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_EE(ccosh, NAN, 2.0, NAN, NAN); TEST_EE(ccosh, NAN, -2.0, NAN, NAN); TEST_EE(ccosh, NAN, NAN, NAN, NAN); TEST_CC(ccosh, 0.5, 0, ADDSUFFIX(cosh)(0.5), 0); return ret; } @@ -1023,10 +1100,10 @@ int test_csinh() { int ret = 1; /* csinh(conj(z)) = conj(csinh(z)) and csinh is odd */ TEST_EE(csinh, 0, 0, 0, 0); TEST_EE(csinh, 0, NZERO, 0, NZERO); TEST_EE(csinh, NZERO, 0, NZERO, 0); TEST_EE(csinh, NZERO, NZERO, NZERO, NZERO); /* sign of real part is unspecified */ TEST_RAISES_UNSPECIFIED2(csinh, 0, INFINITY, 0, NAN, \ @@ -1042,30 +1119,30 @@ int test_csinh() TEST_RAISES(csinh, -2.0, -INFINITY, NAN, NAN, FE_INVALID); /* can raise FE_INVALID or not */ TEST_EE(csinh, 2.0, NAN, NAN, NAN); TEST_EE(csinh, -2.0, NAN, NAN, NAN); TEST_EE(csinh, INFINITY, 0, INFINITY, 0); TEST_EE(csinh, INFINITY, NZERO, INFINITY, NZERO); TEST_EE(csinh, -INFINITY, 0, -INFINITY, 0); TEST_EE(csinh, -INFINITY, NZERO, -INFINITY, NZERO); TEST_EE(csinh, INFINITY, 1.0, INFINITY, INFINITY); TEST_EE(csinh, INFINITY, -1.0, INFINITY, -INFINITY); TEST_EE(csinh, -INFINITY, 1.0, -INFINITY, INFINITY); TEST_EE(csinh, -INFINITY, -1.0, -INFINITY, -INFINITY); TEST_EE(csinh, INFINITY, 2.0, -INFINITY, INFINITY); TEST_EE(csinh, INFINITY, -2.0, -INFINITY, -INFINITY); TEST_EE(csinh, -INFINITY, 2.0, INFINITY, INFINITY); TEST_EE(csinh, -INFINITY, -2.0, INFINITY, -INFINITY); TEST_EE(csinh, INFINITY, 4.0, -INFINITY, -INFINITY); TEST_EE(csinh, INFINITY, -4.0, -INFINITY, INFINITY); TEST_EE(csinh, -INFINITY, 4.0, INFINITY, -INFINITY); TEST_EE(csinh, -INFINITY, -4.0, INFINITY, INFINITY); TEST_EE(csinh, INFINITY, 5.0, INFINITY, -INFINITY); TEST_EE(csinh, INFINITY, -5.0, INFINITY, INFINITY); TEST_EE(csinh, -INFINITY, 5.0, -INFINITY, -INFINITY); TEST_EE(csinh, -INFINITY, -5.0, -INFINITY, INFINITY); /* sign of real part is unspecified */ TEST_RAISES_UNSPECIFIED2(csinh, INFINITY, INFINITY, INFINITY, NAN, \ @@ -1075,16 +1152,16 @@ int test_csinh() TEST_UNSPECIFIED2(csinh, INFINITY, NAN, INFINITY, NAN, -INFINITY, NAN); TEST_UNSPECIFIED2(csinh, -INFINITY, NAN, INFINITY, NAN, -INFINITY, NAN); TEST_EE(csinh, NAN, 0, NAN, 0); TEST_EE(csinh, NAN, NZERO, NAN, NZERO); /* can raise FE_INVALID or not */ TEST_EE(csinh, NAN, 2.0, NAN, NAN); TEST_EE(csinh, NAN, -2.0, NAN, NAN); TEST_EE(csinh, NAN, NAN, NAN, NAN); TEST_CC(csinh, 0.5, 0, ADDSUFFIX(sinh)(0.5), 0); return ret; } @@ -1095,26 +1172,26 @@ int test_ctanh() { int ret = 1; /* ctanh(conj(z)) = conj(ctanh(z)) and ctanh is odd */ TEST_EE(ctanh, 0, 0, 0, 0); TEST_EE(ctanh, 0, NZERO, 0, NZERO); TEST_EE(ctanh, NZERO, 0, NZERO, 0); TEST_EE(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_EE(ctanh, 2.0, NAN, NAN, NAN); TEST_EE(ctanh, -2.0, NAN, NAN, NAN); TEST_EE(ctanh, INFINITY, 1.0, 1.0, 0); TEST_EE(ctanh, INFINITY, -1.0, 1.0, NZERO); TEST_EE(ctanh, -INFINITY, 1.0, -1.0, 0); TEST_EE(ctanh, -INFINITY, -1.0, -1.0, NZERO); TEST_EE(ctanh, INFINITY, 2.0, 1.0, NZERO); TEST_EE(ctanh, INFINITY, -2.0, 1.0, 0); TEST_EE(ctanh, -INFINITY, 2.0, -1.0, NZERO); TEST_EE(ctanh, -INFINITY, -2.0, -1.0, 0); /* sign of imaginary part is unspecified */ TEST_UNSPECIFIED2(ctanh, INFINITY, INFINITY, 1, 0, 1, NZERO); @@ -1126,19 +1203,19 @@ int test_ctanh() TEST_UNSPECIFIED2(ctanh, INFINITY, NAN, 1, 0, 1, NZERO); TEST_UNSPECIFIED2(ctanh, -INFINITY, NAN, -1, 0, -1, NZERO); TEST_EE(ctanh, NAN, 0, NAN, 0); TEST_EE(ctanh, NAN, NZERO, NAN, NZERO); /* can raise FE_INVALID or not */ TEST_EE(ctanh, NAN, 2.0, NAN, NAN); TEST_EE(ctanh, NAN, -2.0, NAN, NAN); TEST_EE(ctanh, NAN, NAN, NAN, NAN); TEST_CC(ctanh, 0.5, 0, ADDSUFFIX(tanh)(0.5), 0); TEST_CC(ctanh, 1000, 0, 1, 0); TEST_CC(ctanh, -1000, 0, -1, 0); return ret; } @@ -1149,38 +1226,38 @@ int test_cexp() { int ret = 1; /* cexp(conj(z)) = conj(cexp(z)) */ TEST_EE(cexp, 0, 0, 1, 0); TEST_EE(cexp, 0, NZERO, 1, NZERO); TEST_EE(cexp, NZERO, 0, 1, 0); TEST_EE(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_EE(cexp, 42.0, NAN, NAN, NAN); TEST_EE(cexp, INFINITY, 0, INFINITY, 0); TEST_EE(cexp, INFINITY, NZERO, INFINITY, NZERO); TEST_EE(cexp, -INFINITY, 1.0, 0, 0); TEST_EE(cexp, -INFINITY, -1.0, 0, NZERO); TEST_EE(cexp, -INFINITY, 2.0, NZERO, 0); TEST_EE(cexp, -INFINITY, -2.0, NZERO, NZERO); TEST_EE(cexp, -INFINITY, 4.0, NZERO, NZERO); TEST_EE(cexp, -INFINITY, -4.0, NZERO, 0); TEST_EE(cexp, -INFINITY, 5.0, 0, NZERO); TEST_EE(cexp, -INFINITY, -5.0, 0, 0); TEST_EE(cexp, INFINITY, 1.0, INFINITY, INFINITY); TEST_EE(cexp, INFINITY, -1.0, INFINITY, -INFINITY); TEST_EE(cexp, INFINITY, 2.0, -INFINITY, INFINITY); TEST_EE(cexp, INFINITY, -2.0, -INFINITY, -INFINITY); TEST_EE(cexp, INFINITY, 4.0, -INFINITY, -INFINITY); TEST_EE(cexp, INFINITY, -4.0, -INFINITY, INFINITY); TEST_EE(cexp, INFINITY, 5.0, INFINITY, -INFINITY); TEST_EE(cexp, INFINITY, -5.0, INFINITY, INFINITY); /* signs of both parts are unspecified */ TEST_UNSPECIFIED4(cexp, -INFINITY, INFINITY, 0, 0, NZERO, 0, \ @@ -1199,21 +1276,20 @@ int test_cexp() /* sign of real part is unspecified */ TEST_UNSPECIFIED2(cexp, INFINITY, NAN, INFINITY, NAN, -INFINITY, NAN); TEST_EE(cexp, NAN, 0, NAN, 0); TEST_EE(cexp, NAN, NZERO, NAN, NZERO); /* can raise FE_INVALID or not */ TEST_EE(cexp, NAN, 2.0, NAN, NAN); TEST_EE(cexp, NAN, -2.0, NAN, NAN); TEST_EE(cexp, NAN, NAN, NAN, NAN); TEST_CC(cexp, 0.5, 0, ADDSUFFIX(exp)(0.5), 0); TEST_CC(cexp, 1, 0, M_E, 0); TEST_CC(cexp, 0, 1, ADDSUFFIX(cos)(1), ADDSUFFIX(sin)(1)); TEST_CC(cexp, 1, 1, M_E*ADDSUFFIX(cos)(1), M_E*ADDSUFFIX(sin)(1)); return ret; } @@ -1224,48 +1300,48 @@ int test_clog() { int ret = 1; /* clog(conj(z)) = conj(clog(z)) */ TEST_RAISES(clog, NZERO, 0, -INFINITY, NPY_PI, FE_DIVBYZERO); TEST_RAISES(clog, NZERO, NZERO, -INFINITY, -NPY_PI, FE_DIVBYZERO); TEST_RAISES(clog, 0, 0, -INFINITY, 0, FE_DIVBYZERO); TEST_RAISES(clog, 0, NZERO, -INFINITY, NZERO, FE_DIVBYZERO); TEST_EC(clog, 2.0, INFINITY, INFINITY, NPY_PI_2); TEST_EC(clog, 2.0, -INFINITY, INFINITY, -NPY_PI_2); /* can raise FE_INVALID or not */ TEST_EE(clog, 2.0, NAN, NAN, NAN); TEST_EC(clog, -INFINITY, 2.0, INFINITY, NPY_PI); TEST_EC(clog, -INFINITY, -2.0, INFINITY, -NPY_PI); TEST_EE(clog, INFINITY, 2.0, INFINITY, 0); TEST_EE(clog, INFINITY, -2.0, INFINITY, NZERO); TEST_EC(clog, -INFINITY, INFINITY, INFINITY, 0.75 * NPY_PI); TEST_EC(clog, -INFINITY, -INFINITY, INFINITY, -0.75 * NPY_PI); TEST_EC(clog, INFINITY, INFINITY, INFINITY, 0.25 * NPY_PI); TEST_EC(clog, INFINITY, -INFINITY, INFINITY, -0.25 * NPY_PI); TEST_EE(clog, INFINITY, NAN, INFINITY, NAN); TEST_EE(clog, -INFINITY, NAN, INFINITY, NAN); /* can raise FE_INVALID or not */ TEST_EE(clog, NAN, 2.0, NAN, NAN); TEST_EE(clog, NAN, -2.0, NAN, NAN); TEST_EE(clog, NAN, INFINITY, INFINITY, NAN); TEST_EE(clog, NAN, -INFINITY, INFINITY, NAN); TEST_EE(clog, NAN, NAN, NAN, NAN); TEST_BRANCH_CUT(clog, -0.5, 0, 0, 1, 1, -1, 1); TEST_CC(clog, 0.5, 0, ADDSUFFIX(log)(0.5), 0); TEST_CC(clog, 1, 0, 0, 0); TEST_CC(clog, 1, 2, 0.80471895621705014, 1.1071487177940904); return ret; } @@ -1280,78 +1356,78 @@ int test_cpow() /* We can check for branch cuts in here */ /* tests from test_umath.py: TestPower: test_power_complex */ TEST_CPOW_CC(1, 2, 0, 0, 1, 0); TEST_CPOW_CC(2, 3, 0, 0, 1, 0); TEST_CPOW_CC(3, 4, 0, 0, 1, 0); TEST_CPOW_CC(1, 2, 1, 0, 1, 2); TEST_CPOW_CC(2, 3, 1, 0, 2, 3); TEST_CPOW_CC(3, 4, 1, 0, 3, 4); TEST_CPOW_CC(1, 2, 2, 0, -3, 4); TEST_CPOW_CC(2, 3, 2, 0, -5, 12); TEST_CPOW_CC(3, 4, 2, 0, -7, 24); TEST_CPOW_CC(1, 2, 3, 0, -11, -2); TEST_CPOW_CC(2, 3, 3, 0, -46, 9); TEST_CPOW_CC(3, 4, 3, 0, -117, 44); TEST_CPOW_CC(1, 2, 4, 0, -7, -24); TEST_CPOW_CC(2, 3, 4, 0, -119, -120); TEST_CPOW_CC(3, 4, 4, 0, -527, -336); TEST_CPOW_CC(1, 2, -1, 0, 1.0/5.0, -2.0/5.0); TEST_CPOW_CC(2, 3, -1, 0, 2.0/13.0, -3.0/13.0); TEST_CPOW_CC(3, 4, -1, 0, 3.0/25.0, -4.0/25.0); TEST_CPOW_CC(1, 2, -2, 0, -3.0/25.0, -4.0/25.0); TEST_CPOW_CC(2, 3, -2, 0, -5.0/169.0, -12.0/169.0); TEST_CPOW_CC(3, 4, -2, 0, -7.0/625.0, -24.0/625.0); TEST_CPOW_CC(1, 2, -3, 0, -11.0/125.0, 2.0/125.0); TEST_CPOW_CC(2, 3, -3, 0, -46.0/2197.0, -9.0/2197.0); TEST_CPOW_CC(3, 4, -3, 0, -117.0/15625.0, -44.0/15625.0); TEST_CPOW_CC(1, 2, 0.5, 0, 1.272019649514069, 0.7861513777574233); TEST_CPOW_CC(2, 3, 0.5, 0, 1.6741492280355401, 0.895977476129838); TEST_CPOW_CC(3, 4, 0.5, 0, 2, 1); TEST_CPOW_CC(1, 2, 14, 0, -76443, 16124); TEST_CPOW_CC(2, 3, 14, 0, 23161315, 58317492); TEST_CPOW_CC(3, 4, 14, 0, 5583548873, 2465133864); TEST_CPOW_EE(0, INFINITY, 1, 0, 0, INFINITY); TEST_CPOW_EE(0, INFINITY, 2, 0, -INFINITY, NAN); TEST_CPOW_EE(0, INFINITY, 3, 0, NAN, NAN); TEST_CPOW_EE(1, INFINITY, 1, 0, 1, INFINITY); TEST_CPOW_EE(1, INFINITY, 2, 0, -INFINITY, INFINITY); TEST_CPOW_EE(1, INFINITY, 3, 0, -INFINITY, NAN); /* tests from test_umath.py: TestPower: test_power_zero */ TEST_CPOW_CC(0, 0, 0.33, 0, 0, 0); TEST_CPOW_CC(0, 0, 0.5, 0, 0, 0); TEST_CPOW_CC(0, 0, 1.0, 0, 0, 0); TEST_CPOW_CC(0, 0, 1.5, 0, 0, 0); TEST_CPOW_CC(0, 0, 2.0, 0, 0, 0); TEST_CPOW_CC(0, 0, 3.0, 0, 0, 0); TEST_CPOW_CC(0, 0, 4.0, 0, 0, 0); TEST_CPOW_CC(0, 0, 5.0, 0, 0, 0); TEST_CPOW_CC(0, 0, 6.6, 0, 0, 0); TEST_CPOW_EE(0, 0, 0, 0, 1, 0); TEST_CPOW_EE(0, 0, 0, 1, NAN, NAN); TEST_CPOW_EE(0, 0, -0.33, 0, NAN, NAN); TEST_CPOW_EE(0, 0, -0.5, 0, NAN, NAN); TEST_CPOW_EE(0, 0, -1.0, 0, NAN, NAN); TEST_CPOW_EE(0, 0, -1.5, 0, NAN, NAN); TEST_CPOW_EE(0, 0, -2.0, 0, NAN, NAN); TEST_CPOW_EE(0, 0, -3.0, 0, NAN, NAN); TEST_CPOW_EE(0, 0, -4.0, 0, NAN, NAN); TEST_CPOW_EE(0, 0, -5.0, 0, NAN, NAN); TEST_CPOW_EE(0, 0, -6.6, 0, NAN, NAN); TEST_CPOW_EE(0, 0, -1, 0.2, NAN, NAN); /* tests from test_umath_complex.py: TestCpow: test_simple * --- skip, duplicating existing tests --- @@ -1360,40 +1436,40 @@ int test_cpow() /* tests from test_umath_complex.py: TestCpow: test_scalar, test_array * these tests are equilvent for this level. */ TEST_CPOW_CC(1, 0, 1, 0, 1, 0); TEST_CPOW_CC(1, 0, 0, 1, 1, 0); TEST_CPOW_CC(1, 0, -0.5, 1.5, 1, 0); TEST_CPOW_CC(1, 0, 2, 0, 1, 0); TEST_CPOW_CC(1, 0, 3, 0, 1, 0); TEST_CPOW_CC(0, 1, 1, 0, 0, 1); TEST_CPOW_CC(0, 1, 0, 1, ADDSUFFIX(exp)(-NPY_PI_2), 0); TEST_CPOW_CC(0, 1, -0.5, 1.5, 0.067019739708273365, 0.067019739708273365); TEST_CPOW_CC(0, 1, 2, 0, -1, 0); TEST_CPOW_CC(0, 1, 3, 0, 0, -1); TEST_CPOW_CC(2, 0, 1, 0, 2, 0); TEST_CPOW_CC(2, 0, 0, 1, ADDSUFFIX(cos)(NPY_LOG2E), ADDSUFFIX(sin)(NPY_LOG2E)); TEST_CPOW_CC(2, 0, 2, 0, 4, 0); TEST_CPOW_CC(2, 0, 3, 0, 8, 0); TEST_CPOW_CC(2.5, 0.375, 1, 0, 2.5, 0.375); TEST_CPOW_CC(2.5, 0.375, 0, 1, 0.51691507509598866, 0.68939360813851125); TEST_CPOW_CC(2.5, 0.375, -0.5, 1.5, 0.12646517347496394, 0.48690593271654437); TEST_CPOW_CC(2.5, 0.375, 2, 0, 391.0/64.0, 15.0/8.0); TEST_CPOW_CC(2.5, 0.375, 3, 0, 1865.0/128.0, 3573.0/512.0); TEST_CPOW_EE(INFINITY, 0, 1, 0, NAN, NAN); TEST_CPOW_EE(INFINITY, 0, 0, 1, NAN, NAN); TEST_CPOW_EE(INFINITY, 0, -0.5, 1.5, NAN, NAN); TEST_CPOW_EE(INFINITY, 0, 2, 0, NAN, NAN); TEST_CPOW_EE(INFINITY, 0, 3, 0, NAN, NAN); TEST_CPOW_EE(NAN, 0, 1, 0, NAN, NAN); TEST_CPOW_EE(NAN, 0, 0, 1, NAN, NAN); TEST_CPOW_EE(NAN, 0, -0.5, 1.5, NAN, NAN); TEST_CPOW_EE(NAN, 0, 2, 0, NAN, NAN); TEST_CPOW_EE(NAN, 0, 3, 0, NAN, NAN); return ret; } @@ -1404,53 +1480,53 @@ int test_csqrt() { int ret = 1; /* csqrt(conj(z)) = conj(csqrt(z)) */ TEST_EE(csqrt, 0, 0, 0, 0); TEST_EE(csqrt, 0, NZERO, 0, NZERO); TEST_EE(csqrt, NZERO, 0, 0, 0); TEST_EE(csqrt, NZERO, NZERO, 0, NZERO); TEST_EE(csqrt, 2.0, INFINITY, INFINITY, INFINITY); TEST_EE(csqrt, 2.0, -INFINITY, INFINITY, -INFINITY); TEST_EE(csqrt, NAN, INFINITY, INFINITY, INFINITY); TEST_EE(csqrt, NAN, -INFINITY, INFINITY, -INFINITY); TEST_EE(csqrt, INFINITY, INFINITY, INFINITY, INFINITY); TEST_EE(csqrt, INFINITY, -INFINITY, INFINITY, -INFINITY); TEST_EE(csqrt, -INFINITY, INFINITY, INFINITY, INFINITY); TEST_EE(csqrt, -INFINITY, -INFINITY, INFINITY, -INFINITY); /* can raise FE_INVALID or not */ TEST_EE(csqrt, 2.0, NAN, NAN, NAN); TEST_EE(csqrt, -INFINITY, 2.0, 0, INFINITY); TEST_EE(csqrt, -INFINITY, -2.0, 0, -INFINITY); TEST_EE(csqrt, INFINITY, 2.0, INFINITY, 0); TEST_EE(csqrt, INFINITY, -2.0, INFINITY, NZERO); /* sign of imaginary part is unspecified */ TEST_UNSPECIFIED2(csqrt, -INFINITY, NAN, NAN, INFINITY, NAN, -INFINITY); TEST_EE(csqrt, INFINITY, NAN, INFINITY, NAN); /* can raise FE_INVALID or not */ TEST_EE(csqrt, NAN, 2.0, NAN, NAN); TEST_EE(csqrt, NAN, -2.0, NAN, NAN); TEST_EE(csqrt, NAN, NAN, NAN, NAN); TEST_BRANCH_CUT(csqrt, -0.5, 0, 0, 1, 1, -1, 1); TEST_CC(csqrt, 0.5, 0, ADDSUFFIX(sqrt)(0.5), 0); TEST_CC(csqrt, 1, 0, 1, 0); TEST_CC(csqrt, 0, 1, NPY_SQRT2/2.0, NPY_SQRT2/2.0); TEST_CC(csqrt, -1, 0, 0, 1); TEST_CC(csqrt, 1, 1, 1.0986841134678100, 0.4550898605622273); TEST_CC(csqrt, 1, -1, 1.0986841134678100, -0.4550898605622273); return ret; } @@ -1497,7 +1573,7 @@ int main(int argc, char** argv) #ifdef CEXP printf("cexp: %d\n\n", test_cexp()); #endif #ifdef CLOG printf("clog: %d\n\n", test_clog()); #endif #ifdef CPOW -
ewmoore revised this gist
Sep 25, 2013 . 1 changed file with 474 additions and 191 deletions.There are no files selected for viewing
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 charactersOriginal file line number Diff line number Diff line change @@ -8,24 +8,29 @@ #define TYPE float #define SUFFIX f #define EPS FLT_EPSILON #define CLOSE_ATOL 0 #define CLOSE_RTOL 1e-5 #else #ifdef DOUBLE #define TYPE double #define SUFFIX #define EPS DBL_EPSILON #define CLOSE_ATOL 0 #define CLOSE_RTOL 1e-12 #else #ifdef LONGDOUBLE #define TYPE long double #define SUFFIX l #define EPS 50*LDBL_EPSILON #define CLOSE_ATOL 0 #define CLOSE_RTOL 1e-12 #else #error "Define FLOAT or DOUBLE or LONGDOUBLE" #endif #endif #endif const TYPE NZERO = -1.0 * 0.0; #define STRINGIZE_INT(A) #A #define STRINGIZE(A) STRINGIZE_INT(A) @@ -34,14 +39,18 @@ const float NZEROf = -1.0 * 0.0; #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 = cpack(xr, xi); \ TYPE complex e = cpack(er, ei); \ TYPE complex r = ADDSUFFIX(func)(x); \ if (!cisclose(r, e)) { \ ret = 0; \ TEST_PRINTF(func, x, e, r); \ } \ @@ -50,11 +59,11 @@ const float NZEROf = -1.0 * 0.0; #define TEST_UNSPECIFIED2(func, xr, xi, er1, ei1, er2, ei2) \ do { \ TYPE complex x = cpack(xr, xi); \ TYPE complex e1 = cpack(er1, ei1); \ TYPE complex e2 = cpack(er2, ei2); \ TYPE complex r = ADDSUFFIX(func)(x); \ if (!(cisclose(r, e1) || cisclose(r, e2))) { \ ret = 0; \ TEST_PRINTF(func, x, e1, r); \ printf("or"); \ @@ -65,14 +74,14 @@ const float NZEROf = -1.0 * 0.0; #define TEST_UNSPECIFIED4(func, xr, xi, er1, ei1, er2, ei2, er3, ei3, er4, ei4)\ do { \ TYPE complex x = cpack(xr, xi); \ TYPE complex e1 = cpack(er1, ei1); \ TYPE complex e2 = cpack(er2, ei2); \ TYPE complex e3 = cpack(er3, ei3); \ TYPE complex e4 = cpack(er4, ei4); \ TYPE complex r = func(x); \ if (!(cisclose(r, e1) || cisclose(r, e2) \ || cisclose(r, e3) || cisclose(r, e4))) { \ ret = 0; \ TEST_PRINTF(func, x, e1, r); \ printf("or"); \ @@ -85,65 +94,114 @@ const float NZEROf = -1.0 * 0.0; } \ while(0) #define TEST_CPOW(xr, xi, yr, yi, er, ei) \ do { \ TYPE complex x = cpack(xr, xi); \ TYPE complex y = cpack(yr, yi); \ TYPE complex e = cpack(er, ei); \ TYPE complex r = ADDSUFFIX(cpow)(x, y); \ if (!cisclose(r, e)) { \ ret = 0; \ printf("%d: " STRINGIZE(cpow) STRINGIZE(SUFFIX) "(%.16e + %.16ej," \ " %.16e + %.16ej): expected: %.16e + %.16ej: received: " \ "%.16e + %.16ej\n", __LINE__, ADDSUFFIX(creal)(x), \ ADDSUFFIX(cimag)(x), ADDSUFFIX(creal)(y), \ ADDSUFFIX(cimag)(y), ADDSUFFIX(creal)(e), \ ADDSUFFIX(cimag)(e), ADDSUFFIX(creal)(r), \ ADDSUFFIX(cimag)(r)); \ } \ } \ while(0) #define TEST_RAISES(func, xr, xi, er, ei, fpe) \ do { \ int except; \ TYPE complex r; \ TYPE complex x = cpack(xr, xi); \ TYPE complex e = cpack(er, ei); \ feclearexcept(FE_ALL_EXCEPT); \ r = ADDSUFFIX(func)(x); \ except = fetestexcept(fpe); \ if (!(except & fpe && cisclose(r, e))) { \ ret = 0; \ TEST_PRINTF(func, x, e, r); \ } \ } \ while(0) #define TEST_RAISES_UNSPECIFIED2(func, xr, xi, er1, ei1, er2, ei2, fpe) \ do { \ int except; \ TYPE complex r; \ TYPE complex x = cpack(xr, xi); \ TYPE complex e1 = cpack(er1, ei1); \ TYPE complex e2 = cpack(er2, ei2); \ feclearexcept(FE_ALL_EXCEPT); \ r = ADDSUFFIX(func)(x); \ except = fetestexcept(fpe); \ if (!(except & fpe && (cisclose(r, e1) || cisclose(r, e2)))) { \ ret = 0; \ TEST_PRINTF(func, x, e1, r); \ printf("or"); \ TEST_PRINTF(func, x, e2, r); \ } \ } \ while(0) #define TEST_BRANCH_CUT(func, xr, xi, dxr, dxi, rsign, isign, cksignzero) \ do { \ TYPE complex x = cpack(xr, xi); \ TYPE complex dx = cpack(dxr, dxi); \ int q = check_branch_cut(ADDSUFFIX(func), x, dx, \ rsign, isign, cksignzero); \ if (!q) { \ ret = 0; \ printf(STRINGIZE(func) STRINGIZE(SUFFIX) ": branch cut failure: " \ "x = %.16g + %.16gj, dx = %.16g + %.16gj, rsign = %d, " \ "isign = %d, check_sign_zero = %d\n", creal(x), cimag(x), \ creal(dx), cimag(dx), rsign, isign, cksignzero); \ } \ } \ while(0) #define TEST_LOSS_OF_PRECISION(cfunc, rfunc, real) \ do { \ if (!check_loss_of_precision(ADDSUFFIX(cfunc), ADDSUFFIX(rfunc), real, \ STRINGIZE(cfunc) STRINGIZE(SUFFIX))) { \ ret = 0; \ } \ if (!check_near_crossover(ADDSUFFIX(cfunc), \ STRINGIZE(cfunc) STRINGIZE(SUFFIX))) { \ ret = 0; \ } \ } \ while(0) TYPE complex cpack(TYPE r, TYPE i) { union { TYPE complex z; TYPE a[2]; } z1; z1.a[0] = r; z1.a[1] = i; return z1.z; } int isclose(TYPE a, TYPE b) { const TYPE atol = CLOSE_ATOL; const TYPE rtol = CLOSE_RTOL; TYPE signa = ADDSUFFIX(copysign)(1.0, a); TYPE signb = ADDSUFFIX(copysign)(1.0, b); if (isfinite(a) && isfinite(b)) { if (ADDSUFFIX(fabs)(a - b) <= (atol + rtol*ADDSUFFIX(fabs)(b))) { if (b == 0 && signb < 0) { return (signa == signb); } } } else if (isinf(a) && isinf(b)) { return (signa == signb); @@ -153,96 +211,76 @@ int isclose(double a, double b) } } int cisclose(TYPE complex a, TYPE complex b) { TYPE ar = ADDSUFFIX(creal)(a); TYPE ai = ADDSUFFIX(cimag)(a); TYPE br = ADDSUFFIX(creal)(b); TYPE bi = ADDSUFFIX(cimag)(b); return isclose(ar, br) && isclose(ai, bi); } typedef TYPE complex (*complexfunc)(TYPE complex); typedef TYPE (*realfunc)(TYPE); int check_branch_cut(complexfunc cfunc, TYPE complex x0, TYPE complex dx, int re_sign, int im_sign, int sig_zero_ok) { const TYPE scale = EPS * 1e3; const TYPE atol = 1e-4; TYPE complex shift = dx*scale*ADDSUFFIX(cabs)(x0)/ADDSUFFIX(cabs)(dx); TYPE complex y0 = cfunc(x0); TYPE complex yp = cfunc(x0 + shift); TYPE complex ym = cfunc(x0 - shift); TYPE y0r, y0i, ypr, ypi, ymr, ymi; y0r = ADDSUFFIX(creal)(y0); y0i = ADDSUFFIX(cimag)(y0); ypr = ADDSUFFIX(creal)(yp); ypi = ADDSUFFIX(cimag)(yp); ymr = ADDSUFFIX(creal)(ym); ymi = ADDSUFFIX(cimag)(ym); if (ADDSUFFIX(fabs)(y0r - ypr) >= atol) return 0; if (ADDSUFFIX(fabs)(y0i - ypi) >= atol) return 0; if (ADDSUFFIX(fabs)(y0r - re_sign*ymr) >= atol) return 0; if (ADDSUFFIX(fabs)(y0i - im_sign*ymi) >= atol) return 0; if (sig_zero_ok) { if (ADDSUFFIX(creal)(x0) == 0 && ADDSUFFIX(creal)(dx) != 0) { x0 = cpack(NZERO, ADDSUFFIX(cimag)(x0)); ym = cfunc(x0); ymr = ADDSUFFIX(creal)(ym); ymi = ADDSUFFIX(cimag)(ym); if (ADDSUFFIX(fabs)(y0r - re_sign*ymr) >= atol) return 0; if (ADDSUFFIX(fabs)(y0i - im_sign*ymi) >= atol) return 0; } else if (ADDSUFFIX(cimag)(x0) == 0 && ADDSUFFIX(cimag)(dx) != 0) { x0 = cpack(ADDSUFFIX(creal)(x0), NZERO); ym = cfunc(x0); ymr = ADDSUFFIX(creal)(ym); ymi = ADDSUFFIX(cimag)(ym); if (ADDSUFFIX(fabs)(y0r - re_sign*ymr) >= atol) return 0; if (ADDSUFFIX(fabs)(y0i - im_sign*ymi) >= atol) return 0; } } return 1; } int check_near_crossover(complexfunc cfunc, const char* fname) { const TYPE x = 1e-3; const int rpnt[] = {-1, -1, -1, 0, 0, 1, 1, 1}; @@ -260,17 +298,22 @@ int check_near_crossover(complexfunc cfunc) drj = 2 * x * dr[j] * EPS; dij = 2 * x * di[j] * EPS; for (k = 0; k < npnt; k++) { zp = cpack(x*rpnt[k] + drj, x*ipnt[k] + dij); zm = 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(fname); printf(": Loss of precision: 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; } @@ -279,26 +322,27 @@ int check_near_crossover(complexfunc cfunc) return 1; } int clp_internal(complexfunc cfunc, realfunc rfunc, int real, TYPE x) { TYPE num = rfunc(x); TYPE den; TYPE complex z; if (real == 1) { z = cpack(x, 0); z = cfunc(z); den = ADDSUFFIX(creal)(z); } else { z = 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 char* fname) { const int n_series = 200; const int n_basic = 10; @@ -318,9 +362,10 @@ int check_loss_of_precision(complexfunc cfunc, realfunc rfunc, int real) for(k = 0; k < n_series; k++) { x = ADDSUFFIX(pow)(10.0, xsb + k*dxs); ratio = clp_internal(cfunc, rfunc, real, x); if (ratio > rtol) { printf(fname); printf(": Loss of precision vs real:\n"); printf("x = %.16e\n", x); printf("ratio = %.16e\n", ratio); ret = 0; @@ -329,18 +374,19 @@ int check_loss_of_precision(complexfunc cfunc, realfunc rfunc, int real) for(k = 0; k < n_basic; k++) { x = ADDSUFFIX(pow)(10.0, xbb + k*dxb); ratio = clp_internal(cfunc, rfunc, real, x); if (ratio > rtol) { printf(fname); printf(": Loss of precision vs. real:\n"); printf("x = %.16e\n", x); printf("ratio = %.16e\n", ratio); ret = 0; } } return ret; } #ifdef CACOS int test_cacos() { int ret = 1; @@ -385,9 +431,18 @@ int test_cacos() TEST(cacos, NAN, NAN, NAN, NAN); TEST_BRANCH_CUT(cacos, -2, 0, 0, 1, 1, -1, 1); TEST_BRANCH_CUT(cacos, 2, 0, 0, -1, 1, -1, 1); TEST_BRANCH_CUT(cacos, 0, -2, 1, 0, 1, 1, 1); TEST_BRANCH_CUT(cacos, 0, 2, 1, 0, 1, 1, 1); TEST(cacos, .5, 0, ADDSUFFIX(acos)(0.5), 0); return ret; } #endif #ifdef CASIN int test_casin() { int ret = 1; @@ -433,23 +488,22 @@ int test_casin() TEST(casin, NAN, NAN, NAN, NAN); TEST_LOSS_OF_PRECISION(casin, asin, 0); TEST(casin, 1e-5, 1e-5, 9.999999999666666667e-6, 1.0000000000333333333e-5); TEST_BRANCH_CUT(casin, -2, 0, 0, 1, 1, -1, 1); TEST_BRANCH_CUT(casin, 2, 0, 0, -1, 1, -1, 1); TEST_BRANCH_CUT(casin, 0, -2, 1, 0, 1, 1, 1); TEST_BRANCH_CUT(casin, 0, 2, 1, 0, 1, 1, 1); TEST(casin, 0.5, 0, ADDSUFFIX(asin)(0.5), 0); return ret; } #endif #ifdef CATAN int test_catan() { int ret = 1; @@ -499,23 +553,22 @@ int test_catan() TEST(catan, NAN, NAN, NAN, NAN); TEST_LOSS_OF_PRECISION(catan, atan, 0); TEST(catan, 1e-5, 1e-5, 1.000000000066666666e-5, 9.999999999333333333e-6); TEST_BRANCH_CUT(catan, 0, -2, 1, 0, -1, 1, 1); TEST_BRANCH_CUT(catan, 0, 2, -1, 0, -1, 1, 1); TEST_BRANCH_CUT(catan, -2, 0, 0, 1, 1, 1, 1); TEST_BRANCH_CUT(catan, 2, 0, 0, 1, 1, 1, 1); TEST(catan, 0.5, 0, ADDSUFFIX(catan)(0.5), 0); return ret; } #endif #ifdef CACOSH int test_cacosh() { int ret = 1; @@ -556,9 +609,18 @@ int test_cacosh() TEST(cacosh, NAN, NAN, NAN, NAN); TEST_BRANCH_CUT(cacosh, -1, 0, 0, 1, 1, -1, 1); TEST_BRANCH_CUT(cacosh, 0.5, 0, 0, 1, 1, -1, 1); TEST_BRANCH_CUT(cacosh, 0, -2, 1, 0, 1, 1, 1); TEST_BRANCH_CUT(cacosh, 0, 2, 1, 0, 1, 1, 1); TEST_BRANCH_CUT(cacosh, 2, 0, 0, 1, 1, 1, 1); TEST(cacosh, 0.5, 0, ADDSUFFIX(acosh)(1.5), 0); return ret; } #endif #ifdef CASINH int test_casinh() { int ret = 1; @@ -603,24 +665,23 @@ int test_casinh() TEST(casinh, NAN, NAN, NAN, NAN); TEST_LOSS_OF_PRECISION(casinh, asinh, 1); TEST(casinh, 1e-5, 1e-5, 1.0000000000333333333e-5, 9.999999999666666667e-6); TEST_BRANCH_CUT(casinh, 0, -2, -1, 0, -1, 1, 1); TEST_BRANCH_CUT(casinh, 0, 2, 1, 0, -1, 1, 1); TEST_BRANCH_CUT(casinh, -2, 0, 0, 1, 1, 1, 1); TEST_BRANCH_CUT(casinh, 2, 0, 0, 1, 1, 1, 1); TEST_BRANCH_CUT(casinh, 0, 0, 1, 0, 1, 1, 1); TEST(casinh, 0.5, 0, ADDSUFFIX(asinh)(0.5), 0); return ret; } #endif #ifdef CATANH int test_catanh() { int ret = 1; @@ -671,23 +732,23 @@ int test_catanh() /* TEST(catanh, NAN, INFINITY, 0, M_PI_2); */ TEST(catanh, NAN, NAN, NAN, NAN); TEST_LOSS_OF_PRECISION(catanh, atanh, 1); TEST(catanh, 1e-5, 1e-5, 9.999999999333333333e-6, 1.000000000066666666e-5); TEST_BRANCH_CUT(catanh, -2, 0, 0, 1, 1, -1, 1); TEST_BRANCH_CUT(catanh, 2, 0, 0, -1, 1, -1, 1); TEST_BRANCH_CUT(catanh, 0, -2, 1, 0, 1, 1, 1); TEST_BRANCH_CUT(catanh, 0, 2, 1, 0, 1, 1, 1); TEST_BRANCH_CUT(catanh, 0, 0, 0, 1, 1, 1, 1); TEST(catanh, 0.5, 0, ADDSUFFIX(atanh)(0.5), 0); return ret; } #endif #ifdef CCOS int test_ccos() { int ret = 1; @@ -698,7 +759,8 @@ int test_ccos() TEST(ccos, 0, NZERO, 1, 0); /* sign of imaginary part is unspecified */ TEST_RAISES_UNSPECIFIED2(ccos, -INFINITY, 0, NAN, 0, \ NAN, NZERO, FE_INVALID); /* sign of imaginary part is unspecified */ TEST_UNSPECIFIED2(ccos, NAN, 0, NAN, 0, NAN, NZERO); @@ -736,7 +798,8 @@ int test_ccos() TEST(ccos, 5.0, -INFINITY, INFINITY, -INFINITY); /* sign of real part is unspecified */ TEST_RAISES_UNSPECIFIED2(ccos, -INFINITY, INFINITY, INFINITY, NAN, \ -INFINITY, NAN, FE_INVALID); TEST(ccos, NAN, INFINITY, INFINITY, NAN); TEST(ccos, NAN, -INFINITY, INFINITY, NAN); @@ -750,10 +813,14 @@ int test_ccos() TEST(ccos, 2.0, NAN, NAN, NAN); TEST(ccos, NAN, NAN, NAN, NAN); TEST(ccos, 0.5, 0, ADDSUFFIX(cos)(0.5), 0); return ret; } #endif #ifdef CSIN int test_csin() { int ret = 1; @@ -764,7 +831,8 @@ int test_csin() TEST(csin, NZERO, NZERO, NZERO, NZERO); /* sign of imaginary part is unspecified */ TEST_RAISES_UNSPECIFIED2(csin, -INFINITY, 0, NAN, 0, \ NAN, NZERO, FE_INVALID); /* sign of imaginary part is unspecified */ TEST_UNSPECIFIED2(csin, NAN, 0, NAN, 0, NAN, NZERO); @@ -802,7 +870,8 @@ int test_csin() TEST(csin, 5.0, -INFINITY, -INFINITY, -INFINITY); /* sign of imaginary part is unspecified */ TEST_RAISES_UNSPECIFIED2(csin, -INFINITY, INFINITY, NAN, INFINITY, \ NAN, -INFINITY, FE_INVALID); /* sign of imaginary part is unspecified */ TEST_UNSPECIFIED2(csin, NAN, INFINITY, NAN, INFINITY, NAN, -INFINITY); @@ -816,10 +885,14 @@ int test_csin() TEST(csin, 2.0, NAN, NAN, NAN); TEST(csin, NAN, NAN, NAN, NAN); TEST(csin, 0.5, 0, ADDSUFFIX(sin)(0.5), 0); return ret; } #endif #ifdef CTAN int test_ctan() { int ret = 1; @@ -864,9 +937,16 @@ int test_ctan() TEST(ctan, NAN, NAN, NAN, NAN); TEST(ctan, 0.5, 0, ADDSUFFIX(tan)(0.5), 0); TEST(ctan, 0, 1000, 0, 1); TEST(ctan, 0, -1000, 0, -1); return ret; } #endif #ifdef CCOSH int test_ccosh() { int ret = 1; @@ -877,7 +957,8 @@ int test_ccosh() TEST(ccosh, NZERO, NZERO, 1, 0); /* sign of imaginary part is unspecified */ TEST_RAISES_UNSPECIFIED2(ccosh, 0, INFINITY, NAN, 0, \ NAN, NZERO, FE_INVALID); /* sign of imaginary part is unspecified */ TEST_UNSPECIFIED2(ccosh, 0, NAN, NAN, 0, NAN, NZERO); @@ -915,7 +996,8 @@ int test_ccosh() TEST(ccosh, -INFINITY, -5.0, INFINITY, -INFINITY); /* sign of real part is unspecified */ TEST_RAISES_UNSPECIFIED2(ccosh, INFINITY, INFINITY, INFINITY, NAN, \ -INFINITY, NAN, FE_INVALID); TEST(ccosh, INFINITY, NAN, INFINITY, NAN); TEST(ccosh, -INFINITY, NAN, INFINITY, NAN); @@ -930,9 +1012,13 @@ int test_ccosh() TEST(ccosh, NAN, NAN, NAN, NAN); TEST(ccosh, 0.5, 0, ADDSUFFIX(cosh)(0.5), 0); return ret; } #endif #ifdef CSINH int test_csinh() { int ret = 1; @@ -943,7 +1029,8 @@ int test_csinh() TEST(csinh, NZERO, NZERO, NZERO, NZERO); /* sign of real part is unspecified */ TEST_RAISES_UNSPECIFIED2(csinh, 0, INFINITY, 0, NAN, \ NZERO, NAN, FE_INVALID); /* sign of real part is unspecified */ TEST_UNSPECIFIED2(csinh, 0, NAN, 0, NAN, NZERO, NAN); @@ -981,7 +1068,8 @@ int test_csinh() TEST(csinh, -INFINITY, -5.0, -INFINITY, INFINITY); /* sign of real part is unspecified */ TEST_RAISES_UNSPECIFIED2(csinh, INFINITY, INFINITY, INFINITY, NAN, \ -INFINITY, NAN, FE_INVALID); /* sign of real part is unspecified */ TEST_UNSPECIFIED2(csinh, INFINITY, NAN, INFINITY, NAN, -INFINITY, NAN); @@ -995,10 +1083,14 @@ int test_csinh() TEST(csinh, NAN, -2.0, NAN, NAN); TEST(csinh, NAN, NAN, NAN, NAN); TEST(csinh, 0.5, 0, ADDSUFFIX(sinh)(0.5), 0); return ret; } #endif #ifdef CTANH int test_ctanh() { int ret = 1; @@ -1043,9 +1135,16 @@ int test_ctanh() TEST(ctanh, NAN, NAN, NAN, NAN); TEST(ctanh, 0.5, 0, ADDSUFFIX(tanh)(0.5), 0); TEST(ctanh, 1000, 0, 1, 0); TEST(ctanh, -1000, 0, -1, 0); return ret; } #endif #ifdef CEXP int test_cexp() { int ret = 1; @@ -1084,14 +1183,18 @@ int test_cexp() 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_UNSPECIFIED2(cexp, INFINITY, INFINITY, INFINITY, \ NAN, -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); @@ -1105,9 +1208,18 @@ int test_cexp() TEST(cexp, NAN, NAN, NAN, NAN); TEST(cexp, 0.5, 0, ADDSUFFIX(exp)(0.5), 0); TEST(cexp, 1, 0, M_E, 0); TEST(cexp, 0, 1, ADDSUFFIX(cos)(1), ADDSUFFIX(sin)(1)); TEST(cexp, 1, 1, M_E*ADDSUFFIX(cos)(1), M_E*ADDSUFFIX(sin)(1)); return ret; } #endif #ifdef CLOG int test_clog() { int ret = 1; @@ -1147,19 +1259,147 @@ int test_clog() TEST(clog, NAN, -INFINITY, INFINITY, NAN); TEST(clog, NAN, NAN, NAN, NAN); TEST_BRANCH_CUT(clog, -0.5, 0, 0, 1, 1, -1, 1); TEST(clog, 0.5, 0, ADDSUFFIX(log)(0.5), 0); TEST(clog, 1, 0, 0, 0); TEST(clog, 1, 2, 0.80471895621705014, 1.1071487177940904); return ret; } #endif #ifdef CPOW int test_cpow() { int ret = 1; /* there are _no_ annex G values for cpow. */ /* We can check for branch cuts in here */ /* tests from test_umath.py: TestPower: test_power_complex */ TEST_CPOW(1, 2, 0, 0, 1, 0); TEST_CPOW(2, 3, 0, 0, 1, 0); TEST_CPOW(3, 4, 0, 0, 1, 0); TEST_CPOW(1, 2, 1, 0, 1, 2); TEST_CPOW(2, 3, 1, 0, 2, 3); TEST_CPOW(3, 4, 1, 0, 3, 4); TEST_CPOW(1, 2, 2, 0, -3, 4); TEST_CPOW(2, 3, 2, 0, -5, 12); TEST_CPOW(3, 4, 2, 0, -7, 24); TEST_CPOW(1, 2, 3, 0, -11, -2); TEST_CPOW(2, 3, 3, 0, -46, 9); TEST_CPOW(3, 4, 3, 0, -117, 44); TEST_CPOW(1, 2, 4, 0, -7, 24); TEST_CPOW(2, 3, 4, 0, -119, -120); TEST_CPOW(3, 4, 4, 0, -527, -336); TEST_CPOW(1, 2, -1, 0, 1.0/5.0, -2.0/5.0); TEST_CPOW(2, 3, -1, 0, 2.0/13.0, -3.0/13.0); TEST_CPOW(3, 4, -1, 0, 3.0/25.0, -4.0/25.0); TEST_CPOW(1, 2, -2, 0, -3.0/25.0, -4.0/25.0); TEST_CPOW(2, 3, -2, 0, -5.0/169.0, -12.0/169.0); TEST_CPOW(3, 4, -2, 0, -7.0/625.0, -24.0/625.0); TEST_CPOW(1, 2, -3, 0, -11.0/125.0, 2.0/125.0); TEST_CPOW(2, 3, -3, 0, -46.0/2197.0, -9.0/2197.0); TEST_CPOW(3, 4, -3, 0, -117.0/15625.0, -44.0/15625.0); TEST_CPOW(1, 2, 0.5, 0, 1.272019649514069, 0.7861513777574233); TEST_CPOW(2, 3, 0.5, 0, 1.6741492280355401, 0.895977476129838); TEST_CPOW(3, 4, 0.5, 0, 2, 1); TEST_CPOW(1, 2, 14, 0, -76443, 16124); TEST_CPOW(2, 3, 14, 0, 23161315, 58317492); TEST_CPOW(3, 4, 14, 0, 5583548873, 2465133864); TEST_CPOW(0, INFINITY, 1, 0, 0, INFINITY); TEST_CPOW(0, INFINITY, 2, 0, -INFINITY, NAN); TEST_CPOW(0, INFINITY, 3, 0, NAN, NAN); TEST_CPOW(1, INFINITY, 1, 0, 1, INFINITY); TEST_CPOW(1, INFINITY, 2, 0, -INFINITY, INFINITY); TEST_CPOW(1, INFINITY, 3, 0, -INFINITY, NAN); /* tests from test_umath.py: TestPower: test_power_zero */ TEST_CPOW(0, 0, 0.33, 0, 0, 0); TEST_CPOW(0, 0, 0.5, 0, 0, 0); TEST_CPOW(0, 0, 1.0, 0, 0, 0); TEST_CPOW(0, 0, 1.5, 0, 0, 0); TEST_CPOW(0, 0, 2.0, 0, 0, 0); TEST_CPOW(0, 0, 3.0, 0, 0, 0); TEST_CPOW(0, 0, 4.0, 0, 0, 0); TEST_CPOW(0, 0, 5.0, 0, 0, 0); TEST_CPOW(0, 0, 6.6, 0, 0, 0); TEST_CPOW(0, 0, 0, 0, 1, 0); TEST_CPOW(0, 0, 0, 1, NAN, NAN); TEST_CPOW(0, 0, -0.33, 0, NAN, NAN); TEST_CPOW(0, 0, -0.5, 0, NAN, NAN); TEST_CPOW(0, 0, -1.0, 0, NAN, NAN); TEST_CPOW(0, 0, -1.5, 0, NAN, NAN); TEST_CPOW(0, 0, -2.0, 0, NAN, NAN); TEST_CPOW(0, 0, -3.0, 0, NAN, NAN); TEST_CPOW(0, 0, -4.0, 0, NAN, NAN); TEST_CPOW(0, 0, -5.0, 0, NAN, NAN); TEST_CPOW(0, 0, -6.6, 0, NAN, NAN); TEST_CPOW(0, 0, -1, 0.2, NAN, NAN); /* tests from test_umath_complex.py: TestCpow: test_simple * --- skip, duplicating existing tests --- */ /* tests from test_umath_complex.py: TestCpow: test_scalar, test_array * these tests are equilvent for this level. */ TEST_CPOW(1, 0, 1, 0, 1, 0); TEST_CPOW(1, 0, 0, 1, 1, 0); TEST_CPOW(1, 0, -0.5, 1.5, 1, 0); TEST_CPOW(1, 0, 2, 0, 1, 0); TEST_CPOW(1, 0, 3, 0, 1, 0); TEST_CPOW(0, 1, 1, 0, 0, 1); TEST_CPOW(0, 1, 0, 1, exp(-M_PI_2), 0); TEST_CPOW(0, 1, -0.5, 1.5, 0.067019739708273365, 0.067019739708273365); TEST_CPOW(0, 1, 2, 0, -1, 0); TEST_CPOW(0, 1, 3, 0, 0, -1); TEST_CPOW(2, 0, 1, 0, 2, 0); TEST_CPOW(2, 0, 0, 1, cos(M_LN2), sin(M_LN2)); TEST_CPOW(2, 0, 2, 0, 4, 0); TEST_CPOW(2, 0, 3, 0, 8, 0); TEST_CPOW(2.5, 0.375, 1, 0, 2.5, 0.375); TEST_CPOW(2.5, 0.375, 0, 1, 0.51691507509598866, 0.68939360813851125); TEST_CPOW(2.5, 0.375, -0.5, 1.5, 0.12646517347496394, 0.48690593271654437); TEST_CPOW(2.5, 0.375, 2, 0, 391.0/64.0, 15.0/8.0); TEST_CPOW(2.5, 0.375, 3, 0, 1865.0/128.0, 3573.0/512.0); TEST_CPOW(INFINITY, 0, 1, 0, NAN, NAN); TEST_CPOW(INFINITY, 0, 0, 1, NAN, NAN); TEST_CPOW(INFINITY, 0, -0.5, 1.5, NAN, NAN); TEST_CPOW(INFINITY, 0, 2, 0, NAN, NAN); TEST_CPOW(INFINITY, 0, 3, 0, NAN, NAN); TEST_CPOW(NAN, 0, 1, 0, NAN, NAN); TEST_CPOW(NAN, 0, 0, 1, NAN, NAN); TEST_CPOW(NAN, 0, -0.5, 1.5, NAN, NAN); TEST_CPOW(NAN, 0, 2, 0, NAN, NAN); TEST_CPOW(NAN, 0, 3, 0, NAN, NAN); return ret; } #endif #ifdef CSQRT int test_csqrt() { int ret = 1; @@ -1202,27 +1442,70 @@ int test_csqrt() TEST(csqrt, NAN, NAN, NAN, NAN); TEST_BRANCH_CUT(csqrt, -0.5, 0, 0, 1, 1, -1, 1); TEST(csqrt, 0.5, 0, ADDSUFFIX(sqrt)(0.5), 0); TEST(csqrt, 1, 0, 1, 0); TEST(csqrt, 0, 1, M_SQRT2/2.0, M_SQRT2/2.0); TEST(csqrt, -1, 0, 0, 1); TEST(csqrt, 1, 1, 1.0986841134678100, 0.4550898605622273); TEST(csqrt, 1, -1, 1.0986841134678100, -0.4550898605622273); return ret; } #endif int main(int argc, char** argv) { #ifdef CACOS printf("cacos: %d\n\n", test_cacos()); #endif #ifdef CASIN printf("casin: %d\n\n", test_casin()); #endif #ifdef CATAN printf("catan: %d\n\n", test_catan()); #endif #ifdef CACOSH printf("cacosh: %d\n\n", test_cacosh()); #endif #ifdef CASINH printf("casinh: %d\n\n", test_casinh()); #endif #ifdef CATANH printf("catanh: %d\n\n", test_catanh()); #endif #ifdef CCOS printf("ccos: %d\n\n", test_ccos()); #endif #ifdef CSIN printf("csin: %d\n\n", test_csin()); #endif #ifdef CTAN printf("ctan: %d\n\n", test_ctan()); #endif #ifdef CCOSH printf("ccosh: %d\n\n", test_ccosh()); #endif #ifdef CSINH printf("csinh: %d\n\n", test_csinh()); #endif #ifdef CTANH printf("ctanh: %d\n\n", test_ctanh()); #endif #ifdef CEXP printf("cexp: %d\n\n", test_cexp()); #endif #ifdef clog printf("clog: %d\n\n", test_clog()); #endif #ifdef CPOW printf("cpow, %d\n\n", test_cpow()); #endif #ifdef CSQRT printf("csqrt: %d\n\n", test_csqrt()); #endif return 0; } -
ewmoore revised this gist
Sep 19, 2013 . 1 changed file with 1111 additions and 129 deletions.There are no files selected for viewing
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 charactersOriginal file line number Diff line number Diff line change @@ -4,31 +4,102 @@ #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) { @@ -41,13 +112,70 @@ double complex cpack(double r, double 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)); @@ -57,7 +185,7 @@ int isclose(double a, double b) } } int cisclose(double complex a, double complex b) { double ar = creal(a); double ai = cimag(a); @@ -67,16 +195,26 @@ int cd_isclose(double complex a, double complex 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; @@ -95,152 +233,996 @@ int check_branch_cut(double complex (*func)(double complex), double complex x0, 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; } -
ewmoore created this gist
Apr 1, 2013 .There are no files selected for viewing
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 charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,246 @@ #include <fenv.h> #include <float.h> #include <stdio.h> #include <math.h> #include <complex.h> const double NZERO = 1.0 * 0.0; #define STRINGIZE_INT(A) #A #define STRINGIZE(A) STRINGIZE_INT(A) #define TEST_PRINTF(func, x, e, r) printf("%d: " STRINGIZE(func) "(%g + %gj): expected: %g + %gj: received: %g + %gj\n", __LINE__, creal(x), cimag(x), creal(e), cimag(e), creal(r), cimag(r)) #define TEST(func, x, e) do { \ double complex r = func(x); \ if (!cd_isclose(r, e)) { \ ret = 0; \ TEST_PRINTF(func, x, e, r); \ } \ } \ while(0) #define TEST_RAISES(func, x, e, fpe) do { \ int except; \ double complex r; \ feclearexcept(FE_ALL_EXCEPT); \ r = func(x); \ except = fetestexcept(fpe); \ if (!(except & fpe && cd_isclose(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; } int isclose(double a, double b) { double atol = 0.0; double rtol = 1e-7; if (isfinite(a) && isfinite(b)) { return fabs(a - b) <= (atol + rtol*fabs(b)); } else if (isinf(a) && isinf(b)) { return (signbit(a) == signbit(b)); } else { return (isnan(a) && isnan(b)); } } int cd_isclose(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 cd_isnan(double complex x) { return isnan(creal(x)) && isnan(cimag(x)); } int cd_isinf(double complex x) { return isinf(creal(x)) && isinf(cimag(x)); } 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) { /* check that signed zeros also work as a displacement. */ return 0; } return 1; } /* * We assume that if we make it here at all, we have c99 complex support in * the compiler that we are using. * * We define a single test_fname function for each function that will be * tested. These function return 1 if the tests pass and 0 if the tests * fail. These are go/no go tests and which test failed is not reported. */ /*========================================================== * clog *=========================================================*/ #define TEST_CLOG(x, e) TEST(clog, x, e) #define TEST_RAISES_CLOG(x, e, fpe) TEST_RAISES(clog, x, e, fpe) int test_clog() { int ret = 1; const double NZERO = -1.0 * 0.0; /* tests from test_umath.py: TestComplexFunctions: test_it */ TEST_CLOG(0.5, log(0.5)); /* tests from test_umath_complex.py: TestCLog: test_simple */ TEST_CLOG(1, 0); TEST_CLOG(1 + 2*I, 0.80471895621705014 + 1.1071487177940904*I); /* tests from test_umath_complex.py: TestCLog: test_special_values * These are testing the the value in Appendix G. */ TEST_RAISES_CLOG(cpack(NZERO, 0), cpack(-INFINITY, M_PI), FE_DIVBYZERO); TEST_RAISES_CLOG(cpack(0, 0), cpack(-INFINITY, 0), FE_DIVBYZERO); TEST_CLOG(cpack(1, INFINITY), cpack(INFINITY, M_PI_2)); TEST_CLOG(cpack(1, NAN), cpack(NAN, NAN)); /* can raise FE_INVALID or not. */ TEST_CLOG(cpack(-INFINITY, 1), cpack(+INFINITY, M_PI)); TEST_CLOG(cpack(+INFINITY, 1), cpack(+INFINITY, 0)); TEST_CLOG(cpack(-INFINITY, +INFINITY), cpack(INFINITY, 0.75 * M_PI)); TEST_CLOG(cpack(+INFINITY, +INFINITY), cpack(INFINITY, 0.25 * M_PI)); TEST_CLOG(cpack(-INFINITY, NAN), cpack(INFINITY, NAN)); TEST_CLOG(cpack(+INFINITY, NAN), cpack(INFINITY, NAN)); TEST_CLOG(cpack(NAN, 1), cpack(NAN, NAN)); /* can raise FE_INVALID or not */ TEST_CLOG(cpack(NAN, INFINITY), cpack(INFINITY, NAN)); TEST_CLOG(cpack(NAN, NAN), cpack(NAN, NAN)); /* clog(conj(z)) = conj(clog(z)) */ /* tests concerning the sign of nan are not included. */ TEST_RAISES_CLOG(cpack(NZERO, NZERO), cpack(-INFINITY, -M_PI), FE_DIVBYZERO); TEST_RAISES_CLOG(cpack(0, NZERO), cpack(-INFINITY, NZERO), FE_DIVBYZERO); TEST_CLOG(cpack(1, -INFINITY), cpack(INFINITY, -M_PI_2)); TEST_CLOG(cpack(-INFINITY, -1), cpack(+INFINITY, -M_PI)); TEST_CLOG(cpack(+INFINITY, -1), cpack(+INFINITY, NZERO)); TEST_CLOG(cpack(-INFINITY, -INFINITY), cpack(INFINITY, -0.75 * M_PI)); TEST_CLOG(cpack(+INFINITY, -INFINITY), cpack(INFINITY, -0.25 * M_PI)); TEST_CLOG(cpack(NAN, -INFINITY), cpack(INFINITY, NAN)); if(!check_branch_cut(clog, -0.5, 1*I, 1, -1, 0)) { ret = 0; printf("clog branch cut bad!\n"); } if(!check_branch_cut(clog, -0.5, 1*I, 1, -1, 1)) { ret = 0; printf("clog branch cut bad! 2\n"); } return ret; } #undef TEST_CLOG #undef TEST_RAISES_CLOG /*========================================================== * ctanh *=========================================================*/ #define TEST_CTANH(x, e) TEST(ctanh, x, e) #define TEST_RAISES_CTANH(x, e, fpe) TEST_RAISES(ctanh, x, e, fpe) int test_ctanh() { int ret = 1; /**** Test Appendix G special values ****/ TEST_CTANH(cpack(0.0, 0.0), cpack(0.0, 0.0)); TEST_RAISES_CTANH(cpack(1.0, INFINITY), cpack(NAN, NAN), FE_INVALID); /* can raise FE_INVALID or not */ TEST_CTANH(cpack(1.0, NAN), cpack(NAN, NAN)); /* only for positive, nonzero imag part */ TEST_CTANH(cpack(INFINITY, 1.0), cpack(1.0, 0.0)); /* only for positive nonzero imag part */ TEST_CTANH(cpack(INFINITY, 2.0), cpack(1.0, NZERO)); /* signbit(cimag(r)) is unspecified. */ TEST_CTANH(cpack(INFINITY, INFINITY), cpack(1.0, 0.0)); /* signbit(cimag(r)) is unspecified */ TEST_CTANH(cpack(INFINITY, NAN), cpack(1.0, 0.0)); TEST_CTANH(cpack(NAN, 0.0), cpack(NAN, 0.0)); /* can raise FE_INVALID or not */ TEST_CTANH(cpack(NAN, 1.0), cpack(NAN, NAN)); TEST_CTANH(cpack(NAN, NAN), cpack(NAN, NAN)); /* ctanh(conj(z)) = conj(ctanh(z)) */ TEST_CTANH(cpack(0.0, NZERO), cpack(0.0, NZERO)); TEST_RAISES_CTANH(cpack(1.0, -INFINITY), cpack(NAN, NAN), FE_INVALID); TEST_CTANH(cpack(NAN, NZERO), cpack(NAN, NZERO)); /* ctanh is odd */ TEST_CTANH(cpack(NZERO, NZERO), cpack(NZERO, NZERO)); TEST_RAISES_CTANH(cpack(-1.0, INFINITY), cpack(NAN, NAN), FE_INVALID); /* can raise FE_INVALID or not */ TEST_CTANH(cpack(-1.0, NAN), cpack(NAN, NAN)); /* signbit(cimag(r)) is unspecified. */ TEST_CTANH(cpack(-INFINITY, -INFINITY), cpack(-1.0, 0.0)); /* signbit(cimag(r)) is unspecified */ TEST_CTANH(cpack(-INFINITY, NAN), cpack(-1.0, 0.0)); TEST_CTANH(cpack(NAN, NZERO), cpack(NAN, NZERO)); /* can raise FE_INVALID or not */ TEST_CTANH(cpack(NAN, -1.0), cpack(NAN, NAN)); /**** Github Issue 2321: nans for large arguments ****/ TEST_CTANH(cpack(1000.0, 0.0), cpack(1.0, 0.0)); return ret; } #undef TEST_CTANH #undef TEST_RAISES_CTANH int main(int argc, char** argv) { int tclog, tctanh; tclog = test_clog(); printf("clog: %d\n\n", tclog); tctanh = test_ctanh(); printf("ctanh: %d\n\n", tctanh); return 0; }