Conversation
There was a problem hiding this comment.
Pull Request Overview
This PR refines and expands the documentation of the Mod operator to clearly describe its behavior under both integer and floating-point modes, aligning the text with ONNX Runtime and reference implementations.
- Rewrote the C++ schema comment to specify
fmodattribute semantics, valid types, and special cases. - Mirror those documentation updates in the high-level Operators.md and Changelog.md.
Reviewed Changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated 4 comments.
| File | Description |
|---|---|
| onnx/defs/math/defs.cc | Enhanced Mod operator docstring with detailed fmod rules and special-case behaviors. |
| docs/Operators.md | Updated the Mod operator section to match the new schema description. |
| docs/Changelog.md | Reflected the same expanded documentation in the changelog entry for Mod-13. |
There was a problem hiding this comment.
Pull Request Overview
This PR refines the documentation of the Mod operator across code and markdown, clarifying type constraints, fmod behavior, and special cases to match ONNX reference implementations and ONNX Runtime.
- Update C++ schema doc for
Modwith detailed semantics forfmod=0(integer%) andfmod=1(Cfmod) including special floating-point cases. - Revise user-facing docs in
Operators.mdandChangelog.mdto mirror the enhanced description.
Reviewed Changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated no comments.
| File | Description |
|---|---|
| onnx/defs/math/defs.cc | Enhanced Mod operator schema doc with precise behavior |
| docs/Operators.md | Updated Mod operator markdown doc for clarity |
| docs/Changelog.md | Aligned changelog entry for Mod operator v13 docs |
Signed-off-by: Christian Bourjau <christian.bourjau@quantco.com>
| The result of this operator is the remainder of the division operation `x / y` where `x` and `y` are respective elements of `A` and `B`. The result is exactly the value `x - n * y`, where `n` is `x / y` with its fractional part truncated. | ||
| The returned value has the same sign as `x` (except if `x` is `-0`) and is less or equal to `|y|` in magnitude. | ||
| The following special cases apply when `fmod` is set to `1`: | ||
| - If `x` is `-0` and `y` is greater than zero, either `+0` or `-0` may be returned. |
There was a problem hiding this comment.
I should point out that currently, both onnxruntime and the reference implementation return the sign of x even in that case. However, the array-api standard points out this special case, which makes me suspect that some backends would have an issue here.
Signed-off-by: Christian Bourjau <christian.bourjau@quantco.com>
### Description Improve description of the `Mod` operator. Closes onnx#5564 ### Motivation and Context The description of the `Mod` operator has been very vague. The proposed change aligns with the behavior of onnxruntime and the onnx reference implementation. <details> <summary>Test against onnxruntime and onnx reference implementation</summary> The following code snippet checks the existing behavior of onnxruntime and the onnx reference implementation. This is not a stable feature of spox, yet, thus the private imports. Execute using pixi ``` pixi exec -s onnxruntime -s onnx -s spox -s numpy python mod.py ``` or in any Python environment with onnx, onnxruntime and spox installed. ```python import math import spox import spox._future import spox.opset.ai.onnx.v21 as op import numpy as np BACKENDS = [spox._value_prop.ValuePropBackend.ONNXRUNTIME, spox._value_prop.ValuePropBackend.REFERENCE] def check_mod_impl(x, y, expected, fmod): for backend in BACKENDS: spox._future.set_value_prop_backend(backend) a = op.const(x) b = op.const(y) res = op.mod(a, b, fmod=fmod)._value.value np.testing.assert_equal(expected, res) cases = [ (3.0, 2.0), (3.0, -2.0), (-3.0, 2.0), (-3.0, -2.0), ] for (x, y) in cases: expected = x - math.trunc(x/y) * y check_mod_impl(x, y, expected, fmod=1) special_cases = [ (-0.0, -1.0, -0.0), (-0.0, 1.0, -0.0), (float("inf"), 2.0, float("nan")), (3.0, float("inf"), 3.0), (float("nan"), 2.0, float("nan")), (2.0, float("nan"), float("nan")), ] for (x, y, expected) in special_cases: check_mod_impl(x, y, expected, fmod=1) cases = [ (5, 3), (5, -3), (-5, 3), (-5, -3), ] for (x, y) in cases: expected = x % y check_mod_impl(x, y, expected, fmod=0) ``` </details> --------- Signed-off-by: Christian Bourjau <christian.bourjau@quantco.com>
### Description Improve description of the `Mod` operator. Closes onnx#5564 ### Motivation and Context The description of the `Mod` operator has been very vague. The proposed change aligns with the behavior of onnxruntime and the onnx reference implementation. <details> <summary>Test against onnxruntime and onnx reference implementation</summary> The following code snippet checks the existing behavior of onnxruntime and the onnx reference implementation. This is not a stable feature of spox, yet, thus the private imports. Execute using pixi ``` pixi exec -s onnxruntime -s onnx -s spox -s numpy python mod.py ``` or in any Python environment with onnx, onnxruntime and spox installed. ```python import math import spox import spox._future import spox.opset.ai.onnx.v21 as op import numpy as np BACKENDS = [spox._value_prop.ValuePropBackend.ONNXRUNTIME, spox._value_prop.ValuePropBackend.REFERENCE] def check_mod_impl(x, y, expected, fmod): for backend in BACKENDS: spox._future.set_value_prop_backend(backend) a = op.const(x) b = op.const(y) res = op.mod(a, b, fmod=fmod)._value.value np.testing.assert_equal(expected, res) cases = [ (3.0, 2.0), (3.0, -2.0), (-3.0, 2.0), (-3.0, -2.0), ] for (x, y) in cases: expected = x - math.trunc(x/y) * y check_mod_impl(x, y, expected, fmod=1) special_cases = [ (-0.0, -1.0, -0.0), (-0.0, 1.0, -0.0), (float("inf"), 2.0, float("nan")), (3.0, float("inf"), 3.0), (float("nan"), 2.0, float("nan")), (2.0, float("nan"), float("nan")), ] for (x, y, expected) in special_cases: check_mod_impl(x, y, expected, fmod=1) cases = [ (5, 3), (5, -3), (-5, 3), (-5, -3), ] for (x, y) in cases: expected = x % y check_mod_impl(x, y, expected, fmod=0) ``` </details> --------- Signed-off-by: Christian Bourjau <christian.bourjau@quantco.com> Signed-off-by: Markus Bilz <github@markusbilz.com>
### Description Improve description of the `Mod` operator. Closes onnx#5564 ### Motivation and Context The description of the `Mod` operator has been very vague. The proposed change aligns with the behavior of onnxruntime and the onnx reference implementation. <details> <summary>Test against onnxruntime and onnx reference implementation</summary> The following code snippet checks the existing behavior of onnxruntime and the onnx reference implementation. This is not a stable feature of spox, yet, thus the private imports. Execute using pixi ``` pixi exec -s onnxruntime -s onnx -s spox -s numpy python mod.py ``` or in any Python environment with onnx, onnxruntime and spox installed. ```python import math import spox import spox._future import spox.opset.ai.onnx.v21 as op import numpy as np BACKENDS = [spox._value_prop.ValuePropBackend.ONNXRUNTIME, spox._value_prop.ValuePropBackend.REFERENCE] def check_mod_impl(x, y, expected, fmod): for backend in BACKENDS: spox._future.set_value_prop_backend(backend) a = op.const(x) b = op.const(y) res = op.mod(a, b, fmod=fmod)._value.value np.testing.assert_equal(expected, res) cases = [ (3.0, 2.0), (3.0, -2.0), (-3.0, 2.0), (-3.0, -2.0), ] for (x, y) in cases: expected = x - math.trunc(x/y) * y check_mod_impl(x, y, expected, fmod=1) special_cases = [ (-0.0, -1.0, -0.0), (-0.0, 1.0, -0.0), (float("inf"), 2.0, float("nan")), (3.0, float("inf"), 3.0), (float("nan"), 2.0, float("nan")), (2.0, float("nan"), float("nan")), ] for (x, y, expected) in special_cases: check_mod_impl(x, y, expected, fmod=1) cases = [ (5, 3), (5, -3), (-5, 3), (-5, -3), ] for (x, y) in cases: expected = x % y check_mod_impl(x, y, expected, fmod=0) ``` </details> --------- Signed-off-by: Christian Bourjau <christian.bourjau@quantco.com>
Description
Improve description of the
Modoperator. Closes #5564Motivation and Context
The description of the
Modoperator has been very vague. The proposed change aligns with the behavior of onnxruntime and the onnx reference implementation.Test against onnxruntime and onnx reference implementation
The following code snippet checks the existing behavior of onnxruntime and the onnx reference implementation. This is not a stable feature of spox, yet, thus the private imports.Execute using pixi
or in any Python environment with onnx, onnxruntime and spox installed.