Skip to content
Merged
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
19 changes: 19 additions & 0 deletions doc/modules/ROOT/pages/int128_t.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -264,6 +264,25 @@ constexpr bool operator!=(const int128_t lhs, const int128_t rhs) noexcept;
Returns if the `lhs` value is not equal to the `rhs` value without exception.
This operation is only defined for integers and is subject to mixed sign limitations discussed xref:int128_t.adoc#i128_operator_behavior[above].

=== Spaceship Operator (Requires pass:[C++20])

[source, c++]
----
constexpr std::strong_ordering operator<=>(const int128_t lhs, const int128_t rhs) noexcept;

template <BOOST_INT128_INTEGER_CONCEPT Integer>
constexpr std::strong_ordering operator<=>(const int128_t lhs, const Integer rhs) noexcept;

template <BOOST_INT128_INTEGER_CONCEPT Integer>
constexpr std::strong_ordering operator<=>(const Integer lhs, const int128_t rhs) noexcept;
----

Returns one of the following without exception:

- `std::strong_ordering::less` if `lhs < rhs`
- `std::strong_ordering::equivalent` if `lhs == rhs`
- `std::strong_ordering::greater` otherwise (implies `lhs > rhs`)

[#i128_bitwise_operators]
== Bitwise Operators

Expand Down
19 changes: 19 additions & 0 deletions doc/modules/ROOT/pages/uint128_t.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -303,6 +303,25 @@ constexpr bool operator!=(const uint128_t lhs, const uint128_t rhs) noexcept;
Returns if the `lhs` value is not equal to the `rhs` value without exception.
This operation is only defined for integers and is subject to mixed sign limitations discussed xref:uint128_t.adoc#u128_operator_behavior[above].

=== Spaceship Operator (Requires pass:[C++20])

[source, c++]
----
constexpr std::strong_ordering operator<=>(const uint128_t lhs, const uint128_t rhs) noexcept;

template <BOOST_INT128_INTEGER_CONCEPT Integer>
constexpr std::strong_ordering operator<=>(const uint128_t lhs, const Integer rhs) noexcept;

template <BOOST_INT128_INTEGER_CONCEPT Integer>
constexpr std::strong_ordering operator<=>(const Integer lhs, const uint128_t rhs) noexcept;
----

Returns one of the following without exception:

- `std::strong_ordering::less` if `lhs < rhs`
- `std::strong_ordering::equivalent` if `lhs == rhs`
- `std::strong_ordering::greater` otherwise (implies `lhs > rhs`)

[#u128_bitwise_operators]
== Bitwise Operators

Expand Down
7 changes: 7 additions & 0 deletions include/boost/int128/detail/config.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -278,4 +278,11 @@ using builtin_u128 = std::_Unsigned128;

#endif // Exceptions

#if defined(__cpp_impl_three_way_comparison) && __cpp_impl_three_way_comparison >= 201907L && __has_include(<compare>)
# define BOOST_INT128_HAS_SPACESHIP_OPERATOR
# ifndef BOOST_INT128_BUILD_MODULE
# include <compare>
# endif
#endif

#endif // BOOST_INT128_DETAIL_CONFIG_HPP
114 changes: 114 additions & 0 deletions include/boost/int128/detail/int128_imp.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -1100,6 +1100,120 @@ BOOST_INT128_BUILTIN_CONSTEXPR bool operator>=(const T, const int128_t) noexcept

#endif // BOOST_INT128_HAS_INT128

//=====================================
// Spaceship Operator
//=====================================

#ifdef BOOST_INT128_HAS_SPACESHIP_OPERATOR

BOOST_INT128_EXPORT constexpr std::strong_ordering operator<=>(const int128_t lhs, const int128_t rhs) noexcept
{
if (lhs < rhs)
{
return std::strong_ordering::less;
}
else if (lhs == rhs)
{
return std::strong_ordering::equivalent;
}
else
{
return std::strong_ordering::greater;
}
}

BOOST_INT128_EXPORT template <BOOST_INT128_DEFAULTED_SIGNED_INTEGER_CONCEPT>
constexpr std::strong_ordering operator<=>(const int128_t lhs, const SignedInteger rhs) noexcept
{
if (lhs < rhs)
{
return std::strong_ordering::less;
}
else if (lhs == rhs)
{
return std::strong_ordering::equivalent;
}
else
{
return std::strong_ordering::greater;
}
}

BOOST_INT128_EXPORT template <BOOST_INT128_DEFAULTED_SIGNED_INTEGER_CONCEPT>
constexpr std::strong_ordering operator<=>(const SignedInteger lhs, const int128_t rhs) noexcept
{
if (lhs < rhs)
{
return std::strong_ordering::less;
}
else if (lhs == rhs)
{
return std::strong_ordering::equivalent;
}
else
{
return std::strong_ordering::greater;
}
}

BOOST_INT128_EXPORT template <BOOST_INT128_DEFAULTED_UNSIGNED_INTEGER_CONCEPT>
constexpr std::strong_ordering operator<=>(const int128_t lhs, const UnsignedInteger rhs) noexcept
{
#ifdef BOOST_INT128_ALLOW_SIGN_COMPARE

if (lhs < rhs)
{
return std::strong_ordering::less;
}
else if (lhs == rhs)
{
return std::strong_ordering::equivalent;
}
else
{
return std::strong_ordering::greater;
}

#else

static_assert(detail::is_signed_integer_v<UnsignedInteger>, "Sign Compare Error");
static_cast<void>(lhs);
static_cast<void>(rhs);
return std::strong_ordering::less;

#endif
}

BOOST_INT128_EXPORT template <BOOST_INT128_DEFAULTED_UNSIGNED_INTEGER_CONCEPT>
constexpr std::strong_ordering operator<=>(const UnsignedInteger lhs, const int128_t rhs) noexcept
{
#ifdef BOOST_INT128_ALLOW_SIGN_COMPARE

if (lhs < rhs)
{
return std::strong_ordering::less;
}
else if (lhs == rhs)
{
return std::strong_ordering::equivalent;
}
else
{
return std::strong_ordering::greater;
}

#else

static_assert(detail::is_signed_integer_v<UnsignedInteger>, "Sign Compare Error");
static_cast<void>(lhs);
static_cast<void>(rhs);
return std::strong_ordering::less;

#endif
}

#endif

//=====================================
// Not Operator
//=====================================
Expand Down
114 changes: 114 additions & 0 deletions include/boost/int128/detail/uint128_imp.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -1216,6 +1216,120 @@ BOOST_INT128_BUILTIN_CONSTEXPR bool operator>=(const T, const uint128_t) noexcep

#endif // BOOST_INT128_HAS_INT128

//=====================================
// Spaceship Operator
//=====================================

#ifdef BOOST_INT128_HAS_SPACESHIP_OPERATOR

BOOST_INT128_EXPORT constexpr std::strong_ordering operator<=>(const uint128_t lhs, const uint128_t rhs) noexcept
{
if (lhs < rhs)
{
return std::strong_ordering::less;
}
else if (lhs == rhs)
{
return std::strong_ordering::equivalent;
}
else
{
return std::strong_ordering::greater;
}
}

BOOST_INT128_EXPORT template <BOOST_INT128_DEFAULTED_UNSIGNED_INTEGER_CONCEPT>
constexpr std::strong_ordering operator<=>(const uint128_t lhs, const UnsignedInteger rhs) noexcept
{
if (lhs < rhs)
{
return std::strong_ordering::less;
}
else if (lhs == rhs)
{
return std::strong_ordering::equivalent;
}
else
{
return std::strong_ordering::greater;
}
}

BOOST_INT128_EXPORT template <BOOST_INT128_DEFAULTED_UNSIGNED_INTEGER_CONCEPT>
constexpr std::strong_ordering operator<=>(const UnsignedInteger lhs, const uint128_t rhs) noexcept
{
if (lhs < rhs)
{
return std::strong_ordering::less;
}
else if (lhs == rhs)
{
return std::strong_ordering::equivalent;
}
else
{
return std::strong_ordering::greater;
}
}

BOOST_INT128_EXPORT template <BOOST_INT128_DEFAULTED_SIGNED_INTEGER_CONCEPT>
constexpr std::strong_ordering operator<=>(const SignedInteger lhs, const uint128_t rhs) noexcept
{
#ifdef BOOST_INT128_ALLOW_SIGN_COMPARE

if (lhs < rhs)
{
return std::strong_ordering::less;
}
else if (lhs == rhs)
{
return std::strong_ordering::equivalent;
}
else
{
return std::strong_ordering::greater;
}

#else

static_assert(detail::is_unsigned_integer_v<SignedInteger>, "Sign Compare Error");
static_cast<void>(lhs);
static_cast<void>(rhs);
return std::strong_ordering::less;

#endif
}

BOOST_INT128_EXPORT template <BOOST_INT128_DEFAULTED_SIGNED_INTEGER_CONCEPT>
constexpr std::strong_ordering operator<=>(const uint128_t lhs, const SignedInteger rhs) noexcept
{
#ifdef BOOST_INT128_ALLOW_SIGN_COMPARE

if (lhs < rhs)
{
return std::strong_ordering::less;
}
else if (lhs == rhs)
{
return std::strong_ordering::equivalent;
}
else
{
return std::strong_ordering::greater;
}

#else

static_assert(detail::is_unsigned_integer_v<SignedInteger>, "Sign Compare Error");
static_cast<void>(lhs);
static_cast<void>(rhs);
return std::strong_ordering::less;

#endif
}

#endif

//=====================================
// Not Operator
//=====================================
Expand Down
1 change: 1 addition & 0 deletions module/int128.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ module;
#include <cassert>
#include <cerrno>
#include <cstddef>
#include <compare>

#if __has_include(<__msvc_int128.hpp>) && _MSVC_LANG >= 202002L

Expand Down
1 change: 1 addition & 0 deletions test/Jamfile
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,7 @@ run test_fmt_format.cpp ;
run test_div.cpp ;

run test_num_digits.cpp ;
run test_spaceship_operator.cpp ;

# Make sure we run the examples as well
run ../examples/construction.cpp ;
Expand Down
44 changes: 44 additions & 0 deletions test/test_spaceship_operator.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
// Copyright 2026 Matt Borland
// Distributed under the Boost Software License, Version 1.0.
// https://www.boost.org/LICENSE_1_0.txt

#include <boost/int128/int128.hpp>

#ifdef BOOST_INT128_HAS_SPACESHIP_OPERATOR

#include <boost/core/lightweight_test.hpp>

void test_u128()
{
constexpr boost::int128::uint128_t x {5U};
BOOST_TEST((x <=> 4U) == std::strong_ordering::greater);
BOOST_TEST((x <=> 5U) == std::strong_ordering::equivalent);
BOOST_TEST((x <=> 5U) == std::strong_ordering::equal);
BOOST_TEST((x <=> 6U) == std::strong_ordering::less);
}

void test_int128()
{
constexpr boost::int128::int128_t x {5};
BOOST_TEST((x <=> 4) == std::strong_ordering::greater);
BOOST_TEST((x <=> 5) == std::strong_ordering::equivalent);
BOOST_TEST((x <=> 5) == std::strong_ordering::equal);
BOOST_TEST((x <=> 6) == std::strong_ordering::less);
}

int main()
{
test_u128();
test_int128();

return boost::report_errors();
}

#else

int main()
{
return 0;
}

#endif