Skip to content

Commit

Permalink
Fix some edge cases for compile time operations of % operator (lcompi…
Browse files Browse the repository at this point in the history
  • Loading branch information
faze-geek committed Mar 16, 2023
1 parent cd7217a commit 02aa0d3
Show file tree
Hide file tree
Showing 4 changed files with 24 additions and 5 deletions.
8 changes: 8 additions & 0 deletions integration_tests/expr_05.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ def main0():
b: i32
a = 10
b = -5
eps: f64
eps = 1e-12
assert test_multiply(a, b) == -50
i: i64
i = i64(1)
Expand Down Expand Up @@ -69,6 +71,12 @@ def main0():
assert a == 0
b **= 4
assert b == 256
# Test Issue 1562
assert ((-8)%3) == 1
assert ((8)%-3) == -1
assert (-8%-3) == -2
assert abs((11.0%-3.0) - (-1.0)) < eps
assert abs((-11.0%3.0) - (1.0)) < eps


main0()
15 changes: 13 additions & 2 deletions src/lpython/semantics/python_comptime_eval.h
Original file line number Diff line number Diff line change
Expand Up @@ -211,13 +211,24 @@ struct PythonIntrinsicProcedures {
if (ASRUtils::is_integer(*type)) {
int64_t a = ASR::down_cast<ASR::IntegerConstant_t>(arg1)->m_n;
int64_t b = ASR::down_cast<ASR::IntegerConstant_t>(arg2)->m_n;
if(b == 0) { // Zero Division
throw SemanticError("Integer division or modulo by zero",loc);
}

// Refer the following link to understand how modulo in C++ is modified to behave like Python.
// https://stackoverflow.com/questions/1907565/c-and-python-different-behaviour-of-the-modulo-operation
return ASR::down_cast<ASR::expr_t>(
ASR::make_IntegerConstant_t(al, loc, a%b, type));
ASR::make_IntegerConstant_t(al, loc, ((a%b)+b)%b, type));
} else if (ASRUtils::is_real(*type)) {
double a = ASR::down_cast<ASR::RealConstant_t>(arg1)->m_r;
double b = ASR::down_cast<ASR::RealConstant_t>(arg2)->m_r;
if (b == 0) { // Zero Division
throw SemanticError("Float division or modulo by zero", loc);
}

// https://stackoverflow.com/questions/1907565/c-and-python-different-behaviour-of-the-modulo-operation
return ASR::down_cast<ASR::expr_t>(
ASR::make_RealConstant_t(al, loc, std::fmod(a, b), type));
ASR::make_RealConstant_t(al, loc, std::fmod(std::fmod(a, b) + b, b), type));
} else {
throw SemanticError("_mod() must have both integer or both real arguments.", loc);
}
Expand Down
4 changes: 2 additions & 2 deletions tests/reference/asr-expr_05-3a37324.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,11 @@
"basename": "asr-expr_05-3a37324",
"cmd": "lpython --show-asr --no-color {infile} -o {outfile}",
"infile": "tests/../integration_tests/expr_05.py",
"infile_hash": "e391b0795af9d77b92cd60ce235d00761db224f5056cab55cb6278c2",
"infile_hash": "59668f790720eb827bd2963bb57a934805aa5139fff582a3b138a8e4",
"outfile": null,
"outfile_hash": null,
"stdout": "asr-expr_05-3a37324.stdout",
"stdout_hash": "e9ee5559639de0903d652344a2e091fe76c25f5e6d57bcb0d30f8554",
"stdout_hash": "6ee2e60ba4c39354eb284734d4588f8197a52a75634e49fceda63ec3",
"stderr": null,
"stderr_hash": null,
"returncode": 0
Expand Down
Loading

0 comments on commit 02aa0d3

Please sign in to comment.