Skip to main content
Pre-release

This release is a pre-release and may not be stable for production use.

fortran-nlp-kernels

Python Fortran Platform License Version

Python-facing exact lexical and dense-vector similarity search backed by Fortran, OpenMP, and OpenBLAS.

fortran-nlp-kernels provides a clean Python API while executing the computational kernels in compiled native code. The initial CPU beta includes exact word-shingle Jaccard search, exact inner-product search, exact squared-L2 search, cosine similarity, multicore OpenMP execution, and batched BLAS search.

Beta status

0.1.0b2 is the current Linux CPU beta.

This release adds batched lexical Jaccard search, automatic backend selection, expanded input validation, package-version exposure, and tested manylinux wheels for CPython 3.10–3.13.

The beta is intended for evaluation, reproducible systems work, and early integration. Public APIs may still evolve before the stable 0.1.0 release.

Included

  • Exact word-shingle Jaccard search
  • Serial Fortran lexical scoring
  • OpenMP Fortran lexical scoring
  • Exact inner-product vector search
  • Exact squared-L2 vector search
  • Exact cosine-similarity search
  • Serial Fortran vector scoring
  • OpenMP Fortran vector scoring
  • OpenBLAS SGEMV single-query search
  • OpenBLAS SGEMM batched-query search
  • Exact top-k selection
  • NumPy correctness references
  • Python, native Fortran, C ABI, and integration tests
  • Batched lexical Jaccard search
  • OpenMP parallelism across candidate-document pairs
  • Automatic backend selection
  • CPython 3.10–3.13 manylinux wheels

Current limitations

  • Linux x86-64 only
  • Result IDs are currently zero-based positional indexes
  • Batched lexical search requires backend="fortran_openmp" or backend="auto"
  • Batched vector search requires backend="fortran_blas" or backend="auto"
  • Handwritten top-k selection currently uses an O(Nk) reference implementation
  • CUDA Fortran and GPU backends are not included in this beta

Architecture

Python public API
        ↓
Python validation, preprocessing, and orchestration
        ↓
nanobind C++ extension
        ↓
stable C ABI
        ↓
Fortran / OpenMP / OpenBLAS kernels

The native lexical path is separated into focused layers:

lexical_core.f90     → lexical algorithms
lexical_c_api.f90    → Fortran-to-C adapter
.h header            → C declarations
cpu_bindings.cpp     → C-to-Python adapter

The vector-search path follows the same structure:

vector_search_core.f90   → handwritten IP and squared-L2 kernels
vector_search_blas.f90   → SGEMV and SGEMM implementations
topk_core.f90            → exact top-k selection
vector_search_c_api.f90  → Fortran-to-C adapter
cpu_bindings.cpp         → C-to-Python adapter

Platform support

The initial 0.1.0b1 wheel targets CPython 3.12. The current development branch is continuously built and tested for:

Operating system: Linux 
Architecture: x86-64 
Python: CPython 3.10, 3.11, 3.12, and 3.13 
Wheel policy: manylinux_2_28

The source package declares Python 3.10 or newer, but this beta has currently been built and validated with CPython 3.12 on Ubuntu 24.04.

System prerequisites

Installing the prebuilt Linux wheel

The published manylinux wheel bundles the required non-policy native libraries. No Fortran compiler or OpenBLAS development package is needed when installing a compatible prebuilt wheel.

Building from source

Install the compiler and development libraries:

sudo apt update
sudo apt install gfortran g++ libopenblas-dev libgomp1

A source build also requires a supported Python environment and pip. Build-time Python dependencies are installed through pyproject.toml.

Installation

PyPI Beta

Install the latest available pre-release:

python -m pip install --pre fortran-nlp-kernels

To request this exact beta:

python -m pip install fortran-nlp-kernels==0.1.0b2

Local wheel

Download the wheel matching the installed CPython version from the GitHub release or CI artifacts, then install it by path:

python -m pip install \ 
    ./fortran_nlp_kernels-0.1.0b2-cp312-cp312-manylinux_2_28_x86_64.whl

Editable source installation

git clone https://github.com/suwesh/fortran-nlp-kernels.git
cd fortran-nlp-kernels
python -m pip install -e .

Quick start

from fortran_nlp.lexical import JaccardIndex

index = JaccardIndex(
    [
        "reset the account password",
        "update seller information",
        "create a new loan application",
    ],
    backend="fortran_openmp",
)

