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}