-
Notifications
You must be signed in to change notification settings - Fork 1.3k
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
Normative: fully define Math.sqrt #3345
Conversation
Implementations most likely call into |
In addition to changing the semantics for JIT-based implementations will likely use the And in case any implementations using the fdlibm |
I did some tests on this today. I ran 10 million random non-negative doubles through SM, JSC, V8, XS, LibJS, and Chakra. Chakra had a lot of divergence, but the other engines all agreed on all inputs. It's not conclusive, but it seems pretty likely that the large cohort are all currently implemented in a way that will always produce the exact result. |
Thank you for running the test to characterize the current level of conformance to the proposed change and for including XS in that. XS has the option to use fdlibm for math functions known to diverge, but that does not include sqrt. That means the test you ran used the host implementation of sqrt. It would be interesting to repeat your test on an embedded device or two. Those runtimes are not always as precise so there's a greater chance of a difference. Is it possible for me to run your test? |
Okay, I think I found the reason for Chakra's divergence, and it was due to differences in how they print floats, not how they do function simpleHashInt32(n, accum = 0) {
accum = 0 | (accum + n);
accum = 0 | (accum + (accum << 10));
accum ^= accum >> 6;
accum = 0 | (accum + (accum << 3));
accum ^= accum >> 11;
accum = 0 | (accum + (accum << 15));
return accum;
}
let taInt32 = new Int32Array(2);
let taFloat64 = new Float64Array(taInt32.buffer);
function intsToFloat(low, high) {
taInt32[0] = low;
taInt32[1] = high;
return taFloat64[0];
}
function floatToInts(f) {
taFloat64[0] = f;
return [taInt32[0], taInt32[1]];
}
let runningInputHash = 0;
let runningSqrtHash = 0;
let state = 1;
let tests = 0;
for (let tests = 0; tests < 10000000;) {
let low = simpleHashInt32(state);
let high = simpleHashInt32(low);
state = high;
let candidate = intsToFloat(low, high);
if (!Number.isFinite(candidate) || candidate <= 0) {
continue;
}
++tests;
runningInputHash = simpleHashInt32(low, simpleHashInt32(high, runningInputHash))
let [sqrtLow, sqrtHigh] = floatToInts(Math.sqrt(candidate));
runningSqrtHash = simpleHashInt32(sqrtLow, simpleHashInt32(sqrtHigh, runningSqrtHash))
}
print(runningInputHash);
print(runningSqrtHash); which outputs
on all of the above engines for me. |
@michaelficarra – thank you for posting the test script. I ran an abbreviated version (1M iterations) on ESP32-S3. The results match XS on macOS. |
@sunfishcode Would you like to attend the presentation of this to TC39 as an invited expert and possibly co-champion? |
@michaelficarra Yes, I would like to attend, as an invited expert. |
@sunfishcode Okay, I've initiated the process at https://github.com/tc39/Admin-and-Business/issues/459. The chairs may reach out for additional on-boarding information soon. |
@sunfishcode In case you didn't see, I sent you an email with some stuff to fill out in https://github.com/tc39/Admin-and-Business/issues/461. We'll need to get that done before the meeting next week. |
This matches the behaviour that web engines today already display with the WebAssembly
f64.sqrt
instruction./cc @sunfishcode