mirror of
https://github.com/tildearrow/furnace.git
synced 2024-11-18 10:35:11 +00:00
172 lines
3.1 KiB
C
172 lines
3.1 KiB
C
|
/* addition-chain optimizer */
|
||
|
#include <stdio.h>
|
||
|
#include <stdlib.h>
|
||
|
#include <unistd.h>
|
||
|
|
||
|
static int verbose;
|
||
|
static int mulcost = 18;
|
||
|
static int ldcost = 2;
|
||
|
static int sqcost = 10;
|
||
|
static int reflcost = 8;
|
||
|
#define INFTY 100000
|
||
|
|
||
|
static int *answer;
|
||
|
static int best_so_far;
|
||
|
|
||
|
static void print_answer(int n, int t)
|
||
|
{
|
||
|
int i;
|
||
|
printf("| (%d, %d) -> [", n, t);
|
||
|
for (i = 0; i < t; ++i)
|
||
|
printf("%d;", answer[i]);
|
||
|
printf("] (* %d *)\n", best_so_far);
|
||
|
}
|
||
|
|
||
|
#define DO(i, j, k, cst) \
|
||
|
if (k < n) { \
|
||
|
int c = A[i] + A[j] + cst; \
|
||
|
if (c < A[k]) { \
|
||
|
A[k] = c; \
|
||
|
changed = 1; \
|
||
|
} \
|
||
|
}
|
||
|
|
||
|
#define DO3(i, j, l, k, cst) \
|
||
|
if (k < n) { \
|
||
|
int c = A[i] + A[j] + A[l] + cst; \
|
||
|
if (c < A[k]) { \
|
||
|
A[k] = c; \
|
||
|
changed = 1; \
|
||
|
} \
|
||
|
}
|
||
|
|
||
|
static int optimize(int n, int *A)
|
||
|
{
|
||
|
int i, j, k, changed, cst, cstmax;
|
||
|
|
||
|
do {
|
||
|
changed = 0;
|
||
|
for (i = 0; i < n; ++i) {
|
||
|
k = i + i;
|
||
|
DO(i, i, k, sqcost);
|
||
|
}
|
||
|
|
||
|
for (i = 0; i < n; ++i) {
|
||
|
for (j = 0; j <= i; ++j) {
|
||
|
k = i + j;
|
||
|
DO(i, j, k, mulcost);
|
||
|
k = i - j;
|
||
|
DO(i, j, k, mulcost);
|
||
|
|
||
|
k = i + j;
|
||
|
DO3(i, j, i - j, k, reflcost);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
} while (changed);
|
||
|
|
||
|
cst = cstmax = 0;
|
||
|
for (i = 0; i < n; ++i) {
|
||
|
cst += A[i];
|
||
|
if (A[i] > cstmax) cstmax = A[i];
|
||
|
}
|
||
|
/* return cstmax; */
|
||
|
return cst;
|
||
|
}
|
||
|
|
||
|
static void search(int n, int t, int *A, int *B, int depth)
|
||
|
{
|
||
|
if (depth == 0) {
|
||
|
int i, tc;
|
||
|
for (i = 0; i < n; ++i)
|
||
|
A[i] = INFTY;
|
||
|
A[0] = 0; /* always free */
|
||
|
for (i = 1; i <= t; ++i)
|
||
|
A[B[-i]] = ldcost;
|
||
|
|
||
|
tc = optimize(n, A);
|
||
|
if (tc < best_so_far) {
|
||
|
best_so_far = tc;
|
||
|
for (i = 1; i <= t; ++i)
|
||
|
answer[t - i] = B[-i];
|
||
|
if (verbose)
|
||
|
print_answer(n, t);
|
||
|
}
|
||
|
} else {
|
||
|
for (B[0] = B[-1] + 1; B[0] < n; ++B[0])
|
||
|
search(n, t, A, B + 1, depth - 1);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
static void doit(int n, int t)
|
||
|
{
|
||
|
int *A;
|
||
|
int *B;
|
||
|
|
||
|
A = malloc(n * sizeof(int));
|
||
|
B = malloc((t + 1) * sizeof(int));
|
||
|
answer = malloc(t * sizeof(int));
|
||
|
|
||
|
B[0] = 0;
|
||
|
best_so_far = INFTY;
|
||
|
search(n, t, A, B + 1, t);
|
||
|
|
||
|
print_answer(n, t);
|
||
|
|
||
|
free(A); free(B); free(answer);
|
||
|
}
|
||
|
|
||
|
int main(int argc, char *argv[])
|
||
|
{
|
||
|
int n = 32;
|
||
|
int t = 3;
|
||
|
int all;
|
||
|
int ch;
|
||
|
|
||
|
verbose = 0;
|
||
|
all = 0;
|
||
|
while ((ch = getopt(argc, argv, "n:t:m:l:r:s:va")) != -1) {
|
||
|
switch (ch) {
|
||
|
case 'n':
|
||
|
n = atoi(optarg);
|
||
|
break;
|
||
|
case 't':
|
||
|
t = atoi(optarg);
|
||
|
break;
|
||
|
case 'm':
|
||
|
mulcost = atoi(optarg);
|
||
|
break;
|
||
|
case 'l':
|
||
|
ldcost = atoi(optarg);
|
||
|
break;
|
||
|
case 's':
|
||
|
sqcost = atoi(optarg);
|
||
|
break;
|
||
|
case 'r':
|
||
|
reflcost = atoi(optarg);
|
||
|
break;
|
||
|
case 'v':
|
||
|
++verbose;
|
||
|
break;
|
||
|
case 'a':
|
||
|
++all;
|
||
|
break;
|
||
|
case '?':
|
||
|
fprintf(stderr, "use the source\n");
|
||
|
exit(1);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (all) {
|
||
|
for (n = 4; n <= 64; n *= 2) {
|
||
|
int n1 = n - 1; if (n1 > 7) n1 = 7;
|
||
|
for (t = 1; t <= n1; ++t)
|
||
|
doit(n, t);
|
||
|
}
|
||
|
} else {
|
||
|
doit(n, t);
|
||
|
}
|
||
|
|
||
|
return 0;
|
||
|
}
|