code wiki / _hdl_build / nx_ocr_recall_lib.nx

nx_ocr_recall_lib.nx source

↩ module page · 104 lines · 3824 B

1// nx_ocr_recall_lib.nx -- the reading-recall SCORING MATH as a shared lib (single-responsibility: the CLI 2// nx_ocr_recall.nx and the gate nx_ocr_recall_gate.nx both call ocr_recall_score, so the gate proves the 3// EXACT code the CLI runs -- no fork/pipe harness to deadlock). Truth-token multiset recall/precision/F1, 4// SQuAD-norm (lowercase, non-alnum->space, articles a/an/the dropped). out[0]=recall out[1]=precision 5// out[2]=f1 out[3]=truth_tokens out[4]=ours_tokens out[5]=matched, all integer permille where a ratio. 6// license_tier: ORIGINAL 7import "nx_syscalls.nx" 8 9const ORL_CAP: i64 = 262144 10const ORL_MAXTOK: i64 = 8192 11 12func orl_norm(src: *u8, n: i64, buf: *u8) -> i64 { 13 var i: i64 = 0 14 while i < n { 15 var c: i64 = (src[i] as i64) & 255 16 if c >= 65 { if c <= 90 { c = c + 32 } } 17 var ok: i64 = 0 18 if c >= 97 { if c <= 122 { ok = 1 } } 19 if c >= 48 { if c <= 57 { ok = 1 } } 20 if ok == 1 { buf[i] = c as u8 } else { buf[i] = 32 as u8 } 21 i = i + 1 22 } 23 return n 24} 25func orl_tok(buf: *u8, n: i64, toff: *i64, tlen: *i64) -> i64 { 26 var cnt: i64 = 0 27 var i: i64 = 0 28 while i < n { 29 var sk: i64 = 1 30 while sk == 1 { 31 if i >= n { sk = 0 } 32 else { if (buf[i] as i64) == 32 { i = i + 1 } else { sk = 0 } } 33 } 34 if i < n { 35 var j: i64 = i 36 var sc: i64 = 1 37 while sc == 1 { 38 if j >= n { sc = 0 } 39 else { if (buf[j] as i64) != 32 { j = j + 1 } else { sc = 0 } } 40 } 41 let L: i64 = j - i 42 var art: i64 = 0 43 if L == 1 { if (buf[i] as i64) == 97 { art = 1 } } 44 if L == 2 { if (buf[i] as i64) == 97 { if (buf[i+1] as i64) == 110 { art = 1 } } } 45 if L == 3 { if (buf[i] as i64) == 116 { if (buf[i+1] as i64) == 104 { if (buf[i+2] as i64) == 101 { art = 1 } } } } 46 if art == 0 { if cnt < ORL_MAXTOK { toff[cnt] = i; tlen[cnt] = L; cnt = cnt + 1 } } 47 i = j 48 } 49 } 50 return cnt 51} 52func orl_eq(a: *u8, ao: i64, al: i64, b: *u8, bo: i64, bl: i64) -> i64 { 53 if al != bl { return 0 } 54 var k: i64 = 0 55 while k < al { if a[ao+k] != b[bo+k] { return 0 } k = k + 1 } 56 return 1 57} 58// score truth (n bytes) vs ours (m bytes) -> out[0..5] 59func ocr_recall_score(truth: *u8, tn0: i64, ours: *u8, on0: i64, out: *i64) -> i64 { 60 let tb: *u8 = sys_mmap(ORL_CAP) 61 let ob: *u8 = sys_mmap(ORL_CAP) 62 var tn: i64 = tn0 63 if tn > ORL_CAP { tn = ORL_CAP } 64 var on: i64 = on0 65 if on > ORL_CAP { on = ORL_CAP } 66 orl_norm(truth, tn, tb) 67 if on > 0 { orl_norm(ours, on, ob) } 68 let t_off: *i64 = sys_mmap(ORL_MAXTOK*8) as *i64 69 let t_len: *i64 = sys_mmap(ORL_MAXTOK*8) as *i64 70 let o_off: *i64 = sys_mmap(ORL_MAXTOK*8) as *i64 71 let o_len: *i64 = sys_mmap(ORL_MAXTOK*8) as *i64 72 let used: *i64 = sys_mmap(ORL_MAXTOK*8) as *i64 73 let ntt: i64 = orl_tok(tb, tn, t_off, t_len) 74 var not_: i64 = 0 75 if on > 0 { not_ = orl_tok(ob, on, o_off, o_len) } 76 var i: i64 = 0 77 while i < not_ { used[i] = 0; i = i + 1 } 78 var hit: i64 = 0 79 i = 0 80 while i < ntt { 81 var j: i64 = 0 82 var done: i64 = 0 83 while j < not_ { 84 if done == 0 { if used[j] == 0 { 85 if orl_eq(tb, t_off[i], t_len[i], ob, o_off[j], o_len[j]) == 1 { used[j] = 1; hit = hit + 1; done = 1 } 86 } } 87 j = j + 1 88 } 89 i = i + 1 90 } 91 var recall: i64 = 0 92 if ntt > 0 { recall = (hit * 1000) / ntt } 93 var prec: i64 = 0 94 if not_ > 0 { prec = (hit * 1000) / not_ } 95 var f1: i64 = 0 96 if recall + prec > 0 { f1 = (2 * recall * prec) / (recall + prec) } 97 out[0] = recall 98 out[1] = prec 99 out[2] = f1 100 out[3] = ntt 101 out[4] = not_ 102 out[5] = hit 103 return 0 104}