Posts

Post not yet marked as solved
1 Replies
645 Views
vDSP.convolve() reverses the kernel before applying it. For example, the following uses a kernel of 10 elements where the first element is 1.0 and the rest of the elements are 0.0. Applying this kernel to a vector should return the same vector. let values = (0 ..< 30).map { Double($0) } var kernel = Array.init(repeating: 0.0, count: 10) kernel[0] = 1.0 let result = vDSP.convolve(values, withKernel: kernel) print("kernel: \(kernel)") print("values: \(values)") print("result: \(result)") Applied to a values array containing elements 0.0, 1.0, 2.0, etc. the first results should be 0.0, 1.0, 2.0, etc, but instead the results start at 9.0 and increase from there: kernel: [1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0] values: [0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0, 13.0, 14.0, 15.0, 16.0, 17.0, 18.0, 19.0, 20.0, 21.0, 22.0, 23.0, 24.0, 25.0, 26.0, 27.0, 28.0, 29.0] result: [9.0, 10.0, 11.0, 12.0, 13.0, 14.0, 15.0, 16.0, 17.0, 18.0, 19.0, 20.0, 21.0, 22.0, 23.0, 24.0, 25.0, 26.0, 27.0, 28.0] If instead the kernel is reversed, placing the 1.0 at the end of the kernel: let values = (0 ..< 30).map { Double($0) } var kernel = Array.init(repeating: 0.0, count: 10) kernel[9] = 1.0 let result = vDSP.convolve(values, withKernel: kernel) print("kernel: \(kernel)") print("values: \(values)") print("result: \(result)") The results are now correct: kernel: [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0] values: [0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0, 13.0, 14.0, 15.0, 16.0, 17.0, 18.0, 19.0, 20.0, 21.0, 22.0, 23.0, 24.0, 25.0, 26.0, 27.0, 28.0, 29.0] result: [0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0, 13.0, 14.0, 15.0, 16.0, 17.0, 18.0, 19.0]
Posted
by jolonf.
Last updated
.
Post not yet marked as solved
1 Replies
645 Views
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.
Posted
by jolonf.
Last updated
.