nx_u384_mul.nx source
↩ module page · 110 lines · 3122 B
1// nx_u384_mul.nx -- 384x384 -> 768-bit schoolbook multiplication +
2// wide-buffer helpers (alloc / cmp / fits_in_384 / copy_low).
3//
4// Mirror of nx_u256_mul.nx with 24-limb wide buffers in place of
5// 16-limb. Foundation for nx_p384_field_mul.
6//
7// API:
8// u384_wide_alloc() -> *i64 24-limb buffer (zeroed)
9// u384_mul_wide(out_24, a, b) out_24 = a * b (no reduction)
10// u384_wide_cmp(a_24, b_24) -> -1 | 0 | +1
11// u384_wide_fits_in_384(a_24) -> 0 | 1
12// u384_wide_copy_low(out_12, src_24)
13//
14// license_tier: INDEPENDENT_REDERIVE
15// genealogy_id: international-research-sources/nist/fips_186_5
16// lineage_id: nishi_u384_mul_q10
17
18// nx_safety_envelope:
19// intended_use: AUTO_APPLIED -- primitive-specific tuning queued
20// sil_target: SIL1
21// evidence: [bulk_applied_2026-05-20, u384-wide-mul]
22// verdict: NOT_YET_EVALUATED
23
24import "nx_syscalls.nx"
25import "nx_u384.nx"
26
27const NX_U384_WIDE_LIMBS: i64 = 24
28const NX_U384_WIDE_BYTES: i64 = 96
29
30func u384_wide_alloc() -> *i64 {
31 let b: *u8 = sys_mmap(NX_U384_WIDE_LIMBS * 8)
32 let p: *i64 = b as *i64
33 var i: i64 = 0
34 while i < NX_U384_WIDE_LIMBS {
35 p[i] = 0
36 i = i + 1
37 }
38 return p
39}
40
41// Free a u384_wide_alloc buffer (the 768-bit product scratch). Paired
42// with u384_free so p384_field_mul_fast leaves no per-call leak.
43func u384_wide_free(p: *i64) -> i64 {
44 if (p as i64) == 0 { return 0 }
45 sys_munmap(p as *u8, NX_U384_WIDE_LIMBS * 8)
46 return 0
47}
48
49// out_24 = a * b (384x384 -> 768). No reduction.
50// Aliasing: out_24 MUST be a distinct buffer from a and b.
51func u384_mul_wide(out_24: *i64, a: *i64, b: *i64) -> i64 {
52 var k: i64 = 0
53 while k < NX_U384_WIDE_LIMBS {
54 out_24[k] = 0
55 k = k + 1
56 }
57 var i: i64 = 0
58 while i < NX_U384_LIMBS {
59 let ai: i64 = a[i] & NX_U384_LIMB_MASK
60 var carry: i64 = 0
61 var j: i64 = 0
62 while j < NX_U384_LIMBS {
63 let bj: i64 = b[j] & NX_U384_LIMB_MASK
64 let prev: i64 = out_24[i + j] & NX_U384_LIMB_MASK
65 let s: i64 = prev + ai * bj + carry
66 out_24[i + j] = s & NX_U384_LIMB_MASK
67 carry = (s >> NX_U384_LIMB_BITS) & NX_U384_LIMB_MASK
68 j = j + 1
69 }
70 out_24[i + 12] = carry
71 i = i + 1
72 }
73 return 0
74}
75
76func u384_wide_cmp(a_24: *i64, b_24: *i64) -> i64 {
77 var i: i64 = NX_U384_WIDE_LIMBS - 1
78 while i >= 0 {
79 let av: i64 = a_24[i] & NX_U384_LIMB_MASK
80 let bv: i64 = b_24[i] & NX_U384_LIMB_MASK
81 if av < bv { return 0 - 1 }
82 if av > bv { return 1 }
83 i = i - 1
84 }
85 return 0
86}
87
88func u384_wide_fits_in_384(a_24: *i64) -> i64 {
89 var i: i64 = 12
90 var acc: i64 = 0
91 while i < NX_U384_WIDE_LIMBS {
92 acc = acc | (a_24[i] & NX_U384_LIMB_MASK)
93 i = i + 1
94 }
95 if acc == 0 { return 1 }
96 return 0
97}
98
99func u384_wide_copy_low(out_12: *i64, src_24: *i64) -> i64 {
100 var i: i64 = 0
101 while i < NX_U384_LIMBS {
102 out_12[i] = src_24[i]
103 i = i + 1
104 }
105 return 0
106}
107
108func main() -> i64 {
109 return 0
110}