Skip to main content

CHANGELOG.md

# Changelog

## 0.1.1

### Changed

- `knot:uniform/1` spec tightened from `pos_integer() -> pos_integer()`
  to `1..4294967295 -> 1..4294967295`. The NIF's C-side argument is
  `enif_get_uint` (unsigned 32-bit), so values above `2^32 - 1` raise
  `badarg`. The previous spec lied — dialyzer now catches the
  out-of-range cases at compile time.

- Module and function docstrings (`@doc`) added — algorithm,
  per-thread state, lazy seeding, the bounded-output bias bound, and
  the `badarg` semantics for over-range inputs are now in the
  generated hexdocs without having to read `c_src/knot.c`.

No behavioural changes; no new code paths.

## 0.1.0

Initial release.

- `knot:uniform/1` — fast non-cryptographic PRNG NIF, drop-in
  replacement for `granderl:uniform/1`. Uses wyrand (1 multiply +
  1 xor + 1 add per draw, BigCrush-passing) with the biased
  multiply-and-shift bounded method (single multiply, no rejection
  branch; bias < 1e-7 for bounds ≤ 256).
- Pure C NIF — ~75 LOC. No Rust toolchain, no cargo, no rustler.
  Per-OS-thread state via `__thread`. Lazy seed from `getrandom`/
  `arc4random_buf`.
- Build via `c_src/build.sh` (granderl-style `pre_hooks`), with the
  OTP 27+ `erl -noshell -s init stop -eval` order bug fixed —
  `-eval` runs before init terminates.