view src/fftw-3.3.5/support/addchain.c @ 83:ae30d91d2ffe

Replace these with versions built using an older toolset (so as to avoid ABI compatibilities when linking on Ubuntu 14.04 for packaging purposes)
author Chris Cannam
date Fri, 07 Feb 2020 11:51:13 +0000
parents 2cd0e3b3e1fd
children
line wrap: on
line source
/* 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;
}