package mikera.vectorz;

import mikera.arrayz.INDArray;
import mikera.matrixx.AMatrix;
import mikera.transformz.ATransform;
import mikera.transformz.impl.AOpTransform;
import mikera.vectorz.impl.ADenseArrayVector;
import mikera.vectorz.ops.Composed;
import mikera.vectorz.ops.Derivative;
import mikera.vectorz.ops.Division;
import mikera.vectorz.ops.Inverse;
import mikera.vectorz.ops.Product;
import mikera.vectorz.ops.Sum;

/**
 * Abstract class for representing a unary operation
 * 
 * @author Mike
 */
public abstract class Op implements IOperator {
	
	@Override
	public abstract double apply(double x);
	
	/**
	 * Applies the inverse of this Op. Throws an error if the inverse function does not exist.
	 * Returns Double.NaN if no inverse exists for the specific value of y.
	 * 
	 * @param y
	 * @return
	 */
	public double applyInverse(double y) {
		throw new UnsupportedOperationException("Inverse not defined for operator: "+this.toString());
	}
	
	@Override
	public void applyTo(AVector v) {
		if (v instanceof ADenseArrayVector) {
			applyTo((ADenseArrayVector)v);
		} else {
			v.applyOp(this);
		}
	}
	
	/**
	 * Applies this operator to every element of a target matrix, mutating the matrix
	 */
	public void applyTo(AMatrix m) {
		m.applyOp(this);
	}
	
	@Override
	public void applyTo(AVector v, int offset, int length) {
		if (offset<0) throw new IllegalArgumentException("Negative start position: "+offset);
		if ((offset==0)&&(length==v.length())) {
			v.applyOp(this);
		} else {
			v.subVector(offset, length).applyOp(this);
		}
	}
	
	/**
	 * Applies this operator to a scalar, mutating the scalar
	 * @param s
	 */
	public void applyTo(AScalar s) {
		s.set(apply(s.get()));
	}
	
	/**
	 * Applies this operator to a dense array vector, mutating the vector
	 * @param s
	 */
	public void applyTo(ADenseArrayVector v) {
		applyTo(v.getArray(), v.getArrayOffset(),v.length());
	}
	
	/**
	 * Applies this operator to every element of a target array. Mutates the array in place.
	 * @param a
	 */
	public void applyTo(INDArray a) {
		if (a instanceof AVector) {
			applyTo((AVector)a);
		} else if (a instanceof AMatrix) {
			applyTo((AMatrix)a);
		} else if (a instanceof AScalar) {
			applyTo((AScalar)a);
		} else {
			a.applyOp(this);
		}
	}

	@Override
	public void applyTo(double[] data, int offset, int length) {
		for (int i=0; i=-Double.MAX_VALUE)||(maxDomain()<=Double.MAX_VALUE);
		
	}
	
	/**
	 * Validates whether all values in a double[] are within the possible output range for this Op
	 * @param output
	 * @return
	 */
	public boolean validateOutput(double[] output) {
		double min=minValue();
		double max=maxValue();
		for (double d: output) {
			if ((dmax)) return false;
		}
		return true;
	}
	
	/**
	 * Creates a copy of the values of src in dest, constraining them to be within the valid
	 * range of output values from this Op
	 * @param src
	 * @param dest
	 * @param offset
	 * @param length
	 */
	public void constrainValues(double[] src, double[] dest, int offset, int length) {
		if (!isBounded()) {
			System.arraycopy(src, 0, dest, offset, length);
		}
		double min=minValue();
		double max=maxValue();
		
		for (int i=offset; i<(offset+length); i++) {
			double v=src[i];
			if (v>max) {
				dest[i]=max;
			} else if (v=-Double.MAX_VALUE)||(maxValue()<=Double.MAX_VALUE);
	}
	
	/**
	 * Gets an operator which represents the derivative of this operator.
	 * 
	 * Returns nil if this cannot be computed or does not exist.
	 * @return
	 */
	public Op getDerivativeOp() {
		if (!hasDerivative()) {
			return null;
		}
		return new Derivative(this);
	}
	
	public static Op compose(Op op1, Op op2) {
		return Ops.compose(op1,op2);
	}
 
	public Op compose(Op op) {
		return Composed.create(this, op);
	}
	
	public Op product(Op op) {
		return Product.create(this, op);
	}
	
	public Op divide(Op op) {
		return Division.create(this, op);
	}
	
	public Op sum(Op op) {
		return Sum.create(this, op);
	}
	
	@Override public String toString() {
		return getClass().toString();
	}
}

 

Ads help maintain this website.