code wiki / (root) / nx_mathcore.nx

nx_mathcore.nx source

↩ module page · 107 lines · 4125 B

1// nx_mathcore.nx -- emit an EXACT multi-precision product so an OUTSIDE arithmetic can adjudicate it. 2// 3// The gate beside this organ (nx_mathcore_gate) proves our exact arithmetic by algebraic identity, which is 4// OUR instrument judging OUR artifact. That is one method class. The second class needs a witness we did not 5// write and cannot influence, which is why this organ exists: it prints a real product of real operands in a 6// form any arbitrary-precision arithmetic on earth can check, so a third party can CONFIRM it -- and, handed a 7// perturbed digit, must REFUSE it. A witness that cannot disagree proves nothing. 8// 9// nx_mathcore mul <decimal_a> <decimal_b> 10// -> MATHCORE-MUL a=<dec> b=<dec> product=<32 hex digits, big-endian, 128 bits> 11// 12// Operands are parsed as unsigned decimal into two 32-bit limbs each; the product is four limbs, serialised 13// big-endian by the same bi_to_bytes_be the crypto lane uses. No floats anywhere, by construction. 14// license_tier: ORIGINAL 15import "nx_bigint_lib.nx" 16import "nx_itoa_lib.nx" 17 18const MC_SLOTS: i64 = 8 19const MC_SLOT_BYTES: i64 = 64 20const MC_PROD_BYTES: i64 = 16 // 4 limbs x 32 bits = 128 bits 21const MC_FULL_LIMB: i64 = 0xFFFFFFFF 22const MC_N2: i64 = 2 23const MC_N4: i64 = 4 24const MC_ASCII_0: i64 = 48 25const MC_ASCII_9: i64 = 57 26const MC_ASCII_a: i64 = 97 27const MC_HEX_A_OFF: i64 = 10 28const MC_USAGE: i64 = 2 29 30func mc_slen(s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } return n } 31func mc_puts(s: *u8) -> i64 { sys_write(1, s, mc_slen(s)); return 0 } 32func mc_streq(a: *u8, b: *u8) -> i64 { 33 var i: i64 = 0 34 while a[i] != (0 as u8) { if a[i] != b[i] { return 0 } i = i + 1 } 35 if b[i] != (0 as u8) { return 0 } 36 return 1 37} 38// unsigned decimal -> i64; returns -1 on any non-digit so a bad operand is REFUSED, never silently zero 39func mc_atou(s: *u8) -> i64 { 40 var v: i64 = 0 41 var i: i64 = 0 42 if s[0] == (0 as u8) { return 0 - 1 } 43 while s[i] != (0 as u8) { 44 let c: i64 = s[i] as i64 45 if c < MC_ASCII_0 { return 0 - 1 } 46 if c > MC_ASCII_9 { return 0 - 1 } 47 v = v * 10 + (c - MC_ASCII_0) 48 i = i + 1 49 } 50 return v 51} 52func mc_put64(x: *i64, v: i64) -> i64 { 53 bi_zero(x, MC_SLOTS) 54 x[0] = v & MC_FULL_LIMB 55 x[1] = (v >> 32) & MC_FULL_LIMB 56 return 0 57} 58func mc_hexdigit(v: i64) -> i64 { 59 if v < MC_HEX_A_OFF { return MC_ASCII_0 + v } 60 return MC_ASCII_a + (v - MC_HEX_A_OFF) 61} 62 63func main(argc: i64, argv: *i64) -> i64 { 64 if argc < 4 { 65 mc_puts("usage: nx_mathcore mul <decimal_a> <decimal_b> -- prints the exact 128-bit product as big-endian hex for an outside arithmetic to check\n" as *u8) 66 sys_exit(MC_USAGE); return MC_USAGE 67 } 68 if mc_streq(argv[1] as *u8, "mul" as *u8) == 0 { 69 mc_puts("nx_mathcore: unknown verb (mul)\n" as *u8) 70 sys_exit(MC_USAGE); return MC_USAGE 71 } 72 let sa: *u8 = argv[2] as *u8 73 let sb: *u8 = argv[3] as *u8 74 let va: i64 = mc_atou(sa) 75 let vb: i64 = mc_atou(sb) 76 if va < 0 { 77 mc_puts("MATHCORE-REFUSED operand-a-is-not-an-unsigned-decimal\n" as *u8); sys_exit(1); return 1 78 } 79 if vb < 0 { 80 mc_puts("MATHCORE-REFUSED operand-b-is-not-an-unsigned-decimal\n" as *u8); sys_exit(1); return 1 81 } 82 let a: *i64 = sys_mmap(MC_SLOT_BYTES) as *i64 83 let b: *i64 = sys_mmap(MC_SLOT_BYTES) as *i64 84 let r: *i64 = sys_mmap(MC_SLOT_BYTES) as *i64 85 mc_put64(a, va) 86 mc_put64(b, vb) 87 bi_zero(r, MC_SLOTS) 88 bi_mul(r, a, MC_N2, b, MC_N2) 89 let bytes: *u8 = sys_mmap(MC_PROD_BYTES + 8) 90 bi_to_bytes_be(bytes, MC_PROD_BYTES, r, MC_N4) 91 mc_puts("MATHCORE-MUL a=" as *u8); mc_puts(sa) 92 mc_puts(" b=" as *u8); mc_puts(sb) 93 mc_puts(" product=" as *u8) 94 let hex: *u8 = sys_mmap(MC_PROD_BYTES * 2 + 8) 95 var i: i64 = 0 96 while i < MC_PROD_BYTES { 97 let byte: i64 = bytes[i] as i64 98 hex[i * 2] = mc_hexdigit((byte >> 4) & 15) as u8 99 hex[i * 2 + 1] = mc_hexdigit(byte & 15) as u8 100 i = i + 1 101 } 102 hex[MC_PROD_BYTES * 2] = 0 as u8 103 mc_puts(hex) 104 mc_puts("\n" as *u8) 105 sys_exit(0) 106 return 0 107}