diff --git a/CHANGELOG.md b/CHANGELOG.md index d3936b15f732..66e0169d7a55 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,8 @@ ## Changelog ##### Unreleased - Added [`ArrayBuffer.prototype.{ transfer, transferToFixedLength }`](https://github.com/tc39/proposal-arraybuffer-transfer) and support transferring of `ArrayBuffer`s via [`structuredClone`](https://html.spec.whatwg.org/multipage/structured-data.html#dom-structuredclone) to engines with `MessageChannel` +- Optimized [`Math.f16round`](https://github.com/tc39/proposal-float16array) polyfill +- Fixed [some conversion cases](https://github.com/petamoriken/float16/issues/1046) of `Math.f16round` - Fully forced polyfilling of [the TC39 `Observable` proposal](https://github.com/tc39/proposal-observable) because of incompatibility with [the new WHATWG `Observable` proposal](https://github.com/WICG/observable) - Added an extra workaround of errors with exotic environment objects in `Symbol` polyfill, [#1289](https://github.com/zloirock/core-js/issues/1289) - Compat data improvements: diff --git a/packages/core-js/internals/math-f16round.js b/packages/core-js/internals/math-f16round.js new file mode 100644 index 000000000000..09fd7da38599 --- /dev/null +++ b/packages/core-js/internals/math-f16round.js @@ -0,0 +1,29 @@ +'use strict'; +var sign = require('../internals/math-sign'); + +var abs = Math.abs; + +var EPSILON = 2.220446049250313e-16; // Number.EPSILON +var EPSILON16 = 0.0009765625; // 2 ** -10 +var INVERSE_EPSILON = 1 / EPSILON; +var MAX16 = 65504; // 2 ** 15 - 2 ** 10 +var MIN16 = 6.103515625e-05; // 2 ** -14 + +var roundTiesToEven = function (n) { + return n + INVERSE_EPSILON - INVERSE_EPSILON; +}; + +// `Math.f16round` method implementation +// https://github.com/tc39/proposal-float16array +module.exports = Math.f16round || function f16round(x) { + var n = +x; + var $abs = abs(n); + var $sign = sign(n); + var a, result; + if ($abs < MIN16) return $sign * roundTiesToEven($abs / MIN16 / EPSILON16) * MIN16 * EPSILON16; + a = (1 + EPSILON16 / EPSILON) * $abs; + result = a - (a - $abs); + // eslint-disable-next-line no-self-compare -- NaN check + if (result > MAX16 || result !== result) return $sign * Infinity; + return $sign * result; +}; diff --git a/packages/core-js/internals/math-fround.js b/packages/core-js/internals/math-fround.js index b5e35d3cfb2b..9c5758269be2 100644 --- a/packages/core-js/internals/math-fround.js +++ b/packages/core-js/internals/math-fround.js @@ -2,14 +2,15 @@ var sign = require('../internals/math-sign'); var abs = Math.abs; -var pow = Math.pow; -var EPSILON = pow(2, -52); -var EPSILON32 = pow(2, -23); -var MAX32 = pow(2, 127) * (2 - EPSILON32); -var MIN32 = pow(2, -126); + +var EPSILON = 2.220446049250313e-16; // Number.EPSILON +var EPSILON32 = 1.1920928955078125e-7; // 2 ** -23; +var INVERSE_EPSILON = 1 / EPSILON; +var MAX32 = 3.4028234663852886e+38; // 2 ** 128 - 2 ** 104 +var MIN32 = 1.1754943508222875e-38; // 2 ** -126; var roundTiesToEven = function (n) { - return n + 1 / EPSILON - 1 / EPSILON; + return n + INVERSE_EPSILON - INVERSE_EPSILON; }; // `Math.fround` method implementation diff --git a/packages/core-js/modules/esnext.math.f16round.js b/packages/core-js/modules/esnext.math.f16round.js index 5ad662e5524d..09a3e012998a 100644 --- a/packages/core-js/modules/esnext.math.f16round.js +++ b/packages/core-js/modules/esnext.math.f16round.js @@ -1,16 +1,7 @@ 'use strict'; var $ = require('../internals/export'); -var IEEE754 = require('../internals/ieee754'); - -var packIEEE754 = IEEE754.pack; -var unpackIEEE754 = IEEE754.unpack; -var $isFinite = isFinite; +var f16round = require('../internals/math-f16round'); // `Math.f16round` method // https://github.com/tc39/proposal-float16array -$({ target: 'Math', stat: true }, { - f16round: function f16round(x) { - var n = +x; - return $isFinite(n) && n !== 0 ? unpackIEEE754(packIEEE754(n, 10, 2), 10) : n; - } -}); +$({ target: 'Math', stat: true }, { f16round: f16round }); diff --git a/tests/unit-global/esnext.math.f16round.js b/tests/unit-global/esnext.math.f16round.js index 9b954e2f2295..230e51e085c0 100644 --- a/tests/unit-global/esnext.math.f16round.js +++ b/tests/unit-global/esnext.math.f16round.js @@ -36,6 +36,8 @@ QUnit.test('Math.f16round', assert => { assert.same(f16round(-2.980232238769531911744490042422139897126953655970282852649688720703125e-8), -minFloat16); assert.same(f16round(1.337), 1.3369140625); + assert.same(f16round(0.499994), 0.5); + assert.same(f16round(7.9999999), 8); const checker = createConversionChecker(1.1); assert.same(f16round(checker), 1.099609375, 'object wrapper'); diff --git a/tests/unit-pure/esnext.math.f16round.js b/tests/unit-pure/esnext.math.f16round.js index ba0ec7675155..f7ba20f8a73a 100644 --- a/tests/unit-pure/esnext.math.f16round.js +++ b/tests/unit-pure/esnext.math.f16round.js @@ -35,6 +35,8 @@ QUnit.test('Math.f16round', assert => { assert.same(f16round(-2.980232238769531911744490042422139897126953655970282852649688720703125e-8), -minFloat16); assert.same(f16round(1.337), 1.3369140625); + assert.same(f16round(0.499994), 0.5); + assert.same(f16round(7.9999999), 8); const checker = createConversionChecker(1.1); assert.same(f16round(checker), 1.099609375, 'object wrapper');