diff options
| author | Jakob Kaivo <jkk@ung.org> | 2019-03-03 21:19:47 -0500 |
|---|---|---|
| committer | Jakob Kaivo <jkk@ung.org> | 2019-03-03 21:19:47 -0500 |
| commit | 8c7cdf31bd692e1697a5a01664717c3b9dbffc59 (patch) | |
| tree | 948e7a2d189f5aba85e0f8be3386424290fdb231 /src/complex | |
| parent | 6eb245579dfdefa0da7f59909bf2e3f8b277c426 (diff) | |
fill out special cases outlined in C18 annex G
Diffstat (limited to 'src/complex')
| -rw-r--r-- | src/complex/cabs.c | 3 | ||||
| -rw-r--r-- | src/complex/cacos.c | 61 | ||||
| -rw-r--r-- | src/complex/cacosh.c | 58 | ||||
| -rw-r--r-- | src/complex/carg.c | 3 | ||||
| -rw-r--r-- | src/complex/casin.c | 2 | ||||
| -rw-r--r-- | src/complex/casinh.c | 51 | ||||
| -rw-r--r-- | src/complex/catan.c | 2 | ||||
| -rw-r--r-- | src/complex/catanh.c | 57 | ||||
| -rw-r--r-- | src/complex/ccos.c | 2 | ||||
| -rw-r--r-- | src/complex/ccosh.c | 62 | ||||
| -rw-r--r-- | src/complex/cexp.c | 68 | ||||
| -rw-r--r-- | src/complex/clog.c | 64 | ||||
| -rw-r--r-- | src/complex/csin.c | 2 | ||||
| -rw-r--r-- | src/complex/csinh.c | 62 | ||||
| -rw-r--r-- | src/complex/csqrt.c | 47 | ||||
| -rw-r--r-- | src/complex/ctan.c | 2 | ||||
| -rw-r--r-- | src/complex/ctanh.c | 58 |
17 files changed, 587 insertions, 17 deletions
diff --git a/src/complex/cabs.c b/src/complex/cabs.c index 3e2d1ac8..f98ec907 100644 --- a/src/complex/cabs.c +++ b/src/complex/cabs.c @@ -1,11 +1,12 @@ # define TGSOURCE "../complex/cabs.c" #include "_tgmath.h" +#include "math.h" #include <complex.h> TYPE TGFN(cabs)(TYPE complex z) { - return z; + return TGFN(hypot)(TGFN(creal)(z), TGFN(cimag)(z)); } /*d diff --git a/src/complex/cacos.c b/src/complex/cacos.c index b669f478..3bfe9d38 100644 --- a/src/complex/cacos.c +++ b/src/complex/cacos.c @@ -1,10 +1,69 @@ # define TGSOURCE "../complex/cacos.c" #include "_tgmath.h" - #include <complex.h> +#include "math.h" +#include "fenv.h" + +#include "../math/M_PI.c" +#include "../math/M_PI_2.c" +#include "../math/M_PI_4.c" TYPE complex TGFN(cacos)(TYPE complex z) { + int classr = fpclassify(TGFN(creal)(z)); + int classi = fpclassify(TGFN(cimag)(z)); + int signr = signbit(TGFN(creal)(z)); + int signi = signbit(TGFN(cimag)(z)); + + if (classr == FP_ZERO && classi == FP_ZERO) { + return TGCMPLX(M_PI_2, 0.0); + } + + if (classr == FP_ZERO && classi == FP_NAN) { + return TGCMPLX(M_PI_2, NAN); + } + + if (classr != FP_INFINITE && classi == FP_INFINITE) { + return TGCMPLX(M_PI_2, INFINITY); + } + + if (classr != FP_ZERO && classr != FP_INFINITE && classi == FP_NAN) { + return TGCMPLX(NAN, NAN); + } + + if (classr == FP_INFINITE && signr && classi != FP_INFINITE && !signi) { + return TGCMPLX(M_PI, -INFINITY); + } + + if (classr == FP_INFINITE && !signr && classi != FP_INFINITE && !signi) { + return TGCMPLX(0.0, -INFINITY); + } + + if (classr == FP_INFINITE && signr && classi == FP_INFINITE) { + return TGCMPLX(3 * M_PI_4, -INFINITY); + } + + if (classr == FP_INFINITE && !signr && classi == FP_INFINITE) { + return TGCMPLX(M_PI_4, -INFINITY); + } + + if (classr == FP_INFINITE && classi == FP_NAN) { + return TGCMPLX(NAN, INFINITY); + } + + if (classr == FP_NAN && classi != FP_INFINITE) { + feraiseexcept(FE_INVALID); + return TGCMPLX(NAN, NAN); + } + + if (classr == NAN && classi == FP_INFINITE) { + return TGCMPLX(NAN, -INFINITY); + } + + if (classr == NAN && classi == NAN) { + return TGCMPLX(NAN, NAN); + } + return z; } diff --git a/src/complex/cacosh.c b/src/complex/cacosh.c index 9f7d6aea..c9a8060d 100644 --- a/src/complex/cacosh.c +++ b/src/complex/cacosh.c @@ -1,10 +1,66 @@ # define TGSOURCE "../complex/cacosh.c" #include "_tgmath.h" - #include <complex.h> +#include "math.h" +#include "fenv.h" + +#include "../math/M_PI.c" +#include "../math/M_PI_2.c" +#include "../math/M_PI_4.c" TYPE complex TGFN(cacosh)(TYPE complex z) { + int classr = fpclassify(TGFN(creal)(z)); + int classi = fpclassify(TGFN(cimag)(z)); + int signr = signbit(TGFN(creal)(z)); + int signi = signbit(TGFN(cimag)(z)); + + if (classr == FP_ZERO && classi == FP_ZERO) { + return TGCMPLX(0.0, M_PI_2); + } + + if (classr != FP_INFINITE && classi == FP_INFINITE) { + return TGCMPLX(INFINITY, M_PI_2); + } + + if (classr == FP_ZERO && classi == FP_NAN) { + return TGCMPLX(NAN, M_PI_2); + } + + if (classr != FP_INFINITE && classr != FP_ZERO && classi == FP_NAN) { + feraiseexcept(FE_INVALID); + return TGCMPLX(NAN, NAN); + } + + if (classr == FP_INFINITE && signr && classi != FP_INFINITE && !signi) { + return TGCMPLX(INFINITY, M_PI); + } + + if (classr == FP_INFINITE && !signr && classi != FP_INFINITE && !signi) { + return TGCMPLX(INFINITY, 0.0); + } + + if (classr == FP_INFINITE && signr && classi == FP_INFINITE) { + return TGCMPLX(INFINITY, 3 * M_PI_4); + } + + if (classr == FP_INFINITE && !signr && classi == FP_INFINITE) { + return TGCMPLX(INFINITY, M_PI_4); + } + + if (classr == FP_INFINITE && classi == FP_NAN) { + return TGCMPLX(INFINITY, NAN); + } + + if (classr == FP_NAN && classi != FP_INFINITE) { + feraiseexcept(FE_INVALID); + return TGCMPLX(NAN, NAN); + } + + if (classr == FP_NAN && classi == FP_INFINITE) { + return TGCMPLX(INFINITY, NAN); + } + return z; } diff --git a/src/complex/carg.c b/src/complex/carg.c index 092b1194..b4e5b0d8 100644 --- a/src/complex/carg.c +++ b/src/complex/carg.c @@ -1,11 +1,12 @@ # define TGSOURCE "../complex/carg.c" #include "_tgmath.h" +#include "math.h" #include <complex.h> TYPE TGFN(carg)(TYPE complex z) { - return z; + return TGFN(atan2)(TGFN(cimag)(z), TGFN(creal)(z)); } /*d diff --git a/src/complex/casin.c b/src/complex/casin.c index 45084641..e26cc76a 100644 --- a/src/complex/casin.c +++ b/src/complex/casin.c @@ -5,7 +5,7 @@ TYPE complex TGFN(casin)(TYPE complex z) { - return z; + return TGCMPLX(0.0, -TGFN(casinh)(I * z)); } /*d diff --git a/src/complex/casinh.c b/src/complex/casinh.c index 9251ce37..8cc39474 100644 --- a/src/complex/casinh.c +++ b/src/complex/casinh.c @@ -1,10 +1,59 @@ # define TGSOURCE "../complex/casinh.c" #include "_tgmath.h" - #include <complex.h> +#include "math.h" +#include "fenv.h" + +#include "../math/M_PI_4.c" TYPE complex TGFN(casinh)(TYPE complex z) { + int classr = fpclassify(TGFN(creal)(z)); + int classi = fpclassify(TGFN(cimag)(z)); + int signr = signbit(TGFN(creal)(z)); + int signi = signbit(TGFN(cimag)(z)); + + if (classr == FP_ZERO && classi == FP_ZERO) { + return TGCMPLX(0.0, 0.0); + } + + if (classr != FP_INFINITE && !signr && classi == FP_INFINITE) { + return TGCMPLX(INFINITY, NAN); + } + + if (classr != FP_INFINITE && classi == FP_NAN) { + return TGCMPLX(NAN, NAN); + } + + if (classr == FP_INFINITE && classi != FP_INFINITE && !signi) { + return TGCMPLX(INFINITY, 0.0); + } + + if (classr == FP_INFINITE && classi == FP_INFINITE) { + return TGCMPLX(INFINITY, M_PI_4); + } + + if (classr == FP_INFINITE && classi == FP_NAN) { + return TGCMPLX(INFINITY, NAN); + } + + if (classr == FP_NAN && classi == FP_ZERO) { + return TGCMPLX(NAN, 0.0); + } + + if (classr == FP_NAN && classi != FP_INFINITE && classi != FP_ZERO) { + feraiseexcept(FE_INVALID); + return TGCMPLX(NAN, NAN); + } + + if (classr == FP_NAN && classi == FP_INFINITE) { + return TGCMPLX(INFINITY, NAN); + } + + if (classr == FP_NAN && classi == FP_NAN) { + return TGCMPLX(NAN, NAN); + } + return z; } diff --git a/src/complex/catan.c b/src/complex/catan.c index 4ae60ce6..bbe06ccb 100644 --- a/src/complex/catan.c +++ b/src/complex/catan.c @@ -5,7 +5,7 @@ TYPE complex TGFN(catan)(TYPE complex z) { - return z; + return TGCMPLX(0.0, -TGFN(catanh)(I * z)); } /*d diff --git a/src/complex/catanh.c b/src/complex/catanh.c index 2be96dfc..198fc5ea 100644 --- a/src/complex/catanh.c +++ b/src/complex/catanh.c @@ -1,10 +1,65 @@ # define TGSOURCE "../complex/catanh.c" #include "_tgmath.h" - #include <complex.h> +#include "math.h" +#include "fenv.h" + +#include "../math/M_PI_2.c" TYPE complex TGFN(catanh)(TYPE complex z) { + int classr = fpclassify(TGFN(creal)(z)); + int classi = fpclassify(TGFN(cimag)(z)); + int signr = signbit(TGFN(creal)(z)); + int signi = signbit(TGFN(cimag)(z)); + + if (classr == FP_ZERO && classi == FP_ZERO) { + return TGCMPLX(0.0, 0.0); + } + + if (classr == FP_ZERO && classi == FP_NAN) { + return TGCMPLX(0.0, NAN); + } + + if (TGFN(creal)(z) == 1.0 && classi == FP_ZERO) { + feraiseexcept(FE_DIVBYZERO); + return TGCMPLX(INFINITY, 0.0); + } + + if (classr != FP_INFINITE && !signr && classi == FP_INFINITE) { + return TGCMPLX(0.0, M_PI_2); + } + + if (classr != FP_INFINITE && !signr && classi == FP_NAN) { + feraiseexcept(FE_INVALID); + return TGCMPLX(NAN, NAN); + } + + if (classr == FP_INFINITE && classi != FP_INFINITE && !signi) { + return TGCMPLX(0.0, M_PI_2); + } + + if (classr == FP_INFINITE && classi == FP_INFINITE) { + return TGCMPLX(0.0, M_PI_2); + } + + if (classr == FP_INFINITE && classi == FP_NAN) { + return TGCMPLX(0.0, NAN); + } + + if (classr == FP_NAN && classi != FP_INFINITE) { + feraiseexcept(FE_INVALID); + return TGCMPLX(NAN, NAN); + } + + if (classr == FP_NAN && classi == FP_INFINITE) { + return TGCMPLX(0.0, M_PI_2); + } + + if (classr == FP_NAN && classi == FP_NAN) { + return TGCMPLX(NAN, NAN); + } + return z; } diff --git a/src/complex/ccos.c b/src/complex/ccos.c index 329c66e7..a6478823 100644 --- a/src/complex/ccos.c +++ b/src/complex/ccos.c @@ -5,7 +5,7 @@ TYPE complex TGFN(ccos)(TYPE complex z) { - return z; + return TGFN(ccosh)(I * z); } /*d diff --git a/src/complex/ccosh.c b/src/complex/ccosh.c index 0e05250a..9725e8d8 100644 --- a/src/complex/ccosh.c +++ b/src/complex/ccosh.c @@ -1,10 +1,70 @@ # define TGSOURCE "../complex/ccosh.c" #include "_tgmath.h" - #include <complex.h> +#include "math.h" +#include "fenv.h" TYPE complex TGFN(ccosh)(TYPE complex z) { + int classr = fpclassify(TGFN(creal)(z)); + int classi = fpclassify(TGFN(cimag)(z)); + //int signr = signbit(TGFN(creal)(z)); + //int signi = signbit(TGFN(cimag)(z)); + + if (classr == FP_ZERO && classi == FP_ZERO) { + return TGCMPLX(1.0, 0.0); + } + + if (classr == FP_ZERO && classi == FP_INFINITE) { + feraiseexcept(FE_INVALID); + return TGCMPLX(NAN, 0.0); + } + + if (classr == FP_ZERO && classi == FP_NAN) { + return TGCMPLX(NAN, 0.0); + } + + if (classr != FP_INFINITE && classr != FP_ZERO && classi == FP_INFINITE) { + feraiseexcept(FE_INVALID); + return TGCMPLX(NAN, NAN); + } + + if (classr != FP_INFINITE && classr != FP_ZERO && classi == FP_NAN) { + feraiseexcept(FE_INVALID); + return TGCMPLX(NAN, NAN); + } + + if (classr == FP_INFINITE && classi == FP_ZERO) { + return TGCMPLX(INFINITY, 0.0); + } + + if (classr == FP_INFINITE && classi != FP_INFINITE && classi != FP_ZERO) { + TYPE y = TGFN(cimag)(z); + return TGCMPLX(TGFN(cos)(y), TGFN(sin)(y)); + } + + if (classr == FP_INFINITE && classi == FP_INFINITE) { + feraiseexcept(FE_INVALID); + return TGCMPLX(INFINITY, NAN); + } + + if (classr == FP_INFINITE && classi == FP_NAN) { + return TGCMPLX(INFINITY, NAN); + } + + if (classr == FP_NAN && classi == FP_ZERO) { + return TGCMPLX(NAN, 0.0); + } + + if (classr == FP_NAN && classi != FP_INFINITE && classi != FP_ZERO) { + feraiseexcept(FE_INVALID); + return TGCMPLX(NAN, NAN); + } + + if (classr == FP_NAN && classi == FP_NAN) { + return TGCMPLX(NAN, NAN); + } + return z; } diff --git a/src/complex/cexp.c b/src/complex/cexp.c index d343a02e..c6d7b537 100644 --- a/src/complex/cexp.c +++ b/src/complex/cexp.c @@ -1,10 +1,76 @@ # define TGSOURCE "../complex/cexp.c" #include "_tgmath.h" - #include <complex.h> +#include "math.h" +#include "fenv.h" TYPE complex TGFN(cexp)(TYPE complex z) { + int classr = fpclassify(TGFN(creal)(z)); + int classi = fpclassify(TGFN(cimag)(z)); + int signr = signbit(TGFN(creal)(z)); + //int signi = signbit(TGFN(cimag)(z)); + + if (classr == FP_ZERO && classi == FP_ZERO) { + return TGCMPLX(1.0, 0.0); + } + + if (classr != FP_INFINITE && classi == FP_INFINITE) { + feraiseexcept(FE_INVALID); + return TGCMPLX(NAN, NAN); + } + + if (classr != FP_INFINITE && classi == FP_NAN) { + feraiseexcept(FE_INVALID); + return TGCMPLX(NAN, NAN); + } + + if (classr == FP_INFINITE && classi == FP_ZERO) { + return TGCMPLX(INFINITY, 0.0); + } + + if (classr == FP_INFINITE && signr && classi != FP_INFINITE) { + TYPE y = TGFN(cimag)(z); + /* FIXME */ + return TGCMPLX(0 * TGFN(cos)(y), TGFN(sin)(y)); + } + + if (classr == FP_INFINITE && !signr && classi != FP_INFINITE && classi != FP_ZERO) { + TYPE y = TGFN(cimag)(z); + /* FIXME */ + return TGCMPLX(INFINITY * TGFN(cos)(y), TGFN(sin)(y)); + } + + if (classr == FP_INFINITE && signr && classi == FP_INFINITE) { + return TGCMPLX(INFINITY, INFINITY); + } + + if (classr == FP_INFINITE && !signr && classi == FP_INFINITE) { + feraiseexcept(FE_INVALID); + return TGCMPLX(INFINITY, NAN); + } + + if (classr == FP_INFINITE && signr && classi == FP_NAN) { + return TGCMPLX(0.0, 0.0); + } + + if (classr == FP_INFINITE && !signr && classi == FP_NAN) { + return TGCMPLX(INFINITY, NAN); + } + + if (classr == FP_NAN && classi == FP_ZERO) { + return TGCMPLX(NAN, 0.0); + } + + if (classr == FP_NAN && classi != FP_ZERO) { + feraiseexcept(FE_INVALID); + return TGCMPLX(NAN, NAN); + } + + if (classr == FP_NAN && classi == FP_NAN) { + return TGCMPLX(NAN, NAN); + } + return z; } diff --git a/src/complex/clog.c b/src/complex/clog.c index ad8ec1da..53c209c1 100644 --- a/src/complex/clog.c +++ b/src/complex/clog.c @@ -1,10 +1,72 @@ # define TGSOURCE "../complex/clog.c" #include "_tgmath.h" - #include <complex.h> +#include "math.h" +#include "fenv.h" + +#include "../math/M_PI.c" +#include "../math/M_PI_2.c" +#include "../math/M_PI_4.c" TYPE complex TGFN(clog)(TYPE complex z) { + int classr = fpclassify(TGFN(creal)(z)); + int classi = fpclassify(TGFN(cimag)(z)); + int signr = signbit(TGFN(creal)(z)); + int signi = signbit(TGFN(cimag)(z)); + + if (classr == FP_ZERO && signr && classi == FP_ZERO) { + feraiseexcept(FE_DIVBYZERO); + return TGCMPLX(-INFINITY, M_PI); + } + + if (classr == FP_ZERO && !signr && classi == FP_ZERO) { + feraiseexcept(FE_DIVBYZERO); + return TGCMPLX(-INFINITY, 0.0); + } + + if (classr != FP_INFINITE && classi == FP_INFINITE) { + return TGCMPLX(INFINITY, M_PI_2); + } + + if (classr != FP_INFINITE && classi == FP_NAN) { + feraiseexcept(FE_INVALID); + return TGCMPLX(NAN, NAN); + } + + if (classr == FP_INFINITE && signr && classi != FP_INFINITE && !signi) { + return TGCMPLX(INFINITY, M_PI); + } + + if (classr == FP_INFINITE && !signr && classi != FP_INFINITE && !signi) { + return TGCMPLX(INFINITY, 0.0); + } + + if (classr == FP_INFINITE && signr && classi == FP_INFINITE) { + return TGCMPLX(INFINITY, 3 * M_PI_4); + } + + if (classr == FP_INFINITE && !signr && classi == FP_INFINITE) { + return TGCMPLX(INFINITY, M_PI_4); + } + + if (classr == FP_INFINITE && classi == FP_NAN) { + return TGCMPLX(INFINITY, NAN); + } + + if (classr == FP_NAN && classi != FP_INFINITE) { + feraiseexcept(FE_INVALID); + return TGCMPLX(NAN, NAN); + } + + if (classr == FP_NAN && classi == FP_INFINITE) { + return TGCMPLX(INFINITY, NAN); + } + + if (classr == FP_NAN && classi == FP_NAN) { + return TGCMPLX(NAN, NAN); + } + return z; } diff --git a/src/complex/csin.c b/src/complex/csin.c index 13006c01..1f96a7a2 100644 --- a/src/complex/csin.c +++ b/src/complex/csin.c @@ -5,7 +5,7 @@ TYPE complex TGFN(csin)(TYPE complex z) { - return z; + return TGCMPLX(0.0, -TGFN(csinh)(I * z)); } /*d diff --git a/src/complex/csinh.c b/src/complex/csinh.c index d1ad8626..9b8e08cd 100644 --- a/src/complex/csinh.c +++ b/src/complex/csinh.c @@ -1,10 +1,70 @@ # define TGSOURCE "../complex/csinh.c" #include "_tgmath.h" - #include <complex.h> +#include "math.h" +#include "fenv.h" TYPE complex TGFN(csinh)(TYPE complex z) { + int classr = fpclassify(TGFN(creal)(z)); + int classi = fpclassify(TGFN(cimag)(z)); + int signr = signbit(TGFN(creal)(z)); + int signi = signbit(TGFN(cimag)(z)); + + if (classr == FP_ZERO && classi == FP_ZERO) { + return TGCMPLX(0.0, 0.0); + } + + if (classr == FP_ZERO && classi == FP_INFINITE) { + feraiseexcept(FE_INVALID); + return TGCMPLX(0.0, NAN); + } + + if (classr == FP_ZERO && classi == FP_NAN) { + return TGCMPLX(0.0, NAN); + } + + if (classr != FP_INFINITE && !signr && classi == FP_INFINITE) { + feraiseexcept(FE_INVALID); + return TGCMPLX(NAN, NAN); + } + + if (classr != FP_INFINITE && classr != FP_ZERO && classi == FP_NAN) { + feraiseexcept(FE_INVALID); + return TGCMPLX(NAN, NAN); + } + + if (classr == FP_INFINITE && classi == FP_ZERO) { + return TGCMPLX(INFINITY, 0.0); + } + + if (classr == FP_INFINITE && classi != FP_INFINITE && !signi) { + TYPE y = TGFN(cimag)(z); + return TGCMPLX(INFINITY * TGFN(cos)(y), TGFN(sin)(y)); + } + + if (classr == FP_INFINITE && classi == FP_INFINITE) { + feraiseexcept(FE_INVALID); + return TGCMPLX(INFINITY, INFINITY); + } + + if (classr == FP_INFINITE && classi == FP_NAN) { + return TGCMPLX(INFINITY, NAN); + } + + if (classr == FP_NAN && classi == FP_ZERO) { + return TGCMPLX(NAN, 0.0); + } + + if (classr == FP_NAN && classi != FP_ZERO) { + feraiseexcept(FE_INVALID); + return TGCMPLX(NAN, NAN); + } + + if (classr == FP_NAN && classi == FP_NAN) { + return TGCMPLX(NAN, NAN); + } + return z; } diff --git a/src/complex/csqrt.c b/src/complex/csqrt.c index f3a735ca..47b4c843 100644 --- a/src/complex/csqrt.c +++ b/src/complex/csqrt.c @@ -1,10 +1,55 @@ # define TGSOURCE "../complex/csqrt.c" #include "_tgmath.h" - #include <complex.h> +#include "math.h" +#include "fenv.h" TYPE complex TGFN(csqrt)(TYPE complex z) { + int classr = fpclassify(TGFN(creal)(z)); + int classi = fpclassify(TGFN(cimag)(z)); + int signr = signbit(TGFN(creal)(z)); + int signi = signbit(TGFN(cimag)(z)); + + if (classr == FP_ZERO && classi == FP_ZERO) { + return TGCMPLX(0.0, 0.0); + } + + if (classi == FP_INFINITE) { + /* for all reals, even NAN */ + return TGCMPLX(INFINITY, INFINITY); + } + + if (classr != FP_INFINITE && classi == FP_NAN) { + feraiseexcept(FE_INVALID); + return TGCMPLX(NAN, NAN); + } + + if (classr == FP_INFINITE && signr && classi != FP_INFINITE && !signi) { + return TGCMPLX(0.0, INFINITY); + } + + if (classr == FP_INFINITE && !signr && classi != FP_INFINITE && !signi) { + return TGCMPLX(INFINITY, 0.0); + } + + if (classr == FP_INFINITE && signr && classi == FP_NAN) { + return TGCMPLX(NAN, INFINITY); + } + + if (classr == FP_INFINITE && !signr && classi == FP_NAN) { + return TGCMPLX(INFINITY, NAN); + } + + if (classr == FP_NAN && classi != FP_INFINITE) { + feraiseexcept(FE_INVALID); + return TGCMPLX(NAN, NAN); + } + + if (classr == FP_NAN && classi == FP_NAN) { + return TGCMPLX(NAN, NAN); + } + return z; } diff --git a/src/complex/ctan.c b/src/complex/ctan.c index 31bbd8c4..0bfb19b7 100644 --- a/src/complex/ctan.c +++ b/src/complex/ctan.c @@ -5,7 +5,7 @@ TYPE complex TGFN(ctan)(TYPE complex z) { - return z; + return TGCMPLX(0.0, -TGFN(ctanh)(I * z)); } /*d diff --git a/src/complex/ctanh.c b/src/complex/ctanh.c index cf203dd5..c787e5ba 100644 --- a/src/complex/ctanh.c +++ b/src/complex/ctanh.c @@ -1,10 +1,66 @@ # define TGSOURCE "../complex/ctanh.c" #include "_tgmath.h" - #include <complex.h> +#include "math.h" +#include "fenv.h" TYPE complex TGFN(ctanh)(TYPE complex z) { + int classr = fpclassify(TGFN(creal)(z)); + int classi = fpclassify(TGFN(cimag)(z)); + //int signr = signbit(TGFN(creal)(z)); + int signi = signbit(TGFN(cimag)(z)); + + if (classr == FP_ZERO && classi == FP_ZERO) { + return TGCMPLX(0.0, 0.0); + } + + if (classr == FP_ZERO && classi == FP_INFINITE) { + feraiseexcept(FE_INVALID); + return TGCMPLX(0.0, NAN); + } + + if (classr != FP_INFINITE && classr != FP_ZERO && classi == FP_INFINITE) { + feraiseexcept(FE_INVALID); + return TGCMPLX(NAN, NAN); + } + + if (classr == FP_ZERO && classi == FP_NAN) { + return TGCMPLX(0.0, NAN); + } + + if (classr != FP_INFINITE && classr != FP_ZERO && classi == FP_NAN) { + feraiseexcept(FE_INVALID); + return TGCMPLX(NAN, NAN); + } + + if (classr == FP_INFINITE && classi != FP_INFINITE && !signi) { + TYPE y = TGFN(cimag)(z); + /* FIXME: this is surely a typo in C18 */ + return TGCMPLX(1.0, 0 * TGFN(sin)(2 * y)); + } + + if (classr == FP_INFINITE && classi == FP_INFINITE) { + return TGCMPLX(1.0, 0.0); + } + + if (classr == FP_INFINITE && classi == FP_NAN) { + return TGCMPLX(1.0, 0.0); + } + + if (classr == FP_NAN && classi == FP_ZERO) { + return TGCMPLX(NAN, 0.0); + } + + if (classr == FP_NAN && classi != FP_INFINITE && classi != FP_ZERO) { + feraiseexcept(FE_INVALID); + return TGCMPLX(NAN, NAN); + } + + if (classr == FP_NAN && classi == FP_NAN) { + return TGCMPLX(NAN, NAN); + } + return z; } |
