aboutsummaryrefslogtreecommitdiff
path: root/source/photon_spin_random.h
blob: 568c0988ef0101eeeb731005d313e16f8199159f (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
/* MIT License - Copyright (c) 2025 wallstop
 * Original C# implementation from: https://github.com/wallstop/unity-helpers
 * Converted to C for librandom project
 */

#ifndef PHOTON_SPIN_RANDOM_H
#define PHOTON_SPIN_RANDOM_H

#include <stdint.h>
#include <stdbool.h>

/* PhotonSpin32: a 20-word ring-buffer generator inspired by SHISHUA,
 * tuned for high throughput and large period.
 *
 * Reference: Will Stafford Parsons (wileylooper/photonspin, repository offline).
 * This generator produces batches of 20 new 32-bit values per round,
 * offering a huge period (~2^512) and robust statistical performance.
 *
 * Pros:
 * - Large state with excellent distribution; great for heavy simulation workloads
 * - Deterministic snapshots through state capture
 *
 * Cons:
 * - Higher per-instance memory (~20×4 bytes)
 * - Not cryptographically secure
 */

#define PHOTON_SPIN_BLOCK_SIZE 20
#define PHOTON_SPIN_INCREMENT 111111U

typedef struct {
    uint32_t elements[PHOTON_SPIN_BLOCK_SIZE];
    uint32_t a;
    uint32_t b;
    uint32_t c;
    int index;
    bool has_primed;
} photon_spin_random_t;

/* Initialize the generator with a single seed */
void photon_spin_init(photon_spin_random_t *rng, uint32_t seed);

/* Initialize the generator with three seeds */
void photon_spin_init_scalars(photon_spin_random_t *rng, uint32_t seed_a, uint32_t seed_b, uint32_t seed_c);

/* Initialize the generator with two 64-bit seeds */
void photon_spin_init_ulongs(photon_spin_random_t *rng, uint64_t seed0, uint64_t seed1);

/* Generate next random 32-bit unsigned integer */
uint32_t photon_spin_next_uint(photon_spin_random_t *rng);

/* Generate next random float in [0, 1) */
float photon_spin_next_float(photon_spin_random_t *rng);

/* Generate next random double in [0, 1) */
double photon_spin_next_double(photon_spin_random_t *rng);

/* Generate next random int in range [min, max) */
int32_t photon_spin_next_int_range(photon_spin_random_t *rng, int32_t min, int32_t max);

#endif /* PHOTON_SPIN_RANDOM_H */