https://mooseframework.inl.gov
Public Member Functions | Private Member Functions | Static Private Member Functions | Private Attributes | List of all members
MooseRandomPerturbation Class Reference

Generates a keyed pseudo-random permutation of the integers [0, n) using a balanced Feistel network. More...

#include <MooseRandomPerturbation.h>

Public Member Functions

 MooseRandomPerturbation (uint64_t seed, unsigned int n, unsigned int rounds=8)
 Construct a permutation of [0, n) keyed by seed. More...
 
uint32_t permute (uint32_t x) const
 Map x to its permuted index in [0, n). More...
 
uint32_t invert (uint32_t y) const
 Recover the original index from a permuted value, i.e. More...
 

Private Member Functions

uint32_t permutePadded (uint32_t x) const
 Apply one full pass of the balanced Feistel network over the padded domain [0, 2^(2*half_bits)). More...
 
uint32_t invertPadded (uint32_t y) const
 Invert one full pass of the Feistel network by running rounds in reverse. More...
 
uint32_t roundFunction (uint32_t half, unsigned int round) const
 Keyed round function F(half, round) used in each Feistel step. More...
 

Static Private Member Functions

static unsigned int ceilLog2 (uint32_t n)
 Return the number of bits needed to represent values in [0, n-1], i.e. More...
 
static uint32_t mix32 (uint32_t x)
 Bijective 32-bit avalanche hash (finalizer from Murmur3 / degski hash). More...
 

Private Attributes

const uint32_t _k0
 Lower 32 bits of the seed, used as the first subkey in the round function. More...
 
const uint32_t _k1
 Upper 32 bits of the seed, used as the second subkey in the round function. More...
 
const unsigned int _n
 Size of the permutation domain [0, n) More...
 
const unsigned int _half_bits
 Number of bits in each Feistel half-block: ceil((ceil(log2(n)) + 1) / 2) More...
 
const uint32_t _half_mask
 Bitmask of width _half_bits, used to keep half-block arithmetic in range. More...
 
const unsigned int _rounds
 Number of Feistel rounds to apply per permute/invert call. More...
 

Detailed Description

Generates a keyed pseudo-random permutation of the integers [0, n) using a balanced Feistel network.

Given the same seed and n, the mapping is fully deterministic and bijective: every input in [0, n) maps to a unique output in [0, n). Different seeds produce statistically independent permutations.

Because n need not be a power of two, the Feistel network operates on a padded domain of size 2^(2*half_bits) >= n and uses cycle-walking: if the raw output falls outside [0, n) it is re-applied until a valid index is reached. This guarantees termination because the padded permutation is itself a bijection and n > 0 ensures at least one valid output exists.

The permutation is also invertible via invert(), which runs the Feistel rounds in reverse order.

Definition at line 31 of file MooseRandomPerturbation.h.

Constructor & Destructor Documentation

◆ MooseRandomPerturbation()

MooseRandomPerturbation::MooseRandomPerturbation ( uint64_t  seed,
unsigned int  n,
unsigned int  rounds = 8 
)

Construct a permutation of [0, n) keyed by seed.

Parameters
seed64-bit seed; split into two 32-bit subkeys for the round function.
nSize of the domain to permute; must be > 0.
roundsNumber of Feistel rounds. More rounds improve mixing at the cost of throughput; 8 is sufficient for sampling applications.

Definition at line 12 of file MooseRandomPerturbation.C.

13  : _k0(static_cast<uint32_t>(seed)),
14  _k1(static_cast<uint32_t>(seed >> 32)),
15  _n(n),
16  _half_bits((ceilLog2(n) + 1) / 2),
17  _half_mask((uint32_t(1) << _half_bits) - 1),
18  _rounds(rounds)
19 {
20  mooseAssert(_n > 0, "n must be > 0");
21  mooseAssert(_rounds > 0, "rounds must be greater than 0.");
22 }
const uint32_t _k0
Lower 32 bits of the seed, used as the first subkey in the round function.
const uint32_t _k1
Upper 32 bits of the seed, used as the second subkey in the round function.
const uint32_t _half_mask
Bitmask of width _half_bits, used to keep half-block arithmetic in range.
const unsigned int _half_bits
Number of bits in each Feistel half-block: ceil((ceil(log2(n)) + 1) / 2)
const unsigned int _rounds
Number of Feistel rounds to apply per permute/invert call.
static unsigned int ceilLog2(uint32_t n)
Return the number of bits needed to represent values in [0, n-1], i.e.
const unsigned int _n
Size of the permutation domain [0, n)

