You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@commons.apache.org by lu...@apache.org on 2008/02/01 13:02:20 UTC

svn commit: r617482 - in /commons/proper/math/trunk: src/java/org/apache/commons/math/ src/java/org/apache/commons/math/fraction/ src/test/org/apache/commons/math/fraction/ xdocs/

Author: luc
Date: Fri Feb  1 04:02:12 2008
New Revision: 617482

URL: http://svn.apache.org/viewvc?rev=617482&view=rev
Log:
added checks for integer overflows during double to Fraction conversion
JIRA: MATH-182

Modified:
    commons/proper/math/trunk/src/java/org/apache/commons/math/MessagesResources_fr.java
    commons/proper/math/trunk/src/java/org/apache/commons/math/fraction/Fraction.java
    commons/proper/math/trunk/src/java/org/apache/commons/math/fraction/FractionConversionException.java
    commons/proper/math/trunk/src/test/org/apache/commons/math/fraction/FractionTest.java
    commons/proper/math/trunk/xdocs/changes.xml

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=617482&r1=617481&r2=617482&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 Fri Feb  1 04:02:12 2008
@@ -71,6 +71,8 @@
     // org.apache.commons.math.fraction.FractionConversionException
     { "Unable to convert {0} to fraction after {1} iterations",
       "Impossible de convertir {0} en fraction apr\u00e8s {1} it\u00e9rations" },
