Skip to content

Do not convert floats to integers#2324

Open
ThrudPrimrose wants to merge 3 commits intomainfrom
float_print_fix
Open

Do not convert floats to integers#2324
ThrudPrimrose wants to merge 3 commits intomainfrom
float_print_fix

Conversation

@ThrudPrimrose
Copy link
Collaborator

@ThrudPrimrose ThrudPrimrose commented Mar 14, 2026

The symstr might convert 0.0 to 0. E.g. the iedge below is generated from lc = max(-zdqs[jl], 0.0), can be converted to use 0.

I had an interesting butterfly effect. Sympy reordered arguments because the max function is commutative. But not with implicit promotions. If 0 is an integer, and appears first, then the double variable is promoted to int, thus the result will be different from when the double appears first.

I thought it could be related to sympy_numeric_fix, but I think the fix is in improving the print Float function symstr. I propose to change the _print_Float of symstr to clean trailing zeroes as before, but ensuring that there is at least one and not converting floats to integers implicitly.

With the new print I avoid implicit casts to integer in CloudSC SDFG. (I add some tests too).

See my comment below for a better explanation.

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Updates DaCe’s SymPy string printer to avoid implicitly printing float literals (e.g., 0.0) as integer literals (0), which can trigger unintended integer promotions/reordering in downstream code generation (notably around max/Max), and adds regression tests.

Changes:

  • Modified DaceSympyPrinter._print_Float to format floats with trimmed trailing zeros while keeping at least one decimal digit.
  • Added tests intended to ensure float literals (especially 0.0 in max(a, 0.0)) round-trip through symstr without demotion.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 3 comments.

File Description
dace/symbolic.py Adjusts Float printing logic in symstr’s printer implementation.
tests/symbolic_print_test.py Adds regression tests around float demotion and Max/max printing.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

You can also share your feedback on Copilot code review. Take the survey.

@ThrudPrimrose
Copy link
Collaborator Author

SymPy printer silently narrows double constants to int, causing non-commutative max behavior

DaCe's max wrapper uses variadic templates to bridge Python's loosely-typed frontend to C++. Since std::max requires both arguments to be the same type, the wrapper deduces the type from the first argument and promotes the second argument to match. This is well-defined C++ behavior.

max(5, 3.7) -> deduces max<int> -> truncates 3.7 to 3 -> returns 5
max(3.7, 5) -> deduces max<double> -> promotes 5 to 5.0 -> returns 5.0

This becomes a problem because SymPy's printer implicitly converts double constants to int: a value like 5.0 gets printed as 5 (if you use sympy printer). So instead of generating max(double, double), we emit max(int, double). Combined with the first-argument-biased template deduction, the generated code can silently produce wrong results.

To make matters worse, SymPy treats max as commutative and may freely reorder arguments, so the argument order (and therefore the deduced type) is effectively non-deterministic.

Possible mitigations:

Fix the SymPy printer (preferred): ensure double constants are always emitted with a decimal point. And not implicitly cast to integer

Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
@ThrudPrimrose ThrudPrimrose requested review from pratyai and tim0s March 16, 2026 11:24
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