urng 0.2.5

Universal Random Number Generator
[<img alt="crates.io" src="https://img.shields.io/crates/v/urng.svg?style=for-the-badge&color=fc8d62&logo=rust" height="20">](https://crates.io/crates/urng)
[<img alt="docs.rs" src="https://img.shields.io/badge/docs.rs-urng-66c2a5?style=for-the-badge&labelColor=555555&logo=docs.rs" height="20">](https://docs.rs/urng)

# Universal RNG


A collection of efficient pseudo-random number generators (PRNGs) implemented in pure Rust.
This crate provides a wide variety of algorithms, ranging from standard Mersenne Twister to modern high-performance generators like Xoshiro and Philox.

## Installation


Add this to your `Cargo.toml`:

```toml
[dependencies]
urng = "0.2.4"
```

## Supported Generators


All generators implement either the `Rng32` or `Rng64` trait, providing a unified interface.

### 32-bit Generators (`urng::rng32`)


Output `u32` natively.

| Struct        | Algorithm        | Period / State   | Description                               |
| ------------- | ---------------- | ---------------- | ----------------------------------------- |
| `Mt19937`     | Mersenne Twister | $2^{19937}-1$    | Standard reliable generator.              |
| `Pcg32`       | PCG-XSH-RR       | $2^{64}$         | Fast, statistically good, small state.    |
| `Philox32`    | Philox 4x32      | -                | Counter-based, suitable for parallel use. |
| `SplitMix32`  | SplitMix32       | $2^{32}$         | Fast, used for initializing other states. |
| `Xorwow`      | XORWOW           | $2^{192}-2^{32}$ | Used in NVIDIA cuRAND.                    |
| `Xorshift32`  | Xorshift         | $2^{32}-1$       | Very simple and fast.                     |
| `TwistedGFSR` | TGFSR            | $2^{800}$ approx | Generalized Feedback Shift Register.      |
| `Lcg32`       | LCG              | $m$              | Linear Congruential Generator.            |

### 64-bit Generators (`urng::rng64`)


Output `u64` natively.

| Struct         | Algorithm           | Period / State   | Description                               |
| -------------- | ------------------- | ---------------- | ----------------------------------------- |
| `Xoshiro256Pp` | xoshiro256++        | $2^{256}-1$      | **Recommended** all-purpose generator.    |
| `Xoshiro256Ss` | xoshiro256\*\*      | $2^{256}-1$      | **Recommended** all-purpose generator.    |
| `SplitMix64`   | SplitMix64          | $2^{64}$         | Fast, used for initializing other states. |
| `Sfc64`        | SFC64               | $2^{256}$ approx | Small Fast Chaotic PRNG.                  |
| `Mt1993764`    | Mersenne Twister 64 | $2^{19937}-1$    | 64-bit variant of MT.                     |
| `Philox64`     | Philox 2x64         | -                | Counter-based.                            |
| `Xorshift64`   | Xorshift            | $2^{64}-1$       | Simple and fast.                          |
| `Cet64`        | CET                 | -                | Custom experimental generator.            |
| `Lcg64`        | LCG                 | $m$              | Linear Congruential Generator.            |

### Other (`urng::rng128`)


- `Xorshift128`: 128-bit state Xorshift, implements `Rng32` (outputs `u32`).

## Usage Examples


### Basic Usage


```rust
use urng::rng64::{Xoshiro256Pp, SplitMix64};
use urng::rng::Rng64; // Import trait for common methods

fn main() {
    // 1. Initialize with a seed
    let mut rng = Xoshiro256Pp::new(12345);

    // 2. Generate random numbers
    let val_u64 = rng.nextu();
    println!("u64: {}", val_u64);

    let val_f64 = rng.nextf(); // [0.0, 1.0)
    println!("f64: {}", val_f64);

    // 3. Generate within a range
    let val_range = rng.randi(1, 100);
    println!("Integer (1-100): {}", val_range);

    // 4. Seeding with SplitMix64 (common pattern)
    // If you need to seed a large state generator from a single u64
    let mut sm = SplitMix64::new(9999);
    let seed_val = sm.nextu();
    let mut rng2 = Xoshiro256Pp::new(seed_val);
}
```

### Weighted Choice (BST)


The crate includes a binary-search-tree based weighted selector for efficient sampling.

```rust
use urng::bst::choice;
use urng::rng64::Xoshiro256Pp;

fn main() {
    let mut rng = Xoshiro256Pp::new(42);
    let items = vec!["Common", "Rare", "Epic"];
    let weights = vec![100.0, 10.0, 1.0];

    // Select an item based on weights
    if let Some(item) = choice(&mut rng, weights, &items) {
        println!("You got: {}", item);
    }
}
```

### Using Macros


For convenience, you can use the provided macros (must import `urng::*`).
These macros automatically initialize the generator with a system-seeded state.

```rust
use urng::{next, rand}; // Import macros

fn main() {
    // next! generates a single random number
    // Format: [algorithm][bits][u/f]
    let u = next!(mt64u); // Returns u64 using Mersenne Twister 64
    let f = next!(xor32f); // Returns f32 using Xorshift 32

    // rand! generates a number within a range
    // Format: [algorithm][bits][i/f]; [min], [max]
    let r = rand!(xor32i; 1, 10); // Returns i32 in range [1, 10]
    let f2 = rand!(mt64f; 0.0, 1.0); // Returns f64 in range [0.0, 1.0)
}
```

## C API


This crate exports a C-compatible FFI generic interface. Each generator has corresponding:

- `_new`
- `_free`
- `_next_uXXs` (bulk generation)
- `_next_fXXs` (bulk generation)

Example for `Mt19937`:

```c
void* mt19937_new(uint32_t seed, size_t warm);
void mt19937_next_u32s(void* ptr, uint32_t* out, size_t count);
void mt19937_free(void* ptr);
```