PallasLFSR88RNG#

class brainevent.PallasLFSR88RNG(seed)#

Combined LFSR random number generator by L’Ecuyer (LFSR88).

Implements the LFSR88 algorithm, a combined Linear Feedback Shift Register random number generator developed by Pierre L’Ecuyer. The algorithm combines three independent LFSRs to produce high-quality pseudorandom numbers with a period of approximately 2^88.

Parameters:

seed (int) – An integer used to initialize the three-component state. The seed is offset by +2, +8, and +16 for the three components to satisfy the minimum-seed constraints of the algorithm.

See also

PallasLFSR113RNG

Four-component variant with period ~2^113.

PallasLFSR128RNG

Four-component variant with period ~2^128.

LFSRBase

Abstract base class defining the LFSR interface.

Notes

The LFSR88 algorithm combines three Tausworthe generators with the following parameters:

  • Component 1: shift (13, 19), mask 0xFFFFFFFE, left-shift 12

  • Component 2: shift (2, 25), mask 0xFFFFFFF8, left-shift 4

  • Component 3: shift (3, 11), mask 0xFFFFFFF0, left-shift 17

Each component advances independently, and the final output is the XOR of all three component values. The fourth element of the internal key tuple is unused by the generation algorithm and is set to zero.

The implementation is based on L’Ecuyer’s original C code: cmcqueen/simplerandom

Examples

>>> rng = PallasLFSR88RNG(seed=42)
>>> rand_float = rng.rand()        # Random float in [0, 1)
>>> rand_int = rng.randint()        # Random 32-bit unsigned integer
>>> norm_val = rng.normal(0, 1)     # Value from N(0, 1)
>>> unif_val = rng.uniform(5.0, 10.0)  # Float in [5, 10)
>>> dice = rng.random_integers(1, 6)   # Integer from 1 to 6
generate_key(seed)[source]#

Initialize the random key of the LFSR88 algorithm.

Creates a 4-element state tuple from the given seed, ensuring that each element meets the minimum required value to guarantee proper algorithm function.

Parameters:

seed (int) – An integer seed value used to initialize the generator state.

Returns:

A tuple of four jnp.uint32 scalars containing the initial state. The fourth element is set to 0 as it is not used by the LFSR88 algorithm.

Return type:

Tuple[uint32, uint32, uint32, uint32]

Notes

The LFSR88 algorithm requires that the initial seeds are at least 2, 8, and 16 for the three components respectively. This method adds these offsets to the provided seed to ensure the constraint is always satisfied.

Examples

>>> rng = PallasLFSR88RNG.__new__(PallasLFSR88RNG)
>>> key = rng.generate_key(42)
>>> len(key)
4
generate_next_key()[source]#

Generate the next random key and update the internal state.

Computes the next state of the LFSR88 generator by applying the three-component LFSR transformations to the current state.

Returns:

A tuple of four jnp.uint32 scalars containing the new state after one iteration.

Return type:

Tuple[uint32, uint32, uint32, uint32]

Notes

This method mutates the internal _key attribute. The fourth element stores the last intermediate value b from the third component, though this is not part of the original algorithm’s state.

Examples

>>> rng = PallasLFSR88RNG(seed=42)
>>> new_key = rng.generate_next_key()
>>> len(new_key)
4
rand()[source]#

Generate a uniformly distributed random float in [0, 1).

Advances the generator state and converts the resulting integer to a floating-point number by multiplying with 1 / (2^32 - 1).

Returns:

A scalar float32 value in the range [0, 1).

Return type:

Array

See also

randint

Generate a raw 32-bit unsigned integer.

uniform

Generate a float in an arbitrary range.

Examples

>>> rng = PallasLFSR88RNG(seed=42)
>>> value = rng.rand()  # e.g. 0.27183515
randint()[source]#

Generate a uniformly distributed random 32-bit unsigned integer.

Advances the generator state and returns the XOR of the three state components.

Returns:

A scalar uint32 value in the range [0, 2^32 - 1].

Return type:

Array

See also

rand

Generate a random float in [0, 1).

random_integers

Generate a random integer in a specified range.

Examples

>>> rng = PallasLFSR88RNG(seed=42)
>>> value = rng.randint()
randn(epsilon=1e-10)[source]#

Generate a random number from the standard normal distribution N(0, 1).

Uses the Box-Muller transform to convert two uniform random numbers into a normally distributed value.

Parameters:

epsilon (float) – A small positive value used to clamp the first uniform sample away from zero, preventing log(0). Defaults to 1e-10.

Returns:

A scalar float32 value sampled from N(0, 1).

Return type:

Array

See also

normal

Generate a value from N(mu, sigma).

rand

Generate a uniform float in [0, 1).

Notes

The Box-Muller transform generates two independent standard normal values from two independent uniform values. This implementation returns only the sine component.

References: Box-Muller transform, https://en.wikipedia.org/wiki/Box%E2%80%93Muller_transform

Examples

>>> rng = PallasLFSR88RNG(seed=42)
>>> value = rng.randn()  # Random value from standard normal