code wiki / _hdl_build / nx_recip_div24_test.nx
nx_recip_div24_test.nx source
↩ module page · 134 lines · 4829 B
1// nx_recip_div24_test.nx -- TRIANGULATED 1:1 proof of the W=24 Newton/Goldschmidt
2// reciprocal divider gate-network (nx_recip_div24_synth), the first rung that
3// composes the proven 64x64->128 wide multiplier (x*t overflows i64 at W=24).
4//
5// Three independent legs must agree on every vector (a bug would have to fool all
6// three): LEG A the GATE-NETWORK Newton divider via nx_nxgate_sim (q and r);
7// LEG B an independent restoring (shift-subtract) divider, W=24, SCALAR; LEG C
8// the i64 oracle / and %. Battery (2,297,160 vectors): dense D in [1,256] x
9// N in [0,8191] + 200,000 random FULL 24-bit (N,D in [1,2^24-1]) + 8 edges.
10//
11// Known answer (FAIL LOUD): "2297160 2297160 1763 4" rc=0 (ok total q_chk r_chk;
12// 12345/7 = 1763 rem 4). Built on the known-good compiler.
13
14import "nx_recip_div24.nx"
15
16const RT_W24: i64 = 16777215 // 2^24 - 1
17const RT_LCG_A: i64 = 6364136223846793005
18const RT_LCG_C: i64 = 1442695040888963407
19
20func _emit_num(v: i64) -> i64 {
21 let b: *u8 = sys_mmap(28); var n: i64 = v; if n < 0 { n = 0 - n }
22 let t2: *u8 = sys_mmap(28); var t: i64 = 0
23 if n == 0 { t2[0] = 48; t = 1 }
24 while n > 0 { t2[t] = 48 + (n % 10); n = n / 10; t = t + 1 }
25 var i: i64 = 0; while i < t { b[i] = t2[t - 1 - i]; i = i + 1 }
26 b[t] = 32; sys_write(1, b, t + 1); return 0
27}
28func _nl() -> i64 { let z: *u8 = sys_mmap(2); z[0] = 10; sys_write(1, z, 1); return 0 }
29
30// LEG B -- independent restoring divider, W=24, SCALAR.
31func rt_restoring(N: i64, D: i64) -> i64 {
32 var q: i64 = 0
33 var r: i64 = 0
34 var i: i64 = 23
35 while i >= 0 {
36 r = (r << 1) | ((N >> i) & 1)
37 if r >= D { r = r - D; q = q | (1 << i) }
38 i = i - 1
39 }
40 return q
41}
42
43// run the prebuilt gate-net for (N,D); returns quotient, writes remainder to r_out.
44func rt_run(g: *NxGsim, qnet: i64, rnet: i64, N: i64, D: i64, r_out: *i64) -> i64 {
45 g.vals[0] = N
46 g.vals[1] = D
47 if nx_gsim_run(g) != NX_GSIM_OK { r_out[0] = 0 - 1; return 0 - 1 }
48 r_out[0] = g.vals[rnet]
49 return g.vals[qnet]
50}
51
52func main() -> i64 {
53 let vals: *i64 = sys_mmap(8 * 4096) as *i64
54 let cells: *NxGsimCell = sys_mmap(48 * 4096) as *NxGsimCell
55 let g: *NxGsim = sys_mmap(64) as *NxGsim
56 g.vals = vals; g.n_nets = 2; g.cells = cells; g.n_cells = 0
57
58 let rob: *i64 = sys_mmap(8) as *i64; rob[0] = 0
59 let qnet: i64 = nx_recip_div24_synth(g, 0, 1, rob)
60 let rnet: i64 = rob[0]
61 let r_out: *i64 = sys_mmap(8) as *i64; r_out[0] = 0
62
63 var total: i64 = 0
64 var ok: i64 = 0
65 var q_chk: i64 = 0
66 var r_chk: i64 = 0
67
68 // dense: D in [1,256], N in [0,8191]
69 var D: i64 = 1
70 while D <= 256 {
71 var N: i64 = 0
72 while N <= 8191 {
73 let a: i64 = rt_run(g, qnet, rnet, N, D, r_out)
74 let ar: i64 = r_out[0]
75 let b: i64 = rt_restoring(N, D)
76 let c: i64 = N / D
77 let cr: i64 = N - (N / D) * D
78 total = total + 1
79 if a == b { if a == c { if ar == cr { ok = ok + 1 } } }
80 N = N + 1
81 }
82 D = D + 1
83 }
84
85 q_chk = rt_run(g, qnet, rnet, 12345, 7, r_out)
86 r_chk = r_out[0]
87
88 // random FULL 24-bit: N,D in [1, 2^24-1] -- exercises the wide-multiplier path
89 var seed: i64 = 2463534242
90 var nr: i64 = 0
91 while nr < 200000 {
92 seed = seed * RT_LCG_A + RT_LCG_C; var N: i64 = seed & RT_W24
93 seed = seed * RT_LCG_A + RT_LCG_C; var D: i64 = (seed & RT_W24)
94 if D == 0 { D = 1 }
95 let a: i64 = rt_run(g, qnet, rnet, N, D, r_out)
96 let ar: i64 = r_out[0]
97 let b: i64 = rt_restoring(N, D)
98 let c: i64 = N / D
99 let cr: i64 = N - (N / D) * D
100 total = total + 1
101 if a == b { if a == c { if ar == cr { ok = ok + 1 } } }
102 nr = nr + 1
103 }
104
105 // edges
106 let en: *i64 = sys_mmap(8 * 8) as *i64
107 let ed: *i64 = sys_mmap(8 * 8) as *i64
108 en[0]=16777215; ed[0]=1
109 en[1]=16777215; ed[1]=16777215
110 en[2]=16777215; ed[2]=8388608
111 en[3]=0; ed[3]=16777215
112 en[4]=1; ed[4]=1
113 en[5]=16777215; ed[5]=2
114 en[6]=12345; ed[6]=255
115 en[7]=16777215; ed[7]=257
116 var e: i64 = 0
117 while e < 8 {
118 let a: i64 = rt_run(g, qnet, rnet, en[e], ed[e], r_out)
119 let ar: i64 = r_out[0]
120 let b: i64 = rt_restoring(en[e], ed[e])
121 let c: i64 = en[e] / ed[e]
122 let cr: i64 = en[e] - (en[e] / ed[e]) * ed[e]
123 total = total + 1
124 if a == b { if a == c { if ar == cr { ok = ok + 1 } } }
125 e = e + 1
126 }
127
128 _emit_num(ok); _emit_num(total); _emit_num(q_chk); _emit_num(r_chk); _nl()
129 if ok != total { sys_exit(1); return 1 }
130 if total != 2297160 { sys_exit(2); return 2 }
131 if q_chk != 1763 { sys_exit(3); return 3 }
132 if r_chk != 4 { sys_exit(4); return 4 }
133 sys_exit(0); return 0
134}