# SPDX-FileCopyrightText: 2024 Marco Ricci <software@the13thletter.info>
#
# SPDX-License-Identifier: MIT
"""A Python reimplementation of James Coglan's "sequin" Node.js module.
James Coglan's "sequin" Node.js module provides a pseudorandom number
generator (using rejection sampling on a stream of input numbers) that
attempts to minimize the amount of information it throws away:
(non-degenerate) rejected samples are fed into a stream of higher-order
numbers from which the next random number generation request will be
served. The sequin module is used in Coglan's "vault" module (a
deterministic, stateless password manager that recomputes passwords
instead of storing them), and this reimplementation is used for
a similar purpose.
The main API is the [`Sequin`] [derivepassphrase.sequin.Sequin] class,
which is thoroughly documented.
"""
# ruff: noqa: RUF002,RUF003
from __future__ import annotations
import collections
from typing import TYPE_CHECKING
from typing_extensions import assert_type
if TYPE_CHECKING:
from collections.abc import Iterator, Sequence
__all__ = ('Sequin', 'SequinExhaustedError')
__author__ = 'Marco Ricci <software@the13thletter.info>'
class Sequin:
"""Generate pseudorandom non-negative numbers in different ranges.
Given a (presumed high-quality) uniformly random sequence of input
bits, generate pseudorandom non-negative integers in a certain range
on each call of the `generate` method. (It is permissible to
specify a different range per call to `generate`; this is the main
use case.) We use a modified version of rejection sampling, where
rejected values are stored in "rejection queues" if possible, and
these rejection queues re-seed the next round of rejection sampling.
This is a Python reimplementation of James Coglan's [Node.js sequin
module][JS_SEQUIN], as introduced in [his blog post][BLOG_POST]. It
uses a [technique by Christian Lawson-Perfect][SEQUIN_TECHNIQUE].