/****************************************************************************/
/*	Copyright (c) 2009, Bendor Research Pty. Ltd. All rights reserved.		*/
/*	This software is released under the GNU General Public License, version	*/
/*	3, with the exemptions that 1) the header files installed by this 	 	*/
/*	package can be included in closed-source code and 2) the libraries		*/
/*	built by this package can be statically linked into a closed-source 	*/
/*	binary. See the file LICENSE for the details.							*/
/*	This software is provided "AS IS", without any warranty or guarantee.	*/
/*	By using this software you acknowledge that neither Bendor Research nor	*/
/*	any of its personnel or affiliates can be held liable for any damages,	*/
/*	including, but not limited to, loss of business, loss of money, loss of */
/*	life, loss of reputation, arising out of this software being faulty or	*/
/*	not performing as advertised, even if Bendor Research was aware of such	*/
/*	faults in the software. You use this software at your own risk, any and */
/*	all liabilities that arise out of your using this software are strictly	*/
/*	yours.																	*/
/****************************************************************************/

#include <math.h>
#include <libm.h>

/****************************************************************************/
/*					Local definitions										*/
/****************************************************************************/

/*
*	PI / 4 with a precision extended by 14 bits.
*	PI4_HI has only 13 bits set in its mantissa, they represent the
*	first 13 bits of PI/4. PI4_LO's mantissa contains the next 53 bits.
*
*	When we have to add PI/4 to some other number, we add PI4_LO first
*	and then add PI4_HI to the result. This increases the effective
*	precision. This trick is by Cody and Waite.
*/

#define	PI4_HI	(6433.0/8192.0)
#define	PI4_LO	1.198430849483154297228014983618758076966e-4

/****************************************************************************/
/*					Local data												*/
/****************************************************************************/

/*
*	Polynom coefficients for the rational approximation.
*	P is the numerator and Q is the denominator.
*	The coefficients are by Moshier.
*/

static const double P[] = {

	-6.485021904942025371773e+01,
	-1.228866684490136173410e+02,
	-7.500855792314704667340e+01,
	-1.615753718733365076637e+01,
	-8.750608600031904122785e-01,
};

static const double Q[] = {

	+1.945506571482613964425e+02,
	+4.853903996359136964868e+02,
	+4.328810604912902668951e+02,
	+1.650270098316988542046e+02,
	+2.485846490142306297962e+01,
	+1.000000000000000000000e+00,
};

/****************************************************************************/
/*					Public API functions									*/
/****************************************************************************/

/** @addtogroup func */
/** @{ */

/**
*	Arcus tangent function.
*
*	@param	x		The value of which the arcus tangent should be calculated
*	@retval	NaN		The argument was NaN
*	@retval	+PI/2	The argument was positive infinity
*	@retval	-PI/2	The argument was negative infinity
*	@retval	atan(x)	Otherwise. The returned value is in radian and in the
*					principal range of [-PI/2,+PI/2].
*/

double	atan( double x )
{
double	x1, x2;
double	ah, al;
int		sg, of;

	// Basic sanity check and extremity behaviour

	if ( isnan( x ) || iszero( x ) ) return( x );

	if ( ( sg = isinf( x ) ) ) {

		if ( sg > 0 )

			return( +2.0 * ( PI4_HI + PI4_LO ) );
		else
			return( -2.0 * ( PI4_HI + PI4_LO ) );
	}

	// Although the approximation itself is symmetrical, the
	// range reduction assumes a positive argument, so we make
	// it positive and keep track of the signum.

	if ( x < 0 ) {

		x1 = -x;
		sg = 1;
	}
	else {

		x1 = x;
		sg = 0;
	}

	// The range reduction cuts the 0 - +INF into 3 parts.
	// Between 0 and 0.66 we use a rational approximation function.
	// Above 0.66, using a trigonometric identity the calculation is
	// transformed to atan( x ) = PI/4 + atan( ( x-1 ) / ( x+1 ) ).
	// Since the above is an identity, the choice of the switch-over
	// point is arbitrary. The value 0.66 is the point where the two
	// approximations have the same error; if you move the switch-over
	// point either way, the approximation error will increase.
	// The next point uses an other trigonometric identity, namely
	// atan( x ) = PI/2 - atan( 1/x ). Again, since that is an identity,
	// the switch-over is arbitrary. The choice of 1/0.66 makes the
	// transformed range of the previous identity symmetrical to 0.
	// These switch-over points have also been tested for monotonicity
	// preservation. Note that at most one transformation is used.

	if ( x1 > 1.0 / 0.66 ) {

		x1 = +1.0 / x1;
		ah = -2.0 * PI4_HI;
		al = -2.0 * PI4_LO;
		sg = ! sg;
		of = 1;
	}
	else if ( x1 > 0.66 ) {

		x1 = ( x1 - 1.0 ) / ( x1 + 1.0 );
		ah = PI4_HI;
		al = PI4_LO;
		of = 1;
	}
	else {

		ah = 0;			// This is needed because gcc is not smart
		al = 0;			// enough to deduce that if 'of' is set to 0,
		of = 0;			// then 'ah' and 'al' are never used.
	}

	// This is the actual approximation in the principal
	// range:
	//						   P( x^2 )
	// atan( x ) ~= x + x^3 * ----------
	//						   Q( x^2 )

	x2  = x1 * x1;
	x1 += x2 * x1 * polynom( x2, P, 4 ) / polynom( x2, Q, 5 );

	// If due to the range reduction we have to offset the result,
	// we do it in two steps, as per Cody and Waite.

	if( of ) {

		x1 += al;
		x1 += ah;
	}

	return( sg ? -x1 : +x1 );
}

/** @} */

