This commit is contained in:
Brooke Vibber 2023-01-07 22:02:26 -08:00
parent c5a62cfa1d
commit a47836a39a
3 changed files with 180 additions and 35 deletions

View file

@ -8,7 +8,8 @@ let inputRange = 4;
let shift = 4; let shift = 4;
let base = 2 ** (bits - shift); let base = 2 ** (bits - shift);
let reduction = 4; //let reduction = 4;
let reduction = 0;
let roundOffset = (2 ** (reduction - 1)) + 1; let roundOffset = (2 ** (reduction - 1)) + 1;
let entries = 2 ** (bits - reduction); let entries = 2 ** (bits - reduction);
let bytes = Math.ceil(bits / 8) * entries; let bytes = Math.ceil(bits / 8) * entries;

View file

@ -8,14 +8,28 @@
<body> <body>
<h1>Mandelbrot fixed-point test</h1> <h1>Mandelbrot fixed-point test</h1>
<h2>Float</h2> <table>
<canvas id="float" width="256" height="256"></canvas> <tr>
<th>Float</th>
<h2>Fixed-point imul</h2> <th>Fixed-point imul</th>
<canvas id="imul" width="256" height="256"></canvas> <th>Fixed-point log</th>
</tr>
<h2>Fixed-point log</h2> <tr>
<canvas id="log" width="256" height="256"></canvas> <td><canvas id="float" width="256" height="256"></canvas></td>
<td><canvas id="imul" width="256" height="256"></canvas></td>
<td><canvas id="log" width="256" height="256"></canvas></td>
</tr>
<tr>
<td colspan=3>
<button id="zoom-in">Zoom in</button>
<button id="zoom-out">Zoom out</button>
<button id="left">Left</button>
<button id="right">Right</button>
<button id="up">Up</button>
<button id="down">Down</button>
</td>
</tr>
</table>
<script async type="module" src="sim.js"></script> <script async type="module" src="sim.js"></script>
</body> </body>

154
sim.js
View file

@ -1,9 +1,50 @@
import {toFixed, toFloat, mul} from './fixed.js'; 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 max = 256;
let width = 256; let width = 256;
let height = 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 black = 0xff000000;
let tricolor = [ let tricolor = [
@ -17,33 +58,73 @@ palette[0] = black;
for (let i = 0; i < 255; i++) { for (let i = 0; i < 255; i++) {
palette[i + 1] = tricolor[i % 3]; palette[i + 1] = tricolor[i % 3];
} }
function nap() { function nap(ms=0) {
return new Promise((resolve) => setTimeout(() => resolve())); 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) { async function setup(id, iterfunc) {
let canvas = document.getElementById(id); let canvas = document.getElementById(id);
let ctx = canvas.getContext('2d'); let ctx = canvas.getContext('2d');
let imageData = ctx.createImageData(width, height); let imageData = ctx.createImageData(width, height);
let rgba = new Uint32Array(imageData.data.buffer); let rgba = new Uint32Array(imageData.data.buffer);
cancelled = false;
for (let y = 0; y < height; y++) { 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++) { 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 i = iterfunc(cx, cy);
let color = palette[i]; let color = palette[i];
rgba[y * width + x] = color; rgba[y * width + x] = color;
rgba[(256 - y) * width + x] = color;
if (x % 16 == 15) { if (x % 256 == 255) {
ctx.putImageData(imageData, 0, 0); ctx.putImageData(imageData, 0, 0);
await nap(); await nap();
if (cancelled) {
return;
}
} }
} }
} }
} }
setup('float', (cx, cy) => { function run() {
setup('float', (cx, cy) => {
let zx = 0; let zx = 0;
let zy = 0; let zy = 0;
let zx_2 = 0; let zx_2 = 0;
@ -55,11 +136,60 @@ setup('float', (cx, cy) => {
zx_2 = zx * zx; zx_2 = zx * zx;
zy_2 = zy * zy; zy_2 = zy * zy;
zx_zy = zx * zy; zx_zy = zx * zy;
if (zx_2 >= 4 || zy_2 >= 4 || zx_2 + zy_2 >= 4) { if (zx_2 + zy_2 >= 4) {
return i; return i;
} }
} }
return 0; return 0;
}).then(() => { }).then(() => {
console.log('done'); 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();