Skip to content

Repository files navigation

math

pi.py pi-rs prime-rs fib.py fib-rs sq.py sq-rs twin-primes-rs e.py e-rs factorial-py factorial-rs perfect-numbers-py perfect-numbers-rs collatz-py collatz-rs goldbach-rs amicable.py amicable-rs scripts

High-performance mathematical computation tools.

Project Description Implementation CI
pi/ Calculate π to N decimal places Python + Rust pi.py pi-rs
prime/ Find all primes up to 10^N Rust prime-rs
fib/ Generate all Fibonacci numbers with up to 10^X digits Python + Rust fib.py fib-rs
sq/ Generate all perfect squares with up to 10^N digits (N=1 max) Python + Rust sq.py sq-rs
twin-primes/ Find all twin prime pairs up to 10^N Rust twin-primes-rs
e/ Calculate e to N decimal places Python + Rust e.py e-rs
factorial/ Compute N! to arbitrary precision (prime swing algorithm) Python + Rust factorial-py factorial-rs
perfect-numbers/ Find all perfect numbers up to 10^N (Lucas-Lehmer + sigma) Python + Rust perfect-numbers-py perfect-numbers-rs
collatz/ Find Collatz chain record-setters up to 10^N Python + Rust collatz-py collatz-rs
goldbach/ Find all Goldbach pairs for even numbers up to 10^N Rust goldbach-rs
amicable/ Find all amicable pairs (a,b) with b ≤ 10^N (proper-divisor sum sieve) Python + Rust amicable.py amicable-rs

Coverage

CLI Python Rust
amicable python rust
collatz python rust
e python rust
factorial python rust
fib python rust
goldbach — rust
perfect-numbers python rust
pi python rust
prime — rust
sq python rust
twin-primes — rust

pi

Calculates π to an arbitrary number of decimal places using the Chudnovsky algorithm with binary splitting.

  • Python implementation (pi/pi.py) — best for up to ~50M digits
  • Rust implementation (pi/pi-rs/) — best for 50M+ digits; shared-memory rayon parallelism with zero IPC overhead

See pi/README.md for full details.


prime

Finds every prime number up to 10^N using a parallel segmented Sieve of Eratosthenes.

  • Rust implementation (prime/prime-rs/) — packed bitset segments (32 KB each, fits in L2 cache), rayon-parallelised across all cores, streams output to file to keep peak RAM ≤ ~50 MB

See prime/README.md for full details.


fib

Generates every Fibonacci number with at most 10^X decimal digits.

  • Python implementation (fib/fib.py) — uses Python's built-in arbitrary-precision int; no external dependencies
  • Rust implementation (fib/fib-rs/) — uses rug/GMP for best performance at large digit counts

See fib/README.md for full details.


sq

Generates every perfect square with at most 10^N decimal digits. N=1 is the only valid value (produces 99,999 squares up to 10 digits).

  • Python implementation (sq/sq.py) — Python stdlib only, no external dependencies
  • Rust implementation (sq/sq-rs/) — plain u64 arithmetic, no GMP required

See sq/README.md for full details.


twin-primes

Finds every twin prime pair (p, p+2) where both primes are less than 10^N.

  • Rust implementation (twin-primes/twin-primes-rs/) — packed bitset segments (32 KB each, fits in L2 cache), constant memory usage regardless of N

See twin-primes/README.md for full details.


e

Calculates Euler's number e to an arbitrary number of decimal places using the Taylor series with binary splitting.

  • Python implementation (e/e.py) — gmpy2/GMP fast path with mpmath fallback
  • Rust implementation (e/e-rs/) — shared-memory rayon parallelism with zero IPC overhead

See e/README.md for full details.


factorial

Computes N! (N factorial) to arbitrary precision using the prime swing algorithm (n! = swing(n) × (⌊n/2⌋!)²).

  • Python implementation (factorial/factorial.py) — gmpy2/GMP fast path with plain int fallback; parallel swing via ProcessPoolExecutor
  • Rust implementation (factorial/factorial-rs/) — rug/GMP with rayon parallel chunks

See factorial/README.md for full details.


perfect-numbers

Finds all perfect numbers up to 10^N using the Lucas-Lehmer primality test (even perfect numbers via Mersenne primes) and a sigma divisor-sum sieve (odd perfect numbers, none known but checked for completeness).

  • Python implementation (perfect-numbers/perfect_numbers.py) — pure Python stdlib, no external dependencies
  • Rust implementation (perfect-numbers/perfect-numbers-rs/) — rug/GMP for arbitrary-precision sigma computation

