Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions doc/modules/ROOT/pages/int128_t.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -101,15 +101,15 @@ struct int128_t
constexpr int128_t(const SignedInteger v) noexcept;

template <BOOST_INT128_UNSIGNED_INTEGER_CONCEPT UnsignedInteger>
constexpr int128_t(const UnsignedInteger v) noexcept;
explicit constexpr int128_t(const UnsignedInteger v) noexcept;

#ifdef BOOST_INT128_HAS_INT128

// Typically a typedef from __int128
constexpr int128_t(const detail::builtin_i128 v) noexcept;

// Typically a typedef unsigned __int128
constexpr int128_t(const detail::builtin_u128 v) noexcept;
explicit constexpr int128_t(const detail::builtin_u128 v) noexcept;

#endif // BOOST_INT128_HAS_INT128
};
Expand Down
4 changes: 2 additions & 2 deletions doc/modules/ROOT/pages/uint128_t.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -137,15 +137,15 @@ struct uint128_t
constexpr uint128_t(const std::uint64_t hi, const std::uint64_t lo) noexcept;

template <BOOST_INT128_SIGNED_INTEGER_CONCEPT SignedInteger>
constexpr uint128_t(const SignedInteger v) noexcept;
explicit constexpr uint128_t(const SignedInteger v) noexcept;

template <BOOST_INT128_UNSIGNED_INTEGER_CONCEPT UnsignedInteger>
constexpr uint128_t(const UnsignedInteger v) noexcept;

#ifdef BOOST_INT128_HAS_INT128

// Typically a typedef from __int128
constexpr uint128_t(const detail::builtin_i128 v) noexcept;
explicit constexpr uint128_t(const detail::builtin_i128 v) noexcept;

