nx_hamming.nx source
↩ module page · 66 lines · 2381 B
1// nx_hamming.nx -- Hamming distance for equal-length byte sequences.
2//
3// Counts positions at which corresponding bytes differ. Applies ONLY
4// to strings of equal length -- non-equal lengths are an error (return
5// NX_HAMMING_LENGTH_MISMATCH sentinel). Useful when the substrate has
6// already aligned the sequences (fixed-width tokens, error-correction
7// codes, hashes-of-equal-bit-width, DNA k-mers of fixed k).
8//
9// Cross-modal: bytes of any signal (pixels, audio samples quantized
10// to u8, code tokens, network packet headers).
11//
12// Idea-provenance (patent-clean): Hamming 1950 "Error detecting and
13// error correcting codes" Bell System Technical Journal.
14//
15// genealogy_id: hamming_1950_error_detecting_codes
16// lineage_id: hamming_distance_q10
17
18// nx_safety_envelope:
19// intended_use: AUTO_APPLIED -- primitive-specific tuning queued
20// sil_target: SIL1
21// evidence: [bulk_applied_2026-05-16, see-file-comment-for-detail]
22// verdict: NOT_YET_EVALUATED
23
24import "nx_syscalls.nx"
25import "nx_tier.nx"
26import "nx_jaro_winkler.nx"
27
28const NX_HAMMING_Q: nx_int = 1024
29const NX_HAMMING_LENGTH_MISMATCH: nx_int = -1
30
31// ===== Raw distance ==================================================
32
33func nx_hamming(s1: *u8, s2: *u8, n: nx_int) -> nx_int {
34 if n <= 0 { return 0 }
35 var count: nx_int = 0
36 var i: nx_int = 0
37 while i < n {
38 if s1[i] != s2[i] { count = count + 1 }
39 i = i + 1
40 }
41 return count
42}
43
44// Length-checked variant; returns NX_HAMMING_LENGTH_MISMATCH if lengths
45// disagree. Use when caller can't guarantee equal length.
46func nx_hamming_safe(s1: *u8, n1: nx_int, s2: *u8, n2: nx_int) -> nx_int {
47 if n1 != n2 { return NX_HAMMING_LENGTH_MISMATCH }
48 return nx_hamming(s1, s2, n1)
49}
50
51// ===== Q10 similarity (1 - d/n) =====================================
52
53func nx_hamming_similarity_q10(s1: *u8, s2: *u8, n: nx_int) -> nx_int {
54 if n <= 0 { return NX_HAMMING_Q }
55 let d: nx_int = nx_hamming(s1, s2, n)
56 let asym: nx_int = (d * NX_HAMMING_Q) / n
57 if asym >= NX_HAMMING_Q { return 0 }
58 return NX_HAMMING_Q - asym
59}
60
61// ===== Qualitative classifier (shared NX_STRSIM_* bands from
62// nx_jaro_winkler.nx -- single source of truth across the family) ====
63
64func nx_hamming_classify(similarity_q10: nx_int) -> nx_int {
65 return nx_jaro_winkler_classify(similarity_q10)
66}