arriu 100 Report post Posted September 27, 2010 Hey guys,I'm trying to remove what seems to be a bottle neck in my noise function. I have a call to Math.Cos() which calculates the cosine in double precision but also adds another function call and cast to float. I have seen simple methods of estimating the cosine function in the past (using a parabola I think) but I'm having trouble tracking them down. Anyways, here is the function I wish to speed up, any help is appreciated:// cosine interpolation between a and b by a factor of xpublic float lerp(float a, float b, float x){ float ft = x * 3.1415927f; float f = (1.0f - (float)Math.Cos(ft)) * 0.5f; return a * (1.0f - f) + b * f;} 0 Share this post Link to post Share on other sites
Kambiz 758 Report post Posted September 27, 2010 In the range -pi/2 to pi/2 you can use the approximatoioncos(x) ~ -(x-pi/2)(x+pi/2)/(pi*pi/4)(This approximation is different from the Taylor expansion 1-x^2/2+... but has the nice property of having roots at exactly -pi/2 and pi/2) 0 Share this post Link to post Share on other sites
arriu 100 Report post Posted September 27, 2010 Thanks! I may end up using that. Also I managed to dig up the article I was looking for: http://www.devmaster.net/forums/showthread.php?t=5784Is there any way to remove the abs()? I am working with the compact .net framework which does not inline any function calls. Calling Math.Abs() may make it pointless.float sine(float x){ const float B = 4/pi; const float C = -4/(pi*pi); float y = B * x + C * x * abs(x); #ifdef EXTRA_PRECISION // const float Q = 0.775; const float P = 0.225; y = P * (y * abs(y) - y) + y; // Q * y + P * y * abs(y) #endif} 0 Share this post Link to post Share on other sites
Dave Eberly 1173 Report post Posted September 27, 2010 This file has several approximations for trigonometric functions. The header has the restrictions on the domain of these functions. 0 Share this post Link to post Share on other sites
Matias Goldberg 9593 Report post Posted September 27, 2010 If you are working with 32 bit floats all the time, you may want to try changing the precision and rounding mode at the start of the application:_controlfp(_PC_24, _MCW_PC)_controlfp(_RC_NEAR, _MCW_RC)Every now and then you will have to check a DLL (i.e. Direct3D) didn't change it back:assert( (_controlfp(0, 0) & _MCW_PC) == _PC_24 );assert( (_controlfp(0, 0) & _MCW_RC) == _RC_NEAR );By the way, what happens when you just use cosf()?If precision isn't your concern, try changing your compiler optimizations from Precise to Fast (in MSVC, Alt+F7 -> C++ -> Code Generation -> Floating Point Model)CheersDark SylincEdit: Oh I see, this seems C#, then you're probably f**ked. 0 Share this post Link to post Share on other sites
arriu 100 Report post Posted September 27, 2010 Yeah, I'm stuck with c#. Which is why I do not want to use the Math.Cos class. It's overkill for what I need.I guess I am going to use this: public static float Cos(float x) { const float B = 4 / PI; const float C = -4 / (TwoPi); x -= PIby2; return -(B * x + C * x * ((x < 0) ? -x : x)); } public static float CosLerp(float a, float b, float x) { const float B = 4 / PI; const float C = -4 / (TwoPi); float ft = x * PI; //float f = (1.0f - (float)Math.Cos(ft)) * 0.5f; float c = ft - PIby2; float f = (1.0f + (B * c + C * c * ((c < 0) ? -c : c))) * 0.5f; return a * (1.0f - f) + b * f; }edit: even without the extra precision this will do nicely[Edited by - arriu on September 27, 2010 5:30:08 PM] 0 Share this post Link to post Share on other sites