code wiki / (root) / nx_u384_mul.nx

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}