code wiki / _hdl_build / nx_textnorm_lib.nx
nx_textnorm_lib.nx
buildroot/runtime/_hdl_build/nx_textnorm_lib.nx
about
nx_textnorm_lib.nx -- ONE COPY OF THE PRE-SHINGLING NORMALISATION DECISION.
module: nishi-core.search.textnorm
capability: CORE_COMPUTE (pure; reads no conf, touches no store, writes no file)
license_tier: ORIGINAL No hw writes (Rule 26).
WHY THIS EXISTS, MEASURED 2026-08-25 BY THE GATE THAT MOTIVATED IT:
nx_sitededup_gate fingerprints a REAL capture pair -- one document stored twice, the second copy
carrying an HTTP capture header and a bumped revision line -- and measured their Hamming distance
at SIX bits against the published k=3 bar. The collapse pass therefore did NOT collapse the very
duplicate class it was built for. A fingerprint taken over un-normalised bytes cannot: the header
and the revision id are TOKENS, and tokens move bits.
THE ESTABLISHED FIX, and it is not ours: normalise the text BEFORE shingling, and in particular
normalise DIGITS TO A CONSTANT -- the step that collapses counter, date, revision and price
near-duplicates, which is exactly the class our store holds. Charikar (STOC 2002) defines the
fingerprint and Manku/Jain/Das Sarma (WWW 2007) the k=3 bar for 64-bit fingerprints; NEITHER says
anything about what text you hand it, and that omission is where our duplicates were surviving.
The normalisation is the missing half of the published recipe, not an invention of ours.
COMPOSES, NEVER RE-IMPLEMENTS: nx_simhash for the fingerprint (there must stay exactly ONE
fingerprint kernel in the estate) and nx_html_to_text for markup (there must stay exactly ONE
markup stripper). This file adds only what neither has: the capture-header strip and the digit fold.
WHAT IT DELIBERATELY DOES NOT DO: it does not re-implement block-density boilerplate extraction.
bd_fit_text (nx_block_density) is the ruler for that and belongs to the ingest lane, which already
applies it FORWARD. The residue actually present in already-stored rows is the HTTP capture header,
which is what tn_body_offset removes -- precisely, by parsing the header grammar, not by a
heuristic that could eat the first paragraph of a document.
FAILS TOWARD DOING NOTHING IS NOT AVAILABLE HERE, SO SAY SO PLAINLY: every step below can only make
two texts MORE similar, so the direction of any error is a FALSE POSITIVE -- a document wrongly
judged a duplicate and hidden from search. That is why the consumer carries a neg-control of
genuinely different documents and measures its false-positive rate against REAL corpus documents,
never against fixtures written by the same hand that chose the rule.
dependencies 3 imports · 2 importers
imports: nx_syscalls.nxnx_simhash.nxnx_html_to_text.nx
imported by: nx_sitededup.nxnx_sitededup_gate.nx
structs
| none |
consts
| 40 | const TN_ZERO: i64 = 48 |
| 41 | const TN_NINE: i64 = 57 |
| 42 | const TN_LT: i64 = 60 |
| 43 | const TN_SLASH: i64 = 47 |
| 44 | const TN_NL: i64 = 10 |
| 45 | const TN_CR: i64 = 13 |
| 46 | const TN_COLON: i64 = 58 |
| 47 | const TN_HYPHEN: i64 = 45 |
| 48 | const TN_UA: i64 = 65 |
| 49 | const TN_UZ: i64 = 90 |
| 50 | const TN_LA: i64 = 97 |
| 51 | const TN_LZ: i64 = 122 |
| 52 | const TN_WORD: i64 = 8 |
| 53 | const TN_BOX: i64 = 8 |
| 54 | const TN_DEC: i64 = 10 |
| 56 | const TN_H_H: i64 = 72 |
| 57 | const TN_H_T: i64 = 84 |
| 58 | const TN_H_P: i64 = 80 |
functions
| 60 | func tn_is_alpha(c: i64) -> i64 |
| 65 | func tn_is_digit(c: i64) -> i64 |
| 71 | func tn_line_end(src: *u8, n: i64, i0: i64) -> i64 called by 1: tn_body_offset |
| 83 | func tn_is_header_line(src: *u8, n: i64, i0: i64) -> i64 |
| 107 | func tn_body_offset(src: *u8, n: i64) -> i64 |
| 141 | func tn_has_markup(src: *u8, n: i64) -> i64 |
| 163 | func tn_fold_digits(src: *u8, n: i64, out: *u8, cap: i64, box: *i64) -> i64 |
| 181 | func tn_normalize(src: *u8, n: i64, out: *u8, cap: i64, box: *i64) -> i64 called by 1: tn_fingerprint_box calls 6: tn_body_offsettn_has_markupsys_mmapnx_html_to_texttn_fold_digitssys_munmap |
| 210 | func tn_fingerprint_box(src: *u8, n: i64, box: *i64) -> i64 called by 3: sd_fp_ofmaintn_fingerprint calls 4: sys_mmaptn_normalizenx_simhash_fingerprintsys_munmap |
| 222 | func tn_fingerprint(src: *u8, n: i64) -> i64 |
| 235 | func tn_mkfpnkey(cid: i64, out: *u8) -> i64 |