%mathpiper,def="ArcTanNum"

/// low-level numerical calculations of elementary functions.
/// These are only called if InNumericMode() returns True

ArcTanNum(x) :=
[
	// using trigonometric identities is faster for now
	If(
		Abs(x)>1,
		Sign(x)*(Internal'Pi()/2-ArcSin(1/Sqrt(x^2+1))),
		ArcSin(x/Sqrt(x^2+1))
	);
];





/* old methods -- slower for now
/// numerical evaluation of ArcTan using continued fractions: top level
2 # ArcTan(x_IsNumber)_InNumericMode() <--
Sign(x) *
// now we need to compute ArcTan of a nonnegative number Abs(x)
[
	Local(nterms, y);
	y := Abs(x);
	// use identities to improve convergence -- see essays book
	If(
		y>1,
		y:=1/y	// now y <= 1
	// we shall know that the first identity was used because Abs(x) > 1 still
	);
	// use the second identity
	y := y/(1+Sqrt(1+y^2));	// now y <= Sqrt(2)-1
	// find the required number of terms in the continued fraction
	nterms := 1/y;	// this needs to be calculated at full precision
	// see essays book on the choice of the number of terms (added 2 "guard terms").
	// we need Hold() because otherwise, if InNumericMode() returns True, N(..., 5) will not avoid the full precision calculation of Ln().
	// the value of x should not be greater than 1 here!
	nterms := 2 + Ceil( N(Hold(Ln(10)/(Ln(4)+2*Ln(nterms))), 5) * BuiltinPrecisionGet() );
	If(	// call the actual routine
		Abs(x)>1,
		Pi/2-2*MyArcTan(y, nterms),	// this is for |x|>1
		2*MyArcTan(y, nterms)
		// MyArcTan(x, nterms)
	);
];
*/



/// numerical evaluation of ArcTan using continued fractions: low level

// evaluation using recursion -- slightly faster but lose some digits to roundoff errors and needs large recursion depth
/*
10 # ContArcTan(_x,_n,_n) <-- (2*n-1);
20 # ContArcTan(_x,_n,_m) <--
[
  (2*n-1) + (n*x)^2/ContArcTan(x,n+1,m);
];

MyArcTan(x,n) :=
[
  x/ContArcTan(x,1,n);
];
*/
/*
/// evaluate n terms of the continued fraction for ArcTan(x) without recursion.
/// better control of roundoff errors
MyArcTan(x, n) :=
[
	Local(i, p, q, t);
	// initial numerator and denominator
	p:=1;
	q:=1;
	// start evaluating from the last term upwards
	For(i:=n, i>=1, i--)
	[
		//{p,q} := {p + q*(i*x)^2/(4*i^2-1), p};
	//	t := p*(2*i-1) + q*(i*x)^2; then have to start with p:=2*n+1
		t := p + q*(i*x)^2/(4*i^2-1);
		q := p;
		p := t;
	];
	// answer is x/(p/q)
	x*q/p;
];
*/

%/mathpiper