// Typically a typedef unsigned __int128
constexpr uint128_t(const detail::builtin_u128 v) noexcept;
Expand Down
248 changes: 232 additions & 16 deletions include/boost/int128/detail/conversions.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -42,87 +42,303 @@ constexpr uint128_t::uint128_t(const int128_t& v) noexcept : high {static_cast<s
// Comparison Operators
//=====================================

#ifdef _MSC_VER
#pragma warning(push)
#pragma warning(disable: 4127)
#endif

template <typename T, typename U, std::enable_if_t<detail::is_valid_overload_v<T> && detail::is_valid_overload_v<U> && !std::is_same<T, U>::value, bool> = true>
constexpr bool operator==(T, U) noexcept
constexpr bool operator==(const T lhs, const U rhs) noexcept
{
#ifndef BOOST_INT128_ALLOW_SIGN_COMPARE

static_assert(std::is_same<T, U>::value, "Sign Compare Error, cast one type to the other for this operation");
static_cast<void>(lhs);
static_cast<void>(rhs);
return true;

#else

BOOST_INT128_IF_CONSTEXPR (std::is_same<T, int128_t>::value)
{
if (lhs < T{0})
{
return false;
}

return static_cast<uint128_t>(lhs) == rhs;
}
else
{
if (rhs < T{0})
{
return false;
}

return lhs == static_cast<uint128_t>(rhs);
}

#endif
}

template <typename T, typename U, std::enable_if_t<detail::is_valid_overload_v<T> && detail::is_valid_overload_v<U> && !std::is_same<T, U>::value, bool> = true>
constexpr bool operator!=(T, U) noexcept
constexpr bool operator!=(const T lhs, const U rhs) noexcept
{
#ifndef BOOST_INT128_ALLOW_SIGN_COMPARE

static_assert(std::is_same<T, U>::value, "Sign Compare Error, cast one type to the other for this operation");
static_cast<void>(lhs);
static_cast<void>(rhs);
return true;

#else

BOOST_INT128_IF_CONSTEXPR (std::is_same<T, int128_t>::value)
{
if (lhs < T{0})
{
return true;
}

return static_cast<uint128_t>(lhs) != rhs;
}
else
{
if (rhs < T{0})
{
return true;
}

return lhs != static_cast<uint128_t>(rhs);
}

#endif
}

template <typename T, typename U, std::enable_if_t<detail::is_valid_overload_v<T> && detail::is_valid_overload_v<U> && !std::is_same<T, U>::value, bool> = true>
constexpr bool operator<(T, U) noexcept
constexpr bool operator<(const T lhs, const U rhs) noexcept
{
#ifndef BOOST_INT128_ALLOW_SIGN_COMPARE

static_assert(std::is_same<T, U>::value, "Sign Compare Error, cast one type to the other for this operation");
static_cast<void>(lhs);
static_cast<void>(rhs);
return true;

#else

BOOST_INT128_IF_CONSTEXPR (std::is_same<T, int128_t>::value)
{
if (lhs < T{0})
{
return true;
}

return static_cast<uint128_t>(lhs) < rhs;
}
else
{
if (rhs < T{0})
{
return false;
}

return lhs < static_cast<uint128_t>(rhs);
}

#endif
}

template <typename T, typename U, std::enable_if_t<detail::is_valid_overload_v<T> && detail::is_valid_overload_v<U> && !std::is_same<T, U>::value, bool> = true>
constexpr bool operator<=(T, U) noexcept
constexpr bool operator<=(const T lhs, const U rhs) noexcept
{
#ifndef BOOST_INT128_ALLOW_SIGN_COMPARE

static_assert(std::is_same<T, U>::value, "Sign Compare Error, cast one type to the other for this operation");
static_cast<void>(lhs);
static_cast<void>(rhs);
return true;

#else

BOOST_INT128_IF_CONSTEXPR (std::is_same<T, int128_t>::value)
{
if (lhs < T{0})
{
return true;
}

return static_cast<uint128_t>(lhs) <= rhs;
}
else
{
if (rhs < T{0})
{
return false;
}

return lhs <= static_cast<uint128_t>(rhs);
}

#endif
}

template <typename T, typename U, std::enable_if_t<detail::is_valid_overload_v<T> && detail::is_valid_overload_v<U> && !std::is_same<T, U>::value, bool> = true>
constexpr bool operator>(T, U) noexcept
constexpr bool operator>(const T lhs, const U rhs) noexcept
{
#ifndef BOOST_INT128_ALLOW_SIGN_COMPARE

static_assert(std::is_same<T, U>::value, "Sign Compare Error, cast one type to the other for this operation");
static_cast<void>(lhs);
static_cast<void>(rhs);
return true;

#else

BOOST_INT128_IF_CONSTEXPR (std::is_same<T, int128_t>::value)
{
if (lhs < T{0})
{
return false;
}

return static_cast<uint128_t>(lhs) > rhs;
}
else
{
if (rhs < T{0})
{
return true;
}

return lhs > static_cast<uint128_t>(rhs);
}

#endif
}

template <typename T, typename U, std::enable_if_t<detail::is_valid_overload_v<T> && detail::is_valid_overload_v<U> && !std::is_same<T, U>::value, bool> = true>
constexpr bool operator>=(T, U) noexcept
constexpr bool operator>=(const T lhs, const U rhs) noexcept
{
#ifndef BOOST_INT128_ALLOW_SIGN_COMPARE

static_assert(std::is_same<T, U>::value, "Sign Compare Error, cast one type to the other for this operation");
static_cast<void>(lhs);
static_cast<void>(rhs);
return true;

#else

BOOST_INT128_IF_CONSTEXPR (std::is_same<T, int128_t>::value)
{
if (lhs < T{0})
{
return false;
}

return static_cast<uint128_t>(lhs) >= rhs;
}
else
{
if (rhs < T{0})
{
return true;
}

return lhs >= static_cast<uint128_t>(rhs);
}

#endif
}

//=====================================
// Arithmetic Operators
//=====================================

template <typename T, typename U, std::enable_if_t<detail::is_valid_overload_v<T> && detail::is_valid_overload_v<U> && !std::is_same<T, U>::value, bool> = true>
constexpr T operator+(T lhs, U) noexcept
constexpr uint128_t operator+(const T lhs, const U rhs) noexcept
{
#ifndef BOOST_INT128_ALLOW_SIGN_CONVERSION

static_assert(std::is_same<T, U>::value, "Sign Conversion Error, cast one type to the other for this operation");
return lhs;
static_cast<void>(rhs);
return static_cast<uint128_t>(lhs);

#else

return static_cast<uint128_t>(lhs) + static_cast<uint128_t>(rhs);

#endif
}

template <typename T, typename U, std::enable_if_t<detail::is_valid_overload_v<T> && detail::is_valid_overload_v<U> && !std::is_same<T, U>::value, bool> = true>
constexpr T operator-(T lhs, U) noexcept
constexpr uint128_t operator-(const T lhs, const U rhs) noexcept
{
#ifndef BOOST_INT128_ALLOW_SIGN_CONVERSION

static_assert(std::is_same<T, U>::value, "Sign Conversion Error, cast one type to the other for this operation");
return lhs;
static_cast<void>(rhs);
return static_cast<uint128_t>(lhs);

#else

return static_cast<uint128_t>(lhs) - static_cast<uint128_t>(rhs);

#endif
}

template <typename T, typename U, std::enable_if_t<detail::is_valid_overload_v<T> && detail::is_valid_overload_v<U> && !std::is_same<T, U>::value, bool> = true>
constexpr T operator*(T lhs, U) noexcept
constexpr uint128_t operator*(const T lhs, const U rhs) noexcept
{
#ifndef BOOST_INT128_ALLOW_SIGN_CONVERSION

static_assert(std::is_same<T, U>::value, "Sign Conversion Error, cast one type to the other for this operation");
return lhs;
static_cast<void>(rhs);
return static_cast<uint128_t>(lhs);

#else

return static_cast<uint128_t>(lhs) * static_cast<uint128_t>(rhs);

#endif
}

template <typename T, typename U, std::enable_if_t<detail::is_valid_overload_v<T> && detail::is_valid_overload_v<U> && !std::is_same<T, U>::value, bool> = true>
constexpr T operator/(T lhs, U) noexcept
constexpr uint128_t operator/(const T lhs, const U rhs) noexcept
{
#ifndef BOOST_INT128_ALLOW_SIGN_CONVERSION

static_assert(std::is_same<T, U>::value, "Sign Conversion Error, cast one type to the other for this operation");
return lhs;
static_cast<void>(rhs);
return static_cast<uint128_t>(lhs);

#else

return static_cast<uint128_t>(lhs) / static_cast<uint128_t>(rhs);

#endif
}

template <typename T, typename U, std::enable_if_t<detail::is_valid_overload_v<T> && detail::is_valid_overload_v<U> && !std::is_same<T, U>::value, bool> = true>
constexpr T operator%(T lhs, U) noexcept
constexpr uint128_t operator%(const T lhs, const U rhs) noexcept
{
#ifndef BOOST_INT128_ALLOW_SIGN_CONVERSION

static_assert(std::is_same<T, U>::value, "Sign Conversion Error, cast one type to the other for this operation");
return lhs;
static_cast<void>(rhs);
return static_cast<uint128_t>(lhs);

#else

return static_cast<uint128_t>(lhs) % static_cast<uint128_t>(rhs);

#endif
}

#ifdef _MSC_VER
#pragma warning(pop)
#endif

} // namespace int128
} // namespace boost

