Skip to content

Take a floating-point remainder with fmod or math.Mod in C, C++ and Go [patch] - #210

Open
matt-edmondson wants to merge 3 commits into
mainfrom
fix/174-floating-modulo
Open

matt-edmondson wants to merge 3 commits into
mainfrom
fix/174-floating-modulo

Conversation

@matt-edmondson

Copy link
Copy Markdown
Contributor

Fixes #174

What changed

C, C++ and Go define % on integers only. A remainder or %= of double or float operands was written as % anyway, and none of the three compiled it.

  • StandardLanguageGenerator gains FloatingRemainderType, which returns the floating type of a remainder when either operand's static type is float or double. It also gains a SpellsFloatingRemainderAsCall / WriteFloatingRemainder hook.

  • GenerateBinary lowers a floating Modulo through that hook. A new GenerateAssignmentStatement override lowers a floating x %= y to x = <call>(x, y). Go's own override still defers to it for any value that is not a conditional.

  • What each target writes:

    Target double float Import
    C fmod(a, b) fmodf(a, b) <math.h>
    C++ std::fmod(a, b) std::fmod(a, b) <cmath>
    Go math.Mod(a, b) float32(math.Mod(float64(a), float64(b))) "math"
  • Before this change, C and C++ never pushed a static-type scope. GenerateFunction now opens one and GenerateVariableDeclaration registers each local, the same way Go already did. That is the prerequisite the triage comment shares with Calling a method through a pointer or reference, or on another call's result, generates C, C++ and Rust that doesn't compile #170.

  • Imports are written before the body, so ContainsFloatingRemainder(SourceFile) asks the question of the AST. It puts each function's parameters and locals in scope and then looks for a floating % or %=. Go needs this to be exact, because an unused "math" import does not compile there.

  • Integer % and %= are unchanged, and C#, Rust, Python and JavaScript are untouched, since the hook defaults to off.

Tests (FloatingRemainderTests)

  • AFloatingRemainderIsACall (C, C++, Go): checks the spelling of double % double, float % float and %= on a double local.
  • AnIntegerRemainderIsUnchanged (C, C++, Go): int % and %= are still written as %.
  • OnlyAFloatingRemainderImportsItsCall (C, C++, Go): the header or package appears exactly once for floating remainders, and not at all for integer ones.
  • RemaindersCompile (C, C++, Go): both files compile with gcc -std=c11 -Wall -Wextra -pedantic -Werror, g++ -std=c++20 … -Werror and go vet.

With the generator changes reverted, 9 of the 12 fail. The 3 that still pass are the unchanged integer rows. With the changes, the full suite passes (1127/1127).

🤖 Generated with Claude Code

https://claude.ai/code/session_01NgDciLntSfQTDeqFaJ3BM1


Generated by Claude Code

claude and others added 2 commits October 12, 2026 20:30
…o [patch]

C, C++ and Go define % only on integers, so a remainder or %= of double or
float operands did not compile there. StandardLanguageGenerator now lowers a
floating remainder through a WriteFloatingRemainder hook for a target that
opts in: fmod/fmodf in C, std::fmod in C++, math.Mod in Go (converting
through float64 for float32). x %= y becomes x = <call>(x, y). C and C++
now push a static-type scope and register locals, as Go already did, so the
operands' types are known. The file includes <math.h>/<cmath> or imports
"math" only when it takes such a remainder. Integer % is unchanged.

Fixes #174

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NgDciLntSfQTDeqFaJ3BM1
Keep both import conditions: main renamed ContainsNonFiniteDouble to
ContainsNonFiniteLiteral, and this branch adds ContainsFloatingRemainder.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01P8rVj8U65vKDPQv2LuKHEw
Keep both C++ include conditions: main added <vector>/<string> for an
entry point that accepts arguments (#211), and this branch adds <cmath>
for a floating-point remainder.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NgDciLntSfQTDeqFaJ3BM1
@sonarqubecloud

Copy link
Copy Markdown

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.

C, C++ and Go: % between double operands does not compile (needs fmod / math.Mod)

2 participants