package mikera.vectorz.ops;
import mikera.arrayz.INDArray;
import mikera.matrixx.AMatrix;
import mikera.vectorz.AVector;
import mikera.vectorz.Op;
import mikera.vectorz.Ops;
import mikera.vectorz.util.DoubleArrays;
public final class Power extends Op {
private final double exponent;
private final Op inverse;
private Power(double d) {
exponent=d;
inverse=new Power(1.0/d,this);
}
private Power(double d, Op inv) {
exponent=d;
inverse=inv;
}
public static Op create(double exponent) {
if (exponent==-1) return Ops.RECIPROCAL;
if (exponent==0) return Constant.ONE;
if (exponent==1) return Identity.INSTANCE;
if (exponent==2) return Ops.SQUARE;
return new Power(exponent);
}
@Override
public double minDomain() {
if (exponent!=(long)exponent) return 0.0;
return super.minDomain();
}
@Override
public double apply(double x) {
return Math.pow(x, exponent);
}
@Override
public void applyTo(INDArray a) {
a.pow(exponent);
}
@Override
public void applyTo(AMatrix a) {
a.pow(exponent);
}
@Override
public void applyTo(AVector a) {
a.pow(exponent);
}
@Override
public void applyTo(double[] data, int start,int length) {
DoubleArrays.pow(data, start, length,exponent);
}
@Override
public double applyInverse(double x) {
return Math.pow(x, 1.0/exponent);
}
@Override
public boolean hasDerivative() {
return true;
}
@Override
public double derivative(double x) {
return exponent*Math.pow(x, exponent-1);
}
@Override
public double derivativeForOutput(double y) {
return y*Math.pow(y, 1.0/exponent)/exponent;
}
@Override
public Op getDerivativeOp() {
return Ops.product(Constant.create(exponent), Power.create(exponent-1.0));
}
@Override
public boolean hasInverse() {
return true;
}
@Override
public Op getInverse() {
return inverse;
}
@Override
public double averageValue() {
return 1;
}
public double getExponent() {
return exponent;
}
}