You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@commons.apache.org by er...@apache.org on 2013/10/29 13:01:12 UTC

svn commit: r1536683 - in /commons/proper/math/trunk/src: main/java/org/apache/commons/math3/exception/util/ main/java/org/apache/commons/math3/util/ main/resources/assets/org/apache/commons/math3/exception/util/ test/java/org/apache/commons/math3/exce...

Author: erans
Date: Tue Oct 29 12:01:12 2013
New Revision: 1536683

URL: http://svn.apache.org/r1536683
Log:
MATH-1047
Overflow checking in "ArithmeticUtils.pow(int,int)".
Added "LocalizedFormats.BASE" error pattern.

Modified:
    commons/proper/math/trunk/src/main/java/org/apache/commons/math3/exception/util/LocalizedFormats.java
    commons/proper/math/trunk/src/main/java/org/apache/commons/math3/util/ArithmeticUtils.java
    commons/proper/math/trunk/src/main/resources/assets/org/apache/commons/math3/exception/util/LocalizedFormats_fr.properties
    commons/proper/math/trunk/src/test/java/org/apache/commons/math3/exception/util/LocalizedFormatsTest.java
    commons/proper/math/trunk/src/test/java/org/apache/commons/math3/util/ArithmeticUtilsTest.java

Modified: commons/proper/math/trunk/src/main/java/org/apache/commons/math3/exception/util/LocalizedFormats.java
URL: http://svn.apache.org/viewvc/commons/proper/math/trunk/src/main/java/org/apache/commons/math3/exception/util/LocalizedFormats.java?rev=1536683&r1=1536682&r2=1536683&view=diff
==============================================================================
--- commons/proper/math/trunk/src/main/java/org/apache/commons/math3/exception/util/LocalizedFormats.java (original)
+++ commons/proper/math/trunk/src/main/java/org/apache/commons/math3/exception/util/LocalizedFormats.java Tue Oct 29 12:01:12 2013
@@ -205,6 +205,7 @@ public enum LocalizedFormats implements 
     NOT_POSITIVE_ELEMENT_AT_INDEX("element {0} is not positive: {1}"),
     NOT_POSITIVE_EXPONENT("invalid exponent {0} (must be positive)"),
     NUMBER_OF_ELEMENTS_SHOULD_BE_POSITIVE("number of elements should be positive ({0})"),
+    BASE("base ({0})"), /* keep */
     EXPONENT("exponent ({0})"), /* keep */
     NOT_POSITIVE_LENGTH("length must be positive ({0})"),
     LENGTH("length ({0})"), /* keep */