See perfect-numbers/README.md for full details.


Quick Reference

Python (pi/)

cd pi
make run       # python3 pi.py
make lint      # ruff check . && ruff format --check .
make test      # lint, then pytest test_pi.py -v
make coverage  # pytest --cov=pi --cov-report=term-missing

Rust (pi/pi-rs/)

cd pi/pi-rs
make pi        # cargo build --release
make lint      # cargo fmt --check, then cargo clippy --all-targets -- -D warnings
make test      # lint, then cargo test

Rust (prime/prime-rs/)

cd prime/prime-rs
make prime     # cargo build --release
make lint      # cargo fmt --check, then cargo clippy --all-targets -- -D warnings
make test      # lint, then cargo test

Python (fib/)

cd fib
make run       # python3 fib.py
make lint      # ruff check . && ruff format --check .
make test      # lint, then pytest test_fib.py -v
make coverage  # pytest --cov=fib --cov-report=term-missing

Rust (fib/fib-rs/)

cd fib/fib-rs
make fib       # cargo build --release
make lint      # cargo fmt --check, then cargo clippy --all-targets -- -D warnings
make test      # lint, then cargo test

Python (sq/)

cd sq
make run       # python3 sq.py
make lint      # ruff check . && ruff format --check .
make test      # lint, then pytest test_sq.py -v
make coverage  # pytest --cov=sq --cov-report=term-missing

Rust (sq/sq-rs/)

cd sq/sq-rs
make sq        # cargo build --release
make lint      # cargo fmt --check, then cargo clippy --all-targets -- -D warnings
make test      # lint, then cargo test

Rust (twin-primes/twin-primes-rs/)

cd twin-primes/twin-primes-rs
make twin-primes  # cargo build --release
make lint         # cargo fmt --check, then cargo clippy --all-targets -- -D warnings
make test         # lint, then cargo test

Python (e/)

cd e
make run       # python3 e.py
make lint      # ruff check . && ruff format --check .
make test      # lint, then pytest test_e.py -v
make coverage  # pytest --cov=e --cov-report=term-missing

Rust (e/e-rs/)

cd e/e-rs
make e         # cargo build --release
make lint      # cargo fmt --check, then cargo clippy --all-targets -- -D warnings
make test      # lint, then cargo test

Python (factorial/)

cd factorial
make run       # python3 factorial.py
make lint      # ruff check . && ruff format --check .
make test      # lint, then pytest test_factorial.py -v
make coverage  # pytest --cov=factorial --cov-report=term-missing

Rust (factorial/factorial-rs/)

cd factorial/factorial-rs
make factorial # cargo build --release
make lint      # cargo fmt --check, then cargo clippy --all-targets -- -D warnings
make test      # lint, then cargo test

Python (perfect-numbers/)

cd perfect-numbers
make run       # python3 perfect_numbers.py
make lint      # ruff check . && ruff format --check .
make test      # lint, then pytest test_perfect_numbers.py -v
make coverage  # pytest --cov=perfect_numbers --cov-report=term-missing

Rust (perfect-numbers/perfect-numbers-rs/)

cd perfect-numbers/perfect-numbers-rs
make perfect-numbers  # cargo build --release
make lint             # cargo fmt --check, then cargo clippy --all-targets -- -D warnings
make test             # lint, then cargo test

Python (collatz/)

cd collatz
make run       # python3 collatz.py
make lint      # ruff check . && ruff format --check .
make test      # lint, then pytest test_collatz.py -v
make coverage  # pytest --cov=collatz --cov-report=term-missing

Rust (collatz/collatz-rs/)

cd collatz/collatz-rs
make collatz   # cargo build --release
make lint      # cargo fmt --check, then cargo clippy --all-targets -- -D warnings
make test      # lint, then cargo test

Rust (goldbach/goldbach-rs/)

cd goldbach/goldbach-rs
make goldbach  # cargo build --release
make lint      # cargo fmt --check, then cargo clippy --all-targets -- -D warnings
make test      # lint, then cargo test

Python (amicable/)

