blob: c961e9dfdde5344b45a55f40563a1460055666d8 [file] [log] [blame]
// Mandelbrot Benchmark
// Author: Peter Jensen
(function () {
// Kernel configuration
var kernelConfig = {
kernelName: "Mandelbrot",
kernelInit: initMandelbrot,
kernelCleanup: cleanupMandelbrot,
kernelSimd: simdMandelbrot,
kernelNonSimd: nonSimdMandelbrot,
kernelIterations: 10000
};
// Hook up to the harness
benchmarks.add (new Benchmark (kernelConfig));
function Float32x4ToString (f4) {
return "[" + SIMD.Float32x4.extractLane(f4, 0) + "," +
SIMD.Float32x4.extractLane(f4, 1) + "," +
SIMD.Float32x4.extractLane(f4, 2) + "," +
SIMD.Float32x4.extractLane(f4, 3) + "]";
}
function Int32x4ToString (i4) {
return "[" + SIMD.Int32x4.extractLane(i4, 0) + "," +
SIMD.Int32x4.extractLane(i4, 1) + "," +
SIMD.Int32x4.extractLane(i4, 2) + "," +
SIMD.Int32x4.extractLane(i4, 3) + "]";
}
function mandelx1(c_re, c_im, max_iterations) {
var z_re = c_re,
z_im = c_im,
i;
for (i = 0; i < max_iterations; i++) {
var z_re2 = z_re*z_re;
var z_im2 = z_im*z_im;
if (z_re2 + z_im2 > 4.0)
break;
var new_re = z_re2 - z_im2;
var new_im = 2.0 * z_re * z_im;
z_re = c_re + new_re;
z_im = c_im + new_im;
}
return i;
}
function mandelx4(c_re4, c_im4, max_iterations) {
var z_re4 = c_re4;
var z_im4 = c_im4;
var four4 = SIMD.Float32x4.splat (4.0);
var two4 = SIMD.Float32x4.splat (2.0);
var count4 = SIMD.Int32x4.splat (0);
var one4 = SIMD.Int32x4.splat (1);
for (var i = 0; i < max_iterations; ++i) {
var z_re24 = SIMD.Float32x4.mul (z_re4, z_re4);
var z_im24 = SIMD.Float32x4.mul (z_im4, z_im4);
var mi4 = SIMD.Float32x4.lessThanOrEqual (SIMD.Float32x4.add (z_re24, z_im24), four4);
// if all 4 values are greater than 4.0, there's no reason to continue
if (mi4.signMask === 0x00) {
break;
}
var new_re4 = SIMD.Float32x4.sub(z_re24, z_im24);
var new_im4 = SIMD.Float32x4.mul(SIMD.Float32x4.mul (two4, z_re4), z_im4);
z_re4 = SIMD.Float32x4.add(c_re4, new_re4);
z_im4 = SIMD.Float32x4.add(c_im4, new_im4);
count4 = SIMD.Int32x4.add(count4, SIMD.Int32x4.and (mi4, one4));
}
return count4;
}
function sanityCheck() {
var simd = simdMandelbrot(1);
var nonSimd = nonSimdMandelbrot(1);
if (simd.length !== nonSimd.length) {
return false;
}
for (var i = 0, n = simd.length; i < n; ++i) {
if (simd[i] !== nonSimd[i]) {
return false;
}
}
return true;
}
function initMandelbrot() {
return sanityCheck();
}
function cleanupMandelbrot() {
return sanityCheck();
}
// Non SIMD version of the kernel
function nonSimdMandelbrot (n) {
var result = new Array (4);
for (var i = 0; i < n; ++i) {
result [0] = mandelx1 (0.01, 0.01, 100);
result [1] = mandelx1 (0.01, 0.01, 100);
result [2] = mandelx1 (0.01, 0.01, 100);
result [3] = mandelx1 (0.01, 0.01, 100);
}
return result;
}
// SIMD version of the kernel
function simdMandelbrot (n) {
var result = new Array (4);
var vec0 = SIMD.Float32x4.splat (0.01);
for (var i = 0; i < n; ++i) {
var r = mandelx4 (vec0, vec0, 100);
result [0] = SIMD.Int32x4.extractLane(r, 0);
result [1] = SIMD.Int32x4.extractLane(r, 1);
result [2] = SIMD.Int32x4.extractLane(r, 2);
result [3] = SIMD.Int32x4.extractLane(r, 3);
}
return result;
}
} ());