From 3e4cf801c5e757ba2724c82a125487c68a6b65f1 Mon Sep 17 00:00:00 2001 From: Yixuan Chen Date: Sun, 26 Apr 2026 00:49:38 +0800 Subject: [PATCH] Fix bytes_to_scalar for float/complex on RISC-V bytes_to_scalar previously round-tripped raw bytes through Python float/complex values (via ctypes) before constructing the tensor. This loses NaN bit patterns on architectures (such as RISC-V) that canonicalize NaNs in floating-point loads/conversions, causing test_bytes_to_scalar_cpu_{float32,float64,complex64,complex128} to fail with mismatched storage bytes. Construct the scalar tensor by reinterpreting the raw bytes as the target dtype via tensor.view(dtype), so all input bit patterns (including NaN payloads) are preserved exactly. Test Plan: python test/test_torch.py TestTorchDeviceTypeCPU.test_bytes_to_scalar_cpu_complex64 --- torch/testing/_internal/common_utils.py | 32 ++++++++++--------------- 1 file changed, 12 insertions(+), 20 deletions(-) diff --git a/torch/testing/_internal/common_utils.py b/torch/testing/_internal/common_utils.py index 65534c77950a5..d85ef2acd5dd4 100644 --- a/torch/testing/_internal/common_utils.py +++ b/torch/testing/_internal/common_utils.py @@ -5977,27 +5977,19 @@ def check_bytes(byte_list): if not (0 <= byte <= 255): raise AssertionError(f"byte value out of range: expected 0 <= byte <= 255, got {byte}") - if dtype.is_complex: - if len(byte_list) != (num_bytes * 2): - raise AssertionError( - f"expected len(byte_list) == {num_bytes * 2} for complex dtype, got {len(byte_list)}" - ) - check_bytes(byte_list) - real = ctype.from_buffer((ctypes.c_byte * num_bytes)( - *byte_list[:num_bytes])).value - imag = ctype.from_buffer((ctypes.c_byte * num_bytes)( - *byte_list[num_bytes:])).value - res = real + 1j * imag - else: - if len(byte_list) != num_bytes: - raise AssertionError( - f"expected len(byte_list) == {num_bytes}, got {len(byte_list)}" - ) - check_bytes(byte_list) - res = ctype.from_buffer((ctypes.c_byte * num_bytes)( - *byte_list)).value + expected_len = num_bytes * 2 if dtype.is_complex else num_bytes + if len(byte_list) != expected_len: + raise AssertionError( + f"expected len(byte_list) == {expected_len}" + f"{' for complex dtype' if dtype.is_complex else ''}, got {len(byte_list)}" + ) + check_bytes(byte_list) - return torch.tensor(res, device=device, dtype=dtype) + # Reinterpret the raw bytes as the target dtype to preserve exact bit + # patterns (e.g. NaN payloads, which are not preserved when round-tripping + # through Python float/complex, especially on architectures like RISC-V + # that canonicalize NaNs). + return torch.tensor(byte_list, dtype=torch.uint8, device=device).view(dtype=dtype).squeeze(0) def copy_func(f):