aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitignore5
-rw-r--r--source/Makefile44
-rw-r--r--source/README.md146
-rw-r--r--source/pcg_random.c94
-rw-r--r--source/pcg_random.h52
-rw-r--r--source/splitmix64.c89
-rw-r--r--source/splitmix64.h44
-rw-r--r--source/wy_random.c105
-rw-r--r--source/wy_random.h44
-rw-r--r--source/xoroshiro_random.c108
-rw-r--r--source/xoroshiro_random.h48
-rw-r--r--source/xorshift_random.c75
-rw-r--r--source/xorshift_random.h44
13 files changed, 843 insertions, 55 deletions
diff --git a/.gitignore b/.gitignore
index 719f723..56f9f14 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,5 +1,10 @@
# Compiled binaries
source/photon_spin_random
+source/xorshift_random
+source/splitmix64
+source/wy_random
+source/pcg_random
+source/xoroshiro_random
# Object files
*.o
diff --git a/source/Makefile b/source/Makefile
index 5888d63..cefad43 100644
--- a/source/Makefile
+++ b/source/Makefile
@@ -1,22 +1,46 @@
-# Makefile for PhotonSpinRandom C implementation
+# Makefile for Random Number Generator C implementations
CC = cc
CFLAGS = -O2 -Wall -Wextra -std=c99
LDFLAGS = -lm
-TARGET = photon_spin_random
-SRC = photon_spin_random.c
-HEADER = photon_spin_random.h
+TARGETS = photon_spin_random xorshift_random splitmix64 wy_random pcg_random xoroshiro_random
.PHONY: all clean test
-all: $(TARGET)
+all: $(TARGETS)
-$(TARGET): $(SRC) $(HEADER)
- $(CC) $(CFLAGS) -DPHOTON_SPIN_TEST_MAIN -o $(TARGET) $(SRC) $(LDFLAGS)
+photon_spin_random: photon_spin_random.c photon_spin_random.h
+ $(CC) $(CFLAGS) -DPHOTON_SPIN_TEST_MAIN -o $@ photon_spin_random.c $(LDFLAGS)
-test: $(TARGET)
- ./$(TARGET)
+xorshift_random: xorshift_random.c xorshift_random.h
+ $(CC) $(CFLAGS) -DXORSHIFT_TEST_MAIN -o $@ xorshift_random.c $(LDFLAGS)
+
+splitmix64: splitmix64.c splitmix64.h
+ $(CC) $(CFLAGS) -DSPLITMIX64_TEST_MAIN -o $@ splitmix64.c $(LDFLAGS)
+
+wy_random: wy_random.c wy_random.h
+ $(CC) $(CFLAGS) -DWY_TEST_MAIN -o $@ wy_random.c $(LDFLAGS)
+
+pcg_random: pcg_random.c pcg_random.h
+ $(CC) $(CFLAGS) -DPCG_TEST_MAIN -o $@ pcg_random.c $(LDFLAGS)
+
+xoroshiro_random: xoroshiro_random.c xoroshiro_random.h
+ $(CC) $(CFLAGS) -DXOROSHIRO_TEST_MAIN -o $@ xoroshiro_random.c $(LDFLAGS)
+
+test: $(TARGETS)
+ @echo "=== Testing PhotonSpinRandom ==="
+ ./photon_spin_random
+ @echo "\n=== Testing XorShiftRandom ==="
+ ./xorshift_random
+ @echo "\n=== Testing SplitMix64 ==="
+ ./splitmix64
+ @echo "\n=== Testing WyRandom ==="
+ ./wy_random
+ @echo "\n=== Testing PCG Random ==="
+ ./pcg_random
+ @echo "\n=== Testing XoroShiro Random ==="
+ ./xoroshiro_random
clean:
- rm -f $(TARGET)
+ rm -f $(TARGETS)
diff --git a/source/README.md b/source/README.md
index c1f8d7f..af72351 100644
--- a/source/README.md
+++ b/source/README.md
@@ -1,95 +1,151 @@
-# PhotonSpinRandom C Implementation
+# Random Number Generator C Implementations
-This directory contains a C implementation of the PhotonSpinRandom generator, originally written in C# by Will Stafford Parsons and distributed in the [unity-helpers](https://github.com/wallstop/unity-helpers) repository.
+This directory contains C implementations of various random number generators, originally written in C# by Will Stafford Parsons and distributed in the [unity-helpers](https://github.com/wallstop/unity-helpers) repository.
## Files
-- **photon_spin_random.h** - Header file with type definitions and function declarations
-- **photon_spin_random.c** - Implementation of the PhotonSpin32 random number generator
-- **Makefile** - Build configuration for easy compilation
-- **donut.c** - ASCII art donut (not a source file, QA artifact)
+### PhotonSpinRandom
+- **photon_spin_random.h** / **photon_spin_random.c** - 20-word ring-buffer RNG inspired by SHISHUA
+- Large state, excellent distribution, huge period (~2^512)
+- Best for: Heavy simulation workloads requiring large streams
-## About PhotonSpinRandom
+### XorShift
+- **xorshift_random.h** / **xorshift_random.c** - Classic, extremely fast PRNG
+- Tiny state (32-bit), very fast, modest quality
+- Best for: Effects, particles, jitter, lightweight randomness
-PhotonSpin32 is a 20-word ring-buffer random number generator inspired by SHISHUA, designed for high throughput and large period (~2^512). It excels at:
+### SplitMix64
+- **splitmix64.h** / **splitmix64.c** - Fast 64-bit seeding/mixing generator
+- Very fast, great for seed generation and hashing
+- Best for: Seeding other PRNGs, quick mixing, gameplay randomness
-- Generating large streams of high-quality random numbers
-- Heavy simulation workloads requiring excellent distribution
-- Deterministic state capture and restoration
+### WyRandom
+- **wy_random.h** / **wy_random.c** - Wyhash-inspired multiply-mix PRNG
+- Fast, good distribution, multiply-based mixing
+- Best for: General gameplay RNG, weight selection, shuffles
-**Not suitable for**: Cryptographic or security-sensitive applications.
+### PCG (Permuted Congruential Generator)
+- **pcg_random.h** / **pcg_random.c** - High-quality, small-state PRNG
+- Excellent statistical quality, passes TestU01 BigCrush and PractRand
+- Best for: General gameplay, procedural content, Monte Carlo sampling
+
+### XoroShiro
+- **xoroshiro_random.h** / **xoroshiro_random.c** - Fast 128-bit state Xoroshiro PRNG
+- Very fast, good quality, long period (~2^128−1)
+- Best for: General-purpose randomness, procedural generation
+
+### Build System
+- **Makefile** - Build configuration for all generators
+- **donut.c** - ASCII art donut (QA artifact, not a source file)
## Building
### Using Make
```bash
-make # Build the test program
-make test # Build and run tests
+make # Build all test programs
+make test # Build and run all tests
make clean # Clean build artifacts
```
### Using @BAKE
-The source file includes a `@BAKE` statement for use with the [bake](https://github.com/8e8m/bake) build tool:
+Each source file includes a `@BAKE` statement for use with the [bake](https://github.com/8e8m/bake) build tool. Example from photon_spin_random.c:
```bash
-# The @BAKE command is embedded in photon_spin_random.c:
# @BAKE cc -O2 -Wall -Wextra -std=c99 -o photon_spin_random photon_spin_random.c -lm @STOP
```
-To use it with bake, simply run bake in this directory.
-
### Manual Compilation
```bash
# For testing with built-in test harness:
cc -O2 -Wall -Wextra -std=c99 -DPHOTON_SPIN_TEST_MAIN -o photon_spin_random photon_spin_random.c -lm
+cc -O2 -Wall -Wextra -std=c99 -DXORSHIFT_TEST_MAIN -o xorshift_random xorshift_random.c -lm
+cc -O2 -Wall -Wextra -std=c99 -DSPLITMIX64_TEST_MAIN -o splitmix64 splitmix64.c -lm
+cc -O2 -Wall -Wextra -std=c99 -DWY_TEST_MAIN -o wy_random wy_random.c -lm
+cc -O2 -Wall -Wextra -std=c99 -DPCG_TEST_MAIN -o pcg_random pcg_random.c -lm
+cc -O2 -Wall -Wextra -std=c99 -DXOROSHIRO_TEST_MAIN -o xoroshiro_random xoroshiro_random.c -lm
-# As a library (without test main):
+# As libraries (without test main):
cc -O2 -Wall -Wextra -std=c99 -c photon_spin_random.c
+# ... etc for other generators
```
-## Usage Example
+## Usage Examples
+### PhotonSpinRandom
```c
#include "photon_spin_random.h"
-int main(void) {
- photon_spin_random_t rng;
-
- // Initialize with a seed
- photon_spin_init(&rng, 42);
-
- // Generate random numbers
- uint32_t rand_uint = photon_spin_next_uint(&rng);
- float rand_float = photon_spin_next_float(&rng); // [0, 1)
- double rand_double = photon_spin_next_double(&rng); // [0, 1)
- int32_t rand_range = photon_spin_next_int_range(&rng, 0, 100); // [0, 100)
-
- return 0;
-}
+photon_spin_random_t rng;
+photon_spin_init(&rng, 42);
+uint32_t rand_uint = photon_spin_next_uint(&rng);
+float rand_float = photon_spin_next_float(&rng); // [0, 1)
```
-## API Reference
+### XorShift
+```c
+#include "xorshift_random.h"
+
+xorshift_random_t rng;
+xorshift_init(&rng, 42);
+uint32_t value = xorshift_next_uint(&rng);
+```
-### Initialization Functions
+### SplitMix64
+```c
+#include "splitmix64.h"
+
+splitmix64_t rng;
+splitmix64_init(&rng, 42);
+uint64_t value = splitmix64_next_ulong(&rng);
+```
+
+### WyRandom
+```c
+#include "wy_random.h"
+
+wy_random_t rng;
+wy_init(&rng, 42);
+uint32_t value = wy_next_uint(&rng);
+```
+
+### PCG
+```c
+#include "pcg_random.h"
+
+pcg_random_t rng;
+pcg_init(&rng, 42);
+uint32_t value = pcg_next_uint(&rng);
+```
+
+### XoroShiro
+```c
+#include "xoroshiro_random.h"
+
+xoroshiro_random_t rng;
+xoroshiro_init(&rng, 42, 12345);
+uint64_t value = xoroshiro_next_ulong(&rng);
+```
-- `photon_spin_init(rng, seed)` - Initialize with a single 32-bit seed
-- `photon_spin_init_scalars(rng, seed_a, seed_b, seed_c)` - Initialize with three 32-bit seeds
-- `photon_spin_init_ulongs(rng, seed0, seed1)` - Initialize with two 64-bit seeds
+## Choosing a Generator
-### Generation Functions
+| Generator | Speed | Quality | State Size | Use Case |
+|-----------|-------|---------|------------|----------|
+| XorShift | Fastest | Fair | 4 bytes | Particles, effects, simple randomness |
+| SplitMix64 | Very Fast | Very Good | 8 bytes | Seeding, mixing, quick generation |
+| WyRandom | Very Fast | Very Good | 8 bytes | General gameplay, hashing-like uses |
+| PCG | Fast | Excellent | 16 bytes | High-quality gameplay, simulations |
+| XoroShiro | Very Fast | Very Good | 16 bytes | General-purpose, procedural gen |
+| PhotonSpin | Fast | Excellent | 80 bytes | Large streams, heavy simulations |
-- `photon_spin_next_uint(rng)` - Generate next 32-bit unsigned integer
-- `photon_spin_next_float(rng)` - Generate next float in [0, 1)
-- `photon_spin_next_double(rng)` - Generate next double in [0, 1)
-- `photon_spin_next_int_range(rng, min, max)` - Generate integer in [min, max)
+**Note**: None of these generators are cryptographically secure. Do not use for security-sensitive applications.
## License
MIT License - Copyright (c) 2025 wallstop
-Original C# implementation from: https://github.com/wallstop/unity-helpers
+Original C# implementations from: https://github.com/wallstop/unity-helpers
Converted to C for the librandom project.
diff --git a/source/pcg_random.c b/source/pcg_random.c
new file mode 100644
index 0000000..4d01b49
--- /dev/null
+++ b/source/pcg_random.c
@@ -0,0 +1,94 @@
+/* MIT License - Copyright (c) 2025 wallstop
+ * Original C# implementation from: https://github.com/wallstop/unity-helpers
+ * Converted to C for librandom project
+ *
+ * @BAKE cc -O2 -Wall -Wextra -std=c99 -o pcg_random pcg_random.c -lm @STOP
+ */
+
+#include "pcg_random.h"
+
+static inline uint64_t normalize_increment(uint64_t increment) {
+ return (increment & 1ULL) == 0 ? increment | 1ULL : increment;
+}
+
+void pcg_init(pcg_random_t *rng, uint64_t seed) {
+ rng->increment = normalize_increment(6554638469ULL);
+ rng->state = seed;
+ /* Warm up the state */
+ pcg_next_uint(rng);
+ rng->increment = normalize_increment((uint64_t)pcg_next_uint(rng) | ((uint64_t)pcg_next_uint(rng) << 32));
+}
+
+void pcg_init_full(pcg_random_t *rng, uint64_t state, uint64_t increment) {
+ rng->state = state;
+ rng->increment = normalize_increment(increment);
+}
+
+uint32_t pcg_next_uint(pcg_random_t *rng) {
+ uint64_t old_state = rng->state;
+ rng->state = old_state * 6364136223846793005ULL + rng->increment;
+ uint32_t xor_shifted = (uint32_t)(((old_state >> 18) ^ old_state) >> 27);
+ int rot = (int)(old_state >> 59);
+ return (xor_shifted >> rot) | (xor_shifted << ((-rot) & 31));
+}
+
+uint64_t pcg_next_ulong(pcg_random_t *rng) {
+ uint64_t high = (uint64_t)pcg_next_uint(rng) << 32;
+ uint64_t low = (uint64_t)pcg_next_uint(rng);
+ return high | low;
+}
+
+float pcg_next_float(pcg_random_t *rng) {
+ uint32_t value = pcg_next_uint(rng);
+ return (value >> 8) * 0x1.0p-24f;
+}
+
+double pcg_next_double(pcg_random_t *rng) {
+ uint64_t value = pcg_next_ulong(rng);
+ return (value >> 11) * 0x1.0p-53;
+}
+
+#ifdef PCG_TEST_MAIN
+#include <stdio.h>
+#include <time.h>
+
+int main(void) {
+ pcg_random_t rng;
+
+ printf("PCG Random C Implementation Test\n");
+ printf("=================================\n\n");
+
+ pcg_init(&rng, 42);
+
+ printf("Testing with seed 42:\n");
+ printf("First 10 uint32_t values:\n");
+ for (int i = 0; i < 10; i++) {
+ printf(" %u\n", pcg_next_uint(&rng));
+ }
+
+ printf("\nFirst 10 uint64_t values:\n");
+ pcg_init(&rng, 42);
+ for (int i = 0; i < 10; i++) {
+ printf(" %llu\n", (unsigned long long)pcg_next_ulong(&rng));
+ }
+
+ printf("\nFirst 10 float values:\n");
+ pcg_init(&rng, 42);
+ for (int i = 0; i < 10; i++) {
+ printf(" %.6f\n", pcg_next_float(&rng));
+ }
+
+ printf("\nPerformance test: generating 10 million uint32_t values...\n");
+ pcg_init(&rng, (uint64_t)time(NULL));
+ clock_t start = clock();
+ uint64_t sum = 0;
+ for (int i = 0; i < 10000000; i++) {
+ sum += pcg_next_uint(&rng);
+ }
+ clock_t end = clock();
+ double elapsed = (double)(end - start) / CLOCKS_PER_SEC;
+ printf("Time: %.3f seconds (sum: %llu to prevent optimization)\n", elapsed, (unsigned long long)sum);
+
+ return 0;
+}
+#endif
diff --git a/source/pcg_random.h b/source/pcg_random.h
new file mode 100644
index 0000000..ae4886a
--- /dev/null
+++ b/source/pcg_random.h
@@ -0,0 +1,52 @@
+/* MIT License - Copyright (c) 2025 wallstop
+ * Original C# implementation from: https://github.com/wallstop/unity-helpers
+ * Converted to C for librandom project
+ */
+
+#ifndef PCG_RANDOM_H
+#define PCG_RANDOM_H
+
+#include <stdint.h>
+#include <stdbool.h>
+
+/* PCG (Permuted Congruential Generator): High-quality, small-state PRNG.
+ *
+ * PCG offers excellent statistical quality with very small state and extremely
+ * fast generation. This implementation uses a 64-bit state with 32-bit outputs
+ * and an increment (stream selector).
+ *
+ * Pros:
+ * - Fast and allocation-free; suitable for gameplay hot paths
+ * - Great statistical quality; passes TestU01 BigCrush and PractRand
+ * - Deterministic and reproducible across platforms
+ * - Small state footprint
+ *
+ * Cons:
+ * - Not cryptographically secure
+ * - 32-bit outputs (use multiple calls for 64-bit)
+ */
+
+typedef struct {
+ uint64_t state;
+ uint64_t increment;
+} pcg_random_t;
+
+/* Initialize the generator with a seed */
+void pcg_init(pcg_random_t *rng, uint64_t seed);
+
+/* Initialize with explicit state and increment */
+void pcg_init_full(pcg_random_t *rng, uint64_t state, uint64_t increment);
+
+/* Generate next random 32-bit unsigned integer */
+uint32_t pcg_next_uint(pcg_random_t *rng);
+
+/* Generate next random 64-bit unsigned integer */
+uint64_t pcg_next_ulong(pcg_random_t *rng);
+
+/* Generate next random float in [0, 1) */
+float pcg_next_float(pcg_random_t *rng);
+
+/* Generate next random double in [0, 1) */
+double pcg_next_double(pcg_random_t *rng);
+
+#endif /* PCG_RANDOM_H */
diff --git a/source/splitmix64.c b/source/splitmix64.c
new file mode 100644
index 0000000..c840258
--- /dev/null
+++ b/source/splitmix64.c
@@ -0,0 +1,89 @@
+/* MIT License - Copyright (c) 2025 wallstop
+ * Original C# implementation from: https://github.com/wallstop/unity-helpers
+ * Converted to C for librandom project
+ *
+ * @BAKE cc -O2 -Wall -Wextra -std=c99 -o splitmix64 splitmix64.c -lm @STOP
+ */
+
+#include "splitmix64.h"
+
+void splitmix64_init(splitmix64_t *rng, uint64_t seed) {
+ rng->state = seed;
+}
+
+uint32_t splitmix64_next_uint(splitmix64_t *rng) {
+ rng->state += 0x9E3779B97F4A7C15ULL;
+
+ uint64_t z = rng->state;
+ z = (z ^ (z >> 30)) * 0xBF58476D1CE4E5B9ULL;
+ z = (z ^ (z >> 27)) * 0x94D049BB133111EBULL;
+ z ^= z >> 31;
+
+ return (uint32_t)z;
+}
+
+uint64_t splitmix64_next_ulong(splitmix64_t *rng) {
+ rng->state += 0x9E3779B97F4A7C15ULL;
+
+ uint64_t z = rng->state;
+ z = (z ^ (z >> 30)) * 0xBF58476D1CE4E5B9ULL;
+ z = (z ^ (z >> 27)) * 0x94D049BB133111EBULL;
+ z ^= z >> 31;
+
+ return z;
+}
+
+float splitmix64_next_float(splitmix64_t *rng) {
+ uint32_t value = splitmix64_next_uint(rng);
+ return (value >> 8) * 0x1.0p-24f;
+}
+
+double splitmix64_next_double(splitmix64_t *rng) {
+ uint64_t value = splitmix64_next_ulong(rng);
+ return (value >> 11) * 0x1.0p-53;
+}
+
+#ifdef SPLITMIX64_TEST_MAIN
+#include <stdio.h>
+#include <time.h>
+
+int main(void) {
+ splitmix64_t rng;
+
+ printf("SplitMix64 C Implementation Test\n");
+ printf("=================================\n\n");
+
+ splitmix64_init(&rng, 42);
+
+ printf("Testing with seed 42:\n");
+ printf("First 10 uint32_t values:\n");
+ for (int i = 0; i < 10; i++) {
+ printf(" %u\n", splitmix64_next_uint(&rng));
+ }
+
+ printf("\nFirst 10 uint64_t values:\n");
+ splitmix64_init(&rng, 42);
+ for (int i = 0; i < 10; i++) {
+ printf(" %llu\n", (unsigned long long)splitmix64_next_ulong(&rng));
+ }
+
+ printf("\nFirst 10 float values:\n");
+ splitmix64_init(&rng, 42);
+ for (int i = 0; i < 10; i++) {
+ printf(" %.6f\n", splitmix64_next_float(&rng));
+ }
+
+ printf("\nPerformance test: generating 10 million uint64_t values...\n");
+ splitmix64_init(&rng, (uint64_t)time(NULL));
+ clock_t start = clock();
+ uint64_t sum = 0;
+ for (int i = 0; i < 10000000; i++) {
+ sum += splitmix64_next_ulong(&rng);
+ }
+ clock_t end = clock();
+ double elapsed = (double)(end - start) / CLOCKS_PER_SEC;
+ printf("Time: %.3f seconds (sum: %llu to prevent optimization)\n", elapsed, (unsigned long long)sum);
+
+ return 0;
+}
+#endif
diff --git a/source/splitmix64.h b/source/splitmix64.h
new file mode 100644
index 0000000..27d7eda
--- /dev/null
+++ b/source/splitmix64.h
@@ -0,0 +1,44 @@
+/* MIT License - Copyright (c) 2025 wallstop
+ * Original C# implementation from: https://github.com/wallstop/unity-helpers
+ * Converted to C for librandom project
+ */
+
+#ifndef SPLITMIX64_H
+#define SPLITMIX64_H
+
+#include <stdint.h>
+#include <stdbool.h>
+
+/* SplitMix64: A fast 64-bit generator often used as a high-quality seeding/mixing PRNG.
+ *
+ * SplitMix64 is widely used to quickly generate well-distributed 64-bit values
+ * and as a seed source for other generators.
+ *
+ * Pros:
+ * - Very fast; great as a hash/mixer and for seed generation
+ * - Deterministic, portable, and simple
+ *
+ * Cons:
+ * - Not cryptographically secure
+ */
+
+typedef struct {
+ uint64_t state;
+} splitmix64_t;
+
+/* Initialize the generator with a seed */
+void splitmix64_init(splitmix64_t *rng, uint64_t seed);
+
+/* Generate next random 32-bit unsigned integer */
+uint32_t splitmix64_next_uint(splitmix64_t *rng);
+
+/* Generate next random 64-bit unsigned integer */
+uint64_t splitmix64_next_ulong(splitmix64_t *rng);
+
+/* Generate next random float in [0, 1) */
+float splitmix64_next_float(splitmix64_t *rng);
+
+/* Generate next random double in [0, 1) */
+double splitmix64_next_double(splitmix64_t *rng);
+
+#endif /* SPLITMIX64_H */
diff --git a/source/wy_random.c b/source/wy_random.c
new file mode 100644
index 0000000..dcec829
--- /dev/null
+++ b/source/wy_random.c
@@ -0,0 +1,105 @@
+/* MIT License - Copyright (c) 2025 wallstop
+ * Original C# implementation from: https://github.com/wallstop/unity-helpers
+ * Converted to C for librandom project
+ *
+ * @BAKE cc -O2 -Wall -Wextra -std=c99 -o wy_random wy_random.c -lm @STOP
+ */
+
+#include "wy_random.h"
+
+#define WY_PRIME0 0xa0761d6478bd642fULL
+#define WY_PRIME1 0xe7037ed1a0b428dbULL
+
+/* Multiply two 64-bit integers and return hi and lo parts of 128-bit result */
+static inline void multiply_64(uint64_t x, uint64_t y, uint64_t *hi, uint64_t *lo) {
+ uint64_t x0 = (uint32_t)x;
+ uint64_t x1 = x >> 32;
+ uint64_t y0 = (uint32_t)y;
+ uint64_t y1 = y >> 32;
+
+ uint64_t p11 = x1 * y1;
+ uint64_t p01 = x0 * y1;
+ uint64_t p10 = x1 * y0;
+ uint64_t p00 = x0 * y0;
+
+ uint64_t middle = p10 + (p00 >> 32) + (uint32_t)p01;
+
+ *lo = (middle << 32) | (uint32_t)p00;
+ *hi = p11 + (middle >> 32) + (p01 >> 32);
+}
+
+/* MUM (MUltiply and Mix) operation */
+static inline uint64_t mum(uint64_t x, uint64_t y) {
+ uint64_t hi, lo;
+ multiply_64(x, y, &hi, &lo);
+ return hi ^ lo;
+}
+
+void wy_init(wy_random_t *rng, uint64_t seed) {
+ rng->state = seed;
+}
+
+uint32_t wy_next_uint(wy_random_t *rng) {
+ rng->state += WY_PRIME0;
+ return (uint32_t)mum(rng->state ^ WY_PRIME1, rng->state);
+}
+
+uint64_t wy_next_ulong(wy_random_t *rng) {
+ rng->state += WY_PRIME0;
+ return mum(rng->state ^ WY_PRIME1, rng->state);
+}
+
+float wy_next_float(wy_random_t *rng) {
+ uint32_t value = wy_next_uint(rng);
+ return (value >> 8) * 0x1.0p-24f;
+}
+
+double wy_next_double(wy_random_t *rng) {
+ uint64_t value = wy_next_ulong(rng);
+ return (value >> 11) * 0x1.0p-53;
+}
+
+#ifdef WY_TEST_MAIN
+#include <stdio.h>
+#include <time.h>
+
+int main(void) {
+ wy_random_t rng;
+
+ printf("WyRandom C Implementation Test\n");
+ printf("===============================\n\n");
+
+ wy_init(&rng, 42);
+
+ printf("Testing with seed 42:\n");
+ printf("First 10 uint32_t values:\n");
+ for (int i = 0; i < 10; i++) {
+ printf(" %u\n", wy_next_uint(&rng));
+ }
+
+ printf("\nFirst 10 uint64_t values:\n");
+ wy_init(&rng, 42);
+ for (int i = 0; i < 10; i++) {
+ printf(" %llu\n", (unsigned long long)wy_next_ulong(&rng));
+ }
+
+ printf("\nFirst 10 float values:\n");
+ wy_init(&rng, 42);
+ for (int i = 0; i < 10; i++) {
+ printf(" %.6f\n", wy_next_float(&rng));
+ }
+
+ printf("\nPerformance test: generating 10 million uint64_t values...\n");
+ wy_init(&rng, (uint64_t)time(NULL));
+ clock_t start = clock();
+ uint64_t sum = 0;
+ for (int i = 0; i < 10000000; i++) {
+ sum += wy_next_ulong(&rng);
+ }
+ clock_t end = clock();
+ double elapsed = (double)(end - start) / CLOCKS_PER_SEC;
+ printf("Time: %.3f seconds (sum: %llu to prevent optimization)\n", elapsed, (unsigned long long)sum);
+
+ return 0;
+}
+#endif
diff --git a/source/wy_random.h b/source/wy_random.h
new file mode 100644
index 0000000..80afb43
--- /dev/null
+++ b/source/wy_random.h
@@ -0,0 +1,44 @@
+/* MIT License - Copyright (c) 2025 wallstop
+ * Original C# implementation from: https://github.com/wallstop/unity-helpers
+ * Converted to C for librandom project
+ */
+
+#ifndef WY_RANDOM_H
+#define WY_RANDOM_H
+
+#include <stdint.h>
+#include <stdbool.h>
+
+/* WyRandom: A wyhash-inspired PRNG variant leveraging multiply-mix operations.
+ *
+ * Designed around 64-bit multiply-and-mix steps, this generator is fast and
+ * suitable for general-purpose randomness and hashing-like use cases.
+ *
+ * Pros:
+ * - Fast and simple; good distribution for typical gameplay uses
+ * - Deterministic across platforms
+ *
+ * Cons:
+ * - Not cryptographically secure
+ */
+
+typedef struct {
+ uint64_t state;
+} wy_random_t;
+
+/* Initialize the generator with a seed */
+void wy_init(wy_random_t *rng, uint64_t seed);
+
+/* Generate next random 32-bit unsigned integer */
+uint32_t wy_next_uint(wy_random_t *rng);
+
+/* Generate next random 64-bit unsigned integer */
+uint64_t wy_next_ulong(wy_random_t *rng);
+
+/* Generate next random float in [0, 1) */
+float wy_next_float(wy_random_t *rng);
+
+/* Generate next random double in [0, 1) */
+double wy_next_double(wy_random_t *rng);
+
+#endif /* WY_RANDOM_H */
diff --git a/source/xoroshiro_random.c b/source/xoroshiro_random.c
new file mode 100644
index 0000000..4b5d8d3
--- /dev/null
+++ b/source/xoroshiro_random.c
@@ -0,0 +1,108 @@
+/* MIT License - Copyright (c) 2025 wallstop
+ * Original C# implementation from: https://github.com/wallstop/unity-helpers
+ * Converted to C for librandom project
+ *
+ * @BAKE cc -O2 -Wall -Wextra -std=c99 -o xoroshiro_random xoroshiro_random.c -lm @STOP
+ */
+
+#include "xoroshiro_random.h"
+
+static inline uint64_t rotl(uint64_t x, int k) {
+ return (x << k) | (x >> (64 - k));
+}
+
+static void ensure_non_zero_state(xoroshiro_random_t *rng) {
+ if ((rng->s0 | rng->s1) == 0) {
+ rng->s0 = 0x9E3779B97F4A7C15ULL;
+ rng->s1 = 0xD1B54A32D192ED03ULL;
+ }
+}
+
+void xoroshiro_init(xoroshiro_random_t *rng, uint64_t seed1, uint64_t seed2) {
+ rng->s0 = seed1;
+ rng->s1 = seed2;
+ ensure_non_zero_state(rng);
+}
+
+uint32_t xoroshiro_next_uint(xoroshiro_random_t *rng) {
+ ensure_non_zero_state(rng);
+
+ uint64_t s0 = rng->s0;
+ uint64_t s1 = rng->s1;
+ uint64_t result = s0 + s1;
+
+ s1 ^= s0;
+ rng->s0 = rotl(s0, 24) ^ s1 ^ (s1 << 16);
+ rng->s1 = rotl(s1, 37);
+
+ return (uint32_t)result;
+}
+
+uint64_t xoroshiro_next_ulong(xoroshiro_random_t *rng) {
+ ensure_non_zero_state(rng);
+
+ uint64_t s0 = rng->s0;
+ uint64_t s1 = rng->s1;
+ uint64_t result = s0 + s1;
+
+ s1 ^= s0;
+ rng->s0 = rotl(s0, 24) ^ s1 ^ (s1 << 16);
+ rng->s1 = rotl(s1, 37);
+
+ return result;
+}
+
+float xoroshiro_next_float(xoroshiro_random_t *rng) {
+ uint32_t value = xoroshiro_next_uint(rng);
+ return (value >> 8) * 0x1.0p-24f;
+}
+
+double xoroshiro_next_double(xoroshiro_random_t *rng) {
+ uint64_t value = xoroshiro_next_ulong(rng);
+ return (value >> 11) * 0x1.0p-53;
+}
+
+#ifdef XOROSHIRO_TEST_MAIN
+#include <stdio.h>
+#include <time.h>
+
+int main(void) {
+ xoroshiro_random_t rng;
+
+ printf("XoroShiro Random C Implementation Test\n");
+ printf("=======================================\n\n");
+
+ xoroshiro_init(&rng, 42, 12345);
+
+ printf("Testing with seeds 42, 12345:\n");
+ printf("First 10 uint32_t values:\n");
+ for (int i = 0; i < 10; i++) {
+ printf(" %u\n", xoroshiro_next_uint(&rng));
+ }
+
+ printf("\nFirst 10 uint64_t values:\n");
+ xoroshiro_init(&rng, 42, 12345);
+ for (int i = 0; i < 10; i++) {
+ printf(" %llu\n", (unsigned long long)xoroshiro_next_ulong(&rng));
+ }
+
+ printf("\nFirst 10 float values:\n");
+ xoroshiro_init(&rng, 42, 12345);
+ for (int i = 0; i < 10; i++) {
+ printf(" %.6f\n", xoroshiro_next_float(&rng));
+ }
+
+ printf("\nPerformance test: generating 10 million uint64_t values...\n");
+ xoroshiro_init(&rng, (uint64_t)time(NULL), (uint64_t)time(NULL) * 2);
+ clock_t start = clock();
+ uint64_t sum = 0;
+ for (int i = 0; i < 10000000; i++) {
+ sum += xoroshiro_next_ulong(&rng);
+ }
+ clock_t end = clock();
+ double elapsed = (double)(end - start) / CLOCKS_PER_SEC;
+ printf("Time: %.3f seconds (sum: %llu to prevent optimization)\n", elapsed, (unsigned long long)sum);
+
+ return 0;
+}
+#endif
diff --git a/source/xoroshiro_random.h b/source/xoroshiro_random.h
new file mode 100644
index 0000000..d8b41b6
--- /dev/null
+++ b/source/xoroshiro_random.h
@@ -0,0 +1,48 @@
+/* MIT License - Copyright (c) 2025 wallstop
+ * Original C# implementation from: https://github.com/wallstop/unity-helpers
+ * Converted to C for librandom project
+ */
+
+#ifndef XOROSHIRO_RANDOM_H
+#define XOROSHIRO_RANDOM_H
+
+#include <stdint.h>
+#include <stdbool.h>
+
+/* XoroShiro: A fast 128-bit state Xoroshiro-based PRNG with good quality.
+ *
+ * Xoroshiro family generators offer an excellent balance between speed and
+ * quality for real-time applications. This implementation maintains two 64-bit
+ * state variables.
+ *
+ * Pros:
+ * - Very fast; suitable for gameplay and procedural generation
+ * - Good statistical properties; long period (~2^128−1)
+ * - Deterministic and reproducible across platforms
+ *
+ * Cons:
+ * - Not cryptographically secure
+ * - Low bits may show weaker properties in some variants
+ */
+
+typedef struct {
+ uint64_t s0;
+ uint64_t s1;
+} xoroshiro_random_t;
+
+/* Initialize the generator with two seeds */
+void xoroshiro_init(xoroshiro_random_t *rng, uint64_t seed1, uint64_t seed2);
+
+/* Generate next random 32-bit unsigned integer */
+uint32_t xoroshiro_next_uint(xoroshiro_random_t *rng);
+
+/* Generate next random 64-bit unsigned integer */
+uint64_t xoroshiro_next_ulong(xoroshiro_random_t *rng);
+
+/* Generate next random float in [0, 1) */
+float xoroshiro_next_float(xoroshiro_random_t *rng);
+
+/* Generate next random double in [0, 1) */
+double xoroshiro_next_double(xoroshiro_random_t *rng);
+
+#endif /* XOROSHIRO_RANDOM_H */
diff --git a/source/xorshift_random.c b/source/xorshift_random.c
new file mode 100644
index 0000000..daeecfd
--- /dev/null
+++ b/source/xorshift_random.c
@@ -0,0 +1,75 @@
+/* MIT License - Copyright (c) 2025 wallstop
+ * Original C# implementation from: https://github.com/wallstop/unity-helpers
+ * Converted to C for librandom project
+ *
+ * @BAKE cc -O2 -Wall -Wextra -std=c99 -o xorshift_random xorshift_random.c -lm @STOP
+ */
+
+#include "xorshift_random.h"
+
+static uint32_t normalize_state(uint32_t state) {
+ return state != 0 ? state : XORSHIFT_DEFAULT_STATE;
+}
+
+void xorshift_init(xorshift_random_t *rng, uint32_t seed) {
+ rng->state = normalize_state(seed);
+}
+
+uint32_t xorshift_next_uint(xorshift_random_t *rng) {
+ rng->state = normalize_state(rng->state);
+ rng->state ^= rng->state << 13;
+ rng->state ^= rng->state >> 17;
+ rng->state ^= rng->state << 5;
+ return rng->state;
+}
+
+float xorshift_next_float(xorshift_random_t *rng) {
+ uint32_t value = xorshift_next_uint(rng);
+ return (value >> 8) * 0x1.0p-24f;
+}
+
+double xorshift_next_double(xorshift_random_t *rng) {
+ uint32_t high = xorshift_next_uint(rng);
+ uint32_t low = xorshift_next_uint(rng);
+ uint64_t combined = ((uint64_t)high << 32) | low;
+ return (combined >> 11) * 0x1.0p-53;
+}
+
+#ifdef XORSHIFT_TEST_MAIN
+#include <stdio.h>
+#include <time.h>
+
+int main(void) {
+ xorshift_random_t rng;
+
+ printf("XorShift Random C Implementation Test\n");
+ printf("=====================================\n\n");
+
+ xorshift_init(&rng, 42);
+
+ printf("Testing with seed 42:\n");
+ printf("First 10 uint32_t values:\n");
+ for (int i = 0; i < 10; i++) {
+ printf(" %u\n", xorshift_next_uint(&rng));
+ }
+
+ printf("\nFirst 10 float values:\n");
+ xorshift_init(&rng, 42);
+ for (int i = 0; i < 10; i++) {
+ printf(" %.6f\n", xorshift_next_float(&rng));
+ }
+
+ printf("\nPerformance test: generating 10 million uint32_t values...\n");
+ xorshift_init(&rng, (uint32_t)time(NULL));
+ clock_t start = clock();
+ uint64_t sum = 0;
+ for (int i = 0; i < 10000000; i++) {
+ sum += xorshift_next_uint(&rng);
+ }
+ clock_t end = clock();
+ double elapsed = (double)(end - start) / CLOCKS_PER_SEC;
+ printf("Time: %.3f seconds (sum: %llu to prevent optimization)\n", elapsed, (unsigned long long)sum);
+
+ return 0;
+}
+#endif
diff --git a/source/xorshift_random.h b/source/xorshift_random.h
new file mode 100644
index 0000000..40e5724
--- /dev/null
+++ b/source/xorshift_random.h
@@ -0,0 +1,44 @@
+/* MIT License - Copyright (c) 2025 wallstop
+ * Original C# implementation from: https://github.com/wallstop/unity-helpers
+ * Converted to C for librandom project
+ */
+
+#ifndef XORSHIFT_RANDOM_H
+#define XORSHIFT_RANDOM_H
+
+#include <stdint.h>
+#include <stdbool.h>
+
+/* XorShift: A classic, extremely fast PRNG with small state and modest quality.
+ *
+ * XorShift generators are known for their simplicity and speed. This variant
+ * operates on a 32-bit state and produces 32-bit outputs.
+ *
+ * Pros:
+ * - Very fast; tiny state footprint
+ * - Deterministic and easy to serialize/restore
+ *
+ * Cons:
+ * - Lower statistical quality than newer generators
+ * - Not cryptographically secure
+ */
+
+#define XORSHIFT_DEFAULT_STATE 2463534242U
+
+typedef struct {
+ uint32_t state;
+} xorshift_random_t;
+
+/* Initialize the generator with a seed */
+void xorshift_init(xorshift_random_t *rng, uint32_t seed);
+
+/* Generate next random 32-bit unsigned integer */
+uint32_t xorshift_next_uint(xorshift_random_t *rng);
+
+/* Generate next random float in [0, 1) */
+float xorshift_next_float(xorshift_random_t *rng);
+
+/* Generate next random double in [0, 1) */
+double xorshift_next_double(xorshift_random_t *rng);
+
+#endif /* XORSHIFT_RANDOM_H */