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