Accelerate のものを使用しない別のソリューションを次に示します。
public class Resampler {
///
/// ### Class method to resample some data
///
/// ### Inputs
/// - Actual time data that may not be regularly sampled
/// - Desired times you want the metric found at
/// - Metric data corresponding with actual time data
///
public class func resample( acualTimes atimes: [Double], desiredTimes dtimes: [Double], metric: [Double] ) ->[Double]
{
//
// Initialize the desired metrics array
//
var desiredMetrics: [Double] = [Double](count: dtimes.count, repeatedValue: 0);
// Initialize a counter to keep track of which metric value we are on
var counter: Int = 0;
// Loop through the desired times
for dtime in dtimes {
// Find the bounding indices, based on actual time data, for the desired time
// using a binary search
let (li, ri) = binarySearch(0,highBound: atimes.count-1, desiredTime: dtime, timeData: atimes);
// Find the desired metric using an interpolation
desiredMetrics[counter] = linearInterpolate(lowTime: atimes[li],
highTime: atimes[ri],
lowMetric: metric[li],
highMetric: metric[ri],
desiredTime: dtime);
// Increment the counter
counter++;
}
// Return the desired metrics
return desiredMetrics;
}
///
/// ### Binary search code to find the bounding time value indices
///
private class func binarySearch( lowBound: Int,
highBound: Int,
desiredTime: Double,
timeData: [Double]) -> (leftIndex: Int, rightIndex: Int)
{
if( highBound-lowBound == 1 ){
return (lowBound, highBound);
}else{
let center: Int = (lowBound + highBound)/2;
if( desiredTime <= timeData[center]){
return binarySearch(lowBound, highBound: center, desiredTime: desiredTime, timeData: timeData);
}else{
return binarySearch(center, highBound: highBound, desiredTime: desiredTime, timeData: timeData);
}
}
}
///
/// ### Linear interpolation method
///
private class func linearInterpolate( lowTime lt: Double,
highTime ht: Double,
lowMetric lm: Double,
highMetric hm: Double,
desiredTime dt: Double ) -> Double
{
return lm + (dt-lt)*(hm-lm)/(ht-lt);
}
}
そして、次のようにするだけで実行できます。
let times: [Double] = [0.0,1.3,2.2,3.4,4.2,5.5,6.6,7.2,8.4,9.5,10.0];
let desiredTimes: [Double] = [0,1,2,3,4,5,6,7,8,9,10];
let metricData: [Double] = [4,3,6,7,4,5,7,4,2,7,2];
let desiredMetrics = Resampler.resample(acualTimes: times, desiredTimes: desiredTimes, metric: metricData);
print(desiredMetrics)
上記の例では、次のように出力されます。
[4.0, 3.23076923076923, 5.33333333333333, 6.66666666666667, 4.75, 4.61538461538461, 5.90909090909091, 5.0, 2.66666666666667, 4.72727272727273, 2.0]