nx_u4096_test.nx source
↩ module page · 131 lines · 4032 B
1// nx_u4096_test.nx -- KAT for the 4096-bit big-int primitives.
2// Mirrors nx_u384_test / nx_u256_test, scaled to 128 limbs / 512 bytes.
3//
4// expect_exit: 0
5// license_tier: ORIGINAL
6
7import "nx_syscalls.nx"
8import "nx_u4096.nx"
9
10func main() -> i64 {
11 // ---- Test A: zero / one ----
12 let z: *i64 = u4096_alloc()
13 u4096_zero(z)
14 if u4096_is_zero(z) != 1 { return 1 }
15 u4096_one(z)
16 if z[0] != 1 { return 2 }
17 if u4096_is_zero(z) != 0 { return 3 }
18 var i: i64 = 1
19 while i < NX_U4096_LIMBS {
20 if z[i] != 0 { return 4 }
21 i = i + 1
22 }
23
24 // ---- Test B: load_be / store_be round-trip ----
25 let pat: *u8 = sys_mmap(NX_U4096_BYTES)
26 i = 0
27 while i < NX_U4096_BYTES {
28 pat[i] = (i + 1) as u8 // 0x01..0x200 (wraps at 256 mod 256)
29 i = i + 1
30 }
31 let a: *i64 = u4096_alloc()
32 u4096_load_be(a, pat)
33 // High limb (index 127) should hold bytes 0..3 BE = 0x01020304
34 if a[127] != 0x01020304 { return 10 }
35 // Low limb (index 0) should hold bytes 508..511 BE.
36 // pat[508] = (508+1)&0xff = 509 & 0xff = 253 = 0xFD
37 // pat[509] = 510 & 0xff = 254 = 0xFE
38 // pat[510] = 511 & 0xff = 255 = 0xFF
39 // pat[511] = 512 & 0xff = 0 = 0x00
40 if a[0] != 0xFDFEFF00 { return 11 }
41
42 let pat2: *u8 = sys_mmap(NX_U4096_BYTES)
43 u4096_store_be(pat2, a)
44 i = 0
45 while i < NX_U4096_BYTES {
46 if (pat2[i] & 0xff) != (pat[i] & 0xff) { return 20 }
47 i = i + 1
48 }
49
50 // ---- Test C: add / sub round-trip ----
51 // c = a + 1; d = c - 1; d == a
52 let one_v: *i64 = u4096_alloc()
53 u4096_one(one_v)
54 let c: *i64 = u4096_alloc()
55 let carry: i64 = u4096_add_with_carry(c, a, one_v)
56 if carry != 0 { return 50 }
57 let d: *i64 = u4096_alloc()
58 let borrow: i64 = u4096_sub_with_borrow(d, c, one_v)
59 if borrow != 0 { return 51 }
60 if u4096_eq(d, a) != 1 { return 52 }
61
62 // ---- Test D: carry propagation across all 128 limbs ----
63 // 0xFF..FF + 1 = 0 with carry-out 1
64 let all_ones: *i64 = u4096_alloc()
65 i = 0
66 while i < NX_U4096_LIMBS {
67 all_ones[i] = NX_U4096_LIMB_MASK
68 i = i + 1
69 }
70 let e: *i64 = u4096_alloc()
71 let carry2: i64 = u4096_add_with_carry(e, all_ones, one_v)
72 if carry2 != 1 { return 60 }
73 if u4096_is_zero(e) != 1 { return 61 }
74
75 // 0 - 1 = 0xFF..FF with borrow-out 1
76 let f: *i64 = u4096_alloc()
77 let z2: *i64 = u4096_alloc()
78 let borrow2: i64 = u4096_sub_with_borrow(f, z2, one_v)
79 if borrow2 != 1 { return 70 }
80 if u4096_eq(f, all_ones) != 1 { return 71 }
81
82 // ---- Test E: cmp ----
83 if u4096_cmp(z2, one_v) != 0 - 1 { return 80 }
84 if u4096_cmp(one_v, z2) != 1 { return 81 }
85 if u4096_cmp(one_v, one_v) != 0 { return 82 }
86
87 // ---- Test F: shl1 / shr1 round-trip with carry across all limbs ----
88 // Start with 1 in low bit; shl1 four times -> 16 at low bit.
89 let g: *i64 = u4096_alloc()
90 u4096_one(g)
91 u4096_shl1(g)
92 u4096_shl1(g)
93 u4096_shl1(g)
94 u4096_shl1(g)
95 if g[0] != 16 { return 90 }
96 u4096_shr1(g)
97 u4096_shr1(g)
98 u4096_shr1(g)
99 u4096_shr1(g)
100 if g[0] != 1 { return 91 }
101 var k: i64 = 1
102 while k < NX_U4096_LIMBS {
103 if g[k] != 0 { return 92 }
104 k = k + 1
105 }
106
107 // ---- Test G: shl1 carry from limb 0 into limb 1 ----
108 let h: *i64 = u4096_alloc()
109 u4096_zero(h)
110 h[0] = 0x80000000 // high bit of limb 0
111 u4096_shl1(h)
112 if h[0] != 0 { return 100 }
113 if h[1] != 1 { return 101 }
114
115 // ---- Test H: get_bit ----
116 let j: *i64 = u4096_alloc()
117 u4096_zero(j)
118 j[0] = 0x5 // bits 0 and 2 set
119 j[3] = 0x80000000 // bit 32*3+31 = 127 set
120 if u4096_get_bit(j, 0) != 1 { return 110 }
121 if u4096_get_bit(j, 1) != 0 { return 111 }
122 if u4096_get_bit(j, 2) != 1 { return 112 }
123 if u4096_get_bit(j, 127) != 1 { return 113 }
124 if u4096_get_bit(j, 128) != 0 { return 114 }
125
126 // "PASS\n"
127 let ok: *u8 = sys_mmap(8)
128 ok[0]=80; ok[1]=65; ok[2]=83; ok[3]=83; ok[4]=10
129 sys_write(1, ok, 5)
130 return 0
131}