results = index.search(
    "how to reset the account password",
    k=2,
    minimum_score=0.01,
)

for result in results:
    print(result)

Example result:

JaccardResult(
    document_id=0,
    score=0.5,
    intersection_count=2,
    union_count=4
)

Text preprocessing performs Unicode normalization, case folding, fixed-size word shingling, deterministic 64-bit hashing, sorting, and deduplication before invoking the native kernel.

JaccardIndex.search_batch() compares multiple candidate texts against the same indexed corpus.

from fortran_nlp.lexical import JaccardIndex

index = JaccardIndex(
    [
        "reset the account password",
        "update seller information",
        "create a new loan application",
    ],
    backend="auto",
)

batch_results = index.search_batch(
    [
        "how to reset the account password",
        "seller information update",
    ],
    k=2,
    minimum_score=0.01,
)

for candidate_index, candidate_results in enumerate(batch_results):
    print(candidate_index, candidate_results)

The return type is:

list[list[JaccardResult]]

The outer list contains one entry per candidate. Each inner list contains the ranked corpus matches for that candidate.

Candidate shingles are stored in a packed variable-length representation with candidate offsets. The OpenMP backend distributes independent candidate-document comparisons across threads.

Batched lexical search requires:

backend="fortran_openmp"

or:

backend="auto"

Use OMP_NUM_THREADS to control parallel execution.

The Python-facing database layout is:

(vector_count, dimension)

All public vector-search inputs are converted to contiguous float32 arrays. The package internally stores the database in a Fortran-compatible native layout.

Inner product

Higher scores are better.

import numpy as np

from fortran_nlp.vector_search import FlatIndexIP

database = np.array(
    [
        [1.0, 2.0, 3.0],
        [4.0, 5.0, 6.0],
        [-1.0, 2.0, 1.0],
    ],
    dtype=np.float32,
)

query = np.array(
    [1.0, 2.0, 3.0],
    dtype=np.float32,
)

index = FlatIndexIP(
    database,
    backend="fortran_openmp",
)

scores, ids = index.search(query, k=2)

print(scores)
print(ids)

Squared-L2 distance

Lower distances are better. The package returns squared Euclidean distance and does not calculate the square root.

from fortran_nlp.vector_search import FlatIndexL2

index = FlatIndexL2(
    database,
    backend="fortran",
)

distances, ids = index.search(query, k=2)

Cosine similarity

Database vectors and queries are L2-normalized, then searched using the inner-product backend.

from fortran_nlp.vector_search import FlatIndexCosine

index = FlatIndexCosine(
    database,
    backend="fortran_blas",
)

scores, ids = index.search(query, k=2)

Zero vectors cannot be used with FlatIndexCosine because cosine normalization is undefined for a zero norm.

Batched search uses OpenBLAS SGEMM and currently requires:

backend="fortran_blas"

The public query layout is:

(query_count, dimension)

Example:

queries = np.array(
    [
        [1.0, 2.0, 3.0],
        [0.0, 1.0, 0.0],
    ],
    dtype=np.float32,
)

index = FlatIndexIP(
    database,
    backend="fortran_blas",
)

scores, ids = index.search_batch(
    queries,
    k=2,
)

print(scores.shape)  # (query_count, k)
print(ids.shape)     # (query_count, k)

FlatIndexL2 and FlatIndexCosine expose the same search_batch() interface.

Backends

fortran          → handwritten serial Fortran
fortran_openmp   → handwritten OpenMP Fortran
fortran          → handwritten serial Fortran
fortran_openmp   → handwritten OpenMP Fortran
fortran_blas     → OpenBLAS SGEMV/SGEMM through Fortran

Automatic backend selection

Both public index families accept:

backend="auto"

The current deterministic policy is:

JaccardIndex
auto → fortran_openmp

FlatIndexIP
FlatIndexL2
FlatIndexCosine
auto → fortran_blas

Example:

from fortran_nlp.lexical import JaccardIndex
from fortran_nlp.vector_search import FlatIndexCosine

lexical_index = JaccardIndex(
    corpus_texts,
    backend="auto",
)

vector_index = FlatIndexCosine(
    database_vectors,
    backend="auto",
)

The current policy selects stable production defaults. It does not benchmark the host machine dynamically. Future releases may use measured workload crossover points to refine automatic selection.

