Math Tutorial
Visual C++ .NET



Rychlejší funkce


Zdroják ke stažení (10k)

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