Expand Down
10 changes: 5 additions & 5 deletions include/boost/int128/detail/int128_imp.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -55,8 +55,8 @@ int128_t
constexpr int128_t& operator=(const int128_t&) noexcept = default;
constexpr int128_t& operator=(int128_t&&) noexcept = default;

// Requires conversion file to be implemented
constexpr int128_t(const uint128_t& v) noexcept;
// Requires a conversion file to be implemented
explicit constexpr int128_t(const uint128_t& v) noexcept;

// Construct from integral types
#if BOOST_INT128_ENDIAN_LITTLE_BYTE
Expand All @@ -67,12 +67,12 @@ int128_t
constexpr int128_t(const SignedInteger v) noexcept : low {static_cast<std::uint64_t>(v)}, high {v < 0 ? -1 : 0} {}

template <BOOST_INT128_DEFAULTED_UNSIGNED_INTEGER_CONCEPT>
constexpr int128_t(const UnsignedInteger v) noexcept : low {static_cast<std::uint64_t>(v)}, high {} {}
explicit constexpr int128_t(const UnsignedInteger v) noexcept : low {static_cast<std::uint64_t>(v)}, high {} {}

#if defined(BOOST_INT128_HAS_INT128) || defined(BOOST_INT128_HAS_MSVC_INT128)

BOOST_INT128_BUILTIN_CONSTEXPR int128_t(const detail::builtin_i128 v) noexcept : low {static_cast<std::uint64_t>(v & static_cast<detail::builtin_i128>(detail::low_word_mask))}, high {static_cast<std::int64_t>(v >> static_cast<detail::builtin_i128>(64U))} {}
BOOST_INT128_BUILTIN_CONSTEXPR int128_t(const detail::builtin_u128 v) noexcept : low {static_cast<std::uint64_t>(v & static_cast<detail::builtin_u128>(detail::low_word_mask))}, high {static_cast<std::int64_t>(v >> static_cast<detail::builtin_u128>(64U))} {}
explicit BOOST_INT128_BUILTIN_CONSTEXPR int128_t(const detail::builtin_u128 v) noexcept : low {static_cast<std::uint64_t>(v & static_cast<detail::builtin_u128>(detail::low_word_mask))}, high {static_cast<std::int64_t>(v >> static_cast<detail::builtin_u128>(64U))} {}

#endif // BOOST_INT128_HAS_INT128

Expand Down Expand Up @@ -1541,7 +1541,7 @@ constexpr int128_t operator^(const UnsignedInteger lhs, const int128_t rhs) noex
static_assert(detail::is_signed_integer_v<UnsignedInteger>, "Sign Conversion Error");
static_cast<void>(lhs);
static_cast<void>(rhs);
return true;
return int128_t{};

#endif
}
Expand Down
Loading
Loading