in commons-math-legacy-core/src/main/java/org/apache/commons/math4/legacy/core/dfp/DfpMath.java [500:657]
public static Dfp pow(Dfp x, final Dfp y) {
// make sure we don't mix number with different precision
if (x.getField().getRadixDigits() != y.getField().getRadixDigits()) {
x.getField().setIEEEFlagsBits(DfpField.FLAG_INVALID);
final Dfp result = x.newInstance(x.getZero());
result.nans = Dfp.QNAN;
return x.dotrap(DfpField.FLAG_INVALID, POW_TRAP, x, result);
}
final Dfp zero = x.getZero();
final Dfp one = x.getOne();
final Dfp two = x.getTwo();
boolean invert = false;
int ui;
/* Check for special cases */
if (y.equals(zero)) {
return x.newInstance(one);
}
if (y.equals(one)) {
if (x.isNaN()) {
// Test for NaNs
x.getField().setIEEEFlagsBits(DfpField.FLAG_INVALID);
return x.dotrap(DfpField.FLAG_INVALID, POW_TRAP, x, x);
}
return x;
}
if (x.isNaN() || y.isNaN()) {
// Test for NaNs
x.getField().setIEEEFlagsBits(DfpField.FLAG_INVALID);
return x.dotrap(DfpField.FLAG_INVALID, POW_TRAP, x, x.newInstance((byte)1, Dfp.QNAN));
}
// X == 0
if (x.equals(zero)) {
if (Dfp.copySign(one, x).greaterThan(zero)) {
// X == +0
if (y.greaterThan(zero)) {
return x.newInstance(zero);
} else {
return x.newInstance(x.newInstance((byte)1, Dfp.INFINITE));
}
} else {
// X == -0
if (y.classify() == Dfp.FINITE && y.rint().equals(y) && !y.remainder(two).equals(zero)) {
// If y is odd integer
if (y.greaterThan(zero)) {
return x.newInstance(zero.negate());
} else {
return x.newInstance(x.newInstance((byte)-1, Dfp.INFINITE));
}
} else {
// Y is not odd integer
if (y.greaterThan(zero)) {
return x.newInstance(zero);
} else {
return x.newInstance(x.newInstance((byte)1, Dfp.INFINITE));
}
}
}
}
if (x.lessThan(zero)) {
// Make x positive, but keep track of it
x = x.negate();
invert = true;
}
if (x.greaterThan(one) && y.classify() == Dfp.INFINITE) {
if (y.greaterThan(zero)) {
return y;
} else {
return x.newInstance(zero);
}
}
if (x.lessThan(one) && y.classify() == Dfp.INFINITE) {
if (y.greaterThan(zero)) {
return x.newInstance(zero);
} else {
return x.newInstance(Dfp.copySign(y, one));
}
}
if (x.equals(one) && y.classify() == Dfp.INFINITE) {
x.getField().setIEEEFlagsBits(DfpField.FLAG_INVALID);
return x.dotrap(DfpField.FLAG_INVALID, POW_TRAP, x, x.newInstance((byte)1, Dfp.QNAN));
}
if (x.classify() == Dfp.INFINITE) {
// x = +/- inf
if (invert) {
// negative infinity
if (y.classify() == Dfp.FINITE && y.rint().equals(y) && !y.remainder(two).equals(zero)) {
// If y is odd integer
if (y.greaterThan(zero)) {
return x.newInstance(x.newInstance((byte)-1, Dfp.INFINITE));
} else {
return x.newInstance(zero.negate());
}
} else {
// Y is not odd integer
if (y.greaterThan(zero)) {
return x.newInstance(x.newInstance((byte)1, Dfp.INFINITE));
} else {
return x.newInstance(zero);
}
}
} else {
// positive infinity
if (y.greaterThan(zero)) {
return x;
} else {
return x.newInstance(zero);
}
}
}
if (invert && !y.rint().equals(y)) {
x.getField().setIEEEFlagsBits(DfpField.FLAG_INVALID);
return x.dotrap(DfpField.FLAG_INVALID, POW_TRAP, x, x.newInstance((byte)1, Dfp.QNAN));
}
// End special cases
Dfp r;
if (y.lessThan(x.newInstance(100000000)) && y.greaterThan(x.newInstance(-100000000))) {
final Dfp u = y.rint();
ui = u.intValue();
final Dfp v = y.subtract(u);
if (v.unequal(zero)) {
final Dfp a = v.multiply(log(x));
final Dfp b = a.divide(x.getField().getLn2()).rint();
final Dfp c = a.subtract(b.multiply(x.getField().getLn2()));
r = splitPow(split(x), ui);
r = r.multiply(pow(two, b.intValue()));
r = r.multiply(exp(c));
} else {
r = splitPow(split(x), ui);
}
} else {
// very large exponent. |y| > 1e8
r = exp(log(x).multiply(y));
}
if (invert && y.rint().equals(y) && !y.remainder(two).equals(zero)) {
// if y is odd integer
r = r.negate();
}
return x.newInstance(r);
}