feat(cccl): integrate missing CCCL directories — python/, ci/, .agent/, docs/, test/

Sparse-checkout from NVIDIA/cccl main branch to complete cccl_upstream:

Added:
- python/cuda_cccl/ (226 files) — Python bindings for device-level algorithms
  Critical for muh toolchain: cuda.compute.reduce_into, scan, radix_sort, etc.
  Includes 204 .py files with full test coverage for all 27 algorithms
- ci/ (163 files) — Build/test infrastructure
  build_cub.sh, test_cub.sh, build_and_test_targets.sh, matrix.yaml
  Directly maps to our [INFRA-CI] and [INFRA-BUILD] items
- .agent/skills/ (7 files) — NVIDIA's own agent skills for CCCL
  cccl-style/SKILL.md, cccl-test/SKILL.md, sass-diff/SKILL.md
- docs/ (491 files) — Official CCCL documentation
  CI references, CMake guides, Python compute docs, libcudacxx PTX docs
- test/ (12 files) — Top-level integration tests (cuda_smoke, stdpar)
- Root configs: .clang-format, .clang-tidy, CONTRIBUTING.md, pyproject.toml
- CLAUDE.md symlink → AGENTS.md (NVIDIA's standard)

cccl_upstream now mirrors full NVIDIA/cccl structure:
  Before: 42M (cub + thrust + libcudacxx + cudax + c + examples + benchmarks)
  After:  53M (+python +ci +docs +.agent +test +configs)

This completes the CCCL base needed for:
- [muh-bench] items: ci/util/build_and_test_targets.sh for targeted builds
- [CCCL-verify] items: python/cuda_cccl/tests/ as reference implementations
- [CCCL-test] items: ci/test_cub.sh, ci/test_thrust.sh
- Agent workflow: .agent/skills/ for consistent style and test patterns
This commit is contained in:
muh-bot
2026-08-07 02:34:33 +00:00
parent 3f97dca7ad
commit 2a7ca101d7
908 changed files with 121615 additions and 0 deletions

View File

@@ -0,0 +1,89 @@
.. _libcudacxx-extended-api-numeric-add_overflow:
``cuda::add_overflow``
======================
Defined in ``<cuda/numeric>`` header.
.. code:: cpp
namespace cuda {
template <class T>
struct overflow_result;
template <class Result = /*unspecified*/, class Lhs, class Rhs>
[[nodiscard]] __host__ __device__ constexpr
overflow_result</*see-below*/> add_overflow(Lhs lhs, Rhs rhs) noexcept; // (1)
template <class Result, class Lhs, class Rhs>
[[nodiscard]] __host__ __device__ constexpr
bool add_overflow(Result& result, Lhs lhs, Rhs rhs) noexcept; // (2)
} // namespace cuda
The function ``cuda::add_overflow`` performs addition of two values ``lhs`` and ``rhs`` with overflow checking. The result is the same as if the operands were first promoted to an infinite precision signed type, added together and the result truncated to the type of the return value.
**Parameters**
- ``result``: The result of the addition (2).
- ``lhs``: The left-hand side operand (1, 2).
- ``rhs``: The right-hand side operand (1, 2).
**Return value**
1. Returns an :ref:`overflow_result <libcudacxx-extended-api-numeric-overflow_result>` object containing the result of the addition and a boolean indicating whether an overflow or underflow occurred. If the ``Result`` type is specified, it will be used as the type of the result, otherwise the common type of ``Lhs`` and ``Rhs`` is used.
2. Returns ``true`` if an overflow or underflow occurred, ``false`` otherwise.
**Constraints**
- ``Result``, ``Lhs``, and ``Rhs`` must be `integer types <https://eel.is/c++draft/basic.fundamental#1>`_.
**Performance considerations**
- No overflow checking is required if ``Lhs + Rhs`` is always representable with the ``Result`` type.
- Computation is generally faster when ``Lhs``, ``Rhs``, and ``Result`` have the same signedness.
- Unsigned computations are generally faster than signed computations.
- The function uses PTX ``asm`` on device and compiler intrinsics on host whenever possible.
Example
-------
.. code:: cuda
#include <cuda/numeric>
#include <cuda/std/cassert>
#include <cuda/std/limits>
__global__ void kernel()
{
constexpr auto int_max = cuda::std::numeric_limits<int>::max();
constexpr auto int_min = cuda::std::numeric_limits<int>::min();
// cuda::add_overflow(lhs, rhs) returning common type of lhs and rhs
// 'result' is evaluated to true if an overflow occurred, false otherwise
if (auto result = cuda::add_overflow(1, int_max))
{
assert(result.value == int_min);
}
// cuda::add_overflow<Result>(lhs, rhs) with explicit return type
auto result = cuda::add_overflow<long long>(-1, int_min)
assert(!result.overflow); // no overflow
assert(result.value == static_cast<long long>(int_min) + (-1ll));
unsigned result{};
// cuda::add_overflow(result, lhs, rhs) with bool return type
if (!cuda::add_overflow(result, 1, int_max))
{
assert(result.value == static_cast<unsigned>(int_max) + 1u);
}
}
int main()
{
kernel<<<1, 1>>>();
cudaDeviceSynchronize();
}
`See it on Godbolt 🔗 <https://godbolt.org/z/PPT17ozx6>`_

View File

@@ -0,0 +1,92 @@
.. _libcudacxx-extended-api-numeric-div_overflow:
``cuda::div_overflow``
======================
Defined in ``<cuda/numeric>`` header.
.. code:: cpp
namespace cuda {
template <class T>
struct overflow_result;
template <class Result = /*unspecified*/, class Lhs, class Rhs>
[[nodiscard]] __host__ __device__ constexpr
overflow_result</*see-below*/> div_overflow(Lhs lhs, Rhs rhs) noexcept; // (1)
template <class Result, class Lhs, class Rhs>
[[nodiscard]] __host__ __device__ constexpr
bool div_overflow(Result& result, Lhs lhs, Rhs rhs) noexcept; // (2)
} // namespace cuda
The function ``cuda::div_overflow`` performs integer division of ``lhs`` by ``rhs`` with overflow and error detection. The result is the same as if the operands were first promoted to an infinite precision signed type, divided, and the result truncated to the type of the return value.
**Parameters**
- ``result``: Receives the quotient when no overflow is detected (2).
- ``lhs``: The dividend (1, 2).
- ``rhs``: The divisor (1, 2).
**Return value**
1. Returns an :ref:`overflow_result <libcudacxx-extended-api-numeric-overflow_result>` object containing the computed quotient and a boolean flag indicating whether an overflow or underflow occurred. If the ``Result`` type is specified, it will be used as the type of the result, otherwise the common type of ``Lhs`` and ``Rhs`` is used.
2. Returns ``true`` if an overflow or underflow occurred. When ``false`` is returned, the computed quotient is stored in ``result``.
**Preconditions**
- ``rhs != 0``
**Constraints**
- ``Result``, ``Lhs``, and ``Rhs`` must be `integer types <https://eel.is/c++draft/basic.fundamental#1>`_.
**Notes**
- For signed types, ``numeric_limits<Lhs>::min()`` divided by ``-1`` triggers overflow when ``Result`` matches the operand types.
**Performance considerations**
- No overflow checking if ``Lhs / Rhs`` is always representable with the ``Result`` type.
- The computation with unsigned types is faster than signed types.
Example
-------
.. code:: cuda
#include <cuda/numeric>
#include <cuda/std/cassert>
#include <cuda/std/limits>
__global__ void kernel()
{
constexpr auto int_min = cuda::std::numeric_limits<int>::min();
// cuda::div_overflow(lhs, rhs) returning the common type of the operands
if (auto result = cuda::div_overflow(-1, int_min))
{
assert(result.overflow);
}
// cuda::div_overflow<Result>(lhs, rhs) with an explicitly wider result type
auto wide = cuda::div_overflow<long long>(-1, int_min);
assert(!wide.overflow);
assert(wide.value == 0);
unsigned quotient{};
// cuda::div_overflow(result, lhs, rhs) with bool return type
bool overflow = cuda::div_overflow(quotient, 10u, 2u);
assert(!overflow);
assert(quotient == 5u);
}
int main()
{
kernel<<<1, 1>>>();
cudaDeviceSynchronize();
}
`See it on Godbolt 🔗 <https://godbolt.org/z/dYG3dWss5>`_

View File

@@ -0,0 +1,103 @@
.. _libcudacxx-extended-api-numeric-isclose:
``cuda::isclose``
=================
Defined in ``<cuda/numeric>`` header.
.. code:: cpp
namespace cuda {
template <class T>
[[nodiscard]] __host__ __device__
bool isclose(T lhs, T rhs) noexcept;
template <class T>
[[nodiscard]] __host__ __device__
bool isclose(T lhs, T rhs, float relative_tol) noexcept;
template <class T>
[[nodiscard]] __host__ __device__
bool isclose(T lhs, T rhs, float relative_tol, T absolute_tol) noexcept;
template <class Complex>
[[nodiscard]] __host__ __device__
bool isclose(const Complex& lhs, const Complex& rhs) noexcept;
template <class Complex>
[[nodiscard]] __host__ __device__
bool isclose(const Complex& lhs, const Complex& rhs, float relative_tol) noexcept;
template <class Complex, class AbsTol>
[[nodiscard]] __host__ __device__
bool isclose(const Complex& lhs,
const Complex& rhs,
float relative_tol,
AbsTol absolute_tol) noexcept;
} // namespace cuda
``cuda::isclose`` checks whether two values are approximately equal using the weak symmetric comparison in a similar manner to `PEP 485 <https://peps.python.org/pep-0485/>`_:
.. code:: cpp
abs(lhs - rhs) <= max(absolute_tol, relative_tol * max(abs(lhs), abs(rhs)))
- For integral operands, ``relative_tol`` is interpreted as its exact binary floating-point value. Comparing it to the integral difference is equivalent to rounding the relative threshold down to the nearest integer.
- The overloads without ``relative_tol`` use a default relative tolerance based on half of available digits of accuracy. The default relative tolerance for integer types is 0.
- The overloads without ``absolute_tol`` use ``absolute_tol == 0``.
**Parameters**
- ``lhs``: The first value to compare.
- ``rhs``: The second value to compare.
- ``relative_tol``: The relative tolerance. Passing ``0`` performs a purely absolute tolerance check when ``absolute_tol`` is non-zero.
- ``absolute_tol``: The absolute tolerance. This is useful for comparisons near zero.
**Return value**
- Returns ``true`` if ``lhs`` and ``rhs`` are close to each other, otherwise returns ``false``.
**Preconditions**
- ``relative_tol``: Must be in the range ``[0.0, 1.0]``.
- ``absolute_tol``: Must be finite and non-negative.
**Constraints**
- Scalar overloads require ``lhs``, ``rhs``, ``absolute_tol`` to have the same arithmetic type (integer or floating point).
- Complex overloads accept ``cuda::std::complex<T>`` and ``std::complex<T>`` operands.
- ``AbsTol`` must be the same type as the complex value type.
**Special values**
- ``NaN`` is never close to any value, including another ``NaN``.
- Infinity and negative infinity are only close to themselves.
Example
-------
.. code:: cuda
#include <cuda/numeric>
#include <cuda/std/cassert>
#include <cuda/std/complex>
__global__ void kernel()
{
assert(cuda::isclose( 1.0f, 1.0f + 5e-6f));
assert(!cuda::isclose(1.0f, 1.0f + 2e-5f));
assert(cuda::isclose( 0.0f, 1e-12f, 0.0f, 1e-12f));
cuda::std::complex<float> z1{1.0f, 1.0f};
cuda::std::complex<float> z2{2.0f, 0.0f};
assert(cuda::isclose(z1, z2, 0.75f));
}
int main()
{
kernel<<<1, 1>>>();
cudaDeviceSynchronize();
}

View File

@@ -0,0 +1,88 @@
.. _libcudacxx-extended-api-numeric-mul_overflow:
``cuda::mul_overflow``
======================
Defined in ``<cuda/numeric>`` header.
.. code:: cpp
namespace cuda {
template <class T>
struct overflow_result;
template <class Result = /*unspecified*/, class Lhs, class Rhs>
[[nodiscard]] __host__ __device__ constexpr
overflow_result</*see-below*/> mul_overflow(Lhs lhs, Rhs rhs) noexcept; // (1)
template <class Result, class Lhs, class Rhs>
[[nodiscard]] __host__ __device__ constexpr
bool mul_overflow(Result& result, Lhs lhs, Rhs rhs) noexcept; // (2)
} // namespace cuda
The function ``cuda::mul_overflow`` performs multiplication of two values ``lhs`` and ``rhs`` with overflow checking. The result is the same as if the operands were first promoted to an infinite precision signed type, multiplied together and the result truncated to the type of the return value.
**Parameters**
- ``result``: The result of the multiplication (2).
- ``lhs``: The left-hand side operand (1, 2).
- ``rhs``: The right-hand side operand (1, 2).
**Return value**
1. Returns an :ref:`overflow_result <libcudacxx-extended-api-numeric-overflow_result>` object containing the result of the multiplication and a boolean indicating whether an overflow or underflow occurred. If the ``Result`` type is specified, it will be used as the type of the result, otherwise the common type of ``Lhs`` and ``Rhs`` is used.
2. Returns ``true`` if an overflow or underflow occurred, ``false`` otherwise.
**Constraints**
- ``Result``, ``Lhs``, and ``Rhs`` must be `integer types <https://eel.is/c++draft/basic.fundamental#1>`_.
**Performance considerations**
- No overflow checking is required if ``Lhs + Rhs`` is always representable with the ``Result`` type.
- Computation is generally faster when ``Lhs``, ``Rhs``, and ``Result`` have the same signedness.
- Unsigned computations are generally faster than signed computations.
Example
-------
.. code:: cuda
#include <cuda/numeric>
#include <cuda/std/cassert>
#include <cuda/std/limits>
__global__ void kernel()
{
constexpr auto int_max = cuda::std::numeric_limits<int>::max();
constexpr auto int_min = cuda::std::numeric_limits<int>::min();
// cuda::mul_overflow(lhs, rhs) returning common type of lhs and rhs
// 'result' is evaluated to true if an overflow occurred, false otherwise
if (auto result1 = cuda::mul_overflow(-1, int_min))
{
assert(result1.value == int_min);
}
// cuda::mul_overflow<Result>(lhs, rhs) with explicit return type
auto [result2, overflow2] = cuda::mul_overflow<long long>(-1, int_min);
assert(!overflow2); // no overflow
assert(result2 == static_cast<long long>(int_min) * (-1ll));
unsigned result3{};
// cuda::mul_overflow(result, lhs, rhs) with bool return type
if (!cuda::mul_overflow(result3, 2, int_max))
{
assert(result3 == static_cast<unsigned>(int_max) * 2u);
}
}
int main()
{
kernel<<<1, 1>>>();
cudaDeviceSynchronize();
}
`See it on Godbolt 🔗 <https://godbolt.org/z/hTME8v6rK>`_

View File

@@ -0,0 +1,55 @@
.. _libcudacxx-extended-api-numeric-narrow:
``cuda::narrow``
=====================
.. code:: cpp
struct narrowing_error;
template <typename To, typename From>
[[nodiscard]] constexpr
To narrow(From from);
template <typename To, typename From>
[[nodiscard]] constexpr
To narrow_cast(From&& __from) noexcept;
Both functions use a ``static_cast`` to cast the value ``from`` to type ``To``.
``From`` needs to be convertible to ``To``, and implement ``operator!=``.
``cuda::narrow`` additionally checks whether the value has changed,
and if so, throws ``cuda::narrowing_error`` in host code and traps in device code.
In this case, ``To`` additionally needs to be convertible to ``From``.
``cuda::narrow_cast`` does not perform such a check (it's a plain cast) and is just intended to show
that narrowing and a potential change of the value is intended.
The functions are modelled after ``gsl::narrow`` and ``gsl::narrow_cast``.
See also the C++ Core Guidelines
`ES.46 <https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#Res-narrowing>`_ and
`ES.49 <https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#Res-casts-named>`_.
Example
-------
.. code:: cpp
#include <cuda/numeric>
__global__ void kernel(size_t n) {
unsigned int r1 = cuda::narrow<unsigned int>(n); // traps
unsigned int r2 = cuda::narrow_cast<unsigned int>(n); // truncation of value is intended
}
void host() {
unsigned char r1 = cuda::narrow<unsigned char>( 200); // ok
unsigned char r2 = cuda::narrow<unsigned char>( 300); // throws narrowing_error
unsigned int r3 = cuda::narrow<unsigned int >(-100); // throws narrowing_error
unsigned char r4 = cuda::narrow_cast<unsigned char>(300); // truncation of value is intended
kernel<<<1, 1>>>(2LL << 35); // size larger than unsigned int
}
`See it on Godbolt 🔗 <https://godbolt.org/z/ahcqv6joY>`_

View File

@@ -0,0 +1,68 @@
.. _libcudacxx-extended-api-numeric-overflow_cast:
``cuda::overflow_cast``
==========================
.. code:: cpp
template <class T>
struct overflow_result;
template <class To, class From>
[[nodiscard]] __host__ __device__ inline constexpr
overflow_result<To> overflow_cast(From from) noexcept;
The function ``cuda::overflow_cast`` casts a value of type ``From`` to type ``To`` with overflow checking.
**Parameters**
- ``from``: The value to be casted.
**Return value**
- Returns an :ref:`overflow_result <libcudacxx-extended-api-numeric-overflow_result>` object that contains the result of the cast and a boolean indicating whether an overflow occurred.
**Constraints**
- ``To`` and ``From`` must be `integer types <https://eel.is/c++draft/basic.fundamental#1>`_.
Example
-------
.. code:: cuda
#include <cuda/numeric>
#include <cuda/std/cassert>
#include <cuda/std/limits>
__global__ void kernel()
{
constexpr auto int_max = cuda::std::numeric_limits<int>::max();
constexpr auto int_min = cuda::std::numeric_limits<int>::min();
if (auto result = cuda::overflow_cast<unsigned>(int_max))
{
assert(false); // Should not be reached
}
else
{
assert(result.value == static_cast<unsigned>(int_max));
}
if (auto result = cuda::overflow_cast<unsigned>(int_min))
{
assert(result.value == static_cast<unsigned>(int_min));
}
else
{
assert(false); // Should not be reached
}
}
int main()
{
kernel<<<1, 1>>>();
cudaDeviceSynchronize();
}
`See it on Godbolt 🔗 <https://godbolt.org/z/vK3WMMs1n>`_

View File

@@ -0,0 +1,38 @@
.. _libcudacxx-extended-api-numeric-overflow_result:
``cuda::overflow_result``
=========================
.. code:: cpp
template <class T>
struct overflow_result
{
T value;
bool overflow;
__host__ __device__
constexpr explicit operator bool() const noexcept;
};
The ``overflow_result`` struct is used to represent the result of arithmetic operations that may overflow. It contains the following members:
- ``value``: The result of the operation of type ``T``.
- ``overflow``: A boolean indicating whether an overflow occurred during the operation.
The ``operator bool()`` returns ``true`` if an overflow occurred, and ``false`` otherwise.
It can be used in conditional expressions to check whether an overflow occurred.
Example:
.. code:: cpp
auto result = /* overflow operation */;
if (result)
{
// Overflow occurred
}
**Constraints**
- ``T`` must be an integer type.

View File

@@ -0,0 +1,78 @@
.. _libcudacxx-extended-api-numeric-saturating_add_overflow:
``cuda::saturating_add_overflow``
=================================
Defined in ``<cuda/numeric>`` header.
.. code:: cpp
namespace cuda {
template <class T>
struct overflow_result;
template <class T>
[[nodiscard]] __host__ __device__ constexpr
overflow_result<T> saturating_add_overflow(T lhs, T rhs) noexcept; // (1)
template <class T>
[[nodiscard]] __host__ __device__ constexpr
bool saturating_add_overflow(T& result, T lhs, T rhs) noexcept; // (2)
} // namespace cuda
The function ``cuda::saturating_add_overflow`` performs saturating addition of two values ``lhs`` and ``rhs`` with overflow checking.
**Parameters**
- ``result``: The result of the saturating addition. (2)
- ``lhs``: The left-hand side operand. (1, 2)
- ``rhs``: The right-hand side operand. (1, 2)
**Return value**
1. Returns an :ref:`overflow_result <libcudacxx-extended-api-numeric-overflow_result>` object containing the result of the saturating addition and a boolean indicating whether an overflow or underflow occurred.
2. Returns ``true`` if an overflow or underflow occurred, ``false`` otherwise.
**Constraints**
- ``T`` must be an `integer type <https://eel.is/c++draft/basic.fundamental#1>`_.
**Performance considerations**
- Functionality is implemented by correcting the ``cuda::add_overflow`` result in case of overflow/underflow.
- Unsigned computations are generally faster than signed computations.
Example
-------
.. code:: cuda
#include <cuda/numeric>
#include <cuda/std/cassert>
#include <cuda/std/limits>
__global__ void kernel()
{
constexpr auto int_max = cuda::std::numeric_limits<int>::max();
const auto result = cuda::saturating_add_overflow(1, int_max); // saturated
assert(result.value == int_max);
assert(result.overflow);
int value;
if (cuda::saturating_add_overflow(value, 42, 1024))
{
assert(false); // shouldn't be reached
}
assert(value == 1066);
}
int main()
{
kernel<<<1, 1>>>();
cudaDeviceSynchronize();
}
`See it on Godbolt 🔗 <https://godbolt.org/z/f4jrMb5cW>`_

View File

@@ -0,0 +1,83 @@
.. _libcudacxx-extended-api-numeric-saturating_div_overflow:
``cuda::saturating_div_overflow``
=================================
Defined in ``<cuda/numeric>`` header.
.. code:: cpp
namespace cuda {
template <class T>
struct overflow_result;
template <class T>
[[nodiscard]] __host__ __device__ constexpr
overflow_result<T> saturating_div_overflow(T lhs, T rhs) noexcept; // (1)
template <class T>
[[nodiscard]] __host__ __device__ constexpr
bool saturating_div_overflow(T& result, T lhs, T rhs) noexcept; // (2)
} // namespace cuda
The function ``cuda::saturating_div_overflow`` performs saturating integer division of ``lhs`` by ``rhs`` with overflow and error detection.
**Parameters**
- ``result``: Result of the saturating integer division. (2)
- ``lhs``: The dividend. (1, 2)
- ``rhs``: The divisor. (1, 2)
**Return value**
1. Returns an :ref:`overflow_result <libcudacxx-extended-api-numeric-overflow_result>` object containing the result of saturating integer division and a boolean flag indicating whether an overflow or underflow occurred.
2. Returns ``true`` if an overflow or underflow occurred.
**Preconditions**
- ``rhs != 0``
**Constraints**
- ``T`` must be an `integer type <https://eel.is/c++draft/basic.fundamental#1>`_.
**Performance considerations**
- Functionality is implemented by correcting the ``cuda::div_overflow`` result in case of overflow/underflow.
- Unsigned computations are generally faster than signed computations.
Example
-------
.. code:: cuda
#include <cuda/numeric>
#include <cuda/std/cassert>
#include <cuda/std/limits>
__global__ void kernel()
{
constexpr auto int_max = cuda::std::numeric_limits<int>::max();
constexpr auto int_min = cuda::std::numeric_limits<int>::min();
const auto result = cuda::saturating_div_overflow(int_min, -1); // saturated
assert(result.value == int_max);
assert(result.overflow);
int value;
if (cuda::saturating_div_overflow(value, 256, 8))
{
assert(false); // shouldn't be reached
}
assert(value == 32);
}
int main()
{
kernel<<<1, 1>>>();
cudaDeviceSynchronize();
}
`See it on Godbolt 🔗 <https://godbolt.org/z/T91jMKEjY>`_

View File

@@ -0,0 +1,79 @@
.. _libcudacxx-extended-api-numeric-saturating_mul_overflow:
``cuda::saturating_mul_overflow``
=================================
Defined in ``<cuda/numeric>`` header.
.. code:: cpp
namespace cuda {
template <class T>
struct overflow_result;
template <class T>
[[nodiscard]] __host__ __device__ constexpr
overflow_result<T> saturating_mul_overflow(T lhs, T rhs) noexcept; // (1)
template <class T>
[[nodiscard]] __host__ __device__ constexpr
bool saturating_mul_overflow(T& result, T lhs, T rhs) noexcept; // (2)
} // namespace cuda
The function ``cuda::saturating_mul_overflow`` performs saturating multiplication of two values ``lhs`` and ``rhs`` with overflow checking.
**Parameters**
- ``result``: The result of the saturating multiplication (2).
- ``lhs``: The left-hand side operand (1, 2).
- ``rhs``: The right-hand side operand (1, 2).
**Return value**
1. Returns an :ref:`overflow_result <libcudacxx-extended-api-numeric-overflow_result>` object containing the result of the saturating multiplication and a boolean indicating whether an overflow or underflow occurred.
2. Returns ``true`` if an overflow or underflow occurred, ``false`` otherwise.
**Constraints**
- ``T`` must be an `integer type <https://eel.is/c++draft/basic.fundamental#1>`_.
**Performance considerations**
- Functionality is implemented by correcting the ``cuda::mul_overflow`` result in case of overflow/underflow.
- Unsigned computations are generally faster than signed computations.
Example
-------
.. code:: cuda
#include <cuda/numeric>
#include <cuda/std/cassert>
#include <cuda/std/limits>
__global__ void kernel()
{
constexpr auto int_max = cuda::std::numeric_limits<int>::max();
constexpr auto int_min = cuda::std::numeric_limits<int>::min();
const auto result = cuda::saturating_mul_overflow(int_max, int_min); // saturated
assert(result.value == int_min);
assert(result.overflow);
int value;
if (cuda::saturating_mul_overflow(value, 4, 8))
{
assert(false); // shouldn't be reached
}
assert(value == 32);
}
int main()
{
kernel<<<1, 1>>>();
cudaDeviceSynchronize();
}
`See it on Godbolt 🔗 <https://godbolt.org/z/chrG67YWT>`_

View File

@@ -0,0 +1,68 @@
.. _libcudacxx-extended-api-numeric-saturating_overflow_cast:
``cuda::overflow_cast``
==========================
.. code:: cpp
template <class T>
struct overflow_result;
template <class To, class From>
[[nodiscard]] __host__ __device__ inline constexpr
overflow_result<To> saturating_overflow_cast(From from) noexcept;
The function ``cuda::saturating_overflow_cast`` does saturating cast of a value of type ``From`` to type ``To`` with overflow checking.
**Parameters**
- ``from``: The value to be casted.
**Return value**
- Returns an :ref:`overflow_result <libcudacxx-extended-api-numeric-overflow_result>` object that contains the result of the saturating cast and a boolean indicating whether an overflow occurred.
**Constraints**
- ``To`` and ``From`` must be `integer types <https://eel.is/c++draft/basic.fundamental#1>`_.
Example
-------
.. code:: cuda
#include <cuda/numeric>
#include <cuda/std/cassert>
#include <cuda/std/limits>
__global__ void kernel()
{
constexpr auto int_max = cuda::std::numeric_limits<int>::max();
constexpr auto int_min = cuda::std::numeric_limits<int>::min();
if (auto result = cuda::saturating_overflow_cast<unsigned>(int_max))
{
assert(false); // Should not be reached
}
else
{
assert(result.value == static_cast<unsigned>(int_max));
}
if (auto result = cuda::saturating_overflow_cast<unsigned>(int_min)) // saturated
{
assert(result.value == 0);
}
else
{
assert(false); // Should not be reached
}
}
int main()
{
kernel<<<1, 1>>>();
cudaDeviceSynchronize();
}
`See it on Godbolt 🔗 <https://godbolt.org/z/jcv39ohso>`_

View File

@@ -0,0 +1,78 @@
.. _libcudacxx-extended-api-numeric-saturating_sub_overflow:
``cuda::saturating_sub_overflow``
=================================
Defined in ``<cuda/numeric>`` header.
.. code:: cpp
namespace cuda {
template <class T>
struct overflow_result;
template <class T>
[[nodiscard]] __host__ __device__ constexpr
overflow_result<T> saturating_sub_overflow(T lhs, T rhs) noexcept; // (1)
template <class T>
[[nodiscard]] __host__ __device__ constexpr
bool saturating_sub_overflow(T& result, T lhs, T rhs) noexcept; // (2)
} // namespace cuda
The function ``cuda::saturating_sub_overflow`` performs saturating subtraction of two values ``lhs`` and ``rhs`` with overflow detection.
**Parameters**
- ``result``: The result of the saturating subtraction. (2)
- ``lhs``: The left-hand side operand. (1, 2)
- ``rhs``: The right-hand side operand. (1, 2)
**Return value**
1. Returns an :ref:`overflow_result <libcudacxx-extended-api-numeric-overflow_result>` object containing the result of the saturating subtraction and a boolean flag indicating whether an overflow or underflow occurred.
2. Returns ``true`` if an overflow or underflow occurred, ``false`` otherwise.
**Constraints**
- ``T`` must be an `integer type <https://eel.is/c++draft/basic.fundamental#1>`_.
**Performance considerations**
- Functionality is implemented by correcting the ``cuda::sub_overflow`` result in case of overflow/underflow.
- Unsigned computations are generally faster than signed computations.
Example
-------
.. code:: cuda
#include <cuda/numeric>
#include <cuda/std/cassert>
#include <cuda/std/limits>
__global__ void kernel()
{
constexpr auto uint_max = cuda::std::numeric_limits<unsigned>::max();
const auto result = cuda::saturating_sub_overflow(42u, uint_max); // saturated
assert(result.value == 0);
assert(result.overflow);
int value;
if (cuda::saturating_sub_overflow(value, 42, 1024))
{
assert(false); // shouldn't be reached
}
assert(value == -982);
}
int main()
{
kernel<<<1, 1>>>();
cudaDeviceSynchronize();
}
`See it on Godbolt 🔗 <https://godbolt.org/z/1M9j9oG9z>`_

View File

@@ -0,0 +1,87 @@
.. _libcudacxx-extended-api-numeric-sub_overflow:
``cuda::sub_overflow``
======================
Defined in ``<cuda/numeric>`` header.
.. code:: cpp
namespace cuda {
template <class T>
struct overflow_result;
template <class Result = /*unspecified*/, class Lhs, class Rhs>
[[nodiscard]] __host__ __device__ constexpr
overflow_result</*see-below*/> sub_overflow(Lhs lhs, Rhs rhs) noexcept; // (1)
template <class Result, class Lhs, class Rhs>
[[nodiscard]] __host__ __device__ constexpr
bool sub_overflow(Result& result, Lhs lhs, Rhs rhs) noexcept; // (2)
} // namespace cuda
The function ``cuda::sub_overflow`` performs subtraction of two values ``lhs`` and ``rhs`` with overflow detection. The result is the same as if the operands were first promoted to an infinite precision signed type, subtracted, and then the result truncated to the type of the return value.
**Parameters**
- ``result``: The result of the subtraction (2).
- ``lhs``: The left-hand side operand (1, 2).
- ``rhs``: The right-hand side operand (1, 2).
**Return value**
1. Returns an :ref:`overflow_result <libcudacxx-extended-api-numeric-overflow_result>` object containing the computed difference and a boolean flag indicating whether an overflow or underflow occurred. If the ``Result`` type is specified, it will be used as the type of the result, otherwise the common type of ``Lhs`` and ``Rhs`` is used.
2. Returns ``true`` if an overflow or underflow occurred, ``false`` otherwise.
**Constraints**
- ``Result``, ``Lhs``, and ``Rhs`` must be `integer types <https://eel.is/c++draft/basic.fundamental#1>`_.
**Performance considerations**
- No overflow checking is required when ``lhs - rhs`` is always representable with the ``Result`` type.
- Computation is generally faster when ``Lhs``, ``Rhs``, and ``Result`` have the same signedness.
- Unsigned computations are generally faster than signed computations.
- The function uses PTX ``asm`` on device and compiler intrinsics on host whenever possible.
Example
-------
.. code:: cuda
#include <cuda/numeric>
#include <cuda/std/cassert>
#include <cuda/std/limits>
__global__ void kernel()
{
constexpr auto int_max = cuda::std::numeric_limits<int>::max();
constexpr auto int_min = cuda::std::numeric_limits<int>::min();
// cuda::sub_overflow(lhs, rhs) returning the common type of lhs and rhs
auto result = cuda::sub_overflow(3, 1))
assert(result.value == 2);
// cuda::sub_overflow<Result>(lhs, rhs) with an explicit result type
auto result2 = cuda::sub_overflow<long long>(int_min, 1);
assert(!result2.overflow);
assert(result2.value == static_cast<long long>(int_min) - 1ll);
unsigned result3{};
// cuda::sub_overflow(result, lhs, rhs) returning a bool flag
if (!cuda::sub_overflow(result, 5u, 3u))
{
assert(result == 2u);
}
}
int main()
{
kernel<<<1, 1>>>();
cudaDeviceSynchronize();
}
`See it on Godbolt 🔗 <https://godbolt.org/z/Pq8sc9s7a>`_