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}