Improve performance by integrating binary search into MathFunction

This commit is contained in:
Joel Therrien 2018-09-11 17:12:27 -07:00
parent 6e58122380
commit 98cb97a1f1

View file

@ -4,9 +4,7 @@ import lombok.Getter;
import java.io.Serializable;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.Optional;
/**
* Represents a function represented by discrete points. We assume that the function is a stepwise continuous function,
@ -35,29 +33,67 @@ public class MathFunction implements Serializable {
}
public Point evaluate(double time){
Point point = defaultValue;
for(final Point currentPoint: points){
if(currentPoint.getTime() > time){
break;
int index = binarySearch(points, time);
if(index < 0){
return defaultValue;
}
point = currentPoint;
else{
return points.get(index);
}
return point;
}
public Point evaluatePrevious(double time){
Point point = defaultValue;
for(final Point currentPoint: points){
if(currentPoint.getTime() >= time){
break;
int index = binarySearch(points, time) - 1;
if(index < 0){
return defaultValue;
}
point = currentPoint;
else{
return points.get(index);
}
return point;
}
/**
* Returns the index of the largest (in terms of time) Point that is <= the provided time value.
*
* @param points
* @param time
* @return The index of the largest Point who's time is <= the time parameter.
*/
private static int binarySearch(List<Point> points, double time){
final int pointSize = points.size();
if(pointSize == 0 || points.get(pointSize-1).getTime() <= time){
// we're already too far
return pointSize - 1;
}
if(pointSize < 200){
for(int i = 0; i < pointSize; i++){
if(points.get(i).getTime() > time){
return i - 1;
}
}
}
// else
final int middle = pointSize / 2;
final double middleTime = points.get(middle).getTime();
if(middleTime < time){
// go right
return binarySearch(points.subList(middle, pointSize), time) + middle;
}
else if(middleTime > time){
// go left
return binarySearch(points.subList(0, middle), time);
}
else{ // middleTime == time
return middle;
}
}
@Override