Skip to content

Instantly share code, notes, and snippets.

@grind086
Last active January 14, 2019 14:51
Show Gist options
  • Save grind086/5990400c9ca8c81e31927fda2a1cacc7 to your computer and use it in GitHub Desktop.
Save grind086/5990400c9ca8c81e31927fda2a1cacc7 to your computer and use it in GitHub Desktop.
Adding data to NaN values
console.log(examineNaN(NaN));
// > { isNaN: true, sign: 0, signaling: false, payload: 0 }
const nan = createNaN(false, false, 5000);
console.log(isNaN(nan));
// > true
console.log(examineNaN(nan));
// > { isNaN: true, sign: 0, signaling: false, payload: 5000 }
const nan2 = createNaN(false, false, [1, 2, 3, 4, 5, 6]);
console.log(isNaN(nan2));
// > true
console.log(examineNaN(nan2));
// > { isNaN: true, sign: 0, signaling: false, payload: Uint8Array [ 1, 2, 3, 4, 5, 6 ] }
console.log(examineNaN(nan + 3).payload === examineNaN(nan).payload);
// > true
/**
* @param {boolean} sign false is positive, true is negative
* @param {boolean} signaling Whether or not this is a signaling NaN
* @param {number | number[] | Uint8Array} payload A single 32-bit integer or an array of up to 6 bytes.
*/
function createNaN(sign, signaling, payload) {
const buf = new ArrayBuffer(8);
const view = new DataView(buf);
const isByteArray = !('number' === typeof payload);
if (isByteArray) {
const byteCount = Math.min(6, payload.length);
for (let i = 0; i < byteCount; i++) {
view.setUint8(i + 2, payload[i]);
}
} else {
view.setUint32(4, parseInt(payload), false);
}
view.setUint8(0, (sign << 7) | 0b01111111);
view.setUint8(1, 0b11110100 | ((!signaling) << 3) | isByteArray);
return view.getFloat64(0);
}
/**
* @param {number} value
*/
function examineNaN(value) {
const buf = new ArrayBuffer(8);
const view = new DataView(buf);
view.setFloat64(0, value);
const ui8_0 = view.getUint8(0);
const ui8_1 = view.getUint8(1);
const signValue = (ui8_0 & 0b10000000) >> 7;
const signalingValue = ui8_1 & 0b00001000;
const exponentValue = ((ui8_0 & 0b011111111) << 4) | ((ui8_1 & 0b11110000) >> 4);
view.setUint8(0, 0);
view.setUint8(1, ui8_1 & 0b00001111);
const significandValue = view.getFloat64(0);
const isNaNValue = !!significandValue && exponentValue === 2047;
const isByteArray = (ui8_1 & 0b00000001);
return {
isNaN: isNaNValue,
sign: signValue,
signaling: isNaNValue ? !signalingValue : undefined,
payload: isNaNValue ? (isByteArray ? new Uint8Array(buf, 2, 6) : view.getUint32(4, false)) : undefined
};
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment