summaryrefslogtreecommitdiff
path: root/absl/random/internal/randen_slow.cc
diff options
context:
space:
mode:
Diffstat (limited to 'absl/random/internal/randen_slow.cc')
-rw-r--r--absl/random/internal/randen_slow.cc21
1 files changed, 21 insertions, 0 deletions
diff --git a/absl/random/internal/randen_slow.cc b/absl/random/internal/randen_slow.cc
index d5c9347b..9bfd2a40 100644
--- a/absl/random/internal/randen_slow.cc
+++ b/absl/random/internal/randen_slow.cc
@@ -395,6 +395,23 @@ inline ABSL_RANDOM_INTERNAL_ATTRIBUTE_ALWAYS_INLINE void Permute(
}
}
+// Enables native loads in the round loop by pre-swapping.
+inline ABSL_RANDOM_INTERNAL_ATTRIBUTE_ALWAYS_INLINE void SwapEndian(
+ absl::uint128* state) {
+#ifdef ABSL_IS_BIG_ENDIAN
+ for (uint32_t block = 0; block < RandenTraits::kFeistelBlocks; ++block) {
+ uint64_t new_lo = absl::little_endian::ToHost64(
+ static_cast<uint64_t>(state[block] >> 64));
+ uint64_t new_hi = absl::little_endian::ToHost64(
+ static_cast<uint64_t>((state[block] << 64) >> 64));
+ state[block] = (static_cast<absl::uint128>(new_hi) << 64) | new_lo;
+ }
+#else
+ // Avoid warning about unused variable.
+ (void)state;
+#endif
+}
+
} // namespace
namespace absl {
@@ -439,8 +456,12 @@ void RandenSlow::Generate(const void* keys_void, void* state_void) {
const absl::uint128 prev_inner = state[0];
+ SwapEndian(state);
+
Permute(state, keys);
+ SwapEndian(state);
+
// Ensure backtracking resistance.
*state ^= prev_inner;
}