From 30a5fd2734188e31bec4157a5f8492ba8dd1191b Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Sat, 16 Dec 2023 12:27:23 +0100 Subject: [PATCH] Bump internal copy of half to fix issues on older x86_64 CPUs on Windows On some older CPUs without support for the lzcnt instruction, the conversion from half to float was wrong. See AcademySoftwareFoundation/Imath#358 for more details. Thanks to Ray Molenkamp for tracking down this bug. Signed-off-by: Brecht Van Lommel --- openvdb/openvdb/math/Half.h | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/openvdb/openvdb/math/Half.h b/openvdb/openvdb/math/Half.h index b8045ba441..ba72b0e6df 100644 --- a/openvdb/openvdb/math/Half.h +++ b/openvdb/openvdb/math/Half.h @@ -342,8 +342,14 @@ imath_half_to_float (imath_half_bits_t h) // other compilers may provide count-leading-zeros primitives, // but we need the community to inform us of the variants uint32_t lc; -# if defined(_MSC_VER) && (_M_IX86 || _M_X64) - lc = __lzcnt (hexpmant); +# if defined(_MSC_VER) + // The direct intrinsic for this is __lznct, but that is not supported + // on older x86_64 hardware or ARM. Instead uses the bsr instruction + // and one additional subtraction. This assumes hexpmant != 0, for 0 + // bsr and lznct would behave differently. + unsigned long bsr; + _BitScanReverse (&bsr, hexpmant); + lc = (31 - bsr); # elif defined(__GNUC__) || defined(__clang__) lc = (uint32_t) __builtin_clz (hexpmant); # else