Skip to main content

A high-performance algorithm library built in Rust for Python.

Project description

algofarm

Fast, dependency-free algorithms for Python, implemented from scratch in Rust.

No rand, no rayon, no std::collections::HashMap under the hood — just pyo3 and hand-rolled implementations of the things people rewrite in every project: sorting, searching, string distance, number theory, basic stats, and a custom hashmap you can use directly from Python.

Why

Python's standard library and numpy already cover a lot of this, but:

  • sorted(x)[:k] sorts the whole array to get the top ktop_k doesn't.
  • Pure-Python Levenshtein distance is slow enough to matter on real string data.
  • list(dict.fromkeys(x)) for dedup pays per-element interpreter overhead at scale.
  • Everyone has a copy-pasted GCD/sieve/Miller-Rabin snippet from an old competitive programming folder.

algofarm exists so you don't have to write (or copy-paste) these again.

Install

pip install maturin
maturin develop --release

This builds the Rust extension and installs it into your active Python environment. Use --release — debug builds of the sort/search functions are dramatically slower.

Sorting

import algofarm

algofarm.quicksort([5, 3, 8, 1])          # [1, 3, 5, 8]   — randomized pivot, 3-way partition
algofarm.quicksort_f64([3.1, 1.5, 2.2])   # float variant, NaN-safe ordering
algofarm.mergesort([5, 3, 8, 1])          # stable, O(n log n) guaranteed
algofarm.parallel_sort(big_list)          # multi-threaded via std::thread; only worth it above ~50k elements

quicksort uses a randomized pivot and Dutch-flag 3-way partitioning, so duplicate-heavy data and adversarial inputs don't degrade to O(n²). Recursion always descends into the smaller partition first, which bounds stack depth to O(log n) regardless of input shape. Arrays of 16 or fewer elements fall back to insertion sort.

Searching

algofarm.binary_search([1, 3, 5, 7, 9], 5)   # 2 (index), or None if not found
algofarm.kth_smallest([9, 2, 7, 4, 1], 2)    # 2nd smallest, O(n) average — no full sort
algofarm.top_k([9, 2, 7, 4, 1], 3)           # [9, 7, 4], descending

kth_smallest and top_k use quickselect, so pulling the top 100 rows out of 50 million doesn't pay for sorting the other 49,999,900.

Deduplication

algofarm.dedup([1, 2, 2, 3, 1, 4])   # [1, 2, 3, 4] — first-occurrence order preserved

String distance

algofarm.levenshtein("kitten", "sitting")   # 3

Rolling two-row DP — O(min(n, m)) space instead of the full O(n·m) matrix.

Number theory

algofarm.gcd(48, 18)              # 6
algofarm.lcm(4, 6)                # 12
algofarm.mod_pow(7, 128, 13)      # binary exponentiation, u128 intermediate — no overflow
algofarm.is_prime(982451653)      # deterministic Miller-Rabin, correct for the full u64 range
algofarm.sieve(100)               # all primes up to 100, as a list
algofarm.fibonacci(50)            # fast doubling, O(log n) — not the naive O(n) loop

Statistics

algofarm.mean([1.0, 2.0, 3.0])       # 2.0
algofarm.median([1.0, 2.0, 3.0])     # 2.0
algofarm.variance([1.0, 2.0, 3.0])   # population variance (divides by n, not n-1)
algofarm.std_dev([1.0, 2.0, 3.0])

Linear algebra

algofarm.dot_product([1.0, 2.0], [3.0, 4.0])   # 11.0
algofarm.matmul(a, b)                          # a: m×k, b: k×n -> m×n; raises ValueError on mismatch

matmul uses i-k-j loop ordering for cache locality and skips multiplies against zero entries — meaningfully faster than the naive i-j-k triple loop on anything but tiny matrices.

FarmHashMap

A hand-rolled open-addressing hashmap (linear probing, tombstone deletion, grows at 70% load factor), usable as a Python object:

from algofarm import FarmHashMap

m = FarmHashMap()
m.insert(1, 100)
m.get(1)          # 100
m.contains(1)      # True
m.remove(1)        # 100 (the removed value)
len(m)
m.keys()
m.values()
m.items()

Currently keyed on int -> int. Hashing is a splitmix64-style bit mixer, not std::collections::HashMap's default hasher.

Performance notes

  • parallel_sort spawns real OS threads via std::thread::scope and only pays that overhead above ~50,000 elements — below that it silently falls back to the sequential quicksort.
  • All functions release the GIL during the actual computation (py.allow_threads), so other Python threads keep running while algofarm works — this matters if you're calling these from a multi-threaded application, not just for the parallel_sort case.
  • is_prime is deterministic (not probabilistic) for the entire u64 range using a fixed 12-witness Miller-Rabin set — no false positives, unlike a naive random-witness version.

