// Path: src/vash/ImageParameters.java
// public class ImageParameters {
// 	final private int w;
// 	final private int h;
// 	final private float[] X;
// 	final private float[] Y;
// 	private final LinkedList<Plane> cache;
// 	private long _puts = 0;
// 	private long _gets = 0;
// 	private final static long MAX_CACHE_SIZE = 64 * 1024 * 1024;
// 	private final static boolean DEBUG = false;
// 	
// 	/**
// 	 * Initialize a new set of image parameters for the given width and height.
// 	 */
// 	public ImageParameters(int w, int h) {
// 		this.w = w;
// 		this.h = h;
// 		this.cache = new LinkedList<Plane>();
// 		this.X = new float[w];
// 		this.Y = new float[h];
// 		
// 		int i, j;
// 		float gX, gY;
// 		float delta_x = 2.0f / w;
// 		float delta_y = 2.0f / h;
// 		for(j = 0, gY = 1.0f - (delta_y / 2.0f); j < h; j++, gY -= delta_y)
// 			Y[j] = gY;
// 		for(i = 0, gX = -1.0f + (delta_x / 2.0f); i < w; i++, gX += delta_x)
// 			X[i] = gX;
// 	}
// 
// 	public int getW() {
// 		return w;
// 	}
// 	
// 	public int getH() {
// 		return h;
// 	}
// 
// 	
// 	/**
// 	 * Returns an array of width length filled such that each index offset is 
// 	 * the logical X value for that index.  We use this as a faster way to map 
// 	 * [0,width) offsets into the [-1.0, 1.0] logical range used by our 
// 	 * computations.
// 	 */
// 	public float[] getXValues() {
// 		return X;
// 	}
// 	
// 	
// 	/**
// 	 * Returns an array of height length filled such that each index offset is 
// 	 * the logical Y value for that index.  We use this as a faster way to map 
// 	 * [0,height) offsets into the [1.0, -1.0] logical range used by our 
// 	 * computations.
// 	 */
// 	public float[] getYValues() {
// 		return Y;
// 	}
// 	
// 	
// 	/**
// 	 * Returns a new, or cached, plane of values.  The plane values will not be
// 	 * initialized to any specific value.
// 	 */
// 	public Plane getPlane() {
// 		_gets += 1;
// 		if(DEBUG) {
// 			long tmp = ((_gets - _puts) + cache.size()) * (w * h * 4);
// 			System.out.format("GetPlane: %d gets, %d puts, %d out, %d cached: %d%n", 
// 					_gets, _puts, _gets - _puts, cache.size(), tmp);
// 		}
// 		if(cache.size() > 0) {
// 			return cache.removeFirst();
// 		}
// 		return new Plane(this.w, this.h);
// 	}
// 
// 	/**
// 	 * Give back a plane taken with getPlane.  This allows us to re-use planes,
// 	 * rather than re-allocating new, massive arrays constantly.
// 	 */
// 	public void putPlane(Plane p) {
// 		_puts += 1;
// 		long outstanding = ((_gets - _puts) + cache.size()) * (w * h * 4);
// 		if(outstanding < MAX_CACHE_SIZE) {
// 			cache.addFirst(p);
// 		}
// 	}
// 	
// 	/**
// 	 * Returns a new plane of values who's coordinates are mirrored around 
// 	 * y=x.  This is useful in some nodes that use slope, in order to avoid 
// 	 * singularities around vertical lines.
// 	 * @return a one-off plane; must be returned with putYXPlane
// 	 */
// 	public Plane getYXPlane() {
// 		return new Plane(this.h, this.w);
// 	}
// 
// 	/**
// 	 * Give back a plane taken with getYXPlane.
// 	 * @param p the plane allocated with getYXPlane
// 	 */
// 	public void putYXPlane(Plane p) {
// 	}
// }


import java.io.IOException;
import java.io.OutputStream;
import java.util.ArrayList;
import vash.ImageParameters;
import vash.Plane;
import vash.value.Value;
	 * A utility function used by many nodes when computing values.
	 */
	protected static float clampf(float in, float lower, float upper) {
		return Math.min(Math.max(in, lower), upper);
	}

	/**
	 * A utility function used by many nodes when computing values.
	 * @param x0
	 * @param y0
	 * @param x1
	 * @param y1
	 * @return
	 */
	protected static float distance(float x0, float y0, float x1, float y1) {
		float xp = x1 - x0;
		float yp = y1 - y0;
		return (float)Math.sqrt(xp * xp + yp * yp);
	}

	/**
	 * Create and return a completely independent copy of this node.
	 */
	@Override
	abstract public OperationNode clone();

	/**
	 * The main computation routine.
	 * @param ip
	 */
