Author: luc Date: Mon Mar 30 15:43:14 2009 New Revision: 760014 URL: http://svn.apache.org/viewvc?rev=760014&view=rev Log: Added some utility functions to compute powers with integral types (int, long, BigInteger)
Modified: commons/proper/math/trunk/src/java/org/apache/commons/math/MessagesResources_fr.java commons/proper/math/trunk/src/java/org/apache/commons/math/util/MathUtils.java commons/proper/math/trunk/src/site/xdoc/changes.xml commons/proper/math/trunk/src/test/org/apache/commons/math/util/MathUtilsTest.java Modified: commons/proper/math/trunk/src/java/org/apache/commons/math/MessagesResources_fr.java URL: http://svn.apache.org/viewvc/commons/proper/math/trunk/src/java/org/apache/commons/math/MessagesResources_fr.java?rev=760014&r1=760013&r2=760014&view=diff ============================================================================== --- commons/proper/math/trunk/src/java/org/apache/commons/math/MessagesResources_fr.java (original) +++ commons/proper/math/trunk/src/java/org/apache/commons/math/MessagesResources_fr.java Mon Mar 30 15:43:14 2009 @@ -47,6 +47,8 @@ // 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}", Modified: commons/proper/math/trunk/src/java/org/apache/commons/math/util/MathUtils.java URL: http://svn.apache.org/viewvc/commons/proper/math/trunk/src/java/org/apache/commons/math/util/MathUtils.java?rev=760014&r1=760013&r2=760014&view=diff ============================================================================== --- commons/proper/math/trunk/src/java/org/apache/commons/math/util/MathUtils.java (original) +++ commons/proper/math/trunk/src/java/org/apache/commons/math/util/MathUtils.java Mon Mar 30 15:43:14 2009 @@ -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 @@ 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; + + } + } Modified: commons/proper/math/trunk/src/site/xdoc/changes.xml URL: http://svn.apache.org/viewvc/commons/proper/math/trunk/src/site/xdoc/changes.xml?rev=760014&r1=760013&r2=760014&view=diff ============================================================================== --- commons/proper/math/trunk/src/site/xdoc/changes.xml (original) +++ commons/proper/math/trunk/src/site/xdoc/changes.xml Mon Mar 30 15:43:14 2009 @@ -39,6 +39,9 @@ </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. Modified: commons/proper/math/trunk/src/test/org/apache/commons/math/util/MathUtilsTest.java URL: http://svn.apache.org/viewvc/commons/proper/math/trunk/src/test/org/apache/commons/math/util/MathUtilsTest.java?rev=760014&r1=760013&r2=760014&view=diff ============================================================================== --- commons/proper/math/trunk/src/test/org/apache/commons/math/util/MathUtilsTest.java (original) +++ commons/proper/math/trunk/src/test/org/apache/commons/math/util/MathUtilsTest.java Mon Mar 30 15:43:14 2009 @@ -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 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))); + + } } \ No newline at end of file