-
-
Notifications
You must be signed in to change notification settings - Fork 1.5k
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
Low level arithmetics bug: -3 mod 7 == 3 #12514
Comments
An easier example to see the buggy behaviour: echo -3 mod 5
echo -13 mod 5
Another example: echo ( 7 mod 5)
echo (-7 mod 5)
echo ( 7 mod -5)
echo (-7 mod -5)
echo "----"
echo ( 2 mod 5)
echo (-2 mod 5)
echo ( 2 mod -5)
echo (-2 mod -5)
I can confirm all these worked correctly in 0.20.x version. |
Seems like I jumped the gun. This is actually more intricate see C vs Python below. It is very important for us that we can trust all Nim low-level operators to do give the same results at runtime, during constant folding and in the VM. We implemented an anti-regression suite in stint (status-im/nim-stint#91) but those regressions, bugs and flawed tests (#11138, #9572) are very time-consuming. This is a necessary condition to build healthy big int libraries, crypto libraries and number theory related libraries in Nim. I suggest we have an extensive run-time, compile-time and semantic fold test suite for basic operators. C output:C uses the underlying hardware convention. On x86_64, the sign of the remainder is the sign of the dividend. #include <stdio.h>
#include <stdint.h>
int main(int argc, char *argv[])
{
int64_t dividend, divisor;
dividend = -3;
divisor = 5;
printf("%d mod %d = %d\n", dividend, divisor, dividend % divisor);
dividend = -13;
divisor = 5;
printf("%d mod %d = %d\n", dividend, divisor, dividend % divisor);
printf("----------------------------------------------------------\n");
printf("%d mod %d = %d\n", 7, 5, 7 % 5);
printf("%d mod %d = %d\n", -7, 5, -7 % 5);
printf("%d mod %d = %d\n", 7, -5, 7 % -5);
printf("%d mod %d = %d\n", -7, -5, -7 % -5);
printf("----\n");
printf("%d mod %d = %d\n", 2, 5, 2 % 5);
printf("%d mod %d = %d\n", -2, 5, -2 % 5);
printf("%d mod %d = %d\n", 2, -5, 2 % -5);
printf("%d mod %d = %d\n", -2, -5, -2 % -5);
}
Python output: Python has the convention that remainder is non-negative print(f"-3 mod 5 = {-3 % 5}")
print(f"-13 mod 5 = {-13 % 5}")
print("----------------------------------------------------------")
print(f" 7 mod 5 = { 7 % 5}")
print(f"-7 mod 5 = {-7 % 5}")
print(f" 7 mod -5 = { 7 % -5}")
print(f"-7 mod -5 = {-7 % -5}")
print("----")
print(f" 2 mod 5 = { 2 % 5}")
print(f"-2 mod 5 = {-2 % 5}")
print(f" 2 mod -5 = { 2 % -5}")
print(f"-2 mod -5 = {-2 % -5}")
I suggest we choose the same convention as C and assembly. Note that once a convention is chosen, the output of Important noticeAs mentioned mod and div in C are "implementation-defined" by the hardware. We should just mention that in the VM for modulo/remainder operations we follow x86 convention. |
Function mod returns the wrong result.
Nim versions affected by the bug: >= 1.0
Example
Current Output
Expected Output
Possible Solution
rollback mod operation to 0.20.2 version
The text was updated successfully, but these errors were encountered: