package mikera.vectorz.ops; import mikera.vectorz.AVector; import mikera.vectorz.Op; import mikera.vectorz.impl.ADenseArrayVector; public final class Quadratic extends APolynomialOp { private final double a; private final double b; private final double c; private Quadratic(double a,double b, double c) { this.a=a; this.b=b; this.c=c; } public static Op create(double a,double b, double c) { if (a==0.0) { return Linear.create(b,c); } if ((a==1.0)&&(b==0.0)&&(c==0.0)) { return Square.INSTANCE; } return new Quadratic(a,b,c); } @Override public final double apply(double x) { return (a*x*x)+(b*x)+c; } @Override public double applyInverse(double y) { throw new UnsupportedOperationException(); } @Override public void applyTo(AVector v) { if (v instanceof ADenseArrayVector) { ADenseArrayVector av=(ADenseArrayVector)v; applyTo(av.getArray(),av.getArrayOffset(),av.length()); return; } int len=v.length(); for (int i=0; i<len; i++) { double x=v.unsafeGet(i); v.unsafeSet(i,apply(x)); } } @Override public void applyTo(double[] data) { for (int i=0; i<data.length; i++) { double x=data[i]; data[i]=apply(x); } } @Override public void applyTo(double[] data, int start,int length) { for (int i=0; i<length; i++) { double x=data[i+start]; data[i+start]=apply(x); } } @Override public double averageValue() { return apply(-2.0*b/a)+a; } @Override public boolean hasDerivative() { return true; } @Override public double derivative(double x) { return 2.0*a*x+b; } @Override public double derivativeForOutput(double y) { return b; } @Override public Op getDerivativeOp() { return Linear.create(2*a,b); } @Override public boolean hasInverse() { return false; } public Op compose(ALinearOp op) { double f=op.getFactor(); double g=op.getConstant(); return Quadratic.create(a*f*f,(2*a*f*g+f*b),a*g*g+b*g+c); } @Override public Op compose(Op op) { if (op instanceof ALinearOp) { return compose((ALinearOp) op); } return super.compose(op); } }