nx_f32_log_test.nx source
↩ module page · 60 lines · 2118 B
1// nx_f32_log_test.nx -- smoke for nx_f32_log.nx.
2
3import "nx_syscalls.nx"
4import "nx_tier.nx"
5import "nx_f32.nx"
6import "nx_f32_div.nx"
7import "nx_f32_cvt.nx"
8import "nx_f32_log.nx"
9
10func _ulp_diff_pos(a: i64, b: i64) -> i64 {
11 if a >= b { return a - b }
12 return b - a
13}
14
15func main() -> i64 {
16 // Exact special cases.
17 // log(1.0) = 0 (exact short-circuit)
18 if nx_f32_log(0x3F800000) != 0 { return 10 }
19
20 // log(+inf) = +inf
21 if nx_f32_log(0x7F800000) != 0x7F800000 { return 11 }
22
23 // log(+0) = -inf (= 0xFF800000)
24 if nx_f32_log(0x00000000) != 0xFF800000 { return 12 }
25
26 // log(NaN) = NaN
27 let r_nan: i64 = nx_f32_log(0x7FC00000)
28 if nx_f32_is_nan(r_nan) != 1 { return 13 }
29
30 // Approximate cases (atanh polynomial, ~50-500 ULP accuracy).
31 // log(2) = ln(2) ~= 0.6931472 = 0x3F317218
32 let r2: i64 = nx_f32_log(0x40000000)
33 if _ulp_diff_pos(r2, 0x3F317218) > 1024 { return 20 }
34
35 // log(e) = 1.0 = 0x3F800000. e = 2.71828183 = 0x402DF854.
36 let r_e: i64 = nx_f32_log(0x402DF854)
37 if _ulp_diff_pos(r_e, 0x3F800000) > 1024 { return 21 }
38
39 // log(0.5) = -ln(2) ~= -0.6931472 = 0xBF317218
40 // Since negative, we use the signed-i64 difference; check separately.
41 let r_half: i64 = nx_f32_log(0x3F000000)
42 // |r_half - target| with target = 0xBF317218. Both should be ~equal-magnitude negative.
43 // For convenience, just check that r_half is negative + sign bit set + magnitude close.
44 if (r_half >> 31) & 1 != 1 { return 30 }
45 let abs_r_half: i64 = r_half & 0x7FFFFFFF
46 if _ulp_diff_pos(abs_r_half, 0x3F317218) > 1024 { return 31 }
47
48 // log(10) ~= 2.302585093. The IEEE 754 binary32 nearest is
49 // 0x40135D8E. v1 atanh polynomial + k*ln(2) accumulation gives
50 // ~10000 ULP accuracy at x=10; relative error still <1e-3, fine
51 // for ML loss math. v2 Remez tightening drops this dramatically.
52 let r_10: i64 = nx_f32_log(0x41200000)
53 if _ulp_diff_pos(r_10, 0x40135D8E) > 16384 { return 40 }
54
55 // log(-1) = NaN
56 let r_neg: i64 = nx_f32_log(0xBF800000)
57 if nx_f32_is_nan(r_neg) != 1 { return 50 }
58
59 return 0
60}