|
Rychlejší funkce
|
|
|
18.03.2004
|
|
|
Rychlejší funkce sqrt, sin, cos, tan, asin, acos, atan
můžeme řešit pomocí aproximace.
Invertovaná funkce pro odmocninu vypadá takto.
|
|
float CMath::FastInvSqrt (float fX)
{
float fHalf = 0.5f*fX;
int i = *(int*)&X;
i = 0x5f3759df - (i >> 1); // This line hides a LOT of math!
fX = *(float*)&i;
fX = fX*(1.5f - fHalf*fX*fX); // repeat this statement for a better approximation
return fX;
}
|
Abychom získali odmocninu, budeme muset funkci volat 1 / FastInvSqrt()
Přesto je funkce rychlejší, než standartní fukce.
Funkce FastSin() je přibližně dvakrát rychlejší než standartní funkce, pokud je úhel v rozmezí [0,pi/2].
Největší možná nepřestnost výpočtu je kolem 1.7e-04.
Pokud má úhel větší, nebo menší hodnotu než je stanovené rozmezí, volá se funkce pro konverzi do tohoto rozmezí, tímpádem
čím je větší rozdíl hodnot úhlu a rozmezí, tím je funkce pomalejší.
|
|
float CMath::FastSin(const float fAngle)
{
float fA;
bool bNeg = 0;
if((fAngle>HALF_PI)||(fAngle<0))
{
// Convert to PI/2 for fast sin functions
fA = ConvertHalfPiSin(fAngle, bNeg);
}
else
{
fA = fAngle;
}
float fASqr = fA*fA;
float fResult = (float)7.61e-03;
fResult *= fASqr;
fResult -= (float)1.6605e-01;
fResult *= fASqr;
fResult += (float)1.0;
fResult *= fA;
// If negative reference from conversion
if(bNeg)
{
fResult = -fResult;
}
return fResult;
}
|
Funkce FastCos() je přibližně dvakrát rychlejší než standartní funkce, pokud je úhel v rozmezí [0,pi/2].
Největší možná nepřestnost výpočtu je kolem 1.2e-03.
Pokud má úhel větší, nebo menší hodnotu než je stanovené rozmezí, volá se funkce pro konverzi do tohoto rozmezí, tímpádem
čím je větší rozdíl hodnot úhlu a rozmezí, tím je funkce pomalejší.
|
|
float CMath::FastCos(const float fAngle)
{
float fA;
bool bNeg = 0;
if((fAngle>HALF_PI)||(fAngle<0))
{
// Convert to PI/2 for fast cos function
fA = ConvertHalfPiCos(fAngle, bNeg);
}
else
{
fA = fAngle;
}
float fASqr = fA*fA;
float fResult = (float)3.705e-02;
fResult *= fASqr;
fResult -= (float)4.967e-01;
fResult *= fASqr;
fResult += (float)1.0;
// If negative reference from conversion
if(bNeg)
{
fResult = -fResult;
}
return fResult;
}
|
Funkce FastTan() je přibližně 2.5x rychlejší než standartní funkce, pokud je úhel v rozmezí [0,pi/4].
Největší možná nepřestnost výpočtu je kolem 8.1e-04.
Pokud má úhel větší, nebo menší hodnotu než je stanovené rozmezí, počítá se
FastTan = FastSin / FastCos, takže je potom výpočet pomalejší.
|
|
float CMath::FastTan(const float fAngle)
{
float fA;
float fSinA;
float fCosA;
if((fAngle>QUARTER_PI)||(fAngle<0))
{
if((fAngle>TWO_PI)||(fAngle<0))
{
// Convert to TWO_PI
fA = CMath::ConvertTwoPi(fAngle);
fCosA = CMath::FastCos(fA);
}
else
{
fA = fAngle;
fCosA = CMath::FastCos(fA);
}
if(fCosA)
{
fSinA = CMath::FastSin(fA);
return fSinA/fCosA;
}
else
{
return 0.0f;
}
}
else
{
fA = fAngle;
}
float fASqr = fA*fA;
float fResult = (float)2.033e-01;
fResult *= fASqr;
fResult += (float)3.1755e-01;
fResult *= fASqr;
fResult += (float)1.0;
fResult *= fA;
return fResult;
}
|
Funkce FastASin() je přibližně 2.5x rychlejší než standartní funkce, pokud je úhel v rozmezí [-1,1].
Největší možná nepřestnost výpočtu je kolem 6.8e-05.
Pokud má úhel větší, nebo menší hodnotu než je stanovené rozmezí, vrací funkce nulovou hodnotu.
|
|
float CMath::FastASin(const float fValue)
{
float fV;
if((fValue>1.0f)||(fValue<-1.0f))
{
return 0.0f;
}
if(fValue<0)
{
fV = -fValue;
}
else
{
fV = fValue;
}
float fRoot = sqrt(((float)1.0)-fV);
float fResult = -(float)0.0187293;
fResult *= fV;
fResult += (float)0.0742610;
fResult *= fV;
fResult -= (float)0.2121144;
fResult *= fV;
fResult += (float)1.5707288;
fResult = HALF_PI - fRoot*fResult;
if(fValue<0)
{
fResult = -fResult;
}
return fResult;
}
|
Funkce FastACos() je přibližně 2.2x rychlejší než standartní funkce, pokud je úhel v rozmezí [-1,1].
Největší možná nepřestnost výpočtu je kolem 6.8e-05.
Pokud má úhel větší, nebo menší hodnotu než je stanovené rozmezí, vrací funkce nulovou hodnotu.
|
|
float CMath::FastACos(const float fValue)
{
float fV;
if((fValue>1.0f)||(fValue<-1.0f))
{
return 0.0f;
}
if(fValue<0)
{
fV = -fValue;
}
else
{
fV = fValue;
}
float fRoot = sqrt(((float)1.0)-fV);
float fResult = -(float)0.0187293;
fResult *= fV;
fResult += (float)0.0742610;
fResult *= fV;
fResult -= (float)0.2121144;
fResult *= fV;
fResult += (float)1.5707288;
fResult *= fRoot;
if(fValue<0)
{
fResult = PI-fResult;
}
return fResult;
}
|
Funkce FastATan() je přibližně 2.2x rychlejší než standartní funkce, pokud je úhel v rozmezí [-1,1].
Největší možná nepřestnost výpočtu je kolem 1.2e-05.
Pokud má úhel větší, nebo menší hodnotu než je stanovené rozmezí, provádí se více výpočtů, takže je funkce pomalejší.
|
|
float CMath::FastATan(const float fValue)
{
float fV;
if((fValue>1.0f)||(fValue<-1.0f))
{
if(fValue)
{
fV = 1/fValue;
}
else
{
return 0.0f;
}
}
else
{
fV = fValue;
}
float fVSqr = fV*fV;
float fResult = (float)0.0208351;
fResult *= fVSqr;
fResult -= (float)0.085133;
fResult *= fVSqr;
fResult += (float)0.180141;
fResult *= fVSqr;
fResult -= (float)0.3302995;
fResult *= fVSqr;
fResult += (float)0.999866;
fResult *= fV;
if(fValue>1.0f)
{
fResult = HALF_PI - fResult;
}
if(fValue<-1.0f)
{
fResult = -(fResult + HALF_PI);
}
return fResult;
}
Home