Skip to content

Commit 02aa0d3

Browse files
authored
Fix some edge cases for compile time operations of % operator (#1566)
1 parent cd7217a commit 02aa0d3

File tree

4 files changed

+24
-5
lines changed

4 files changed

+24
-5
lines changed

integration_tests/expr_05.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@ def main0():
1111
b: i32
1212
a = 10
1313
b = -5
14+
eps: f64
15+
eps = 1e-12
1416
assert test_multiply(a, b) == -50
1517
i: i64
1618
i = i64(1)
@@ -69,6 +71,12 @@ def main0():
6971
assert a == 0
7072
b **= 4
7173
assert b == 256
74+
# Test Issue 1562
75+
assert ((-8)%3) == 1
76+
assert ((8)%-3) == -1
77+
assert (-8%-3) == -2
78+
assert abs((11.0%-3.0) - (-1.0)) < eps
79+
assert abs((-11.0%3.0) - (1.0)) < eps
7280

7381

7482
main0()

src/lpython/semantics/python_comptime_eval.h

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -211,13 +211,24 @@ struct PythonIntrinsicProcedures {
211211
if (ASRUtils::is_integer(*type)) {
212212
int64_t a = ASR::down_cast<ASR::IntegerConstant_t>(arg1)->m_n;
213213
int64_t b = ASR::down_cast<ASR::IntegerConstant_t>(arg2)->m_n;
214+
if(b == 0) { // Zero Division
215+
throw SemanticError("Integer division or modulo by zero",loc);
216+
}
217+
218+
// Refer the following link to understand how modulo in C++ is modified to behave like Python.
219+
// https://stackoverflow.com/questions/1907565/c-and-python-different-behaviour-of-the-modulo-operation
214220
return ASR::down_cast<ASR::expr_t>(
215-
ASR::make_IntegerConstant_t(al, loc, a%b, type));
221+
ASR::make_IntegerConstant_t(al, loc, ((a%b)+b)%b, type));
216222
} else if (ASRUtils::is_real(*type)) {
217223
double a = ASR::down_cast<ASR::RealConstant_t>(arg1)->m_r;
218224
double b = ASR::down_cast<ASR::RealConstant_t>(arg2)->m_r;
225+
if (b == 0) { // Zero Division
226+
throw SemanticError("Float division or modulo by zero", loc);
227+
}
228+
229+
// https://stackoverflow.com/questions/1907565/c-and-python-different-behaviour-of-the-modulo-operation
219230
return ASR::down_cast<ASR::expr_t>(
220-
ASR::make_RealConstant_t(al, loc, std::fmod(a, b), type));
231+
ASR::make_RealConstant_t(al, loc, std::fmod(std::fmod(a, b) + b, b), type));
221232
} else {
222233
throw SemanticError("_mod() must have both integer or both real arguments.", loc);
223234
}

tests/reference/asr-expr_05-3a37324.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,11 @@
22
"basename": "asr-expr_05-3a37324",
33
"cmd": "lpython --show-asr --no-color {infile} -o {outfile}",
44
"infile": "tests/../integration_tests/expr_05.py",
5-
"infile_hash": "e391b0795af9d77b92cd60ce235d00761db224f5056cab55cb6278c2",
5+
"infile_hash": "59668f790720eb827bd2963bb57a934805aa5139fff582a3b138a8e4",
66
"outfile": null,
77
"outfile_hash": null,
88
"stdout": "asr-expr_05-3a37324.stdout",
9-
"stdout_hash": "e9ee5559639de0903d652344a2e091fe76c25f5e6d57bcb0d30f8554",
9+
"stdout_hash": "6ee2e60ba4c39354eb284734d4588f8197a52a75634e49fceda63ec3",
1010
"stderr": null,
1111
"stderr_hash": null,
1212
"returncode": 0

0 commit comments

Comments
 (0)