// Path: src/vash/ImageParameters.java
// public class ImageParameters {
// 	final private int w;
// 	final private int h;
// 	final private float[] X;
// 	final private float[] Y;
// 	private final LinkedList<Plane> cache;
// 	private long _puts = 0;
// 	private long _gets = 0;
// 	private final static long MAX_CACHE_SIZE = 64 * 1024 * 1024;
// 	private final static boolean DEBUG = false;
// 	
// 	/**
// 	 * Initialize a new set of image parameters for the given width and height.
// 	 */
// 	public ImageParameters(int w, int h) {
// 		this.w = w;
// 		this.h = h;
// 		this.cache = new LinkedList<Plane>();
// 		this.X = new float[w];
// 		this.Y = new float[h];
// 		
// 		int i, j;
// 		float gX, gY;
// 		float delta_x = 2.0f / w;
// 		float delta_y = 2.0f / h;
// 		for(j = 0, gY = 1.0f - (delta_y / 2.0f); j < h; j++, gY -= delta_y)
// 			Y[j] = gY;
// 		for(i = 0, gX = -1.0f + (delta_x / 2.0f); i < w; i++, gX += delta_x)
// 			X[i] = gX;
// 	}
// 
// 	public int getW() {
// 		return w;
// 	}
// 	
// 	public int getH() {
// 		return h;
// 	}
// 
// 	
// 	/**
// 	 * Returns an array of width length filled such that each index offset is 
// 	 * the logical X value for that index.  We use this as a faster way to map 
// 	 * [0,width) offsets into the [-1.0, 1.0] logical range used by our 
// 	 * computations.
// 	 */
// 	public float[] getXValues() {
// 		return X;
// 	}
// 	
// 	
// 	/**
// 	 * Returns an array of height length filled such that each index offset is 
// 	 * the logical Y value for that index.  We use this as a faster way to map 
// 	 * [0,height) offsets into the [1.0, -1.0] logical range used by our 
// 	 * computations.
// 	 */
// 	public float[] getYValues() {
// 		return Y;
// 	}
// 	
// 	
// 	/**
// 	 * Returns a new, or cached, plane of values.  The plane values will not be
// 	 * initialized to any specific value.
// 	 */
// 	public Plane getPlane() {
// 		_gets += 1;
// 		if(DEBUG) {
// 			long tmp = ((_gets - _puts) + cache.size()) * (w * h * 4);
// 			System.out.format("GetPlane: %d gets, %d puts, %d out, %d cached: %d%n", 
// 					_gets, _puts, _gets - _puts, cache.size(), tmp);
// 		}
// 		if(cache.size() > 0) {
// 			return cache.removeFirst();
// 		}
// 		return new Plane(this.w, this.h);
// 	}
// 
// 	/**
// 	 * Give back a plane taken with getPlane.  This allows us to re-use planes,
// 	 * rather than re-allocating new, massive arrays constantly.
// 	 */
// 	public void putPlane(Plane p) {
// 		_puts += 1;
// 		long outstanding = ((_gets - _puts) + cache.size()) * (w * h * 4);
// 		if(outstanding < MAX_CACHE_SIZE) {
// 			cache.addFirst(p);
// 		}
// 	}
// 	
// 	/**
// 	 * Returns a new plane of values who's coordinates are mirrored around 
// 	 * y=x.  This is useful in some nodes that use slope, in order to avoid 
// 	 * singularities around vertical lines.
// 	 * @return a one-off plane; must be returned with putYXPlane
// 	 */
// 	public Plane getYXPlane() {
// 		return new Plane(this.h, this.w);
// 	}
// 
// 	/**
// 	 * Give back a plane taken with getYXPlane.
// 	 * @param p the plane allocated with getYXPlane
// 	 */
// 	public void putYXPlane(Plane p) {
// 	}
// }


// Path: src/vash/operation/OperationNode.java
import java.io.IOException;
import java.io.OutputStream;
import java.util.ArrayList;
import vash.ImageParameters;
import vash.Plane;
import vash.value.Value;

	 * A utility function used by many nodes when computing values.
	 */
	protected static float clampf(float in, float lower, float upper) {
		return Math.min(Math.max(in, lower), upper);
	}

	/**
	 * A utility function used by many nodes when computing values.
	 * @param x0
	 * @param y0
	 * @param x1
	 * @param y1
	 * @return
	 */
	protected static float distance(float x0, float y0, float x1, float y1) {
		float xp = x1 - x0;
		float yp = y1 - y0;
		return (float)Math.sqrt(xp * xp + yp * yp);
	}

	/**
	 * Create and return a completely independent copy of this node.
	 */
	@Override
	abstract public OperationNode clone();

	/**
	 * The main computation routine.
	 * @param ip
	 */
	abstract public Plane compute(ImageParameters ip);