-
-
Notifications
You must be signed in to change notification settings - Fork 672
fix: Math.pow
constant optimization behaves inconsistently in different versions of node
#2920
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
fix: Math.pow
constant optimization behaves inconsistently in different versions of node
#2920
Conversation
b404098
to
4d9b05b
Compare
4d9b05b
to
a022591
Compare
Hmm, but how about of rest browsers? AS may run in different browsers. Besides, there is no guarantee that even in the next versions of node this speculation will not appear again |
Is the current behavior causing any problems? |
But it still can be slightly optimized I gues to: if (Math.trunc(y) == y && Math.abs(y) > 2 && Math.abs(y) < 100) {
...
}
return Math.pow(x, y); |
In latest version, it will get this result x = 2
y = 2
Math.pow(x, y - 0.5) * Math.pow(x, 0.5) // 4.000000000000001 It the reason why #2917 CI failed |
It is meaningless actually, change IMO, It is impossible to keep determinism between different js engine except introducing high precision pow lib. |
If there's still a (potential) need for this function, is there any other working alternative? |
according to https://tc39.es/ecma262/#sec-numeric-types-number-exponentiate. Math.pow only required to be precision as much as possible. To be honest, I think it is hard to make everything same except not using IEEE754 floating number (software implement). |
I'm also tempted to say "throw this function out", because I can also see this imprecise behavior with integer exponents on Python and Java (tested via |
The best way I see, and the way I originally thought, is to compile the |
What I was thinking: shouldn't we fix our Even C exhibits this behavior: #include <math.h>
#include <stdio.h>
int main(int argc, char* argv[]) {
printf("pi: %e\n", M_PI);
double regular = pow(M_PI, 210);
double accurate = pow(M_PI, 209.5) * pow(M_PI, 0.5);
printf("regular: %.18e, accurate: %.18e, equal: %d\n", regular, accurate, regular == accurate);
return 0;
} I get this output:
And testing these values in Node.js too:
|
what do you think about to introduce 3rd lib to ensure mathematical correctness? IMO it can ensure compliance with ECMA specifications to the greatest extent possible. According to spec:
|
If it will under AssemblyScript's umbrella similar to binaryen.js it will be ok I guess |
@MaxGraey Are we able to align our (And how should I try to do that?) |
@dcodeIO In the meantime, do you have thoughts on adding an extra dependency (currently named |
A minimal approach could be to make this a small inline Wasm module that is instantiated synchronously, similar to what long.js does for its Wasm optimizations. Then it'd be part of the glue, eliminating the need for bindings or a separate dependency. Or are there reasons that speak against this approach? |
Since that's okay with you, I'll do that. I don't think anything stops us from this approach. Note that the external dependency was already compiled to Wasm, so the only difference would be inlining it into AS. |
We cannot use wasm / wat to write this code. pow is complex code. So I think using AS bootstrap itself may be good idea. It will introduce additional work only when we want to change the algorithm of Math.pow (but I think last change is long time ago) |
So should we go in this way? |
Created https://github.com/AssemblyScript/as-float in case, or it could live under |
It is hard to handle upgrading since as-float is like bootstrap. Having a separated repo can avoid circular dependency problem |
code is sync to new repo. I also invite AssemblyScript and @dcodeIO as npm maintainer. |
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.
LGTM but you should probably rename the PR
Unfortunately, |
Math.pow
constant optimization behaves inconsistently in different versions of node
use the pow function compiled by AS bootstrap to optimize the constant propagation of pow