Last active
April 20, 2021 02:25
-
-
Save SPY/505ab63b53d95eb72fe74c88fe8739e4 to your computer and use it in GitHub Desktop.
JS parser for Float Hex notation
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
function floatToWord(f) { | |
let b = new ArrayBuffer(4) | |
let iView = new Uint32Array(b) | |
let fView = new Float32Array(b) | |
fView[0] = f | |
return iView[0] | |
} | |
function wordToFloat(w) { | |
let b = new ArrayBuffer(4) | |
let iView = new Uint32Array(b) | |
let fView = new Float32Array(b) | |
iView[0] = w | |
return fView[0] | |
} | |
function readHexFloat(str) { | |
var [_, sign, int, _, frac, _, expStr] = /^([+-]?)0x([0-9a-f]*)(\.([0-9a-f]*))?([pP]([+-]?\d*))?$/.exec(str.toLowerCase()) | |
let exp = parseInt(expStr || '0', 10) | |
int = int.replace(/^0*/, '') || '0' | |
frac = (frac || '').replace(/0*$/, '') || '0' | |
let w = sign === '-' ? 0x80000000 : 0 | |
if (parseInt(int, 16)) { | |
frac = int + frac | |
exp += int.length * 4 | |
} | |
if (parseInt(frac, 16) === 0) { | |
return wordToFloat(w) | |
} | |
let hexFracWithoutLeadingZeros = frac.replace(/^0*/, '') | |
exp -= (frac.length - hexFracWithoutLeadingZeros.length) * 4 | |
let binFrac = parseInt(frac, 16).toString(2) | |
exp -= hexFracWithoutLeadingZeros.length * 4 - binFrac.length + 1 | |
binFrac = binFrac.replace(/0*$/, '') | |
const budget = Math.min(24, 150 + exp) | |
if (binFrac.length > budget) { | |
let roundedFrac = binFrac.slice(0, budget) | |
let rest = binFrac.slice(budget) | |
if (rest[0] === '1' && (rest.length > 1 || roundedFrac[roundedFrac.length - 1] === '1')) { | |
if (roundedFrac.length === roundedFrac.replace('0', '').length) { | |
exp++ | |
binFrac = '1' | |
} | |
else { | |
binFrac = (parseInt(roundedFrac, 2) + 1).toString(2) | |
} | |
} | |
else { | |
binFrac = roundedFrac | |
} | |
} | |
if (exp < -150 || exp > 127) { | |
throw Error('Constant out of range: ' + exp) | |
} | |
if (exp >= -126) { | |
w = w | ((exp + 127) << 23) | (parseInt(binFrac.slice(1) || '0', 2) << (24 - binFrac.length)) | |
} | |
else { | |
const shift = 150 - binFrac.length - Math.abs(exp) | |
if (shift < 0) { | |
return wordToFloat(w) | |
} | |
w = w | (parseInt(binFrac, 2) << (150 - binFrac.length - Math.abs(exp))) | |
} | |
return wordToFloat(w) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment