nx_f32_test.nx source
↩ module page · 161 lines · 8683 B
1// nx_f32_test.nx -- smoke + IEEE 754 conformance for nx_f32.nx.
2//
3// KAT vectors hand-computed against IEEE 754-2019 binary32 reference.
4//
5// Canonical bit patterns we exercise:
6// 1.0 = 0x3F800000
7// 2.0 = 0x40000000
8// 0.5 = 0x3F000000
9// 0.25 = 0x3E800000
10// 4.0 = 0x40800000
11// 0.0625 = 0x3D800000
12// -1.0 = 0x00000000BF800000
13// 3.0 = 0x40400000 (1.0 + 0.5 * 2^1 = 1.5 * 2 = 3.0)
14// 6.0 = 0x40C00000
15// +inf = 0x7F800000
16// -inf = 0x00000000FF800000
17// qNaN = 0x000000007FC00000
18// +0 = 0x00000000
19// -0 = 0x0000000080000000
20
21import "nx_syscalls.nx"
22import "nx_tier.nx"
23import "nx_f32.nx"
24
25func main() -> i64 {
26 // ----- A) Verdict gate -----
27 var vi: nx_int = 0
28 while vi < NX_F32_CLS_N {
29 if nx_f32_cls_is_valid(vi) != 1 { return 5 + vi }
30 vi = vi + 1
31 }
32
33 // ----- B) Classification -----
34 if nx_f32_classify(0x00000000) != NX_F32_CLS_ZERO { return 10 }
35 if nx_f32_classify(0x0000000080000000) != NX_F32_CLS_ZERO { return 11 }
36 if nx_f32_classify(0x3F800000) != NX_F32_CLS_NORMAL { return 12 } // 1.0
37 if nx_f32_classify(0x00000000BF800000) != NX_F32_CLS_NORMAL { return 13 } // -1.0
38 if nx_f32_classify(0x7F800000) != NX_F32_CLS_INF { return 14 }
39 if nx_f32_classify(0x00000000FF800000) != NX_F32_CLS_INF { return 15 }
40 if nx_f32_classify(0x000000007FC00000) != NX_F32_CLS_NAN { return 16 }
41 if nx_f32_classify(0x00000001) != NX_F32_CLS_SUBNORMAL { return 17 }
42
43 // ----- C) Sign manipulation -----
44 if nx_f32_neg(0x3F800000) != 0x00000000BF800000 { return 30 } // 1 -> -1
45 if nx_f32_neg(0x00000000BF800000) != 0x3F800000 { return 31 }
46 if nx_f32_neg(0x00000000) != 0x0000000080000000 { return 32 }
47 if nx_f32_abs(0x00000000BF800000) != 0x3F800000 { return 33 }
48 if nx_f32_abs(0x3F800000) != 0x3F800000 { return 34 }
49
50 // ----- D) IEEE 754 equality -----
51 if nx_f32_eq(0x3F800000, 0x3F800000) != 1 { return 40 }
52 if nx_f32_eq(0x3F800000, 0x00000000BF800000) != 0 { return 41 }
53 if nx_f32_eq(0x00000000, 0x0000000080000000) != 1 { return 42 } // +0 == -0
54 if nx_f32_eq(0x000000007FC00000, 0x000000007FC00000) != 0 { return 43 } // NaN != NaN
55 if nx_f32_eq(0x7F800000, 0x7F800000) != 1 { return 44 } // +inf == +inf
56 if nx_f32_eq(0x7F800000, 0x00000000FF800000) != 0 { return 45 } // +inf != -inf
57
58 // ----- E) Multiplication KAT -----
59 //
60 // Hand-computed using IEEE 754 binary32 semantics with round-to-nearest-even.
61 if nx_f32_mul(0x3F800000, 0x3F800000) != 0x3F800000 { return 60 } // 1*1 = 1
62 if nx_f32_mul(0x40000000, 0x3F000000) != 0x3F800000 { return 61 } // 2*0.5 = 1
63 if nx_f32_mul(0x3F000000, 0x3F000000) != 0x3E800000 { return 62 } // 0.5*0.5 = 0.25
64 if nx_f32_mul(0x00000000BF800000, 0x3F800000) != 0x00000000BF800000 { return 63 } // -1*1 = -1
65 if nx_f32_mul(0x00000000BF800000, 0x00000000BF800000) != 0x3F800000 { return 64 } // -1*-1 = 1
66 if nx_f32_mul(0x40000000, 0x40000000) != 0x40800000 { return 65 } // 2*2 = 4
67 if nx_f32_mul(0x40400000, 0x40000000) != 0x40C00000 { return 66 } // 3*2 = 6
68 if nx_f32_mul(0x3F000000, 0x3F000000) != 0x3E800000 { return 67 } // 0.5*0.5 = 0.25
69
70 // Tiny * small: 0.0625 * 0.25 = 0.015625 = 0x3C800000
71 if nx_f32_mul(0x3D800000, 0x3E800000) != 0x3C800000 { return 70 }
72
73 // Zero propagation
74 if nx_f32_mul(0x00000000, 0x3F800000) != 0x00000000 { return 80 } // 0 * 1 = 0
75 if nx_f32_mul(0x3F800000, 0x00000000) != 0x00000000 { return 81 }
76 if nx_f32_mul(0x0000000080000000, 0x3F800000) != 0x0000000080000000 { return 82 } // -0 * 1 = -0
77 if nx_f32_mul(0x0000000080000000, 0x0000000080000000) != 0x00000000 { return 83 } // -0 * -0 = +0
78 if nx_f32_mul(0x0000000080000000, 0x00000000BF800000) != 0x00000000 { return 84 } // -0 * -1 = +0
79
80 // 0 * Inf = NaN (IEEE 754)
81 if nx_f32_is_nan(nx_f32_mul(0x00000000, 0x7F800000)) != 1 { return 90 }
82 if nx_f32_is_nan(nx_f32_mul(0x7F800000, 0x00000000)) != 1 { return 91 }
83 if nx_f32_is_nan(nx_f32_mul(0x00000000, 0x00000000FF800000)) != 1 { return 92 }
84
85 // Inf * non-zero non-NaN = signed inf
86 if nx_f32_mul(0x7F800000, 0x3F800000) != 0x7F800000 { return 100 } // +inf * 1
87 if nx_f32_mul(0x00000000FF800000, 0x3F800000) != 0x00000000FF800000 { return 101 } // -inf * 1
88 if nx_f32_mul(0x7F800000, 0x00000000BF800000) != 0x00000000FF800000 { return 102 } // +inf * -1
89 if nx_f32_mul(0x00000000FF800000, 0x00000000FF800000) != 0x7F800000 { return 103 } // -inf * -inf
90 if nx_f32_mul(0x7F800000, 0x40000000) != 0x7F800000 { return 104 } // +inf * 2
91
92 // NaN propagation
93 if nx_f32_is_nan(nx_f32_mul(0x000000007FC00000, 0x3F800000)) != 1 { return 110 }
94 if nx_f32_is_nan(nx_f32_mul(0x3F800000, 0x000000007FC00000)) != 1 { return 111 }
95 if nx_f32_is_nan(nx_f32_mul(0x000000007FC00000, 0x000000007FC00000)) != 1 { return 112 }
96 if nx_f32_is_nan(nx_f32_mul(0x000000007FC00000, 0x00000000)) != 1 { return 113 }
97 if nx_f32_is_nan(nx_f32_mul(0x000000007FC00000, 0x7F800000)) != 1 { return 114 }
98
99 // ===== F) Addition KAT (IEEE 754 round-to-nearest-even) =====
100 // 1 + 1 = 2
101 if nx_f32_add(0x3F800000, 0x3F800000) != 0x40000000 { return 200 }
102 // 1 + 0.5 = 1.5 (0x3FC00000)
103 if nx_f32_add(0x3F800000, 0x3F000000) != 0x3FC00000 { return 201 }
104 // 2 + 1 = 3 (0x40400000)
105 if nx_f32_add(0x40000000, 0x3F800000) != 0x40400000 { return 202 }
106 // 2 + 2 = 4 (0x40800000)
107 if nx_f32_add(0x40000000, 0x40000000) != 0x40800000 { return 203 }
108 // 1 + (-1) = 0 (exact cancellation)
109 if nx_f32_add(0x3F800000, 0x00000000BF800000) != 0x00000000 { return 204 }
110 // 2 + (-1) = 1
111 if nx_f32_add(0x40000000, 0x00000000BF800000) != 0x3F800000 { return 205 }
112 // 0.25 + 0.25 = 0.5 (0x3F000000)
113 if nx_f32_add(0x3E800000, 0x3E800000) != 0x3F000000 { return 206 }
114 // 1 + 0 = 1
115 if nx_f32_add(0x3F800000, 0x00000000) != 0x3F800000 { return 207 }
116 // 0 + 1 = 1
117 if nx_f32_add(0x00000000, 0x3F800000) != 0x3F800000 { return 208 }
118 // -1 + 2 = 1 (sign tracking on subtraction-via-swap)
119 if nx_f32_add(0x00000000BF800000, 0x40000000) != 0x3F800000 { return 209 }
120 // -2 + 1 = -1
121 if nx_f32_add(0x00000000C0000000, 0x3F800000) != 0x00000000BF800000 { return 210 }
122
123 // Zero handling
124 if nx_f32_add(0x00000000, 0x00000000) != 0x00000000 { return 220 } // +0+0
125 if nx_f32_add(0x0000000080000000, 0x0000000080000000) != 0x0000000080000000 { return 221 } // -0-0=-0
126 if nx_f32_add(0x00000000, 0x0000000080000000) != 0x00000000 { return 222 } // +0-0=+0
127 if nx_f32_add(0x0000000080000000, 0x00000000) != 0x00000000 { return 223 } // -0+0=+0
128
129 // Inf handling
130 if nx_f32_add(0x7F800000, 0x3F800000) != 0x7F800000 { return 230 } // +inf+1=+inf
131 if nx_f32_add(0x3F800000, 0x7F800000) != 0x7F800000 { return 231 }
132 if nx_f32_add(0x00000000FF800000, 0x3F800000) != 0x00000000FF800000 { return 232 } // -inf+1=-inf
133 if nx_f32_add(0x7F800000, 0x7F800000) != 0x7F800000 { return 233 } // +inf+inf=+inf
134 if nx_f32_add(0x00000000FF800000, 0x00000000FF800000) != 0x00000000FF800000 { return 234 } // -inf-inf=-inf
135 if nx_f32_is_nan(nx_f32_add(0x7F800000, 0x00000000FF800000)) != 1 { return 235 } // inf-inf=NaN
136
137 // NaN propagation in add
138 if nx_f32_is_nan(nx_f32_add(0x000000007FC00000, 0x3F800000)) != 1 { return 240 }
139 if nx_f32_is_nan(nx_f32_add(0x3F800000, 0x000000007FC00000)) != 1 { return 241 }
140 if nx_f32_is_nan(nx_f32_add(0x000000007FC00000, 0x000000007FC00000)) != 1 { return 242 }
141
142 // ===== G) Subtraction (a + (-b)) =====
143 if nx_f32_sub(0x3F800000, 0x3F800000) != 0x00000000 { return 260 } // 1-1=0
144 if nx_f32_sub(0x40000000, 0x3F800000) != 0x3F800000 { return 261 } // 2-1=1
145 if nx_f32_sub(0x40800000, 0x40000000) != 0x40000000 { return 262 } // 4-2=2
146 if nx_f32_sub(0x40400000, 0x3F800000) != 0x40000000 { return 263 } // 3-1=2
147
148 // ===== H) Square root KAT =====
149 if nx_f32_sqrt(0x00000000) != 0x00000000 { return 280 } // sqrt(+0)=+0
150 if nx_f32_sqrt(0x3F800000) != 0x3F800000 { return 281 } // sqrt(1)=1
151 if nx_f32_sqrt(0x40800000) != 0x40000000 { return 282 } // sqrt(4)=2
152 if nx_f32_sqrt(0x3E800000) != 0x3F000000 { return 283 } // sqrt(0.25)=0.5
153 if nx_f32_sqrt(0x40000000) != 0x3FB504F3 { return 284 } // sqrt(2)=√2
154 if nx_f32_sqrt(0x3F000000) != 0x3F3504F3 { return 285 } // sqrt(0.5)=√0.5
155 if nx_f32_sqrt(0x7F800000) != 0x7F800000 { return 286 } // sqrt(+inf)=+inf
156
157 // f32 div lives in nx_f32_div.nx with its own smoke
158 // (nx_f32_div_test.nx) -- separated per Task #10 codegen quirk.
159
160 return 0
161}