(Copied from an internal Mentor Graphics issue.)

Introduction

------------

C-VSIPL defines the following equation to compute the values y_n of a

minimum support 1-D convolution:

y_n = Sum k from 0 to M-1 of ( h_k * x_(n*D + (M-1) - k) )

Where:

N is the input vector length,

M is the kernel length,

D is the deimation,

x_j is the input vector (of size N)

h_k is the kernel vector (of size M)

C-VSIPL defines the length of the output vector (i.e. values n for

which y_n is defined) as:

floor( (N-1) / D ) - floor( (M-1) / D) + 1

In some cases, this equation requires the implementation to access

elements of x outside the x proper.

Example Illustrating the Problem

--------------------------------

To see this, first consider the case (where the equation is correct):

N = 5, M = 4, D = 1.

The expected output length is:

floor((5-1)/1) - floor((4-1)/1) + 1

= 4 - 3 + 1

= 2

Consider a diagram showing how each output is computed:

x_0 x_1 x_2 x_3 x_4

y_0 = h_3 h_2 h_1 h_0

y_1 = h_3 h_2 h_1 h_0

I.e.

y_0 = h_0*x_3 + h_1*x_2 + h_2*x_1 + h_3*x_0

y_1 = h_0*x_4 + h_1*x_3 + h_2*x_2 + h_3*x_1

In computing y_0 and y_1, only values

{ x_j | 0 <= j < 5 }
are required.

Next, consider the case:

N = 5, M = 4, D = 2.

The expected output length is:

floor((5-1)/2) - floor((4-1)/2) + 1

= floor(4/2) - floor(3/2) + 1

= 2 - 1 + 1

= 2

To compute y_n, we need to multiply h_k by x_(n D + (M-1) - k).

For n=1, k=0, the index to x is

n D + (M-1) - k

= 1 2 + (4-1) - 0

= 2 + 3 - 0

= 5

However, x_5 is not a valid element of x.

Pictorally:

x_0 x_1 x_2 x_3 x_4

y_0 = h_3 h_2 h_1 h_0

y_1 = h_3 h_2 h_1 h_0

Finally, consider two more cases:

N = 5, M = 4, D = 3 -> output length = 1

N = 5, M = 4, D = 4 -> output length = 2

(Why should D=3 be any different from the other cases?)

This does not make sense for several reasons:

- First, when D=2, a value (x_5) outside the support of x is required

to compute the result. This might run counter to user's expectations

of how the minimal output region of support should be defined.

- Second, changing the decimation

A New Equation for the Output Length

------------------------------------

What should the output length be?

Starting from the assumption that the formula for y_n is correct, we

need to determine the range of indices

{n}
for which all indices to x

are valid.

In particular, we want to find the largest n such that the following

holds for all k in 0 <= k <= M-1:

0 <= n*D + (M-1) - k < N

The lower bound is true for all n >= 0 since n*D >= 0 and (M-1)-k >= 0.

The upper bound:

n*D + (M-1) - k < N

The largest LHS occurs when k = 0:

n*D + (M-1) < N

n*D < N - M + 1

n < ceil((N-M+1) / D)

The largest n that we can compute y_n for is

n = ceil((N-M+1) / D)-1

Hence the output length is:

ceil((N-M+1) / D)

In the case where D=1, this reduces to:

N-M+1

(which is what the current equation reduces too when D=1).

Comparing the new equation with the old one for the previous examples:

N=5, M=4, D=1 old=2 new=2

N=5, M=4, D=2 old=2 new=1

N=5, M=4, D=3 old=1 new=1

N=5, M=4, D=4 old=2 new=1

Equation for Full Support Output Length

---------------------------------------

Similarly, the lengths for full support case are also incorrect.

For full support, the assumption is that each output vector should

have at least one value from x used to compute it:

n*D - k < N

(minimal index occurs when k = M-1)

n*D - (M-1) < N

n*D < N + (M-1)

n < ceil((N+M-1)/D)

However, here the error is less of an issue because the equation to

compute y_n is based on < x_k > rather than x_k. <x_k> is defined to

be 0 if k < 0 of k >= N