Thread control

The handwritten OpenMP and OpenBLAS backends use different thread controls.

Handwritten OpenMP backend

OMP_NUM_THREADS=4 python your_script.py

OpenBLAS backend

OPENBLAS_NUM_THREADS=4 python your_script.py

For controlled benchmarks, avoid enabling high thread counts in both runtimes simultaneously:

# Handwritten serial
OMP_NUM_THREADS=1 OPENBLAS_NUM_THREADS=1 python benchmark.py

# Handwritten OpenMP
OMP_NUM_THREADS=12 OPENBLAS_NUM_THREADS=1 python benchmark.py

# BLAS
OMP_NUM_THREADS=1 OPENBLAS_NUM_THREADS=12 python benchmark.py

The library does not globally overwrite these environment variables.

Correctness and tests

The implementation is validated across several boundaries:

native Fortran core tests
C ABI tests
nanobind extension tests
NumPy equivalence tests
serial/OpenMP equivalence tests
BLAS/handwritten equivalence tests
single-query and batched-query tests
public Python API tests
input-validation and edge-case tests
deterministic tie-handling tests
package-metadata tests
wheel smoke tests

The 0.1.0b2 release passes 98 Python tests covering lexical search, batched lexical search, exact vector search, native bindings, automatic backend selection, memory layouts, input validation, deterministic tie handling, and package metadata.

Run the Python test suite:

OPENBLAS_NUM_THREADS=1 \
OMP_NUM_THREADS=4 \
python -m pytest tests/ -v

Native test programs are available under:

tests/native/

Continuous integration

The repository includes two Linux CI workflows:

CPU Tests
→ builds the package from source
→ runs the complete test suite on CPython 3.10–3.13

Build Linux Wheels
→ builds and tests manylinux wheels with cibuildwheel
→ targets CPython 3.10, 3.11, 3.12, and 3.13

The wheel workflow runs manually or when a version tag matching v* is pushed. Generated wheels are stored as temporary workflow artifacts. The workflow does not automatically attach wheels to GitHub Releases or upload them to PyPI.

Build system

The project uses:

meson-python  → Python build backend
Meson         → native build configuration
GFortran      → Fortran compilation
nanobind      → compiled Python extension
OpenMP        → handwritten multicore kernels
OpenBLAS      → SGEMV and SGEMM vector-search backends

Build the wheel and source distribution:

python -m pip install build
rm -rf dist/ build/ .mesonpy-*
python -m build

Expected release artifacts:

fortran_nlp_kernels-0.1.0b2-cp310-cp310-manylinux_2_28_x86_64.whl
fortran_nlp_kernels-0.1.0b2-cp311-cp311-manylinux_2_28_x86_64.whl
fortran_nlp_kernels-0.1.0b2-cp312-cp312-manylinux_2_28_x86_64.whl
fortran_nlp_kernels-0.1.0b2-cp313-cp313-manylinux_2_28_x86_64.whl
fortran_nlp_kernels-0.1.0b2.tar.gz

Validate distribution metadata and README rendering:

