/* **************************************************************

   Uebungen zur Analysis I fuer Informatiker - WS 2003/04
   Blatt 11

   Freiwillige Zusatzaufgabe 50) - arcsct_approx.cpp
   Approximation an arcsin, arccos, arctan

   Leonhard Fellermayr, Mat. Nr. 22128130XXXX

   Auch im WWW: http://www.slacky.de/files/uni/analysis/arcsct_approx.cpp

   Fehlerbehandlung via errno () :
   http://www.qnx.com/developer/docs/momentics621_docs/dinkum_en/full/math.html

*************************************************************** */

#include <iostream>
#include <errno.h>

using namespace std;
typedef long double ldb;

const ldb EPSILON_IEEE64 = 10e-16;

ldb my_arcsin_recurse (ldb l, int n)
{
	ldb t = (2 * l) / sqrtl(2 + 2 * sqrtl(1 - powl(4, -n) * powl(l, 2)));

	if (fabsl (l - t) >= EPSILON_IEEE64)
		return my_arcsin_recurse (t, ++n);
	else
		return t;
}

ldb my_arcsin (ldb x) {
	if (fabsl (x) > 1) errno = EDOM;
	else return (my_arcsin_recurse (x, 0));
}

ldb my_arccos (ldb x) {
	if (fabsl (x) > 1) errno = EDOM;
	else return (M_PI_2 - my_arcsin (x));
}

ldb my_arctan (ldb x) {
	return (my_arcsin (x / sqrtl (1 + powl (x, 2))));
}

void do_output (ldb x)
{
	printf ("     id (x) = % Lg\n", x);
	printf ("my_asin (x) = % .15Lf   C++ asin (x) = % .15Lf\n",   my_arcsin (x), asinl (x));
	printf ("my_acos (x) = % .15Lf   C++ acos (x) = % .15Lf\n",   my_arccos (x), acosl (x));
	printf ("my_atan (x) = % .15Lf   C++ atan (x) = % .15Lf\n\n", my_arctan (x), atanl (x));
}

int main ()
{
	errno = 0;
	ldb beispiele[] = { -0.7, 0.2, 0.5, 1, 5, 1000 };

	for (int i = 0; i < sizeof (beispiele) / sizeof (ldb); i++)
		do_output (beispiele[i]);
}
