code wiki / (root) / nx_f32_test.nx

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}