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