code wiki / (root) / fp64_parts_test.nx

fp64_parts_test.nx source

↩ module page · 87 lines · 2797 B

1// fp64_parts_test.nx -- IEEE 754 binary64 literal-encoding round-trip. 2// 3// Verifies fp64_from_parts produces the correct IEEE 754 bit pattern 4// for common literal values. These are the reference encodings the 5// parser will embed in const Values when it hits TK_FLOAT and the 6// surrounding context wants f64. 7// 8// Canonical patterns cross-referenced against C compilers (printf 9// "%016llx" of *(uint64_t*)&double_val): 10// 0.0 -> 0x0000000000000000 11// 1.0 -> 0x3FF0000000000000 12// 2.0 -> 0x4000000000000000 13// 0.5 -> 0x3FE0000000000000 14// 1.5 -> 0x3FF8000000000000 15// 4.0 -> 0x4010000000000000 16// 8.0 -> 0x4020000000000000 17// 3.14 -> 0x40091EB851EB851F (exact fp64; integer encoder may round 18// by a ULP, so we allow ULP tolerance) 19// 0.1 -> 0x3FB999999999999A (recurring decimal, ULP-close) 20 21import "syscalls.nx" 22import "quant.nx" 23 24func ulp_close64(a: i64, b: i64) -> i64 { 25 if a == b { return 1 } 26 let d: i64 = a - b 27 if d == 1 { return 1 } 28 if d == -1 { return 1 } 29 return 0 30} 31 32func main() -> i64 { 33 // 0.0 34 if fp64_from_parts(0, 0, 0) != 0 { 35 return __syscall(93, 10, 0, 0, 0, 0, 0) 36 } 37 if fp64_from_parts(0, 0, 1) != 0 { 38 return __syscall(93, 11, 0, 0, 0, 0, 0) 39 } 40 41 // 1.0 -> 0x3FF0000000000000 42 if fp64_from_parts(1, 0, 0) != 0x3FF0000000000000 { 43 return __syscall(93, 20, 0, 0, 0, 0, 0) 44 } 45 if fp64_from_parts(1, 0, 1) != 0x3FF0000000000000 { 46 return __syscall(93, 21, 0, 0, 0, 0, 0) 47 } 48 49 // 2.0 -> 0x4000000000000000 50 if fp64_from_parts(2, 0, 0) != 0x4000000000000000 { 51 return __syscall(93, 30, 0, 0, 0, 0, 0) 52 } 53 54 // 0.5 -> 0x3FE0000000000000 55 if fp64_from_parts(0, 5, 1) != 0x3FE0000000000000 { 56 return __syscall(93, 40, 0, 0, 0, 0, 0) 57 } 58 59 // 1.5 -> 0x3FF8000000000000 60 if fp64_from_parts(1, 5, 1) != 0x3FF8000000000000 { 61 return __syscall(93, 50, 0, 0, 0, 0, 0) 62 } 63 64 // 3.14 -> ~0x40091EB851EB851F (within 1 ULP) 65 let pi_bits: i64 = fp64_from_parts(3, 14, 2) 66 if ulp_close64(pi_bits, 0x40091EB851EB851F) != 1 { 67 return __syscall(93, 60, 0, 0, 0, 0, 0) 68 } 69 70 // 0.1 -> ~0x3FB999999999999A (recurring decimal, ULP tolerance) 71 let tenth_bits: i64 = fp64_from_parts(0, 1, 1) 72 if ulp_close64(tenth_bits, 0x3FB999999999999A) != 1 { 73 return __syscall(93, 70, 0, 0, 0, 0, 0) 74 } 75 76 // 4.0 -> 0x4010000000000000 77 if fp64_from_parts(4, 0, 0) != 0x4010000000000000 { 78 return __syscall(93, 80, 0, 0, 0, 0, 0) 79 } 80 81 // 8.0 -> 0x4020000000000000 82 if fp64_from_parts(8, 0, 0) != 0x4020000000000000 { 83 return __syscall(93, 81, 0, 0, 0, 0, 0) 84 } 85 86 return 0 87}