about summary refs log tree commit diff
path: root/src/complex/catanf.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/complex/catanf.c')
-rw-r--r--src/complex/catanf.c115
1 files changed, 115 insertions, 0 deletions
diff --git a/src/complex/catanf.c b/src/complex/catanf.c
new file mode 100644
index 00000000..8533bde3
--- /dev/null
+++ b/src/complex/catanf.c
@@ -0,0 +1,115 @@
+/* origin: OpenBSD /usr/src/lib/libm/src/s_catanf.c */
+/*
+ * Copyright (c) 2008 Stephen L. Moshier <steve@moshier.net>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+/*
+ *      Complex circular arc tangent
+ *
+ *
+ * SYNOPSIS:
+ *
+ * float complex catanf();
+ * float complex z, w;
+ *
+ * w = catanf( z );
+ *
+ *
+ * DESCRIPTION:
+ *
+ * If
+ *     z = x + iy,
+ *
+ * then
+ *          1       (    2x     )
+ * Re w  =  - arctan(-----------)  +  k PI
+ *          2       (     2    2)
+ *                  (1 - x  - y )
+ *
+ *               ( 2         2)
+ *          1    (x  +  (y+1) )
+ * Im w  =  - log(------------)
+ *          4    ( 2         2)
+ *               (x  +  (y-1) )
+ *
+ * Where k is an arbitrary integer.
+ *
+ *
+ * ACCURACY:
+ *
+ *                      Relative error:
+ * arithmetic   domain     # trials      peak         rms
+ *    IEEE      -10,+10     30000        2.3e-6      5.2e-8
+ */
+
+#include "libm.h"
+
+#define MAXNUMF 1.0e38F
+
+static const double DP1 = 3.140625;
+static const double DP2 = 9.67502593994140625E-4;
+static const double DP3 = 1.509957990978376432E-7;
+
+static float _redupif(float xx)
+{
+	float x, t;
+	long i;
+
+	x = xx;
+	t = x/(float)M_PI;
+	if (t >= 0.0f)
+		t += 0.5f;
+	else
+		t -= 0.5f;
+
+	i = t;  /* the multiple */
+	t = i;
+	t = ((x - t * DP1) - t * DP2) - t * DP3;
+	return t;
+}
+
+float complex catanf(float complex z)
+{
+	float complex w;
+	float a, t, x, x2, y;
+
+	x = crealf(z);
+	y = cimagf(z);
+
+	if ((x == 0.0f) && (y > 1.0f))
+		goto ovrf;
+
+	x2 = x * x;
+	a = 1.0f - x2 - (y * y);
+	if (a == 0.0f)
+		goto ovrf;
+
+	t = 0.5f * atan2f(2.0f * x, a);
+	w = _redupif(t);
+
+	t = y - 1.0f;
+	a = x2 + (t * t);
+	if (a == 0.0f)
+		goto ovrf;
+
+	t = y + 1.0f;
+	a = (x2 + (t * t))/a;
+	w = w + (0.25f * logf (a)) * I;
+	return w;
+
+ovrf:
+	// FIXME
+	w = MAXNUMF + MAXNUMF * I;
+	return w;
+}