Skip to content

Instantly share code, notes, and snippets.

@tannergooding
Last active September 29, 2017 21:54
Show Gist options
  • Save tannergooding/d1b74360d11b15aaea9c525d9986c394 to your computer and use it in GitHub Desktop.
Save tannergooding/d1b74360d11b15aaea9c525d9986c394 to your computer and use it in GitHub Desktop.
/* The Computer Language Benchmarks Game
http://benchmarksgame.alioth.debian.org/
started with Java #2 program (Krause/Whipkey/Bennet/AhnTran/Enotus/Stalcup)
adapted for C# by Jan de Vaan
simplified and optimised to use TPL by Anthony Lloyd
simplified to compute Cib alongside Crb by Tanner Gooding
optimized to use Vector<double> by Tanner Gooding
*/
using System;
using System.Numerics;
using System.Runtime.CompilerServices;
using System.Threading.Tasks;
public class MandelBrot
{
// Vector<double>.Count is treated as a constant by the JIT, don't both storing
// it in a temporary variable anywhere below.
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private static unsafe byte GetByte(double* pCrb, double Ciby, int x, int y)
{
var res = 0;
for (var i = 0; i < 8; i += 2)
{
var Crbx = Unsafe.Read<Vector<double>>(pCrb + x + i);
var Zr = Crbx;
var vCiby = new Vector<double>(Ciby);
var Zi = vCiby;
var b = 0;
var j = 49;
do
{
var nZr = Zr * Zr - Zi * Zi + Crbx;
Zi = Zr * Zi + Zr * Zi + vCiby;
Zr = nZr;
var t = Zr * Zr + Zi * Zi;
if (t[0] > 4)
{
b |= 2;
if (b == 3)
{
break;
}
}
if (t[1] > 4)
{
b |= 1;
if (b == 3)
{
break;
}
}
} while (--j > 0);
res = (res << 2) + b;
}
return (byte)(res ^ -1);
}
public static unsafe void Main(string[] args)
{
var size = (args.Length > 0) ? int.Parse(args[0]) : 200;
var adjustedSize = (size + (Vector<double>.Count * 8)) & ~(Vector<double>.Count * 8);
var Crb = new double[adjustedSize];
var Cib = new double[adjustedSize];
fixed (double* pCrb = &Crb[0])
fixed (double* pCib = &Cib[0])
{
var invN = new Vector<double>(2.0 / size);
var onePtFive = new Vector<double>(1.5);
var step = new Vector<double>(Vector<double>.Count);
var value = (Vector<double>.Count == 2) ? new Vector<double>(new double[] { 0, 1 })
: (Vector<double>.Count == 4) ? new Vector<double>(new double[] { 0, 1, 2, 3 })
: new Vector<double>(new double[] { 0, 1, 2, 3, 4, 5, 6, 7 });
for (var i = 0; i < size; i += Vector<double>.Count)
{
var t = value * invN;
Unsafe.Write(pCrb + i, t - onePtFive);
Unsafe.Write(pCib + i, t - Vector<double>.One);
value += step;
}
}
var lineLength = size >> 3;
var data = new byte[adjustedSize * lineLength];
fixed (double* pCrb = &Crb[0])
{
var _Crb = pCrb;
Parallel.For(0, size, y =>
{
var offset = y * lineLength;
for (var x = 0; x < lineLength; x++)
{
data[offset + x] = GetByte(_Crb, Cib[y], x * 8, y);
}
});
}
// generate the bitmap header
Console.Out.Write("P4\n{0} {0}\n", size);
Console.OpenStandardOutput().Write(data, 0, size * lineLength);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment