Skip to content

[To Discuss] Python floor division and modulo lower to C semantics - #2537

Draft
ThrudPrimrose wants to merge 2 commits into
mainfrom
fix/python-floordiv-mod-codegen
Draft

[To Discuss] Python floor division and modulo lower to C semantics#2537
ThrudPrimrose wants to merge 2 commits into
mainfrom
fix/python-floordiv-mod-codegen

Conversation

@ThrudPrimrose

@ThrudPrimrose ThrudPrimrose commented Aug 27, 2026

Copy link
Copy Markdown
Collaborator

// and % in a tasklet lowered to C's truncating division, so -32 // 7 gave -4 and -32 % 7 gave -4 where Python and NumPy give -5 and 3, and % on a float operand did not compile at all. Routing both to py_floor/py_mod fixes that, and int_floor_ni drops std::div in the same change because nvcc removes a host-only call -- and the guarded region containing it -- from device code.

Both rounded toward zero rather than toward negative infinity, so -32 // 7 gave -4 and -32 % 7 gave
-4 where NumPy gives -5 and 3, and % on a float operand did not compile at all. int_floor_ni also
reached for host-only std::div, which nvcc removes from device code along with the branch holding
it.
@ThrudPrimrose

Copy link
Copy Markdown
Collaborator Author

Two points for the discussion, neither of them fixed here.

Division by zero still diverges from NumPy. NumPy answers 0 for integers and inf/nan for floats; the emitted C traps or is undefined. Matching it puts a branch on every division, which did not seem like a trade to make silently.

// and % are no longer infix. They emit py_floor(a, b) / py_mod(a, b), so anything asserting on emitted C text for these operators will see a different string.

The table in the new test is 64 operand pairs per dtype over {int32, int64, float32, float64} x {host, device}, compared against NumPy itself. The device half is not redundant with the host half: the floor correction is a branch, and that branch is what held the std::div call, so only running it on a GPU shows the branch survived compilation.

The goldens still spell FloorDiv as ifloor(a / b), the form this branch replaced because integer
division has already truncated by the time the floor runs. Same two expressions, now py_floor.
@tbennun

tbennun commented Aug 27, 2026

Copy link
Copy Markdown
Collaborator

As per the discussion, let's add a few sympy functions:

  • CMod
  • FtnMod
  • PyMod

have them lower to sympy.Mod in the cases that it can be evaluated at compile time

Also, modify the docs so that in dace, tasklet code is translated to C Modulo semantics, memlets and symbolic expressions in maps/ISedges/... follow SymPy Modulo semantics, and each respective frontend adds their own (PyMod, etc.).

@ThrudPrimrose

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants