-
-
Notifications
You must be signed in to change notification settings - Fork 1.7k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
9 changed files
with
182 additions
and
0 deletions.
There are no files selected for viewing
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
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
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
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
'use strict'; | ||
require('../../modules/es.array.iterator'); | ||
require('../../modules/esnext.math.sum-precise'); | ||
var path = require('../../internals/path'); | ||
|
||
module.exports = path.Math.sumPrecise; |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,162 @@ | ||
'use strict'; | ||
// based on Shewchuk's algorithm for exactly floating point addition | ||
// adapted from https://github.com/tc39/proposal-math-sum/blob/3513d58323a1ae25560e8700aa5294500c6c9287/polyfill/polyfill.mjs | ||
var $ = require('../internals/export'); | ||
var uncurryThis = require('../internals/function-uncurry-this'); | ||
var iterate = require('../internals/iterate'); | ||
|
||
var $RangeError = RangeError; | ||
var $TypeError = TypeError; | ||
var $Infinity = Infinity; | ||
var $NaN = NaN; | ||
var abs = Math.abs; | ||
var pow = Math.pow; | ||
var push = uncurryThis([].push); | ||
|
||
var POW_2_1023 = pow(2, 1023); | ||
var MAX_SAFE_INTEGER = pow(2, 53) - 1; | ||
// exponent 11111111110, significand all 1s | ||
var MAX_DOUBLE = 1.79769313486231570815e+308; // 2 ** 1024 - 2 ** (1023 - 52) | ||
// exponent 11111111110, significand all 1s except final 0 | ||
var PENULTIMATE_DOUBLE = 1.79769313486231550856e+308; // 2 ** 1024 - 2 * 2 ** (1023 - 52) | ||
// exponent 11111001010, significand all 0s | ||
var MAX_ULP = MAX_DOUBLE - PENULTIMATE_DOUBLE; // 1.99584030953471981166e+292, <- 2 ** (1023 - 52) | ||
|
||
var NOT_A_NUMBER = {}; | ||
var MINUS_INFINITY = {}; | ||
var PLUS_INFINITY = {}; | ||
var MINUS_ZERO = {}; | ||
var FINITE = {}; | ||
|
||
// prerequisite: abs(x) >= abs(y) | ||
var twosum = function (x, y) { | ||
var hi = x + y; | ||
var lo = y - (hi - x); | ||
return { hi: hi, lo: lo }; | ||
}; | ||
|
||
// `Math.sumPrecise` method | ||
// https://github.com/tc39/proposal-math-sum | ||
$({ target: 'Math', stat: true, forced: true }, { | ||
// eslint-disable-next-line max-statements -- ok | ||
sumPrecise: function sumPrecise(items) { | ||
var numbers = []; | ||
var count = 0; | ||
var state = MINUS_ZERO; | ||
|
||
iterate(items, function (n) { | ||
if (++count >= MAX_SAFE_INTEGER) throw new $RangeError('Maximum allowed index exceeded'); | ||
if (typeof n != 'number') throw new $TypeError('Value is not a number'); | ||
if (state !== NOT_A_NUMBER) { | ||
// eslint-disable-next-line no-self-compare -- NaN check | ||
if (n !== n) state = NOT_A_NUMBER; | ||
else if (n === $Infinity) state = state === MINUS_INFINITY ? NOT_A_NUMBER : PLUS_INFINITY; | ||
else if (n === -$Infinity) state = state === PLUS_INFINITY ? NOT_A_NUMBER : MINUS_INFINITY; | ||
else if ((n !== 0 || (1 / n) === $Infinity) && (state === MINUS_ZERO || state === FINITE)) { | ||
state = FINITE; | ||
push(numbers, n); | ||
} | ||
} | ||
}); | ||
|
||
switch (state) { | ||
case NOT_A_NUMBER: return $NaN; | ||
case MINUS_INFINITY: return -$Infinity; | ||
case PLUS_INFINITY: return $Infinity; | ||
case MINUS_ZERO: return -0; | ||
} | ||
|
||
var partials = []; | ||
var overflow = 0; // conceptually 2**1024 times this value; the final partial is biased by this amount | ||
var x, y, sum, hi, lo, tmp; | ||
|
||
for (var i = 0; i < numbers.length; i++) { | ||
x = numbers[i]; | ||
var actuallyUsedPartials = 0; | ||
for (var j = 0; j < partials.length; j++) { | ||
y = partials[j]; | ||
if (abs(x) < abs(y)) { | ||
tmp = x; | ||
x = y; | ||
y = tmp; | ||
} | ||
sum = twosum(x, y); | ||
hi = sum.hi; | ||
lo = sum.lo; | ||
if (abs(hi) === $Infinity) { | ||
var sign = hi === $Infinity ? 1 : -1; | ||
overflow += sign; | ||
|
||
x = (x - (sign * POW_2_1023)) - (sign * POW_2_1023); | ||
if (abs(x) < abs(y)) { | ||
tmp = x; | ||
x = y; | ||
y = tmp; | ||
} | ||
sum = twosum(x, y); | ||
hi = sum.hi; | ||
lo = sum.lo; | ||
} | ||
if (lo !== 0) { | ||
partials[actuallyUsedPartials] = lo; | ||
actuallyUsedPartials += 1; | ||
} | ||
x = hi; | ||
} | ||
partials.length = actuallyUsedPartials; | ||
if (x !== 0) partials[partials.length] = x; | ||
} | ||
|
||
// compute the exact sum of partials, stopping once we lose precision | ||
var n = partials.length - 1; | ||
hi = 0; | ||
lo = 0; | ||
|
||
if (overflow !== 0) { | ||
var next = n >= 0 ? partials[n] : 0; | ||
n -= 1; | ||
if (abs(overflow) > 1 || (overflow > 0 && next > 0) || (overflow < 0 && next < 0)) { | ||
return overflow > 0 ? $Infinity : -$Infinity; | ||
} | ||
// here we actually have to do the arithmetic | ||
// drop a factor of 2 so we can do it without overflow | ||
// assert(abs(overflow) === 1) | ||
sum = twosum(overflow * POW_2_1023, next / 2); | ||
hi = sum.hi; | ||
lo = sum.lo; | ||
lo *= 2; | ||
if (abs(2 * hi) === $Infinity) { | ||
// rounding to the maximum value | ||
if (hi > 0) { | ||
return (hi === POW_2_1023 && lo === -(MAX_ULP / 2) && n >= 0 && partials[n] < 0) ? MAX_DOUBLE : $Infinity; | ||
} return (hi === -POW_2_1023 && lo === (MAX_ULP / 2) && n >= 0 && partials[n] > 0) ? -MAX_DOUBLE : -$Infinity; | ||
} | ||
|
||
if (lo !== 0) { | ||
partials[n + 1] = lo; | ||
n += 1; | ||
lo = 0; | ||
} | ||
|
||
hi *= 2; | ||
} | ||
|
||
while (n >= 0) { | ||
x = hi; | ||
y = partials[n]; | ||
n -= 1; | ||
sum = twosum(x, y); | ||
hi = sum.hi; | ||
lo = sum.lo; | ||
if (lo !== 0) break; | ||
} | ||
|
||
if (n >= 0 && ((lo < 0.0 && partials[n] < 0.0) || (lo > 0.0 && partials[n] > 0.0))) { | ||
y = lo * 2.0; | ||
x = hi + y; | ||
if (y === x - hi) hi = x; | ||
} | ||
|
||
return hi; | ||
} | ||
}); |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
'use strict'; | ||
// https://github.com/tc39/proposal-math-sum | ||
require('../modules/esnext.math.sum-precise'); |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,6 +1,7 @@ | ||
'use strict'; | ||
var parent = require('./3'); | ||
|
||
require('../proposals/math-sum'); | ||
require('../proposals/promise-try'); | ||
|
||
module.exports = parent; |
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
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