Add a test to verify bit casting between signed and unsigned int128 works as expected

PiperOrigin-RevId: 684941948
Change-Id: I78a7ae6f4ec8f29e5bed414016eadf2ec95167a4
diff --git a/absl/numeric/int128_test.cc b/absl/numeric/int128_test.cc
index 3f16e05..0b59af8 100644
--- a/absl/numeric/int128_test.cc
+++ b/absl/numeric/int128_test.cc
@@ -22,6 +22,7 @@
 #include <vector>
 
 #include "gtest/gtest.h"
+#include "absl/base/casts.h"
 #include "absl/base/internal/cycleclock.h"
 #include "absl/hash/hash_testing.h"
 #include "absl/meta/type_traits.h"
@@ -1282,4 +1283,50 @@
   EXPECT_EQ(absl::Int128Max(), std::numeric_limits<absl::int128>::max());
 }
 
+TEST(Int128, BitCastable) {
+  // NOTE: This test is not intended to be an example that demonstrate usages of
+  // `static_cast` and `std::bit_cast`, rather it is here simply to verify
+  // behavior. When deciding whether you should use `static_cast` or
+  // `std::bit_cast` when converting between `absl::int128` and `absl::uint128`,
+  // use your best judgement. As a rule of thumb, use the same cast that you
+  // would use when converting between the signed and unsigned counterparts of a
+  // builtin integral type.
+
+  // Verify bit casting between signed and unsigned works with regards to two's
+  // complement. This verifies we exhibit the same behavior as a theoretical
+  // builtin int128_t and uint128_t in C++20 onwards.
+  EXPECT_EQ(absl::bit_cast<absl::uint128>(absl::int128(-1)),
+            std::numeric_limits<absl::uint128>::max());
+  EXPECT_EQ(
+      absl::bit_cast<absl::int128>(std::numeric_limits<absl::uint128>::max()),
+      absl::int128(-1));
+  EXPECT_EQ(
+      absl::bit_cast<absl::uint128>(std::numeric_limits<absl::int128>::min()),
+      absl::uint128(1) << 127);
+  EXPECT_EQ(absl::bit_cast<absl::int128>(absl::uint128(1) << 127),
+            std::numeric_limits<absl::int128>::min());
+  EXPECT_EQ(
+      absl::bit_cast<absl::uint128>(std::numeric_limits<absl::int128>::max()),
+      (absl::uint128(1) << 127) - 1);
+  EXPECT_EQ(absl::bit_cast<absl::int128>((absl::uint128(1) << 127) - 1),
+            std::numeric_limits<absl::int128>::max());
+
+  // Also verify static casting has the same behavior as bit casting.
+  EXPECT_EQ(static_cast<absl::uint128>(absl::int128(-1)),
+            std::numeric_limits<absl::uint128>::max());
+  EXPECT_EQ(
+      static_cast<absl::int128>(std::numeric_limits<absl::uint128>::max()),
+      absl::int128(-1));
+  EXPECT_EQ(
+      static_cast<absl::uint128>(std::numeric_limits<absl::int128>::min()),
+      absl::uint128(1) << 127);
+  EXPECT_EQ(static_cast<absl::int128>(absl::uint128(1) << 127),
+            std::numeric_limits<absl::int128>::min());
+  EXPECT_EQ(
+      static_cast<absl::uint128>(std::numeric_limits<absl::int128>::max()),
+      (absl::uint128(1) << 127) - 1);
+  EXPECT_EQ(static_cast<absl::int128>((absl::uint128(1) << 127) - 1),
+            std::numeric_limits<absl::int128>::max());
+}
+
 }  // namespace