+ /**
+ * Use interpolation to determine the value of the function at point t.
+ * Current implementation uses simple linear interpolation. The domain
+ * and range lists must include the same number of values, t must be within
+ * the domain, and the domain list must be sorted.
+ *
+ * @param domain list containing domain samples
+ * @param range list of corresponding range samples
+ * @param t domain value at which to interpolate
+ * @return returns Double.NaN if either list is null or empty or different size, or if t is outsize the domain.
+ */
+ public static double interpolate( List<Double> domain, List<Double> range, double t ) {
+
+ if ( domain == null || range == null || domain.size() != range.size() ) {
+ return Double.NaN;
+ }
+
+ int length = domain.size();
+ if ( length <= 1 || t < domain.get(0) || t > domain.get( length-1 ) ) {
+ return Double.NaN;
+ }
+
+ // Look for the index of the right end point.
+ int right = 1;
+ while( t > domain.get(right) ) {
+ right ++;
+ }
+ int left = right -1;
+
+ // Points are:
+
+ double deltax = domain.get(right) - domain.get(left);
+ double deltay = range.get(right) - range.get(left);
+
+ // For numerical stability, if deltax is small,
+ if ( Math.abs(deltax) < EPSILON ) {
+ if ( deltay < -1.0 * EPSILON ) {
+ // return neg infinity if deltay is negative
+ return Double.NEGATIVE_INFINITY;
+ }
+ else if ( deltay > EPSILON ) {
+ // return infinity if deltay is large
+ return Double.POSITIVE_INFINITY;
+ } else {
+ // otherwise return 0
+ return 0.0d;
+ }
+ }
+
+ return range.get(left) + ( t - domain.get(left) ) * deltay / deltax;
+
+ }
+