I'm trying to iterate through all 32 bit floating point numbers in JavaScript to visually compare some methods for polynomial evaluation for accuracy. To do so, I've implemented the code shown below. Unfortunately, this code is way too slow.
Would there be any way to improve performance?
In C/C++ the equivalent code runs in a bit over a minute on my computer, whereas I haven't had the patience to see how long this code takes.
function nextFloat(f) {
// Note that this moves away from 0.0
// It will fail at +/- infinity and result in an NaN
var bitRepr = floatToBits(f);
bitRepr++;
return bitsToFloat(bitRepr);
}
function prevFloat(f) {
// Note that this moves towards 0.0
// This will fail at 0.0 and result in an NaN
var bitRepr = floatToBits(f);
bitRepr--;
return bitsToFloat(bitRepr);
}
function floatToBits(f) {
var buf = new ArrayBuffer(4);
(new Float32Array(buf))[0] = f;
return (new Uint32Array(buf))[0];
}
function bitsToFloat(b) {
var buf = new ArrayBuffer(4);
(new Uint32Array(buf))[0] = b;
return (new Float32Array(buf))[0];
}
Another method I might consider is using is multiplying the number by (1 + epsilon), though I believe that has edge cases that I would need to resolve at the bit level anyways.
If your code is synchronous you don't need to be calling new
all the time, this means that you can keep your Uint32Array
and Float32Array
which are linked through the same buffer across all functions, for example
var obj = (function () {
var int = new Uint32Array(1),
float = new Float32Array(int.buffer);
return {
i2f: function (i) {
int[0] = i;
return float[0];
},
f2i: function (f) {
float[0] = f;
return int[0];
},
next: function () {
int[0] = int[0] + 1;
return float[0];
},
prev: function () {
int[0] = int[0] - 1;
return float[0];
}
};
}());
Something like this should work, and doesn't require allocating arrays:
function testall(f) {
var M = Math.pow(2,-126);
var x;
for (p = -1; p <= 1; p +=2) {
for (s = 0; s < 1<<23; s++) {
// subnormals (including zeros)
x = p*M*(s/(1<<23));
f(x);
}
for (b = M; b <= 2/M; b *= 2) {
for (s = 0; s < 1<<23; s++) {
// normals
x = p*b*(1+s/(1<<23));
f(x);
}
}
}
}
This will iterate through all real-valued floats (subnormals and normals). It won't handle Infs (there are only two of those, so I leave them up to you), or NaNs (as far as I know, there is no efficient way to iterate through all the NaN bit patterns in JavaScript).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With