franken_numpy: FrankenNumPy: Rebuilding NumPy in Safe Rust, Then Proving It Against NumPy Itself

A clean-room array library with one unusual rule: every edge case has to survive a live oracle check, a conformance ledger, and a zero-unsafe codebase.

8 min read • View on GitHub • More from Dicklesworthstone

A split mechanical workshop shows a brittle legacy machine on one side and a precision-built Rust machine on the other, with an inspector's desk between them. It explains the repo's core idea: rebuild NumPy's behavior without trusting the rewrite until the oracle agrees.
The project's central move is not to replace NumPy quietly. It is to rebuild the mechanism while checking every output against the original.

Memory-safe, clean-room NumPy reimplementation in Rust. Zero unsafe code. 2,358 tests. Bit-exact RNG parity. Every feature family green.

Dicklesworthstone, Project Creator and Maintainer · franken_numpy README
Key Takeaways

FrankenNumPy's most interesting move is not that it is written in Rust. It is that it refuses to trust its own behavior unless NumPy agrees.

That turns migration into verification. The project is less a port than a system for proving that a new implementation has not drifted from the old one.

One fixture runs through FrankenNumPy and NumPy, then meets at a comparison gate that writes both a verdict and an evidence trail.

Why NumPy parity is a harder problem than it looks

NumPy compatibility is hard because the visible API is not the real challenge. Broadcasting, dtype promotion, stride semantics, NaN propagation, reshape legality, and random-number behavior all hide tiny rules that real code depends on.

Miss one edge case and you do not get a slightly imperfect replacement. You get code that appears fine until a legacy workload leans on the exact corner you missed.

A crowded clockwork puzzle box is jammed with tiny gears, cams, and spring traps while test cards rain in from above. It represents the hidden complexity of NumPy parity, where edge cases matter more than basic array math.
Parity work is crowded by the tiny rules that live between ordinary array operations.

Inside the Stride Calculus Engine

The Stride Calculus Engine reads like a bureaucracy, but that is the point. Before FrankenNumPy lets an array view, reshape, or broadcast exist, it checks whether the transformation is legal and deterministic.

That fail-closed posture is what keeps the library from pretending that an ambiguous transform is safe. In a numerical stack, maybe is just another word for latent corruption.

#![forbid(unsafe_code)]

The zero-unsafe rule is not cosmetic. It pushes more reasoning into the type system and more invariants into the design, but it also makes the memory-safety claim legible to anyone reading the code.

The conformance harness is the real product

If the stride engine is the skeleton, fnp-conformance is the pulse. It captures a fixture, runs it through FrankenNumPy and a live NumPy process, compares the outputs, and writes the result into parity reports and evidence artifacts.

WSJ-style hedcut portrait of Dicklesworthstone on a white background. It gives a face to the maintainer behind the clean-room rewrite and the conformance pipeline.

That artifact trail matters because the project is not only chasing a passing test. It is preserving the history of how a result was reached, which edge case was exercised, and what the oracle returned when the answer was not obvious.

Strict mode, hardened mode

The runtime split is a good example of FrankenNumPy's temperament. Strict mode is there for exact behavioral fidelity. Hardened mode keeps the same core, then adds guardrails for bounded defensive recovery.

That is a serious trade. Strict mode serves compatibility debugging and parity work. Hardened mode serves deployments that want a safety envelope without pretending every input is well-behaved.

Two similar control panels sit side by side, but one is exposed and spare while the other has shields, recovery levers, and extra guards around the output path. It illustrates the project's split between exact compatibility and bounded defensive recovery.
Strict mode preserves fidelity. Hardened mode adds a second layer of protection.
DimensionStrict modeHardened mode
Behavioral targetMatch NumPy as closely as possibleMatch NumPy plus protective recovery
Failure handlingSurface the same edge-case behavior as the oracleIntervene with bounded defensive checks
Best forCompatibility debugging and parity workRiskier deployments that still want NumPy semantics
TradeoffLess flexibility, more exactnessMore resilience, more policy

What FrankenNumPy is really competing with

The real comparison is not with every Rust array crate. FrankenNumPy sits between a source-of-truth Python library and native Rust tools. Its job is to make old NumPy code safer without making it think differently.

That means it is competing on migration cost, not just on performance charts. For teams with large Python estates, the question is whether semantics survive the move.

ProjectPrimary userCompatibility goalSafety modelWhat it is not
FrankenNumPyPython teams migrating numerical codeDrop-in NumPy parity with live oracle checksSafe Rust, zero unsafe codeNot a faster NumPy clone or a dataframe engine
NumPyScientific Python usersBaseline behavior and ecosystem standardLegacy C, C++, and Python runtimeNot memory-safe by construction
ndarrayRust developersErgonomic n-dimensional arrays in RustNative Rust safety modelNot a Python drop-in
PolarsData and analytics teamsFast dataframe and query workflowsRust core with Python bindingsNot a NumPy parity project

Built like an audit trail

The most distinctive thing about FrankenNumPy may be the paperwork around the code. Parity reports, logging contracts, and durability sidecars turn each run into a record that can be inspected later, not just a transient CI result.

That is where the project stops looking like a library and starts looking like forensic engineering. The evidence trail is not decoration. It is the mechanism that makes the compatibility claim credible.

A secure archive room holds artifact containers, parity reports, and repair-coded sidecars while a clerk files a stamped sheet into a vault. It explains how the repo treats verification as evidence to preserve, not just a test result to discard.
The repo treats compatibility as something worth archiving, not just asserting.

FrankenNumPy's ambition is simple to state and difficult to fake. It wants the safety of Rust, the semantics of NumPy, and a chain of evidence for every hard edge between them.