3

私は他の人々のコードをレビューするのはかなりまともだと思いたいです...しかし私は途方に暮れています。これはDoom3数学ライブラリから来ています。これはおそらくQuake1以降のGPLに存在していると思います。これはmath.hを参照していることに注意してください。これが実際にコサインを計算する方法があると思います...しかし、私はそれを理解することができません。誰か説明しますか?

    ID_INLINE float idMath::Cos16( float a ) {
    float s, d;

    if ( ( a < 0.0f ) || ( a >= TWO_PI ) ) {
        a -= floorf( a / TWO_PI ) * TWO_PI;
    }
#if 1
    if ( a < PI ) {
        if ( a > HALF_PI ) {
            a = PI - a;
            d = -1.0f;
        } else {
            d = 1.0f;
        }
    } else {
        if ( a > PI + HALF_PI ) {
            a = a - TWO_PI;
            d = 1.0f;
        } else {
            a = PI - a;
            d = -1.0f;
        }
    }
#else
    a = PI - a;
    if ( fabs( a ) >= HALF_PI ) {
        a = ( ( a < 0.0f ) ? -PI : PI ) - a;
        d = 1.0f;
    } else {
        d = -1.0f;
    }
#endif
    s = a * a;
    return d * ( ( ( ( ( -2.605e-07f * s + 2.47609e-05f ) * s - 1.3888397e-03f ) * s + 4.16666418e-02f ) * s - 4.999999963e-01f ) * s + 1.0f );
}
4

1 に答える 1

5

すべての条件付きのものは、角度を 1 つの象限に折り畳んでいるように見えます (または、八分円かもしれません。それを理解するのは面倒です... ;) )、および補正係数 ( d) を記録します。

最後の行は、ある種の 10 次多項式近似を実行しています (おそらくテイラーまたはチェビシェフ?)。* ただしcos、偶数関数と同様に、偶数ベキでのみ機能します。また、ホーナーの方法を使用して、大きなべき乗を複数回直接計算することを回避しています。

次に、を使用して正しい符号を再適用していますd


* これが「かなり」正確であることを確認するには、Octave で次のコードを実行してみてください (たとえば、ここでオンラインで実行できます)。

% One quadrant
a = (-pi/2):0.1:(+pi/2);

% Exact result
y_exact = cos(a);

% Our approximation
s = a .* a;
y_approx = (((((-2.605e-07 .* s + 2.47609e-05) .* s - 1.3888397e-03) .* s + 4.16666418e-02) .* s - 4.999999963e-01) .* s + 1);

% Plot
hold on
plot(a, y_exact,  'b')
plot(a, y_approx, 'r')

于 2013-02-05T17:41:27.487 に答える