示例#1
0
文件: convolve.c 项目: iegor/kdesktop
int convolve_match (float * lastchoice,
		    float * input,
		    convolve_state * state)
/* lastchoice is a 256 sized array.  input is a 512 array.  We find the
 * contiguous length 256 sub-array of input that best matches lastchoice.
 * A measure of how good a sub-array is compared with the lastchoice is
 * given by the sum of the products of each pair of entries.  We maximise
 * that, by taking an appropriate convolution, and then finding the maximum
 * entry in the convolutions.  state is a (non-NULL) pointer returned by
 * convolve_init.  */
{
	double avg;
	double best;
	int p;
	int i;
	double * left = state->left;
	double * right = state->right;
	double * scratch = state->scratch;
	stack_entry * top = state->stack + STACK_SIZE - 1;

	for (i=0; i<512; i++)
		left[i]=input[i];

	avg = 0;
    for (i = 0; i < 256; i++)
	{
		double a = lastchoice[255 - i];
		right[i] = a;
		avg += a;
	}

	/* We adjust the smaller of the two input arrays to have average
	 * value 0.  This makes the eventual result insensitive to both
	 * constant offsets and positive multipliers of the inputs. */
	avg /= 256;
	for (i = 0; i < 256; i++)
		right[i] -= avg;

	/* End-of-stack marker. */
	top[1].b.null = scratch;
	top[1].b.main = NULL;

	/* The low 256x256, of which we want the high 256 outputs. */
	top->v.left = left;
	top->v.right = right;
	top->v.out = right + 256;
	convolve_run (top, 256, scratch);
	
	/* The high 256x256, of which we want the low 256 outputs. */
	top->v.left = left + 256;
	top->v.right = right;
	top->v.out = right;
	convolve_run (top, 256, scratch);

	/* Now find the best position amoungs this.  Apart from the first
	 * and last, the required convolution outputs are formed by adding
	 * outputs from the two convolutions above. */
	best = right[511];
	right[767] = 0;
	p = -1;
	for (i = 0; i < 256; i++) {
		double a = right[i] + right[i + 512];
		if (a > best) {
			best = a;
			p = i;
		}
	}
	p++;

#if 0
	{
		/* This is some debugging code... */
		int bad = 0;
		best = 0;
		for (i = 0; i < 256; i++)
			best += ((double) input[i+p]) * ((double) lastchoice[i] - avg);
		
		for (i = 0; i < 257; i++) {
			double tot = 0;
			unsigned int j;
			for (j = 0; j < 256; j++)
				tot += ((double) input[i+j]) * ((double) lastchoice[j] - avg);
			if (tot > best)
				printf ("(%i)", i);
			if (tot != left[i + 255])
				printf ("!");
		}

		printf ("%i\n", p);
	}
#endif		

	return p;
}
/*
 * convolve_match:
 * @lastchoice: an array of size SMALL.
 * @input: an array of size BIG (2*SMALL)
 * @state: a (non-NULL) pointer returned by convolve_init.
 *
 * We find the contiguous SMALL-size sub-array of input that best matches
 * lastchoice. A measure of how good a sub-array is compared with the lastchoice
 * is given by the sum of the products of each pair of entries.  We maximise
 * that, by taking an appropriate convolution, and then finding the maximum
 * entry in the convolutions.
 *
 * Return: the position of the best match
 */
int
convolve_match (const int *lastchoice, const short *input,
                convolve_state * state)
{
    double avg = 0;
    double best;
    int p = 0;
    int i;
    double *left = state->left;
    double *right = state->right;
    double *scratch = state->scratch;
    stack_entry *top = state->stack + (state->stack_size - 1);

    for (i = 0; i < state->big; i++)
        left[i] = input[i];

    for (i = 0; i < state->small; i++) {
        double a = lastchoice[(state->small - 1) - i];

        right[i] = a;
        avg += a;
    }

    /* We adjust the smaller of the two input arrays to have average
     * value 0.  This makes the eventual result insensitive to both
     * constant offsets and positive multipliers of the inputs. */
    avg /= state->small;
    for (i = 0; i < state->small; i++)
        right[i] -= avg;
    /* End-of-stack marker. */
    top[1].b.null = scratch;
    top[1].b.main = NULL;
    /* The low (small x small) part, of which we want the high outputs. */
    top->v.left = left;
    top->v.right = right;
    top->v.out = right + state->small;
    convolve_run (top, state->small, scratch);

    /* The high (small x small) part, of which we want the low outputs. */
    top->v.left = left + state->small;
    top->v.right = right;
    top->v.out = right;
    convolve_run (top, state->small, scratch);

    /* Now find the best position amoungs this.  Apart from the first
     * and last, the required convolution outputs are formed by adding
     * outputs from the two convolutions above. */
    best = right[state->big - 1];
    right[state->big + state->small - 1] = 0;
    p = -1;
    for (i = 0; i < state->small; i++) {
        double a = right[i] + right[i + state->big];

        if (a > best) {
            best = a;
            p = i;
        }
    }
    p++;

#if 0
    {
        /* This is some debugging code... */
        best = 0;
        for (i = 0; i < state->small; i++)
            best += ((double) input[i + p]) * ((double) lastchoice[i] - avg);

        for (i = 0; i <= state->small; i++) {
            double tot = 0;
            unsigned int j;

            for (j = 0; j < state->small; j++)
                tot += ((double) input[i + j]) * ((double) lastchoice[j] - avg);
            if (tot > best)
                printf ("(%i)", i);
            if (tot != left[i + (state->small - 1)])
                printf ("!");
        }

        printf ("%i\n", p);
    }
#endif

    return p;
}