Skip to content

Commit

Permalink
Try to address #61, and also add a path for ICC
Browse files Browse the repository at this point in the history
  • Loading branch information
jk-jeon committed Apr 16, 2024
1 parent bbb24df commit 2998f97
Showing 1 changed file with 57 additions and 12 deletions.
69 changes: 57 additions & 12 deletions include/dragonbox/dragonbox.h
Original file line number Diff line number Diff line change
Expand Up @@ -198,6 +198,8 @@

#if defined(_MSC_VER)
#include <intrin.h>
#elif defined(__INTEL_COMPILER)
#include <immintrin.h>
#endif

namespace jkj {
Expand Down Expand Up @@ -618,24 +620,67 @@ namespace jkj {
// To suppress warning.
static_cast<void>(generic_impl);

JKJ_IF_CONSTEXPR(value_bits<stdr::uint_least64_t>::value > 64) {
generic_impl();
return *this;
}

JKJ_IF_CONSTEVAL {
generic_impl();
return *this;
}
#if JKJ_HAS_BUILTIN(__builtin_addcll)
static_assert(stdr::is_same<unsigned long long, stdr::uint_least64_t>::value &&
value_bits<stdr::uint_least64_t>::value == 64,
"");
unsigned long long carry{};
low_ = __builtin_addcll(low_, n, 0, &carry);
high_ = __builtin_addcll(high_, 0, carry, &carry);
#elif JKJ_HAS_BUILTIN(__builtin_ia32_addcarryx_u64)

// See https://github.com/fmtlib/fmt/pull/2985.
#if JKJ_HAS_BUILTIN(__builtin_addcll) && !defined(__ibmxl__)
JKJ_IF_CONSTEXPR(
stdr::is_same<stdr::uint_least64_t, unsigned long long>::value) {
unsigned long long carry{};
low_ = stdr::uint_least64_t(__builtin_addcll(low_, n, 0, &carry));
high_ = stdr::uint_least64_t(__builtin_addcll(high_, 0, carry, &carry));
return *this;
}
#endif
#if JKJ_HAS_BUILTIN(__builtin_addcl) && !defined(__ibmxl__)
JKJ_IF_CONSTEXPR(stdr::is_same<stdr::uint_least64_t, unsigned long>::value) {
unsigned long carry{};
low_ = stdr::uint_least64_t(
__builtin_addcl(static_cast<unsigned long>(low_),
static_cast<unsigned long>(n), 0, &carry));
high_ = stdr::uint_least64_t(
__builtin_addcl(static_cast<unsigned long>(high_), 0, carry, &carry));
return *this;
}
#endif
#if JKJ_HAS_BUILTIN(__builtin_addc) && !defined(__ibmxl__)
JKJ_IF_CONSTEXPR(stdr::is_same<stdr::uint_least64_t, unsigned int>::value) {
unsigned int carry{};
low_ = stdr::uint_least64_t(__builtin_addc(static_cast<unsigned int>(low_),
static_cast<unsigned int>(n), 0,
&carry));
high_ = stdr::uint_least64_t(
__builtin_addc(static_cast<unsigned int>(high_), 0, carry, &carry));
return *this;
}
#endif

#if JKJ_HAS_BUILTIN(__builtin_ia32_addcarry_u64)
// __builtin_ia32_addcarry_u64 is not documented, but it seems it takes unsigned
// long long arguments.
unsigned long long result{};
auto const carry = __builtin_ia32_addcarryx_u64(0, low_, n, &result);
low_ = result;
__builtin_ia32_addcarryx_u64(carry, high_, 0, &result);
high_ = result;
auto const carry = __builtin_ia32_addcarry_u64(0, low_, n, &result);
low_ = stdr::uint_least64_t(result);
__builtin_ia32_addcarry_u64(carry, high_, 0, &result);
high_ = stdr::uint_least64_t(result);
#elif defined(_MSC_VER) && defined(_M_X64)
// On MSVC, uint_least64_t and __int64 must be unsigned long long; see
// https://learn.microsoft.com/en-us/cpp/c-runtime-library/standard-types
// and https://learn.microsoft.com/en-us/cpp/cpp/int8-int16-int32-int64.
static_assert(stdr::is_same<unsigned long long, stdr::uint_least64_t>::value,
"");
auto const carry = _addcarry_u64(0, low_, n, &low_);
_addcarry_u64(carry, high_, 0, &high_);
#elif defined(__INTEL_COMPILER) && (defined(_M_X64) || defined(__x86_64))
static_assert(std::is_same<unsigned __int64, std::uint_least64_t>::value, "");
auto const carry = _addcarry_u64(0, low_, n, &low_);
_addcarry_u64(carry, high_, 0, &high_);
#else
Expand Down

0 comments on commit 2998f97

Please sign in to comment.