Skip to content

Commit 89a8c91

Browse files
authored
Add Maximum Array Rotation in M4 (#4948)
1 parent 2f87a08 commit 89a8c91

File tree

1 file changed

+72
-0
lines changed

1 file changed

+72
-0
lines changed
Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
divert(-1)
2+
define(`show_usage',
3+
`Usage: please provide a list of integers (e.g. "8, 3, 1, 2")
4+
m4exit(`1')')
5+
6+
dnl Reference: https://www.gnu.org/software/m4/manual/m4.html#index-array
7+
dnl array_get(var_name, idx)
8+
define(`array_get', `defn(format(``%s[%s]'', `$1', `$2'))')
9+
10+
dnl array_set(var_name, idx, value)
11+
define(`array_set', `define(format(``%s[%s]'', `$1', `$2'), `$3')')
12+
13+
dnl is_valid(n)
14+
define(`is_valid', `eval(regexp(`$1', `^\s*-?[0-9]+\s*$') >= 0)')
15+
16+
dnl parse_int_list(varname, args):
17+
dnl varname[length] = 0
18+
dnl foreach arg in args:
19+
dnl if not is_valid(arg):
20+
dnl Return 0
21+
dnl varname[varname[length]] = arg
22+
dnl varname[length] = varname[length] + 1
23+
dnl Return 1
24+
define(`parse_int_list',
25+
`array_set(`$1', `length', 0)dnl
26+
_parse_int_list(`$1', $2)'dnl
27+
)
28+
define(`_parse_int_list',
29+
`ifelse(is_valid(`$2'), 0, `0',
30+
`array_set(`$1', array_get(`$1', `length'), `$2')dnl
31+
array_set(`$1', `length', incr(array_get(`$1', `length')))dnl
32+
ifelse(eval($# > 2), 1, `_parse_int_list(`$1', shift(shift($@)))', `1')'dnl
33+
)'dnl
34+
)
35+
36+
dnl M4 does not have infinity so choose smallest integer value as minus infinity
37+
define(`MINUS_INF', -2147483648)
38+
39+
dnl max(a, b)
40+
define(`max', `ifelse(eval($1 > $2), 1, `$1', `$2')')
41+
42+
dnl maximum_array_rotation(varname):
43+
dnl wmax = -infinity
44+
dnl for n = 0 to varname[length] - 1:
45+
dnl w = array_rotation_sum(varname, n, varname[length])
46+
dnl wmax = max(wmax, w)
47+
dnl return wmax
48+
define(`maximum_array_rotation', `_maxmimum_array_rotation(`$1', 0, MINUS_INF)')
49+
define(`_maxmimum_array_rotation',
50+
`ifelse(
51+
eval($2 >= array_get(`$1', `length')), 1, `$3',
52+
`_maxmimum_array_rotation(`$1', incr($2),
53+
max($3, array_rotation_sum(`$1', $2, array_get(`$1', `length'))))'`'dnl
54+
)'dnl
55+
)
56+
57+
dnl array_rotation_sum(varname, offset, mod):
58+
dnl w = 0
59+
dnl for n = 0 to mod - 1:
60+
dnl w = w + n * varname[(n + offset) % mod]
61+
dnl return w
62+
define(`array_rotation_sum', `_array_rotation_sum(`$1', $2, $3, 0, 0)')
63+
define(`_array_rotation_sum',
64+
`ifelse(
65+
eval($4 >= $3), 1, `$5',
66+
`_array_rotation_sum(`$1', $2, $3, incr($4),
67+
eval($5 + $4 * array_get(`$1', eval(($4 + $2) % $3))))'`'dnl
68+
)'dnl
69+
)
70+
divert(0)dnl
71+
ifelse(eval(ARGC < 1 || len(ARGV1) < 1 || !parse_int_list(`arr', ARGV1)), 1, `show_usage()')dnl
72+
maximum_array_rotation(`arr')

0 commit comments

Comments
 (0)