Skip to main content

hashrope

A BB[2/7] weight-balanced binary tree augmented with polynomial hash metadata at every node.

PyPI version Python 3.10+ License: MIT Tests

Zero dependencies. Pure Python. Python 3.10+.

What it does

hashrope is a rope data structure where every node carries a polynomial hash. This enables:

  • O(k log w) concat and split with strict BB[2/7] rebalancing via Adams-style balanced join
  • O(k log q) repetition encoding via RepeatNode -- represents "repeat this subtree q times" without materializing the data
  • O(k log w) substring hashing without allocating new nodes
  • O(1) whole-sequence hash at any point during streaming ingestion
  • Bounded-memory sliding window that evicts old data while maintaining a running hash of everything seen

All arithmetic uses Mersenne prime modular reduction (bit-shift, no division).

Install

pip install hashrope

Quick start

from hashrope import PolynomialHash, Leaf, rope_concat, rope_split, rope_substr_hash, rope_hash

h = PolynomialHash()

# Build a rope
a = Leaf(b"hello ", h)
b = Leaf(b"world", h)
ab = rope_concat(a, b, h)

# Whole-string hash matches direct computation
assert rope_hash(ab) == h.hash(b"hello world")

# Split at any byte position
left, right = rope_split(ab, 6, h)

# Substring hash without allocation
sub_h = rope_substr_hash(ab, 0, 5, h)
assert sub_h == h.hash(b"hello")

RepeatNode

Encode repetitions in O(log q) time and O(1) space:

from hashrope import PolynomialHash, Leaf, rope_repeat, rope_hash

h = PolynomialHash()
pattern = Leaf(b"ab", h)
repeated = rope_repeat(pattern, 1000, h)  # "ab" x 1000

# Hash computed in O(log 1000), not O(2000)
assert rope_hash(repeated) == h.hash(b"ab" * 1000)

SlidingWindow

Bounded-memory streaming hash with copy-from-window support:

from hashrope import PolynomialHash, SlidingWindow

h = PolynomialHash()
sw = SlidingWindow(d_max=1024, m_max=256)

# Stream data in
sw.append_bytes(b"hello ")
sw.append_bytes(b"world")

# Hash of everything seen so far
assert sw.current_hash() == h.hash(b"hello world")

# Copy-from-window (like LZ77 back-references)
sw.append_copy(offset=5, length=5)  # copies "world" again
assert sw.final_hash() == h.hash(b"hello worldworld")

API reference

Polynomial hash

Function / Class Description
PolynomialHash(prime, base) Hash function over Z/pZ. Default: p = 2^61 - 1, base = 131
PolynomialHash.hash(data) H(data) with +1 byte offset to prevent zero collisions
PolynomialHash.hash_concat(h_a, len_b, h_b) H(A || B) from H(A), |B|, H(B) in O(1)
PolynomialHash.hash_repeat(h_s, d, q) H(S^q) from H(S) and |S| in O(log q)
PolynomialHash.hash_overlap(h_p, d, l, h_prefix) H(P^q || P[0..r-1]) for overlapping references
phi(q, alpha, p) Geometric accumulator: sum of alpha^i for i in [0, q) in O(log q)
mersenne_mod(a, p) Bit-shift reduction mod Mersenne prime
mersenne_mul(a, b, p) Modular multiply via mersenne_mod
MERSENNE_61 2^61 - 1 (default prime)
MERSENNE_127 2^127 - 1 (high-security prime)

Rope nodes

Class Description
Leaf(data, h) Immutable leaf storing a byte sequence. Weight = 1
Internal(left, right, h) Internal node. Hash = H(left) * x^len(right) + H(right)
RepeatNode(child, reps, h) Represents child^reps. Hash via geometric accumulator

Rope operations

Function Time Description
rope_concat(left, right, h) O(k |h_L - h_R|) Concatenate with Adams-style balanced join and BB[2/7] rebalancing
rope_split(node, pos, h) O(k log w) Split at byte position
rope_repeat(node, q, h) O(k log q) Create RepeatNode
rope_substr_hash(node, start, length, h) O(k log w) Substring hash without allocation
rope_len(node) O(1) Total byte length
rope_hash(node) O(1) Hash of represented string
rope_from_bytes(data, h) O(n) Create Leaf from bytes
rope_to_bytes(node) O(n) Reconstruct bytes (for testing)
validate_rope(node) O(w) Assert all 9 invariants hold

SlidingWindow

Method Description
SlidingWindow(d_max, m_max, prime, base) Create window. W = d_max + m_max
.append_bytes(data) Append literal bytes
.append_copy(offset, length) Copy from window (handles overlapping)
.current_hash() H(everything seen) in O(1)
.final_hash() Same as current_hash (alias)
.window_len Current window size in bytes
.pos Total bytes ingested

Mathematical foundation

The data structure and its correctness proofs come from the compressed-domain hashing framework (24 theorems, 14 lemmas, 5 corollaries). Key results used by hashrope:

Result Statement
Theorem 1 (Concatenation) H(A || B) = H(A) * x^{|B|} + H(B)
Theorem 2 (Repetition) H(S^q) = H(S) * Phi(q, x^d)
Theorem 3 (Phi computation) Phi(q, alpha) computable in O(log q) without modular inverse
Theorem 6 (Join) Adams-style balanced join with BB[2/7] rebalancing
Theorem 7 (Split) Split in O(k log w) with RepeatNode splittability
Theorem 8 (Repeat) RepeatNode in O(k log q), O(1) space
Theorem 9 (SubstrHash) Allocation-free substring hashing in O(k log w)
Theorem 11 (Sliding window) Bounded-memory streaming with eviction

Changelog

See CHANGELOG.md for version history and details on the v0.2.1 balance bugfix.

Provenance

Extracted from UHC (Unified Hash-Compression Engine). The rope and polynomial hash modules are verbatim copies with import paths updated. The sliding window is adapted from UHC's SlidingRopeState with the LZ77 dependency removed.

License

MIT

Metadata

Release files for hashrope 0.2.2

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

Source distribution (sdist)

Source distribution for hashrope 0.2.2
File Size Uploaded Provenance
hashrope-0.2.2.tar.gz 27.6 kB Without provenance Details

Built distribution (wheel)

Table of built distributions (wheels) for hashrope 0.2.2
File Interpreter ABI Platform
hashrope-0.2.2-py3-none-any.whl Python 3 none any Details

Total release size: 43.2 kB

Release files / hashrope-0.2.2.tar.gz

Download URL hashrope-0.2.2.tar.gz
Size 27.6 kB
Tags Source
SHA-256 checksum
How to use checksums
881b367afc38b5d32609d3d604e4a19ce27e4eaeb3078e54948bdad69e54b499
BLAKE2b-256 checksum
How to use checksums
9552d8073f3d00eb2682e8192353949addab2049972be78ebff01780da51f8be
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.1.0 CPython/3.12.2

Release files / hashrope-0.2.2-py3-none-any.whl

Download URL hashrope-0.2.2-py3-none-any.whl
Size 15.6 kB
Tags Python 3
SHA-256 checksum
How to use checksums
710112e3aa14a991918a15331c1f418ce9d1c9d93c34a9da09e22be33c68a2d2
BLAKE2b-256 checksum
How to use checksums
38486a779bd0ae7decefff20e58999cb4ab78866eda6f6884874deb5dd149ab6
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.1.0 CPython/3.12.2

Security for hashrope 0.2.2

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.

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