This commit is contained in:
Brooke Vibber 2023-01-07 20:06:12 -08:00
parent 38005a6f7d
commit a34687ba25

View file

@ -1,19 +1,20 @@
// i/o range: 16 bits // i/o range: 16 bits
let bits = 16; let bits = 16;
// Room to hold values up to 15.9 for 16-bit mandelbrot // max Mandelbrot zx/zy addition range prior to checking distance
let inputRange = 4;
// Room to hold power up to -12/+4 for 16-bit mandelbrot
let shift = 4; let shift = 4;
let base = 2 ** (bits - shift); let base = 2 ** (bits - shift);
let inputRange = 8; // max Mandelbrot zx/zy addition range prior to checking distance
let reduction = 0; 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;
// try to keep all but the last few bits semi-accurate // try to keep all but the last few bits semi-accurate
let epsilonBits = 2; let epsilonBits = 1;
let epsilon = 2 ** epsilonBits; let epsilon = 2 ** epsilonBits;
function toFixed(float) { function toFixed(float) {
@ -34,15 +35,15 @@ function toIndex(fixed) {
} }
// x -> log2 x // x -> log2 x
let enloggen = new Uint32Array(entries); let enloggen = new Int32Array(entries);
for (let i = 0; i < entries; i++) { for (let i = 0; i < entries; i++) {
enloggen[i] = toFixed(Math.log2(toFloat(i << reduction))); enloggen[i] = toFixed(Math.log2(toFloat(i << reduction)));
} }
// x -> 2 ^ x // x -> 2 ^ x
let empower = new Uint32Array(entries * 2); let empower = new Int32Array(entries * 2);
for (let i = 0; i < entries * 2; i++) { for (let i = 0; i < entries * 2; i++) {
empower[i] = toFixed(2 ** toFloat(i << reduction)); empower[i] = toFixed(2 ** toFloat(i - entries << reduction));
} }
@ -53,7 +54,11 @@ function log2(fixed) {
// returns rounded integer // returns rounded integer
function pow2(fixed) { function pow2(fixed) {
return empower[toIndex(fixed)]; let n = toIndex(fixed);
if (n > empower.length) {
n = empower.length - 1;
}
return empower[entries + n];
} }
function mul(a, b) { function mul(a, b) {
@ -64,7 +69,7 @@ function mul(a, b) {
let sum = la + lb; let sum = la + lb;
if (sum >= 2 * entries) { if (sum >= 2 * entries) {
// overflow // overflow
throw new Error('overflow on mul'); //throw new Error('overflow on mul');
} }
return pow2(la + lb); return pow2(la + lb);
} }
@ -104,13 +109,18 @@ while (true) {
let expected = toFixed(toFloat(a) * toFloat(b)); let expected = toFixed(toFloat(a) * toFloat(b));
let result = mul(a, b); let result = mul(a, b);
if (result === NaN || result === undefined) {
console.log(a, b, result);
console.log(log2(a), log2(b));
throw new Error('invalid');
}
//console.log(`fixed a ${a} b ${b} expected ${expected} result ${result}`); console.log(`fixed a ${a} b ${b} expected ${expected} result ${result} loga ${log2(a)} logb ${log2(b)} sum ${log2(a)+log2(b)} pow ${pow2(log2(a)+log2(b))}`);
//console.log(`float a ${toFloat(a)} b ${toFloat(b)} expected ${toFloat(expected)} result ${toFloat(result)} loga ${toFloat(log2(a))} logb ${toFloat(log2(b))} pow ${toFloat(pow2(log2(a)+log2(b)))}`); console.log(`float a ${toFloat(a)} b ${toFloat(b)} expected ${toFloat(expected)} result ${toFloat(result)} loga ${toFloat(log2(a))} logb ${toFloat(log2(b))} sum ${toFloat(log2(a)+log2(b))} pow ${toFloat(pow2(log2(a)+log2(b)))}`);
let delta = Math.abs(result - expected); let delta = Math.abs(result - expected);
if (delta > 0) { if (delta >= epsilon) {
let percent = 100 * (delta / expected); let percent = 100 * (delta / expected);
if (delta > epsilon) { if (delta > epsilon) {
console.log(`${toFloat(a)} * ${toFloat(b)} = ${toFloat(expected)}, but got ${toFloat(result)} delta ${toFloat(delta)} ${Math.round(percent * 100) / 100}%`); console.log(`${toFloat(a)} * ${toFloat(b)} = ${toFloat(expected)}, but got ${toFloat(result)} delta ${toFloat(delta)} ${Math.round(percent * 100) / 100}%`);
@ -118,7 +128,7 @@ while (true) {
deltas += delta; deltas += delta;
deltaCount++; deltaCount++;
} else { } else {
//console.log(`${toFloat(a)} * ${toFloat(b)} = ${toFloat(result)}`); console.log(`${toFloat(a)} * ${toFloat(b)} = ${toFloat(result)}`);
} }
count++; count++;
if (count > 10000) { if (count > 10000) {