summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJakob Kaivo <jkk@ung.org>2019-03-03 21:19:47 -0500
committerJakob Kaivo <jkk@ung.org>2019-03-03 21:19:47 -0500
commit8c7cdf31bd692e1697a5a01664717c3b9dbffc59 (patch)
tree948e7a2d189f5aba85e0f8be3386424290fdb231
parent6eb245579dfdefa0da7f59909bf2e3f8b277c426 (diff)
fill out special cases outlined in C18 annex G
-rw-r--r--src/complex/cabs.c3
-rw-r--r--src/complex/cacos.c61
-rw-r--r--src/complex/cacosh.c58
-rw-r--r--src/complex/carg.c3
-rw-r--r--src/complex/casin.c2
-rw-r--r--src/complex/casinh.c51
-rw-r--r--src/complex/catan.c2
-rw-r--r--src/complex/catanh.c57
-rw-r--r--src/complex/ccos.c2
-rw-r--r--src/complex/ccosh.c62
-rw-r--r--src/complex/cexp.c68
-rw-r--r--src/complex/clog.c64
-rw-r--r--src/complex/csin.c2
-rw-r--r--src/complex/csinh.c62
-rw-r--r--src/complex/csqrt.c47
-rw-r--r--src/complex/ctan.c2
-rw-r--r--src/complex/ctanh.c58
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;
}