//===----------------------------------------------------------------------===// // // Part of libcu++, the C++ Standard Library for your entire system, // under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // SPDX-FileCopyrightText: Copyright (c) 2025 NVIDIA CORPORATION & AFFILIATES. // //===----------------------------------------------------------------------===// // MIT License // // Modifications Copyright (C) 2025 Advanced Micro Devices, Inc. All rights reserved. // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in all // copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE // SOFTWARE. #ifndef _LIBCUDACXX___BIT_BYTESWAP_H #define _LIBCUDACXX___BIT_BYTESWAP_H #include #if defined(_CCCL_IMPLICIT_SYSTEM_HEADER_GCC) # pragma GCC system_header #elif defined(_CCCL_IMPLICIT_SYSTEM_HEADER_CLANG) # pragma clang system_header #elif defined(_CCCL_IMPLICIT_SYSTEM_HEADER_MSVC) # pragma system_header #endif // no system header //#include #include #include #include #include #include #include #include #if _CCCL_COMPILER(MSVC) # include #endif // _CCCL_COMPILER(MSVC) _LIBCUDACXX_BEGIN_NAMESPACE_STD template _CCCL_NODISCARD _LIBCUDACXX_HIDE_FROM_ABI constexpr _Tp __byteswap_impl(_Tp __val) noexcept; template _CCCL_NODISCARD _LIBCUDACXX_HIDE_FROM_ABI constexpr _Full __byteswap_impl_recursive(_Full __val) noexcept { using _Half = __make_nbit_uint_t::digits / 2>; constexpr auto __shift = numeric_limits<_Half>::digits; if constexpr (sizeof(_Full) > 2) { return static_cast<_Full>(_CUDA_VSTD::__byteswap_impl(static_cast<_Half>(__val >> __shift))) | (static_cast<_Full>(_CUDA_VSTD::__byteswap_impl(static_cast<_Half>(__val))) << __shift); } else { return static_cast<_Full>((__val << __shift) | (__val >> __shift)); } } template _CCCL_NODISCARD _CCCL_HIDE_FROM_ABI _CCCL_DEVICE _Tp __byteswap_impl_device(_Tp __val) noexcept { #if __cccl_ptx_isa >= 200 if constexpr (sizeof(_Tp) == sizeof(uint16_t)) { return static_cast(_CUDA_VPTX::prmt(static_cast(__val), uint32_t{0}, uint32_t{0x3201})); } else if constexpr (sizeof(_Tp) == sizeof(uint32_t)) { return _CUDA_VPTX::prmt(__val, uint32_t{0}, uint32_t{0x0123}); } else if constexpr (sizeof(_Tp) == sizeof(uint64_t)) { const auto __hi = static_cast(__val >> 32); const auto __lo = static_cast(__val); const auto __new_lo = _CUDA_VPTX::prmt(__hi, uint32_t{0}, uint32_t{0x0123}); const auto __new_hi = _CUDA_VPTX::prmt(__lo, uint32_t{0}, uint32_t{0x0123}); return static_cast(__new_hi) << 32 | static_cast(__new_lo); } else #endif // __cccl_ptx_isa >= 200 { return _CUDA_VSTD::__byteswap_impl_recursive(__val); } } template _CCCL_NODISCARD _LIBCUDACXX_HIDE_FROM_ABI constexpr _Tp __byteswap_impl(_Tp __val) noexcept { constexpr auto __shift = numeric_limits::digits; _Tp __result{}; _CCCL_PRAGMA_UNROLL_FULL() for (size_t __i = 0; __i < sizeof(_Tp); ++__i) { __result <<= __shift; __result |= _Tp(__val & _Tp(numeric_limits::max())); __val >>= __shift; } return __result; } _CCCL_NODISCARD _LIBCUDACXX_HIDE_FROM_ABI constexpr uint16_t __byteswap_impl(uint16_t __val) noexcept { #if defined(_CCCL_BUILTIN_BSWAP16) return _CCCL_BUILTIN_BSWAP16(__val); #else // ^^^ _CCCL_BUILTIN_BSWAP16 ^^^ / vvv !_CCCL_BUILTIN_BSWAP16 vvv if (!_CUDA_VSTD::__cccl_default_is_constant_evaluated()) { # if _CCCL_COMPILER(MSVC) NV_IF_TARGET_LIBHIPCXX(NV_IS_HOST_LIBHIPCXX, return ::_byteswap_ushort(__val);) # endif // _CCCL_COMPILER(MSVC) NV_IF_TARGET_LIBHIPCXX(NV_IS_DEVICE_LIBHIPCXX, return _CUDA_VSTD::__byteswap_impl_device(__val);) } return _CUDA_VSTD::__byteswap_impl_recursive(__val); #endif // !_CCCL_BUILTIN_BSWAP16 } _CCCL_NODISCARD _LIBCUDACXX_HIDE_FROM_ABI constexpr uint32_t __byteswap_impl(uint32_t __val) noexcept { #if defined(_CCCL_BUILTIN_BSWAP32) return _CCCL_BUILTIN_BSWAP32(__val); #else // ^^^ _CCCL_BUILTIN_BSWAP32 ^^^ / vvv !_CCCL_BUILTIN_BSWAP32 vvv if (!_CUDA_VSTD::__cccl_default_is_constant_evaluated()) { # if _CCCL_COMPILER(MSVC) NV_IF_TARGET_LIBHIPCXX(NV_IS_HOST_LIBHIPCXX, return ::_byteswap_ulong(__val);) # endif // _CCCL_COMPILER(MSVC) NV_IF_TARGET_LIBHIPCXX(NV_IS_DEVICE_LIBHIPCXX, return _CUDA_VSTD::__byteswap_impl_device(__val);) } return _CUDA_VSTD::__byteswap_impl_recursive(__val); #endif // !_CCCL_BUILTIN_BSWAP32 } _CCCL_NODISCARD _LIBCUDACXX_HIDE_FROM_ABI constexpr uint64_t __byteswap_impl(uint64_t __val) noexcept { #if defined(_CCCL_BUILTIN_BSWAP64) return _CCCL_BUILTIN_BSWAP64(__val); #else // ^^^ _CCCL_BUILTIN_BSWAP64 ^^^ / vvv !_CCCL_BUILTIN_BSWAP64 vvv if (!_CUDA_VSTD::__cccl_default_is_constant_evaluated()) { # if _CCCL_COMPILER(MSVC) NV_IF_TARGET_LIBHIPCXX(NV_IS_HOST_LIBHIPCXX, return ::_byteswap_uint64(__val);) # endif // _CCCL_COMPILER(MSVC) NV_IF_TARGET_LIBHIPCXX(NV_IS_DEVICE_LIBHIPCXX, return _CUDA_VSTD::__byteswap_impl_device(__val);) } return _CUDA_VSTD::__byteswap_impl_recursive(__val); #endif // !_CCCL_BUILTIN_BSWAP64 } #if _CCCL_HAS_INT128() _CCCL_NODISCARD _LIBCUDACXX_HIDE_FROM_ABI constexpr __uint128_t __byteswap_impl(__uint128_t __val) noexcept { # if defined(_CCCL_BUILTIN_BSWAP128) return _CCCL_BUILTIN_BSWAP128(__val); # else // ^^^ _CCCL_BUILTIN_BSWAP128 ^^^ / vvv !_CCCL_BUILTIN_BSWAP128 vvv return _CUDA_VSTD::__byteswap_impl_recursive(__val); # endif // !_CCCL_BUILTIN_BSWAP128 } #endif // _CCCL_HAS_INT128() _CCCL_TEMPLATE(class _Integer) _CCCL_REQUIRES(_CCCL_TRAIT(is_integral, _Integer)) _CCCL_NODISCARD _LIBCUDACXX_HIDE_FROM_ABI constexpr _Integer byteswap(_Integer __val) noexcept { if constexpr (sizeof(_Integer) > 1) { return static_cast<_Integer>(_CUDA_VSTD::__byteswap_impl(_CUDA_VSTD::__to_unsigned_like(__val))); } else { return __val; } } _LIBCUDACXX_END_NAMESPACE_STD #endif // _LIBCUDACXX___BIT_BYTESWAP_H