I am working on generation 3d perlin noise. The C# Math library seems like overkill for what I need since most of its functions use double percision. I use Math.Sin() in several places to generate the noise. Does anyone know of a faster sine function?
3 Answers
You can use a parabola to aproximate the value of the sine function. This has the advantage of having the roots at exactly -pi/2 and pi/2 which is usually not the case with other fast approximations based on the TaylorSeries or MaclaurinSeries.
public float Sin(float x)
{
const float B = 4 / PI;
const float C = -4 / (PI*PI);
return -(B * x + C * x * ((x < 0) ? -x : x));
}
Here is a comparison to the actual sine function:
-
3\$\begingroup\$ This is indeed a great solution. Here is an excellent article from devmaster.net which describes why this works and gives some implementation details: devmaster.net/forums/showthread.php?t=5784 \$\endgroup\$– reverbbOct 23, 2010 at 20:25
-
\$\begingroup\$ I don't know about C#, but the abs() function in most C environments will likely be faster than a branch (the ?: operator), when optimized. \$\endgroup\$– user744Oct 23, 2010 at 20:50
-
3\$\begingroup\$ I removed the Math.Abs() call because I assumed that this code might run on the Xbox 360 or Windows Phone 7. The JIT compiler on Xbox 360 does not inline anything. A call to Math.Abs() is actually more expensive. \$\endgroup\$– zfedoranOct 23, 2010 at 21:09
-
-
1\$\begingroup\$ @zfedoran Why do you negate the return value? It appears to be a negative sine wave. \$\endgroup\$ Jan 13, 2015 at 1:36
What is the range of input values to your sin() function? For what you're using it for, it sounds like they might be limited, which means you could pre-compute the values. For instance, if you're rounding up the input values to the nearest degree, then you only have 360 possible values - just pre-compute them and store in a table.
If you need slightly more values, say to one decimal place, you could interpolate from the table - I'm not familiar with perlin noise, but the word "noise" seems to indicate it doesn't require high accuracy. :) (You could also just make a larger table, 3600 entries isn't much space).
-
3\$\begingroup\$ If speed is your number-one concern, and you do not mind sacrificing a bit of accuracy, this is the best answer. \$\endgroup\$ Oct 24, 2010 at 21:07
-
1\$\begingroup\$ I don't know about "best" - As shown in another answer, you can get another very good approximation in five ops + abs (the speed of which depends on your arch / compiler, but is often branchless). If the lookup table is not in cache, it's going to be much slower. \$\endgroup\$– user744Oct 26, 2010 at 12:31
You might want to read this too, it's got fast sine and cosine approximations
-
1\$\begingroup\$ This link is 404. But you can find a backup here: web.archive.org/web/20110925033606/http://lab.polygonal.de/2007/… \$\endgroup\$– eisbergJun 26, 2013 at 12:21