Repository navigation
Enable __float128 in cuda::std::ceil, floor, trunc and round - #12253
Conversation
Add `__float128` overloads that use `__builtin_<fn>f128` on the host and `__nv_fp128_<fn>` on the device, with a portable bit-level fallback built on a shared truncation helper for hosts that provide neither. The float128 test driver only exercises these four functions, since the other rounding functions do not support `__float128` yet.
|
Note Reviews pausedIt looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
📝 Summary
Priority: Change: Feature Merge Risk:
|
| # if defined(_CCCL_BUILTIN_CEILF128) | ||
| return _CCCL_BUILTIN_CEILF128(__x); | ||
| # else // ^^^ _CCCL_BUILTIN_CEILF128 ^^^ / vvv !_CCCL_BUILTIN_CEILF128 vvv | ||
| NV_IF_TARGET(NV_IS_DEVICE, (return ::__nv_fp128_ceil(__x);)) |
There was a problem hiding this comment.
I believe this requires some NV_PROVIDES_SMXY
There was a problem hiding this comment.
Thanks! Switched all four __nv_fp128_* calls to NV_IF_TARGET(NV_PROVIDES_SM_100, ...), matching isnan/min_max, so older architectures fall through to the portable path. Fixed in 65ff009.
miscco
left a comment
There was a problem hiding this comment.
Looks good to me @davebayer can you also give it a look
|
/ok to test 65ff009 |
There was a problem hiding this comment.
🧹 Nitpick comments: 1
libcudacxx/test/libcudacxx/std/numerics/c.math/rounding.pass.cpp: 1
443-446:Trivial · Functional Correctness · Quick win suggestion: Cover all four overloads at the
2^111 + 0.5boundary.The test checks
truncandceilathuge, but notfloororround. A boundary regression in either changed overload can pass. Add the corresponding assertions.assert(eq(cuda::std::trunc(huge), huge - T(0.5))); + assert(eq(cuda::std::floor(huge), huge - T(0.5))); assert(eq(cuda::std::ceil(huge), huge + T(0.5))); + assert(eq(cuda::std::round(huge), huge + T(0.5)));

Review info
-
Run configuration-
- Source mode: Auto
- Repository: NVIDIA/cccl
- Branch: main
- File: .coderabbit.yaml
- Commit: 036ecd2
- Layers: Repository YAML
- Review profile: CHILL
- Plan: Enterprise
- Run ID:
4c63f65d-23de-4905-9bc8-976d54b51ba7
Files selected for processing: 1-
libcudacxx/include/cuda/std/__cmath/rounding_functions.h
Included review availability: This review used your included allowance. Your plan provides up to 12 included reviews per hour; 10 remain after this review.
-
This comment has been minimized.
This comment has been minimized.
|
/ok to test d5dc435 |
This comment has been minimized.
This comment has been minimized.
Co-authored-by: David Bayer <[email protected]>
|
/ok to test 8c32ca0 |
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments: 1
libcudacxx/include/cuda/std/__cmath/rounding_functions.h: 1
41-41:Trivial · Maintainability & Code Quality · Quick win suggestion: Mark
__trunc_fp128_implasconstexpr.The helper depends only on pure bit operations and
constexprhelpers:__fp_get_exp(decompose.h:63),__fp_get_storage, and__fp_from_storage. The libcudacxx guideline requiresconstexprfor such functions.Suggested fix
-[[nodiscard]] _CCCL_API inline __float128 __trunc_fp128_impl(__float128 __x) noexcept +[[nodiscard]] _CCCL_API constexpr __float128 __trunc_fp128_impl(__float128 __x) noexcept

Review info
-
Run configuration-
- Source mode: Auto
- Repository: NVIDIA/cccl
- Branch: main
- File: .coderabbit.yaml
- Commit: 036ecd2
- Layers: Repository YAML
- Review profile: CHILL
- Plan: Enterprise
- Run ID:
57501574-fa6a-45f0-93f4-04b2381bd7ce
Files selected for processing: 1-
libcudacxx/include/cuda/std/__cmath/rounding_functions.h
Included review availability: This review used your included allowance. Your plan provides up to 12 included reviews per hour; 10 remain after this review.
-
This comment has been minimized.
This comment has been minimized.
|
/ok to test 7703cf7 |
🥳 CI Workflow Results🟩 Finished in 2h 30m: Pass: 100%/228 | Total: 3d 18h | Max: 1h 30m | Hits: 82%/875804See results here. |
Description
closes #9940, closes #9941, closes #9942, closes #9943
Adds
__float128overloads forcuda::std::ceil,floor,truncandround, following the pattern from #9895 (fabs) and #9991 (copysign):__builtin_<fn>f128when available (_CCCL_CHECK_BUILTIN(...) || _CCCL_COMPILER(GCC)), undefined for the nvcc device pass.__nv_fp128_<fn>.__trunc_fp128_implclears the fractional mantissa bits using the existing__fp_*storage and mask helpers.floor,ceilandroundare derived from it.roundcomparesx - trunc(x), which is exact, against 0.5 instead of computingtrunc(x + 0.5), which avoids double rounding near the halfway point.The rounding functions are separate overloads rather than one
if constexprtemplate, so the new overloads sit next to the existing__halfand__nv_bfloat16ones inrounding_functions.h.Tests: the generic
test<T>()driver inrounding.pass.cppalso callsllrint,nextafterand the other functions, which don't support__float128yet. So, like #10014 did inlogarithms.pass.cpp, a separatetest_float128driver calls only these four. It also adds float128-specific cases: values beyond the 64-bit range (2^65 + 0.5 and 2^111 + 0.5), halfway cases, signed zeros and NaN.Verified locally (WSL Ubuntu 24.04, CUDA 13.3; no NVIDIA GPU, so device behavior is up to CI):
rounding.pass.cppprecompiles for sm_100 with a clang 18 host, where_CCCL_HAS_FLOAT128()is 1 on both host and device. It also precompiles with a gcc 13 host, where it is 0 because of__STRICT_ANSI__, as a regression check.ceilq/floorq/truncq/roundq) on special values, every exponent boundary from 2^-4 to 2^116, and 4M random inputs. It was built twice, once with the builtins and once with the builtin defines removed to force the fallback. Both runs had 0 mismatches.pre-commit runpasses on the changed files.Checklist