+    { "Overflow trying to convert {0} to fraction ({1}/{2})",
+      "D\u00e9passement de capacit\u00e9 lors de la conversion de {0} en fraction ({1}/{2})" },
 
     // org.apache.commons.math.analysis.UnivariateRealSolverUtils
     { "Number of iterations={0}, maximum iterations={1}, initial={2}, lower bound={3}, upper bound={4}," +

Modified: commons/proper/math/trunk/src/java/org/apache/commons/math/fraction/Fraction.java
URL: http://svn.apache.org/viewvc/commons/proper/math/trunk/src/java/org/apache/commons/math/fraction/Fraction.java?rev=617482&r1=617481&r2=617482&view=diff
==============================================================================
--- commons/proper/math/trunk/src/java/org/apache/commons/math/fraction/Fraction.java (original)
+++ commons/proper/math/trunk/src/java/org/apache/commons/math/fraction/Fraction.java Fri Feb  1 04:02:12 2008
@@ -34,7 +34,7 @@
     public static final Fraction ZERO = new Fraction(0, 1);
 
     /** Serializable version identifier */
-    private static final long serialVersionUID = 5463066929751300926L;
+    private static final long serialVersionUID = -8958519416450949235L;
     
     /** The denominator. */
     private int denominator;
@@ -128,33 +128,40 @@
     private Fraction(double value, double epsilon, int maxDenominator, int maxIterations)
         throws FractionConversionException
     {
+        long overflow = Integer.MAX_VALUE;
         double r0 = value;
-        int a0 = (int)Math.floor(r0);
+        long a0 = (long)Math.floor(r0);
+        if (a0 > overflow) {
+            throw new FractionConversionException(value, a0, 1l);
+        }
 
         // check for (almost) integer arguments, which should not go
         // to iterations.
         if (Math.abs(a0 - value) < epsilon) {
-            this.numerator = a0;
+            this.numerator = (int) a0;
             this.denominator = 1;
             return;
         }
-        
-        int p0 = 1;
-        int q0 = 0;
-        int p1 = a0;
-        int q1 = 1;
 
-        int p2 = 0;
-        int q2 = 1;
+       long p0 = 1;
+        long q0 = 0;
+        long p1 = a0;
+        long q1 = 1;
+
+        long p2 = 0;
+        long q2 = 1;
 
         int n = 0;
         boolean stop = false;
         do {
             ++n;
             double r1 = 1.0 / (r0 - a0);
-            int a1 = (int)Math.floor(r1);
+            long a1 = (long)Math.floor(r1);
             p2 = (a1 * p1) + p0;
             q2 = (a1 * q1) + q0;
+            if ((p2 > overflow) || (q2 > overflow)) {
+                throw new FractionConversionException(value, p2, q2);
+            }
             
             double convergent = (double)p2 / (double)q2;
             if (n < maxIterations && Math.abs(convergent - value) > epsilon && q2 < maxDenominator) {
@@ -174,11 +181,11 @@
         }
         
         if (q2 < maxDenominator) {
-            this.numerator = p2;
-            this.denominator = q2;
+            this.numerator = (int) p2;
+            this.denominator = (int) q2;
         } else {
-            this.numerator = p1;
-            this.denominator = q1;
+            this.numerator = (int) p1;
+            this.denominator = (int) q1;
         }
 
     }

Modified: commons/proper/math/trunk/src/java/org/apache/commons/math/fraction/FractionConversionException.java
URL: http://svn.apache.org/viewvc/commons/proper/math/trunk/src/java/org/apache/commons/math/fraction/FractionConversionException.java?rev=617482&r1=617481&r2=617482&view=diff
==============================================================================
--- commons/proper/math/trunk/src/java/org/apache/commons/math/fraction/FractionConversionException.java (original)
+++ commons/proper/math/trunk/src/java/org/apache/commons/math/fraction/FractionConversionException.java Fri Feb  1 04:02:12 2008
@@ -17,7 +17,7 @@
 
 package org.apache.commons.math.fraction;
 
-import org.apache.commons.math.MaxIterationsExceededException;
+import org.apache.commons.math.ConvergenceException;
 
 /**
  * Error thrown when a double value cannot be converted to a fraction
@@ -25,10 +25,10 @@
  *
  * @version $Revision$ $Date$
  */
-public class FractionConversionException extends MaxIterationsExceededException {
+public class FractionConversionException extends ConvergenceException {
 
     /** Serializable version identifier. */
-    private static final long serialVersionUID = 4588659344016668813L;
+    private static final long serialVersionUID = -4661812640132576263L;
 
     /**
      * Constructs an exception with specified formatted detail message.
@@ -37,9 +37,20 @@
      * @param maxIterations maximal number of iterations allowed
      */
     public FractionConversionException(double value, int maxIterations) {
-        super(maxIterations,
-              "Unable to convert {0} to fraction after {1} iterations",
+        super("Unable to convert {0} to fraction after {1} iterations",
               new Object[] { new Double(value), new Integer(maxIterations) });
+    }
+
+    /**
+     * Constructs an exception with specified formatted detail message.
+     * Message formatting is delegated to {@link java.text.MessageFormat}.
+     * @param value double value to convert
+     * @param p current numerator 
+     * @param q current denominator
+     */
+    public FractionConversionException(double value, long p, long q) {
+        super("Overflow trying to convert {0} to fraction ({1}/{2})",
+              new Object[] { new Double(value), new Long(p), new Long(q) });
     }
 
 }

Modified: commons/proper/math/trunk/src/test/org/apache/commons/math/fraction/FractionTest.java
URL: http://svn.apache.org/viewvc/commons/proper/math/trunk/src/test/org/apache/commons/math/fraction/FractionTest.java?rev=617482&r1=617481&r2=617482&view=diff
==============================================================================
--- commons/proper/math/trunk/src/test/org/apache/commons/math/fraction/FractionTest.java (original)
+++ commons/proper/math/trunk/src/test/org/apache/commons/math/fraction/FractionTest.java Fri Feb  1 04:02:12 2008
@@ -133,6 +133,22 @@
         assertFraction(769, 1250, new Fraction(0.6152, 9999));
     }
 
+    public void testIntegerOverflow() {
+        checkIntegerOverflow(0.75000000001455192);
+        checkIntegerOverflow(1.0e10);
+    }
+
+    private void checkIntegerOverflow(double a) {
+        try {
+            new Fraction(a, 1.0e-12, 1000);
+            fail("an exception should have been thrown");
+        } catch (ConvergenceException ce) {
+            // expected behavior
+        } catch (Exception e) {
+            fail("wrong exception caught");
+        }
+    }
+
     public void testEpsilonLimitConstructor() throws ConvergenceException  {
         assertFraction(2, 5, new Fraction(0.4, 1.0e-5, 100));
 

Modified: commons/proper/math/trunk/xdocs/changes.xml
URL: http://svn.apache.org/viewvc/commons/proper/math/trunk/xdocs/changes.xml?rev=617482&r1=617481&r2=617482&view=diff
==============================================================================
--- commons/proper/math/trunk/xdocs/changes.xml (original)
+++ commons/proper/math/trunk/xdocs/changes.xml Fri Feb  1 04:02:12 2008
@@ -136,6 +136,9 @@
       <action dev="luc" type="update" issue="MATH-181" due-to="Niall Pemberton">
         Add Fraction constructor using max denominator value.
       </action> 
+      <action dev="luc" type="fix" issue="MATH-18x">
+        Add integer overflow checks in Fraction constructor using double parameter.
+      </action>     
     </release>
     <release version="1.1" date="2005-12-17"  
  description="This is a maintenance release containing bug fixes and enhancements.