js-hexfloat
Version:
Rudimentary C99 Hexadecimal Floating Point Support in JS
68 lines (67 loc) • 2.24 kB
JavaScript
/*
* Licensed under the MIT license.
* http://www.opensource.org/licenses/mit-license.php
*/
(function (global) {
// ES5 Required
if (! Object.defineProperty) {
throw Error("Object.defineProperty missing");
}
var pat_hexfloat =
'([\+\-]?)0x([0-9A-F]+)\.?([0-9A-F]*)p([\+\-]?[0-9]+)';
// 1 2 3 4
var RE_HEXFLOAT = new RegExp(pat_hexfloat, 'i');
var RE_HEXFLOAT_G = new RegExp(pat_hexfloat, 'gi');
var parseHexFloat = function() {
var m = arguments.length < 2
? RE_HEXFLOAT.exec(arguments[0])
: arguments;
if (!m) {
var mx = (/^([\+\-]?)inf(?:inity)?/i).exec(arguments[0]);
if (!mx) return NaN;
return mx[1] == '-' ? -1/0 : 1/0;
}
var mantissa = parseInt(m[1] + m[2] + m[3], 16);
var exponent = (m[4]|0) - 4*m[3].length;
return mantissa * Math.pow(2, exponent);
};
var toHexString = function() {
if (isNaN(this)) {
return 'nan';
}
var that = +this;
if (Object.is(that, +0.0)) {
return '0x0p+0';
} else if (Object.is(that, -0.0)) {
return '-0x0p+0';
} else if (!isFinite(that)) {
return (that < 0 ? '-' : '') + 'inf';
}
var sign = that < 0 ? '-' : '';
var a = Math.abs(that);
var p = 0;
if (a < 1) {
while (a < 1) { a *= 2; p-- }
} else {
while (a >= 2) { a /= 2; p++ }
}
var es = p < 0 ? '' : '+';
return sign + '0x' + a.toString(16) + 'p' + es + p.toString(10);
};
// install
[
[ global, 'parseHexFloat', parseHexFloat ],
[ Number, 'parseHexFloat', parseHexFloat ],
[ global, 'RE_HEXFLOAT', RE_HEXFLOAT ],
[ global, 'RE_HEXFLOAT_G', RE_HEXFLOAT_G ],
[ Number.prototype, 'toHexString', toHexString ]
].forEach(function(a){
var o = a[0], k = a[1], v = a[2];
if (!o[k]) Object.defineProperty(o, k, {
value: v,
enumerable: false,
writable: true,
configurable: true
})
});
})(typeof root === 'object' ? root : this);