Skip to content

[libclc] Improve nextafter behaviour around zero #127469

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Feb 19, 2025

Conversation

frasercrmck
Copy link
Contributor

This commit improves the behaviour of (_clc)nextafter around zero. Specifically, the nextafter value of very small negative numbers in the positive direction is now negative zero. Previously we'd return positive zero.

This behaviour is not required as far as OpenCL is concerned: at least, the CTS isn't testing for it. However, this change does bring our implementation into bit-equivalence with (libstdc++'s implementation of) std::nextafter, tested on all possible values of 32-bit float towards both positive and negative INFINITY.

Furthermore, since the implementation of libclc's floating-point 'rtp' and 'rtz' conversions use __clc_nextafter, the previous behaviour was resulting in CTS validation issues. For example, when converting float -0x1.000002p-25 to half, rounding towards zero or positive infinity, nextafter was returning +0.0, whereas the correct conversion requires us to return -0.0.

We could work around this issue in the conversion functions, but since the change to nextafter is small enough and the behaviour around zero matches libstdc++, the fix feels at home there.

This commit also converts several variables to unsigned types to avoid undefined behaviour surrounding signed underflow on the subtractions.

@frasercrmck frasercrmck added the libclc libclc OpenCL library label Feb 17, 2025
@frasercrmck frasercrmck requested a review from arsenm February 17, 2025 10:33
@frasercrmck
Copy link
Contributor Author

With this PR and with #126905 I achieved a fully passing OpenCL-CTS conversions run.

This commit improves the behaviour of (__clc_)nextafter around zero.
Specifically, the nextafter value of very small negative numbers in the
positive direction is now negative zero. Previously we'd return positive
zero.

This behaviour is not required as far as OpenCL is concerned: at
least, the CTS isn't testing for it. However, this change does bring our
implementation into bit-equivalence with (libstdc++'s implementation of)
std::nextafter, tested on all possible values of 32-bit float towards
both positive and negative INFINITY.

Furthermore, since the implementation of libclc's floating-point 'rtp'
and 'rtz' conversions use __clc_nextafter, the previous behaviour was
resulting in CTS validation issues. For example, when converting float
-0x1.000002p-25 to half, rounding towards zero or positive infinity,
nextafter was returning +0.0, whereas the correct conversion requires
us to return -0.0.

We could work around this issue in the conversion functions, but since
the change to nextafter is small enough and the behaviour around zero
matches libstdc++, the fix feels at home there.

This commit also converts several variables to unsigned types to avoid
undefined behaviour surrounding signed underflow on the subtractions.
@frasercrmck frasercrmck force-pushed the libclc-clc-nextafter-zeroes branch from ae75e98 to e25ac41 Compare February 19, 2025 09:54
@frasercrmck frasercrmck merged commit 1509b46 into llvm:main Feb 19, 2025
8 checks passed
@frasercrmck frasercrmck deleted the libclc-clc-nextafter-zeroes branch February 19, 2025 10:24
@arsenm arsenm added the floating-point Floating-point math label Feb 19, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
floating-point Floating-point math libclc libclc OpenCL library
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants