4#include "native/config.h"
11namespace native::detail::x86_adx {
13 constexpr std::uint8_t add(std::uint8_t carry, U a, U b, U * result)
noexcept {
14 auto first =
static_cast<U
>(a + b);
15 auto overflow = first < a;
16 auto sum =
static_cast<U
>(first + (carry != 0));
18 return static_cast<std::uint8_t
>(overflow || sum < first);
21 template<isa<x86> Arch>
requires(Arch.has(x86_feature::adx))
23 std::uint8_t addcarryx(std::uint8_t carry, std::uint32_t a, std::uint32_t b, std::uint32_t * result) noexcept {
24 return _addcarryx_u32(carry, a, b, result);
27 template<isa<x86> Arch>
requires(Arch.has(x86_feature::adx))
29 std::uint8_t addcarryx(std::uint8_t carry, std::uint64_t a, std::uint64_t b, std::uint64_t * result) noexcept {
31 unsigned long long sum;
32 auto next = _addcarryx_u64(carry, a, b, &sum);
37 template<isa<x86> Arch,
class... Args>
38 void addcarryx(Args...) =
delete;
53 template<isa<x86> Arch>
requires(Arch.has(x86_feature::adx))
56 std::uint8_t carry,
std::uint32_t a,
std::uint32_t b,
std::uint32_t * result) noexcept {
58 return detail::x86_adx::add(carry, a, b, result);
60 return detail::x86_adx::addcarryx<Arch>(carry, a, b, result);
65 template<isa<x86> Arch>
requires(Arch.has(x86_feature::adx))
68 std::uint8_t carry, std::uint64_t a, std::uint64_t b, std::uint64_t * result)
noexcept {
70 return detail::x86_adx::add(carry, a, b, result);
72 return detail::x86_adx::addcarryx<Arch>(carry, a, b, result);
77 template<isa<x86> Arch>
requires(!Arch.has(x86_feature::adx))
79 std::uint8_t carry, std::uint32_t a, std::uint32_t b, std::uint32_t * result)
noexcept {
80 return detail::x86_adx::add(carry, a, b, result);
84 template<isa<x86> Arch>
requires(!Arch.has(x86_feature::adx))
86 std::uint8_t carry, std::uint64_t a, std::uint64_t b, std::uint64_t * result)
noexcept {
87 return detail::x86_adx::add(carry, a, b, result);
Compiler attributes for host code, with shader-safe shared modifiers.
#define native_inline
inline [[always_inline]]
#define native_nodiscard
C++17 [[nodiscard]].
#define native_target(x)
this indicates a required feature set for the current multiversioned function.
constexpr std::uint8_t addcarryx(std::uint8_t carry, std::uint32_t a, std::uint32_t b, std::uint32_t *result) noexcept
Add 32-bit operands with carry, writing the modular result.
Architecture-tagged vectors, register packs and supporting value types. Native arithmetic follows its...
Standard-library adaptations documented here for SIMD value types.