changeset 7:47f08ebded06

Fix Cross implementation and add to test matrix
author Chris Cannam
date Mon, 05 Oct 2015 12:54:49 +0100
parents 91d77df352fa
children c6577c4b3780
files fft/cross/FFT.js fft/test.html fft/test.js
diffstat 3 files changed, 82 insertions(+), 1 deletions(-) [+]
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/fft/cross/FFT.js	Mon Oct 05 12:54:49 2015 +0100
@@ -0,0 +1,39 @@
+"use strict";
+
+var fftCross = Module.cwrap(
+    'fftCross', 'void', ['number', 'number', 'number',
+			 'number', 'number', 'number' ]
+);
+
+function FFTCross(size) {
+    this.size = size;
+    this.n = size * 8;
+    this.ptr = Module._malloc(this.n * 4);
+    this.ri = new Uint8Array(Module.HEAPU8.buffer, this.ptr, this.n);
+    this.ii = new Uint8Array(Module.HEAPU8.buffer, this.ptr + this.n, this.n);
+    this.transform = function(real, imag, inverse) {
+	var ptr = this.ptr;
+	var n = this.n;
+	this.ri.set(new Uint8Array(real.buffer));
+	this.ii.set(new Uint8Array(imag.buffer));
+	fftCross(this.size, inverse,
+		 ptr, ptr + n, ptr + n * 2, ptr + n * 3);
+	var ro = new Float64Array(Module.HEAPU8.buffer, ptr + n * 2, this.size);
+	var io = new Float64Array(Module.HEAPU8.buffer, ptr + n * 3, this.size);
+	return { real: ro, imag: io };
+    }
+    this.transformReal = function(real, inverse) {
+	var ptr = this.ptr;
+	var n = this.n;
+	this.ri.set(new Uint8Array(real.buffer));
+	fftCross(this.size, inverse,
+		 ptr, 0, ptr + n * 2, ptr + n * 3);
+	var ro = new Float64Array(Module.HEAPU8.buffer, ptr + n * 2, this.size);
+	var io = new Float64Array(Module.HEAPU8.buffer, ptr + n * 3, this.size);
+	return { real: ro, imag: io };
+    }
+    this.discard = function() {
+	Module._free(this.ptr);
+    }
+}
+
--- a/fft/test.html	Mon Oct 05 11:54:32 2015 +0100
+++ b/fft/test.html	Mon Oct 05 12:54:49 2015 +0100
@@ -1,5 +1,6 @@
 <html>
-
+  <head>
+    
   <meta charset="UTF-8">
 
   <style type="text/css">
@@ -12,8 +13,11 @@
   <script src="fft.js/lib/complex.js"></script>
   <script src="jsfft/lib/complex_array.js"></script>
   <script src="jsfft/lib/fft.js"></script>
+  <script src="cross/Cross.js"></script>
+  <script src="cross/FFT.js"></script>
   <script src="test.js"></script>
 
+  </head>
 <body>
 
   <h3>Results</h3>
@@ -30,6 +34,8 @@
       <td>Nockert</td><td id="nockert-result"></td><td id="nockert-1"></td><td id="nockert-2"></td><td id="nockert-itr"></td>
     </tr><tr>
       <td>Dntj</td><td id="dntj-result"></td><td id="dntj-1"></td><td id="dntj-2"></td><td id="dntj-itr"></td>
+    </tr><tr>
+      <td>Cross</td><td id="cross-result"></td><td id="cross-1"></td><td id="cross-2"></td><td id="cross-itr"></td>
     </tr>
   </table>
 
@@ -39,6 +45,7 @@
     <li><b>Nayuki</b>: in-place single-precision complex-complex</li>
     <li><b>Nockert</b>: double-precision real-complex</li>
     <li><b>Nayuki</b>: double-precision complex-complex. Forward transform is scaled and I've scaled it back again here, which may introduce rounding error.</li>
+    <li><b>Cross</b>: double-precision real-complex in C, compiled with Emscripten. This is considered a slow implementation amongst native code ones.</li>
   </ul>
   
   <h3>Rationale</h3>
--- a/fft/test.js	Mon Oct 05 11:54:32 2015 +0100
+++ b/fft/test.js	Mon Oct 05 12:54:49 2015 +0100
@@ -23,6 +23,13 @@
     return result;
 }
 
+function zeroReal64s(size) {
+    var result = new Float64Array(size);
+    for (var i = 0; i < result.length; i++)
+	result[i] = (i % 20) / 10.0 - 1.0;
+    return result;
+}
+
 function inputComplexArray(size) {
     var result = new complex_array.ComplexArray(size);
     for (var i = 0; i < size; i++) {
@@ -123,6 +130,33 @@
     report("dntj", start, middle, end, total);
 }
 
+function testCross() {
+
+    var fft = new FFTCross(size);
+    
+    var start = performance.now();
+    var middle = start;
+    var end = start;
+
+    total = 0.0;
+
+    for (var i = 0; i < 2*iterations; ++i) {
+	if (i == iterations) {
+	    middle = performance.now();
+	}
+	var ri = inputReal64s(size);
+	var out = fft.transformReal(ri, false);
+	for (var j = 0; j < size; ++j) {
+	    total += 
+		Math.sqrt(out.real[j] * out.real[j] + out.imag[j] * out.imag[j]);
+	}
+    }
+
+    var end = performance.now();
+
+    report("cross", start, middle, end, total);
+}
+
 function test() {
 
     document.getElementById("test-description").innerHTML =
@@ -132,6 +166,7 @@
     testNayuki();
     testNockert();
     testDntj();
+    testCross();
 }
 
 window.onload = test;