code wiki / (root) / nx_f32_log_test.nx

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}