package mikera.vectorz;
import mikera.util.Maths;
import mikera.vectorz.ops.AFunctionOp;
import mikera.vectorz.ops.ARoundingOp;
import mikera.vectorz.ops.Absolute;
import mikera.vectorz.ops.Clamp;
import mikera.vectorz.ops.Cosh;
import mikera.vectorz.ops.Exp;
import mikera.vectorz.ops.Identity;
import mikera.vectorz.ops.Linear;
import mikera.vectorz.ops.Log;
import mikera.vectorz.ops.LogN;
import mikera.vectorz.ops.Logistic;
import mikera.vectorz.ops.NormalRBF;
import mikera.vectorz.ops.Power;
import mikera.vectorz.ops.Reciprocal;
import mikera.vectorz.ops.ScaledLogistic;
import mikera.vectorz.ops.Signum;
import mikera.vectorz.ops.SoftPlus;
import mikera.vectorz.ops.Sqrt;
import mikera.vectorz.ops.Square;
import mikera.vectorz.ops.StochasticBinary;
import mikera.vectorz.ops.Tanh;
/**
* Static unary operator instances and constructor functions.
*
* @author Mike
*
*/
public final class Ops {
public static final Op ABS = Absolute.INSTANCE;
public static final Op SIGNUM = Signum.INSTANCE;
public static final Op STOCHASTIC_BINARY = StochasticBinary.INSTANCE;
public static final Op IDENTITY = Identity.INSTANCE;
public static final Op LINEAR = Identity.INSTANCE;
public static final Op LOGISTIC = Logistic.INSTANCE;
public static final Op SCALED_LOGISTIC = ScaledLogistic.INSTANCE;
public static final Op RECTIFIER = new Clamp(0.0, Double.MAX_VALUE);
public static final Op STOCHASTIC_LOGISTIC = Op.compose(STOCHASTIC_BINARY,
Logistic.INSTANCE);
public static final Op TANH = Tanh.INSTANCE;
public static final Op SOFTPLUS = SoftPlus.INSTANCE;
public static final Op NEGATE = Linear.create(-1.0, 0.0);
public static final Op SQUARE = Square.INSTANCE;
public static final Op SQRT = Sqrt.INSTANCE;
public static final Op CBRT = Power.create(1.0 / 3.0);
public static final Op RBF_NORMAL = NormalRBF.INSTANCE;
public static final Op TO_DEGREES = Linear.create(360.0 / Maths.TAU, 0.0);
public static final Op TO_RADIANS = Linear.create(Maths.TAU / 360.0, 0.0);
public static final Op EXP = Exp.INSTANCE;
public static final Op LOG = Log.INSTANCE;
public static final Op LOG10 = LogN.LOG10;
public static final Op RECIPROCAL = Reciprocal.INSTANCE;
public static final ARoundingOp CEIL = new ARoundingOp() {
@Override
public double apply(double x) {
return Math.ceil(x);
}
};
public static final ARoundingOp FLOOR = new ARoundingOp() {
@Override
public double apply(double x) {
return Math.floor(x);
}
};
public static final ARoundingOp RINT = new ARoundingOp() {
@Override
public double apply(double x) {
return Math.rint(x);
}
};
public static final AFunctionOp COSH = Cosh.INSTANCE;
public static final AFunctionOp SINH = new AFunctionOp() {
@Override
public double apply(double x) {
return Math.sinh(x);
}
};
public static final Op SIN = new AFunctionOp() {
@Override
public double apply(double x) {
return Math.sin(x);
}
@Override
public double derivative(double x) {
return Math.cos(x);
}
@Override
public double derivativeForOutput(double y) {
return Math.asin(y);
}
@Override
public boolean hasDerivative() {
return true;
}
@Override
public double minValue() {
return -1.0;
}
@Override
public double maxValue() {
return 1.0;
}
@Override
public Op getDerivativeOp() {
return COS;
}
};
public static final Op COS = new AFunctionOp() {
@Override
public double apply(double x) {
return Math.cos(x);
}
@Override
public double derivative(double x) {
return -Math.sin(x);
}
@Override
public double derivativeForOutput(double y) {
return Math.acos(y);
}
@Override
public boolean hasDerivative() {
return true;
}
@Override
public double minValue() {
return -1.0;
}
@Override
public double maxValue() {
return 1.0;
}
@Override
public Op getDerivativeOp() {
return Ops.negate(SIN);
}
};
public static final Op TAN = new AFunctionOp() {
@Override
public double apply(double x) {
return Math.tan(x);
}
@Override
public double derivative(double x) {
double sec = 1.0 / Math.cos(x);
return sec * sec;
}
@Override
public double derivativeForOutput(double y) {
return derivative(Math.atan(y));
}
};
public static final Op ACOS = new AFunctionOp() {
@Override
public double apply(double x) {
return Math.acos(x);
}
@Override
public double derivative(double x) {
return -1.0 / Math.sqrt(1.0 - x * x);
}
@Override
public double derivativeForOutput(double y) {
return derivative(Math.cos(y));
}
@Override
public boolean hasDerivative() {
return true;
}
@Override
public boolean hasInverse() {
return true;
}
@Override
public Op getInverse() {
return COS;
}
@Override
public double minValue() {
return -Math.PI;
}
@Override
public double maxValue() {
return Math.PI;
}
@Override
public double minDomain() {
return -1.0;
}
@Override
public double maxDomain() {
return 1.0;
}
};
public static final Op ASIN = new AFunctionOp() {
@Override
public double apply(double x) {
return Math.asin(x);
}
@Override
public double derivative(double x) {
return 1.0 / Math.sqrt(1.0 - x * x);
}
@Override
public double derivativeForOutput(double y) {
return derivative(Math.sin(y));
}
@Override
public boolean hasDerivative() {
return true;
}
@Override
public boolean hasInverse() {
return true;
}
@Override
public Op getInverse() {
return SIN;
}
@Override
public double minValue() {
return -Math.PI;
}
@Override
public double maxValue() {
return Math.PI;
}
@Override
public double minDomain() {
return -1.0;
}
@Override
public double maxDomain() {
return 1.0;
}
};
public static final Op ATAN = new AFunctionOp() {
@Override
public double apply(double x) {
return Math.atan(x);
}
@Override
public double derivative(double x) {
return 1.0 / (1.0 + x * x);
}
@Override
public double derivativeForOutput(double y) {
return derivative(Math.tan(y));
}
@Override
public boolean hasDerivative() {
return true;
}
@Override
public boolean hasInverse() {
return true;
}
@Override
public Op getInverse() {
return TAN;
}
@Override
public double minValue() {
return -Math.PI;
}
@Override
public double maxValue() {
return Math.PI;
}
};
public static Op negate(Op op) {
return NEGATE.compose(op);
}
public static final Op compose(Op a, Op b) {
return a.compose(b);
}
public static Op product(Op a, Op b) {
return a.product(b);
}
public static Op sum(Op a, Op b) {
return a.sum(b);
}
public static Op divide(Op a, Op b) {
return a.divide(b);
}
}