Added some utility functions to compute powers with integral types (int, long, BigInteger)

git-svn-id: https://svn.apache.org/repos/asf/commons/proper/math/trunk@760014 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Luc Maisonobe 2009-03-30 15:43:14 +00:00
parent e143317c7d
commit 40223343f0
4 changed files with 283 additions and 0 deletions

View File

@ -47,6 +47,8 @@ public class MessagesResources_fr
// org.apache.commons.math.util.MathUtils
{ "overflow: gcd({0}, {1}) is 2^31",
"d\u00e9passement de capacit\u00e9 : le PGCD de {0} et {1} vaut 2^31" },
{ "cannot raise an integral value to a negative power ({0}^{1})",
"impossible d''\u00e9lever une valeur enti\u00e8re \u00e0 une puissance n\u00e9gative ({0}^{1})" },
// org.apache.commons.math.FunctionEvaluationException
{ "evaluation failed for argument = {0}",

View File

@ -18,6 +18,7 @@
package org.apache.commons.math.util;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.Arrays;
import org.apache.commons.math.MathRuntimeException;
@ -1246,4 +1247,204 @@ public final class MathUtils {
return ret;
}
/**
* Raise an int to an int power.
* @param k number to raise
* @param e exponent (must be positive or null)
* @return k<sup>e</sup>
* @exception IllegalArgumentException if e is negative
*/
public static int pow(final int k, int e)
throws IllegalArgumentException {
if (e < 0) {
throw MathRuntimeException.createIllegalArgumentException(
"cannot raise an integral value to a negative power ({0}^{1})",
k, e);
}
int result = 1;
int k2p = k;
while (e != 0) {
if ((e & 0x1) != 0) {
result *= k2p;
}
k2p *= k2p;
e = e >> 1;
}
return result;
}
/**
* Raise an int to a long power.
* @param k number to raise
* @param e exponent (must be positive or null)
* @return k<sup>e</sup>
* @exception IllegalArgumentException if e is negative
*/
public static int pow(final int k, long e)
throws IllegalArgumentException {
if (e < 0) {
throw MathRuntimeException.createIllegalArgumentException(
"cannot raise an integral value to a negative power ({0}^{1})",
k, e);
}
int result = 1;
int k2p = k;
while (e != 0) {
if ((e & 0x1) != 0) {
result *= k2p;
}
k2p *= k2p;
e = e >> 1;
}
return result;
}
/**
* Raise a long to an int power.
* @param k number to raise
* @param e exponent (must be positive or null)
* @return k<sup>e</sup>
* @exception IllegalArgumentException if e is negative
*/
public static long pow(final long k, int e)
throws IllegalArgumentException {
if (e < 0) {
throw MathRuntimeException.createIllegalArgumentException(
"cannot raise an integral value to a negative power ({0}^{1})",
k, e);
}
long result = 1l;
long k2p = k;
while (e != 0) {
if ((e & 0x1) != 0) {
result *= k2p;
}
k2p *= k2p;
e = e >> 1;
}
return result;
}
/**
* Raise a long to a long power.
* @param k number to raise
* @param e exponent (must be positive or null)
* @return k<sup>e</sup>
* @exception IllegalArgumentException if e is negative
*/
public static long pow(final long k, long e)
throws IllegalArgumentException {
if (e < 0) {
throw MathRuntimeException.createIllegalArgumentException(
"cannot raise an integral value to a negative power ({0}^{1})",
k, e);
}
long result = 1l;
long k2p = k;
while (e != 0) {
if ((e & 0x1) != 0) {
result *= k2p;
}
k2p *= k2p;
e = e >> 1;
}
return result;
}
/**
* Raise a BigInteger to an int power.
* @param k number to raise
* @param e exponent (must be positive or null)
* @return k<sup>e</sup>
* @exception IllegalArgumentException if e is negative
*/
public static BigInteger pow(final BigInteger k, int e)
throws IllegalArgumentException {
if (e < 0) {
throw MathRuntimeException.createIllegalArgumentException(
"cannot raise an integral value to a negative power ({0}^{1})",
k, e);
}
return k.pow(e);
}
/**
* Raise a BigInteger to a long power.
* @param k number to raise
* @param e exponent (must be positive or null)
* @return k<sup>e</sup>
* @exception IllegalArgumentException if e is negative
*/
public static BigInteger pow(final BigInteger k, long e)
throws IllegalArgumentException {
if (e < 0) {
throw MathRuntimeException.createIllegalArgumentException(
"cannot raise an integral value to a negative power ({0}^{1})",
k, e);
}
BigInteger result = BigInteger.ONE;
BigInteger k2p = k;
while (e != 0) {
if ((e & 0x1) != 0) {
result = result.multiply(k2p);
}
k2p = k2p.multiply(k2p);
e = e >> 1;
}
return result;
}
/**
* Raise a BigInteger to a BigInteger power.
* @param k number to raise
* @param e exponent (must be positive or null)
* @return k<sup>e</sup>
* @exception IllegalArgumentException if e is negative
*/
public static BigInteger pow(final BigInteger k, BigInteger e)
throws IllegalArgumentException {
if (e.compareTo(BigInteger.ZERO) < 0) {
throw MathRuntimeException.createIllegalArgumentException(
"cannot raise an integral value to a negative power ({0}^{1})",
k, e);
}
BigInteger result = BigInteger.ONE;
BigInteger k2p = k;
while (!BigInteger.ZERO.equals(e)) {
if (e.testBit(0)) {
result = result.multiply(k2p);
}
k2p = k2p.multiply(k2p);
e = e.shiftRight(1);
}
return result;
}
}

