Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Open
JobLeonard opened this issue Mar 9, 2018 · 0 comments
Open

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

JobLeonard opened this issue Mar 9, 2018 · 0 comments

Comments

@JobLeonard
Copy link

JobLeonard commented Mar 9, 2018

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?

@JobLeonard JobLeonard changed the title Thanks, and a possible example to add? Thanks, and a possible example to add: faking a C-stye union Mar 9, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant