From 6113eb5b2ef1194183655aba9d31520a4f461a3f Mon Sep 17 00:00:00 2001 From: "Harlow, Jordan" Date: Wed, 7 Oct 2026 12:46:21 -0600 Subject: [PATCH 1/4] task: agent ready prep --- .github/AGENTS.md | 19 ++++ .github/ISSUE_TEMPLATE/bug_report.yml | 66 +++++++++++ .github/ISSUE_TEMPLATE/config.yml | 8 ++ .github/ISSUE_TEMPLATE/feature_request.yml | 38 +++++++ .github/pull_request_template.md | 27 +++++ .gitignore | 9 ++ AGENTS.md | 60 ++++++++++ CONTRIBUTING.md | 122 +++++++++++++++++++++ README.md | 7 ++ SECURITY.md | 12 ++ benchmarks/AGENTS.md | 22 ++++ conda-recipe-cf/AGENTS.md | 14 +++ conda-recipe/AGENTS.md | 15 +++ docs/AGENTS.md | 17 +++ docs/source/maintenance/index.rst | 17 ++- meson.build | 3 +- mkl_random/AGENTS.md | 28 +++++ mkl_random/interfaces/AGENTS.md | 13 +++ mkl_random/src/AGENTS.md | 18 +++ mkl_random/tests/AGENTS.md | 21 ++++ 20 files changed, 530 insertions(+), 6 deletions(-) create mode 100644 .github/AGENTS.md create mode 100644 .github/ISSUE_TEMPLATE/bug_report.yml create mode 100644 .github/ISSUE_TEMPLATE/config.yml create mode 100644 .github/ISSUE_TEMPLATE/feature_request.yml create mode 100644 .github/pull_request_template.md create mode 100644 AGENTS.md create mode 100644 CONTRIBUTING.md create mode 100644 SECURITY.md create mode 100644 benchmarks/AGENTS.md create mode 100644 conda-recipe-cf/AGENTS.md create mode 100644 conda-recipe/AGENTS.md create mode 100644 docs/AGENTS.md create mode 100644 mkl_random/AGENTS.md create mode 100644 mkl_random/interfaces/AGENTS.md create mode 100644 mkl_random/src/AGENTS.md create mode 100644 mkl_random/tests/AGENTS.md diff --git a/.github/AGENTS.md b/.github/AGENTS.md new file mode 100644 index 00000000..19d0a307 --- /dev/null +++ b/.github/AGENTS.md @@ -0,0 +1,19 @@ +# AGENTS.md — .github/ + +CI/CD workflows and repo automation. + +## Workflows (source of truth) +- `conda-package.yml` — Intel-channel conda build and test +- `conda-package-cf.yml` — conda-forge conda build and test +- `build_pip.yml` — editable pip build, including pre-release NumPy +- `build-with-clang.yml` — build with `icx`/`icpx` from the oneAPI apt repository +- `build-with-standard-clang.yml` — build with upstream clang +- `build-docs.yml` — Sphinx build; publishes to `gh-pages` from `master` +- `pre-commit.yml` — lint/format checks +- `coverity.yml` — Coverity static analysis (see `coverity/README.md`) +- `openssf-scorecard.yml` — OpenSSF Scorecard +- `zizmor.yml` — GitHub Actions security lint + +## Policy +- Treat workflow YAML as canonical for platform/Python matrices. +- Avoid doc claims about CI coverage unless present in workflow config. diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml new file mode 100644 index 00000000..d9a64c6b --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug_report.yml @@ -0,0 +1,66 @@ +name: Bug report +description: Report incorrect results, a crash, or a build failure +labels: ["bug"] +body: + - type: markdown + attributes: + value: | + For security vulnerabilities, do not open an issue — follow + [SECURITY.md](https://github.com/IntelPython/mkl_random/blob/master/SECURITY.md). + + - type: textarea + id: description + attributes: + label: Description + description: What happened, and what did you expect instead? + validations: + required: true + + - type: textarea + id: reproducer + attributes: + label: Reproducer + description: | + A minimal, self-contained snippet. Include the seed, the `brng`, the + distribution and its arguments, and `size`. + render: python + validations: + required: true + + - type: dropdown + id: install-source + attributes: + label: How was `mkl_random` installed? + options: + - Intel conda channel (software.repos.intel.com) + - conda-forge + - pip, Intel index (software.repos.intel.com) + - pip / PyPI + - Built from source + validations: + required: true + + - type: textarea + id: versions + attributes: + label: Versions + description: | + Output of: + ``` + python -c "import mkl_random, numpy; print(mkl_random.__version__); print(numpy.__version__)" + ``` + Add your OS and Python version too. + render: shell + validations: + required: true + + - type: textarea + id: notes + attributes: + label: Anything else + description: | + Optional. Whether NumPy patching was active (`mkl_random.is_patched()`), + whether you used `mkl_random.interfaces.numpy_random`, or a non-default + `MKL_NUM_THREADS`. + validations: + required: false diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml new file mode 100644 index 00000000..378931b5 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -0,0 +1,8 @@ +blank_issues_enabled: true +contact_links: + - name: Security vulnerability + url: https://www.intel.com/content/www/us/en/security-center/vulnerability-handling-guidelines.html + about: Report security vulnerabilities through Intel's process, not a public issue. + - name: Question about usage + url: https://intelpython.github.io/mkl_random/ + about: Check the documentation and README first. diff --git a/.github/ISSUE_TEMPLATE/feature_request.yml b/.github/ISSUE_TEMPLATE/feature_request.yml new file mode 100644 index 00000000..393e3d87 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/feature_request.yml @@ -0,0 +1,38 @@ +name: Feature request +description: Propose a new distribution, generator, or capability +labels: ["enhancement"] +body: + - type: textarea + id: problem + attributes: + label: What problem does this solve? + description: The use case, not the implementation. + validations: + required: true + + - type: textarea + id: proposal + attributes: + label: Proposal + description: | + What you would like `mkl_random` to do. If it mirrors a legacy + `numpy.random` function, name it — its signature is the contract for + the NumPy interface. + validations: + required: true + + - type: input + id: upstream + attributes: + label: Upstream equivalent + description: Link to the NumPy or oneMKL docs for the equivalent, if there is one. + validations: + required: false + + - type: textarea + id: alternatives + attributes: + label: Alternatives considered + description: Optional. Workarounds you are using today. + validations: + required: false diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md new file mode 100644 index 00000000..f049f55e --- /dev/null +++ b/.github/pull_request_template.md @@ -0,0 +1,27 @@ +# Description + + + +## Verification + + + +- Tests: +- Lint: + +## Not verified + + + +## Checklist + +- [ ] Legacy `numpy.random` API compatibility preserved, or the break is intentional and called out above. +- [ ] Seeded output is unchanged, or the `CHANGELOG.md` entry says which streams changed. +- [ ] Behavior changes have tests in `mkl_random/tests/`; bug fixes have a regression test. +- [ ] `CHANGELOG.md` updated under `[dev]` with a `[gh-NNN]` link, or the change isn't user-visible. + + diff --git a/.gitignore b/.gitignore index bd23b381..3318944d 100644 --- a/.gitignore +++ b/.gitignore @@ -9,5 +9,14 @@ mkl_random/mklrand.cpp # Byte-compiled / optimized / DLL files __pycache__/ +# Virtual environments, test caches, local env files +.venv/ +venv/ +.pytest_cache/ +.env + # ASV benchmark artifacts .asv/ + +# Developer-local coding agent settings +.claude/settings.local.json diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 00000000..a9e70fe6 --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,60 @@ +# AGENTS.md — mkl_random + +Entry point for agent context in this repo. + +## What this project is +`mkl_random` is a NumPy-based interface to Intel® oneMKL random number +generation. `MKLRandomState` exposes the distributions of legacy +`numpy.random.RandomState` with a choice of MKL basic generators (`brng`). +`mkl_random.interfaces.numpy_random` is a drop-in replacement for legacy +`numpy.random`, and runtime patching can install it in NumPy's place. + +## Key components +- **Package and public API:** `mkl_random/`, `mkl_random/__init__.py` +- **Cython extension:** `mkl_random/mklrand.pyx` +- **C++ kernels:** `mkl_random/src/` +- **NumPy interface:** `mkl_random/interfaces/` +- **Patching:** `_patch_numpy.py`, plus persistent and one-shot patching in + `patch.py`, `with_patch.py`, `_patch_startup.py`, and the `__main__.py` CLI +- **Tests:** `mkl_random/tests/` +- **Docs:** `docs/` (Sphinx) +- **Packaging:** `conda-recipe/`, `conda-recipe-cf/` +- **Benchmarks:** `benchmarks/` + +## Build/runtime basics +- Build system: `pyproject.toml` + `meson.build` +- Build deps: `mkl-devel`, `numpy`, `meson-python`, `cmake`, `ninja`, `cython`, + and a C++ compiler +- Runtime deps: `numpy`; the conda recipes add MKL +- Setup, checks, and style: `CONTRIBUTING.md` +- Single test: `pytest mkl_random/tests/::` +- Single-file lint: `pre-commit run --files ` + +## Development guardrails +- Keep signatures and accepted arguments compatible with legacy `numpy.random`. +- Seeded output is part of the contract: a change to what a fixed seed + produces needs a CHANGELOG entry naming the affected streams. +- Edit `mklrand.pyx` and `src/`, not the Cython-generated C++. +- Keep patching reversible, with `is_patched()` reporting the truth. +- Keep the extension free-threading compatible. +- Pair behavior changes with tests and keep diffs minimal. +- Avoid hardcoding mutable versions/matrices/channels in docs. + +## Where truth lives +- Build/config: `pyproject.toml`, `meson.build` +- Dependencies: `pyproject.toml`, `conda-recipe*/meta.yaml` +- CI/workflows: `.github/workflows/*.yml` +- Public API: `mkl_random/__init__.py`, `mkl_random/interfaces/numpy_random.py` +- Tests: `mkl_random/tests/` + +## Directory map +Use nearest local `AGENTS.md` when present: +- `.github/AGENTS.md` — CI workflows and automation policy +- `mkl_random/AGENTS.md` — package modules, the extension, and generators +- `mkl_random/src/AGENTS.md` — C++ kernels +- `mkl_random/interfaces/AGENTS.md` — `numpy.random` drop-in interface +- `mkl_random/tests/AGENTS.md` — test scope and conventions +- `docs/AGENTS.md` — Sphinx documentation +- `conda-recipe/AGENTS.md` — Intel-channel conda packaging +- `conda-recipe-cf/AGENTS.md` — conda-forge recipe +- `benchmarks/AGENTS.md` — ASV performance suite diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 00000000..cba92861 --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,122 @@ +# Contributing to `mkl_random` + +This document covers the development workflow: how to get a working build, how +to run the checks, and what to include in a pull request. + +For end-user installation and usage, see [README.md](README.md) and the +[documentation](https://intelpython.github.io/mkl_random/). For a map of the +source tree, see [`AGENTS.md`](AGENTS.md), which links to the local `AGENTS.md` +files in directories that have their own rules. Security vulnerabilities go +through the process in [SECURITY.md](SECURITY.md). + +--- + +## Development setup + +Building requires a C++ compiler, oneMKL headers and libraries (`mkl-devel`), +and NumPy. CI builds with `g++`, upstream `clang++`, and Intel `icpx`. A conda +environment is the least surprising way to get the rest: + +```sh +# add python=X.Y to target a specific interpreter +conda create -n mkl_random-dev -c conda-forge --override-channels python pip \ + mkl-devel numpy meson-python ninja cmake "cython>=3.1.0" pytest +conda activate mkl_random-dev +``` + +Then build in place, which reuses the environment's MKL and NumPy: + +```sh +pip install -e . --no-build-isolation --no-deps --verbose +``` + +`pyproject.toml` defines the supported Python range, and `.github/workflows/` is +canonical for the versions CI covers. `README.md` documents the non-editable +install paths. + +### Rebuilding + +`meson-python` rebuilds the extension on import for editable installs, so +editing `mklrand.pyx`, `src/`, or `meson.build` and rerunning `pytest` is +usually enough. The Cython-generated C++ and the compiled extension live under +`build//` rather than in the source tree. If a build gets into a bad state, +`rm -rf build` and reinstall. + +## Running the checks + +```sh +pytest mkl_random/tests # test suite +pre-commit run --all-files # lint and format hooks +``` + +To run a single test, use `pytest mkl_random/tests/::`; to lint one +file, `pre-commit run --files `. + +Install the hooks once with `pre-commit install` and they run on each commit. +`.pre-commit-config.yaml` is the source of truth for the tooling. + +To build the documentation, install `sphinx`, `furo`, `sphinx-design`, and +`sphinxcontrib-programoutput`, then run +`sphinx-build -M html docs/source docs/build`. + +Opening a pull request also runs CI, which builds and tests the package across +platforms and Python versions, builds the documentation, and runs various lint +and static-analysis checks. + +## Code style + +Style is loose, and the pre-commit hooks enforce most of it: + +- Python is formatted with `black` and `isort`, with a line length of 80. +- Cython is not touched by `black`. `isort` sorts its imports, `cython-lint` + checks it against the same 80-column limit, and string literals use double + quotes. +- C++ sources follow the repository's `.clang-format`. +- Otherwise, match the surrounding code. + +## Dos and don'ts + +**Do** + +- Keep changes atomic and single-purpose. +- Keep signatures and accepted arguments compatible with legacy `numpy.random`. + `mkl_random.interfaces.numpy_random` and patching make this package a drop-in + replacement. Call out an intentional break in the PR. +- Treat seeded output as part of the API. If a change alters what a fixed seed + produces, say which streams changed in the `CHANGELOG.md` entry. +- Add tests in `mkl_random/tests/` alongside behavior changes, and a regression + test with every bug fix. +- Seed every generator a test uses, so tests stay deterministic. +- Keep patching reversible and observable: anything installed can be + uninstalled, and `is_patched()` reports the truth. +- Keep the extension free-threading compatible. +- Cite the source-of-truth file for mutable details: `pyproject.toml`, + `meson.build`, `conda-recipe*/meta.yaml`, `.github/workflows/`. +- Give benchmark numbers reproducible context — hardware, versions, and the + command you ran. + +**Don't** + +- Commit generated artifacts, or hand-edit Cython-generated C++. +- Hardcode versions, build flags, CI matrices, or channel URLs in documentation. +- Assert on timing or throughput in the test suite. +- Introduce ISA-specific assumptions outside explicit build configuration. + +## Submitting a change + +Work on a branch: the `no-commit-to-branch` hook blocks direct commits to +`master` and `maintenance/*`. + +If the change is user-visible — behavior, API, seeded output, packaging, or +build output — add a `CHANGELOG.md` entry under the `[dev]` heading in the +matching section, with a +`[gh-NNN](https://github.com/IntelPython/mkl_random/pull/NNN)` link. The format +follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/) and the project +follows [Semantic Versioning](https://semver.org/spec/v2.0.0.html). Docs, +tooling, and CI-only changes are usually left out. + +Then open the PR and fill in the template, including what you verified locally +and what you left to CI. + +By contributing you agree that your contributions are licensed under the +BSD-3-Clause terms in [LICENSE.txt](LICENSE.txt). diff --git a/README.md b/README.md index ce6d04ba..9ed65604 100644 --- a/README.md +++ b/README.md @@ -158,3 +158,10 @@ then build against the existing installation with: ```sh python -m pip install --no-build-isolation --no-deps . ``` + +--- +# Contributing + +See [CONTRIBUTING.md](CONTRIBUTING.md) for the development workflow: setting up a +build environment, running the tests and lint hooks, code style, and what to +include in a pull request. diff --git a/SECURITY.md b/SECURITY.md new file mode 100644 index 00000000..556938bd --- /dev/null +++ b/SECURITY.md @@ -0,0 +1,12 @@ +# Security Policy + +## Report a Vulnerability + +Please report security issues or vulnerabilities to the [Intel® Security Center]. + +For more information on how Intel® works to resolve security issues, see +[Vulnerability Handling Guidelines]. + +[Intel® Security Center]:https://www.intel.com/content/www/us/en/security-center/default.html + +[Vulnerability Handling Guidelines]:https://www.intel.com/content/www/us/en/security-center/vulnerability-handling-guidelines.html diff --git a/benchmarks/AGENTS.md b/benchmarks/AGENTS.md new file mode 100644 index 00000000..335563e0 --- /dev/null +++ b/benchmarks/AGENTS.md @@ -0,0 +1,22 @@ +# AGENTS.md — benchmarks/ + +ASV performance suite for `mkl_random`. + +## Scope +- `asv.conf.json` — ASV configuration, channels, and regression thresholds +- `benchmarks/` — benchmark modules plus shared helpers in `_utils.py` +- `README.md` — coverage table, threading default, measurement notes, and run + commands + +## Guardrails +- Treat `asv.conf.json` as canonical for ASV settings; treat `README.md` as + canonical for what each module covers and how measurements are taken. +- Comparability across machines depends on the thread default in + `benchmarks/__init__.py`, the fixed seeds, and the warmup calls in the timing + benchmarks' `setup`. Changing any of them invalidates comparison against + existing results — call it out explicitly. +- Follow the engine and `method=` restrictions in `README.md` when adding + benchmarks. +- Report performance numbers with reproducible context: hardware, thread count, + versions, and the command used. +- Results under `benchmarks/.asv/` are local artifacts. diff --git a/conda-recipe-cf/AGENTS.md b/conda-recipe-cf/AGENTS.md new file mode 100644 index 00000000..d1603dfb --- /dev/null +++ b/conda-recipe-cf/AGENTS.md @@ -0,0 +1,14 @@ +# AGENTS.md — conda-recipe-cf/ + +conda-forge variant of the conda recipe. + +## Differences from `conda-recipe/` +- Installs with `pip install` directly; no wheel build or retag +- Pins NumPy with `pin_compatible` at run time and runs `pip check` in the + package test +- Adds macOS compiler entries to `conda_build_config.yaml` + +## Guardrails +- Keep conda-forge recipe semantics separate from the Intel-channel recipe. +- Keep changes in step with `.github/workflows/conda-package-cf.yml`, which + builds and tests this recipe. diff --git a/conda-recipe/AGENTS.md b/conda-recipe/AGENTS.md new file mode 100644 index 00000000..97e7fa37 --- /dev/null +++ b/conda-recipe/AGENTS.md @@ -0,0 +1,15 @@ +# AGENTS.md — conda-recipe/ + +Intel-channel conda packaging. + +## Files +- `meta.yaml` — package metadata, dependencies, and the package test + (`pytest --pyargs mkl_random`) +- `build.sh` / `bld.bat` — build a wheel with `python -m build`, then install + it; `build.sh` also retags the wheel's platform +- `conda_build_config.yaml` — compiler and C library pins + +## Guardrails +- Treat recipe files as canonical for packaging intent and dependency pins. +- Keep recipe changes in step with `.github/workflows/conda-package.yml`, which + builds and tests this recipe. diff --git a/docs/AGENTS.md b/docs/AGENTS.md new file mode 100644 index 00000000..dfd1b96a --- /dev/null +++ b/docs/AGENTS.md @@ -0,0 +1,17 @@ +# AGENTS.md — docs/ + +Sphinx sources for the published documentation. + +## Scope +- `source/` — pages; `source/conf.py` — Sphinx configuration +- `source/reference/` — API reference, with one page per basic generator +- `source/maintenance/index.rst` — the contributor page; keep its commands in + step with `CONTRIBUTING.md` + +## Guardrails +- `release` in `source/conf.py` is set by hand; keep it equal to + `mkl_random/_version.py`. +- Build locally with `sphinx-build -M html docs/source docs/build` before + changing `conf.py` or adding extensions. +- `.github/workflows/build-docs.yml` builds the docs on pull requests (as an + artifact) and publishes them to `gh-pages` on pushes to `master`. diff --git a/docs/source/maintenance/index.rst b/docs/source/maintenance/index.rst index e54b6574..ba2b1347 100644 --- a/docs/source/maintenance/index.rst +++ b/docs/source/maintenance/index.rst @@ -1,7 +1,7 @@ Contributing ============ -:mod:`mkl_random` is an free and open source project. +:mod:`mkl_random` is a free and open source project. We welcome and appreciate your contributions. To contribute, fork the repo https://github.com/IntelPython/mkl_random.git, @@ -32,20 +32,27 @@ package and located through CMake, so no environment variable needs to be set. .. code-block:: bash :caption: Building mkl_random - python -m pip install . --no-build-isolation --no-deps + python -m pip install -e . --no-build-isolation --no-deps -To run test suite, install :mod:`pytest`, and run +The editable (``-e``) install builds the extension in place, so the test suite +below runs against it from the repository root. + +To run the test suite, install :mod:`pytest`, and run .. code-block:: bash :caption: Running mkl_random test suite python -m pytest mkl_random/tests -To build documentation, install dependencies and running +To build documentation, install :mod:`sphinx`, :mod:`furo`, :mod:`sphinx-design`, +and :mod:`sphinxcontrib-programoutput`, and run .. code-block:: bash :caption: Building mkl_random documentation - $ sphinx-build -M html docs/source docs/build + sphinx-build -M html docs/source docs/build Rendered documentation can be found in "docs/build/html". + +For code style, the pre-commit hooks, and what to include in a pull request, +see ``CONTRIBUTING.md`` in the repository. diff --git a/meson.build b/meson.build index 2ff5a1c1..b076ad55 100644 --- a/meson.build +++ b/meson.build @@ -111,5 +111,6 @@ py.install_sources( install_subdir( 'mkl_random/tests', - install_dir: py.get_install_dir() / 'mkl_random' + install_dir: py.get_install_dir() / 'mkl_random', + exclude_files: ['AGENTS.md'] ) diff --git a/mkl_random/AGENTS.md b/mkl_random/AGENTS.md new file mode 100644 index 00000000..4c4f81c7 --- /dev/null +++ b/mkl_random/AGENTS.md @@ -0,0 +1,28 @@ +# AGENTS.md — mkl_random/ + +Package sources: the Cython extension, public API, and patching entry points. + +## Key files +- `mklrand.pyx` — the `mklrand` extension: `MKLRandomState`, the + distributions, and the basic-generator registry +- `__init__.py` — public API surface +- `_patch_numpy.py` — `patch_numpy_random()`, `restore_numpy_random()`, + `is_patched()`, and the `mkl_random()` context manager +- `patch.py`, `_patch_startup.py`, `with_patch.py`, `__main__.py` — persistent + (`.pth`) and one-shot patching behind `python -m mkl_random` +- `_version.py` — the version; `meson.build` reads it + +## Guardrails +- Use `MKLRandomState` for the MKL-specific API and + `interfaces.numpy_random.RandomState` for the NumPy drop-in in new code and + docs; `mkl_random.RandomState` is deprecated. +- Edit `mklrand.pyx`; Cython generates the C++ into the build directory. +- Adding a basic generator touches every registration point: the enum in + `src/randomkit.h` and its mirror in `mklrand.pyx`, `brng_list` in + `src/randomkit.cpp`, `_brng_dict` and `_brng_dict_stream_max` in + `mklrand.pyx`, the `brng` docstrings, the list in `README.md`, and a page + under `docs/source/reference/`. The enum value indexes `brng_list`, so keep + the order in sync. +- Keep `freethreading_compatible=True` in `mklrand.pyx`. +- New modules must be listed in `py.install_sources` in `meson.build`, or they + are not installed. diff --git a/mkl_random/interfaces/AGENTS.md b/mkl_random/interfaces/AGENTS.md new file mode 100644 index 00000000..d1fa1b44 --- /dev/null +++ b/mkl_random/interfaces/AGENTS.md @@ -0,0 +1,13 @@ +# AGENTS.md — mkl_random/interfaces/ + +Drop-in replacement for the legacy part of `numpy.random`. + +## Scope +- `numpy_random.py` — public module; `_numpy_random.py` — implementation +- `README.md` — the list of classes and functions the interface covers + +## Guardrails +- Legacy `numpy.random` signatures and semantics are the contract here. +- Keep `README.md` in sync when the covered set changes. +- Patching installs this interface in NumPy's place, so changes here reach + patched NumPy users too; cover them with tests in `mkl_random/tests/`. diff --git a/mkl_random/src/AGENTS.md b/mkl_random/src/AGENTS.md new file mode 100644 index 00000000..129af31e --- /dev/null +++ b/mkl_random/src/AGENTS.md @@ -0,0 +1,18 @@ +# AGENTS.md — mkl_random/src/ + +Hand-written C++11 kernels compiled into the `mklrand` extension. + +## Key files +- `randomkit.cpp`, `randomkit.h` — stream state and basic-generator setup + (`brng_list`) +- `mkl_distributions.cpp`, `mkl_distributions.h` — distribution kernels on MKL + VS +- `mklrand_py_helper.h` — Python/NumPy helpers for the extension +- `numpy_multiiter_workaround.h` — needed only to build against NumPy < 2.0 + (numpy/numpy#26990) + +## Guardrails +- Coordinate kernel changes with their callers in `mklrand.pyx`. +- A kernel change that alters what a fixed seed produces is user-visible; call + it out in the CHANGELOG. +- Keep code C++11; `meson.build` sets the standard. diff --git a/mkl_random/tests/AGENTS.md b/mkl_random/tests/AGENTS.md new file mode 100644 index 00000000..8bb77620 --- /dev/null +++ b/mkl_random/tests/AGENTS.md @@ -0,0 +1,21 @@ +# AGENTS.md — mkl_random/tests/ + +Test suite for the generators, the NumPy interface, and patching. +`meson.build` installs it with the package. + +## Files +- `test_random.py` — distributions and generators +- `test_patch.py` — patch and restore state +- `test_cli.py` — persistent patch install, uninstall, and status +- `test_freethreading.py` — concurrent use; the race tests run only on a + free-threaded build +- `third_party/` — tests adapted from NumPy's `numpy/random/tests` + +## Expectations +- Behavior changes include test updates in the same PR; bug fixes include a + regression test. +- Seed every generator a test uses, and keep tests free of timing assertions. + +## Entry points +- `pytest mkl_random/tests` from a checkout with an editable install +- `pytest --pyargs mkl_random` against an installed package From c9cb3e39cd6082a9ec5485d6d907f2820fbb5f65 Mon Sep 17 00:00:00 2001 From: "Harlow, Jordan" Date: Fri, 9 Oct 2026 07:21:52 -0600 Subject: [PATCH 2/4] task: clean up CONTRIBUTING.md --- CONTRIBUTING.md | 130 ++++++++++-------------------------------------- 1 file changed, 27 insertions(+), 103 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index cba92861..d43ecf9d 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,122 +1,46 @@ # Contributing to `mkl_random` -This document covers the development workflow: how to get a working build, how -to run the checks, and what to include in a pull request. +See [README.md](README.md) for usage, [AGENTS.md](AGENTS.md) for a map of the +source tree, and [SECURITY.md](SECURITY.md) to report a vulnerability. -For end-user installation and usage, see [README.md](README.md) and the -[documentation](https://intelpython.github.io/mkl_random/). For a map of the -source tree, see [`AGENTS.md`](AGENTS.md), which links to the local `AGENTS.md` -files in directories that have their own rules. Security vulnerabilities go -through the process in [SECURITY.md](SECURITY.md). +## Setup ---- - -## Development setup - -Building requires a C++ compiler, oneMKL headers and libraries (`mkl-devel`), -and NumPy. CI builds with `g++`, upstream `clang++`, and Intel `icpx`. A conda -environment is the least surprising way to get the rest: +Building needs a C++ compiler (`g++`, `clang++`, or `icpx`). ```sh -# add python=X.Y to target a specific interpreter -conda create -n mkl_random-dev -c conda-forge --override-channels python pip \ - mkl-devel numpy meson-python ninja cmake "cython>=3.1.0" pytest +conda create -n mkl_random-dev -c conda-forge python pip mkl-devel numpy \ + meson-python ninja cmake "cython>=3.1.0" pytest conda activate mkl_random-dev +pip install -e . --no-build-isolation --no-deps ``` -Then build in place, which reuses the environment's MKL and NumPy: - -```sh -pip install -e . --no-build-isolation --no-deps --verbose -``` - -`pyproject.toml` defines the supported Python range, and `.github/workflows/` is -canonical for the versions CI covers. `README.md` documents the non-editable -install paths. - -### Rebuilding - -`meson-python` rebuilds the extension on import for editable installs, so -editing `mklrand.pyx`, `src/`, or `meson.build` and rerunning `pytest` is -usually enough. The Cython-generated C++ and the compiled extension live under -`build//` rather than in the source tree. If a build gets into a bad state, -`rm -rf build` and reinstall. - -## Running the checks - -```sh -pytest mkl_random/tests # test suite -pre-commit run --all-files # lint and format hooks -``` - -To run a single test, use `pytest mkl_random/tests/::`; to lint one -file, `pre-commit run --files `. - -Install the hooks once with `pre-commit install` and they run on each commit. -`.pre-commit-config.yaml` is the source of truth for the tooling. - -To build the documentation, install `sphinx`, `furo`, `sphinx-design`, and +To build the docs, install `sphinx`, `furo`, `sphinx-design`, and `sphinxcontrib-programoutput`, then run `sphinx-build -M html docs/source docs/build`. -Opening a pull request also runs CI, which builds and tests the package across -platforms and Python versions, builds the documentation, and runs various lint -and static-analysis checks. - -## Code style - -Style is loose, and the pre-commit hooks enforce most of it: - -- Python is formatted with `black` and `isort`, with a line length of 80. -- Cython is not touched by `black`. `isort` sorts its imports, `cython-lint` - checks it against the same 80-column limit, and string literals use double - quotes. -- C++ sources follow the repository's `.clang-format`. -- Otherwise, match the surrounding code. +## Checks -## Dos and don'ts - -**Do** - -- Keep changes atomic and single-purpose. -- Keep signatures and accepted arguments compatible with legacy `numpy.random`. - `mkl_random.interfaces.numpy_random` and patching make this package a drop-in - replacement. Call out an intentional break in the PR. -- Treat seeded output as part of the API. If a change alters what a fixed seed - produces, say which streams changed in the `CHANGELOG.md` entry. -- Add tests in `mkl_random/tests/` alongside behavior changes, and a regression - test with every bug fix. -- Seed every generator a test uses, so tests stay deterministic. -- Keep patching reversible and observable: anything installed can be - uninstalled, and `is_patched()` reports the truth. -- Keep the extension free-threading compatible. -- Cite the source-of-truth file for mutable details: `pyproject.toml`, - `meson.build`, `conda-recipe*/meta.yaml`, `.github/workflows/`. -- Give benchmark numbers reproducible context — hardware, versions, and the - command you ran. - -**Don't** +```sh +pytest mkl_random/tests +pre-commit run --all-files +``` -- Commit generated artifacts, or hand-edit Cython-generated C++. -- Hardcode versions, build flags, CI matrices, or channel URLs in documentation. -- Assert on timing or throughput in the test suite. -- Introduce ISA-specific assumptions outside explicit build configuration. +The pre-commit hooks enforce formatting; otherwise, match the surrounding code. -## Submitting a change +## Guidelines -Work on a branch: the `no-commit-to-branch` hook blocks direct commits to -`master` and `maintenance/*`. +- Keep changes small and focused. +- Keep signatures compatible with legacy `numpy.random`. +- If a change alters what a fixed seed produces, say which streams changed in + the `CHANGELOG.md` entry. +- Add tests with behavior changes, and a regression test with bug fixes. Seed + every generator a test uses. +- Edit `mklrand.pyx` and `src/`, not generated C++. +- Keep patching reversible. -If the change is user-visible — behavior, API, seeded output, packaging, or -build output — add a `CHANGELOG.md` entry under the `[dev]` heading in the -matching section, with a -`[gh-NNN](https://github.com/IntelPython/mkl_random/pull/NNN)` link. The format -follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/) and the project -follows [Semantic Versioning](https://semver.org/spec/v2.0.0.html). Docs, -tooling, and CI-only changes are usually left out. +## Pull requests -Then open the PR and fill in the template, including what you verified locally -and what you left to CI. +Work on a branch and fill in the PR template. For user-visible changes, add a +`CHANGELOG.md` entry under `[dev]` with a `gh-NNN` link. -By contributing you agree that your contributions are licensed under the -BSD-3-Clause terms in [LICENSE.txt](LICENSE.txt). +Contributions are licensed under the terms in [LICENSE.txt](LICENSE.txt). From e1d971bb913521f08b11a4e1bcdc6a31a8e5f267 Mon Sep 17 00:00:00 2001 From: "Harlow, Jordan" Date: Mon, 26 Oct 2026 08:20:08 -0600 Subject: [PATCH 3/4] Address review: drop removed helper, add BRNG_KINDS, MSVC, lint deps Drop mklrand_py_helper.h from src/AGENTS.md (removed in gh-192), name BRNG_KINDS in the new-generator checklist, list MSVC as the Windows compiler, add pre-commit and pylint to the dev environment so the Checks section runs from it, and describe the meson-python editable install accurately. --- CONTRIBUTING.md | 4 ++-- docs/source/maintenance/index.rst | 8 +++++--- mkl_random/AGENTS.md | 3 ++- mkl_random/src/AGENTS.md | 1 - 4 files changed, 9 insertions(+), 7 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index d43ecf9d..f47e0d8f 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -5,11 +5,11 @@ source tree, and [SECURITY.md](SECURITY.md) to report a vulnerability. ## Setup -Building needs a C++ compiler (`g++`, `clang++`, or `icpx`). +Building needs a C++ compiler (`g++`, `clang++`, or `icpx`; MSVC on Windows). ```sh conda create -n mkl_random-dev -c conda-forge python pip mkl-devel numpy \ - meson-python ninja cmake "cython>=3.1.0" pytest + meson-python ninja cmake "cython>=3.1.0" pytest pre-commit pylint conda activate mkl_random-dev pip install -e . --no-build-isolation --no-deps ``` diff --git a/docs/source/maintenance/index.rst b/docs/source/maintenance/index.rst index ba2b1347..8dd6f0f6 100644 --- a/docs/source/maintenance/index.rst +++ b/docs/source/maintenance/index.rst @@ -14,7 +14,8 @@ clone it: A working compiler is needed to build :mod:`mkl_random`. -Gnu :code:`g++`, standard :code:`clang++`, and Intel LLVM :code:`icpx` are supported. +Gnu :code:`g++`, standard :code:`clang++`, Intel LLVM :code:`icpx`, and MSVC on +Windows are supported. Make sure to install Python packages required to build :mod:`mkl_random`: @@ -34,8 +35,9 @@ package and located through CMake, so no environment variable needs to be set. python -m pip install -e . --no-build-isolation --no-deps -The editable (``-e``) install builds the extension in place, so the test suite -below runs against it from the repository root. +The editable (``-e``) install makes the source tree importable and rebuilds the +extension on import, so the test suite below runs against it from the +repository root. To run the test suite, install :mod:`pytest`, and run diff --git a/mkl_random/AGENTS.md b/mkl_random/AGENTS.md index 4c4f81c7..87019773 100644 --- a/mkl_random/AGENTS.md +++ b/mkl_random/AGENTS.md @@ -18,7 +18,8 @@ Package sources: the Cython extension, public API, and patching entry points. docs; `mkl_random.RandomState` is deprecated. - Edit `mklrand.pyx`; Cython generates the C++ into the build directory. - Adding a basic generator touches every registration point: the enum in - `src/randomkit.h` and its mirror in `mklrand.pyx`, `brng_list` in + `src/randomkit.h` and its mirror in `mklrand.pyx`, the `BRNG_KINDS` count + in `src/randomkit.h` (it sizes `brng_list`), `brng_list` in `src/randomkit.cpp`, `_brng_dict` and `_brng_dict_stream_max` in `mklrand.pyx`, the `brng` docstrings, the list in `README.md`, and a page under `docs/source/reference/`. The enum value indexes `brng_list`, so keep diff --git a/mkl_random/src/AGENTS.md b/mkl_random/src/AGENTS.md index 129af31e..3bb36920 100644 --- a/mkl_random/src/AGENTS.md +++ b/mkl_random/src/AGENTS.md @@ -7,7 +7,6 @@ Hand-written C++11 kernels compiled into the `mklrand` extension. (`brng_list`) - `mkl_distributions.cpp`, `mkl_distributions.h` — distribution kernels on MKL VS -- `mklrand_py_helper.h` — Python/NumPy helpers for the extension - `numpy_multiiter_workaround.h` — needed only to build against NumPy < 2.0 (numpy/numpy#26990) From 7aad02b53eed3f8c877886083823e1757d3a66b9 Mon Sep 17 00:00:00 2001 From: "Harlow, Jordan" Date: Thu, 29 Oct 2026 10:07:57 -0600 Subject: [PATCH 4/4] Address review: setup env, generator checklist, issue forms Add a C compiler, --override-channels, and shellcheck to the setup, move "work on a branch" ahead of the checks, and mention pre-commit install and the first run's network use. Complete the new-generator checklist (tests, docs index and how_to, benchmarks, append order), name _init_helper.py, numpy_random.__all__, and the per-thread restore rule, and note that GitHub CI builds the recipes with --no-test. In the issue forms, keep paragraphs on one line, add "Other", the MKL version, and an optional log field. Also fix the stale randomkit.c reference in randomkit.h and the missing aliases in interfaces/README.md. --- .github/AGENTS.md | 21 +++++++++++-- .github/ISSUE_TEMPLATE/bug_report.yml | 24 +++++++++------ .github/ISSUE_TEMPLATE/feature_request.yml | 5 +-- .github/pull_request_template.md | 2 +- AGENTS.md | 20 ++++++++---- CONTRIBUTING.md | 28 +++++++++++++---- benchmarks/AGENTS.md | 2 +- conda-recipe-cf/AGENTS.md | 3 +- conda-recipe/AGENTS.md | 3 +- docs/source/maintenance/index.rst | 6 ++-- mkl_random/AGENTS.md | 36 ++++++++++++++++------ mkl_random/interfaces/AGENTS.md | 8 +++-- mkl_random/interfaces/README.md | 2 +- mkl_random/src/AGENTS.md | 2 ++ mkl_random/src/randomkit.h | 2 +- mkl_random/tests/AGENTS.md | 7 +++++ 16 files changed, 120 insertions(+), 51 deletions(-) diff --git a/.github/AGENTS.md b/.github/AGENTS.md index 19d0a307..e5bb1f46 100644 --- a/.github/AGENTS.md +++ b/.github/AGENTS.md @@ -5,15 +5,30 @@ CI/CD workflows and repo automation. ## Workflows (source of truth) - `conda-package.yml` — Intel-channel conda build and test - `conda-package-cf.yml` — conda-forge conda build and test -- `build_pip.yml` — editable pip build, including pre-release NumPy -- `build-with-clang.yml` — build with `icx`/`icpx` from the oneAPI apt repository -- `build-with-standard-clang.yml` — build with upstream clang +- `build_pip.yml` — editable pip build and test, including pre-release NumPy +- `build-with-clang.yml` — build and test with `icx`/`icpx` from the oneAPI apt + repository +- `build-with-standard-clang.yml` — build and test with Ubuntu's `clang` + package - `build-docs.yml` — Sphinx build; publishes to `gh-pages` from `master` - `pre-commit.yml` — lint/format checks - `coverity.yml` — Coverity static analysis (see `coverity/README.md`) - `openssf-scorecard.yml` — OpenSSF Scorecard - `zizmor.yml` — GitHub Actions security lint +The three pip workflows test the editable install: `build_pip.yml` runs +`pytest mkl_random/tests`, the clang workflows `pytest --pyargs mkl_random`. +The conda workflows build with `conda build --no-test` and run +`pytest --pyargs mkl_random` in separate test jobs on the built package. + +## Templates and config +- `pull_request_template.md` — PR description, verification, and checklist +- `ISSUE_TEMPLATE/` — bug report and feature request forms; `config.yml` adds + contact links that send security reports to Intel's vulnerability process + and usage questions to the docs +- `dependabot.yml` — update schedule for GitHub Actions and pre-commit hooks +- `CODEOWNERS` — default reviewers + ## Policy - Treat workflow YAML as canonical for platform/Python matrices. - Avoid doc claims about CI coverage unless present in workflow config. diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml index d9a64c6b..07149fc8 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.yml +++ b/.github/ISSUE_TEMPLATE/bug_report.yml @@ -5,8 +5,7 @@ body: - type: markdown attributes: value: | - For security vulnerabilities, do not open an issue — follow - [SECURITY.md](https://github.com/IntelPython/mkl_random/blob/master/SECURITY.md). + For security vulnerabilities, do not open an issue — follow [SECURITY.md](https://github.com/IntelPython/mkl_random/blob/master/SECURITY.md). - type: textarea id: description @@ -20,9 +19,7 @@ body: id: reproducer attributes: label: Reproducer - description: | - A minimal, self-contained snippet. Include the seed, the `brng`, the - distribution and its arguments, and `size`. + description: A minimal, self-contained snippet. Include the seed, the `brng`, the distribution and its arguments, and `size`. For a build failure, give the build command. render: python validations: required: true @@ -37,6 +34,7 @@ body: - pip, Intel index (software.repos.intel.com) - pip / PyPI - Built from source + - Other validations: required: true @@ -49,18 +47,24 @@ body: ``` python -c "import mkl_random, numpy; print(mkl_random.__version__); print(numpy.__version__)" ``` - Add your OS and Python version too. + Add the MKL version (`conda list mkl` or `pip list | grep -i mkl`), your OS, and your Python version too. If the build failed, give the NumPy and compiler versions instead. render: shell validations: required: true + - type: textarea + id: logs + attributes: + label: Error output or build log + description: Optional. The full traceback, or the build log for a build failure. + render: shell + validations: + required: false + - type: textarea id: notes attributes: label: Anything else - description: | - Optional. Whether NumPy patching was active (`mkl_random.is_patched()`), - whether you used `mkl_random.interfaces.numpy_random`, or a non-default - `MKL_NUM_THREADS`. + description: Optional. Whether NumPy patching was active (`mkl_random.is_patched()`), whether you used `mkl_random.interfaces.numpy_random`, or a non-default `MKL_NUM_THREADS`. validations: required: false diff --git a/.github/ISSUE_TEMPLATE/feature_request.yml b/.github/ISSUE_TEMPLATE/feature_request.yml index 393e3d87..a532f670 100644 --- a/.github/ISSUE_TEMPLATE/feature_request.yml +++ b/.github/ISSUE_TEMPLATE/feature_request.yml @@ -14,10 +14,7 @@ body: id: proposal attributes: label: Proposal - description: | - What you would like `mkl_random` to do. If it mirrors a legacy - `numpy.random` function, name it — its signature is the contract for - the NumPy interface. + description: What you would like `mkl_random` to do. If it mirrors a legacy `numpy.random` function, name it — its signature is the contract for the NumPy interface. validations: required: true diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md index f049f55e..f93592cc 100644 --- a/.github/pull_request_template.md +++ b/.github/pull_request_template.md @@ -22,6 +22,6 @@ relevant. - [ ] Legacy `numpy.random` API compatibility preserved, or the break is intentional and called out above. - [ ] Seeded output is unchanged, or the `CHANGELOG.md` entry says which streams changed. - [ ] Behavior changes have tests in `mkl_random/tests/`; bug fixes have a regression test. -- [ ] `CHANGELOG.md` updated under `[dev]` with a `[gh-NNN]` link, or the change isn't user-visible. +- [ ] `CHANGELOG.md` updated under `## [dev]` with a `[gh-NNN](https://github.com/IntelPython/mkl_random/pull/NNN)` link, or the change isn't user-visible. diff --git a/AGENTS.md b/AGENTS.md index a9e70fe6..17b29ffb 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -14,29 +14,37 @@ generation. `MKLRandomState` exposes the distributions of legacy - **Cython extension:** `mkl_random/mklrand.pyx` - **C++ kernels:** `mkl_random/src/` - **NumPy interface:** `mkl_random/interfaces/` -- **Patching:** `_patch_numpy.py`, plus persistent and one-shot patching in - `patch.py`, `with_patch.py`, `_patch_startup.py`, and the `__main__.py` CLI +- **Patching:** `mkl_random/_patch_numpy.py`, plus persistent and one-shot + patching in `mkl_random/patch.py`, `mkl_random/with_patch.py`, + `mkl_random/_patch_startup.py`, and the `mkl_random/__main__.py` CLI - **Tests:** `mkl_random/tests/` - **Docs:** `docs/` (Sphinx) - **Packaging:** `conda-recipe/`, `conda-recipe-cf/` - **Benchmarks:** `benchmarks/` +- **Examples:** `examples/` (parallel Monte Carlo with generator families) +- **Coverity:** `coverity/` (Coverity Scan triage guide) ## Build/runtime basics - Build system: `pyproject.toml` + `meson.build` - Build deps: `mkl-devel`, `numpy`, `meson-python`, `cmake`, `ninja`, `cython`, - and a C++ compiler + and C and C++ compilers - Runtime deps: `numpy`; the conda recipes add MKL - Setup, checks, and style: `CONTRIBUTING.md` -- Single test: `pytest mkl_random/tests/::` -- Single-file lint: `pre-commit run --files ` +- Single test: `pytest mkl_random/tests/.py::`, from the editable + install in `CONTRIBUTING.md` +- Single-file lint: `pre-commit run --files `, from a branch (see + `CONTRIBUTING.md`) ## Development guardrails - Keep signatures and accepted arguments compatible with legacy `numpy.random`. - Seeded output is part of the contract: a change to what a fixed seed produces needs a CHANGELOG entry naming the affected streams. -- Edit `mklrand.pyx` and `src/`, not the Cython-generated C++. +- Edit `mkl_random/mklrand.pyx` and `mkl_random/src/`, not the + Cython-generated C++. - Keep patching reversible, with `is_patched()` reporting the truth. - Keep the extension free-threading compatible. +- `meson.build` changes must keep both the GCC-syntax (Linux) and MSVC-syntax + (Windows) branches working; CI covers both. - Pair behavior changes with tests and keep diffs minimal. - Avoid hardcoding mutable versions/matrices/channels in docs. diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index f47e0d8f..f6093862 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -5,26 +5,41 @@ source tree, and [SECURITY.md](SECURITY.md) to report a vulnerability. ## Setup -Building needs a C++ compiler (`g++`, `clang++`, or `icpx`; MSVC on Windows). +Building needs C and C++ compilers (`gcc`/`g++`, `clang`/`clang++`, or +`icx`/`icpx`; MSVC on Windows). ```sh -conda create -n mkl_random-dev -c conda-forge python pip mkl-devel numpy \ - meson-python ninja cmake "cython>=3.1.0" pytest pre-commit pylint +conda create -n mkl_random-dev --override-channels -c conda-forge python pip \ + mkl-devel numpy meson-python ninja cmake "cython>=3.1.0" pytest \ + pre-commit pylint shellcheck conda activate mkl_random-dev pip install -e . --no-build-isolation --no-deps ``` +`--override-channels` keeps MKL from mixing with your configured channels. + To build the docs, install `sphinx`, `furo`, `sphinx-design`, and `sphinxcontrib-programoutput`, then run `sphinx-build -M html docs/source docs/build`. ## Checks +Work on a branch: on `master` or a `maintenance/*` branch, the +`no-commit-to-branch` hook makes `pre-commit run` fail. From the editable +install above: + ```sh pytest mkl_random/tests pre-commit run --all-files ``` +The editable install rebuilds the extension on import, and the `pylint` and +`shellcheck` hooks run the copies installed in the environment, so activate +`mkl_random-dev` first. The first run needs network access: pre-commit fetches +each hook, and builds `gitleaks` and `actionlint` from source with Go, +downloading a Go toolchain if none is on `PATH`. Run `pre-commit install` once +to run the hooks on each commit. + The pre-commit hooks enforce formatting; otherwise, match the surrounding code. ## Guidelines @@ -35,12 +50,13 @@ The pre-commit hooks enforce formatting; otherwise, match the surrounding code. the `CHANGELOG.md` entry. - Add tests with behavior changes, and a regression test with bug fixes. Seed every generator a test uses. -- Edit `mklrand.pyx` and `src/`, not generated C++. +- Edit `mkl_random/mklrand.pyx` and `mkl_random/src/`, not generated C++. - Keep patching reversible. ## Pull requests -Work on a branch and fill in the PR template. For user-visible changes, add a -`CHANGELOG.md` entry under `[dev]` with a `gh-NNN` link. +Fill in the PR template. For user-visible changes, add a `CHANGELOG.md` entry +under `## [dev]`, in the matching section, with a +`[gh-NNN](https://github.com/IntelPython/mkl_random/pull/NNN)` link. Contributions are licensed under the terms in [LICENSE.txt](LICENSE.txt). diff --git a/benchmarks/AGENTS.md b/benchmarks/AGENTS.md index 335563e0..cdadb1dd 100644 --- a/benchmarks/AGENTS.md +++ b/benchmarks/AGENTS.md @@ -19,4 +19,4 @@ ASV performance suite for `mkl_random`. benchmarks. - Report performance numbers with reproducible context: hardware, thread count, versions, and the command used. -- Results under `benchmarks/.asv/` are local artifacts. +- Results under `.asv/` are local artifacts. diff --git a/conda-recipe-cf/AGENTS.md b/conda-recipe-cf/AGENTS.md index d1603dfb..3ea587ea 100644 --- a/conda-recipe-cf/AGENTS.md +++ b/conda-recipe-cf/AGENTS.md @@ -5,7 +5,8 @@ conda-forge variant of the conda recipe. ## Differences from `conda-recipe/` - Installs with `pip install` directly; no wheel build or retag - Pins NumPy with `pin_compatible` at run time and runs `pip check` in the - package test + package test. `conda-package-cf.yml` builds with `--no-test`, so GitHub CI + doesn't run `pip check`. - Adds macOS compiler entries to `conda_build_config.yaml` ## Guardrails diff --git a/conda-recipe/AGENTS.md b/conda-recipe/AGENTS.md index 97e7fa37..5468edb3 100644 --- a/conda-recipe/AGENTS.md +++ b/conda-recipe/AGENTS.md @@ -4,7 +4,8 @@ Intel-channel conda packaging. ## Files - `meta.yaml` — package metadata, dependencies, and the package test - (`pytest --pyargs mkl_random`) + (`pytest --pyargs mkl_random`). `conda-package.yml` builds with `--no-test`, + so GitHub CI runs the same command in separate test jobs instead. - `build.sh` / `bld.bat` — build a wheel with `python -m build`, then install it; `build.sh` also retags the wheel's platform - `conda_build_config.yaml` — compiler and C library pins diff --git a/docs/source/maintenance/index.rst b/docs/source/maintenance/index.rst index 8dd6f0f6..d57cd523 100644 --- a/docs/source/maintenance/index.rst +++ b/docs/source/maintenance/index.rst @@ -13,9 +13,9 @@ clone it: git clone https://github.com//mkl_random.git -A working compiler is needed to build :mod:`mkl_random`. -Gnu :code:`g++`, standard :code:`clang++`, Intel LLVM :code:`icpx`, and MSVC on -Windows are supported. +Working C and C++ compilers are needed to build :mod:`mkl_random`. +GNU :code:`gcc`/:code:`g++`, standard :code:`clang`/:code:`clang++`, Intel LLVM +:code:`icx`/:code:`icpx`, and MSVC on Windows are supported. Make sure to install Python packages required to build :mod:`mkl_random`: diff --git a/mkl_random/AGENTS.md b/mkl_random/AGENTS.md index 87019773..2afe926e 100644 --- a/mkl_random/AGENTS.md +++ b/mkl_random/AGENTS.md @@ -6,6 +6,8 @@ Package sources: the Cython extension, public API, and patching entry points. - `mklrand.pyx` — the `mklrand` extension: `MKLRandomState`, the distributions, and the basic-generator registry - `__init__.py` — public API surface +- `_init_helper.py` — imported first by `__init__.py`; adds `Library/bin` to + the DLL search path in a Windows venv - `_patch_numpy.py` — `patch_numpy_random()`, `restore_numpy_random()`, `is_patched()`, and the `mkl_random()` context manager - `patch.py`, `_patch_startup.py`, `with_patch.py`, `__main__.py` — persistent @@ -15,15 +17,29 @@ Package sources: the Cython extension, public API, and patching entry points. ## Guardrails - Use `MKLRandomState` for the MKL-specific API and `interfaces.numpy_random.RandomState` for the NumPy drop-in in new code and - docs; `mkl_random.RandomState` is deprecated. + docs; `mkl_random.RandomState` is deprecated. The existing + `docs/source/reference/.rst` pages still use it, so don't copy that. - Edit `mklrand.pyx`; Cython generates the C++ into the build directory. -- Adding a basic generator touches every registration point: the enum in - `src/randomkit.h` and its mirror in `mklrand.pyx`, the `BRNG_KINDS` count - in `src/randomkit.h` (it sizes `brng_list`), `brng_list` in - `src/randomkit.cpp`, `_brng_dict` and `_brng_dict_stream_max` in - `mklrand.pyx`, the `brng` docstrings, the list in `README.md`, and a page - under `docs/source/reference/`. The enum value indexes `brng_list`, so keep - the order in sync. +- Append a new basic generator at the end of the enum: its value is the + integer `brng=` accepts (`0 <= brng < BRNG_KINDS`) and indexes `brng_list`. + Then update every registration point: + - the enum and `BRNG_KINDS` in `src/randomkit.h`, and the enum's mirror in + `mklrand.pyx` + - `brng_list` in `src/randomkit.cpp` + - `_brng_dict`, `_brng_dict_stream_max`, and the `brng` docstrings in + `mklrand.pyx` + - in `tests/test_random.py`: `_ALL_BRNGS`, the out-of-range id (`11`) in + `test_out_of_range_integer_brng_falls_back`, and the upper boundary in + `test_boundary_integer_brng_accepted` + - the generator list in the root `README.md` + - a new page under `docs/source/reference/`, plus the bullet list and + `toctree` in its `index.rst` + - the skip-ahead and leap-frog lists in `docs/source/how_to.rst`, if the + generator supports either + - `_ENGINES` in `benchmarks/benchmarks/_utils.py`, and `_ENGINES_BITS` if + the generator implements `viRngUniformBits32/64` - Keep `freethreading_compatible=True` in `mklrand.pyx`. -- New modules must be listed in `py.install_sources` in `meson.build`, or they - are not installed. +- New `mkl_random/*.py` and `interfaces/*.py` modules must be added to the + matching `py.install_sources` call in `meson.build`, or they are not + installed. `tests/` is installed by `install_subdir`; C++ files go in the + extension's `sources`. diff --git a/mkl_random/interfaces/AGENTS.md b/mkl_random/interfaces/AGENTS.md index d1fa1b44..81033803 100644 --- a/mkl_random/interfaces/AGENTS.md +++ b/mkl_random/interfaces/AGENTS.md @@ -3,11 +3,13 @@ Drop-in replacement for the legacy part of `numpy.random`. ## Scope -- `numpy_random.py` — public module; `_numpy_random.py` — implementation -- `README.md` — the list of classes and functions the interface covers +- `numpy_random.py` — public module; its `__all__` is the covered set, and + exactly what patching replaces (`_patch_numpy.py`) +- `_numpy_random.py` — implementation +- `README.md` — human-readable list of the covered classes and functions ## Guardrails - Legacy `numpy.random` signatures and semantics are the contract here. -- Keep `README.md` in sync when the covered set changes. +- Keep `README.md` in sync with `numpy_random.__all__`. - Patching installs this interface in NumPy's place, so changes here reach patched NumPy users too; cover them with tests in `mkl_random/tests/`. diff --git a/mkl_random/interfaces/README.md b/mkl_random/interfaces/README.md index 49452e29..9a54e1b0 100644 --- a/mkl_random/interfaces/README.md +++ b/mkl_random/interfaces/README.md @@ -11,7 +11,7 @@ This interface is a drop-in replacement for the legacy portion of the [`numpy.ra * seeding and state functions: `get_state`, `set_state`, and `seed`. -* simple random data: `rand`, `randn`, `randint`, `random_integers`, `random_sample`, `choice` and `bytes`. +* simple random data: `rand`, `randn`, `randint`, `random_integers`, `random_sample`, `random`, `ranf`, `sample`, `choice` and `bytes`. * permutations: `shuffle` and `permutation` diff --git a/mkl_random/src/AGENTS.md b/mkl_random/src/AGENTS.md index 3bb36920..f49d1fdf 100644 --- a/mkl_random/src/AGENTS.md +++ b/mkl_random/src/AGENTS.md @@ -15,3 +15,5 @@ Hand-written C++11 kernels compiled into the `mklrand` extension. - A kernel change that alters what a fixed seed produces is user-visible; call it out in the CHANGELOG. - Keep code C++11; `meson.build` sets the standard. +- List a new `.cpp` file in the `mklrand` extension's `sources` in + `meson.build`. diff --git a/mkl_random/src/randomkit.h b/mkl_random/src/randomkit.h index 965e00c9..66c8949e 100644 --- a/mkl_random/src/randomkit.h +++ b/mkl_random/src/randomkit.h @@ -47,7 +47,7 @@ typedef enum RK_ERR_MAX = 2 } irk_error; -/* if changing this, also adjust brng_list[BRNG_KINDS] in randomkit.c */ +/* if changing this, also adjust brng_list[BRNG_KINDS] in randomkit.cpp */ #define BRNG_KINDS 11 typedef enum diff --git a/mkl_random/tests/AGENTS.md b/mkl_random/tests/AGENTS.md index 8bb77620..5101f22f 100644 --- a/mkl_random/tests/AGENTS.md +++ b/mkl_random/tests/AGENTS.md @@ -15,6 +15,13 @@ Test suite for the generators, the NumPy interface, and patching. - Behavior changes include test updates in the same PR; bug fixes include a regression test. - Seed every generator a test uses, and keep tests free of timing assertions. +- Tests that patch NumPy restore it before returning, in the same thread + (`try`/`finally` or `with mkl_random.mkl_random():`). + `restore_numpy_random()` only balances a patch made in its own thread; in any + other thread it warns and does nothing. +- The suite assumes NumPy starts unpatched (`test_patch.py`, + `test_freethreading.py`); run `python -m mkl_random --patch uninstall` + first if the persistent patch is installed. ## Entry points - `pytest mkl_random/tests` from a checkout with an editable install