Package ca.nengo.math.impl

Source Code of ca.nengo.math.impl.InterpolatedFunction

package ca.nengo.math.impl;

import java.util.Arrays;

import ca.nengo.config.ConfigUtil;
import ca.nengo.config.Configuration;
import ca.nengo.config.impl.ConfigurationImpl;
import ca.nengo.config.impl.SingleValuedPropertyImpl;
import ca.nengo.math.Function;

/**
* A 1-D Function based on interpolation between known points. 
*
* @author Bryan Tripp
*/
public class InterpolatedFunction extends AbstractFunction {

  private static final long serialVersionUID = 1L;
 
  private float[] myX;
  private float[] myY;

  /**
   * @param x Known function-argument points to interpolate between
   * @param y Known function-output points to interpolate between (must be same length as x)
   */
  public InterpolatedFunction(float[] x, float[] y) {
    super(1);
    myX = x;
    myY = y;
   
    if (x.length != y.length) {
      throw new IllegalArgumentException("Arrays x and y must have the same length; y = f(x)");
    }         
    if (x.length < 2) {
      throw new IllegalArgumentException("At least two points are needed");
    }
  }
 
  /**
   * @return Custom configuration
   */
  public Configuration getConfiguration() {
    ConfigurationImpl result = ConfigUtil.defaultConfiguration(this);
    result.defineProperty(SingleValuedPropertyImpl.getSingleValuedProperty(result, "numPoints", Integer.TYPE));
    return result;
  }

  /**
   * @return Number of points between which this function interpolates
   */
  public int getNumPoints() {
    return myX.length;
  }
 
  /**
   * If this method is used to increase the number of interpolation points, new points
   * are set to equal what was previously the last point.
   *  
   * @param num New number of points between which this function interpolates
   */
  public void setNumPoints(int num) {
    if (num < 2) {
      throw new IllegalArgumentException("At least two points are needed");
    }
   
    float[] newX = new float[num];
    float[] newY = new float[num];
    System.arraycopy(myX, 0, newX, 0, Math.min(num, myX.length));
    System.arraycopy(myY, 0, newY, 0, Math.min(num, myY.length));
   
    for (int i = myX.length; i < newX.length; i++) {
      newX[i] = myX[myX.length-1];
      newY[i] = myY[myY.length-1];
    }
   
    myX = newX;
    myY = newY;
  }
 
  /**
   * @return Known function-argument points to interpolate between
   */
  public float[] getX() {
    return copy(myX);
  }

  /**
   * @param x Known function-argument points to interpolate between
   */
  public void setX(float[] x) {
    if (x.length != myX.length) {
      throw new IllegalArgumentException("Expected " + myX.length + " values.");
    }
    myX = copy(x);
  }

  /**
   * @return Known function-output points to interpolate between
   */
  public float[] getY() {
    return copy(myY);
  }
 
  /**
   * @param y Known function-output points to interpolate between
   */
  public void setY(float[] y) {
    if (y.length != myY.length) {
      throw new IllegalArgumentException("Expected " + myY.length + " values.");
    }
    myY = copy(y);
  }
 
  private static float[] copy(float[] vector) {
    float[] result = new float[vector.length];
    System.arraycopy(vector, 0, result, 0, vector.length);
    return result;
  }

  /**
   * @see ca.nengo.math.impl.AbstractFunction#map(float[])
   */
  public float map(float[] from) {
    return interpolate(myX, myY, from[0]);
//      float x = from[0];
//     
//      //find index of lowest myX that is >= x
//      int index = Arrays.binarySearch(myX, x);
//      if (index < 0) index = - index - 1;    
//     
//      //use last interval on each end for extrapolation
//      if (index == 0) index = 1;
//      if (index == myX.length) index = index - 1;
//     
//      float dx = x - myX[index-1];
//      return myY[index-1] + (myY[index] - myY[index-1]) * dx / (myX[index] - myX[index-1]);
  }
 
  /**
   * @param xs List of x values
   * @param ys List of y values that x values map onto
   * @param x An x value at which to interpolate this mapping
   * @return The interpolated y value
   */
  public static float interpolate(float[] xs, float[] ys, float x) {
    //find index of lowest xs that is >= x
    int index = Arrays.binarySearch(xs, x);
    if (index < 0) index = - index - 1;    
   
    //use last interval on each end for extrapolation
    if (index == 0) index = 1;
    if (index == xs.length) index = index - 1;
   
    float dx = x - xs[index-1];
    return ys[index-1] + (ys[index] - ys[index-1]) * dx / (xs[index] - xs[index-1]);      
  }

  @Override
  public Function clone() throws CloneNotSupportedException {
    return new InterpolatedFunction(myX.clone(), myY.clone());
  }
 
}
TOP

Related Classes of ca.nengo.math.impl.InterpolatedFunction

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.