Testing

Correctness is checked against Python's standard library and reference implementations across randomized inputs (fixed seed for reproducibility) — sorting against sorted(), number theory against math/trial division, stats against the statistics module, FarmHashMap against dict under randomized insert/get/remove/contains sequences.

Design philosophy

Zero dependencies beyond pyo3. No rand, no rayon, no std::collections::HashMap. Randomization uses a hand-rolled xorshift64* PRNG; parallelism uses raw std::thread; the hashmap is open-addressing from scratch. The point isn't that these beat a well-optimized crate on every benchmark — it's that nothing in this library is a black box you have to trust without being able to read it in five minutes.

License

MIT

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distributions

No source distribution files available for this release.See tutorial on generating distribution archives.

Built Distributions

If you're not sure about the file name format, learn more about wheel file names.

algofarm-0.1.1-cp312-abi3-win_amd64.whl (171.2 kB view details)

Uploaded CPython 3.12+Windows x86-64

algofarm-0.1.1-cp312-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (325.9 kB view details)

Uploaded CPython 3.12+manylinux: glibc 2.17+ x86-64

algofarm-0.1.1-cp312-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl (324.1 kB view details)

Uploaded CPython 3.12+manylinux: glibc 2.17+ ARM64

algofarm-0.1.1-cp312-abi3-macosx_11_0_arm64.whl (282.0 kB view details)

Uploaded CPython 3.12+macOS 11.0+ ARM64

algofarm-0.1.1-cp312-abi3-macosx_10_12_x86_64.whl (284.0 kB view details)

Uploaded CPython 3.12+macOS 10.12+ x86-64

File details

Details for the file algofarm-0.1.1-cp312-abi3-win_amd64.whl.

File metadata

  • Download URL: algofarm-0.1.1-cp312-abi3-win_amd64.whl
  • Upload date:
  • Size: 171.2 kB
  • Tags: CPython 3.12+, Windows x86-64
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: maturin/1.14.1

File hashes

Hashes for algofarm-0.1.1-cp312-abi3-win_amd64.whl
Algorithm Hash digest
SHA256 a70c81880fdbc33a0612ff647742cdbf94e60713d63a935b9c1cc19d12941944
MD5 aaa77f8face86a3e0a89a8bef72418ea
BLAKE2b-256 8403c62685475d6ace9e3afaf195e4a86ebd7fce44b87a3912b5d661d400769b

See more details on using hashes here.

File details

Details for the file algofarm-0.1.1-cp312-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for algofarm-0.1.1-cp312-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 a3486090cd3cce7cdfc2dc506d42b7bdbd0f886e2713f75f1591538d2fc9c9eb
MD5 7a972559cf889c6a65858c38f72979d4
BLAKE2b-256 f5e472dc7efc156e7b2f9392e288950ee78d89bfac56a88704427f3cc4f569ed

See more details on using hashes here.

File details

Details for the file algofarm-0.1.1-cp312-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl.

File metadata

File hashes

Hashes for algofarm-0.1.1-cp312-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
Algorithm Hash digest
SHA256 6b16c31373fc597e6914cba22d74e3ae0e503c1f472e4a473501919b14c62262
MD5 378970b9555117d0b139ad9a9de6e50b
BLAKE2b-256 0740348f1bf4ad78d0870b0ed423aeb6d42d3ff8cd49aa600d2e9a621e61b95b

See more details on using hashes here.

File details

Details for the file algofarm-0.1.1-cp312-abi3-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for algofarm-0.1.1-cp312-abi3-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 7ff2eb281780f0f1c387506ab5fd63572015ff726989dc4bf0f3fd837ffb5b40
MD5 0aeb0004f08a46a5f9a7c78a8b8392dd
BLAKE2b-256 8fbd4a53d8cf24554de283a1d29c484932b9de90057143a929e67108d8845d9e

See more details on using hashes here.

File details

Details for the file algofarm-0.1.1-cp312-abi3-macosx_10_12_x86_64.whl.

File metadata

File hashes

Hashes for algofarm-0.1.1-cp312-abi3-macosx_10_12_x86_64.whl
Algorithm Hash digest
SHA256 7abc536e6f8d6ead9724a4e62e156938dada8ebaa5da1db1b6644875686c6b5f
MD5 0120cc67f7a150e973824b8131a24aa0
BLAKE2b-256 28a19a2d778fbc2102b9e566c8ace53f91a9c27d29337ae22f081b41c46bc760

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page