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

Skip to content

Instantly share code, notes, and snippets.

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

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

Select an option

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

Revisions

  1. ewmoore revised this gist Oct 1, 2013. 1 changed file with 677 additions and 601 deletions.
    1,278 changes: 677 additions & 601 deletions test_c99complex.c
    Original 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 0
    #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, 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_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(func, xr, xi, er, ei) \
    #define TEST_INT(func, xr, xi, er, ei, rtest, itest) \
    do { \
    TYPE complex x = cpack(xr, xi); \
    TYPE complex e = cpack(er, ei); \
    TYPE dxr = xr; \
    TYPE dxi = xi; \
    TYPE der = er; \
    TYPE dei = ei; \
    TYPE complex x = cpack(dxr, dxi); \
    TYPE complex r = ADDSUFFIX(func)(x); \
    if (!cisclose(r, e)) { \
    TYPE rr = ADDSUFFIX(creal)(r); \
    TYPE ri = ADDSUFFIX(cimag)(r); \
    if (!(rtest(rr, der) && itest(ri, dei))) { \
    ret = 0; \
    TEST_PRINTF(func, x, e, r); \
    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 complex x = cpack(xr, xi); \
    TYPE complex e1 = cpack(er1, ei1); \
    TYPE complex e2 = cpack(er2, ei2); \
    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); \
    if (!(cisclose(r, e1) || cisclose(r, e2))) { \
    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, x, e1, r); \
    TEST_PRINTF(func, dxr, dxi, der1, dei1, rr, ri); \
    printf("or"); \
    TEST_PRINTF(func, x, e2, r); \
    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 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 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); \
    if (!(cisclose(r, e1) || cisclose(r, e2) \
    || cisclose(r, e3) || cisclose(r, e4))) { \
    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, x, e1, r); \
    TEST_PRINTF(func, dxr, dxi, der1, dei1, rr, ri); \
    printf("or"); \
    TEST_PRINTF(func, x, e2, r); \
    TEST_PRINTF(func, dxr, dxi, der2, dei2, rr, ri); \
    printf("or"); \
    TEST_PRINTF(func, x, e3, r); \
    TEST_PRINTF(func, dxr, dxi, der3, dei3, rr, ri); \
    printf("or"); \
    TEST_PRINTF(func, x, e4, r); \
    TEST_PRINTF(func, dxr, dxi, der4, dei4, rr, ri); \
    } \
    } \
    while(0)

    #define TEST_CPOW(xr, xi, yr, yi, er, ei) \
    #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 e = cpack(er, ei); \
    TYPE complex r = ADDSUFFIX(cpow)(x, y); \
    if (!cisclose(r, e)) { \
    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) "(%.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)); \
    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 complex e = cpack(er, ei); \
    TYPE rr, ri; \
    feclearexcept(FE_ALL_EXCEPT); \
    r = ADDSUFFIX(func)(x); \
    except = fetestexcept(fpe); \
    if (!(except & fpe && cisclose(r, e))) { \
    rr = ADDSUFFIX(creal)(r); \
    ri = ADDSUFFIX(cimag)(r); \
    if (!(except & fpe && isequal(rr, der) && isequal(ri, dei))) { \
    ret = 0; \
    TEST_PRINTF(func, x, e, r); \
    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 complex e1 = cpack(er1, ei1); \
    TYPE complex e2 = cpack(er2, ei2); \
    TYPE rr, ri; \
    feclearexcept(FE_ALL_EXCEPT); \
    r = ADDSUFFIX(func)(x); \
    except = fetestexcept(fpe); \
    if (!(except & fpe && (cisclose(r, e1) || cisclose(r, e2)))) { \
    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, x, e1, r); \
    TEST_PRINTF(func, dxr, dxi, der1, dei1, rr, ri); \
    printf("or"); \
    TEST_PRINTF(func, x, e2, r); \
    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 complex x = cpack(xr, xi); \
    TYPE complex dx = cpack(dxr, dxi); \
    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, \
    rsign, isign, cksignzero); \
    vrsign, visign, vcksignzero); \
    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); \
    "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;

    TYPE signa = ADDSUFFIX(copysign)(1.0, a);
    TYPE signb = ADDSUFFIX(copysign)(1.0, b);
    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 (ADDSUFFIX(fabs)(a - b) <= (atol + rtol*ADDSUFFIX(fabs)(b))) {
    if (b == 0 && signb < 0) {
    return (signa == signb);
    }
    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 (isinf(a) && isinf(b)) {
    return (signa == signb);
    else if (isnan(a) && isnan(b)) {
    return 1;
    }
    else {
    return (isnan(a) && isnan(b));
    else {/* infs */
    return a == 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);

    @@ -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 = (%.16e + %.16ej) -> (%.16e + %.16ej)\n", \
    printf("zp = (" FMT " + " FMT "j) -> (" FMT " + " FMT "j)\n", \
    ADDSUFFIX(creal)(zp), ADDSUFFIX(cimag)(zp), \
    ADDSUFFIX(creal)(czp), ADDSUFFIX(cimag)(czp));
    printf("zm = (%.16e + %.16ej) -> (%.16e + %.16ej)\n", \
    printf("zm = (" FMT " + " FMT "j) -> (" FMT " + " FMT "j)\n", \
    ADDSUFFIX(creal)(zm), ADDSUFFIX(cimag)(zm), \
    ADDSUFFIX(creal)(czm), ADDSUFFIX(cimag)(czm));
    printf("diff = %.16e, exact match = %d\n", diff, czp == czm);
    printf("diff = " FMT ", exact match = %d\n", diff, czp == czm);
    ret = 0;
    }
    }
    }
    return 1;
    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 = %.16e\n", x);
    printf("ratio = %.16e\n", ratio);
    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 = %.16e\n", x);
    printf("ratio = %.16e\n", ratio);
    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(cacos, 0, 0, M_PI_2, NZERO);
    TEST(cacos, 0, NZERO, M_PI_2, 0);
    TEST_CE(cacos, 0, 0, NPY_PI_2, NZERO);
    TEST_CE(cacos, 0, NZERO, NPY_PI_2, 0);

    TEST(cacos, NZERO, 0, M_PI_2, NZERO);
    TEST(cacos, NZERO, NZERO, M_PI_2, 0);
    TEST_CE(cacos, NZERO, 0, NPY_PI_2, NZERO);
    TEST_CE(cacos, NZERO, NZERO, NPY_PI_2, 0);

    TEST(cacos, 0, NAN, M_PI_2, NAN);
    TEST(cacos, NZERO, NAN, M_PI_2, NAN);
    TEST_CE(cacos, 0, NAN, NPY_PI_2, NAN);
    TEST_CE(cacos, NZERO, NAN, NPY_PI_2, NAN);

    TEST(cacos, 2.0, INFINITY, M_PI_2, -INFINITY);
    TEST(cacos, 2.0, -INFINITY, M_PI_2, INFINITY);
    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(cacos, 2.0, NAN, NAN, NAN);
    TEST_EE(cacos, 2.0, NAN, NAN, NAN);

    TEST(cacos, -INFINITY, 2.0, M_PI, -INFINITY);
    TEST(cacos, -INFINITY, -2.0, M_PI, INFINITY);
    TEST_CE(cacos, -INFINITY, 2.0, NPY_PI, -INFINITY);
    TEST_CE(cacos, -INFINITY, -2.0, NPY_PI, INFINITY);

    TEST(cacos, INFINITY, 2.0, 0, -INFINITY);
    TEST(cacos, INFINITY, -2.0, 0, INFINITY);
    TEST_EE(cacos, INFINITY, 2.0, 0, -INFINITY);
    TEST_EE(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_CE(cacos, -INFINITY, INFINITY, 0.75 * NPY_PI, -INFINITY);
    TEST_CE(cacos, -INFINITY, -INFINITY, 0.75 * NPY_PI, INFINITY);

    TEST(cacos, INFINITY, INFINITY, 0.25 * M_PI, -INFINITY);
    TEST(cacos, INFINITY, -INFINITY, 0.25 * M_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(cacos, NAN, 2.0, NAN, NAN);
    TEST(cacos, NAN, -2.0, NAN, NAN);
    TEST_EE(cacos, NAN, 2.0, NAN, NAN);
    TEST_EE(cacos, NAN, -2.0, NAN, NAN);

    TEST(cacos, NAN, INFINITY, NAN, -INFINITY);
    TEST(cacos, NAN, -INFINITY, NAN, INFINITY);
    TEST_EE(cacos, NAN, INFINITY, NAN, -INFINITY);
    TEST_EE(cacos, NAN, -INFINITY, NAN, INFINITY);

    TEST(cacos, NAN, NAN, NAN, NAN);
    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(cacos, .5, 0, ADDSUFFIX(acos)(0.5), 0);
    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(casin, 0, 0, 0, 0);
    TEST(casin, 0, NZERO, 0, NZERO);
    TEST(casin, NZERO, 0, NZERO, 0);
    TEST(casin, NZERO, NZERO, NZERO, NZERO);
    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(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);
    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(casin, NAN, -2.0, NAN, NAN);
    TEST(casin, NAN, 2.0, NAN, NAN);
    TEST_EE(casin, NAN, -2.0, NAN, NAN);
    TEST_EE(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_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(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_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(casin, NAN, INFINITY, NAN, INFINITY);
    TEST(casin, NAN, -INFINITY, NAN, -INFINITY);
    TEST_EE(casin, NAN, INFINITY, NAN, INFINITY);
    TEST_EE(casin, NAN, -INFINITY, NAN, -INFINITY);

    TEST(casin, 0, NAN, 0, NAN);
    TEST(casin, NZERO, NAN, NZERO, NAN);
    TEST_EE(casin, 0, NAN, 0, NAN);
    TEST_EE(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);
    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(casin, NAN, NAN, NAN, NAN);
    TEST_EE(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_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(casin, 0.5, 0, ADDSUFFIX(asin)(0.5), 0);
    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(catan, 0, 0, 0, 0);
    TEST(catan, 0, NZERO, 0, NZERO);
    TEST(catan, NZERO, 0, NZERO, 0);
    TEST(catan, NZERO, NZERO, NZERO, NZERO);
    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(catan, NAN, 0, NAN, 0);
    TEST(catan, NAN, NZERO, NAN, 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(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);
    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(catan, NAN, -2.0, NAN, NAN);
    TEST(catan, NAN, 2.0, NAN, NAN);
    TEST_EE(catan, NAN, -2.0, NAN, NAN);
    TEST_EE(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_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(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_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(catan, NAN, INFINITY, NAN, 0);
    TEST(catan, NAN, -INFINITY, NAN, NZERO);
    TEST_EE(catan, NAN, INFINITY, NAN, 0);
    TEST_EE(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);
    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, -M_PI_2, 0, -M_PI_2, NZERO);
    TEST_UNSPECIFIED2(catan, INFINITY, NAN, M_PI_2, 0, M_PI_2, NZERO);
    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(catan, NAN, NAN, NAN, NAN);
    TEST_EE(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_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(catan, 0.5, 0, ADDSUFFIX(catan)(0.5), 0);
    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(cacosh, 0, 0, 0, M_PI_2);
    TEST(cacosh, 0, NZERO, 0, -M_PI_2);
    TEST_EC(cacosh, 0, 0, 0, NPY_PI_2);
    TEST_EC(cacosh, 0, NZERO, 0, -NPY_PI_2);

    TEST(cacosh, NZERO, 0, 0, M_PI_2);
    TEST(cacosh, NZERO, NZERO, 0, -M_PI_2);
    TEST_EC(cacosh, NZERO, 0, 0, NPY_PI_2);
    TEST_EC(cacosh, NZERO, NZERO, 0, -NPY_PI_2);

    TEST(cacosh, 2.0, INFINITY, INFINITY, M_PI_2);
    TEST(cacosh, 2.0, -INFINITY, INFINITY, -M_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(cacosh, 2.0, NAN, NAN, NAN);
    TEST_EE(cacosh, 2.0, NAN, NAN, NAN);

    TEST(cacosh, -INFINITY, 2.0, INFINITY, M_PI);
    TEST(cacosh, -INFINITY, -2.0, INFINITY, -M_PI);
    TEST_EC(cacosh, -INFINITY, 2.0, INFINITY, NPY_PI);
    TEST_EC(cacosh, -INFINITY, -2.0, INFINITY, -NPY_PI);

    TEST(cacosh, INFINITY, 2.0, INFINITY, 0);
    TEST(cacosh, INFINITY, -2.0, INFINITY, NZERO);
    TEST_EE(cacosh, INFINITY, 2.0, INFINITY, 0);
    TEST_EE(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_EC(cacosh, -INFINITY, INFINITY, INFINITY, 0.75*NPY_PI);
    TEST_EC(cacosh, -INFINITY, -INFINITY, INFINITY, -0.75*NPY_PI);

    TEST(cacosh, INFINITY, INFINITY, INFINITY, 0.25*M_PI);
    TEST(cacosh, INFINITY, -INFINITY, INFINITY, -0.25*M_PI);
    TEST_EC(cacosh, INFINITY, INFINITY, INFINITY, 0.25*NPY_PI);
    TEST_EC(cacosh, INFINITY, -INFINITY, INFINITY, -0.25*NPY_PI);

    TEST(cacosh, INFINITY, NAN, INFINITY, NAN);
    TEST(cacosh, -INFINITY, NAN, INFINITY, NAN);
    TEST_EE(cacosh, INFINITY, NAN, INFINITY, NAN);
    TEST_EE(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_EE(cacosh, NAN, 2.0, NAN, NAN);
    TEST_EE(cacosh, NAN, -2.0, NAN, NAN);

    TEST(cacosh, NAN, INFINITY, INFINITY, NAN);
    TEST(cacosh, NAN, -INFINITY, INFINITY, NAN);
    TEST_EE(cacosh, NAN, INFINITY, INFINITY, NAN);
    TEST_EE(cacosh, NAN, -INFINITY, INFINITY, NAN);

    TEST(cacosh, NAN, NAN, NAN, 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(cacosh, 0.5, 0, ADDSUFFIX(acosh)(1.5), 0);
    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(casinh, 0, 0, 0, 0);
    TEST(casinh, 0, NZERO, 0, NZERO);
    TEST(casinh, NZERO, 0, NZERO, 0);
    TEST(casinh, NZERO, NZERO, NZERO, NZERO);
    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(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);
    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(casinh, 2.0, NAN, NAN, NAN);
    TEST(casinh, -2.0, NAN, NAN, NAN);
    TEST_EE(casinh, 2.0, NAN, NAN, NAN);
    TEST_EE(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_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(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_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(casinh, INFINITY, NAN, INFINITY, NAN);
    TEST(casinh, -INFINITY, NAN, -INFINITY, NAN);
    TEST_EE(casinh, INFINITY, NAN, INFINITY, NAN);
    TEST_EE(casinh, -INFINITY, NAN, -INFINITY, NAN);

    TEST(casinh, NAN, 0, NAN, 0);
    TEST(casinh, NAN, NZERO, NAN, NZERO);
    TEST_EE(casinh, NAN, 0, NAN, 0);
    TEST_EE(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);
    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(casinh, NAN, NAN, NAN, NAN);
    TEST_EE(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_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(casinh, 0.5, 0, ADDSUFFIX(asinh)(0.5), 0);
    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(catanh, 0, 0, 0, 0);
    TEST(catanh, 0, NZERO, 0, NZERO);
    TEST(catanh, NZERO, 0, NZERO, 0);
    TEST(catanh, NZERO, NZERO, NZERO, NZERO);
    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(catanh, 0, NAN, 0, NAN);
    TEST(catanh, NZERO, NAN, NZERO, NAN);
    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(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);
    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(catanh, 2.0, NAN, NAN, NAN);
    TEST(catanh, -2.0, NAN, NAN, NAN);
    TEST_EE(catanh, 2.0, NAN, NAN, NAN);
    TEST_EE(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_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(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_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(catanh, INFINITY, NAN, 0, NAN);
    TEST(catanh, -INFINITY, NAN, NZERO, NAN);
    TEST_EE(catanh, INFINITY, NAN, 0, NAN);
    TEST_EE(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);
    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, M_PI_2, NZERO, M_PI_2);
    TEST_UNSPECIFIED2(catanh, NAN, -INFINITY, 0, -M_PI_2, NZERO, -M_PI_2);
    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, M_PI_2); */
    TEST(catanh, NAN, NAN, NAN, NAN);
    /* TEST(catanh, NAN, INFINITY, 0, NPY_PI_2); */
    TEST_EE(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_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(catanh, 0.5, 0, ADDSUFFIX(atanh)(0.5), 0);
    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(ccos, NZERO, 0, 1, 0);
    TEST(ccos, 0, 0, 1, NZERO);
    TEST(ccos, NZERO, NZERO, 1, NZERO);
    TEST(ccos, 0, NZERO, 1, 0);
    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(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);
    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(ccos, NAN, INFINITY, INFINITY, NAN);
    TEST(ccos, NAN, -INFINITY, INFINITY, NAN);
    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(ccos, -2.0, NAN, NAN, NAN);
    TEST(ccos, 2.0, NAN, NAN, NAN);
    TEST_EE(ccos, -2.0, NAN, NAN, NAN);
    TEST_EE(ccos, 2.0, NAN, NAN, NAN);

    TEST(ccos, NAN, NAN, NAN, NAN);
    TEST_EE(ccos, NAN, NAN, NAN, NAN);

    TEST(ccos, 0.5, 0, ADDSUFFIX(cos)(0.5), 0);
    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(csin, 0, 0, 0, 0);
    TEST(csin, 0, NZERO, 0, NZERO);
    TEST(csin, NZERO, 0, NZERO, 0);
    TEST(csin, NZERO, NZERO, NZERO, NZERO);
    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(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);
    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(csin, 0, NAN, 0, NAN);
    TEST(csin, NZERO, NAN, NZERO, NAN);
    TEST_EE(csin, 0, NAN, 0, NAN);
    TEST_EE(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_EE(csin, -2.0, NAN, NAN, NAN);
    TEST_EE(csin, 2.0, NAN, NAN, NAN);

    TEST(csin, NAN, NAN, NAN, NAN);
    TEST_EE(csin, NAN, NAN, NAN, NAN);

    TEST(csin, 0.5, 0, ADDSUFFIX(sin)(0.5), 0);
    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(ctan, 0, 0, 0, 0);
    TEST(ctan, 0, NZERO, 0, NZERO);
    TEST(ctan, NZERO, 0, NZERO, 0);
    TEST(ctan, NZERO, NZERO, NZERO, NZERO);
    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(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);
    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(ctan, 0, NAN, 0, NAN);
    TEST(ctan, NZERO, NAN, NZERO, NAN);
    TEST_EE(ctan, 0, NAN, 0, NAN);
    TEST_EE(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_EE(ctan, 2.0, NAN, NAN, NAN);
    TEST_EE(ctan, -2.0, NAN, NAN, NAN);

    TEST(ctan, NAN, NAN, NAN, NAN);
    TEST_EE(ctan, NAN, NAN, NAN, NAN);

    TEST(ctan, 0.5, 0, ADDSUFFIX(tan)(0.5), 0);
    TEST_CC(ctan, 0.5, 0, ADDSUFFIX(tan)(0.5), 0);

    TEST(ctan, 0, 1000, 0, 1);
    TEST(ctan, 0, -1000, 0, -1);
    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(ccosh, 0, 0, 1, 0);
    TEST(ccosh, 0, NZERO, 1, NZERO);
    TEST(ccosh, NZERO, 0, 1, NZERO);
    TEST(ccosh, NZERO, NZERO, 1, 0);
    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(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);
    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(ccosh, INFINITY, NAN, INFINITY, NAN);
    TEST(ccosh, -INFINITY, NAN, INFINITY, NAN);
    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(ccosh, NAN, 2.0, NAN, NAN);
    TEST(ccosh, NAN, -2.0, NAN, NAN);
    TEST_EE(ccosh, NAN, 2.0, NAN, NAN);
    TEST_EE(ccosh, NAN, -2.0, NAN, NAN);

    TEST(ccosh, NAN, NAN, NAN, NAN);
    TEST_EE(ccosh, NAN, NAN, NAN, NAN);

    TEST(ccosh, 0.5, 0, ADDSUFFIX(cosh)(0.5), 0);
    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(csinh, 0, 0, 0, 0);
    TEST(csinh, 0, NZERO, 0, NZERO);
    TEST(csinh, NZERO, 0, NZERO, 0);
    TEST(csinh, NZERO, NZERO, NZERO, NZERO);
    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(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);
    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(csinh, NAN, 0, NAN, 0);
    TEST(csinh, NAN, NZERO, NAN, NZERO);
    TEST_EE(csinh, NAN, 0, NAN, 0);
    TEST_EE(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_EE(csinh, NAN, 2.0, NAN, NAN);
    TEST_EE(csinh, NAN, -2.0, NAN, NAN);

    TEST(csinh, NAN, NAN, NAN, NAN);
    TEST_EE(csinh, NAN, NAN, NAN, NAN);

    TEST(csinh, 0.5, 0, ADDSUFFIX(sinh)(0.5), 0);
    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(ctanh, 0, 0, 0, 0);
    TEST(ctanh, 0, NZERO, 0, NZERO);
    TEST(ctanh, NZERO, 0, NZERO, 0);
    TEST(ctanh, NZERO, NZERO, NZERO, NZERO);
    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(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);
    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(ctanh, NAN, 0, NAN, 0);
    TEST(ctanh, NAN, NZERO, NAN, NZERO);
    TEST_EE(ctanh, NAN, 0, NAN, 0);
    TEST_EE(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_EE(ctanh, NAN, 2.0, NAN, NAN);
    TEST_EE(ctanh, NAN, -2.0, NAN, NAN);

    TEST(ctanh, NAN, NAN, NAN, NAN);
    TEST_EE(ctanh, NAN, NAN, NAN, NAN);

    TEST(ctanh, 0.5, 0, ADDSUFFIX(tanh)(0.5), 0);
    TEST_CC(ctanh, 0.5, 0, ADDSUFFIX(tanh)(0.5), 0);

    TEST(ctanh, 1000, 0, 1, 0);
    TEST(ctanh, -1000, 0, -1, 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(cexp, 0, 0, 1, 0);
    TEST(cexp, 0, NZERO, 1, NZERO);
    TEST_EE(cexp, 0, 0, 1, 0);
    TEST_EE(cexp, 0, NZERO, 1, NZERO);

    TEST(cexp, NZERO, 0, 1, 0);
    TEST(cexp, NZERO, 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(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);
    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(cexp, NAN, 0, NAN, 0);
    TEST(cexp, NAN, NZERO, NAN, NZERO);
    TEST_EE(cexp, NAN, 0, NAN, 0);
    TEST_EE(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);
    TEST_EE(cexp, NAN, 2.0, NAN, NAN);
    TEST_EE(cexp, NAN, -2.0, NAN, NAN);

    TEST(cexp, 0.5, 0, ADDSUFFIX(exp)(0.5), 0);
    TEST_EE(cexp, NAN, NAN, NAN, NAN);

    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));
    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, M_PI, FE_DIVBYZERO);
    TEST_RAISES(clog, NZERO, NZERO, -INFINITY, -M_PI, FE_DIVBYZERO);
    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(clog, 2.0, INFINITY, INFINITY, M_PI_2);
    TEST(clog, 2.0, -INFINITY, INFINITY, -M_PI_2);
    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(clog, 2.0, NAN, NAN, NAN);
    TEST_EE(clog, 2.0, NAN, NAN, NAN);

    TEST(clog, -INFINITY, 2.0, INFINITY, M_PI);
    TEST(clog, -INFINITY, -2.0, INFINITY, -M_PI);
    TEST_EC(clog, -INFINITY, 2.0, INFINITY, NPY_PI);
    TEST_EC(clog, -INFINITY, -2.0, INFINITY, -NPY_PI);

    TEST(clog, INFINITY, 2.0, INFINITY, 0);
    TEST(clog, INFINITY, -2.0, INFINITY, NZERO);
    TEST_EE(clog, INFINITY, 2.0, INFINITY, 0);
    TEST_EE(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_EC(clog, -INFINITY, INFINITY, INFINITY, 0.75 * NPY_PI);
    TEST_EC(clog, -INFINITY, -INFINITY, INFINITY, -0.75 * NPY_PI);

    TEST(clog, INFINITY, INFINITY, INFINITY, 0.25 * M_PI);
    TEST(clog, INFINITY, -INFINITY, INFINITY, -0.25 * M_PI);
    TEST_EC(clog, INFINITY, INFINITY, INFINITY, 0.25 * NPY_PI);
    TEST_EC(clog, INFINITY, -INFINITY, INFINITY, -0.25 * NPY_PI);

    TEST(clog, INFINITY, NAN, INFINITY, NAN);
    TEST(clog, -INFINITY, NAN, INFINITY, NAN);
    TEST_EE(clog, INFINITY, NAN, INFINITY, NAN);
    TEST_EE(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_EE(clog, NAN, 2.0, NAN, NAN);
    TEST_EE(clog, NAN, -2.0, NAN, NAN);

    TEST(clog, NAN, INFINITY, INFINITY, NAN);
    TEST(clog, NAN, -INFINITY, INFINITY, NAN);
    TEST_EE(clog, NAN, INFINITY, INFINITY, NAN);
    TEST_EE(clog, NAN, -INFINITY, INFINITY, NAN);

    TEST(clog, NAN, NAN, NAN, NAN);
    TEST_EE(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_CC(clog, 0.5, 0, ADDSUFFIX(log)(0.5), 0);

    TEST(clog, 1, 0, 0, 0);
    TEST(clog, 1, 2, 0.80471895621705014, 1.1071487177940904);
    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(1, 2, 0, 0, 1, 0);
    TEST_CPOW(2, 3, 0, 0, 1, 0);
    TEST_CPOW(3, 4, 0, 0, 1, 0);
    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(1, 2, 1, 0, 1, 2);
    TEST_CPOW(2, 3, 1, 0, 2, 3);
    TEST_CPOW(3, 4, 1, 0, 3, 4);
    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(1, 2, 2, 0, -3, 4);
    TEST_CPOW(2, 3, 2, 0, -5, 12);
    TEST_CPOW(3, 4, 2, 0, -7, 24);
    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(1, 2, 3, 0, -11, -2);
    TEST_CPOW(2, 3, 3, 0, -46, 9);
    TEST_CPOW(3, 4, 3, 0, -117, 44);
    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(1, 2, 4, 0, -7, 24);
    TEST_CPOW(2, 3, 4, 0, -119, -120);
    TEST_CPOW(3, 4, 4, 0, -527, -336);
    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(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_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(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_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(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_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(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_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(1, 2, 14, 0, -76443, 16124);
    TEST_CPOW(2, 3, 14, 0, 23161315, 58317492);
    TEST_CPOW(3, 4, 14, 0, 5583548873, 2465133864);
    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(0, INFINITY, 1, 0, 0, INFINITY);
    TEST_CPOW(0, INFINITY, 2, 0, -INFINITY, NAN);
    TEST_CPOW(0, INFINITY, 3, 0, NAN, NAN);
    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(1, INFINITY, 1, 0, 1, INFINITY);
    TEST_CPOW(1, INFINITY, 2, 0, -INFINITY, INFINITY);
    TEST_CPOW(1, INFINITY, 3, 0, -INFINITY, 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(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);
    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(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);
    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(csqrt, 0, 0, 0, 0);
    TEST(csqrt, 0, NZERO, 0, NZERO);
    TEST_EE(csqrt, 0, 0, 0, 0);
    TEST_EE(csqrt, 0, NZERO, 0, NZERO);

    TEST(csqrt, NZERO, 0, 0, 0);
    TEST(csqrt, NZERO, NZERO, 0, NZERO);
    TEST_EE(csqrt, NZERO, 0, 0, 0);
    TEST_EE(csqrt, NZERO, NZERO, 0, NZERO);

    TEST(csqrt, 2.0, INFINITY, INFINITY, INFINITY);
    TEST(csqrt, 2.0, -INFINITY, INFINITY, -INFINITY);
    TEST_EE(csqrt, 2.0, INFINITY, INFINITY, INFINITY);
    TEST_EE(csqrt, 2.0, -INFINITY, INFINITY, -INFINITY);

    TEST(csqrt, NAN, INFINITY, INFINITY, INFINITY);
    TEST(csqrt, NAN, -INFINITY, INFINITY, -INFINITY);
    TEST_EE(csqrt, NAN, INFINITY, INFINITY, INFINITY);
    TEST_EE(csqrt, NAN, -INFINITY, INFINITY, -INFINITY);

    TEST(csqrt, INFINITY, INFINITY, INFINITY, INFINITY);
    TEST(csqrt, INFINITY, -INFINITY, INFINITY, -INFINITY);
    TEST_EE(csqrt, INFINITY, INFINITY, INFINITY, INFINITY);
    TEST_EE(csqrt, INFINITY, -INFINITY, INFINITY, -INFINITY);

    TEST(csqrt, -INFINITY, INFINITY, INFINITY, INFINITY);
    TEST(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(csqrt, 2.0, NAN, NAN, NAN);
    TEST_EE(csqrt, 2.0, NAN, NAN, NAN);

    TEST(csqrt, -INFINITY, 2.0, 0, INFINITY);
    TEST(csqrt, -INFINITY, -2.0, 0, -INFINITY);
    TEST_EE(csqrt, -INFINITY, 2.0, 0, INFINITY);
    TEST_EE(csqrt, -INFINITY, -2.0, 0, -INFINITY);

    TEST(csqrt, INFINITY, 2.0, INFINITY, 0);
    TEST(csqrt, INFINITY, -2.0, INFINITY, NZERO);
    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(csqrt, INFINITY, NAN, INFINITY, NAN);
    TEST_EE(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_EE(csqrt, NAN, 2.0, NAN, NAN);
    TEST_EE(csqrt, NAN, -2.0, NAN, NAN);

    TEST(csqrt, NAN, NAN, NAN, NAN);
    TEST_EE(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_CC(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);
    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
    #ifdef CLOG
    printf("clog: %d\n\n", test_clog());
    #endif
    #ifdef CPOW
  2. ewmoore revised this gist Sep 25, 2013. 1 changed file with 474 additions and 191 deletions.
    665 changes: 474 additions & 191 deletions test_c99complex.c
    Original 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 LDBL_EPSILON
    #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 double NZERO = -1.0 * 0.0;
    const float NZEROf = -1.0 * 0.0;
    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_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 x = cpack(xr, xi); \
    TYPE complex e = cpack(er, ei); \
    TYPE complex r = ADDSUFFIX(func)(x); \
    if (!ADDSUFFIX(cisclose)(r, e)) { \
    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 = ADDSUFFIX(cpack)(xr, xi); \
    TYPE complex e1 = ADDSUFFIX(cpack)(er1, ei1); \
    TYPE complex e2 = ADDSUFFIX(cpack)(er2, ei2); \
    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 (!ADDSUFFIX(cisclose)(r, e1) && !ADDSUFFIX(cisclose)(r, e2)) { \
    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 = 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 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 (!ADDSUFFIX(cisclose)(r, e1) && !ADDSUFFIX(cisclose)(r, e2) \
    && !ADDSUFFIX(cisclose)(r, e3) && !ADDSUFFIX(cisclose)(r, e4)) { \
    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 = ADDSUFFIX(cpack)(xr, xi); \
    TYPE complex e = ADDSUFFIX(cpack)(er, ei); \
    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 && ADDSUFFIX(cisclose)(r, e))) { \
    if (!(except & fpe && cisclose(r, e))) { \
    ret = 0; \
    TEST_PRINTF(func, x, e, r); \
    } \
    } \
    while(0)

    double complex cpack(double r, double i)
    {
    union {
    double complex z;
    double a[2];
    } z1;
    z1.a[0] = r;
    z1.a[1] = i;
    return z1.z;
    }
    #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)

    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;
    }
    #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)

    long double complex cpackl(long double r, long double i)
    #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 {
    long double complex z;
    long double a[2];
    TYPE complex z;
    TYPE a[2];
    } z1;
    z1.a[0] = r;
    z1.a[1] = i;
    return z1.z;
    }

    int isclose(double a, double b)
    int isclose(TYPE a, TYPE b)
    {
    double atol = 0.0;
    double rtol = 1e-12;
    const TYPE atol = CLOSE_ATOL;
    const TYPE rtol = CLOSE_RTOL;

    double signa = copysign(1.0, a);
    double signb = copysign(1.0, b);
    TYPE signa = ADDSUFFIX(copysign)(1.0, a);
    TYPE signb = ADDSUFFIX(copysign)(1.0, b);

    if (isfinite(a) && isfinite(b)) {
    return (fabs(a - b) <= (atol + rtol*fabs(b))) && (signa == signb);
    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 isclosef(float a, float b)
    {
    float atol = 0.0;
    float rtol = 1e-5;

    if (isfinite(a) && isfinite(b)) {
    return (fabsf(a - b) <= (atol + rtol*fabsf(b))) && (copysignf(1.0, a) == copysignf(1.0, b));
    }
    else if (isinf(a) && isinf(b)) {
    return (signbit(a) == signbit(b));
    }
    else {
    return (isnan(a) && isnan(b));
    }
    }

    int isclosel(long double a, long double b)
    {
    long double atol = 0.0;
    long double rtol = 1e-12;

    if (isfinite(a) && isfinite(b)) {
    return (fabsl(a - b) <= (atol + rtol*fabsl(b))) && (copysignl(1.0, a) == copysignl(1.0, b));
    }
    else if (isinf(a) && isinf(b)) {
    return (signbit(a) == signbit(b));
    }
    else {
    return (isnan(a) && isnan(b));
    }
    }

    int cisclose(double complex a, double complex b)
    int cisclose(TYPE complex a, TYPE complex b)
    {
    double ar = creal(a);
    double ai = cimag(a);
    double br = creal(b);
    double bi = cimag(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);
    }

    int cisclosef(float complex a, float complex b)
    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)
    {
    float ar = crealf(a);
    float ai = cimagf(a);
    float br = crealf(b);
    float bi = cimagf(b);
    const TYPE scale = EPS * 1e3;
    const TYPE atol = 1e-4;

    return isclosef(ar, br) && isclose(ai, bi);
    }
    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);

    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);
    TYPE y0r, y0i, ypr, ypi, ymr, ymi;

    return isclosel(ar, br) && isclosel(ai, bi);
    }
    /*
    int check_branch_cut(double complex (*func)(double complex), double complex x0, double complex dx, double re_sign, double im_sign, int sig_zero_ok)
    {
    double scale = DBL_EPSILON * 1e3;
    double atol = 1e-4;
    double complex y0 = func(x0);
    double complex yp = func(x0 + dx*scale*cabs(x0)/cabs(dx));
    double complex ym = func(x0 - dx*scale*cabs(x0)/cabs(dx));
    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 (fabs(creal(y0) - creal(yp)) >= atol)
    if (ADDSUFFIX(fabs)(y0r - ypr) >= atol)
    return 0;
    if (fabs(cimag(y0) - cimag(yp)) >= atol)
    if (ADDSUFFIX(fabs)(y0i - ypi) >= atol)
    return 0;
    if (fabs(creal(y0) - re_sign*creal(ym)) >= atol)
    if (ADDSUFFIX(fabs)(y0r - re_sign*ymr) >= atol)
    return 0;
    if (fabs(cimag(y0) - im_sign*cimag(ym)) >= atol)
    if (ADDSUFFIX(fabs)(y0i - im_sign*ymi) >= atol)
    return 0;

    if (sig_zero_ok) {
    return 0;
    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;
    }
    */
    typedef TYPE complex (*complexfunc)(TYPE complex);
    typedef TYPE (*realfunc)(TYPE);

    int check_near_crossover(complexfunc cfunc)
    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 = ADDSUFFIX(cpack)(x*rpnt[k] + drj, x*ipnt[k] + dij);
    zm = ADDSUFFIX(cpack)(x*rpnt[k] - drj, x*ipnt[k] - dij);
    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("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(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 foo(complexfunc cfunc, realfunc rfunc, int real, TYPE x)
    int clp_internal(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 = cpack(x, 0);
    z = cfunc(z);
    den = ADDSUFFIX(creal)(z);
    }
    else {
    z = ADDSUFFIX(cpack)(0, x);
    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)
    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 = foo(cfunc, rfunc, real, x);
    ratio = clp_internal(cfunc, rfunc, real, x);
    if (ratio > rtol) {
    printf("Loss of precision:\n");
    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 = foo(cfunc, rfunc, real, x);
    ratio = clp_internal(cfunc, rfunc, real, x);
    if (ratio > rtol) {
    printf("Loss of precision:\n");
    printf(fname);
    printf(": Loss of precision vs. real:\n");
    printf("x = %.16e\n", x);
    printf("ratio = %.16e\n", ratio);
    ret = 0;
    return 0;
    }
    }
    return 1;
    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);

    /*
    * loss of precision
    */
    if (!check_loss_of_precision(ADDSUFFIX(casin), ADDSUFFIX(asinh), 0)) {
    printf("loss of precision: casin\n");
    ret = 0;
    }
    TEST_LOSS_OF_PRECISION(casin, asin, 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;
    }
    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);

    /*
    * loss of precision
    */
    if(!check_loss_of_precision(ADDSUFFIX(catan), ADDSUFFIX(atanh), 0)) {
    printf("loss of precision: catan\n");
    ret = 0;
    }
    TEST_LOSS_OF_PRECISION(catan, atan, 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;
    }
    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);

    /*
    * loss of precision
    */
    if(check_loss_of_precision(ADDSUFFIX(casinh), ADDSUFFIX(asinh), 1)) {
    printf("loss of precision: casinh\n");
    ret = 0;
    }
    TEST_LOSS_OF_PRECISION(casinh, asinh, 1);

    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;
    }
    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);

    /*
    * loss of precision
    */
    if(check_loss_of_precision(ADDSUFFIX(catanh), ADDSUFFIX(atanh), 1)) {
    printf("loss of precision: catanh\n");
    ret = 0;
    }
    TEST_LOSS_OF_PRECISION(catanh, atanh, 1);

    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;
    }
    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(ccos, -INFINITY, 0, NAN, 0, FE_INVALID);
    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(ccos, -INFINITY, INFINITY, INFINITY, NAN, FE_INVALID);
    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(csin, -INFINITY, 0, NAN, 0, FE_INVALID);
    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(csin, -INFINITY, INFINITY, NAN, INFINITY, FE_INVALID);
    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(ccosh, 0, INFINITY, NAN, 0, FE_INVALID);
    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(ccosh, INFINITY, INFINITY, INFINITY, NAN, FE_INVALID);
    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(csinh, 0, INFINITY, 0, NAN, FE_INVALID);
    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(csinh, INFINITY, INFINITY, INFINITY, NAN, FE_INVALID);
    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);
    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);
    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);
    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;
    }

  3. ewmoore revised this gist Sep 19, 2013. 1 changed file with 1111 additions and 129 deletions.
    1,240 changes: 1,111 additions & 129 deletions test_c99complex.c
    Original file line number Diff line number Diff line change
    @@ -4,31 +4,102 @@
    #include <math.h>
    #include <complex.h>

    const double NZERO = 1.0 * 0.0;
    #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 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)

    #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-7;
    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 fabs(a - b) <= (atol + rtol*fabs(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 cd_isclose(double complex a, double complex 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 cd_isnan(double complex x)
    int cisclosef(float complex a, float complex b)
    {
    return isnan(creal(x)) && isnan(cimag(x));
    float ar = crealf(a);
    float ai = cimagf(a);
    float br = crealf(b);
    float bi = cimagf(b);

    return isclosef(ar, br) && isclose(ai, bi);
    }

    int cd_isinf(double complex x)
    int cisclosel(long double complex a, long double complex b)
    {
    return isinf(creal(x)) && isinf(cimag(x));
    }
    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) { /* check that signed zeros also work as a displacement. */
    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);

    /*
    * 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.
    */
    /* can raise FE_INVALID or not */
    TEST(cacos, 2.0, NAN, NAN, NAN);

    /*==========================================================
    * clog
    *=========================================================*/
    TEST(cacos, -INFINITY, 2.0, M_PI, -INFINITY);
    TEST(cacos, -INFINITY, -2.0, M_PI, INFINITY);

    #define TEST_CLOG(x, e) TEST(clog, x, e)
    #define TEST_RAISES_CLOG(x, e, fpe) TEST_RAISES(clog, x, e, fpe)
    TEST(cacos, INFINITY, 2.0, 0, -INFINITY);
    TEST(cacos, INFINITY, -2.0, 0, INFINITY);

    int test_clog()
    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;
    const double NZERO = -1.0 * 0.0;
    /* tests from test_umath.py: TestComplexFunctions: test_it

    /* 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
    */
    TEST_CLOG(0.5, log(0.5));
    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);

    /* tests from test_umath_complex.py: TestCLog: test_simple
    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
    */
    TEST_CLOG(1, 0);
    TEST_CLOG(1 + 2*I, 0.80471895621705014 + 1.1071487177940904*I);
    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);

    /* tests from test_umath_complex.py: TestCLog: test_special_values
    * These are testing the the value in Appendix G.
    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
    */
    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));
    if(check_loss_of_precision(ADDSUFFIX(casinh), ADDSUFFIX(asinh), 1)) {
    printf("loss of precision: casinh\n");
    ret = 0;
    }

    /* 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)) {
    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;
    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;
    }

    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;
    }

    #undef TEST_CLOG
    #undef TEST_RAISES_CLOG
    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);

    /*==========================================================
    * ctanh
    *=========================================================*/
    #define TEST_CTANH(x, e) TEST(ctanh, x, e)
    #define TEST_RAISES_CTANH(x, e, fpe) TEST_RAISES(ctanh, x, e, fpe)
    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;

    /**** Test Appendix G special values ****/
    /* 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);

    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));
    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(cpack(NAN, 1.0), cpack(NAN, NAN));
    TEST_CTANH(cpack(NAN, NAN), cpack(NAN, NAN));
    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);

    /* 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));
    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);

    /* ctanh is odd */
    TEST_CTANH(cpack(NZERO, NZERO), cpack(NZERO, NZERO));
    TEST_RAISES_CTANH(cpack(-1.0, INFINITY), cpack(NAN, NAN), FE_INVALID);
    /* 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_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));
    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_CTANH(cpack(NAN, -1.0), cpack(NAN, NAN));
    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);

    /**** Github Issue 2321: nans for large arguments ****/
    TEST_CTANH(cpack(1000.0, 0.0), cpack(1.0, 0.0));
    TEST(clog, NAN, INFINITY, INFINITY, NAN);
    TEST(clog, NAN, -INFINITY, INFINITY, NAN);

    TEST(clog, NAN, NAN, NAN, NAN);

    return ret;
    }

    #undef TEST_CTANH
    #undef TEST_RAISES_CTANH
    int test_cpow()
    {
    int ret = 1;

    int main(int argc, char** argv)
    /* there are _no_ annex G values for cpow. */

    return ret;
    }

    int test_csqrt()
    {
    int tclog, tctanh;
    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);

    tclog = test_clog();
    printf("clog: %d\n\n", tclog);
    /* sign of imaginary part is unspecified */
    TEST_UNSPECIFIED2(csqrt, -INFINITY, NAN, NAN, INFINITY, NAN, -INFINITY);

    TEST(csqrt, INFINITY, NAN, INFINITY, NAN);

    tctanh = test_ctanh();
    printf("ctanh: %d\n\n", tctanh);
    /* 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;
    }

  4. ewmoore created this gist Apr 1, 2013.
    246 changes: 246 additions & 0 deletions test_c99complex.c
    Original 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;
    }