Modified: commons/proper/math/trunk/src/main/java/org/apache/commons/math3/util/ArithmeticUtils.java
URL: http://svn.apache.org/viewvc/commons/proper/math/trunk/src/main/java/org/apache/commons/math3/util/ArithmeticUtils.java?rev=1536683&r1=1536682&r2=1536683&view=diff
==============================================================================
--- commons/proper/math/trunk/src/main/java/org/apache/commons/math3/util/ArithmeticUtils.java (original)
+++ commons/proper/math/trunk/src/main/java/org/apache/commons/math3/util/ArithmeticUtils.java Tue Oct 29 12:01:12 2013
@@ -632,25 +632,45 @@ public final class ArithmeticUtils {
      *
      * @param k Number to raise.
      * @param e Exponent (must be positive or zero).
-     * @return k<sup>e</sup>
+     * @return \( k^e \)
      * @throws NotPositiveException if {@code e < 0}.
+     * @throws MathArithmeticException if the result would overflow.
      */
-    public static int pow(final int k, int e) throws NotPositiveException {
+    public static int pow(final int k,
+                          final int e)
+        throws NotPositiveException,
+               MathArithmeticException {
         if (e < 0) {
             throw new NotPositiveException(LocalizedFormats.EXPONENT, e);
         }
 
-        int result = 1;
-        int k2p    = k;
-        while (e != 0) {
-            if ((e & 0x1) != 0) {
-                result *= k2p;
+        try {
+            int exp = e;
+            int result = 1;
+            int k2p    = k;
+            while (true) {
+                if ((exp & 0x1) != 0) {
+                    result = mulAndCheck(result, k2p);
+                }
+
+                exp >>= 1;
+                if (exp == 0) {
+                    break;
+                }
+
+                k2p = mulAndCheck(k2p, k2p);
             }
-            k2p *= k2p;
-            e = e >> 1;
-        }
 
-        return result;
+            return result;
+        } catch (MathArithmeticException mae) {
+            // Add context information.
+            mae.getContext().addMessage(LocalizedFormats.OVERFLOW);
+            mae.getContext().addMessage(LocalizedFormats.BASE, k);
+            mae.getContext().addMessage(LocalizedFormats.EXPONENT, e);
+
+            // Rethrow.
+            throw mae;
+        }
     }
 
     /**

Modified: commons/proper/math/trunk/src/main/resources/assets/org/apache/commons/math3/exception/util/LocalizedFormats_fr.properties
URL: http://svn.apache.org/viewvc/commons/proper/math/trunk/src/main/resources/assets/org/apache/commons/math3/exception/util/LocalizedFormats_fr.properties?rev=1536683&r1=1536682&r2=1536683&view=diff
==============================================================================
--- commons/proper/math/trunk/src/main/resources/assets/org/apache/commons/math3/exception/util/LocalizedFormats_fr.properties (original)
+++ commons/proper/math/trunk/src/main/resources/assets/org/apache/commons/math3/exception/util/LocalizedFormats_fr.properties Tue Oct 29 12:01:12 2013
@@ -176,6 +176,7 @@ DEGREES_OF_FREEDOM = degr\u00e9s de libe
 NOT_POSITIVE_ELEMENT_AT_INDEX = l''\u00e9l\u00e9ment {0} n''est pas positif : {1}
 NOT_POSITIVE_EXPONENT = exposant {0} invalide (doit \u00eatre positif)
 NUMBER_OF_ELEMENTS_SHOULD_BE_POSITIVE = le nombre d''\u00e9l\u00e9ments devrait \u00eatre positif ({0})
+BASE = base ({0})
 EXPONENT = exposant ({0})
 NOT_POSITIVE_LENGTH = la longueur doit \u00eatre positive ({0})
 LENGTH = longueur ({0})

Modified: commons/proper/math/trunk/src/test/java/org/apache/commons/math3/exception/util/LocalizedFormatsTest.java
URL: http://svn.apache.org/viewvc/commons/proper/math/trunk/src/test/java/org/apache/commons/math3/exception/util/LocalizedFormatsTest.java?rev=1536683&r1=1536682&r2=1536683&view=diff
==============================================================================
--- commons/proper/math/trunk/src/test/java/org/apache/commons/math3/exception/util/LocalizedFormatsTest.java (original)
+++ commons/proper/math/trunk/src/test/java/org/apache/commons/math3/exception/util/LocalizedFormatsTest.java Tue Oct 29 12:01:12 2013
@@ -30,7 +30,7 @@ public class LocalizedFormatsTest {
 
     @Test
     public void testMessageNumber() {
-        Assert.assertEquals(314, LocalizedFormats.values().length);
+        Assert.assertEquals(315, LocalizedFormats.values().length);
     }
 
     @Test

Modified: commons/proper/math/trunk/src/test/java/org/apache/commons/math3/util/ArithmeticUtilsTest.java
URL: http://svn.apache.org/viewvc/commons/proper/math/trunk/src/test/java/org/apache/commons/math3/util/ArithmeticUtilsTest.java?rev=1536683&r1=1536682&r2=1536683&view=diff
==============================================================================
--- commons/proper/math/trunk/src/test/java/org/apache/commons/math3/util/ArithmeticUtilsTest.java (original)
+++ commons/proper/math/trunk/src/test/java/org/apache/commons/math3/util/ArithmeticUtilsTest.java Tue Oct 29 12:01:12 2013
@@ -460,6 +460,50 @@ public class ArithmeticUtilsTest {
 
     }
 
+    @Test(expected=MathArithmeticException.class)
+    public void testPowIntIntOverflow() {
+        final int base = 21;
+        final int exp = 8;
+        ArithmeticUtils.pow(base, exp);
+    }
+    @Test
+    public void testPowIntIntNoOverflow() {
+        final int base = 21;
+        final int exp = 7;
+        ArithmeticUtils.pow(base, exp);
+    }
+
+    @Test(expected=MathArithmeticException.class)
+    public void testPowNegativeIntIntOverflow() {
+        final int base = -21;
+        final int exp = 8;
+        ArithmeticUtils.pow(base, exp);
+    }
+    @Test
+    public void testPowNegativeIntIntNoOverflow() {
+        final int base = -21;
+        final int exp = 7;
+        ArithmeticUtils.pow(base, exp);
+    }
+
+    @Test
+    public void testPowMinusOneInt() {
+        final int base = -1;
+        for (int i = 0; i < 100; i++) {
+            final int pow = ArithmeticUtils.pow(base, i);
+            Assert.assertEquals("i: " + i, i % 2 == 0 ? 1 : -1, pow);
+        }
+    }
+
+    @Test
+    public void testPowOneInt() {
+        final int base = 1;
+        for (int i = 0; i < 100; i++) {
+            final int pow = ArithmeticUtils.pow(base, i);
+            Assert.assertEquals("i: " + i, 1, pow);
+        }
+    }
+
     @Test
     public void testIsPowerOfTwo() {
         final int n = 1025;