code wiki / _hdl_build / nx_fuzzy.nx
nx_fuzzy.nx source
↩ module page · 42 lines · 1772 B
1// nx_fuzzy.nx -- R-UX-1 of the onsite-search S-class ladder: SOVEREIGN typo/fuzzy tolerance (LIBRARY).
2// A misspelled query ("divorse") should still find the right doc -- the canonical fuzzy-query capability
3// (cited srch_lucene.raw: Lucene's fuzzy query). Implemented as exact Levenshtein edit distance (two-row DP),
4// integer, deterministic. Search use: when a query term has zero exact postings, accept vocab terms within a
5// small edit-distance bound (BK-tree makes that sub-linear -- the named scaling extension).
6//
7// exports: vr_fuzzy (edit distance), vr_fuzzy_within (bounded match). license_tier: ORIGINAL
8import "nx_syscalls.nx"
9
10// Levenshtein edit distance between a[0..na) and b[0..nb). two-row DP, O(na*nb) time, O(nb) space.
11func vr_fuzzy(a: *u8, na: i64, b: *u8, nb: i64) -> i64 {
12 let prev: *i64 = sys_mmap(8*(nb+2)) as *i64
13 let cur: *i64 = sys_mmap(8*(nb+2)) as *i64
14 var j: i64 = 0
15 while j <= nb { prev[j] = j; j = j + 1 }
16 var i: i64 = 1
17 while i <= na {
18 cur[0] = i
19 var k: i64 = 1
20 while k <= nb {
21 var cost: i64 = 1
22 if a[i-1] == b[k-1] { cost = 0 }
23 var m: i64 = prev[k] + 1 // deletion
24 let d: i64 = cur[k-1] + 1 // insertion
25 if d < m { m = d }
26 let r: i64 = prev[k-1] + cost // substitution / match
27 if r < m { m = r }
28 cur[k] = m
29 k = k + 1
30 }
31 var c: i64 = 0
32 while c <= nb { prev[c] = cur[c]; c = c + 1 }
33 i = i + 1
34 }
35 return prev[nb]
36}
37
38// 1 if edit distance(a,b) <= bound, else 0
39func vr_fuzzy_within(a: *u8, na: i64, b: *u8, nb: i64, bound: i64) -> i64 {
40 if vr_fuzzy(a, na, b, nb) <= bound { return 1 }
41 return 0
42}