Calling the atan function on a Blackberry 4.2 JDE
From Arctan to J2ME by Steven Zimmerman :
// calculation functions
public class Calculation {
// Because J2ME has no floating point numbers,
// some sort of fixed point math is required.
// My implementation is simply to shift 10 places.
// for example, 1024 (>> 10) = 1
// and 512 (>> 10) = 0.5
public static final int[] AtanTable = { 0, 1, 2, 3, 5, 6, 7, 8, 10, 11, 12,
13, 14, 16, 17, 18, 19, 20, 21, 22, 23, 25, 26, 27, 28, 29,
30, 30,31, 32, 33, 34, 35, 36, 37, 37, 38, 39, 40, 40, 41,
42, 43, 43, 44, 45 };
// / returns angle 0->359 in degrees
public static int atan(int Y, int X) {
boolean swap = false;
int top = Math.abs(Y);
int bottom = Math.abs(X);
if (top > bottom) {
int btemp = bottom;
bottom = top;
top = btemp;
swap = true;
} else if (bottom == 0)
return -300;
// this should keep index inbounds [0, 45]
int index = (top * 45) / bottom;
int angle = AtanTable[index];
if (swap)
angle = 90 - angle;
// X & Y += 180
// X & !Y = ...90
// !X & Y = ... 270
if ((X < 0) && (Y < 0))
angle += 180;
else if (Y < 0) {
angle = 90 - angle;
angle += 270;
} else if (X < 0) {
angle = 90 - angle;
angle += 90;
}
if (angle == 360)
angle = 0;
return angle;
}
}
source to share
When all else fails, one can probably get a decent value by evaluating the result of an endless series of the function arctan
.
The Wikipedia page on inverse trigonometric functions has a section on infinite series of inverse trigonometric functions including arctan
. To get an estimate, one could run an infinite series until the desired accuracy is obtained.
Due to the fact that the function is arctan
not enabled, it is likely because the processor in the Blackberry is not very efficient and will require a lot of processor resources to perform the calculation.
Also, looking at the Blackberry JDE 4.2 API documentation, there seems to be a fixed point math library called Fixed32
that offers two arctan flavors. They do calculations with 32-bit integers, so they probably have some performance advantages over floating point arithmetic.
source to share
Here's the function I'm using (no guarantee it's very fast):
/** Square root from 3 */
final static public double SQRT3 = 1.732050807568877294;
static public double atan(double x)
{
boolean signChange=false;
boolean Invert=false;
int sp=0;
double x2, a;
// check up the sign change
if(x<0.)
{
x=-x;
signChange=true;
}
// check up the invertation
if(x>1.)
{
x=1/x;
Invert=true;
}
// process shrinking the domain until x<PI/12
while(x>Math.PI/12)
{
sp++;
a=x+SQRT3;
a=1/a;
x=x*SQRT3;
x=x-1;
x=x*a;
}
// calculation core
x2=x*x;
a=x2+1.4087812;
a=0.55913709/a;
a=a+0.60310579;
a=a-(x2*0.05160454);
a=a*x;
// process until sp=0
while(sp>0)
{
a=a+Math.PI/6;
sp--;
}
// invertation took place
if(Invert) a=Math.PI/2-a;
// sign change took place
if(signChange) a=-a;
//
return a;
}
source to share
Let's first implement the standard arctan(x)
using the Taylor series (as described at http://en.wikipedia.org/wiki/Inverse_trigonometric_functions#Infinite_series )
To call arctan, do the following:
1) Do this check first.
if (x == 0) {
return 0;
}
2) if |x| > 1
, calculate arctan(1/x)
and finally subtract the result fromPi/2
3), if |x|
close to 1
, calculate the arctan of the half-angle using the half-angle formula
arctan(x) = 2*arctan(x/(1+sqrt(1+x*x)))
. That is, first calculate the half angle, then multiply the result by 2. Otherwise, for |x|
close to 1, arctan converges very slowly.
source to share