package mikera.vectorz.ops; import mikera.vectorz.Op; public class Composed extends Op { public final Op inner; public final Op outer; private Composed(Op outer, Op inner) { this.outer=outer; this.inner=inner; } public static Op compose(Op outer, Op inner) { if (inner instanceof Composed) { Composed ci=(Composed)inner; return outer.compose(ci.outer).compose(ci.inner); } return new Composed(outer,inner); } public static Op create(Op a, Op b) { return compose(a,b); } @Override public double apply(double x) { return outer.apply(inner.apply(x)); } @Override public void applyTo(double[] data, int start,int length) { inner.applyTo(data, start, length); outer.applyTo(data, start, length); } @Override public boolean isBounded() { return outer.isBounded(); } @Override public double minValue() { return outer.minValue(); } @Override public boolean hasDerivative() { return (outer.hasDerivative())&&(inner.hasDerivative()); } @Override public boolean hasDerivativeForOutput() { return outer.hasInverse()&&(outer.hasDerivativeForOutput())&&(inner.hasDerivativeForOutput()); } @Override public double derivativeForOutput(double y) { return outer.derivativeForOutput(y)*inner.derivativeForOutput(outer.applyInverse(y)); } @Override public double derivative(double x) { double y=inner.apply(x); return outer.derivative(y)*inner.derivative(x); } @Override public Op getDerivativeOp() { return (outer.getDerivativeOp().compose(inner)).product(inner.getDerivativeOp()); } @Override public double maxValue() { return outer.maxValue(); } @Override public boolean hasInverse() { return (outer.hasInverse())&&(inner.hasInverse()); } public boolean isStochastic() { return (outer.isStochastic())||(inner.isStochastic()); } @Override public Op getInverse() { return inner.getInverse().compose(outer.getInverse()); } @Override public double averageValue() { return outer.averageValue(); } @Override public String toString() { return "Composed("+outer+","+inner+")"; } }