nx_phash_index.nx
buildroot/runtime/nx_phash_index.nx
about
nx_phash_index.nx -- SUBLINEAR Hamming-metric index (BK-tree) over 64-bit perceptual
fingerprints. The reverse-image engine (nx_phash / nx_image_search) ranks by a LINEAR O(N)
Hamming scan; that is correct but does not scale to a TinEye-class corpus (10^8..10^10 images).
This adds a metric tree that, for the small-radius near-duplicate regime, prunes the candidate
set to a SUBLINEAR fraction of N via the triangle inequality -- while returning the EXACT same
match set as the linear scan (no recall loss). Integer + deterministic end to end (reuses
nx_simhash_hamming = popcount64 of XOR; ZERO new metric math).
genealogy_id: burkhard_keller_1973_bk_tree (metric tree) over krawetz_2011 dHash fingerprints
WHY a BK-tree: Hamming is a true metric (identity, symmetry, triangle inequality), so for any
node on the path |d(q,node) - d(node,child)| <= d(q,child). A radius-r query can therefore skip
every child whose edge-distance to its parent lies outside [d-r, d+r]. For clustered corpora
(real image collections: near-duplicates + visually-similar groups) this prunes the vast
majority of nodes. HONEST: on uniform-random codes at large radius it degrades toward linear --
that regime is the Multi-Index-Hashing rung (Norouzi 2012), the next step up.
Layout (caller-owned flat arrays, room for `cap` nodes): fp[i], pay[i], and 65 child slots per
node at ch[i*65 + d] (d = Hamming edge distance 0..64 inclusive), each = child node index, or
-1 = empty. The caller owns/sizes the arrays so the index composes with any storage tier.
license_tier: ORIGINAL
dependencies 1 imports · 2 importers
imports: nx_simhash.nx
imported by: nx_imgsearch_engine.nxnx_phash_index_gate.nx
structs
| none |
consts
| 24 | const PI_SLOTS: i64 = 65 // Hamming edge distances 0..64 inclusive |
functions
| 27 | func pi_init_children(ch: *i64, cap: i64) -> i64 |
| 37 | func pi_insert(fp: *i64, pay: *i64, ch: *i64, n: i64, f: i64, p: i64) -> i64 |
| 57 | func pi_query(fp: *i64, pay: *i64, ch: *i64, n: i64, q: i64, r: i64, out: *i64, out_cap: i64, out_visited: *i64) -> i64 |