[Bug]: CPU and GPU plugins ignore Divide's m_pythondiv for integer inputs: -5 / 2 gives -2 instead of -3
OpenVINO Version
2026.4.0-22959-99c81491cc3-releases/2026/4 (pip wheel)
Operating System
Windows System
Device used for inference
CPU
Framework
None
Model used
Minimal ov.Model with a single Divide, see reproducer.
Issue description
The Divide-1 spec defines m_pythondiv as "specifies if floor division should be calculated for integer types (Python-style division)". The core reference implementation honours it (openvino/reference/divide.hpp, try_python_div subtracts one when the signs differ and the remainder is non-zero), and so does constant folding. The CPU and GPU plugins do not: at runtime an integer Divide with m_pythondiv=true truncates toward zero exactly like m_pythondiv=false, so -5 / 2 gives -2 instead of -3 for both i32 and i64.
This surfaces in the PyTorch frontend: aten::floor_divide / aten::floordiv are translated to Divide(m_pythondiv=true) + Floor (src/frontends/pytorch/src/op/floor_divide.cpp), and Floor is a no-op on integers, so any TorchScript integer // with a negative operand (e.g. -x.shape[0] // 2 when computing a shape) gives the wrong value on CPU/GPU while the same graph folds correctly when the operands are constants. The TensorFlow frontend already works around this by computing floor division explicitly for signed integers (translate_floor_div_op in src/frontends/tensorflow_common/src/op/binary_op.cpp), which suggests the plugin behaviour has been known for a while; I'm opening this so it is tracked at the plugin level. I'll send a frontend-side fix for the PyTorch case separately.
Step-by-step reproduction
import numpy as np, openvino as ov
from openvino import opset13 as ops
from openvino._pyopenvino import NodeFactory
def divide(a, b, pythondiv):
return NodeFactory("opset13").create("Divide", [a.output(0), b.output(0)], {"auto_broadcast": "numpy", "m_pythondiv": pythondiv})
for dt in (np.int64, np.int32):
a = ops.parameter([-1], dt); b = ops.parameter([-1], dt)
m = ov.Model([divide(a, b, True), divide(a, b, False)], [a, b])
av = np.array([-5, 5, -5, 5, -7, 7], dt); bv = np.array([2, 2, -2, -2, 3, -3], dt)
for dev in ("CPU", "GPU"):
r = ov.Core().compile_model(m, dev)([av, bv])
print(dt.__name__, dev, "pythondiv:", r[0].tolist(), "trunc:", r[1].tolist(), "python //:", (av // bv).tolist())Output:
int64 CPU pythondiv: [-2, 2, 2, -2, -2, -2] trunc: [-2, 2, 2, -2, -2, -2] python //: [-3, 2, 2, -3, -3, -3]
int64 GPU pythondiv: [-2, 2, 2, -2, -2, -2] trunc: [-2, 2, 2, -2, -2, -2] python //: [-3, 2, 2, -3, -3, -3]
int32 CPU pythondiv: [-2, 2, 2, -2, -2, -2] trunc: [-2, 2, 2, -2, -2, -2] python //: [-3, 2, 2, -3, -3, -3]
int32 GPU pythondiv: [-2, 2, 2, -2, -2, -2] trunc: [-2, 2, 2, -2, -2, -2] python //: [-3, 2, 2, -3, -3, -3]Expected: the pythondiv column equals the python // column.
Relevant log output
(no error; the result is silently wrong)Issue submission checklist
- I'm reporting an issue. It's not a question.
- I checked the problem with the documentation, FAQ, open issues, Stack Overflow, etc., and have not found a solution.
- There is reproducer code and related data files such as images, videos, models, etc.
Source: openvinotoolkit/openvino