次のコードは、有理近似を使用して、[0 1)間隔に正規化されたアークタンジェントを取得します(結果にPi / 2を掛けて、実際のアークタンジェントを取得できます)。
normalized_atan(x)〜(bx + x ^ 2)/(1 + 2 bx + x ^ 2)
ここで、b = 0.596227
最大誤差は0.1620ºです
#include <stdint.h>
#include <math.h>
// Approximates atan(x) normalized to the [-1,1] range
// with a maximum error of 0.1620 degrees.
float normalized_atan( float x )
{
static const uint32_t sign_mask = 0x80000000;
static const float b = 0.596227f;
// Extract the sign bit
uint32_t ux_s = sign_mask & (uint32_t &)x;
// Calculate the arctangent in the first quadrant
float bx_a = ::fabs( b * x );
float num = bx_a + x * x;
float atan_1q = num / ( 1.f + bx_a + num );
// Restore the sign bit
uint32_t atan_2q = ux_s | (uint32_t &)atan_1q;
return (float &)atan_2q;
}
// Approximates atan2(y, x) normalized to the [0,4) range
// with a maximum error of 0.1620 degrees
float normalized_atan2( float y, float x )
{
static const uint32_t sign_mask = 0x80000000;
static const float b = 0.596227f;
// Extract the sign bits
uint32_t ux_s = sign_mask & (uint32_t &)x;
uint32_t uy_s = sign_mask & (uint32_t &)y;
// Determine the quadrant offset
float q = (float)( ( ~ux_s & uy_s ) >> 29 | ux_s >> 30 );
// Calculate the arctangent in the first quadrant
float bxy_a = ::fabs( b * x * y );
float num = bxy_a + y * y;
float atan_1q = num / ( x * x + bxy_a + num );
// Translate it to the proper quadrant
uint32_t uatan_2q = (ux_s ^ uy_s) | (uint32_t &)atan_1q;
return q + (float &)uatan_2q;
}
より高い精度が必要な場合は、3次の有理関数があります。
normalized_atan(x)〜(cx + x ^ 2 + x ^ 3)/(1 +(c + 1)x +(c + 1)x ^ 2 + x ^ 3)
ここで、c =(1 + sqrt(17))/ 8
0.00811ºの最大近似誤差があります