ballercat / walt

:zap: Walt is a JavaScript-like syntax for WebAssembly text format :zap:

Home Page:https://ballercat.github.io/walt/

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Thanks, and a possible example to add: faking a C-stye union

JobLeonard opened this issue · comments

So this week, as an experiment, I ported Paul Mineiro's fast log2 approximation (original C repo here) to plain JavaScript:

// Fake a C-union using a typed array
const unionU32 = new Uint32Array(1),
    unionF32 = new Float32Array(unionU32.buffer);

function fastlog2(x) {
    unionF32[0] = x;
    let vx_u = unionU32[0];
    unionU32[0] = (vx_u & 0x007FFFFF) | 0x3F000000;
    let mx_f = unionF32[0];
    return (vx_u * 1.1920928955078125e-7) - 124.22551499 - 1.498030302 * mx_f - 1.72587999 / (0.3520887068 + mx_f);
}

It actually seems to be slightly faster, despite all the overhead involved. Then I figured "I wonder if WASM works... but I don't want to involve a big toolchain just to test that". A bit of searching later, I found Walt, and using your on-line explorer I created this:

const memory: Memory = { 'initial': 1 };

export function fastlog2(x: f32): f32 {
  // To use arrays simple define a type with array subscript
  // Assign arrays to the same address to mimic a C-union
  const uf: f32[] = 1;
  const ui: i32[] = 1;
  uf[0] = x;
  let vx_u : i32 = ui[0];
  ui[0] = (vx_u & 8388607) | 1056964608;
  let mx_f : f32 = uf[0];
  return (vx_u * 0.00000011920928955078125) - 124.22551499 - 1.498030302 * mx_f - 1.72587999 / (0.3520887068 + mx_f);
}

... which I extracted (quite crudely), by typing this in the JS tab of the explorer:

function compile(buffer) {
  console.log(Array.from(new Uint8Array(buffer)))
}

... the output of which was then copied turned into a quick-and-dirty function like this:

WebAssembly.instantiate(Uint8Array.from([0, 97, 115, 109, 1, 0, 0, 0, 1, 6, 1, 96, 1, 125, 1, 125, 3, 2, 1, 0, 5, 3, 1, 0, 1, 7, 12, 1, 8, 102, 97, 115, 116, 108, 111, 103, 50, 0, 0, 10, 125, 1, 123, 4, 1, 127, 1, 127, 1, 127, 1, 125, 65, 1, 33, 1, 65, 1, 33, 2, 32, 1, 65, 0, 65, 2, 116, 106, 32, 0, 56, 2, 0, 32, 2, 65, 0, 65, 2, 116, 106, 40, 2, 0, 33, 3, 32, 2, 65, 0, 65, 2, 116, 106, 32, 3, 65, 255, 255, 255, 3, 113, 65, 128, 128, 128, 248, 3, 114, 54, 2, 0, 32, 1, 65, 0, 65, 2, 116, 106, 42, 2, 0, 33, 4, 32, 3, 178, 67, 0, 0, 0, 52, 148, 67, 119, 115, 248, 66, 147, 67, 117, 191, 191, 63, 32, 4, 148, 147, 67, 163, 233, 220, 63, 67, 249, 68, 180, 62, 32, 4, 146, 149, 147, 15, 11]).buffer).then(result => console.log([0,1,2,3,4,5,67,8,9,10,11,12].map(v => result.instance.exports.fastlog2(v))));
// => [
//  -127, -0.000002384185791015625, 
//  0.999997615814209,
//  1.584951639175415,
//  1.9999973773956299,
//  2.321864604949951,
//  6.065983772277832,
//  2.99999737739563,
//  3.1697850227355957,
//  3.321864604949951,
//  3.45943021774292,
//  3.584951639175415
// ]

It seems to work! Now I just have to figure out how to benchmark it.

Anyway, I haven't seen any examples discussion unions so far. Perhaps this could work for that purpose?