CPU:LVP float64-to-float16 casts misround values just beyond a half midpoint
CPU:LVP rounds float64 inputs just beyond a float16 midpoint to the wrong half value. This reproduces on unmodified upstream d53f06b0995709a682a9f913b5de37ff8bd65eed with Python 3.12.6, NumPy 1.26.4 and tinymesa 25.2.7.2 on macOS arm64, without the QCOM emulator or any unmerged PR.
From an upstream checkout with NumPy and tinymesa installed, save this as repro.py and run DEV=CPU:LVP python repro.py. The environment selector is required to load the CPU Mesa library.
import numpy as np
from tinygrad import Tensor, dtypes
values = np.array([
sign * (1 + 2**-11 + delta)
for sign in [1, -1] for delta in [-2**-40, 0, 2**-40]
], dtype=np.float64)
expected = np.array([0x3c00, 0x3c00, 0x3c01, 0xbc00, 0xbc00, 0xbc01], dtype=np.uint16)
actual = Tensor(values, device="CPU:LVP").cast(dtypes.float16).bitcast(dtypes.uint16).numpy()
print("expected:", [hex(int(x)) for x in expected])
print("actual: ", [hex(int(x)) for x in actual])
np.testing.assert_array_equal(actual, expected)Expected half bits are 0x3c00, 0x3c00, 0x3c01, 0xbc00, 0xbc00, 0xbc01. Actual upstream output is 0x3c00, 0x3c00, 0x3c00, 0xbc00, 0xbc00, 0xbc00, so the assertion fails on two of six inputs. These are both signs immediately below, exactly at, and immediately above a half midpoint; the above-midpoint values must round away from the even lower-magnitude neighbor.
ncast emits generic f2f16. In the pinned Mesa LVP lowering, the float64-to-float32 split happens before undefined rounding is resolved to nearest-even, so the split misses the tie/sticky-bit correction used for explicit nearest-even. Emitting f2f16_rtne fixes the same numerical reproducer. Mesa fp16 lowering, LVP lowering call.
The same generic NIR conversion also produces IR3 cov.f32f16 instructions with default round-toward-zero encoding; explicit nearest-even adds the (even) rounding encoding. That observation is compiler/disassembly evidence, with no QCOM hardware execution claim.
A minimal fix and independent numerical/compiler regressions are prepared. Investigation, code and tests were developed with AI assistance and a separate AI review; the reported red/green results were executed locally.
Source: tinygrad/tinygrad