Mailing Lists: Apple Mailing Lists

Image of Mac OS face in stamp
 
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Fast atan2




Does anyone know of a fast approximate atan2 algorithm (like those
delightfully sleazy hacks for sqrt and its reciprocal)?

If you have a bunch of them to do, in Tiger there is a new vvatan2()
function in Accelerate.framework/vForce.h.
Ian

Interesting, but not available to me yet.


http://www.shellandslate.com/computermath101.html
Ben

Thanks. I tried it, and (after some translation for gcc) found that the atan2 replacement has good accuracy but is little if any faster than the library atan2.



double fast_atan2(double y, double x)
<snip>
Shaun Wexler

Blindingly fast! The maximum absolute error (>0.07 radians) is, alas, much too big for my application.



http://www.dspguru.com/comp.dsp/tricks/alg/fxdatan2.htm
r i c k

Thanks. The 'accurate' version of the method at that URL (shown below with trivial modifications) has a max |error| around 0.0102 radians:


// max |error| > 0.01
float arctan2( float y, float x )
{
	const float ONEQTR_PI = M_PI / 4.0;
	const float THRQTR_PI = 3.0 * M_PI / 4.0;
	float r, angle;
	float abs_y = fabs(y) + 1e-10f;      // kludge to prevent 0/0 condition
	if ( x < 0.0f )
	{
		r = (x + abs_y) / (abs_y - x);
		angle = THRQTR_PI;
	}
	else
	{
		r = (x - abs_y) / (x + abs_y);
		angle = ONEQTR_PI;
	}
	angle += (0.1963f * r * r - 0.9817f) * r;
	if ( y < 0.0f )
		return( -angle );     // negate if in quad III or IV
	else
		return( angle );
}


Arman Garakani wrote:
Cordic algorithm has been a great way to perform atan2. A great
reference is:
http://www.worldserver.com/turk/opensource/index.html#CORDIC

Hmm. Looks fun, but I need float or double and that code is fixed point.


Here's another answer to my question, based on a 50-year old atan approximation due to Hastings. It has |error| < 0.005, and (with all relevant optimizations in gcc) is 3-5x faster than atan2 in spite of two horrible divisions in the main code path.


#define PI_FLOAT     3.14159265f
#define PIBY2_FLOAT  1.5707963f
// |error| < 0.005
float fast_atan2f( float y, float x )
{
	if ( x == 0.0f )
	{
		if ( y > 0.0f ) return PIBY2_FLOAT;
		if ( y == 0.0f ) return 0.0f;
		return -PIBY2_FLOAT;
	}
	float atan;
	float z = y/x;
	if ( fabsf( z ) < 1.0f )
	{
		atan = z/(1.0f + 0.28f*z*z);
		if ( x < 0.0f )
		{
			if ( y < 0.0f ) return atan - PI_FLOAT;
			return atan + PI_FLOAT;
		}
	}
	else
	{
		atan = PIBY2_FLOAT - z/(z*z + 0.28f);
		if ( y < 0.0f ) return atan - PI_FLOAT;
	}
	return atan;
}

Robert P.



_______________________________________________
Do not post admin requests to the list. They will be ignored.
PerfOptimization-dev mailing list      (email@hidden)
Help/Unsubscribe/Update your Subscription:
http://lists.apple.com/mailman/options/perfoptimization-dev/email@hidden

This email sent to email@hidden


Visit the Apple Store online or at retail locations.
1-800-MY-APPLE

Contact Apple | Terms of Use | Privacy Policy

Copyright © 2007 Apple Inc. All rights reserved.