diff --git a/fixed.js b/fixed.js
index b1d671d..ec39bee 100644
--- a/fixed.js
+++ b/fixed.js
@@ -8,7 +8,8 @@ let inputRange = 4;
let shift = 4;
let base = 2 ** (bits - shift);
-let reduction = 4;
+//let reduction = 4;
+let reduction = 0;
let roundOffset = (2 ** (reduction - 1)) + 1;
let entries = 2 ** (bits - reduction);
let bytes = Math.ceil(bits / 8) * entries;
diff --git a/sim.html b/sim.html
index 61689cb..a260a0d 100644
--- a/sim.html
+++ b/sim.html
@@ -8,14 +8,28 @@
Mandelbrot fixed-point test
- Float
-
-
- Fixed-point imul
-
-
- Fixed-point log
-
+
+
+ Float |
+ Fixed-point imul |
+ Fixed-point log |
+
+
+ |
+ |
+ |
+
+
+
+
+
+
+
+
+
+ |
+
+
diff --git a/sim.js b/sim.js
index 4f819f0..1050860 100644
--- a/sim.js
+++ b/sim.js
@@ -1,9 +1,50 @@
import {toFixed, toFloat, mul} from './fixed.js';
+
+function imul(a, b) {
+ return Math.imul(a, b) >> 12;
+}
+
+function logmul(a, b) {
+ if ((a | b) == 0) {
+ return 0;
+ }
+ let neg = 0;
+ if (a < 0) {
+ a = -a;
+ neg++;
+ }
+ if (b < 0) {
+ b = -b;
+ neg++;
+ }
+ let product = mul(a, b);
+ if (neg == 1) {
+ product = -product;
+ }
+ return product;
+}
+
+let four = toFixed(4);
+
let max = 256;
let width = 256;
let height = 256;
-let zoom = 1;
+
+let zoom = 0;
+let offsetX = 0;
+let offsetY = 0;
+
+function scale() {
+ return 1 / (2 ** zoom);
+}
+
+let cancelled = false;
+
+async function cancel() {
+ cancelled = true;
+ return await nap(100);
+}
let black = 0xff000000;
let tricolor = [
@@ -17,49 +58,138 @@ palette[0] = black;
for (let i = 0; i < 255; i++) {
palette[i + 1] = tricolor[i % 3];
}
-function nap() {
- return new Promise((resolve) => setTimeout(() => resolve()));
+function nap(ms=0) {
+ return new Promise((resolve) => setTimeout(() => resolve(), ms));
}
+function attach(id, func) {
+ document.getElementById(id).addEventListener('click', (_event) => {
+ cancel().then(() => {
+ func();
+ run();
+ });
+ });
+}
+
+attach('zoom-in', () => {
+ zoom++;
+});
+
+attach('zoom-out', () => {
+ if (zoom >= 1) {
+ zoom--;
+ }
+});
+
+attach('left', () => {
+ offsetX -= scale();
+});
+
+attach('right', () => {
+ offsetX += scale();
+});
+
+attach('up', () => {
+ offsetY -= scale();
+});
+
+attach('down', () => {
+ offsetY += scale();
+});
+
async function setup(id, iterfunc) {
let canvas = document.getElementById(id);
let ctx = canvas.getContext('2d');
let imageData = ctx.createImageData(width, height);
let rgba = new Uint32Array(imageData.data.buffer);
+
+ cancelled = false;
for (let y = 0; y < height; y++) {
- let cy = (y * 2 - height) / (height / 2);
+ let cy = scale() * (y * 2 - height) / (height / 2) + offsetY;
for (let x = 0; x < width; x++) {
- let cx = (x * 2 - width) / (width / 2);
+ let cx = scale() * (x * 2 - width) / (width / 2) + offsetX;
let i = iterfunc(cx, cy);
let color = palette[i];
rgba[y * width + x] = color;
- rgba[(256 - y) * width + x] = color;
- if (x % 16 == 15) {
+ if (x % 256 == 255) {
ctx.putImageData(imageData, 0, 0);
await nap();
+ if (cancelled) {
+ return;
+ }
}
}
}
}
-setup('float', (cx, cy) => {
- let zx = 0;
- let zy = 0;
- let zx_2 = 0;
- let zy_2 = 0;
- let zx_zy = 0;
- for (let i = 1; i < max; i++) {
- zx = zx_2 - zy_2 + cx;
- zy = zx_zy + zx_zy + cy;
- zx_2 = zx * zx;
- zy_2 = zy * zy;
- zx_zy = zx * zy;
- if (zx_2 >= 4 || zy_2 >= 4 || zx_2 + zy_2 >= 4) {
- return i;
+function run() {
+ setup('float', (cx, cy) => {
+ let zx = 0;
+ let zy = 0;
+ let zx_2 = 0;
+ let zy_2 = 0;
+ let zx_zy = 0;
+ for (let i = 1; i < max; i++) {
+ zx = zx_2 - zy_2 + cx;
+ zy = zx_zy + zx_zy + cy;
+ zx_2 = zx * zx;
+ zy_2 = zy * zy;
+ zx_zy = zx * zy;
+ if (zx_2 + zy_2 >= 4) {
+ return i;
+ }
}
- }
- return 0;
-}).then(() => {
- console.log('done');
-})
\ No newline at end of file
+ return 0;
+ }).then(() => {
+ console.log('float done');
+ });
+
+ setup('imul', (cx, cy) => {
+ cx = toFixed(cx);
+ cy = toFixed(cy);
+ let zx = 0;
+ let zy = 0;
+ let zx_2 = 0;
+ let zy_2 = 0;
+ let zx_zy = 0;
+ for (let i = 1; i < max; i++) {
+ zx = zx_2 - zy_2 + cx;
+ zy = zx_zy + zx_zy + cy;
+ zx_2 = imul(zx, zx);
+ zy_2 = imul(zy, zy);
+ zx_zy = imul(zx, zy);
+ if (zx_2 + zy_2 >= four) {
+ return i;
+ }
+ }
+ return 0;
+ }).then(() => {
+ console.log('imul done');
+ });
+
+ setup('log', (cx, cy) => {
+ cx = toFixed(cx);
+ cy = toFixed(cy);
+ let zx = 0;
+ let zy = 0;
+ let zx_2 = 0;
+ let zy_2 = 0;
+ let zx_zy = 0;
+ for (let i = 1; i < max; i++) {
+ zx = zx_2 - zy_2 + cx;
+ zy = zx_zy + zx_zy + cy;
+ zx_2 = logmul(zx, zx);
+ zy_2 = logmul(zy, zy);
+ zx_zy = logmul(zx, zy);
+ if (zx_2 + zy_2 >= four) {
+ return i;
+ }
+ }
+ return 0;
+ }).then(() => {
+ console.log('log done');
+ });
+}
+
+run();
\ No newline at end of file