Skip to content

Commit 022527c

Browse files
authored
Fix Randen and PCG on Big Endian platforms (#1031)
1 parent cc413f8 commit 022527c

File tree

3 files changed

+29
-1
lines changed

3 files changed

+29
-1
lines changed

absl/random/internal/explicit_seed_seq.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ class ExplicitSeedSeq {
7474
template <typename OutIterator>
7575
void generate(OutIterator begin, OutIterator end) {
7676
for (size_t index = 0; begin != end; begin++) {
77-
*begin = state_.empty() ? 0 : little_endian::FromHost32(state_[index++]);
77+
*begin = state_.empty() ? 0 : state_[index++];
7878
if (index >= state_.size()) {
7979
index = 0;
8080
}

absl/random/internal/randen_engine.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,13 @@ class alignas(16) randen_engine {
121121
const size_t requested_entropy = (entropy_size == 0) ? 8u : entropy_size;
122122
std::fill(std::begin(buffer) + requested_entropy, std::end(buffer), 0);
123123
seq.generate(std::begin(buffer), std::begin(buffer) + requested_entropy);
124+
#ifdef ABSL_IS_BIG_ENDIAN
125+
// Randen expects the seed buffer to be in Little Endian; reverse it on
126+
// Big Endian platforms.
127+
for (sequence_result_type& e : buffer) {
128+
e = absl::little_endian::FromHost(e);
129+
}
130+
#endif
124131
// The Randen paper suggests preferentially initializing even-numbered
125132
// 128-bit vectors of the randen state (there are 16 such vectors).
126133
// The seed data is merged into the state offset by 128-bits, which

absl/random/internal/randen_slow.cc

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -395,6 +395,23 @@ inline ABSL_RANDOM_INTERNAL_ATTRIBUTE_ALWAYS_INLINE void Permute(
395395
}
396396
}
397397

398+
// Enables native loads in the round loop by pre-swapping.
399+
inline ABSL_RANDOM_INTERNAL_ATTRIBUTE_ALWAYS_INLINE void SwapEndian(
400+
absl::uint128* state) {
401+
#ifdef ABSL_IS_BIG_ENDIAN
402+
for (uint32_t block = 0; block < RandenTraits::kFeistelBlocks; ++block) {
403+
uint64_t new_lo = absl::little_endian::ToHost64(
404+
static_cast<uint64_t>(state[block] >> 64));
405+
uint64_t new_hi = absl::little_endian::ToHost64(
406+
static_cast<uint64_t>((state[block] << 64) >> 64));
407+
state[block] = (static_cast<absl::uint128>(new_hi) << 64) | new_lo;
408+
}
409+
#else
410+
// Avoid warning about unused variable.
411+
(void)state;
412+
#endif
413+
}
414+
398415
} // namespace
399416

400417
namespace absl {
@@ -439,8 +456,12 @@ void RandenSlow::Generate(const void* keys_void, void* state_void) {
439456

440457
const absl::uint128 prev_inner = state[0];
441458

459+
SwapEndian(state);
460+
442461
Permute(state, keys);
443462

463+
SwapEndian(state);
464+
444465
// Ensure backtracking resistance.
445466
*state ^= prev_inner;
446467
}

0 commit comments

Comments
 (0)