Created
February 28, 2012 16:32
-
-
Save jcdickinson/1933489 to your computer and use it in GitHub Desktop.
Sin Lookup Table
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Collections.Generic; | |
using System.Linq; | |
using System.Text; | |
using System.Runtime.InteropServices; | |
namespace FastMath | |
{ | |
public class FastTrig | |
{ | |
// Care when going over 512: | |
// 512 (perfect NT page size) = 93ms. | |
// 16384 = 90ms. | |
// This contradicted what I just said - so I will leave it at 16384. | |
private const int MaxCircleAngle = 16384; | |
private const int HalfMaxCircleAngle = MaxCircleAngle / 2; | |
private const int QuarterMaxCircleAngle = MaxCircleAngle / 4; | |
private const int MaskMaxCircleAngle = MaxCircleAngle - 1; | |
private const double PiOverHalfCircleAngle = Math.PI / HalfMaxCircleAngle; | |
private const float HalfMaxCircleOverPiSingle = HalfMaxCircleAngle / (float)Math.PI; | |
private const double HalfMaxCircleOverPiDouble = HalfMaxCircleAngle / Math.PI; | |
private static readonly float[] _singleLookup = new float[MaxCircleAngle]; | |
private static readonly double[] _doubleLookup = new double[MaxCircleAngle]; | |
static FastTrig() | |
{ | |
for (var i = 0; i < MaxCircleAngle; i++) | |
{ | |
_singleLookup[i] = (float) | |
(_doubleLookup[i] = Math.Sin(i * PiOverHalfCircleAngle)); | |
} | |
} | |
public static float Cos(float radians) | |
{ | |
var i = (int)(radians * HalfMaxCircleOverPiSingle); | |
if (i < 0) | |
{ | |
return _singleLookup[(QuarterMaxCircleAngle - i) & MaskMaxCircleAngle]; | |
} | |
else | |
{ | |
return _singleLookup[(QuarterMaxCircleAngle + i) & MaskMaxCircleAngle]; | |
} | |
} | |
public static float Sin(float radians) | |
{ | |
var i = (int)(radians * HalfMaxCircleOverPiSingle); | |
if (i < 0) | |
{ | |
return _singleLookup[MaxCircleAngle - ((-i) & MaskMaxCircleAngle)]; | |
} | |
else | |
{ | |
return _singleLookup[i & MaskMaxCircleAngle]; | |
} | |
} | |
public static double Cos(double radians) | |
{ | |
var i = (int)(radians * HalfMaxCircleOverPiDouble); | |
if (i < 0) | |
{ | |
return _doubleLookup[(QuarterMaxCircleAngle - i) & MaskMaxCircleAngle]; | |
} | |
else | |
{ | |
return _doubleLookup[(QuarterMaxCircleAngle + i) & MaskMaxCircleAngle]; | |
} | |
} | |
public static double Sin(double radians) | |
{ | |
var i = (int)(radians * HalfMaxCircleOverPiDouble); | |
if (i < 0) | |
{ | |
return _doubleLookup[QuarterMaxCircleAngle - ((-i) & MaskMaxCircleAngle)]; | |
} | |
else | |
{ | |
return _doubleLookup[i & MaskMaxCircleAngle]; | |
} | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Collections.Generic; | |
using System.Linq; | |
using System.Text; | |
using System.Diagnostics; | |
namespace FastMath | |
{ | |
class Program | |
{ | |
private const int Iterations = 5000000; | |
static void Main(string[] args) | |
{ | |
Bench("Math.Sin", () => Math.Sin(1)); | |
Bench("Math.Cos", () => Math.Cos(1)); | |
Bench("FastTrig.Sin", () => FastTrig.Sin(1)); | |
Bench("FastTrig.Cos", () => FastTrig.Cos(1)); | |
Console.Write("Press any key to graph Sin..."); | |
Console.ReadKey(true); | |
Console.Clear(); | |
DrawGraph(-1, 1, -(float)Math.PI, (float)Math.PI, | |
Tuple.Create<ConsoleColor, Func<float, float>>(ConsoleColor.Red, (x) => (float)Math.Sin(x)), | |
Tuple.Create<ConsoleColor, Func<float, float>>(ConsoleColor.Green, (x) => (float)FastTrig.Sin(x)) | |
); | |
Console.Write("Press any key to graph Cos..."); | |
Console.ReadKey(true); | |
Console.Clear(); | |
DrawGraph(-1, 1, -(float)Math.PI, (float)Math.PI, | |
Tuple.Create<ConsoleColor, Func<float, float>>(ConsoleColor.Red, (x) => (float)Math.Cos(x)), | |
Tuple.Create<ConsoleColor, Func<float, float>>(ConsoleColor.Green, (x) => (float)FastTrig.Cos(x)) | |
); | |
Console.Write("Press any key to quit..."); | |
Console.ReadKey(true); | |
} | |
// Console graphs too accurate. | |
static void DrawGraph( | |
float vmin, | |
float vmax, | |
float hmin, | |
float hmax, | |
params Tuple<ConsoleColor, Func<float, float>>[] functions | |
) | |
{ | |
var vrange = vmax - vmin; | |
var hrange = hmax - hmin; | |
var vscale = (Console.WindowHeight - 1) / vrange; | |
var hscale = hrange / (Console.WindowWidth - 1); | |
for (var i = 0; i < Console.WindowWidth - 1; i++) | |
{ | |
var hval = (hscale * i) + hmin; | |
foreach (var item in functions) | |
{ | |
var vval = (item.Item2(hval) - vmin) * vscale; | |
Console.SetCursorPosition(i, (int)vval); | |
Console.ForegroundColor = item.Item1; | |
Console.Write("."); | |
} | |
} | |
Console.ResetColor(); | |
Console.SetCursorPosition(0, Console.WindowHeight - 1); | |
} | |
static void Bench(string description, Action act) | |
{ | |
// Warm up. | |
for (var i = 0; i < 10; i++) | |
act(); | |
var sw = new Stopwatch(); | |
sw.Start(); | |
sw.Stop(); | |
sw.Reset(); | |
Console.WriteLine("Benching {0}", description); | |
sw.Start(); | |
for (var i = 0; i < Iterations; i++) | |
act(); | |
sw.Stop(); | |
Console.WriteLine("Took {0:0.0} ms for {1} iterations", sw.Elapsed.TotalMilliseconds, Iterations); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment