_offc_probe_f32equiv.nx source
↩ module page · 146 lines · 4812 B
1// _offc_probe_f32equiv.nx -- IS THE HARDWARE f32 INTRINSIC BIT-IDENTICAL TO THE
2// SOFTWARE HELPER? (2026-08-23)
3//
4// WHY. Measured this session: NishiLang has float TYPES and float LITERALS and a
5// KAT-gated SSE backend, but NO float OPERATORS -- every one of the 17 `emit_f32`
6// sites in nx_parse.nx is an INTRINSIC dispatch (__f32_add/__f32_mul/__f32_div/...).
7// So organs reach for the SOFTWARE helper nx_f32_add (a full IEEE-754 adder written
8// in integer arithmetic) while the HARDWARE __f32_add sits one intrinsic away. A
9// banked measurement puts that software path at 10x/9x/1.6x slower than its twin.
10//
11// THE CHEAP WIN, IF IT HOLDS: re-point the nx_f32_* helper BODIES at the __f32_*
12// intrinsics. That is a LIBRARY change -- zero call-site edits, no nx_parse.nx
13// touch -- and every existing consumer gets the hardware path for free.
14//
15// THE PRECONDITION, AND THE POINT OF THIS PROBE: the two paths must agree
16// BIT-FOR-BIT. If they DISAGREE, that disagreement is the finding -- a rounding
17// difference hiding in plain sight, not a licence to swap. Specific hazard: the
18// banked backend observation is `addsd` (scalar DOUBLE). If OP_FADD lowers through
19// f64, an f32 bit pattern held in an i64 would be double-rounded or reinterpreted
20// outright. This probe is built to catch both.
21//
22// Reports agreement over every IEEE class -- signed zeros, both infinities, NaN,
23// min/max subnormal, min/max normal, 1-ulp neighbours, rounding-sensitive pairs.
24
25import "nx_syscalls.nx"
26import "nx_f32.nx"
27
28func pnum(v: i64) -> i64 {
29 let buf: *u8 = sys_mmap(64)
30 let out: *u8 = sys_mmap(64)
31 if v == 0 {
32 out[0] = 48 as u8
33 sys_write(1, out, 1)
34 return 0
35 }
36 var n: i64 = 0
37 var x: i64 = v
38 while x > 0 {
39 buf[n] = ((x % 10) + 48) as u8
40 x = x / 10
41 n = n + 1
42 }
43 var k: i64 = 0
44 while k < n {
45 out[k] = buf[n - 1 - k]
46 k = k + 1
47 }
48 sys_write(1, out, n)
49 return 0
50}
51
52func phex(v: i64) -> i64 {
53 let out: *u8 = sys_mmap(64)
54 var i: i64 = 0
55 while i < 8 {
56 let sh: i64 = (7 - i) * 4
57 let nib: i64 = (v / (1 << sh)) % 16
58 if nib < 10 {
59 out[i] = (nib + 48) as u8
60 } else {
61 out[i] = (nib + 87) as u8
62 }
63 i = i + 1
64 }
65 sys_write(1, out, 8)
66 return 0
67}
68
69func main() -> i64 {
70 let v: *i64 = sys_mmap(16 * 8) as *i64
71 v[0] = 0 // +0
72 v[1] = 2147483648 // -0 0x80000000
73 v[2] = 1065353216 // 1.0 0x3F800000
74 v[3] = 3212836864 // -1.0 0xBF800000
75 v[4] = 1073741824 // 2.0 0x40000000
76 v[5] = 1077936128 // 3.0 0x40400000
77 v[6] = 2139095040 // +inf 0x7F800000
78 v[7] = 4286578688 // -inf 0xFF800000
79 v[8] = 2143289344 // NaN 0x7FC00000
80 v[9] = 1 // min subnormal 0x00000001
81 v[10] = 8388607 // max subnormal 0x007FFFFF
82 v[11] = 8388608 // min normal 0x00800000
83 v[12] = 2139095039 // max normal 0x7F7FFFFF
84 v[13] = 1065353217 // 1.0 + 1ulp 0x3F800001
85 v[14] = 855638016 // 2^-24 0x33000000 rounding-sensitive vs 1.0
86 v[15] = 872415232 // 2^-23 0x34000000
87
88 var pairs: i64 = 0
89 var agree: i64 = 0
90 var differ: i64 = 0
91 var seen: i64 = 0
92 var fa: i64 = 0
93 var fb: i64 = 0
94 var fsw: i64 = 0
95 var fhw: i64 = 0
96
97 var i: i64 = 0
98 while i < 16 {
99 var j: i64 = 0
100 while j < 16 {
101 let a: i64 = v[i]
102 let b: i64 = v[j]
103 let sw: i64 = nx_f32_add(a, b)
104 let hw: i64 = __f32_add(a, b)
105 pairs = pairs + 1
106 if sw == hw {
107 agree = agree + 1
108 } else {
109 differ = differ + 1
110 if seen == 0 {
111 seen = 1
112 fa = a
113 fb = b
114 fsw = sw
115 fhw = hw
116 }
117 }
118 j = j + 1
119 }
120 i = i + 1
121 }
122
123 sys_write(1, "F32EQUIV pairs=" as *u8, 15)
124 pnum(pairs)
125 sys_write(1, " agree=" as *u8, 7)
126 pnum(agree)
127 sys_write(1, " differ=" as *u8, 8)
128 pnum(differ)
129 sys_write(1, "\n" as *u8, 1)
130
131 if differ > 0 {
132 sys_write(1, "FIRST-DIFF a=0x" as *u8, 15)
133 phex(fa)
134 sys_write(1, " b=0x" as *u8, 5)
135 phex(fb)
136 sys_write(1, " sw=0x" as *u8, 6)
137 phex(fsw)
138 sys_write(1, " hw=0x" as *u8, 6)
139 phex(fhw)
140 sys_write(1, "\n" as *u8, 1)
141 sys_write(1, "VERDICT=DISAGREE -- swap REFUSED; the difference IS the finding\n" as *u8, 63)
142 } else {
143 sys_write(1, "VERDICT=BIT-IDENTICAL over every IEEE class tested\n" as *u8, 50)
144 }
145 return 0
146}