diff --git a/fixed.js b/fixed.js deleted file mode 100644 index 397de0f..0000000 --- a/fixed.js +++ /dev/null @@ -1,155 +0,0 @@ -// i/o range: 16 bits -let bits = 16; - -// 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 base = 2 ** (bits - shift); - -let reduction = 4; -let roundOffset = (2 ** (reduction - 1)) + 1; -let entries = 2 ** (bits - reduction); -let bytes = Math.ceil(bits / 8) * entries; - -// try to keep all but the last few bits semi-accurate -let epsilonBits = 1 ; -let epsilon = 2 ** epsilonBits; - -function toFixed(float) { - return Math.round(float * base); -} - -function toFloat(fixed) { - return fixed / base; -} - -function toIndex(fixed) { - let n = (fixed + roundOffset) >> reduction; - if (n == entries) { - // round down for the maxo for now - n--; - } - return n; -} - -// x -> log2 x -let enloggen = new Int32Array(entries); -for (let i = 0; i < entries; i++) { - enloggen[i] = toFixed(Math.log2(toFloat(i << reduction))); -} - -// x -> 2 ^ x -let empower = new Int32Array(entries * 2); -for (let i = 0; i < entries * 2; i++) { - empower[i] = toFixed(2 ** toFloat(i - entries << reduction)); -} - - -// returns fixed point -function log2(fixed) { - return enloggen[toIndex(fixed)]; -} - -// returns rounded integer -function pow2(fixed) { - let n = toIndex(fixed); - if (n > empower.length) { - n = empower.length - 1; - } - return empower[entries + n]; -} - -function mul(a, b) { - if (a == 0) return 0; - if (b == 0) return 0; - let la = log2(a)|0; - let lb = log2(b)|0; - let sum = la + lb; - if (sum >= 2 * entries) { - // overflow - //throw new Error('overflow on mul'); - } - return pow2(la + lb); -} - -/* -for (let i = 0; i < logEntries; i++) { - let l = log2(i); - let p = pow2(l); - console.log(`${i} ${l} ${p}`) - if (i !== p) { - console.log(`mismatch ${i} expected, got ${p} via log value ${l} (${toFloat(l)})`); - } -} - -console.log('empower'); -for (let i = 0; i < powEntries; i++) { - let fixed = i << reduction; - let float = toFloat(fixed); - let val = pow2(fixed); - console.log(`${i} ${fixed} ${float} ${val}`) -} -*/ - -// now just try multipling numbers -let deltas = 0; -let deltaAvg = 0; -let deltaCount = 0; -let count = 0; - -function round(n, x) { - return Math.round(x * n) / n; -} - -while (true) { - let a = toFixed(Math.random() * inputRange); - let b = toFixed(Math.random() * inputRange); - - let expected = toFixed(toFloat(a) * toFloat(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} 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))} sum ${toFloat(log2(a)+log2(b))} pow ${toFloat(pow2(log2(a)+log2(b)))}`); - - let delta = Math.abs(result - expected); - - if (delta >= epsilon) { - let percent = 100 * (delta / expected); - if (delta > epsilon) { - console.log(`${toFloat(a)} * ${toFloat(b)} = ${toFloat(expected)}, but got ${toFloat(result)} delta ${toFloat(delta)} ${Math.round(percent * 100) / 100}%`); - } - deltas += delta; - deltaCount++; - } else { - console.log(`${toFloat(a)} * ${toFloat(b)} = ${toFloat(result)}`); - } - count++; - if (count > 10000) { - break; - } -} - -deltaAvg = deltas / count; -console.log(`${count - deltaCount} of ${count} ok -- ${deltaCount} off by avg ${toFloat(deltaAvg)} -- fixed ${round(10,deltaAvg)}`); -count = 0; -deltas = 0; -deltaCount = 0; - -console.log('done'); - - -console.log(`size of enloggen table: ${entries} entries, ${bytes} bytes`); -console.log(`size of empower table: ${entries * 2} entries, ${bytes * 2} bytes`); - -let m = 0; -for (let i = 0; i < enloggen.length; i++) { - m = Math.max(m, enloggen[i]); -} -console.log(`max enloggen entry is ${m}`);