nx_imgsearch_engine.nx
buildroot/runtime/nx_imgsearch_engine.nx
about
nx_imgsearch_engine.nx -- THE MULTI-TIER REVERSE-IMAGE QUERY ENGINE.
Replaces the shipped single-tier client (nx_image_search) on two counts, both of them load-bearing:
1. IT SCALES. The shipped client ranks by scanning every fingerprint and then SELECTION-SORTING the
whole corpus -- O(N^2). At 1,000 images that is a million comparisons; at the 10^6 an indie image
index reaches it is 10^12 and the query never returns. Here every tier extracts its top-K through
a BOUNDED MAX-HEAP of size K: O(N log K) time and O(K) space, with N touched exactly once. Going
from 10^3 to 10^6 images multiplies the work by 10^3, not 10^6.
2. IT FUSES. One descriptor cannot cover the modification space (nx_imgbench proves it class by
class), so the engine runs every registered tier and combines their ranked lists with RECIPROCAL
RANK FUSION -- score = sum over tiers of weight / (K_RRF + rank). RRF is the fusion the S-Class IR
literature settles on precisely because it needs no score calibration between rankers: a Hamming
distance over 64 bits and an L1 distance over 80 dimensions are never comparable as magnitudes,
but their RANKS always are. Same integer discipline as the text engine -- no floats anywhere.
The engine holds only base-class tier pointers. Adding local-feature or semantic matching is a new
nx_imgtier subtype plus one add_tier call; this file does not change. That is the design contract.
genealogy_id: cormack_2009_reciprocal_rank_fusion + williams_1975_bounded_heap_selection
license_tier: ORIGINAL
dependencies 2 imports · 3 importers
imports: nx_imgsearch_tier.nxnx_phash_index.nx
imported by: nx_imgbench.nxnx_imgsearch.nxnx_imgsearch_engine_gate.nx
structs
| 38 | struct nx_bkaccel |
| 47 | struct nx_imgengine |
consts
| 25 | const NX_MAGIC_1000000: i64 = 1000000 |
| 27 | const NX_IE_MAXTIERS: i64 = 8 |
| 28 | const NX_IE_MAXK: i64 = 64 |
| 29 | const NX_IE_RRF_K: i64 = 60 // Cormack/Clarke/Buettcher 2009 -- damps the top-rank monopoly |
| 45 | const NX_BKACCEL_BYTES: i64 = 40 |
| 58 | const NX_IMGENGINE_BYTES: i64 = 64 |
functions
| 60 | func nx_imgengine_count(e: *nx_imgengine) -> i64 { return e.count } called by 1: main |
| 61 | func nx_imgengine_cap(e: *nx_imgengine) -> i64 { return e.cap } |
| 62 | func nx_imgengine_ntiers(e: *nx_imgengine) -> i64 { return e.ntiers } |
| 63 | func nx_imgengine_last_visited(e: *nx_imgengine) -> i64 { return e.last_visited } called by 1: main |
| 64 | func nx_imgengine_tier(e: *nx_imgengine, i: i64) -> *nx_imgtier |
| 69 | func nx_imgengine_new(cap: i64) -> *nx_imgengine |
| 85 | func ie_accel(e: *nx_imgengine, ti: i64) -> *nx_bkaccel |
| 92 | func ie_tier_is_hash(t: *nx_imgtier) -> i64 |
| 103 | func nx_imgengine_add_tier(e: *nx_imgengine, t: *nx_imgtier) -> i64 |
| 128 | func ie_desc_at(e: *nx_imgengine, ti: i64, i: i64) -> *i64 |
| 138 | func nx_imgengine_add_image(e: *nx_imgengine, gray: *u8, rgb: *u8, w: i64, h: i64, payload: i64) -> i64 called by 3: mains_verb_selftestmain calls 5: nx_imgengine_tierie_desc_atnx_imgtier_describe_indexie_accelpi_insert |
| 161 | func ie_swap(hd: *i64, hp: *i64, a: i64, b: i64) -> i64 |
| 166 | func ie_heap_up(hd: *i64, hp: *i64, start: i64) -> i64 |
| 177 | func ie_heap_down(hd: *i64, hp: *i64, n: i64, start: i64) -> i64 |
| 191 | func ie_heap_offer(hd: *i64, hp: *i64, nbox: *i64, k: i64, key: i64, item: i64) -> i64 called by 3: ie_tier_topk_bknx_imgengine_tier_topknx_imgengine_query_class calls 2: ie_heap_upie_heap_down |
| 207 | func ie_heap_drain(hd: *i64, hp: *i64, n_in: i64, out_key: *i64, out_item: *i64) -> i64 |
| 229 | func ie_tier_topk_bk(e: *nx_imgengine, ti: i64, qdesc: *i64, k: i64, |
| 276 | func nx_imgengine_tier_topk(e: *nx_imgengine, ti: i64, qdesc: *i64, k: i64, |
| 309 | func nx_imgengine_query_class(e: *nx_imgengine, gray: *u8, rgb: *u8, w: i64, h: i64, topk: i64, |
| 424 | func nx_imgengine_query(e: *nx_imgengine, gray: *u8, rgb: *u8, w: i64, h: i64, topk: i64, |
| 438 | func nx_imgengine_best_match_r(e: *nx_imgengine, gray: *u8, rgb: *u8, w: i64, h: i64, |
| 472 | func nx_imgengine_best_match(e: *nx_imgengine, gray: *u8, rgb: *u8, w: i64, h: i64, |