fast-math-rs 0.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (39) hide show
  1. fast_math_rs-0.1.0/.github/workflows/ci.yml +108 -0
  2. fast_math_rs-0.1.0/.github/workflows/release.yml +86 -0
  3. fast_math_rs-0.1.0/.github/workflows/wheels.yml +99 -0
  4. fast_math_rs-0.1.0/.gitignore +20 -0
  5. fast_math_rs-0.1.0/CHANGELOG.md +26 -0
  6. fast_math_rs-0.1.0/Cargo.lock +132 -0
  7. fast_math_rs-0.1.0/Cargo.toml +42 -0
  8. fast_math_rs-0.1.0/GLOSSARY.md +51 -0
  9. fast_math_rs-0.1.0/LICENSE +21 -0
  10. fast_math_rs-0.1.0/Makefile +74 -0
  11. fast_math_rs-0.1.0/PKG-INFO +144 -0
  12. fast_math_rs-0.1.0/README.md +112 -0
  13. fast_math_rs-0.1.0/benchmarks/run.py +176 -0
  14. fast_math_rs-0.1.0/docs/benchmarks/py3.14-arm64.json +56 -0
  15. fast_math_rs-0.1.0/docs/benchmarks.md +44 -0
  16. fast_math_rs-0.1.0/docs/guide/development.md +61 -0
  17. fast_math_rs-0.1.0/docs/guide/semantics.md +90 -0
  18. fast_math_rs-0.1.0/pyproject.toml +119 -0
  19. fast_math_rs-0.1.0/python/fast_math/__init__.py +46 -0
  20. fast_math_rs-0.1.0/python/fast_math/_core.pyi +98 -0
  21. fast_math_rs-0.1.0/python/fast_math/py.typed +0 -0
  22. fast_math_rs-0.1.0/rustfmt.toml +1 -0
  23. fast_math_rs-0.1.0/scripts/smoke.sh +27 -0
  24. fast_math_rs-0.1.0/scripts/version.py +107 -0
  25. fast_math_rs-0.1.0/src/arith.rs +277 -0
  26. fast_math_rs-0.1.0/src/lib.rs +10 -0
  27. fast_math_rs-0.1.0/src/number.rs +37 -0
  28. fast_math_rs-0.1.0/src/python.rs +154 -0
  29. fast_math_rs-0.1.0/src/theory.rs +185 -0
  30. fast_math_rs-0.1.0/tests/__init__.py +0 -0
  31. fast_math_rs-0.1.0/tests/conftest.py +8 -0
  32. fast_math_rs-0.1.0/tests/reference.py +56 -0
  33. fast_math_rs-0.1.0/tests/test_arguments.py +66 -0
  34. fast_math_rs-0.1.0/tests/test_arithmetic.py +116 -0
  35. fast_math_rs-0.1.0/tests/test_docs.py +51 -0
  36. fast_math_rs-0.1.0/tests/test_number_theory.py +108 -0
  37. fast_math_rs-0.1.0/tests/test_threads.py +32 -0
  38. fast_math_rs-0.1.0/tests/test_version_script.py +77 -0
  39. fast_math_rs-0.1.0/uv.lock +687 -0
