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}