J'ai parcouru la récente publication Code source de Doom 3 BFG quand je suis tombé sur quelque chose qui ne semble pas avoir de sens. Doom 3 emballe les fonctions mathématiques dans la section idMath classe. Certaines des fonctions renvoient simplement aux fonctions correspondantes de math.h
mais certaines sont des réimplémentations (par ex. idMath::exp16() ) qui, je suppose, ont des performances supérieures à celles de leur math.h
(peut-être au détriment de la précision).
Ce qui me laisse perplexe, cependant, c'est la façon dont ils ont mis en œuvre la float idMath::Sqrt(float x)
fonction :
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;
}
Cela semble effectuer deux opérations en virgule flottante inutiles : D'abord une division, puis une multiplication.
Il est intéressant de noter que le code source original de Doom 3 a également implémenté la fonction Racine carrée de cette manière, mais la Racine carrée inverse utilise la fonction algorithme inverse rapide de la racine carrée .
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 );
}
Voyez-vous un avantage à calculer Sqrt(x)
como x * InvSqrt(x)
si InvSqrt(x)
en interne, il suffit d'appeler math.h
's fsqrt(1.f/x)
? Est-ce que je rate quelque chose d'important à propos des nombres à virgule flottante dénormalisés ou est-ce que ce n'est qu'une négligence de la part du logiciel ID ?