@@ -0,0 +1,108 @@
1
+ name: CI
2
+
3
+ on:
4
+ push:
5
+ branches: [master]
6
+ pull_request:
7
+
8
+ concurrency:
9
+ # A new push to a pull request supersedes the run of the previous one; runs on master all finish
10
+ group: ci-${{ github.ref }}
11
+ cancel-in-progress: ${{ github.event_name == 'pull_request' }}
12
+
13
+ env:
14
+ CARGO_TERM_COLOR: always
15
+
16
+ jobs:
17
+ version:
18
+ # A pull request into master is a release once merged, so it must carry a new version
19
+ if: github.event_name == 'pull_request'
20
+ runs-on: ubuntu-latest
21
+ steps:
22
+ - uses: actions/checkout@v5
23
+ with:
24
+ fetch-depth: 0 # the base branch and the tags
25
+ - uses: astral-sh/setup-uv@v6
26
+ - run: uv run --no-project python scripts/version.py check "origin/${{ github.base_ref }}"
27
+
28
+ lint:
29
+ runs-on: ubuntu-latest
30
+ steps:
31
+ - uses: actions/checkout@v5
32
+ - uses: dtolnay/rust-toolchain@stable
33
+ with:
34
+ components: rustfmt, clippy
35
+ - uses: Swatinem/rust-cache@v2
36
+ - uses: astral-sh/setup-uv@v6
37
+ - run: uv sync --locked
38
+ - run: uv run ruff check .
39
+ - run: uv run ruff format --check .
40
+ - run: uv run mypy
41
+ - run: uvx pyright@1.1.414 # the pin of the Makefile
42
+ - run: uv run stubtest fast_math
43
+ - run: cargo fmt --check
44
+ - run: cargo clippy --all-targets --all-features -- -D warnings
45
+ env:
46
+ # The bindings are configured against an interpreter: the one of the venv
47
+ PYO3_PYTHON: ${{ github.workspace }}/.venv/bin/python
48
+
49
+ rust-test:
50
+ # The core alone, without Python: `cargo test` builds without the `python` feature
51
+ runs-on: ${{ matrix.os }}
52
+ strategy:
53
+ fail-fast: false
54
+ matrix:
55
+ os: [ubuntu-latest, macos-latest, windows-latest]
56
+ steps:
57
+ - uses: actions/checkout@v5
58
+ - uses: dtolnay/rust-toolchain@stable
59
+ - uses: Swatinem/rust-cache@v2
60
+ - run: cargo test
61
+
62
+ test:
63
+ # Every operating system: the float results come from the platform's libm, as Python's own do
64
+ runs-on: ${{ matrix.os }}
65
+ strategy:
66
+ fail-fast: false
67
+ matrix:
68
+ os: [ubuntu-latest, macos-latest, windows-latest]
69
+ python-version: ["3.11", "3.12", "3.13", "3.14"]
70
+ steps:
71
+ - uses: actions/checkout@v5
72
+ - uses: dtolnay/rust-toolchain@stable
73
+ - uses: Swatinem/rust-cache@v2
74
+ - uses: astral-sh/setup-uv@v6
75
+ with:
76
+ python-version: ${{ matrix.python-version }}
77
+ - run: uv sync --locked
78
+ - run: uv run pytest --cov --cov-report=term
79
+
80
+ free-threaded:
81
+ # The tests on CPython 3.14t without PYTHON_GIL=0: importing the extension must leave the GIL off by itself
82
+ runs-on: ubuntu-latest
83
+ steps:
84
+ - uses: actions/checkout@v5
85
+ - uses: dtolnay/rust-toolchain@stable
86
+ - uses: Swatinem/rust-cache@v2
87
+ - uses: astral-sh/setup-uv@v6
88
+ with:
89
+ python-version: "3.14t"
90
+ - run: make test-free-threaded
91
+
92
+ benchmarks:
93
+ # A smoke run of benchmarks/run.py, so it keeps working; the figures of a GitHub runner are too noisy to
94
+ # gate on, docs/benchmarks.md holds the baseline
95
+ runs-on: ubuntu-latest
96
+ continue-on-error: true
97
+ steps:
98
+ - uses: actions/checkout@v5
99
+ - uses: dtolnay/rust-toolchain@stable
100
+ - uses: Swatinem/rust-cache@v2
101
+ - uses: astral-sh/setup-uv@v6
102
+ - run: uv sync --locked
103
+ - run: uv run python benchmarks/run.py --quick
104
+
105
+ wheels:
106
+ # Every release target builds on every pull request, so a platform that breaks fails before the merge
107
+ if: github.event_name == 'pull_request'
108
+ uses: ./.github/workflows/wheels.yml
@@ -0,0 +1,86 @@
1
+ name: Release
2
+
3
+ # Every push to master releases the version in pyproject.toml. The version job of CI makes sure a pull
4
+ # request bumps it; a change that reaches master without a bump fails here. See scripts/version.py.
5
+ on:
6
+ push:
7
+ branches: [master]
8
+
9
+ concurrency:
10
+ group: release
11
+ cancel-in-progress: false
12
+
13
+ jobs:
14
+ version:
15
+ runs-on: ubuntu-latest
16
+ outputs:
17
+ version: ${{ steps.version.outputs.version }}
18
+ steps:
19
+ - uses: actions/checkout@v5
20
+ with:
21
+ fetch-depth: 0 # the tags tell which versions are released
22
+ - uses: astral-sh/setup-uv@v6
23
+ - id: version
24
+ name: Check that the version is not released yet
25
+ run: |
26
+ version=$(uv run --no-project python scripts/version.py unreleased)
27
+ echo "version=${version}" >> "$GITHUB_OUTPUT"
28
+
29
+ test:
30
+ needs: version
31
+ runs-on: ubuntu-latest
32
+ steps:
33
+ - uses: actions/checkout@v5
34
+ - uses: dtolnay/rust-toolchain@stable
35
+ - uses: Swatinem/rust-cache@v2
36
+ - uses: astral-sh/setup-uv@v6
37
+ - run: cargo test
38
+ - run: uv sync --locked
39
+ - run: uv run pytest
40
+
41
+ wheels:
42
+ needs: version
43
+ uses: ./.github/workflows/wheels.yml
44
+
45
+ publish:
46
+ needs: [test, wheels]
47
+ runs-on: ubuntu-latest
48
+ environment:
49
+ name: pypi
50
+ url: https://pypi.org/project/fast-math-rs/
51
+ permissions:
52
+ id-token: write # PyPI Trusted Publishing
53
+ steps:
54
+ - uses: actions/download-artifact@v4
55
+ with:
56
+ pattern: wheels-*
57
+ merge-multiple: true
58
+ path: dist/
59
+ - uses: pypa/gh-action-pypi-publish@release/v1
60
+
61
+ tag:
62
+ needs: [version, publish]
63
+ runs-on: ubuntu-latest
64
+ permissions:
65
+ contents: write
66
+ env:
67
+ VERSION: ${{ needs.version.outputs.version }}
68
+ GH_TOKEN: ${{ github.token }}
69
+ steps:
70
+ - uses: actions/checkout@v5
71
+ - uses: astral-sh/setup-uv@v6
72
+ - uses: actions/download-artifact@v4
73
+ with:
74
+ pattern: wheels-*
75
+ merge-multiple: true
76
+ path: dist/
77
+ - name: Tag the release
78
+ run: |
79
+ git config user.name "github-actions[bot]"
80
+ git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
81
+ git tag -a "v${VERSION}" -m "fast-math-rs ${VERSION}"
82
+ git push origin "v${VERSION}"
83
+ - name: Publish the release notes from CHANGELOG.md, with the wheels and the sdist
84
+ run: |
85
+ uv run --no-project python scripts/version.py notes > notes.md
86
+ gh release create "v${VERSION}" --verify-tag --title "fast-math-rs ${VERSION}" --notes-file notes.md dist/*
@@ -0,0 +1,99 @@
1
+ name: Wheels
2
+
3
+ # The wheels of every release target and the sdist, as artifacts named wheels-*; called by CI on a pull request
4
+ # and by Release. Each target builds an abi3 wheel for CPython 3.11+ and one for free-threaded 3.14t (ADR-0004),
5
+ # and a target the runner can run imports both before they are uploaded.
6
+ on:
7
+ workflow_call:
8
+
9
+ jobs:
10
+ linux:
11
+ runs-on: ${{ matrix.runner }}
12
+ strategy:
13
+ fail-fast: false
14
+ matrix:
15
+ include:
16
+ - { runner: ubuntu-latest, target: x86_64, platform: manylinux_2_28, smoke: true }
17
+ - { runner: ubuntu-24.04-arm, target: aarch64, platform: manylinux_2_28, smoke: true }
18
+ - { runner: ubuntu-latest, target: x86_64, platform: musllinux_1_2, smoke: false }
19
+ - { runner: ubuntu-24.04-arm, target: aarch64, platform: musllinux_1_2, smoke: false }
20
+ steps:
21
+ - uses: actions/checkout@v5
22
+ - uses: PyO3/maturin-action@v1
23
+ with:
24
+ target: ${{ matrix.target }}
25
+ manylinux: ${{ matrix.platform }}
26
+ args: --release --out dist --interpreter 3.11 3.14t
27
+ - uses: astral-sh/setup-uv@v6
28
+ if: matrix.smoke
29
+ - name: Import the wheels
30
+ if: matrix.smoke
31
+ shell: bash
32
+ run: scripts/smoke.sh dist
33
+ - uses: actions/upload-artifact@v4
34
+ with:
35
+ name: wheels-linux-${{ matrix.target }}-${{ matrix.platform }}
36
+ path: dist
37
+
38
+ macos:
39
+ runs-on: ${{ matrix.runner }}
40
+ strategy:
41
+ fail-fast: false
42
+ matrix:
43
+ include:
44
+ - { runner: macos-15-intel, target: x86_64 }
45
+ - { runner: macos-latest, target: aarch64 }
46
+ steps:
47
+ - uses: actions/checkout@v5
48
+ - uses: actions/setup-python@v6
49
+ with:
50
+ python-version: |
51
+ 3.11
52
+ 3.14t
53
+ - uses: PyO3/maturin-action@v1
54
+ with:
55
+ target: ${{ matrix.target }}
56
+ args: --release --out dist --interpreter 3.11 3.14t
57
+ - uses: astral-sh/setup-uv@v6
58
+ - name: Import the wheels
59
+ shell: bash
60
+ run: scripts/smoke.sh dist
61
+ - uses: actions/upload-artifact@v4
62
+ with:
63
+ name: wheels-macos-${{ matrix.target }}
64
+ path: dist
65
+
66
+ windows:
67
+ runs-on: windows-latest
68
+ steps:
69
+ - uses: actions/checkout@v5
70
+ - uses: actions/setup-python@v6
71
+ with:
72
+ python-version: |
73
+ 3.11
74
+ 3.14t
75
+ - uses: PyO3/maturin-action@v1
76
+ with:
77
+ target: x64
78
+ args: --release --out dist --interpreter 3.11 3.14t
79
+ - uses: astral-sh/setup-uv@v6
80
+ - name: Import the wheels
81
+ shell: bash
82
+ run: scripts/smoke.sh dist
83
+ - uses: actions/upload-artifact@v4
84
+ with:
85
+ name: wheels-windows-x64
86
+ path: dist
87
+
88
+ sdist:
89
+ runs-on: ubuntu-latest
90
+ steps:
91
+ - uses: actions/checkout@v5
92
+ - uses: PyO3/maturin-action@v1
93
+ with:
94
+ command: sdist
95
+ args: --out dist
96
+ - uses: actions/upload-artifact@v4
97
+ with:
98
+ name: wheels-sdist
99
+ path: dist
@@ -0,0 +1,20 @@
1
+ __pycache__/
2
+ *.py[cod]
3
+ .venv/
4
+ build/
5
+ dist/
6
+ *.egg-info/
7
+ .pytest_cache/
8
+ .mypy_cache/
9
+ .ruff_cache/
10
+ .hypothesis/
11
+ .coverage
12
+ coverage.xml
13
+ htmlcov/
14
+ .DS_Store
15
+ .idea/
16
+ .vscode/
17
+ # Rust: the build tree, and the extension that an editable install builds into the Python sources
18
+ target/
19
+ python/fast_math/*.so
20
+ python/fast_math/*.pyd
@@ -0,0 +1,26 @@
1
+ # Changelog
2
+
3
+ All notable changes to this project are documented in this file.
4
+ The format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
5
+ and the project adheres to [Semantic Versioning](https://semver.org/).
6
+
7
+ ## [Unreleased]
8
+
9
+ ## [0.1.0] - 2026-10-17
10
+
11
+ ### Added
12
+
13
+ - The Rust core and its Python package `fast_math`:
14
+ - arithmetic with the semantics of the Python operators: `add`, `sub`, `mul`, `div`, `floordiv`, `mod`,
15
+ `pow`, `abs`, `sqrt`; an `int` with an `int` gives an `int`, anything with a `float` a `float`;
16
+ - number theory on 64-bit integers: `gcd`, `lcm`, `factorial`, `fibonacci`, `is_prime` (a deterministic
17
+ Miller-Rabin test, exact for every 64-bit integer) and `primes_up_to` (a sieve that releases the GIL).
18
+ - 64-bit integers with checked arithmetic: a result or an argument beyond 64 bits raises `OverflowError`.
19
+ - Type stubs, checked against the extension by `stubtest`, and `py.typed`.
20
+ - abi3 wheels for CPython 3.11+ and wheels for free-threaded CPython 3.14t, on which the module keeps the GIL
21
+ off; Linux (glibc, musl; x86_64, aarch64), macOS (x86_64, arm64) and Windows (x64).
22
+ - Property tests of every function against Python itself with hypothesis, Rust unit tests of the core, and
23
+ benchmarks against the builtins and plain Python (`docs/benchmarks.md`).
24
+
25
+ [Unreleased]: https://github.com/troyan-dy/fast_math/compare/v0.1.0...HEAD
26
+ [0.1.0]: https://github.com/troyan-dy/fast_math/releases/tag/v0.1.0
@@ -0,0 +1,132 @@
1
+ # This file is automatically @generated by Cargo.
2
+ # It is not intended for manual editing.
3
+ version = 4
4
+
5
+ [[package]]
6
+ name = "fast-math"
7
+ version = "0.0.0"
8
+ dependencies = [
9
+ "pyo3",
10
+ ]
11
+
12
+ [[package]]
13
+ name = "heck"
14
+ version = "0.5.0"
15
+ source = "registry+https://github.com/rust-lang/crates.io-index"
16
+ checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea"
17
+
18
+ [[package]]
19
+ name = "libc"
20
+ version = "0.2.191"
21
+ source = "registry+https://github.com/rust-lang/crates.io-index"
22
+ checksum = "65cd87c9a6d60536580b316ad985726104730a5151c99845f2490428ef91240a"
23
+
24
+ [[package]]
25
+ name = "once_cell"
26
+ version = "1.21.4"
27
+ source = "registry+https://github.com/rust-lang/crates.io-index"
28
+ checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50"
29
+
30
+ [[package]]
31
+ name = "portable-atomic"
32
+ version = "1.15.0"
33
+ source = "registry+https://github.com/rust-lang/crates.io-index"
34
+ checksum = "05c8b63e8d9609db387f0324918f81d68fe27748f084ef092fb35954d0539a85"
35
+
36
+ [[package]]
37
+ name = "proc-macro2"
38
+ version = "1.0.107"
39
+ source = "registry+https://github.com/rust-lang/crates.io-index"
40
+ checksum = "985e7ec9bb745e6ce6535b544d84d6cd6f7ad8bd711c398938ae983b91a766d9"
41
+ dependencies = [
42
+ "unicode-ident",
43
+ ]
44
+
45
+ [[package]]
46
+ name = "pyo3"
47
+ version = "0.30.1"
48
+ source = "registry+https://github.com/rust-lang/crates.io-index"
49
+ checksum = "229ca13b8a15bb0d1487b81ab975bfcd97513416499a8312011b6036e42e0de4"
50
+ dependencies = [
51
+ "libc",
52
+ "once_cell",
53
+ "portable-atomic",
54
+ "pyo3-build-config",
55
+ "pyo3-ffi",
56
+ "pyo3-macros",
57
+ ]
58
+
59
+ [[package]]
60
+ name = "pyo3-build-config"
61
+ version = "0.30.1"
62
+ source = "registry+https://github.com/rust-lang/crates.io-index"
63
+ checksum = "70130e2b6dd1ee589a8788026a429561ca5c40fa7a2fa7914c2282eddae24700"
64
+ dependencies = [
65
+ "target-lexicon",
66
+ ]
67
+
68
+ [[package]]
69
+ name = "pyo3-ffi"
70
+ version = "0.30.1"
71
+ source = "registry+https://github.com/rust-lang/crates.io-index"
72
+ checksum = "5e7ff73c555c286d212d4ce7e5fbda845a973c4f61bd5f160f5f2c3c2a04d1c4"
73
+ dependencies = [
74
+ "libc",
75
+ "pyo3-build-config",
76
+ ]
77
+
78
+ [[package]]
79
+ name = "pyo3-macros"
80
+ version = "0.30.1"
81
+ source = "registry+https://github.com/rust-lang/crates.io-index"
82
+ checksum = "c46d2e5862c7bb8207e3b639f713dda3c499933444784154c11d013c5a691b60"
83
+ dependencies = [
84
+ "proc-macro2",
85
+ "pyo3-macros-backend",
86
+ "quote",
87
+ "syn",
88
+ ]
89
+
90
+ [[package]]
91
+ name = "pyo3-macros-backend"
92
+ version = "0.30.1"
93
+ source = "registry+https://github.com/rust-lang/crates.io-index"
94
+ checksum = "38b89f066f2ae72a2aef52d1537ca2fcd104440ebfadee06e97aa90738a25b9b"
95
+ dependencies = [
96
+ "heck",
97
+ "proc-macro2",
98
+ "quote",
99
+ "syn",
100
+ ]
101
+
102
+ [[package]]
103
+ name = "quote"
104
+ version = "1.0.47"
105
+ source = "registry+https://github.com/rust-lang/crates.io-index"
106
+ checksum = "1fbf4db142a473a8d80c26bbf18454ed458bf8d26c8219c331daecfdbd079001"
107
+ dependencies = [
108
+ "proc-macro2",
109
+ ]
110
+
111
+ [[package]]
112
+ name = "syn"
113
+ version = "3.0.9"
114
+ source = "registry+https://github.com/rust-lang/crates.io-index"
115
+ checksum = "d78c8dee4c7bf0e14673097256fed6142ce9d3b85a408189d07482442145823b"
116
+ dependencies = [
117
+ "proc-macro2",
118
+ "quote",
119
+ "unicode-ident",
120
+ ]
121
+
122
+ [[package]]
123
+ name = "target-lexicon"
124
+ version = "0.13.5"
125
+ source = "registry+https://github.com/rust-lang/crates.io-index"
126
+ checksum = "adb6935a6f5c20170eeceb1a3835a49e12e19d792f6dd344ccc76a985ca5a6ca"
127
+
128
+ [[package]]
129
+ name = "unicode-ident"
130
+ version = "1.0.27"
131
+ source = "registry+https://github.com/rust-lang/crates.io-index"
132
+ checksum = "a2c754d6c33795a1c324727428e5a7dedb5b06195f9890bdbcba760d3e246563"
@@ -0,0 +1,42 @@
1
+ [package]
2
+ name = "fast-math"
3
+ # The version of the package lives in pyproject.toml, which maturin reads; the crate is never published
4
+ version = "0.0.0"
5
+ edition = "2024"
6
+ rust-version = "1.85"
7
+ license = "MIT"
8
+ publish = false
9
+ readme = "README.md"
10
+
11
+ [lib]
12
+ name = "_core"
13
+ # cdylib: the Python extension; rlib: what `cargo test` links the unit tests of the pure Rust core against
14
+ crate-type = ["cdylib", "rlib"]
15
+
16
+ [dependencies]
17
+ # abi3-py311: one wheel per platform for every CPython from 3.11 on; free-threaded builds get a wheel of
18
+ # their own, since the stable ABI does not cover them (ADR-0004)
19
+ pyo3 = { version = "0.30.1", features = ["abi3-py311"], optional = true }
20
+
21
+ [features]
22
+ # The Python extension; off for `cargo test`, which needs no interpreter then. [tool.maturin] turns it on
23
+ python = ["dep:pyo3"]
24
+
25
+ [profile.release]
26
+ lto = "fat"
27
+ codegen-units = 1
28
+ strip = true
29
+
30
+ [lints.rust]
31
+ unsafe_code = "forbid"
32
+
33
+ [lints.clippy]
34
+ pedantic = { level = "warn", priority = -1 }
35
+ # The core casts between i64, u64 and f64 on purpose, each cast follows the semantics of Python
36
+ cast_possible_truncation = "allow"
37
+ cast_possible_wrap = "allow"
38
+ cast_precision_loss = "allow"
39
+ cast_sign_loss = "allow"
40
+ float_cmp = "allow"
41
+ # Every error of the core is a Python exception, documented in the stubs of python/fast_math/_core.pyi
42
+ missing_errors_doc = "allow"
@@ -0,0 +1,51 @@
1
+ # fast-math-rs
2
+
3
+ Arithmetic and number theory on Python numbers, computed by a Rust core.
4
+
5
+ ## Language
6
+
7
+ **Core**:
8
+ The Rust code that computes: `src/arith.rs`, `src/theory.rs` and `src/number.rs`. It knows nothing of Python and
9
+ is tested by `cargo test` on its own.
10
+ _Avoid_: Backend, engine, native code
11
+
12
+ **Bindings**:
13
+ `src/python.rs`: the conversion of Python objects into **Numbers**, of **Math errors** into exceptions, and the
14
+ `fast_math._core` module. Built only with the `python` cargo feature.
15
+ _Avoid_: Wrapper, glue, FFI layer
16
+
17
+ **Extension**:
18
+ The compiled module `fast_math._core` that maturin builds from the **Core** and the **Bindings**; the package
19
+ `fast_math` re-exports it.
20
+ _Avoid_: Shared library, `.so`
21
+
22
+ **Number**:
23
+ An argument or result of an arithmetic operation: an **Integer** or a **Float**.
24
+ _Avoid_: Value, scalar, numeric
25
+
26
+ **Integer**:
27
+ A Python `int` (or `bool`) in `[-2**63, 2**63 - 1]`, an `i64` in the **Core** (ADR-0002).
28
+ _Avoid_: Long, bigint, int64 (in prose)
29
+
30
+ **Float**:
31
+ A Python `float`, an `f64` in the **Core**.
32
+ _Avoid_: Double, real, decimal
33
+
34
+ **Overflow**:
35
+ An **Integer** result or argument outside 64 bits, or a finite **Float** `pow` whose result is infinite;
36
+ raises `OverflowError`. Never a wrapped, saturated or rounded result.
37
+ _Avoid_: Wrap-around, truncation
38
+
39
+ **Reference**:
40
+ The Python operator or `math` function whose semantics a fast_math function has; the tests compare the two
41
+ on generated arguments (ADR-0003).
42
+ _Avoid_: Oracle, spec, expected value
43
+
44
+ **Departure**:
45
+ A documented case where fast_math differs from its **Reference** on purpose: **Overflow** of **Integers**, and
46
+ `ValueError` for a negative base to a fractional power.
47
+ _Avoid_: Bug, incompatibility, quirk
48
+
49
+ **Math error**:
50
+ `MathError` of the **Core**: overflow, division by zero, domain or memory; each kind is one Python exception.
51
+ _Avoid_: Failure, exception (inside the Core)
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Dmitriy Troyan
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,74 @@
1
+ .DEFAULT_GOAL := help
2
+
3
+ PY_VERSIONS := 3.11 3.12 3.13 3.14
4
+ # Not a dev dependency: uvx keeps it out of uv.lock; the same pin is in .github/workflows/ci.yml
5
+ PYRIGHT := pyright@1.1.414
6
+
7
+ .PHONY: help
8
+ help: ## Show available targets
9
+ @awk 'BEGIN {FS = ":.*?## "} /^[a-zA-Z_-]+:.*?## / {printf " \033[36m%-20s\033[0m %s\n", $$1, $$2}' $(MAKEFILE_LIST)
10
+
11
+ .PHONY: install
12
+ install: ## Install the dev dependencies and build the extension into .venv
13
+ uv sync --locked
14
+
15
+ .PHONY: lint
16
+ lint: ## Run ruff, mypy, pyright and stubtest on Python; rustfmt and clippy on Rust
17
+ uv run ruff check .
18
+ uv run ruff format --check .
19
+ uv run mypy
20
+ uvx $(PYRIGHT)
21
+ uv run stubtest fast_math
22
+ cargo fmt --check
23
+ cargo clippy --all-targets --all-features -- -D warnings
24
+
25
+ .PHONY: format
26
+ format: ## Autofix lint issues and format the Python and Rust code
27
+ uv run ruff check --fix .
28
+ uv run ruff format .
29
+ cargo fmt
30
+
31
+ .PHONY: test
32
+ test: ## Run the Python tests
33
+ uv run pytest
34
+
35
+ .PHONY: rust-test
36
+ rust-test: ## Run the Rust unit tests of the core
37
+ cargo test
38
+
39
+ .PHONY: cov
40
+ cov: ## Run the Python tests with a coverage report
41
+ uv run pytest --cov --cov-report=term --cov-report=html
42
+
43
+ .PHONY: test-all
44
+ test-all: ## Run the Python tests on every supported Python version
45
+ @for v in $(PY_VERSIONS); do \
46
+ echo "==> Python $$v"; \
47
+ uv run --isolated --python $$v pytest || exit 1; \
48
+ done
49
+
50
+ .PHONY: test-free-threaded
51
+ test-free-threaded: ## Run the Python tests on free-threaded Python 3.14t, as CI does; the GIL must stay off by itself
52
+ uv run --python 3.14t --isolated --no-default-groups --with pytest --with hypothesis pytest -p no:cacheprovider
53
+
54
+ .PHONY: bench
55
+ bench: ## Run the benchmarks, see docs/benchmarks.md
56
+ uv run python benchmarks/run.py
57
+
58
+ .PHONY: check-version
59
+ check-version: ## Check that the version is bumped against origin/master, as CI does for a pull request
60
+ git fetch --quiet --tags origin master
61
+ uv run --no-project python scripts/version.py check origin/master
62
+
63
+ .PHONY: check
64
+ check: lint rust-test test ## Run everything CI runs
65
+
66
+ .PHONY: wheels
67
+ wheels: ## Build the release wheels of this platform (abi3 and 3.14t) and the sdist into dist/
68
+ uvx maturin build --release --out dist --interpreter 3.11 3.14t
69
+ uvx maturin sdist --out dist
70
+
71
+ .PHONY: clean
72
+ clean: ## Remove build artifacts and caches; the extension built into python/fast_math/ stays, `uv run` needs it
73
+ rm -rf build dist target *.egg-info htmlcov .coverage coverage.xml .pytest_cache .mypy_cache .ruff_cache .hypothesis
74
+ find . -type d -name __pycache__ -not -path './.venv/*' -exec rm -rf {} +