Member Function Documentation

◆ ceilLog2()

unsigned int MooseRandomPerturbation::ceilLog2 ( uint32_t  n)
staticprivate

Return the number of bits needed to represent values in [0, n-1], i.e.

ceil(log2(n)). Returns 0 for n == 1 (no bits needed to index a single element).

Parameters
nMust be > 0.

Definition at line 103 of file MooseRandomPerturbation.C.

104 {
105  mooseAssert(n > 0, "n must be > 0");
106 
107  unsigned int bits = 0;
108  uint32_t v = n - 1;
109  while (v > 0)
110  {
111  ++bits;
112  v >>= 1;
113  }
114  return bits;
115 }

◆ invert()

uint32_t MooseRandomPerturbation::invert ( uint32_t  y) const

Recover the original index from a permuted value, i.e.

invert(permute(x)) == x.

Runs the Feistel rounds in reverse order and cycle-walks back into [0, n).

Parameters
yPermuted index; must satisfy y < n.
Returns
The unique x in [0, n) such that permute(x) == y.

Definition at line 39 of file MooseRandomPerturbation.C.

40 {
41  mooseAssert(y < _n, "y must be < n");
42 
43  uint32_t x = y;
44  do
45  {
46  x = invertPadded(x);
47  } while (x >= _n);
48 
49  return x;
50 }
uint32_t invertPadded(uint32_t y) const
Invert one full pass of the Feistel network by running rounds in reverse.
const unsigned int _n
Size of the permutation domain [0, n)

◆ invertPadded()

uint32_t MooseRandomPerturbation::invertPadded ( uint32_t  y) const
private

Invert one full pass of the Feistel network by running rounds in reverse.

Parameters
yValue in the padded domain produced by permutePadded.
Returns
The original input to permutePadded that produced y.

Definition at line 73 of file MooseRandomPerturbation.C.

Referenced by invert().

74 {
75  uint32_t L = (y >> _half_bits) & _half_mask;
76  uint32_t R = y & _half_mask;
77 
78  // Run rounds in reverse; recover prev_R = L then prev_L = R XOR F(prev_R).
79  for (int r = static_cast<int>(_rounds) - 1; r >= 0; --r)
80  {
81  const uint32_t prevR = L;
82  const uint32_t F = roundFunction(prevR, static_cast<unsigned int>(r));
83  const uint32_t prevL = (R ^ F) & _half_mask;
84  L = prevL;
85  R = prevR;
86  }
87 
88  return ((L & _half_mask) << _half_bits) | (R & _half_mask);
89 }
const uint32_t _half_mask
Bitmask of width _half_bits, used to keep half-block arithmetic in range.
const unsigned int _half_bits
Number of bits in each Feistel half-block: ceil((ceil(log2(n)) + 1) / 2)
uint32_t roundFunction(uint32_t half, unsigned int round) const
Keyed round function F(half, round) used in each Feistel step.
const unsigned int _rounds
Number of Feistel rounds to apply per permute/invert call.

◆ mix32()

uint32_t MooseRandomPerturbation::mix32 ( uint32_t  x)
staticprivate

Bijective 32-bit avalanche hash (finalizer from Murmur3 / degski hash).

Used inside the round function to achieve good bit diffusion.

Parameters
x32-bit input.
Returns
Hashed 32-bit output; the mapping is invertible.

Definition at line 118 of file MooseRandomPerturbation.C.

Referenced by roundFunction().

119 {
120  x ^= x >> 16;
121  x *= 0x7feb352dU;
122  x ^= x >> 15;
123  x *= 0x846ca68bU;
124  x ^= x >> 16;
125  return x;
126 }

◆ permute()

uint32_t MooseRandomPerturbation::permute ( uint32_t  x) const

Map x to its permuted index in [0, n).

Applies the Feistel network to the padded domain and cycle-walks until the result falls within [0, n).

Parameters
xInput index; must satisfy x < n.
Returns
A unique index in [0, n). Calling permute for every x in [0, n) yields each value in [0, n) exactly once.

Definition at line 25 of file MooseRandomPerturbation.C.

26 {
27  mooseAssert(x < _n, "x must be < n");
28 
29  uint32_t y = x;
30  do
31  {
32  y = permutePadded(y);
33  } while (y >= _n);
34 
35  return y;
36 }
uint32_t permutePadded(uint32_t x) const
Apply one full pass of the balanced Feistel network over the padded domain [0, 2^(2*half_bits)).
const unsigned int _n
Size of the permutation domain [0, n)

◆ permutePadded()

uint32_t MooseRandomPerturbation::permutePadded ( uint32_t  x) const
private

Apply one full pass of the balanced Feistel network over the padded domain [0, 2^(2*half_bits)).

The result may fall outside [0, n); the caller is responsible for cycle-walking.

Parameters
xInput value in the padded domain.
Returns
Permuted value in the padded domain.

Definition at line 53 of file MooseRandomPerturbation.C.

Referenced by permute().

54 {
55  // Split x into the upper (L) and lower (R) half_bits-wide halves.
56  uint32_t L = x >> _half_bits;
57  uint32_t R = x & _half_mask;
58 
59  for (unsigned int r = 0; r < _rounds; ++r)
60  {
61  // Standard balanced Feistel step: new_L = R, new_R = L XOR F(R).
62  const uint32_t F = roundFunction(R, r);
63  const uint32_t newL = R;
64  const uint32_t newR = (L ^ F) & _half_mask;
65  L = newL;
66  R = newR;
67  }
68 
69  return ((L & _half_mask) << _half_bits) | (R & _half_mask);
70 }
const uint32_t _half_mask
Bitmask of width _half_bits, used to keep half-block arithmetic in range.
const unsigned int _half_bits
Number of bits in each Feistel half-block: ceil((ceil(log2(n)) + 1) / 2)
uint32_t roundFunction(uint32_t half, unsigned int round) const
Keyed round function F(half, round) used in each Feistel step.
const unsigned int _rounds
Number of Feistel rounds to apply per permute/invert call.

◆ roundFunction()

uint32_t MooseRandomPerturbation::roundFunction ( uint32_t  half,
unsigned int  round 
) const
private

Keyed round function F(half, round) used in each Feistel step.

Mixes the half-block with both subkeys and a round-dependent constant derived from the golden-ratio fractional bits (0x9e3779b9), then passes the result through a 32-bit avalanche hash (mix32).

Parameters
halfThe half-block value (R in the forward direction).
roundZero-based round index, used to vary the constant each round.
Returns
Mixed value masked to _half_bits width.

Definition at line 92 of file MooseRandomPerturbation.C.

Referenced by invertPadded(), and permutePadded().

93 {
94  uint32_t x = half;
95  x ^= _k0;
96  x += 0x9e3779b9U * static_cast<uint32_t>(round + 1); // round-dependent constant
97  x ^= _k1;
98  x = mix32(x);
99  return x & _half_mask;
100 }
static uint32_t mix32(uint32_t x)
Bijective 32-bit avalanche hash (finalizer from Murmur3 / degski hash).
const uint32_t _k0
Lower 32 bits of the seed, used as the first subkey in the round function.
const uint32_t _k1
Upper 32 bits of the seed, used as the second subkey in the round function.
T round(T x)
Definition: MathUtils.h:77
const uint32_t _half_mask
Bitmask of width _half_bits, used to keep half-block arithmetic in range.

Member Data Documentation

◆ _half_bits

const unsigned int MooseRandomPerturbation::_half_bits
private

Number of bits in each Feistel half-block: ceil((ceil(log2(n)) + 1) / 2)

Definition at line 122 of file MooseRandomPerturbation.h.

Referenced by invertPadded(), and permutePadded().

◆ _half_mask

const uint32_t MooseRandomPerturbation::_half_mask
private

Bitmask of width _half_bits, used to keep half-block arithmetic in range.

Definition at line 124 of file MooseRandomPerturbation.h.

Referenced by invertPadded(), permutePadded(), and roundFunction().

◆ _k0

const uint32_t MooseRandomPerturbation::_k0
private

Lower 32 bits of the seed, used as the first subkey in the round function.

Definition at line 116 of file MooseRandomPerturbation.h.

Referenced by roundFunction().

◆ _k1

const uint32_t MooseRandomPerturbation::_k1
private

Upper 32 bits of the seed, used as the second subkey in the round function.

Definition at line 118 of file MooseRandomPerturbation.h.

Referenced by roundFunction().

◆ _n

const unsigned int MooseRandomPerturbation::_n
private

Size of the permutation domain [0, n)

Definition at line 120 of file MooseRandomPerturbation.h.

Referenced by invert(), MooseRandomPerturbation(), and permute().

◆ _rounds

const unsigned int MooseRandomPerturbation::_rounds
private

Number of Feistel rounds to apply per permute/invert call.

Definition at line 126 of file MooseRandomPerturbation.h.

Referenced by invertPadded(), MooseRandomPerturbation(), and permutePadded().


The documentation for this class was generated from the following files: