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;
							 | 
						||
| 
								 | 
							
								}
							 |