day 24 optimize
[aoc_eblake.git] / math64.m4
blob341d386a5a26393d7ac7df74cf9e0151e1100ce7
1 divert(-1)dnl -*- m4 -*-
2 # Build arbitrary-length math on top of 32-bit
3 # assumes common.m4 is already loaded
4 define(`chunk', `_$0($1, eval(len($1) - $2), substr(00000000, 0, $2))')
5 define(`_chunk', `ifelse(eval($2 > 0), 1, `eval(-1$3 + 1substr($1, $2)), $0(
6   substr($1, 0, $2), eval($2 - len($3)), $3)', $1)')
7 define(`rebuild', `trim(_$0($@))')
8 define(`_rebuild', `ifelse(`$#', 2, `$2', `$0($1, shift(shift($@)))eval($2,
9   `', $1)')')
10 define(`trim', `_$0($1, index(translit($1, 123456789, .........), .))')
11 define(`_trim', `ifelse($2, -1, 0, `substr($1, $2)')')
12 define(`split', `ifelse(index($1, -), -1, ``p', $1', ``n', substr($1, 1)')')
13 define(`perform', `_$0(`$1', split($2), split($3))')
14 define(`_perform', `$1$2$4($3, $5)')
16 define(`neg64', `ifelse($1, 0, 0, index($1, -), 0, `substr($1, 1)', -$1)')
17 define(`add64', `ifelse(eval(len($1) < 10 && len($2) < 10), 1, `eval($1 + $2)',
18   `perform(`_$0', $@)')')
19 define(`sub64', `add64($1, neg64($2))')
20 define(`_add64', `ifelse($1, 0, $2, $2, 0, $1, `rebuild(8a1(0, (chunk($1, 8)),
21   chunk($2, 8)))')')
22 define(`_a1', `, ifelse(len($1), 9, `eval($1 - 100000000)', $1)a1(eval($1 >=
23   100000000),')
24 define(`a1', `ifelse($1$2$3, 0(), `', `_$0(eval(first$2 + $3 + $1)) (shift$2),
25   shift(shift(shift($@))))')')
26 define(`_sub64', `ifelse($2, 0, $1, $1, $2, 0, `rebuild(8`'s1(0, (chunk($1, 8)),
27   chunk($2, 8)))')')
28 define(`_s1', `, ifelse(eval($1 < 0), 1, `eval($1 + 100000000)s1(-1,',
29   `$1`'s1(0,')')
30 define(`s1', `ifelse($1$2$3, 0(), `', `_$0(eval(first$2 - $3 + 0 +
31   $1)) (shift$2), shift(shift(shift($@))))')')
32 define(`_add64pp', defn(`_add64'))
33 define(`_add64pn', `ifelse(_lt64pp($1, $2), 1, `-_sub64($2, $1)',
34   `_sub64($1, $2)')')
35 define(`_add64np', `_add64pn($2, $1)')
36 define(`_add64nn', `-_add64($1, $2)')
37 define(`add', `ifelse($#, 1, $1, $#, 2, `add64($1, $2)',
38   `add(add64($1, $2), shift(shift($@)))')')
39 define(`mul64', `ifelse(eval(len($1$2) < 10), 1, `eval($1 * $2)',
40   `perform(`_$0', $@)')')
41 define(`_mul64', `ifelse($1, 0, 0, $1, 1, $2, $2, 0, 0, $1, -1, `neg64($2)',
42   $2, 1, $1, $2, -1, `neg64($1)', `add(m1($2, `', chunk($1, 4)))')')
43 define(`m1', `mul64($1, $3)$2ifelse($#, 3, `', `, m1($1, $2`'0000,
44   shift(shift(shift($@))))')')
45 define(`mul', `ifelse($#, 1, $1, $#, 2, `mul64($1, $2)',
46   `mul(mul64($1, $2), shift(shift($@)))')')
47 define(`_mul64pp', defn(`_mul64'))
48 define(`_mul64pn', `-'defn(`_mul64'))
49 define(`_mul64np', `-'defn(`_mul64'))
50 define(`_mul64nn', defn(`_mul64'))
51 define(`lt64', `ifelse($1, $2, 0, `ifelse(eval(len($1) < 10 && len($2) < 10),
52   1, `eval($1 < $2)', `perform(`_lt64', $@)')')')
53 define(`_lt64', `ifelse($3, $4, `ifelse(eval($5 || $3 < 10), 1,
54   `eval($1 < $2)', `$0(1substr($1, 9), 1substr($2, 9), substr($1, 0, 9),
55   substr($2, 0, 9), eval(len($1) < 17))')', `eval($3 < $4)')')
56 define(`_lt64pp', `_lt64($@, len($1), len($2), 0)')
57 define(`_lt64pn', 0)
58 define(`_lt64np', 1)
59 define(`_lt64nn', `_lt64pp($2, $1)')
61 define(`no64', `pushdef(`add64', `eval($'`1 + $'`2)')pushdef(`sub64',
62   `eval($'`1 - $'`2)')pushdef(`mul64', `eval($'`1 * $'`2)')pushdef(`lt64',
63   `eval($'`1 < $'`2)')')