/*  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */
package jdistlib.math.approx;

import jdistlib.math.UnivariateFunction;

/**
 * Create an approximation function. This is pretty much like R's
 * approxfun. I'm emulating it here. I don't deal with
 * NaN and Infinity. I don't do sanity check and no uniqueness
 * check here. So, watch out.
 * 
 * @author Roby Joehanes
 *
 */
public class ApproximationFunction implements UnivariateFunction
{
	protected double
		mX[],
		mY[],
		mLo,
		mHi,
		mCompromise;
	protected ApproximationType mType;

	public ApproximationFunction(ApproximationType t, double[] x, double[] y, double lo, double hi, double compromise)
	{
		assert (compromise >= 0 && compromise <= 1 && x.length == y.length &&
			(t == ApproximationType.CONSTANT || t == ApproximationType.LINEAR));
		mX = x;
		mY = y;
		mLo = lo;
		mHi = hi;
		mCompromise = compromise;
		mType = t;
	}

	/* (non-Javadoc)
	 * @see qmath.IFunction#eval(double)
	 */
	public double eval(double x) {
		switch (mType) {
			case CONSTANT:
				return constant(x, mX, mY, mLo, mHi, mCompromise);
			case LINEAR:
				return linear(x, mX, mY, mLo, mHi);
			default:
				throw new RuntimeException();
		}
	}

	public void setParameters(double... params) {
	}

	public void setObjects(Object... obj) {
	}

	/**
	 * Linear approximation
	 * @param v
	 * @param x
	 * @param y
	 * @param lo
	 * @param hi
	 * @return Approximated value
	 */
	public static final double linear(double v, double[] x, double[] y, double lo, double hi) {
		int
			left = 0,
			right = x.length - 1;
		if (v < x[left])
			return lo;
		if (v > x[right])
			return hi;
		while(left < right - 1) {
			int mid = (left + right)/2;
			if(v < x[mid]) right = mid; else left = mid;
		}
		if(v == x[right])
			return y[right];
		if(v == x[left])
			return y[left];
		return v = y[left] + (y[right] - y[left]) * ((v - x[left])/(x[right] - x[left]));
	}

	/**
	 * Constant approximation
	 * @param v
	 * @param x
	 * @param y
	 * @param lo
	 * @param hi
	 * @param compromise
	 * @return Approximated value
	 */
	public static final double constant(double v, double[] x, double[] y, double lo, double hi, double compromise) {
		int
			left = 0,
			right = x.length - 1;
		if (v < x[left])
			return lo;
		if (v > x[right])
			return hi;
		while(left < right - 1) {
			int mid = (left + right)/2;
			if(v < x[mid]) right = mid; else left = mid;
		}
		if(v == x[right])
			return y[right];
		if(v == x[left])
			return y[left];
		return y[left] * compromise + y[right] * (1-compromise);
	}
}

 

Ads help maintain this website.