vDSP.convolve returns wrong sized array?

vDSP.convolve() returns an array with length:

values.count - kernel.count

But shouldn't the result array have length:

values.count - kernel.count + 1

I ran the following which prints out the size of the results array with various combinations of values and kernel lengths:

for i in 0 ..< 10 {
  let values = Array.init(repeating: 1.0, count: 1000 + i)
  for j in 0 ..< 10 {
    let kernel = Array.init(repeating: 1.0, count: 100 + j)
    let result = vDSP.convolve(values, withKernel: kernel)
     
    print("values[\(values.count)], kernel[\(kernel.count)], result[\(result.count)], result[\(result.count - 1)] = \(result[result.count - 1])")
  }
}

As you can see the results array always has length values.count - kernel.count:

values[1000], kernel[100], result[900], result[899] = 100.0
values[1000], kernel[101], result[899], result[898] = 101.0
values[1000], kernel[102], result[898], result[897] = 102.0
values[1000], kernel[103], result[897], result[896] = 103.0
values[1000], kernel[104], result[896], result[895] = 104.0
values[1000], kernel[105], result[895], result[894] = 105.0
values[1000], kernel[106], result[894], result[893] = 106.0
values[1000], kernel[107], result[893], result[892] = 107.0
values[1000], kernel[108], result[892], result[891] = 108.0
values[1000], kernel[109], result[891], result[890] = 109.0
values[1001], kernel[100], result[901], result[900] = 100.0
values[1001], kernel[101], result[900], result[899] = 101.0
values[1001], kernel[102], result[899], result[898] = 102.0
values[1001], kernel[103], result[898], result[897] = 103.0
values[1001], kernel[104], result[897], result[896] = 104.0
values[1001], kernel[105], result[896], result[895] = 105.0
...

However, the result array should have length values.count - kernel.count + 1.

For example, if instead of using the returned result array, a result array is passed to vDSP.convolve, with length values.count - kernel.count + 1 the last value has a valid result:

for i in 0 ..< 10 {
  let values = Array.init(repeating: 1.0, count: 1000 + i)
  for j in 0 ..< 10 {
    let kernel = Array.init(repeating: 1.0, count: 100 + j)
    var result = Array.init(repeating: 0.0, count: values.count - kernel.count + 1)
    vDSP.convolve(values, withKernel: kernel, result: &result)
     
    print("values[\(values.count)], kernel[\(kernel.count)], result[\(result.count)], result[\(result.count - 1)] = \(result[result.count - 1])")
  }
}
values[1000], kernel[100], result[901], result[900] = 100.0
values[1000], kernel[101], result[900], result[899] = 101.0
values[1000], kernel[102], result[899], result[898] = 102.0
values[1000], kernel[103], result[898], result[897] = 103.0
values[1000], kernel[104], result[897], result[896] = 104.0
values[1000], kernel[105], result[896], result[895] = 105.0
values[1000], kernel[106], result[895], result[894] = 106.0
values[1000], kernel[107], result[894], result[893] = 107.0
values[1000], kernel[108], result[893], result[892] = 108.0
values[1000], kernel[109], result[892], result[891] = 109.0
values[1001], kernel[100], result[902], result[901] = 100.0
values[1001], kernel[101], result[901], result[900] = 101.0
values[1001], kernel[102], result[900], result[899] = 102.0
values[1001], kernel[103], result[899], result[898] = 103.0
values[1001], kernel[104], result[898], result[897] = 104.0
values[1001], kernel[105], result[897], result[896] = 105.0

If the result array is created with length values.count - kernel.count + 2 then we get the following runtime error:

error: Execution was interrupted, reason: EXC_BAD_INSTRUCTION (code=EXC_I386_INVOP, subcode=0x0).
The process has been left at the point where it was interrupted, use "thread return -x" to return to the state before expression evaluation.

Indicating the extra element in the result array is valid and vDSP.convolve() is returning a result array which is one element too short.

Replies

Many thanks for your post.

It would be super helpful if you could submit a bug report with the Feedback Assistant app, or use the Feedback Assistant web page. That will get the info to the right teams to fully investigate this issue.

In the meantime, as you mention, the class vDSP.convolve(_:withKernel:result:) function returns a result with values.count - kernel.count + 2 elements.