View File

@ -39,6 +39,9 @@ The <action> type attribute can be add,update,fix,remove.
</properties>
<body>
<release version="2.0" date="TBD" description="TBD">
<action dev="luc" type="add">
Added some utility functions to compute powers with integral types (int, long, BigInteger).
</action>
<action dev="luc" type="fix" issue="MATH-252">
Fixed a comparison error when two different fractions evaluate to the
same double due to limited precision.

View File

@ -14,6 +14,7 @@
package org.apache.commons.math.util;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
@ -1077,4 +1078,80 @@ public final class MathUtilsTest extends TestCase {
}
}
public void testPow() {
assertEquals(1801088541, MathUtils.pow(21, 7));
assertEquals(1, MathUtils.pow(21, 0));
try {
MathUtils.pow(21, -7);
fail("Expecting IllegalArgumentException");
} catch (IllegalArgumentException e) {
// expected behavior
}
assertEquals(1801088541, MathUtils.pow(21, 7l));
assertEquals(1, MathUtils.pow(21, 0l));
try {
MathUtils.pow(21, -7l);
fail("Expecting IllegalArgumentException");
} catch (IllegalArgumentException e) {
// expected behavior
}
assertEquals(1801088541l, MathUtils.pow(21l, 7));
assertEquals(1l, MathUtils.pow(21l, 0));
try {
MathUtils.pow(21l, -7);
fail("Expecting IllegalArgumentException");
} catch (IllegalArgumentException e) {
// expected behavior
}
assertEquals(1801088541l, MathUtils.pow(21l, 7l));
assertEquals(1l, MathUtils.pow(21l, 0l));
try {
MathUtils.pow(21l, -7l);
fail("Expecting IllegalArgumentException");
} catch (IllegalArgumentException e) {
// expected behavior
}
BigInteger twentyOne = BigInteger.valueOf(21l);
assertEquals(BigInteger.valueOf(1801088541l), MathUtils.pow(twentyOne, 7));
assertEquals(BigInteger.ONE, MathUtils.pow(twentyOne, 0));
try {
MathUtils.pow(twentyOne, -7);
fail("Expecting IllegalArgumentException");
} catch (IllegalArgumentException e) {
// expected behavior
}
assertEquals(BigInteger.valueOf(1801088541l), MathUtils.pow(twentyOne, 7l));
assertEquals(BigInteger.ONE, MathUtils.pow(twentyOne, 0l));
try {
MathUtils.pow(twentyOne, -7l);
fail("Expecting IllegalArgumentException");
} catch (IllegalArgumentException e) {
// expected behavior
}
assertEquals(BigInteger.valueOf(1801088541l), MathUtils.pow(twentyOne, BigInteger.valueOf(7l)));
assertEquals(BigInteger.ONE, MathUtils.pow(twentyOne, BigInteger.ZERO));
try {
MathUtils.pow(twentyOne, BigInteger.valueOf(-7l));
fail("Expecting IllegalArgumentException");
} catch (IllegalArgumentException e) {
// expected behavior
}
BigInteger bigOne =
new BigInteger("1543786922199448028351389769265814882661837148" +
"4763915343722775611762713982220306372888519211" +
"560905579993523402015636025177602059044911261");
assertEquals(bigOne, MathUtils.pow(twentyOne, 103));
assertEquals(bigOne, MathUtils.pow(twentyOne, 103l));
assertEquals(bigOne, MathUtils.pow(twentyOne, BigInteger.valueOf(103l)));
}
}