参照テーブルを使用してサイン・コサイン関数を高速化してみました。
サンプル間を線形補間することで少ないサンプル数で精度を高めています。
テーブル生成のコードは以下のようになります。
init_sincosLUT
struct SINCOSCOEFFICIENT
{
float Value;
float Gradient;
};
SINCOSCOEFFICIENT sincosLUT[ 0x100 ];
#define TWO_PI 6.2831853071795864
void init_sincosLUT( void )
{
double t[ 0x100 ];
for( int i = 0; i < 0x100; i++ )
t[ i ] = sin( (double)i / 256 * TWO_PI );
for( int i = 0; i < 0x100; i++ )
{
sincosLUT[ i ].Value = (float)t[ i ];
sincosLUT[ i ].Gradient = (float)( ( t[ ( i + 1 ) & 0xFF ] - t[ i ] ) / 65536 );
}
}
作成されたテーブルを利用したサイン・コサイン関数は以下のようになります。
sinFast
inline float sinFast( float Angle )
{
Angle /= TWO_PI;
Angle -= (int)Angle;
int index = int( Angle * 16777216.0f ) & 0x00FFFFFF;
const SINCOSCOEFFICIENT& coef = sincosLUT[ index >> 16 ];
return ( coef.Value + coef.Gradient * float( index & 0xFFFF ) );
}
cosFast
inline float cosFast( float Angle )
{
Angle /= TWO_PI;
Angle -= (int)Angle;
int index = int( Angle * 16777216.0f + 4194304.0f ) & 0x00FFFFFF;
const SINCOSCOEFFICIENT& coef = sincosLUT[ index >> 16 ];
return ( coef.Value + coef.Gradient * (float)( index & 0xFFFF ) );
}
また、サイン・コサインを同時に生成する関数は以下のようになります。
sincosFast
inline void sincosFast( float Angle, float* pSin, float* pCos )
{
Angle /= TWO_PI;
Angle -= (int)Angle;
int index = int( Angle * 16777216.0f ) & 0x00FFFFFF;
float delta = float( index & 0xFFFF );
index >>= 16;
const SINCOSCOEFFICIENT& sincoef = sincosLUT[ index ];
const SINCOSCOEFFICIENT& coscoef = sincosLUT[ ( index + 0x40 ) & 0xFF ];
*pSin = sincoef.Value + sincoef.Gradient * delta;
*pCos = coscoef.Value + coscoef.Gradient * delta;
}