cd amicable
make run       # python3 amicable.py
make lint      # ruff check . && ruff format --check .
make test      # lint, then pytest test_amicable.py -v
make coverage  # pytest --cov=amicable --cov-report=term-missing

Rust (amicable/amicable-rs/)

cd amicable/amicable-rs
make amicable  # cargo build --release
make lint      # cargo fmt --check, then cargo clippy --all-targets -- -D warnings
make test      # lint, then cargo test

collatz

Finds Collatz chain record-setters up to 10^N using vector memoization.

  • Python implementation (collatz/collatz.py) — stdlib only, practical for N≤7
  • Rust implementation (collatz/collatz-rs/) — Vec<u32> memoization, handles N≤9 comfortably

See collatz/README.md for full details.


goldbach

Finds all Goldbach pairs for even numbers up to 10^N.

  • Rust implementation (goldbach/goldbach-rs/) — packed bitset sieve, BufWriter streaming, practical up to N=6 (~20 GB output)

See goldbach/README.md for full details.


amicable

Finds all amicable pairs (a, b) where a < b ≤ 10^N using a proper-divisor sum sieve (sigma function over all numbers up to the limit, then cross-checking pairs).

  • Python implementation (amicable/amicable.py) — stdlib only, no external dependencies
  • Rust implementation (amicable/amicable-rs/) — plain u64 arithmetic with a pre-computed sigma sieve

See amicable/README.md for full details.


Development Setup

After cloning, install the git hooks and root-scope Python dependencies:

make install-hooks   # symlinks pre-commit, pre-push and commit-msg
make install-deps    # installs what tests/, scripts/ and .claude/scripts/ import

install-deps reads requirements-dev.txt — the third-party modules root-scope Python actually imports (defusedxml, pyyaml), not a tool list. It refuses on a PEP 668 externally-managed interpreter rather than using --break-system-packages, and the refusal names the remedy: python3 -m venv .venv && . .venv/bin/activate. Without it, make test fails at import — scripts/pre-push runs the root suite on any push touching scripts/, tests/ or .claude/scripts/.

install-hooks symlinks scripts/pre-commit into .git/hooks/pre-commit. The hook runs make lint on staged sub-projects and scans for secrets with ggshield (skipped gracefully if not installed). CI secret-scan via gitleaks is a backstop — local scanning catches secrets before they leave the machine.

Install ggshield: brew install gitguardian/tap/ggshield && ggshield auth login.

  • brew install git-cliff — CHANGELOG generation (make changelog)

Rust crates use scripts/rust-check.sh for make lint and make test. By default it sets CARGO_HOME to a repo-local writable cache path and can run offline when dependencies are cached:

RUST_CHECK_OFFLINE=1 make test

Every Rust sub-project also has make bench (Criterion benchmarks). CI alerts when any benchmark regresses more than 30% vs the previous run. cargo test includes CLI integration tests from tests/cli.rs alongside the unit tests.

Python CI runs two additional quality steps per sub-project: pyright (static type checking) and pip-audit (dependency security scan). These run in CI only — there is no local make target for them. Run them manually with pyright and pip-audit from the sub-project directory.


Architectural Decisions

Key decisions are recorded in docs/adr/: algorithm choices (Chudnovsky, segmented sieve), language strategy (Python vs Rust), library choices (GMP/rug, rayon), and CI structure.


Verifying releases

Release binaries are signed with cosign using keyless Sigstore signing. Each release includes the binary plus:

  • {name}.sha256 — SHA256 checksum
  • {name}.sbom.spdx.json — SPDX bill of materials
  • {name}.bundle — cosign signature bundle (v4 format; supersedes the separate .sig/.pem pair)

To verify a release binary (example for factorial):

cosign verify-blob factorial \
  --bundle factorial.bundle \
  --certificate-identity \
    "https://github.com/brujack/math/.github/workflows/release-factorial-rs.yml@refs/heads/master" \
  --certificate-oidc-issuer "https://token.actions.githubusercontent.com"

Replace factorial with the sub-project name (e.g. fib), and release-factorial-rs.yml with that sub-project's own release workflow filename (e.g. release-fib-rs.yml) — the certificate identity is the workflow that requested the signing certificate, not the tag being released. No release has been cut with this pipeline yet, so treat the identity above as derived from how keyless signing works rather than observed — read it back from a real release's own .bundle to confirm it before relying on it.

About

No description, website, or topics provided.

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Used by

Contributors

Languages