-
Notifications
You must be signed in to change notification settings - Fork 383
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Math.log2 should be exact for exact powers #323
Conversation
Math.log2(1.0 * (1 << 29)) === 29.000000000000004 in Firefox
Really? Does the spec say this should be exact? |
@@ -1594,6 +1604,10 @@ | |||
Math.imul = MathShims.imul; | |||
} | |||
|
|||
if (Math.log2(536870912.0) !== 29) { | |||
Math.log2 = MathShims.log2; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This would need to use defineProperty
to preserve non-enumerability.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@ljharb , assignment preservers enumerability (previously I thought it sets all flags to "true", but it preservers it, seems)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
huh, indeed it does, disregard my comment then :-) (although, if there were an engine where it was enumerable, this would be an opportunity to correct that)
I'm all for making Math shims more accurate, even if the spec doesn't require it. However, we'd need the following:
|
Well, at least two projects that I know of have recently switched to |
@ljharb , I have updated my patch a little |
if (value === 0) { | ||
return -1 / 0; | ||
} | ||
var e = Math.min(Math.floor(Math.log(value) / Math.LN2), 1023); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
instead of 1023 there should be Math.floor(Math.log(Number.MAX_VALUE) / Math.LN2) - 1
constant or something (?)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
if that's where 1023
comes from, then absolutely a named constant would be ideal.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I need to think how to change this.
Seems, this is a little wrong way of integer part calculation...
@cscott What is "too slow"? Which methods? Did they use profiling to determine that? |
@@ -1498,7 +1498,11 @@ | |||
}, | |||
|
|||
log2: function (value) { | |||
return Math.log(value) * Math.LOG2E; | |||
if (value === 0) { | |||
return -1 / 0; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can this just be -Infinity
? It's a keyword, so there's no advantage to the division by zero.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
if you want
Simple example, in all modern environment with fully complying with the specification var array = [];
for(var i = 0; i < 100000; i++)array.push([{}, {}]);
array = array.concat(array);
console.time('Map test');
var map = new Map(array);
console.log('Map size: ' + map.size);
console.timeEnd('Map test'); BTW, in the specification clearly states:
|
@zloirock they're not actually fully complying if the shim is replacing them (zero engines fully comply at the moment). But yes, that is a limitation, since it's impossible to a) not mutate the objects and also b) have O(1) lookup for them. However, I've filed #326 so that in this situation, we use the native |
@Yaffle This code is totally fine now, thanks! Could you also add a test that fails without your changes? |
they're fully complying, but your subclassing detection is broken :)
but why
in the spec I don't see anything about it. |
@zloirock As for the subclassing detection, please file an issue or open a PR, but I don't think it's broken - you can't actually subclass the native |
@zloirock object mutation is not good and may even affect performance (I hope yo read this page - https://developers.google.com/v8/design ) If the number of object is not big or he can |
@Yaffle broken and slow collections much worse :) Currently, it's required only for old IE, other actual browsers has native collections. Better fix broken methods than replace all collection :) |
Let's debate this on another issue, this isn't the one for it, but no, slow is infinitely better than broken (ours is not broken in any way), and mutation is absolutely broken (and as pointed out, insanely deoptimizes objects in v8, so it'd end up being slower in many ways as well). |
Oh, it's more: babel/babel#1172 |
@zloirock How then can you subclass |
@ljharb see link. It's only emulation, but correct in most case and much better replacing correct collection to broken. |
@ljharb , example engines that implement this correctly: the engine of Edge, Chrome, Safari, Firefox (with an exception of |
Math.log2(1.0 * (1 << 29)) === 29.000000000000004 in Firefox