python -m pip install twine
python -m twine check dist/*

Research direction

The library is being developed as a reusable software artifact and performance-engineering study covering:

  • exact lexical and dense-vector similarity search;
  • Python/native interface overhead;
  • serial and multicore CPU scaling;
  • handwritten Fortran versus optimized BLAS;
  • C++ and CUDA C++ research baselines;
  • CUDA Fortran and cuBLAS backends;
  • CPU/GPU crossover points;
  • kernel-only and end-to-end performance.

Working technical-report title:

Fortran Kernels for NLP: Exact Lexical and Vector Similarity Search Across Multicore CPUs and NVIDIA GPUs

Roadmap

Planned follow-up work includes:

  • benchmark-informed automatic backend selection;
  • benchmark-informed OpenMP scheduling for batched lexical search;
  • optional document and vector IDs;
  • handwritten serial and OpenMP batched vector-search baselines;
  • optimized exact top-k selection;
  • CPU performance evaluation against NumPy, C++, and FAISS;
  • automated PyPI Trusted Publishing;
  • CUDA Fortran lexical and vector-search kernels;
  • cuBLAS-backed vector search;
  • CUDA C++ research baselines;
  • FAISS GPU exact-flat comparisons;
  • GPU-resident corpora and vector databases.

License

This project is licensed under GPL-3.0-only. See LICENSE.

Author

Suwesh Prasad Sah

Metadata

Release files for fortran-nlp-kernels 0.1.0b2

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for fortran-nlp-kernels 0.1.0b2
File Size Uploaded Provenance
fortran_nlp_kernels-0.1.0b2.tar.gz 51.4 kB Without provenance Details

Built distributions (wheels)

Table of built distributions (wheels) for fortran-nlp-kernels 0.1.0b2
File
fortran_nlp_kernels-0.1.0b2-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl CPython 3.13 CPython 3.13 Linux glibc 2.28+ x86-64, Linux glibc 2.27+ x86-64 Details
fortran_nlp_kernels-0.1.0b2-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl CPython 3.12 CPython 3.12 Linux glibc 2.27+ x86-64, Linux glibc 2.28+ x86-64 Details
fortran_nlp_kernels-0.1.0b2-cp311-cp311-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl CPython 3.11 CPython 3.11 Linux glibc 2.27+ x86-64, Linux glibc 2.28+ x86-64 Details
fortran_nlp_kernels-0.1.0b2-cp310-cp310-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl CPython 3.10 CPython 3.10 Linux glibc 2.28+ x86-64, Linux glibc 2.27+ x86-64 Details

Total release size: 48.8 MB

Release files / fortran_nlp_kernels-0.1.0b2.tar.gz

Download URL fortran_nlp_kernels-0.1.0b2.tar.gz
Size 51.4 kB
Tags Source
SHA-256 checksum
How to use checksums
ee9064f3204166135c0d6479ff3092a60794867039d1e670695f6d04b329efe6
BLAKE2b-256 checksum
How to use checksums
5ff47811132575f4284408cdf495857d6acbe9d2769ca25b69abf22ead7694ef
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.12.3

Release files / fortran_nlp_kernels-0.1.0b2-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl

Download URL fortran_nlp_kernels-0.1.0b2-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
Size 12.2 MB
Tags CPython 3.13 Linux glibc 2.27+ x86-64 Linux glibc 2.28+ x86-64
SHA-256 checksum
How to use checksums
2f9944d209b7281202a6cfc6f57a857cf08521e368622a0b5d507d9534c6dbdb
BLAKE2b-256 checksum
How to use checksums
f9bb04db441b9ebf053c333c5e04f98c25cc8fe6513c322ed90253b3591db299
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.12.3

Release files / fortran_nlp_kernels-0.1.0b2-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl

Download URL fortran_nlp_kernels-0.1.0b2-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
Size 12.2 MB
Tags CPython 3.12 Linux glibc 2.27+ x86-64 Linux glibc 2.28+ x86-64
SHA-256 checksum
How to use checksums
ec1c296df9642a91cedba0900de001f4618b10b78b36e5927e6f659b434d2d47
BLAKE2b-256 checksum
How to use checksums
a7cc6e13c7854a7e37b652e27c6e0bf5dfd03afb8cc0703fde45b113aaef9a72
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.12.3

Release files / fortran_nlp_kernels-0.1.0b2-cp311-cp311-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl

Download URL fortran_nlp_kernels-0.1.0b2-cp311-cp311-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
Size 12.2 MB
Tags CPython 3.11 Linux glibc 2.27+ x86-64 Linux glibc 2.28+ x86-64
SHA-256 checksum
How to use checksums
17511bb0e077ec1fd96a477ec0a3518863383504e307d6f6a064c17725efe38b
BLAKE2b-256 checksum
How to use checksums
4e2e846ec051d491143401eaaa2bac9b603992ac859bcb62c647ca42b36c16a9
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.12.3

Release files / fortran_nlp_kernels-0.1.0b2-cp310-cp310-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl

Download URL fortran_nlp_kernels-0.1.0b2-cp310-cp310-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
Size 12.2 MB
Tags CPython 3.10 Linux glibc 2.27+ x86-64 Linux glibc 2.28+ x86-64
SHA-256 checksum
How to use checksums
6cbc0d8a969377a688a9d4706941cfc6b53e23d0ae0176b0a047b3c3a8c4b69e
BLAKE2b-256 checksum
How to use checksums
581c8d6b6c0171f856db21f00b72aab4c4320e6d100b1d7da376479df2d10400
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.12.3

Security for fortran-nlp-kernels 0.1.0b2

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page