util: improve isSafeAddition.

This commit is contained in:
Christopher Jeffrey 2017-06-17 18:39:47 -07:00
parent be0e7e02d2
commit 3db140e119
No known key found for this signature in database
GPG Key ID: 8962AB9DE6666BBD

View File

@ -200,14 +200,6 @@ if (Object.assign)
util.MAX_SAFE_INTEGER = 0x1fffffffffffff;
/**
* Max safe addition (52 bits).
* @const {Number}
* @default
*/
util.MAX_SAFE_ADDITION = 0xfffffffffffff;
/**
* Test whether a number is below MAX_SAFE_INTEGER.
* @param {Number} value
@ -226,9 +218,44 @@ util.isSafeInteger = function isSafeInteger(value) {
*/
util.isSafeAddition = function isSafeAddition(a, b) {
var hi, lo, ahi, alo, bhi, blo;
var as, bs, s, c;
// We only work on positive numbers.
assert(a >= 0);
assert(b >= 0);
return a <= util.MAX_SAFE_ADDITION && b <= util.MAX_SAFE_ADDITION;
// Fast case.
if (a <= 0xfffffffffffff && b <= 0xfffffffffffff)
return true;
// Do a 64 bit addition and check the top 11 bits.
ahi = (a * (1 / 0x100000000)) | 0;
alo = a | 0;
bhi = (b * (1 / 0x100000000)) | 0;
blo = b | 0;
// Credit to @indutny for this method.
lo = (alo + blo) | 0;
s = lo >> 31;
as = alo >> 31;
bs = blo >> 31;
c = ((as & bs) | (~s & (as ^ bs))) & 1;
hi = (((ahi + bhi) | 0) + c) | 0;
hi >>>= 0;
ahi >>>= 0;
bhi >>>= 0;
// Overflow?
if (hi < ahi || hi < bhi)
return false;
return (hi & 0xffe00000) === 0;
};
/**