nx_nxa_morf_admit.nx source
↩ module page · 202 lines · 11018 B
1// ORIGINAL. Allocation-free extraction of mf_eval's FACE/MORF admission.
2// nx_nxa owns the container/checksums. Caller owns immutable file bytes, output
3// view, and one membership byte per vertex. No channel naming policy.
4import "nx_nxa.nx"
5import "nx_morf_eval_core.nx"
6const NMI_E_MISSING: i64 = 0-81
7const NMI_E_SHAPE: i64 = 0-82
8const NMI_E_IDENTITY: i64 = 0-83
9const NMI_E_SCRATCH: i64 = 0-84
10const NMI_FACE_HEADER: i64 = 4
11const NMI_MORF_HEADER: i64 = 4
12const NMI_CHANNEL_WORDS: i64 = 2
13const NMI_R_NO_VERT: i64 = 0-901
14const NMI_R_NO_FACE: i64 = 0-902
15const NMI_R_NO_MORF: i64 = 0-903
16const NMI_R_BAD_VERT: i64 = 0-904
17const NMI_R_BAD_FACE: i64 = 0-905
18const NMI_R_BAD_MORF: i64 = 0-906
19const NMI_R_VERT_SHAPE: i64 = 0-907
20const NMI_R_DUP_VERT: i64 = 0-908
21const NMI_R_DUP_FACE: i64 = 0-909
22const NMI_R_DUP_MORF: i64 = 0-910
23const NMI_R_FACE_HEADER: i64 = 0-911
24const NMI_R_MORF_HEADER: i64 = 0-912
25const NMI_R_EMPTY_VERT: i64 = 0-913
26const NMI_R_EMPTY_FACE: i64 = 0-914
27const NMI_R_FACE_SHAPE: i64 = 0-915
28const NMI_R_FACE_COUNT: i64 = 0-916
29const NMI_R_EMPTY_MORF: i64 = 0-917
30const NMI_R_ROW_COUNT: i64 = 0-918
31const NMI_R_STRIDE: i64 = 0-919
32const NMI_R_UNIT: i64 = 0-920
33const NMI_R_CHANNEL_RECORDS: i64 = 0-921
34const NMI_R_CHANNEL_SHAPE: i64 = 0-922
35const NMI_R_ROW_SHAPE: i64 = 0-923
36const NMI_R_DELTA_COUNT: i64 = 0-924
37const NMI_R_SUPPORT_NEGATIVE: i64 = 0-925
38const NMI_R_SUPPORT_COUNT: i64 = 0-926
39const NMI_R_FACE_NEGATIVE: i64 = 0-927
40const NMI_R_FACE_RANGE: i64 = 0-928
41const NMI_R_FACE_DUPLICATE: i64 = 0-929
42const NMI_R_VERT_FACE: i64 = 0-930
43const NMI_R_VERT_MORF: i64 = 0-931
44const NMI_R_FACE_MORF: i64 = 0-932
45const NMI_R_CHANNEL_RANGE: i64 = 0-933
46struct NmiAsset {
47 view: *MvcView
48 tags: *i64
49 tag_words: i64
50}
51func nmi_scratch_bytes(b: *u8,flen: i64) -> i64 {
52 if flen < 0 { return NMI_E_SHAPE }
53 var file_words: i64 = flen/MVC_WORD
54 if flen%MVC_WORD != 0 { file_words = file_words+1 }
55 if mvc_span(b as *i64,file_words) == 0 { return NMI_E_SHAPE }
56 let vw: i64 = nxa_counted_section(b,flen,nxa_tag4("VERT" as *u8),MVC_AXES)
57 if vw < 0 { return NMI_R_VERT_SHAPE }
58 let h: *i64 = b as *i64
59 if h[vw] < 1 { return NMI_R_EMPTY_VERT }
60 return h[vw]
61}
62func nmi_admit_channel(b: *u8,flen: i64,seen: *u8,seen_bytes: i64,out: *NmiAsset,channel: i64) -> i64 {
63 if flen < 0 { return NMI_E_SHAPE }
64 var file_words: i64 = flen/MVC_WORD
65 if flen%MVC_WORD != 0 { file_words = file_words+1 }
66 if mvc_span(b as *i64,file_words) == 0 { return NMI_E_SHAPE }
67 if mvc_span(out as *i64,__size_of(NmiAsset)/MVC_WORD) == 0 { return NMI_E_SHAPE }
68 let v: *MvcView = out.view
69 if mvc_span(v as *i64,__size_of(MvcView)/MVC_WORD) == 0 { return NMI_E_SHAPE }
70 if nmi_byte_span(seen,seen_bytes) == 0 { return NMI_E_SCRATCH }
71 if nmi_byte_overlap(seen,seen_bytes,b,flen) != 0 { return NMI_E_SCRATCH }
72 if nmi_byte_overlap(seen,seen_bytes,out as *u8,__size_of(NmiAsset)) != 0 { return NMI_E_SCRATCH }
73 if nmi_byte_overlap(seen,seen_bytes,v as *u8,__size_of(MvcView)) != 0 { return NMI_E_SCRATCH }
74 if mvc_overlap(out as *i64,__size_of(NmiAsset)/MVC_WORD,b as *i64,file_words) != 0 { return NMI_E_IDENTITY }
75 if mvc_overlap(v as *i64,__size_of(MvcView)/MVC_WORD,b as *i64,file_words) != 0 { return NMI_E_IDENTITY }
76 if mvc_overlap(v as *i64,__size_of(MvcView)/MVC_WORD,out as *i64,__size_of(NmiAsset)/MVC_WORD) != 0 { return NMI_E_IDENTITY }
77 let vt: i64 = nxa_tag4("VERT" as *u8)
78 let ft: i64 = nxa_tag4("FACE" as *u8)
79 let mt: i64 = nxa_tag4("MORF" as *u8)
80 let ve: i64 = nxa_section_entry(b,flen,vt)
81 let fe: i64 = nxa_section_entry(b,flen,ft)
82 let me: i64 = nxa_section_entry(b,flen,mt)
83 if ve == 0-1 { return NMI_R_NO_VERT }
84 if fe == 0-1 { return NMI_R_NO_FACE }
85 if me == 0-1 { return NMI_R_NO_MORF }
86 if ve < 0 { return NMI_R_BAD_VERT }; if fe < 0 { return NMI_R_BAD_FACE }; if me < 0 { return NMI_R_BAD_MORF }
87 let vw: i64 = nxa_counted_section(b,flen,vt,MVC_AXES)
88 if vw < 0 { return NMI_R_VERT_SHAPE }
89 let h: *i64 = b as *i64
90 let vo: i64 = h[ve+1]; let fo: i64 = h[fe+1]; let mo: i64 = h[me+1]
91 let vwords: i64 = h[ve+2]; let fwords: i64 = h[fe+2]; let mwords: i64 = h[me+2]
92 var s: i64 = 0; var vc: i64 = 0; var fc: i64 = 0; var mc: i64 = 0
93 while s < h[2] {
94 let tag: i64 = h[4+s*4]
95 if tag == vt { vc = vc+1 }; if tag == ft { fc = fc+1 }; if tag == mt { mc = mc+1 }
96 s = s+1
97 }
98 if vc != 1 { return NMI_R_DUP_VERT }; if fc != 1 { return NMI_R_DUP_FACE }; if mc != 1 { return NMI_R_DUP_MORF }
99 if vo < fo+fwords*MVC_WORD { if fo < vo+vwords*MVC_WORD { return NMI_R_VERT_FACE } }
100 if vo < mo+mwords*MVC_WORD { if mo < vo+vwords*MVC_WORD { return NMI_R_VERT_MORF } }
101 if fo < mo+mwords*MVC_WORD { if mo < fo+fwords*MVC_WORD { return NMI_R_FACE_MORF } }
102 if fwords < NMI_FACE_HEADER { return NMI_R_FACE_HEADER }
103 if mwords < NMI_MORF_HEADER { return NMI_R_MORF_HEADER }
104 let f: *i64 = ((b as i64)+fo) as *i64
105 let m: *i64 = ((b as i64)+mo) as *i64
106 let nv: i64 = h[vw]; let nf: i64 = f[0]; let nc: i64 = m[0]
107 if nv < 1 { return NMI_R_EMPTY_VERT }
108 if nf < 1 { return NMI_R_EMPTY_FACE }
109 if nf != fwords-NMI_FACE_HEADER { return NMI_R_FACE_SHAPE }
110 if nf > nv { return NMI_R_FACE_COUNT }
111 if nc < 1 { return NMI_R_EMPTY_MORF }; if m[1] != nf { return NMI_R_ROW_COUNT }
112 if m[2] != MVC_AXES { return NMI_R_STRIDE }; if m[3] < 1 { return NMI_R_UNIT }
113 if channel >= nc { return NMI_R_CHANNEL_RANGE }
114 let rem: i64 = mwords-NMI_MORF_HEADER
115 if nc > rem/NMI_CHANNEL_WORDS { return NMI_R_CHANNEL_RECORDS }
116 let dw: i64 = rem-nc*NMI_CHANNEL_WORDS
117 if dw%nc != 0 { return NMI_R_CHANNEL_SHAPE }
118 let cw: i64 = dw/nc
119 if cw%MVC_AXES != 0 { return NMI_R_ROW_SHAPE }
120 if cw/MVC_AXES != nf { return NMI_R_DELTA_COUNT }
121 var c: i64 = 0
122 while c < nc {
123 let support: i64 = m[NMI_MORF_HEADER+c*NMI_CHANNEL_WORDS+1]
124 if support < 0 { return NMI_R_SUPPORT_NEGATIVE }; if support > nf { return NMI_R_SUPPORT_COUNT }
125 c = c+1
126 }
127 if seen_bytes < nv { return NMI_E_SCRATCH }
128 var i: i64 = 0
129 while i < nv { seen[i] = 0 as u8; i = i+1 }
130 i = 0
131 while i < nf {
132 let id: i64 = f[NMI_FACE_HEADER+i]
133 if id < 0 { return NMI_R_FACE_NEGATIVE }; if id >= nv { return NMI_R_FACE_RANGE }
134 if seen[id] != (0 as u8) { return NMI_R_FACE_DUPLICATE }
135 seen[id] = 1 as u8; i = i+1
136 }
137 // Publish only after all checks. Views borrow the immutable file lifetime.
138 v.bind = ((b as i64)+(vw+1)*MVC_WORD) as *i64; v.bind_words = vwords-1
139 v.face = ((f as i64)+NMI_FACE_HEADER*MVC_WORD) as *i64; v.face_words = nf
140 v.delta = ((m as i64)+(NMI_MORF_HEADER+nc*NMI_CHANNEL_WORDS)*MVC_WORD) as *i64
141 v.delta_words = dw; v.vertices = nv; v.faces = nf; v.channels = nc; v.unit = m[3]
142 out.tags = ((m as i64)+NMI_MORF_HEADER*MVC_WORD) as *i64
143 out.tag_words = nc*NMI_CHANNEL_WORDS
144 return 0
145}
146
147func nmi_byte_span(p: *u8,n: i64) -> i64 {
148 if n < 0 { return 0 }; if n == 0 { return 1 }
149 let addr: i64 = p as i64
150 if addr <= 0 { return 0 }; if addr > MVC_I64_MAX-n { return 0 }
151 return 1
152}
153func nmi_byte_overlap(a: *u8,an: i64,b: *u8,bn: i64) -> i64 {
154 if an == 0 { return 0 }; if bn == 0 { return 0 }
155 if (a as i64) < (b as i64)+bn { if (b as i64) < (a as i64)+an { return 1 } }
156 return 0
157}
158func nmi_admit(b: *u8,flen: i64,seen: *u8,seen_bytes: i64,out: *NmiAsset) -> i64 {
159 return nmi_admit_channel(b,flen,seen,seen_bytes,out,0-1)
160}
161func nmi_missing(rc: i64) -> i64 {
162 if rc == NMI_R_NO_VERT { return 1 }; if rc == NMI_R_NO_FACE { return 1 }; if rc == NMI_R_NO_MORF { return 1 }
163 return 0
164}
165func nmi_diagnostic(rc: i64) -> *u8 {
166 if rc == NMI_R_NO_VERT { return "MORF-REFUSE no VERT section\n" as *u8 }
167 if rc == NMI_R_NO_FACE { return "MORF-REFUSE no FACE section -- run derive first\n" as *u8 }
168 if rc == NMI_R_NO_MORF { return "MORF-REFUSE no MORF section -- run derive first\n" as *u8 }
169 if rc == NMI_R_BAD_VERT { return "MORF-REFUSE absent or invalid VERT/container\n" as *u8 }
170 if rc == NMI_R_BAD_FACE { return "MORF-REFUSE absent or invalid FACE/container\n" as *u8 }
171 if rc == NMI_R_BAD_MORF { return "MORF-REFUSE absent or invalid MORF/container\n" as *u8 }
172 if rc == NMI_R_VERT_SHAPE { return "MORF-REFUSE invalid VERT shape\n" as *u8 }
173 if rc == NMI_R_DUP_VERT { return "MORF-REFUSE duplicate VERT section\n" as *u8 }
174 if rc == NMI_R_DUP_FACE { return "MORF-REFUSE duplicate FACE section\n" as *u8 }
175 if rc == NMI_R_DUP_MORF { return "MORF-REFUSE duplicate MORF section\n" as *u8 }
176 if rc == NMI_R_FACE_HEADER { return "MORF-REFUSE truncated FACE header\n" as *u8 }
177 if rc == NMI_R_MORF_HEADER { return "MORF-REFUSE truncated MORF header\n" as *u8 }
178 if rc == NMI_R_EMPTY_VERT { return "MORF-REFUSE empty VERT\n" as *u8 }
179 if rc == NMI_R_EMPTY_FACE { return "MORF-REFUSE empty or negative FACE count\n" as *u8 }
180 if rc == NMI_R_FACE_SHAPE { return "MORF-REFUSE invalid FACE shape\n" as *u8 }
181 if rc == NMI_R_FACE_COUNT { return "MORF-REFUSE FACE count exceeds VERT count\n" as *u8 }
182 if rc == NMI_R_EMPTY_MORF { return "MORF-REFUSE empty or negative MORF channels\n" as *u8 }
183 if rc == NMI_R_ROW_COUNT { return "MORF-REFUSE MORF/FACE count mismatch\n" as *u8 }
184 if rc == NMI_R_STRIDE { return "MORF-REFUSE unsupported MORF stride\n" as *u8 }
185 if rc == NMI_R_UNIT { return "MORF-REFUSE declared weight unit is not positive\n" as *u8 }
186 if rc == NMI_R_CHANNEL_RECORDS { return "MORF-REFUSE truncated MORF channel records\n" as *u8 }
187 if rc == NMI_R_CHANNEL_SHAPE { return "MORF-REFUSE invalid MORF channel shape\n" as *u8 }
188 if rc == NMI_R_ROW_SHAPE { return "MORF-REFUSE invalid MORF row shape\n" as *u8 }
189 if rc == NMI_R_DELTA_COUNT { return "MORF-REFUSE invalid MORF delta count\n" as *u8 }
190 if rc == NMI_R_SUPPORT_NEGATIVE { return "MORF-REFUSE negative channel support count\n" as *u8 }
191 if rc == NMI_R_SUPPORT_COUNT { return "MORF-REFUSE channel support exceeds FACE count\n" as *u8 }
192 if rc == NMI_R_FACE_NEGATIVE { return "MORF-REFUSE negative FACE vertex ID\n" as *u8 }
193 if rc == NMI_R_FACE_RANGE { return "MORF-REFUSE FACE vertex ID outside VERT\n" as *u8 }
194 if rc == NMI_R_FACE_DUPLICATE { return "MORF-REFUSE duplicate FACE vertex ID\n" as *u8 }
195 if rc == NMI_R_VERT_FACE { return "MORF-REFUSE VERT/FACE overlap\n" as *u8 }
196 if rc == NMI_R_VERT_MORF { return "MORF-REFUSE VERT/MORF overlap\n" as *u8 }
197 if rc == NMI_R_FACE_MORF { return "MORF-REFUSE FACE/MORF overlap\n" as *u8 }
198 if rc == NMI_R_CHANNEL_RANGE { return "MORF-REFUSE channel past the asset's declared channels\n" as *u8 }
199 if rc == NMI_E_SCRATCH { return "MORF-REFUSE admission membership scratch size or alias\n" as *u8 }
200 if rc == NMI_E_IDENTITY { return "MORF-REFUSE admission output aliases immutable input or another output\n" as *u8 }
201 return "MORF-REFUSE invalid admission pointer or length\n" as *u8
202}