Skip to content

Commit a676b12

Browse files
xal-0Jameson Nash
and
Jameson Nash
authored
Fix fptrunc Float64 -> Float16 rounding through Float32 (#57809)
Widening from Float32 to Float64 and then rounding to Float16 will not introduce any error, but going from Float64 -> Float32 -> Float16 will round incorrectly if the intermediate Float32 is halfway between two Float16s. Fixes #57805. Thanks to @vtjnash for suggesting the fix. Co-authored-by: Jameson Nash <[email protected]>
1 parent 7ee404c commit a676b12

File tree

2 files changed

+13
-2
lines changed

2 files changed

+13
-2
lines changed

src/runtime_intrinsics.c

+2-2
Original file line numberDiff line numberDiff line change
@@ -1629,8 +1629,8 @@ cvt_iintrinsic(LLVMFPtoUI, fptoui)
16291629
#define fintrinsic_read_float32(p) *(float *)p
16301630
#define fintrinsic_read_float64(p) *(double *)p
16311631

1632-
#define fintrinsic_write_float16(p, x) *(uint16_t *)p = float_to_half(x)
1633-
#define fintrinsic_write_bfloat16(p, x) *(uint16_t *)p = float_to_bfloat(x)
1632+
#define fintrinsic_write_float16(p, x) *(uint16_t *)p = double_to_half(x)
1633+
#define fintrinsic_write_bfloat16(p, x) *(uint16_t *)p = double_to_bfloat(x)
16341634
#define fintrinsic_write_float32(p, x) *(float *)p = x
16351635
#define fintrinsic_write_float64(p, x) *(double *)p = x
16361636

test/intrinsics.jl

+11
Original file line numberDiff line numberDiff line change
@@ -304,6 +304,17 @@ end
304304
@test_intrinsic Core.Intrinsics.fptrunc Float16 Float32(3.3) Float16(3.3)
305305
@test_intrinsic Core.Intrinsics.fptrunc Float16 Float64(3.3) Float16(3.3)
306306

307+
# #57805 - cases where rounding Float64 -> Float32 -> Float16 would fail
308+
# 2^-25 * 0b1.0000000000000000000000000000000000000001 binary
309+
# 0 01111100110 0000000000000000000000000000000000000001000000000000
310+
# 2^-25 * 0b1.0 binary
311+
# 0 01100110 00000000000000000000000
312+
# 2^-14 * 0b0.0000000001 (subnormal)
313+
# 0 00000 0000000001 (correct)
314+
# 0 00000 0000000000 (incorrect)
315+
@test_intrinsic Core.Intrinsics.fptrunc Float16 0x1.0000000001p-25 Float16(6.0e-8)
316+
@test_intrinsic Core.Intrinsics.fptrunc Float16 -0x1.0000000001p-25 Float16(-6.0e-8)
317+
307318
# float_to_half/bfloat_to_float special cases
308319
@test_intrinsic Core.Intrinsics.fptrunc Float16 Inf32 Inf16
309320
@test_intrinsic Core.Intrinsics.fptrunc Float16 -Inf32 -Inf16

0 commit comments

Comments
 (0)