12

I'm stuck with interpolation in Swift. Can anyone help me with that?

I want to interpolate the float array (say [0, 0, 100, 25, 0, 0, 0, 25, 0, 0, 0]) into another array with some given size (for example 128). I found an article (Use Linear Interpolation to Construct New Data Points) that shows, how to achieve this stuff.

There are two ways (you can see the results below, how they perform):

  • Linear Interpolation using vDSP_vgenp and
  • Smoother (but not for my purposes) Interpolation using vDSP_vlint

The problem is both techniques don't realize my expectations, which illustrated in Screenshot 3. How can I make my interpolated distribution smoother? I want to see a cube-like curve.

Initial Plot:

Screenshot 1

Linear Interpolation:

import Accelerate

let n = vDSP_Length(128)
let stride = vDSP_Stride(1)

let values: [Float] = [0, 0, 100, 25, 0, 0, 0, 25, 0, 0, 0]
let indices: [Float] = [0, 11, 23, 34, 46, 58, 69, 81, 93, 104, 116]

var result = [Float](repeating: 0, count: Int(n))

vDSP_vgenp(values, stride, indices, stride, &result, stride, n, vDSP_Length(values.count))

Screenshot 2

Smooth Interpolation:

import Accelerate
import AVFoundation

let n = vDSP_Length(1024)
let stride = vDSP_Stride(1)

let values: [Float] = [0, 0, 100, 25, 0, 0, 0, 25, 0, 0, 0]
let denominator = Float(n) / Float(values.count - 1)

let control: [Float] = (0 ... n).map {
    let x = Float($0) / denominator
    return floor(x) + simd_smoothstep(0, 1, simd_fract(x))
}

var result = [Float](repeating: 0, count: Int(n))

vDSP_vlint(values, control, stride, &result, stride, n, vDSP_Length(values.count))

Screenshot 3

Mark Rotteveel
  • 100,966
  • 191
  • 140
  • 197
aibek
  • 161
  • 8
  • 9
    I can't help answer your question, but I gotta say, this is a really well asked question, particularly for a first time poster! Clear question, demonstration of effort, example of code, actual vs intended outcomes. Well done, and welcome! – Alexander Sep 08 '20 at 15:12
  • Thank you very much @Alexander-ReinstateMonica! I did my best to demonstrate, what I want to solve ^_^ – aibek Sep 08 '20 at 15:20

1 Answers1

0

It seems to me that the vDSP_vqint quadratic interpolation functions would solve the problem. See the discussion at https://developer.apple.com/documentation/accelerate/1449942-vdsp_vqint.

ib.
  • 27,830
  • 11
  • 80
  • 100
KeithB
  • 417
  • 2
  • 12
  • Possibly. I've seen this function but didn't understand what the parameters should look like. Especially the second one - `_ __B: UnsafePointer`. They say: "Single-precision real input vector. Integer parts are indices into A and fractional parts are interpolation constants". There is no glue for me, what is *fractional* and what is *integer* parts. Maybe you could explain this? – aibek Sep 14 '20 at 14:02
  • The parameters are the same as you used in the linear interpolation function. The trick is to change your input function and it's coordinates (as well as the desired output coordinates) so that they overlap nicely. Massage your input function so that it is of the form f(i) where i is a sequence of integers (from 0 to max). Then massage your desired output function g(j) so that it's coordinates fall along the same axis with values also ranging from 0 to max. These output-function coordinates will generally each fall somwhere between the integer values used in your input function. – KeithB Sep 15 '20 at 00:29
  • @aiba Single precision vector and Double precision vector, only means Float and Double. If you look at the documentation you can see that only the type of pointer change https://developer.apple.com/documentation/accelerate/1449771-vdsp_vgenp https://developer.apple.com/documentation/accelerate/1450645-vdsp_vgenpd I think that's also well explained in the Floating-Point Numbers of the Swift documentation https://docs.swift.org/swift-book/LanguageGuide/TheBasics.html You can also print the value of Float.pi and Double.pi to see what's the difference. – Steven Oct 02 '20 at 08:53
  • 3
    After for the integer part, that what's before the `,` and fractional is what comes after. Also, I think in your case you are looking for cubic spline interpolation and not a linear interpolation. I haven't found how to achieve this using the Accelerate Framework, but here is a library that does the same. https://github.com/gscalzo/SwiftCubicSpline – Steven Oct 02 '20 at 09:17
  • 1
    Thank you all for the answers! I went with @Steven's suggestion and used CubicSpline. – aibek Nov 05 '22 at 00:13