code wiki / _hdl_build / nx_isotope_ingest.nx

nx_isotope_ingest.nx source

↩ module page · 138 lines · 7396 B

1// nx_isotope_ingest.nx -- chemistry external-reference loop, ingest stage. Reads the FOUNDATIONED NIST 2// Atomic Weights data (knowledge/fetched/nist/atomic_weights.raw, CID'd + signed by nx_isotope_foundation) 3// and MECHANICALLY extracts each isotope's (Atomic Number Z, Mass Number A, Relative Atomic Mass) from the 4// "key = value" records, converting the mass to Q4 micro-AMU (mass*10000, rounded) to match our periodic 5// table's iso_mass_q4 scaling. Writes a content-addressed canonical record per isotope into the sovereign 6// seg_store (prefix knowledge/store/isotope-, key "iso:<Z>:<A>") -- the SSOT, NOT a TSV. 7// 8// Parse: a record's "Relative Atomic Mass =" line always follows its "Atomic Number =" and "Mass Number =" 9// lines, so we carry cur_z/cur_a and emit on the mass line. Value like "15.99491461957(72)" -> stop at '(', 10// Q4 = int*10000 + 4 decimals + round(5th). Baked self-test: iso:1:1 -> 10078 (H-1), iso:6:12 -> 120000 11// (C-12 exactly). license_tier: ORIGINAL 12import "nx_syscalls.nx" 13import "nx_canon_cid.nx" 14import "nx_seg_store.nx" 15import "nx_uxf_decode.nx" 16const II_MAGIC_10000: i64 = 10000 17const II_MAGIC_262144: i64 = 262144 18 19const II_RAW: *u8 = "knowledge/fetched/nist/atomic_weights.raw" 20const II_STORE: *u8 = "knowledge/store/isotope-" 21 22func iw(fd: i64, s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8){n=n+1} sys_write(fd,s,n); return 0 } 23func iwn(fd: i64, v: i64) -> i64 { let b: *u8=sys_mmap(16); var m: i64=v; let t: *u8=sys_mmap(16); var k: i64=0; if m==0{t[0]=48 as u8;k=1}; while m>0{t[k]=(48+(m%10)) as u8;m=m/10;k=k+1}; var i: i64=0; while i<k{b[i]=t[k-1-i];i=i+1}; sys_write(fd,b,k); return 0 } 24func ii_streq(a: *u8, b: *u8) -> i64 { var i: i64=0; while a[i]!=(0 as u8){ if a[i]!=b[i]{return 0} i=i+1 } if b[i]!=(0 as u8){return 0} return 1 } 25func ii_itoa(v: i64, dst: *u8) -> i64 { var m: i64=v; let t: *u8=sys_mmap(24); var k: i64=0; if m==0{t[0]=48 as u8;k=1}; while m>0{t[k]=(48+(m%10)) as u8;m=m/10;k=k+1}; var i: i64=0; while i<k{dst[i]=t[k-1-i];i=i+1} dst[k]=0 as u8; return k } 26 27func ii_read(path: *u8, buf: *u8, cap: i64) -> i64 { 28 let fd: i64 = sys_openat_rd(path) 29 if fd < 0 { return 0 } 30 var n: i64 = 0 31 var r: i64 = sys_read(fd, buf, cap - 1) 32 while r > 0 { n = n + r; if n >= cap - 1 { r = 0 } else { r = sys_read(fd, buf + n, cap - 1 - n) } } 33 sys_close(fd); buf[n] = 0 as u8 34 return n 35} 36 37// does line [ls,le) start with prefix (after leading whitespace)? return index after prefix, or -1. 38func ii_starts(buf: *u8, ls: i64, le: i64, prefix: *u8) -> i64 { 39 var p: i64 = ls 40 while p < le { if buf[p]==(32 as u8) { p=p+1 } else { break } } 41 var i: i64 = 0 42 while prefix[i] != (0 as u8) { 43 if p + i >= le { return 0 - 1 } 44 if buf[p+i] != prefix[i] { return 0 - 1 } 45 i = i + 1 46 } 47 return p + i 48} 49func ii_int(buf: *u8, pos: i64, le: i64) -> i64 { 50 var i: i64 = pos 51 while i < le { if buf[i]==(32 as u8) { i=i+1 } else { break } } 52 var v: i64 = 0 53 while i < le { if buf[i]>=(48 as u8) { if buf[i]<=(57 as u8) { v=v*10+(buf[i]-48); i=i+1 } else { break } } else { break } } 54 return v 55} 56// parse "<int>.<decimals>(unc)" at pos -> value*10000 rounded (Q4 micro-AMU). 57func ii_q4(buf: *u8, pos: i64, le: i64) -> i64 { 58 var i: i64 = pos 59 while i < le { if buf[i]==(32 as u8) { i=i+1 } else { break } } 60 var ip: i64 = 0 61 while i < le { if buf[i]>=(48 as u8) { if buf[i]<=(57 as u8) { ip=ip*10+(buf[i]-48); i=i+1 } else { break } } else { break } } 62 var q4: i64 = ip * II_MAGIC_10000 63 if i < le { if buf[i]==(46 as u8) { 64 i = i + 1 65 var dpos: i64 = 0; var mult: i64 = 1000; var d5: i64 = 0 66 while dpos < 5 { 67 if i < le { if buf[i]>=(48 as u8) { if buf[i]<=(57 as u8) { 68 let d: i64 = buf[i] - 48 69 if dpos < 4 { q4 = q4 + d*mult; mult = mult/10 } else { d5 = d } 70 i = i + 1; dpos = dpos + 1 71 } else { break } } else { break } } else { break } 72 } 73 if d5 >= 5 { q4 = q4 + 1 } 74 } } 75 return q4 76} 77 78func main() -> i64 { 79 let buf: *u8 = sys_mmap(II_MAGIC_262144) 80 let n: i64 = ii_read(II_RAW, buf, II_MAGIC_262144) 81 if n <= 0 { iw(2, "ISOTOPE-INGEST verdict=RED reason=no-raw (run nx_isotope_foundation/fetch first)\n" as *u8); sys_exit(11); return 11 } 82 83 let sw: *i64 = ss_begin() 84 var cur_z: i64 = 0; var cur_a: i64 = 0; var count: i64 = 0 85 86 var ls: i64 = 0; var i: i64 = 0 87 while i <= n { 88 var eol: i64 = 0 89 if i==n { eol=1 } else { if buf[i]==(10 as u8) { eol=1 } } 90 if eol==1 { 91 let pz: i64 = ii_starts(buf, ls, i, "Atomic Number = " as *u8) 92 if pz >= 0 { cur_z = ii_int(buf, pz, i) } 93 else { 94 let pa: i64 = ii_starts(buf, ls, i, "Mass Number = " as *u8) 95 if pa >= 0 { cur_a = ii_int(buf, pa, i) } 96 else { 97 let pm: i64 = ii_starts(buf, ls, i, "Relative Atomic Mass = " as *u8) 98 if pm >= 0 { 99 let q4: i64 = ii_q4(buf, pm, i) 100 if cur_z > 0 { if cur_a > 0 { 101 let q4s: *u8 = sys_mmap(24); ii_itoa(q4, q4s) 102 let rk: *i64 = sys_mmap(16) as *i64; let rv: *i64 = sys_mmap(16) as *i64 103 rk[0] = "mass_q4" as *u8 as i64; rv[0] = q4s as i64 104 let recb: *u8 = sys_mmap(256); let recl: i64 = canon_encode(rk, rv, 1, recb) 105 let kb: *u8 = sys_mmap(64); var kn: i64 = 0 106 let kp: *u8 = "iso:" as *u8; var ki: i64 = 0 107 while kp[ki]!=(0 as u8){ kb[kn]=kp[ki]; kn=kn+1; ki=ki+1 } 108 kn = kn + ii_itoa(cur_z, ((kb as i64)+kn) as *u8) 109 kb[kn]=58 as u8; kn=kn+1 110 kn = kn + ii_itoa(cur_a, ((kb as i64)+kn) as *u8) 111 ss_add(sw, 1, kb, recb, recl) 112 count = count + 1 113 } } 114 } 115 } 116 } 117 ls = i + 1 118 } 119 i = i + 1 120 } 121 let segid: i64 = sys_now_ms() 122 ss_commit(II_STORE, sw, segid) 123 124 // self-test: round-trip two exact-known isotopes from the sovereign store 125 var st: i64 = 1 126 let gp: *i64 = sys_mmap(8) as *i64; let gl: *i64 = sys_mmap(8) as *i64 127 let dk: *i64 = sys_mmap(64) as *i64; let dv: *i64 = sys_mmap(64) as *i64 128 var h1: *u8 = "?" as *u8; var c12: *u8 = "?" as *u8 129 if ss_get(II_STORE, "iso:1:1" as *u8, gp, gl)==1 { let nf: i64=canon_decode(gp[0] as *u8, gl[0], dk, dv, 8); var f: i64=0; while f<nf { if ii_streq(dk[f] as *u8, "mass_q4" as *u8)==1 { h1 = dv[f] as *u8 } f=f+1 } } else { st=0 } 130 if ss_get(II_STORE, "iso:6:12" as *u8, gp, gl)==1 { let nf: i64=canon_decode(gp[0] as *u8, gl[0], dk, dv, 8); var f: i64=0; while f<nf { if ii_streq(dk[f] as *u8, "mass_q4" as *u8)==1 { c12 = dv[f] as *u8 } f=f+1 } } else { st=0 } 131 if ii_streq(h1, "10078" as *u8) != 1 { st = 0 } 132 if ii_streq(c12, "120000" as *u8) != 1 { st = 0 } 133 134 iw(1, "ISOTOPE-INGEST stored=" as *u8); iwn(1, count) 135 iw(1, " H-1=" as *u8); iw(1, h1); iw(1, " C-12=" as *u8); iw(1, c12) 136 if st==1 { iw(1, " selftest=OK verdict=GREEN\n" as *u8); sys_exit(0); return 0 } 137 iw(1, " selftest=FAIL verdict=RED\n" as *u8); sys_exit(1); return 1 138}