最近リリースされたDoom 3 BFG のソース コードをブラウズしていると、意味をなさないものに出会いました。Doom 3 は、数学関数をidMathクラスにラップします。一部の関数は から対応する関数に進むだけmath.h
ですが、再実装されたもの ( idMath::exp16() など) は、対応する関数よりもパフォーマンスが高いと思われますmath.h
(おそらく精度が犠牲になります)。
しかし、私を当惑させるのは、彼らがfloat idMath::Sqrt(float x)
機能を実装した方法です:
ID_INLINE float idMath::InvSqrt( float x ) {
return ( x > FLT_SMALLEST_NON_DENORMAL ) ? sqrtf( 1.0f / x ) : INFINITY;
}
ID_INLINE float idMath::Sqrt( float x ) {
return ( x >= 0.0f ) ? x * InvSqrt( x ) : 0.0f;
}
これは、2 つの不必要な浮動小数点演算を実行しているように見えます: 最初に除算、次に乗算です。
元の Doom 3 のソース コードでもこの方法で平方根関数が実装されていたのは興味深いことですが、逆平方根は高速な逆平方根アルゴリズムを使用しています。
ID_INLINE float idMath::InvSqrt( float x ) {
dword a = ((union _flint*)(&x))->i;
union _flint seed;
assert( initialized );
double y = x * 0.5f;
seed.i = (( ( (3*EXP_BIAS-1) - ( (a >> EXP_POS) & 0xFF) ) >> 1)<<EXP_POS) | iSqrt[(a >> (EXP_POS-LOOKUP_BITS)) & LOOKUP_MASK];
double r = seed.f;
r = r * ( 1.5f - r * r * y );
r = r * ( 1.5f - r * r * y );
return (float) r;
}
ID_INLINE float idMath::Sqrt( float x ) {
return x * InvSqrt( x );
}
内部的に単に'sを呼び出しSqrt(x)
ているx * InvSqrt(x)
かのように計算する利点はありますか? ここで、非正規化された浮動小数点数に関する重要な何かが欠けているのでしょうか、それとも id ソフトウェアのずさんな部分ですか?InvSqrt(x)
math.h
fsqrt(1.f/x)