Search code examples
javascriptatomictyped-arrays

Using Atomics and Float32Array in JavaScript


The Atomics.store/load methods (and others? didn't look) do not support Float32Array. I read that this is to be consistent with the fact that it also doesn't support Float64Array for compatibility reasons (some computers don't support it).

Aside from the fact that I think this is stupid, does this also mean I must cast every float I want to use into an unsigned int?

Not only will this result in ugly code, it will also make it slower.

E.g.:

let a = new Float32Array(1); // Want the result here

Atomics.store(a, 0, 0.5); // Oops, can't use Float32Array

let b = new Float32Array(1); // Want the result here

let uint = new Uint32Array(1);
let float = new Float32Array(uint.buffer);

float[0] = 0.5;

Atomics.store(b, 0, uint[0]);

Solution

  • As you discovered, the Atomics methods doesn't support floating point values as argument:

    Atomics.store(typedArray, index, value)

    typedArray
        A shared integer typed array. One of Int8Array, Uint8Array, Int16Array, Uint16Array, Int32Array,
        or Uint32Array.

    You can can read the IEEE754 representation as integer from the underlying buffer as you do in the example code you posted

    var buffer = new ArrayBuffer(4);         // common buffer
    var float32 = new Float32Array(buffer);  // floating point
    var uint32 = new Uint32Array(buffer);    // IEEE754 representation
    
    float32[0] = 0.5;
    console.log("0x" + uint32[0].toString(16));
    
    uint32[0] = 0x3f000000;   /// IEEE754 32-bit representation of 0.5
    console.log(float32[0]);

    or you can use fixed numbers if the accuracy isn't important. The accuracy is of course determined by the magnitude.

    Scale up when storing:

    Atomics.store(a, 0, Math.round(0.5 * 100)); // 0.5 -> 50 (max two decimals with 100)
    

    read back and scale down:

    value = Atomics.load(a, 0) * 0.01;          // 50 -> 0.5