# @tiptap/math@0.1.0

<!-- Generated by scripts/gen-package-reference.mts from the package source.
     Do not edit: §15.4 — package docs are generated, nobody writes them. -->

**Spec §7.1: `@tiptap/math`** — the arithmetic everything else stands on.

Mostly a facade. §7.1 gives the source as `sim-core`, and that is right: the
fixed-point type, the vector, the angle and the lattice snapping already exist
and are already correct. Copying them here to make the package look
substantial would recreate the exact duplication §7 exists to remove.

So this re-exports, and adds the one thing on §7.1's line that did not exist
anywhere: **a seeded RNG**.

## Why the randomness has to live here

A creator needs random numbers — spawn points, loot, a shuffled deck, a
critical hit. Every ambient source of them is a desync:

| Tempting | What happens |
|---|---|
| `Math.random()` | Two clients draw different numbers; the room is in two states inside a second |
| seeding from the clock | The same, one tick later |
| hash-map iteration order | The same, non-reproducibly, which is worse |

[`Rng`] is the supported answer: **explicit state, integer arithmetic, no
ambient entropy anywhere in it.** Seed it from something both clients already
agree on — the match seed, the tick, an entity id — and both get the same
sequence.

Under rollback that matters twice over. A re-simulated tick must draw the
*same* numbers it drew the first time, and the only way to guarantee that is
for the generator's state to be part of the game state, so rewinding the
world rewinds the dice with it. That is why [`Rng::state`] is public and why
the whole generator is one `u64`.

## Types

```rust
pub struct Rng
```

A seeded, deterministic pseudo-random generator.

SplitMix64, chosen for three properties rather than for statistical quality
(which is far better than a game needs):

- **One `u64` of state and nothing else**, so a creator keeps it in game state
and rollback rewinds it for free.
- **No float step and no multiply-high**, so two platforms cannot round it
apart — the same requirement §13.6 puts on everything else here.
- **Every seed is as good as any other**, so `Rng::new(tick)` is safe. A
linear congruential generator would give visibly correlated sequences for
consecutive seeds, and `new(tick)` is the first thing anybody writes.

Not cryptographic. Nothing here should be used to hide information from a
player — that is §3's `private` mode's job.

## Functions

```rust
pub const fn state(&self) -> u64
```

The raw state, so it can be stored in game state and rolled back with it.

```rust
pub fn below(&mut self, n: u64) -> u64
```

Uniform in `0..n`, **without modulo bias**.

The obvious `next % n` is skewed whenever `n` does not divide `2^64`, and
the skew is toward the low values — so a nine-sided loot table drops its
first item measurably more often than its last. Rejection sampling costs
an occasional extra draw and removes it.

```rust
pub fn range(&mut self, lo: i64, hi: i64) -> i64
```

Inclusive on both ends.

`lo > hi` yields `lo` rather than panicking — §11.5, and the bounds may be
creator arithmetic that went somewhere unexpected.

```rust
pub fn chance(&mut self, numerator: u64, denominator: u64) -> bool
```

`true` with probability `numerator / denominator`.

```rust
pub fn unit(&mut self) -> Fixed
```

A `Fixed` in `[0, 1)`.

```rust
pub fn shuffle<T>(&mut self, items: &mut [T])
```

Shuffle in place — Fisher-Yates, which is the one that is actually
uniform.

The `for i in 0..n { swap(i, rand(0..n)) }` version people write from
memory produces `n^n` equally likely outcomes over `n!` permutations, so
some orderings are strictly more common. A card player eventually notices.
