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:
77
cccl_upstream/docs/libcudacxx/extended_api/math/ceil_div.rst
Normal file
77
cccl_upstream/docs/libcudacxx/extended_api/math/ceil_div.rst
Normal file
@@ -0,0 +1,77 @@
|
||||
.. _libcudacxx-extended-api-math-ceil-div:
|
||||
|
||||
``cuda::ceil_div``
|
||||
==================
|
||||
|
||||
Defined in the ``<cuda/cmath>`` header.
|
||||
|
||||
.. code:: cuda
|
||||
|
||||
namespace cuda {
|
||||
|
||||
template <typename T, typename U>
|
||||
[[nodiscard]] __host__ __device__ constexpr
|
||||
cuda::std::common_type_t<T, U> ceil_div(T value, U divisor) noexcept;
|
||||
|
||||
} // namespace cuda
|
||||
|
||||
The function computes the ceiling division between two integral or enumerator values :math:`ceil(\frac{value}{base\_multiple})`.
|
||||
|
||||
**Parameters**
|
||||
|
||||
- ``value``: The value to be divided.
|
||||
- ``divisor``: The divisor.
|
||||
|
||||
**Return value**
|
||||
|
||||
Divides ``value`` by ``divisor``. If ``value`` is not a multiple of ``divisor`` rounds the result up to the next integer value.
|
||||
|
||||
**Constraints**
|
||||
|
||||
- ``T`` and ``U`` are integer types or enumerators.
|
||||
|
||||
**Preconditions**
|
||||
|
||||
- ``value >= 0``
|
||||
- ``divisor > 0``
|
||||
|
||||
**Performance considerations**
|
||||
|
||||
- The function computes ``(value + divisor - 1) / divisor`` when the common type is a signed integer.
|
||||
- The function computes ``min(value, 1 + ((value - 1) / divisor)`` when the common type is an unsigned integer in CUDA, which generates less instructions than ``(value / divisor) + ((value / divisor) * divisor != value)``, especially for 64-bit types.
|
||||
|
||||
Example
|
||||
-------
|
||||
|
||||
This API is very useful for determining the *number of thread blocks* required to process a fixed amount of work, given a fixed number of threads per block:
|
||||
|
||||
.. code:: cuda
|
||||
|
||||
#include <cuda/cmath>
|
||||
#include <cuda/std/span>
|
||||
#include <thrust/device_vector.h>
|
||||
|
||||
__global__ void vector_scale_kernel(cuda::std::span<float> span, float scale) {
|
||||
int index = blockIdx.x * blockDim.x + threadIdx.x;
|
||||
if (index < span.size())
|
||||
span[index] *= scale;
|
||||
}
|
||||
|
||||
int main() {
|
||||
int num_items = 100'000;
|
||||
float scale = 2.f;
|
||||
thrust::device_vector<float> d_vector(num_items, 1.f);
|
||||
// Given a fixed number of threads per block...
|
||||
constexpr int threads_per_block = 256;
|
||||
// ...dividing some "n" by "threads_per_block" may lead to a remainder,
|
||||
// requiring the kernel to be launched with an extra thread block to handle it.
|
||||
auto num_thread_blocks = cuda::ceil_div(num_items, threads_per_block);
|
||||
auto d_ptr = thrust::raw_pointer_cast(d_vector.data());
|
||||
cuda::std::span<float> d_span(d_ptr, num_items);
|
||||
|
||||
vector_scale_kernel<<<num_thread_blocks, threads_per_block>>>(d_span, scale);
|
||||
cudaDeviceSynchronize();
|
||||
return 0;
|
||||
}
|
||||
|
||||
`See it on Godbolt 🔗 <https://godbolt.org/z/dj9a5137z>`__
|
||||
@@ -0,0 +1,92 @@
|
||||
.. _libcudacxx-extended-api-math-fast-mod-div:
|
||||
|
||||
``cuda::fast_mod_div``
|
||||
======================
|
||||
|
||||
Defined in the ``<cuda/cmath>`` header.
|
||||
|
||||
.. code:: cuda
|
||||
|
||||
namespace cuda {
|
||||
|
||||
template <typename T, bool DivisorIsNeverOne = false>
|
||||
class fast_mod_div {
|
||||
public:
|
||||
fast_mod_div() = delete;
|
||||
|
||||
__host__ __device__
|
||||
explicit fast_mod_div(T divisor) noexcept;
|
||||
|
||||
template <typename U>
|
||||
[[nodiscard]] __host__ __device__ friend
|
||||
cuda:::std::common_type_t<T, U> operator/(U dividend, fast_mod_div<T> divisor) noexcept;
|
||||
|
||||
template <typename U>
|
||||
[[nodiscard]] __host__ __device__ friend
|
||||
cuda:::std::common_type_t<T, U> operator%(U dividend, fast_mod_div<T> divisor) noexcept;
|
||||
|
||||
[[nodiscard]] __host__ __device__
|
||||
operator T() const noexcept;
|
||||
};
|
||||
|
||||
} // namespace cuda
|
||||
|
||||
.. code:: cuda
|
||||
|
||||
namespace cuda {
|
||||
|
||||
template <typename T, typename U>
|
||||
[[nodiscard]] __host__ __device__
|
||||
cuda::std::pair<T, U> div(T dividend, fast_mod_div<U> divisor) noexcept;
|
||||
|
||||
} // namespace cuda
|
||||
|
||||
The class ``fast_mod_div`` is used to pre-compute the modulo and division of an integer value, to be used in a second stage for efficiency: :math:`floor\left(\frac{dividend}{divisor}\right)`.
|
||||
|
||||
**Parameters**
|
||||
|
||||
- ``divisor``: The divisor.
|
||||
- ``dividend``: The dividend.
|
||||
- ``DivisorIsNeverOne``: Indicates that ``divisor != 1`` and skips one comparison in the second stage.
|
||||
|
||||
**Constraints**
|
||||
|
||||
- ``T`` and ``U`` are integer types.
|
||||
- ``max_value(dividend type) <= max_value(divisor type)``.
|
||||
|
||||
**Preconditions**
|
||||
|
||||
- ``divisor > 0``.
|
||||
- ``dividend >= 0``.
|
||||
- ``divisor > 1`` if ``DivisorIsNeverOne == true``.
|
||||
|
||||
**Performance considerations**
|
||||
|
||||
- ``fast_mod_div`` needs to be initialized on the host and executed on the device for optimal performance.
|
||||
- ``T`` signed type ensures the best performance. ``T == int`` translates to ``SEL``, ``IMAD``, and x2 ``SHF`` instructions.
|
||||
- Larger types (> 32-bits) are slower than smaller types.
|
||||
- ``DivisorIsNeverOne == true`` can be used to skip one comparison.
|
||||
- ``__builtin_assume(dividend != cuda::std::numeric_limits<U>::max())`` can be used to skip one comparison with unsigned values.
|
||||
|
||||
Example
|
||||
-------
|
||||
|
||||
.. code:: cuda
|
||||
|
||||
#include <cuda/cmath>
|
||||
#include <cuda/std/cassert>
|
||||
|
||||
__global__ void div_kernel(cuda::fast_mod_div<int> divisor) {
|
||||
assert(45 / divisor == 2);
|
||||
assert(45 % divisor == 5);
|
||||
assert((cuda::div(45, divisor) == cuda::std::pair{2, 5}));
|
||||
}
|
||||
|
||||
int main() {
|
||||
cuda::fast_mod_div<int> divisor(20);
|
||||
div_kernel<<<1, 1>>>(divisor);
|
||||
cudaDeviceSynchronize();
|
||||
return 0;
|
||||
}
|
||||
|
||||
`See it on Godbolt 🔗 <https://godbolt.org/z/fM7E9v9aP>`__
|
||||
83
cccl_upstream/docs/libcudacxx/extended_api/math/ilog.rst
Normal file
83
cccl_upstream/docs/libcudacxx/extended_api/math/ilog.rst
Normal file
@@ -0,0 +1,83 @@
|
||||
.. _libcudacxx-extended-api-math-ilog:
|
||||
|
||||
``cuda::ilog2``, ``cuda::ceil_ilog2``, ``cuda::ilog10``, and ``cuda::ceil_ilog10``
|
||||
=================================================================================
|
||||
|
||||
Defined in the ``<cuda/cmath>`` header.
|
||||
|
||||
.. code:: cuda
|
||||
|
||||
namespace cuda {
|
||||
|
||||
template <typename T>
|
||||
[[nodiscard]] __host__ __device__ __tile__ constexpr
|
||||
int ilog2(T value) noexcept;
|
||||
|
||||
template <typename T>
|
||||
[[nodiscard]] __host__ __device__ __tile__ constexpr
|
||||
int ceil_ilog2(T value) noexcept;
|
||||
|
||||
template <typename T>
|
||||
[[nodiscard]] __host__ __device__ __tile__ constexpr
|
||||
int ilog10(T value) noexcept;
|
||||
|
||||
template <typename T>
|
||||
[[nodiscard]] __host__ __device__ __tile__ constexpr
|
||||
int ceil_ilog10(T value) noexcept;
|
||||
|
||||
} // namespace cuda
|
||||
|
||||
The functions compute the logarithm to the base 2 and 10 of an integer value.
|
||||
|
||||
**Parameters**
|
||||
|
||||
- ``value``: The input value.
|
||||
|
||||
**Return value**
|
||||
|
||||
- ``ilog2``, ``ceil_ilog2``: The logarithm to the base 2, rounded down and up to the nearest integer respectively.
|
||||
- ``ilog10``, ``ceil_ilog10``: The logarithm to the base 10, rounded down and up to the nearest integer respectively.
|
||||
|
||||
**Constraints**
|
||||
|
||||
- ``T`` is an integer type.
|
||||
|
||||
**Preconditions**
|
||||
|
||||
- ``value > 0``
|
||||
|
||||
**Performance considerations**
|
||||
|
||||
The functions perform the following operations in device code:
|
||||
|
||||
- ``ilog2``: ``FLO``
|
||||
- ``ceil_ilog2``: ``FLO``, ``POPC``, ``ADD``, comparison
|
||||
- ``ilog10``: ``FLO``, ``FMUL``, ``F2I``, constant memory lookup, ``SEL`` + ``IADD`` only if ``T == uint32_t`` or ``T == __uint128_t``
|
||||
- ``ceil_ilog10``: ``ilog10`` with an additional comparison, subtraction, and ``IADD``
|
||||
|
||||
Example
|
||||
-------
|
||||
|
||||
.. code:: cuda
|
||||
|
||||
#include <cuda/cmath>
|
||||
#include <cuda/std/cassert>
|
||||
|
||||
__global__ void ilog_kernel() {
|
||||
assert(cuda::ilog2(20) == 4);
|
||||
assert(cuda::ceil_ilog2(20) == 5);
|
||||
assert(cuda::ilog2(32) == 5);
|
||||
assert(cuda::ceil_ilog2(32) == 5);
|
||||
assert(cuda::ilog10(100) == 2);
|
||||
assert(cuda::ilog10(2000) == 3);
|
||||
assert(cuda::ceil_ilog10(100) == 2);
|
||||
assert(cuda::ceil_ilog10(2000) == 4);
|
||||
}
|
||||
|
||||
int main() {
|
||||
ilog_kernel<<<1, 1>>>();
|
||||
cudaDeviceSynchronize();
|
||||
return 0;
|
||||
}
|
||||
|
||||
`See it on Godbolt 🔗 <https://godbolt.org/z/7W3WaGd3c>`__
|
||||
60
cccl_upstream/docs/libcudacxx/extended_api/math/ipow.rst
Normal file
60
cccl_upstream/docs/libcudacxx/extended_api/math/ipow.rst
Normal file
@@ -0,0 +1,60 @@
|
||||
.. _libcudacxx-extended-api-math-ipow:
|
||||
|
||||
``cuda::ipow``
|
||||
====================================
|
||||
|
||||
Defined in the ``<cuda/cmath>`` header.
|
||||
|
||||
.. code:: cuda
|
||||
|
||||
namespace cuda {
|
||||
|
||||
template <typename T, typename E>
|
||||
[[nodiscard]] __host__ __device__ constexpr
|
||||
T ipow(T base, E exp) noexcept;
|
||||
|
||||
} // namespace cuda
|
||||
|
||||
The function computes the integer ``base`` raised to the power of ``exp``.
|
||||
|
||||
**Parameters**
|
||||
|
||||
- ``base``: The base value.
|
||||
- ``exp``: The exponent value.
|
||||
|
||||
**Return value**
|
||||
|
||||
- The result of raising ``base`` to the power of ``exp``. If ``exp`` is negative, the result is 0.
|
||||
|
||||
**Constraints**
|
||||
|
||||
- ``T`` is an integer type.
|
||||
- ``E`` is an integer type.
|
||||
|
||||
**Preconditions**
|
||||
|
||||
- if ``base`` is 0, then ``exp`` must be non-negative.
|
||||
|
||||
Example
|
||||
-------
|
||||
|
||||
.. code:: cuda
|
||||
|
||||
#include <cuda/cmath>
|
||||
#include <cuda/std/cassert>
|
||||
|
||||
__global__ void ipow_kernel() {
|
||||
assert(cuda::ipow(0, 0) == 1);
|
||||
assert(cuda::ipow(2, 2) == 4);
|
||||
assert(cuda::ipow(99, 1) == 99);
|
||||
assert(cuda::ipow(4, 7) == 16384);
|
||||
assert(cuda::ipow(-1, 3) == -1);
|
||||
assert(cuda::ipow(23, -1) == 0);
|
||||
}
|
||||
|
||||
int main() {
|
||||
ipow_kernel<<<1, 1>>>();
|
||||
cudaDeviceSynchronize();
|
||||
}
|
||||
|
||||
`See it on Godbolt 🔗 <https://godbolt.org/z/TMacWvz8v>`__
|
||||
57
cccl_upstream/docs/libcudacxx/extended_api/math/isqrt.rst
Normal file
57
cccl_upstream/docs/libcudacxx/extended_api/math/isqrt.rst
Normal file
@@ -0,0 +1,57 @@
|
||||
.. _libcudacxx-extended-api-math-isqrt:
|
||||
|
||||
``cuda::isqrt``
|
||||
====================================
|
||||
|
||||
Defined in the ``<cuda/cmath>`` header.
|
||||
|
||||
.. code:: cuda
|
||||
|
||||
namespace cuda {
|
||||
|
||||
template <typename T>
|
||||
[[nodiscard]] __host__ __device__ constexpr
|
||||
T isqrt(T value) noexcept;
|
||||
|
||||
} // namespace cuda
|
||||
|
||||
The function computes the integer square root of the input value rounded down.
|
||||
|
||||
**Parameters**
|
||||
|
||||
- ``value``: The input value.
|
||||
|
||||
**Return value**
|
||||
|
||||
- The square root value of the input value rounded down.
|
||||
|
||||
**Constraints**
|
||||
|
||||
- ``T`` is an integer type.
|
||||
|
||||
**Preconditions**
|
||||
|
||||
- ``value`` is non-negative.
|
||||
|
||||
Example
|
||||
-------
|
||||
|
||||
.. code:: cuda
|
||||
|
||||
#include <cuda/cmath>
|
||||
#include <cuda/std/cassert>
|
||||
|
||||
__global__ void isqrt_kernel() {
|
||||
assert(cuda::isqrt(1) == 1);
|
||||
assert(cuda::isqrt(4) == 2);
|
||||
assert(cuda::isqrt(42) == 6);
|
||||
assert(cuda::isqrt(99) == 9);
|
||||
assert(cuda::isqrt(100) == 10);
|
||||
}
|
||||
|
||||
int main() {
|
||||
isqrt_kernel<<<1, 1>>>();
|
||||
cudaDeviceSynchronize();
|
||||
}
|
||||
|
||||
`See it on Godbolt 🔗 <https://godbolt.org/z/xPcj35dq6>`__
|
||||
64
cccl_upstream/docs/libcudacxx/extended_api/math/mul_hi.rst
Normal file
64
cccl_upstream/docs/libcudacxx/extended_api/math/mul_hi.rst
Normal file
@@ -0,0 +1,64 @@
|
||||
.. _libcudacxx-extended-api-math-mul-hi:
|
||||
|
||||
``cuda::mul_hi``
|
||||
================
|
||||
|
||||
Defined in ``<cuda/cmath>`` header.
|
||||
|
||||
.. code:: cuda
|
||||
|
||||
namespace cuda {
|
||||
|
||||
template <typename T>
|
||||
[[nodiscard]] __host__ __device__ constexpr
|
||||
T mul_hi(T lhs, T rhs) noexcept;
|
||||
|
||||
} // namespace cuda
|
||||
|
||||
Computes the most significant half of the bits of the product of two non-negative integers ``lhs`` and ``rhs``.
|
||||
|
||||
**Parameters**
|
||||
|
||||
- ``lhs``: First multiplicand.
|
||||
- ``rhs``: Second multiplicand.
|
||||
|
||||
**Return value**
|
||||
|
||||
- The most significant half of ``lhs * rhs`` returned as ``T``.
|
||||
|
||||
**Constraints**
|
||||
|
||||
- ``T`` is an integer type.
|
||||
|
||||
**Remarks**
|
||||
|
||||
- Uses ``__mulhi``, ``__umulhi``, ``__mul64hi``, ``__umul64hi`` intrinsics on device when available.
|
||||
- Uses ``__mulh``, ``__umulh`` intrinsics on Windows host code when available.
|
||||
- Uses a double-width intermediate type when possible.
|
||||
- Relies on a manual decomposition fallback when 128-bit intermediates are unavailable for 64-bit integers.
|
||||
|
||||
Example
|
||||
-------
|
||||
|
||||
.. code:: cuda
|
||||
|
||||
#include <cuda/cmath>
|
||||
#include <cuda/std/cassert>
|
||||
#include <cuda/std/cstdint>
|
||||
|
||||
__global__ void mul_hi_kernel()
|
||||
{
|
||||
uint32_t lhs = 0xABCD1234;
|
||||
uint32_t rhs = 1 << 16; // 2^16
|
||||
uint32_t high_half = cuda::mul_hi(lhs, rhs);
|
||||
assert(high_half == 0xAB);
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
mul_hi_kernel<<<1, 1>>>();
|
||||
cudaDeviceSynchronize();
|
||||
return 0;
|
||||
}
|
||||
|
||||
`See it on Godbolt 🔗 <https://godbolt.org/z/64r6zT9Wq>`__
|
||||
57
cccl_upstream/docs/libcudacxx/extended_api/math/neg.rst
Normal file
57
cccl_upstream/docs/libcudacxx/extended_api/math/neg.rst
Normal file
@@ -0,0 +1,57 @@
|
||||
.. _libcudacxx-extended-api-math-neg:
|
||||
|
||||
``cuda::neg``
|
||||
====================================
|
||||
|
||||
Defined in the ``<cuda/cmath>`` header.
|
||||
|
||||
.. code:: cuda
|
||||
|
||||
namespace cuda {
|
||||
|
||||
template <typename T>
|
||||
[[nodiscard]] __host__ __device__ constexpr
|
||||
T neg(T value) noexcept;
|
||||
|
||||
} // namespace cuda
|
||||
|
||||
The function computes the negation of the input value accepting both signed and unsigned integer types. It doesn't emit any warnings for signed integer overflow and applying ``-`` to unsigned integer types.
|
||||
|
||||
**Parameters**
|
||||
|
||||
- ``value``: The input value.
|
||||
|
||||
**Return value**
|
||||
|
||||
- The negated value of the input value.
|
||||
|
||||
**Constraints**
|
||||
|
||||
- ``T`` is an integer type.
|
||||
|
||||
Example
|
||||
-------
|
||||
|
||||
.. code:: cuda
|
||||
|
||||
#include <cuda/cmath>
|
||||
#include <cuda/std/cassert>
|
||||
#include <cuda/std/limits>
|
||||
|
||||
__global__ void neg_kernel() {
|
||||
using cuda::std::numeric_limits;
|
||||
|
||||
assert(cuda::neg(1) == -1);
|
||||
assert(cuda::neg(20) == -20);
|
||||
assert(cuda::neg(127u) == 4294967169u);
|
||||
assert(cuda::neg(-127) == 127);
|
||||
assert(cuda::neg(cuda::std::numeric_limits<int>::min()) == cuda::std::numeric_limits<int>::min());
|
||||
}
|
||||
|
||||
int main() {
|
||||
neg_kernel<<<1, 1>>>();
|
||||
cudaDeviceSynchronize();
|
||||
return 0;
|
||||
}
|
||||
|
||||
`See it on Godbolt 🔗 <https://godbolt.org/z/K3zcE9zqn>`__
|
||||
70
cccl_upstream/docs/libcudacxx/extended_api/math/pow2.rst
Normal file
70
cccl_upstream/docs/libcudacxx/extended_api/math/pow2.rst
Normal file
@@ -0,0 +1,70 @@
|
||||
.. _libcudacxx-extended-api-math-pow2:
|
||||
|
||||
Power of Two Utilities
|
||||
======================
|
||||
|
||||
Defined in the ``<cuda/cmath>`` header.
|
||||
|
||||
.. code:: cuda
|
||||
|
||||
namespace cuda {
|
||||
|
||||
template <typename T>
|
||||
[[nodiscard]] __host__ __device__ constexpr
|
||||
bool is_power_of_two(T value) noexcept;
|
||||
|
||||
template <typename T>
|
||||
[[nodiscard]] __host__ __device__ constexpr
|
||||
T next_power_of_two(T value) noexcept;
|
||||
|
||||
template <typename T>
|
||||
[[nodiscard]] __host__ __device__ constexpr
|
||||
T prev_power_of_two(T value) noexcept;
|
||||
|
||||
} // namespace cuda
|
||||
|
||||
The functions provide utilities to determine if an integer value is a power of two, and to compute the next and previous power of two.
|
||||
|
||||
**Parameters**
|
||||
|
||||
- ``value``: The input value.
|
||||
|
||||
**Return value**
|
||||
|
||||
- ``is_power_of_two``: Return ``true`` if ``value`` is a power of two, ``false`` otherwise.
|
||||
- ``next_power_of_two``: Return the smallest power of two greater than or equal to ``value``.
|
||||
- ``prev_power_of_two``: Return the largest power of two less than or equal to ``value``.
|
||||
|
||||
**Constraints**
|
||||
|
||||
- ``T`` is an integer types. Contrary to ``cuda::std::has_single_bit``, ``cuda::std::bit_floor``, and ``cuda::std::bit_ceil``, ``T`` can be both signed and unsigned.
|
||||
|
||||
**Preconditions**
|
||||
|
||||
- ``value > 0``
|
||||
|
||||
**Performance considerations**
|
||||
|
||||
See :ref:`\<cuda/std/bit\> performance considerations <libcudacxx-standard-api-numerics-bit>`
|
||||
|
||||
Example
|
||||
-------
|
||||
|
||||
.. code:: cuda
|
||||
|
||||
#include <cuda/cmath>
|
||||
#include <cuda/std/cassert>
|
||||
|
||||
__global__ void pow2_kernel() {
|
||||
assert(!cuda::is_power_of_two(20));
|
||||
assert(cuda::next_power_of_two(20) == 32);
|
||||
assert(cuda::prev_power_of_two(20) == 16);
|
||||
}
|
||||
|
||||
int main() {
|
||||
pow2_kernel<<<1, 1>>>();
|
||||
cudaDeviceSynchronize();
|
||||
return 0;
|
||||
}
|
||||
|
||||
`See it on Godbolt 🔗 <https://godbolt.org/z/896Yx3vf8>`__
|
||||
@@ -0,0 +1,62 @@
|
||||
.. _libcudacxx-extended-api-math-round-down:
|
||||
|
||||
``cuda::round_down``
|
||||
====================
|
||||
|
||||
Defined in the ``<cuda/cmath>`` header.
|
||||
|
||||
.. code:: cuda
|
||||
|
||||
namespace cuda {
|
||||
|
||||
template <typename T, typename U>
|
||||
[[nodiscard]] __host__ __device__ constexpr
|
||||
cuda::std::common_type_t<T, U> round_down(T value, U base_multiple) noexcept;
|
||||
|
||||
} // namespace cuda
|
||||
|
||||
The function computes the round down to the largest multiple of an integral or enumerator value :math:`floor(\frac{value}{base\_multiple}) * base\_multiple`
|
||||
|
||||
**Parameters**
|
||||
|
||||
- ``value``: The value to be rounded down.
|
||||
- ``base_multiple``: The base multiple to which the value rounds down.
|
||||
|
||||
**Return value**
|
||||
|
||||
``value`` rounded down to the largest multiple of ``base_multiple`` less than or equal to ``value``. If ``value`` is already a multiple of ``base_multiple``, returns ``value``.
|
||||
|
||||
**Constraints**
|
||||
|
||||
- ``T`` and ``U`` are integer types or enumerators.
|
||||
|
||||
**Preconditions**
|
||||
|
||||
- ``value >= 0``
|
||||
- ``base_multiple > 0``
|
||||
|
||||
**Performance considerations**
|
||||
|
||||
- The function performs a truncation division followed by a multiplication. It provides better performance than ``(value / base_multiple) * base_multiple`` when the common type is a signed integer
|
||||
|
||||
Example
|
||||
-------
|
||||
|
||||
.. code:: cuda
|
||||
|
||||
#include <cuda/cmath>
|
||||
#include <cstdio>
|
||||
|
||||
__global__ void round_up_kernel() {
|
||||
int value = 7;
|
||||
unsigned multiple = 3;
|
||||
printf("%d\n", cuda::round_down(value, multiple)); // print "6"
|
||||
}
|
||||
|
||||
int main() {
|
||||
round_up_kernel<<<1, 1>>>();
|
||||
cudaDeviceSynchronize();
|
||||
return 0;
|
||||
}
|
||||
|
||||
`See it on Godbolt 🔗 <https://godbolt.org/z/cxGYfMGna>`__
|
||||
66
cccl_upstream/docs/libcudacxx/extended_api/math/round_up.rst
Normal file
66
cccl_upstream/docs/libcudacxx/extended_api/math/round_up.rst
Normal file
@@ -0,0 +1,66 @@
|
||||
.. _libcudacxx-extended-api-math-round-up:
|
||||
|
||||
``cuda::round_up``
|
||||
==================
|
||||
|
||||
Defined in the ``<cuda/cmath>`` header.
|
||||
|
||||
.. code:: cuda
|
||||
|
||||
namespace cuda {
|
||||
|
||||
template <typename T, typename U>
|
||||
[[nodiscard]] __host__ __device__ constexpr
|
||||
cuda::std::common_type_t<T, U> round_up(T value, U base_multiple) noexcept;
|
||||
|
||||
} // namespace cuda
|
||||
|
||||
The function computes the round up to the smallest multiple of an integral or enumerator value :math:`ceil(\frac{value}{base\_multiple}) * base\_multiple`
|
||||
|
||||
**Parameters**
|
||||
|
||||
- ``value``: The value to be rounded up.
|
||||
- ``base_multiple``: The base multiple to which the value rounds up.
|
||||
|
||||
**Return value**
|
||||
|
||||
``value`` rounded up to the smallest multiple of ``base_multiple`` greater than or equal to ``value``. If ``value`` is already a multiple of ``base_multiple``, return ``value``.
|
||||
|
||||
.. note::
|
||||
|
||||
The result can overflow if ``ceil(value / base_multiple) * base_multiple`` exceeds the maximum value of the common type of ``value`` and ``base_multiple``. The condition is checked in debug mode.
|
||||
|
||||
**Constraints**
|
||||
|
||||
- ``T`` and ``U`` are integer types or enumerators.
|
||||
|
||||
**Preconditions**
|
||||
|
||||
- ``value >= 0``
|
||||
- ``base_multiple > 0``
|
||||
|
||||
**Performance considerations**
|
||||
|
||||
- The function performs a ceiling division (``cuda::ceil_div()``) followed by a multiplication
|
||||
|
||||
Example
|
||||
-------
|
||||
|
||||
.. code:: cuda
|
||||
|
||||
#include <cuda/cmath>
|
||||
#include <cstdio>
|
||||
|
||||
__global__ void round_up_kernel() {
|
||||
int value = 7;
|
||||
unsigned multiple = 3;
|
||||
printf("%d\n", cuda::round_up(value, multiple)); // print "9"
|
||||
}
|
||||
|
||||
int main() {
|
||||
round_up_kernel<<<1, 1>>>();
|
||||
cudaDeviceSynchronize();
|
||||
return 0;
|
||||
}
|
||||
|
||||
`See it on Godbolt 🔗 <https://godbolt.org/z/WacYfxsTT>`__
|
||||
68
cccl_upstream/docs/libcudacxx/extended_api/math/sincos.rst
Normal file
68
cccl_upstream/docs/libcudacxx/extended_api/math/sincos.rst
Normal file
@@ -0,0 +1,68 @@
|
||||
.. _libcudacxx-extended-api-math-sincos:
|
||||
|
||||
``cuda::sincos``
|
||||
====================================
|
||||
|
||||
Defined in the ``<cuda/cmath>`` header.
|
||||
|
||||
.. code:: cuda
|
||||
|
||||
namespace cuda {
|
||||
|
||||
template <class T>
|
||||
struct sincos_result
|
||||
{
|
||||
T sin;
|
||||
T cos;
|
||||
};
|
||||
|
||||
template </*floating-point-type*/ T>
|
||||
[[nodiscard]] __host__ __device__
|
||||
sincos_result<T> sincos(T value) noexcept; // (1)
|
||||
|
||||
template <class Integral>
|
||||
[[nodiscard]] __host__ __device__
|
||||
sincos_result<double> sincos(Integral value) noexcept; // (2)
|
||||
|
||||
} // namespace cuda
|
||||
|
||||
Computes :math:`\sin value` and :math:`\cos value` at the same time using more efficient algorithms than if operations were computed separately.
|
||||
|
||||
**Parameters**
|
||||
|
||||
- ``value``: The input value.
|
||||
|
||||
**Return value**
|
||||
|
||||
- ``cuda::sincos_result`` object with both values set to ``NaN`` if the input value is :math:`\pm\infty` or ``NaN`` and to results of :math:`\sin value` and :math:`\cos value` otherwise. (1)
|
||||
- if ``T`` is an integral type, the input value is treated as ``double``. (2)
|
||||
|
||||
**Constraints**
|
||||
|
||||
- ``T`` is an arithmetic type.
|
||||
|
||||
**Performance considerations**
|
||||
|
||||
- If available, the functionality is implemented by compiler builtins, otherwise fallbacks to ``cuda::std::sin(value)`` and ``cuda::std::cos(value)``.
|
||||
|
||||
Example
|
||||
-------
|
||||
|
||||
.. code:: cuda
|
||||
|
||||
#include <cuda/cmath>
|
||||
#include <cuda/std/cassert>
|
||||
|
||||
__global__ void sincos_kernel() {
|
||||
auto [sin_pi, cos_pi] = cuda::sincos(0.f);
|
||||
assert(sin_pi == 0.f);
|
||||
assert(cos_pi == 1.f);
|
||||
}
|
||||
|
||||
int main() {
|
||||
sincos_kernel<<<1, 1>>>();
|
||||
cudaDeviceSynchronize();
|
||||
return 0;
|
||||
}
|
||||
|
||||
`See it on Godbolt 🔗 <https://godbolt.org/z/99PP9s1z6>`__
|
||||
56
cccl_upstream/docs/libcudacxx/extended_api/math/uabs.rst
Normal file
56
cccl_upstream/docs/libcudacxx/extended_api/math/uabs.rst
Normal file
@@ -0,0 +1,56 @@
|
||||
.. _libcudacxx-extended-api-math-uabs:
|
||||
|
||||
``cuda::uabs``
|
||||
====================================
|
||||
|
||||
Defined in the ``<cuda/cmath>`` header.
|
||||
|
||||
.. code:: cuda
|
||||
|
||||
namespace cuda {
|
||||
|
||||
template <typename T>
|
||||
[[nodiscard]] __host__ __device__ constexpr
|
||||
cuda::std::make_unsigned_t<T> uabs(T value) noexcept;
|
||||
|
||||
} // namespace cuda
|
||||
|
||||
The function computes the absolute value of the input value. The result is returned as an unsigned integer type of the same size as the input value. In comparison to the standard ``abs`` function, the ``uabs`` eliminates the undefined behaviour when a signed ``T_MIN`` is passed as an input.
|
||||
|
||||
**Parameters**
|
||||
|
||||
- ``value``: The input value.
|
||||
|
||||
**Return value**
|
||||
|
||||
- The unsigned absolute value of the input value.
|
||||
|
||||
**Constraints**
|
||||
|
||||
- ``T`` is an integer type.
|
||||
|
||||
Example
|
||||
-------
|
||||
|
||||
.. code:: cuda
|
||||
|
||||
#include <cuda/cmath>
|
||||
#include <cuda/std/cassert>
|
||||
#include <cuda/std/limits>
|
||||
|
||||
__global__ void uabs_kernel() {
|
||||
using cuda::std::numeric_limits;
|
||||
|
||||
assert(cuda::uabs(20) == 20u);
|
||||
assert(cuda::uabs(-32) == 32u);
|
||||
assert(cuda::uabs(numeric_limits<int>::max()) == static_cast<unsigned>(numeric_limits<int>::max()));
|
||||
assert(cuda::uabs(numeric_limits<int>::min()) == static_cast<unsigned>(numeric_limits<int>::max()) + 1);
|
||||
}
|
||||
|
||||
int main() {
|
||||
uabs_kernel<<<1, 1>>>();
|
||||
cudaDeviceSynchronize();
|
||||
return 0;
|
||||
}
|
||||
|
||||
`See it on Godbolt 🔗 <https://godbolt.org/z/KEoYfq53G>`__
|
||||
Reference in New Issue
Block a user