On 7 October 2014 12:55, <l...@apache.org> wrote: > Repository: commons-math > Updated Branches: > refs/heads/master cee04d164 -> a67f0a33e > > > Added all Java 8 StrictMath methods to FastMath. > > This change allows FastMath to remain compatible with newer Java > versions, despite it stiil requires only Java 5 to compile and run. > > JIRA: MATH-1156 > > > Project: http://git-wip-us.apache.org/repos/asf/commons-math/repo > Commit: http://git-wip-us.apache.org/repos/asf/commons-math/commit/a67f0a33 > Tree: http://git-wip-us.apache.org/repos/asf/commons-math/tree/a67f0a33 > Diff: http://git-wip-us.apache.org/repos/asf/commons-math/diff/a67f0a33 > > Branch: refs/heads/master > Commit: a67f0a33e68abf1c985db28b19ce70f427fd48bd > Parents: cee04d1 > Author: Luc Maisonobe <l...@apache.org> > Authored: Tue Oct 7 13:54:55 2014 +0200 > Committer: Luc Maisonobe <l...@apache.org> > Committed: Tue Oct 7 13:54:55 2014 +0200 > > ---------------------------------------------------------------------- > pom.xml | 6 +- > src/changes/changes.xml | 4 + > .../math3/exception/util/LocalizedFormats.java | 1 + > .../org/apache/commons/math3/util/FastMath.java | 334 +++++++++++++++ > .../util/LocalizedFormats_fr.properties | 1 + > .../exception/util/LocalizedFormatsTest.java | 3 +- > .../apache/commons/math3/util/FastMathTest.java | 429 ++++++++++++++++++- > 7 files changed, 769 insertions(+), 9 deletions(-) > ---------------------------------------------------------------------- > > > http://git-wip-us.apache.org/repos/asf/commons-math/blob/a67f0a33/pom.xml > ---------------------------------------------------------------------- > diff --git a/pom.xml b/pom.xml > index 3ca4958..3a62e60 100644 > --- a/pom.xml > +++ b/pom.xml > @@ -38,9 +38,9 @@ > </issueManagement> > > <scm> > - > <connection>scm:svn:http://svn.apache.org/repos/asf/commons/proper/math/trunk</connection> > - > <developerConnection>scm:svn:https://svn.apache.org/repos/asf/commons/proper/math/trunk</developerConnection> > - <url>http://svn.apache.org/viewvc/commons/proper/math/trunk</url> > + > <connection>scm:git:http://git-wip-us.apache.org/repos/asf/commons-math.git</connection> > + > <developerConnection>scm:git:https://git-wip-us.apache.org/repos/asf/commons-math.git</developerConnection> > + <url>https://git-wip-us.apache.org/repos/asf?p=commons-math.git</url> > </scm>
The pom.xml change appears to belong to a different commit; it does not seem to relate to the log message. > <distributionManagement> > > http://git-wip-us.apache.org/repos/asf/commons-math/blob/a67f0a33/src/changes/changes.xml > ---------------------------------------------------------------------- > diff --git a/src/changes/changes.xml b/src/changes/changes.xml > index 0c6520b..7ea96c9 100644 > --- a/src/changes/changes.xml > +++ b/src/changes/changes.xml > @@ -73,6 +73,10 @@ Users are encouraged to upgrade to this version as this > release not > 2. A few methods in the FastMath class are in fact slower that their > counterpart in either Math or StrictMath (cf. MATH-740 and MATH-901). > "> > + <action dev="luc" type="add" issue="MATH-1156" > > + Added all Java 8 StrictMath methods to FastMath, so FastMath remains > compatible > + with newer Java versions. > + </action> > <action dev="tn" type="add" issue="MATH-1139" due-to="Alexey Volkov"> > Added Gumbel, Laplace, Logistic and Nakagami distributions. > </action> > > http://git-wip-us.apache.org/repos/asf/commons-math/blob/a67f0a33/src/main/java/org/apache/commons/math3/exception/util/LocalizedFormats.java > ---------------------------------------------------------------------- > diff --git > a/src/main/java/org/apache/commons/math3/exception/util/LocalizedFormats.java > b/src/main/java/org/apache/commons/math3/exception/util/LocalizedFormats.java > index 617a2cc..b775440 100644 > --- > a/src/main/java/org/apache/commons/math3/exception/util/LocalizedFormats.java > +++ > b/src/main/java/org/apache/commons/math3/exception/util/LocalizedFormats.java > @@ -293,6 +293,7 @@ public enum LocalizedFormats implements Localizable { > OVERFLOW_IN_FRACTION("overflow in fraction {0}/{1}, cannot negate"), > OVERFLOW_IN_ADDITION("overflow in addition: {0} + {1}"), > OVERFLOW_IN_SUBTRACTION("overflow in subtraction: {0} - {1}"), > + OVERFLOW_IN_MULTIPLICATION("overflow in multiplication: {0} * {1}"), > PERCENTILE_IMPLEMENTATION_CANNOT_ACCESS_METHOD("cannot access {0} method > in percentile implementation {1}"), > PERCENTILE_IMPLEMENTATION_UNSUPPORTED_METHOD("percentile implementation > {0} does not support {1}"), > PERMUTATION_EXCEEDS_N("permutation size ({0}) exceeds permuation domain > ({1})"), /* keep */ > > http://git-wip-us.apache.org/repos/asf/commons-math/blob/a67f0a33/src/main/java/org/apache/commons/math3/util/FastMath.java > ---------------------------------------------------------------------- > diff --git a/src/main/java/org/apache/commons/math3/util/FastMath.java > b/src/main/java/org/apache/commons/math3/util/FastMath.java > index d16406a..9ed4c04 100644 > --- a/src/main/java/org/apache/commons/math3/util/FastMath.java > +++ b/src/main/java/org/apache/commons/math3/util/FastMath.java > @@ -18,6 +18,9 @@ package org.apache.commons.math3.util; > > import java.io.PrintStream; > > +import org.apache.commons.math3.exception.MathArithmeticException; > +import org.apache.commons.math3.exception.util.LocalizedFormats; > + > /** > * Faster, more accurate, portable alternative to {@link Math} and > * {@link StrictMath} for large scale computation. > @@ -804,6 +807,24 @@ public class FastMath { > return nextAfter(a, Float.POSITIVE_INFINITY); > } > > + /** Compute next number towards negative infinity. > + * @param a number to which neighbor should be computed > + * @return neighbor of a towards negative infinity > + * @since 3.4 > + */ > + public static double nextDown(final double a) { > + return nextAfter(a, Double.NEGATIVE_INFINITY); > + } > + > + /** Compute next number towards negative infinity. > + * @param a number to which neighbor should be computed > + * @return neighbor of a towards negative infinity > + * @since 3.4 > + */ > + public static float nextDown(final float a) { > + return nextAfter(a, Float.NEGATIVE_INFINITY); > + } > + > /** Returns a pseudo-random number between 0.0 and 1.0. > * <p><b>Note:</b> this implementation currently delegates to {@link > Math#random} > * @return a random number between 0.0 and 1.0 > @@ -3634,6 +3655,319 @@ public class FastMath { > return StrictMath.IEEEremainder(dividend, divisor); // TODO provide > our own implementation > } > > + /** Convert a long to interger, detecting overflows > + * @param n number to convert to int > + * @return integer with same valie as n if no overflows occur > + * @exception MathArithmeticException if n cannot fit into an int > + * @since 3.4 > + */ > + public static int toIntExact(final long n) throws > MathArithmeticException { > + if (n < Integer.MIN_VALUE || n > Integer.MAX_VALUE) { > + throw new MathArithmeticException(LocalizedFormats.OVERFLOW); > + } > + return (int) n; > + } > + > + /** Increment a number, detecting overflows. > + * @param n number to increment > + * @return n+1 if no overflows occur > + * @exception MathArithmeticException if an overflow occurs > + * @since 3.4 > + */ > + public static int incrementExact(final int n) throws > MathArithmeticException { > + > + if (n == Integer.MAX_VALUE) { > + throw new > MathArithmeticException(LocalizedFormats.OVERFLOW_IN_ADDITION, n, 1); > + } > + > + return n + 1; > + > + } > + > + /** Increment a number, detecting overflows. > + * @param n number to increment > + * @return n+1 if no overflows occur > + * @exception MathArithmeticException if an overflow occurs > + * @since 3.4 > + */ > + public static long incrementExact(final long n) throws > MathArithmeticException { > + > + if (n == Long.MAX_VALUE) { > + throw new > MathArithmeticException(LocalizedFormats.OVERFLOW_IN_ADDITION, n, 1); > + } > + > + return n + 1; > + > + } > + > + /** Decrement a number, detecting overflows. > + * @param n number to decrement > + * @return n-1 if no overflows occur > + * @exception MathArithmeticException if an overflow occurs > + * @since 3.4 > + */ > + public static int decrementExact(final int n) throws > MathArithmeticException { > + > + if (n == Integer.MIN_VALUE) { > + throw new > MathArithmeticException(LocalizedFormats.OVERFLOW_IN_SUBTRACTION, n, 1); > + } > + > + return n - 1; > + > + } > + > + /** Decrement a number, detecting overflows. > + * @param n number to decrement > + * @return n-1 if no overflows occur > + * @exception MathArithmeticException if an overflow occurs > + * @since 3.4 > + */ > + public static long decrementExact(final long n) throws > MathArithmeticException { > + > + if (n == Long.MIN_VALUE) { > + throw new > MathArithmeticException(LocalizedFormats.OVERFLOW_IN_SUBTRACTION, n, 1); > + } > + > + return n - 1; > + > + } > + > + /** Add two numbers, detecting overflows. > + * @param a first number to add > + * @param b second number to add > + * @return a+b if no overflows occur > + * @exception MathArithmeticException if an overflow occurs > + * @since 3.4 > + */ > + public static int addExact(final int a, final int b) throws > MathArithmeticException { > + > + // compute sum > + final int sum = a + b; > + > + // check for overflow > + if ((a ^ b) >= 0 && (sum ^ b) < 0) { > + throw new > MathArithmeticException(LocalizedFormats.OVERFLOW_IN_ADDITION, a, b); > + } > + > + return sum; > + > + } > + > + /** Add two numbers, detecting overflows. > + * @param a first number to add > + * @param b second number to add > + * @return a+b if no overflows occur > + * @exception MathArithmeticException if an overflow occurs > + * @since 3.4 > + */ > + public static long addExact(final long a, final long b) throws > MathArithmeticException { > + > + // compute sum > + final long sum = a + b; > + > + // check for overflow > + if ((a ^ b) >= 0 && (sum ^ b) < 0) { > + throw new > MathArithmeticException(LocalizedFormats.OVERFLOW_IN_ADDITION, a, b); > + } > + > + return sum; > + > + } > + > + /** Subtract two numbers, detecting overflows. > + * @param a first number > + * @param b second number to subtract from a > + * @return a-b if no overflows occur > + * @exception MathArithmeticException if an overflow occurs > + * @since 3.4 > + */ > + public static int subtractExact(final int a, final int b) { > + > + // compute subtraction > + final int sub = a - b; > + > + // check for overflow > + if ((a ^ b) < 0 && (sub ^ b) >= 0) { > + throw new > MathArithmeticException(LocalizedFormats.OVERFLOW_IN_SUBTRACTION, a, b); > + } > + > + return sub; > + > + } > + > + /** Subtract two numbers, detecting overflows. > + * @param a first number > + * @param b second number to subtract from a > + * @return a-b if no overflows occur > + * @exception MathArithmeticException if an overflow occurs > + * @since 3.4 > + */ > + public static long subtractExact(final long a, final long b) { > + > + // compute subtraction > + final long sub = a - b; > + > + // check for overflow > + if ((a ^ b) < 0 && (sub ^ b) >= 0) { > + throw new > MathArithmeticException(LocalizedFormats.OVERFLOW_IN_SUBTRACTION, a, b); > + } > + > + return sub; > + > + } > + > + /** Multiply two numbers, detecting overflows. > + * @param a first number to multiply > + * @param b second number to multiply > + * @return a*b if no overflows occur > + * @exception MathArithmeticException if an overflow occurs > + * @since 3.4 > + */ > + public static int multiplyExact(final int a, final int b) { > + if (((b > 0) && (a > Integer.MAX_VALUE / b || a < > Integer.MIN_VALUE / b)) || > + ((b < -1) && (a > Integer.MIN_VALUE / b || a < > Integer.MAX_VALUE / b)) || > + ((b == -1) && (a == Integer.MIN_VALUE))) { > + throw new > MathArithmeticException(LocalizedFormats.OVERFLOW_IN_MULTIPLICATION, a, b); > + } > + return a * b; > + } > + > + /** Multiply two numbers, detecting overflows. > + * @param a first number to multiply > + * @param b second number to multiply > + * @return a*b if no overflows occur > + * @exception MathArithmeticException if an overflow occurs > + * @since 3.4 > + */ > + public static long multiplyExact(final long a, final long b) { > + if (((b > 0l) && (a > Long.MAX_VALUE / b || a < Long.MIN_VALUE / > b)) || > + ((b < -1l) && (a > Long.MIN_VALUE / b || a < Long.MAX_VALUE / > b)) || > + ((b == -1l) && (a == Long.MIN_VALUE))) { > + throw new > MathArithmeticException(LocalizedFormats.OVERFLOW_IN_MULTIPLICATION, a, b); > + } > + return a * b; > + } > + > + /** Finds q such that a = q b + r with 0 <= r < b if b > 0 and b < r <= > 0 if b > 0. > + * <p> > + * This methods returns the same value as integer division when > + * a and b are same signs, but returns a different value when > + * they are opposite (i.e. q is negative). > + * </p> > + * @param a dividend > + * @param b divisor > + * @return q such that a = q b + r with 0 <= r < b if b > 0 and b < r <= > 0 if b > 0 > + * @exception MathArithmeticException if b == 0 > + * @see #floorMod(int, int) > + * @since 3.4 > + */ > + public static int floorDiv(final int a, final int b) throws > MathArithmeticException { > + > + if (b == 0) { > + throw new > MathArithmeticException(LocalizedFormats.ZERO_DENOMINATOR); > + } > + > + final int m = a % b; > + if ((a ^ b) >= 0 || m == 0) { > + // a an b have same sign, or division is exact > + return a / b; > + } else { > + // a and b have opposite signs and division is not exact > + return (a / b) - 1; > + } > + > + } > + > + /** Finds q such that a = q b + r with 0 <= r < b if b > 0 and b < r <= > 0 if b > 0. > + * <p> > + * This methods returns the same value as integer division when > + * a and b are same signs, but returns a different value when > + * they are opposite (i.e. q is negative). > + * </p> > + * @param a dividend > + * @param b divisor > + * @return q such that a = q b + r with 0 <= r < b if b > 0 and b < r <= > 0 if b > 0 > + * @exception MathArithmeticException if b == 0 > + * @see #floorMod(long, long) > + * @since 3.4 > + */ > + public static long floorDiv(final long a, final long b) throws > MathArithmeticException { > + > + if (b == 0l) { > + throw new > MathArithmeticException(LocalizedFormats.ZERO_DENOMINATOR); > + } > + > + final long m = a % b; > + if ((a ^ b) >= 0l || m == 0l) { > + // a an b have same sign, or division is exact > + return a / b; > + } else { > + // a and b have opposite signs and division is not exact > + return (a / b) - 1l; > + } > + > + } > + > + /** Finds r such that a = q b + r with 0 <= r < b if b > 0 and b < r <= > 0 if b > 0. > + * <p> > + * This methods returns the same value as integer modulo when > + * a and b are same signs, but returns a different value when > + * they are opposite (i.e. q is negative). > + * </p> > + * @param a dividend > + * @param b divisor > + * @return r such that a = q b + r with 0 <= r < b if b > 0 and b < r <= > 0 if b > 0 > + * @exception MathArithmeticException if b == 0 > + * @see #floorDiv(int, int) > + * @since 3.4 > + */ > + public static int floorMod(final int a, final int b) throws > MathArithmeticException { > + > + if (b == 0) { > + throw new > MathArithmeticException(LocalizedFormats.ZERO_DENOMINATOR); > + } > + > + final int m = a % b; > + if ((a ^ b) >= 0 || m == 0) { > + // a an b have same sign, or division is exact > + return m; > + } else { > + // a and b have opposite signs and division is not exact > + return b + m; > + } > + > + } > + > + /** Finds r such that a = q b + r with 0 <= r < b if b > 0 and b < r <= > 0 if b > 0. > + * <p> > + * This methods returns the same value as integer modulo when > + * a and b are same signs, but returns a different value when > + * they are opposite (i.e. q is negative). > + * </p> > + * @param a dividend > + * @param b divisor > + * @return r such that a = q b + r with 0 <= r < b if b > 0 and b < r <= > 0 if b > 0 > + * @exception MathArithmeticException if b == 0 > + * @see #floorDiv(long, long) > + * @since 3.4 > + */ > + public static long floorMod(final long a, final long b) { > + > + if (b == 0l) { > + throw new > MathArithmeticException(LocalizedFormats.ZERO_DENOMINATOR); > + } > + > + final long m = a % b; > + if ((a ^ b) >= 0l || m == 0l) { > + // a an b have same sign, or division is exact > + return m; > + } else { > + // a and b have opposite signs and division is not exact > + return b + m; > + } > + > + } > + > /** > * Returns the first argument with the sign of the second argument. > * A NaN {@code sign} argument is treated as positive. > > http://git-wip-us.apache.org/repos/asf/commons-math/blob/a67f0a33/src/main/resources/assets/org/apache/commons/math3/exception/util/LocalizedFormats_fr.properties > ---------------------------------------------------------------------- > diff --git > a/src/main/resources/assets/org/apache/commons/math3/exception/util/LocalizedFormats_fr.properties > > b/src/main/resources/assets/org/apache/commons/math3/exception/util/LocalizedFormats_fr.properties > index 1a3c239..599dc7f 100644 > --- > a/src/main/resources/assets/org/apache/commons/math3/exception/util/LocalizedFormats_fr.properties > +++ > b/src/main/resources/assets/org/apache/commons/math3/exception/util/LocalizedFormats_fr.properties > @@ -265,6 +265,7 @@ OVERFLOW = d\u00e9passement de capacit\u00e9 > OVERFLOW_IN_FRACTION = d\u00e9passement de capacit\u00e9 pour la fraction > {0}/{1}, son signe ne peut \u00eatre chang\u00e9 > OVERFLOW_IN_ADDITION = d\u00e9passement de capacit\u00e9 pour l''addition : > {0} + {1} > OVERFLOW_IN_SUBTRACTION = d\u00e9passement de capacit\u00e9 pour la > soustraction : {0} - {1} > +OVERFLOW_IN_MULTIPLICATION = d\u00e9passement de capacit\u00e9 pour la > multiplication : {0} * {1} > PERCENTILE_IMPLEMENTATION_CANNOT_ACCESS_METHOD = acc\u00e8s impossible > \u00e0 la m\u00e9thode {0} dans la mise en \u0153uvre du pourcentage {1} > PERCENTILE_IMPLEMENTATION_UNSUPPORTED_METHOD = l''implantation de > pourcentage {0} ne dispose pas de la m\u00e9thode {1} > PERMUTATION_EXCEEDS_N = la taille de la permutation ({0}) d\u00e9passe le > domaine de la permutation ({1}) > > http://git-wip-us.apache.org/repos/asf/commons-math/blob/a67f0a33/src/test/java/org/apache/commons/math3/exception/util/LocalizedFormatsTest.java > ---------------------------------------------------------------------- > diff --git > a/src/test/java/org/apache/commons/math3/exception/util/LocalizedFormatsTest.java > > b/src/test/java/org/apache/commons/math3/exception/util/LocalizedFormatsTest.java > index 24d5bbc..34344d4 100644 > --- > a/src/test/java/org/apache/commons/math3/exception/util/LocalizedFormatsTest.java > +++ > b/src/test/java/org/apache/commons/math3/exception/util/LocalizedFormatsTest.java > @@ -23,14 +23,13 @@ import java.util.Locale; > import java.util.ResourceBundle; > > import org.junit.Assert; > - > import org.junit.Test; > > public class LocalizedFormatsTest { > > @Test > public void testMessageNumber() { > - Assert.assertEquals(319, LocalizedFormats.values().length); > + Assert.assertEquals(320, LocalizedFormats.values().length); > } > > @Test > > http://git-wip-us.apache.org/repos/asf/commons-math/blob/a67f0a33/src/test/java/org/apache/commons/math3/util/FastMathTest.java > ---------------------------------------------------------------------- > diff --git a/src/test/java/org/apache/commons/math3/util/FastMathTest.java > b/src/test/java/org/apache/commons/math3/util/FastMathTest.java > index 8408b78..f860754 100644 > --- a/src/test/java/org/apache/commons/math3/util/FastMathTest.java > +++ b/src/test/java/org/apache/commons/math3/util/FastMathTest.java > @@ -19,13 +19,16 @@ package org.apache.commons.math3.util; > import java.lang.reflect.Method; > import java.lang.reflect.Modifier; > import java.lang.reflect.Type; > +import java.math.BigInteger; > > import org.apache.commons.math3.TestUtils; > import org.apache.commons.math3.dfp.Dfp; > import org.apache.commons.math3.dfp.DfpField; > import org.apache.commons.math3.dfp.DfpMath; > +import org.apache.commons.math3.exception.MathArithmeticException; > import org.apache.commons.math3.random.MersenneTwister; > import org.apache.commons.math3.random.RandomGenerator; > +import org.apache.commons.math3.random.Well1024a; > import org.junit.Assert; > import org.junit.Before; > import org.junit.Ignore; > @@ -958,13 +961,13 @@ public class FastMathTest { > @Test > public void testNextAfter() { > // 0x402fffffffffffff 0x404123456789abcd -> 4030000000000000 > - Assert.assertEquals(16.0, FastMath.nextAfter(15.999999999999998, > 34.27555555555555), 0.0); > + Assert.assertEquals(16.0, FastMath.nextUp(15.999999999999998), 0.0); > > // 0xc02fffffffffffff 0x404123456789abcd -> c02ffffffffffffe > Assert.assertEquals(-15.999999999999996, > FastMath.nextAfter(-15.999999999999998, 34.27555555555555), 0.0); > > // 0x402fffffffffffff 0x400123456789abcd -> 402ffffffffffffe > - Assert.assertEquals(15.999999999999996, > FastMath.nextAfter(15.999999999999998, 2.142222222222222), 0.0); > + Assert.assertEquals(15.999999999999996, > FastMath.nextDown(15.999999999999998), 0.0); > > // 0xc02fffffffffffff 0x400123456789abcd -> c02ffffffffffffe > Assert.assertEquals(-15.999999999999996, > FastMath.nextAfter(-15.999999999999998, 2.142222222222222), 0.0); > @@ -1037,8 +1040,8 @@ public class FastMathTest { > > Assert.assertEquals(-Float.MAX_VALUE,FastMath.nextAfter(Float.NEGATIVE_INFINITY, > 0F), 0F); > > Assert.assertEquals(Float.MAX_VALUE,FastMath.nextAfter(Float.POSITIVE_INFINITY, > 0F), 0F); > Assert.assertEquals(Float.NaN,FastMath.nextAfter(Float.NaN, 0F), 0F); > - > Assert.assertEquals(Float.POSITIVE_INFINITY,FastMath.nextAfter(Float.MAX_VALUE, > Float.POSITIVE_INFINITY), 0F); > - > Assert.assertEquals(Float.NEGATIVE_INFINITY,FastMath.nextAfter(-Float.MAX_VALUE, > Float.NEGATIVE_INFINITY), 0F); > + > Assert.assertEquals(Float.POSITIVE_INFINITY,FastMath.nextUp(Float.MAX_VALUE), > 0F); > + > Assert.assertEquals(Float.NEGATIVE_INFINITY,FastMath.nextDown(-Float.MAX_VALUE), > 0F); > Assert.assertEquals(Float.MIN_VALUE, FastMath.nextAfter(0F, 1F), 0F); > Assert.assertEquals(-Float.MIN_VALUE, FastMath.nextAfter(0F, -1F), > 0F); > Assert.assertEquals(0F, FastMath.nextAfter(Float.MIN_VALUE, -1F), > 0F); > @@ -1182,4 +1185,422 @@ public class FastMathTest { > } > } > > + @Test > + public void testIncrementExactInt() { > + int[] specialValues = new int[] { > + Integer.MIN_VALUE, Integer.MIN_VALUE + 1, Integer.MIN_VALUE + 2, > + Integer.MAX_VALUE, Integer.MAX_VALUE - 1, Integer.MAX_VALUE - 2, > + -10, -9, -8, -7, -6, -5, -4, -3, -2, -1, 0, 1, 2, 3, 4, 5, 6, 7, > 8, 9, 10, > + -1 - (Integer.MIN_VALUE / 2), 0 - (Integer.MIN_VALUE / 2), 1 - > (Integer.MIN_VALUE / 2), > + -1 + (Integer.MAX_VALUE / 2), 0 + (Integer.MAX_VALUE / 2), 1 + > (Integer.MAX_VALUE / 2), > + }; > + for (int a : specialValues) { > + BigInteger bdA = BigInteger.valueOf(a); > + BigInteger bdSum = bdA.add(BigInteger.ONE); > + if (bdSum.compareTo(BigInteger.valueOf(Integer.MIN_VALUE)) < 0 || > + bdSum.compareTo(BigInteger.valueOf(Integer.MAX_VALUE)) > 0) { > + try { > + FastMath.incrementExact(a); > + Assert.fail("an exception should have been thrown"); > + } catch (MathArithmeticException mae) { > + // expected > + } > + } else { > + Assert.assertEquals(bdSum, > BigInteger.valueOf(FastMath.incrementExact(a))); > + } > + } > + } > + > + @Test > + public void testDecrementExactInt() { > + int[] specialValues = new int[] { > + Integer.MIN_VALUE, Integer.MIN_VALUE + 1, Integer.MIN_VALUE + 2, > + Integer.MAX_VALUE, Integer.MAX_VALUE - 1, Integer.MAX_VALUE - 2, > + -10, -9, -8, -7, -6, -5, -4, -3, -2, -1, 0, 1, 2, 3, 4, 5, 6, 7, > 8, 9, 10, > + -1 - (Integer.MIN_VALUE / 2), 0 - (Integer.MIN_VALUE / 2), 1 - > (Integer.MIN_VALUE / 2), > + -1 + (Integer.MAX_VALUE / 2), 0 + (Integer.MAX_VALUE / 2), 1 + > (Integer.MAX_VALUE / 2), > + }; > + for (int a : specialValues) { > + BigInteger bdA = BigInteger.valueOf(a); > + BigInteger bdSub = bdA.subtract(BigInteger.ONE); > + if (bdSub.compareTo(BigInteger.valueOf(Integer.MIN_VALUE)) < 0 || > + bdSub.compareTo(BigInteger.valueOf(Integer.MAX_VALUE)) > 0) { > + try { > + FastMath.decrementExact(a); > + Assert.fail("an exception should have been thrown"); > + } catch (MathArithmeticException mae) { > + // expected > + } > + } else { > + Assert.assertEquals(bdSub, > BigInteger.valueOf(FastMath.decrementExact(a))); > + } > + } > + } > + > + @Test > + public void testAddExactInt() { > + int[] specialValues = new int[] { > + Integer.MIN_VALUE, Integer.MIN_VALUE + 1, Integer.MIN_VALUE + 2, > + Integer.MAX_VALUE, Integer.MAX_VALUE - 1, Integer.MAX_VALUE - 2, > + -10, -9, -8, -7, -6, -5, -4, -3, -2, -1, 0, 1, 2, 3, 4, 5, 6, 7, > 8, 9, 10, > + -1 - (Integer.MIN_VALUE / 2), 0 - (Integer.MIN_VALUE / 2), 1 - > (Integer.MIN_VALUE / 2), > + -1 + (Integer.MAX_VALUE / 2), 0 + (Integer.MAX_VALUE / 2), 1 + > (Integer.MAX_VALUE / 2), > + }; > + for (int a : specialValues) { > + for (int b : specialValues) { > + BigInteger bdA = BigInteger.valueOf(a); > + BigInteger bdB = BigInteger.valueOf(b); > + BigInteger bdSum = bdA.add(bdB); > + if (bdSum.compareTo(BigInteger.valueOf(Integer.MIN_VALUE)) < > 0 || > + > bdSum.compareTo(BigInteger.valueOf(Integer.MAX_VALUE)) > 0) { > + try { > + FastMath.addExact(a, b); > + Assert.fail("an exception should have been thrown"); > + } catch (MathArithmeticException mae) { > + // expected > + } > + } else { > + Assert.assertEquals(bdSum, > BigInteger.valueOf(FastMath.addExact(a, b))); > + } > + } > + } > + } > + > + @Test > + public void testAddExactLong() { > + long[] specialValues = new long[] { > + Long.MIN_VALUE, Long.MIN_VALUE + 1, Long.MIN_VALUE + 2, > + Long.MAX_VALUE, Long.MAX_VALUE - 1, Long.MAX_VALUE - 2, > + -10, -9, -8, -7, -6, -5, -4, -3, -2, -1, 0, 1, 2, 3, 4, 5, 6, 7, > 8, 9, 10, > + -1 - (Long.MIN_VALUE / 2), 0 - (Long.MIN_VALUE / 2), 1 - > (Long.MIN_VALUE / 2), > + -1 + (Long.MAX_VALUE / 2), 0 + (Long.MAX_VALUE / 2), 1 + > (Long.MAX_VALUE / 2), > + }; > + for (long a : specialValues) { > + for (long b : specialValues) { > + BigInteger bdA = BigInteger.valueOf(a); > + BigInteger bdB = BigInteger.valueOf(b); > + BigInteger bdSum = bdA.add(bdB); > + if (bdSum.compareTo(BigInteger.valueOf(Long.MIN_VALUE)) < 0 > || > + bdSum.compareTo(BigInteger.valueOf(Long.MAX_VALUE)) > > 0) { > + try { > + FastMath.addExact(a, b); > + Assert.fail("an exception should have been thrown"); > + } catch (MathArithmeticException mae) { > + // expected > + } > + } else { > + Assert.assertEquals(bdSum, > BigInteger.valueOf(FastMath.addExact(a, b))); > + } > + } > + } > + } > + > + @Test > + public void testSubtractExactInt() { > + int[] specialValues = new int[] { > + Integer.MIN_VALUE, Integer.MIN_VALUE + 1, Integer.MIN_VALUE + 2, > + Integer.MAX_VALUE, Integer.MAX_VALUE - 1, Integer.MAX_VALUE - 2, > + -10, -9, -8, -7, -6, -5, -4, -3, -2, -1, 0, 1, 2, 3, 4, 5, 6, 7, > 8, 9, 10, > + -1 - (Integer.MIN_VALUE / 2), 0 - (Integer.MIN_VALUE / 2), 1 - > (Integer.MIN_VALUE / 2), > + -1 + (Integer.MAX_VALUE / 2), 0 + (Integer.MAX_VALUE / 2), 1 + > (Integer.MAX_VALUE / 2), > + }; > + for (int a : specialValues) { > + for (int b : specialValues) { > + BigInteger bdA = BigInteger.valueOf(a); > + BigInteger bdB = BigInteger.valueOf(b); > + BigInteger bdSub = bdA.subtract(bdB); > + if (bdSub.compareTo(BigInteger.valueOf(Integer.MIN_VALUE)) < > 0 || > + > bdSub.compareTo(BigInteger.valueOf(Integer.MAX_VALUE)) > 0) { > + try { > + FastMath.subtractExact(a, b); > + Assert.fail("an exception should have been thrown"); > + } catch (MathArithmeticException mae) { > + // expected > + } > + } else { > + Assert.assertEquals(bdSub, > BigInteger.valueOf(FastMath.subtractExact(a, b))); > + } > + } > + } > + } > + > + @Test > + public void testSubtractExactLong() { > + long[] specialValues = new long[] { > + Long.MIN_VALUE, Long.MIN_VALUE + 1, Long.MIN_VALUE + 2, > + Long.MAX_VALUE, Long.MAX_VALUE - 1, Long.MAX_VALUE - 2, > + -10, -9, -8, -7, -6, -5, -4, -3, -2, -1, 0, 1, 2, 3, 4, 5, 6, 7, > 8, 9, 10, > + -1 - (Long.MIN_VALUE / 2), 0 - (Long.MIN_VALUE / 2), 1 - > (Long.MIN_VALUE / 2), > + -1 + (Long.MAX_VALUE / 2), 0 + (Long.MAX_VALUE / 2), 1 + > (Long.MAX_VALUE / 2), > + }; > + for (long a : specialValues) { > + for (long b : specialValues) { > + BigInteger bdA = BigInteger.valueOf(a); > + BigInteger bdB = BigInteger.valueOf(b); > + BigInteger bdSub = bdA.subtract(bdB); > + if (bdSub.compareTo(BigInteger.valueOf(Long.MIN_VALUE)) < 0 > || > + bdSub.compareTo(BigInteger.valueOf(Long.MAX_VALUE)) > > 0) { > + try { > + FastMath.subtractExact(a, b); > + Assert.fail("an exception should have been thrown"); > + } catch (MathArithmeticException mae) { > + // expected > + } > + } else { > + Assert.assertEquals(bdSub, > BigInteger.valueOf(FastMath.subtractExact(a, b))); > + } > + } > + } > + } > + > + @Test > + public void testMultiplyExactInt() { > + int[] specialValues = new int[] { > + Integer.MIN_VALUE, Integer.MIN_VALUE + 1, Integer.MIN_VALUE + 2, > + Integer.MAX_VALUE, Integer.MAX_VALUE - 1, Integer.MAX_VALUE - 2, > + -10, -9, -8, -7, -6, -5, -4, -3, -2, -1, 0, 1, 2, 3, 4, 5, 6, 7, > 8, 9, 10, > + -1 - (Integer.MIN_VALUE / 2), 0 - (Integer.MIN_VALUE / 2), 1 - > (Integer.MIN_VALUE / 2), > + -1 + (Integer.MAX_VALUE / 2), 0 + (Integer.MAX_VALUE / 2), 1 + > (Integer.MAX_VALUE / 2), > + }; > + for (int a : specialValues) { > + for (int b : specialValues) { > + BigInteger bdA = BigInteger.valueOf(a); > + BigInteger bdB = BigInteger.valueOf(b); > + BigInteger bdMul = bdA.multiply(bdB); > + if (bdMul.compareTo(BigInteger.valueOf(Integer.MIN_VALUE)) < > 0 || > + > bdMul.compareTo(BigInteger.valueOf(Integer.MAX_VALUE)) > 0) { > + try { > + FastMath.multiplyExact(a, b); > + Assert.fail("an exception should have been thrown " > + a + b); > + } catch (MathArithmeticException mae) { > + // expected > + } > + } else { > + Assert.assertEquals(bdMul, > BigInteger.valueOf(FastMath.multiplyExact(a, b))); > + } > + } > + } > + } > + > + @Test > + public void testMultiplyExactLong() { > + long[] specialValues = new long[] { > + Long.MIN_VALUE, Long.MIN_VALUE + 1, Long.MIN_VALUE + 2, > + Long.MAX_VALUE, Long.MAX_VALUE - 1, Long.MAX_VALUE - 2, > + -10, -9, -8, -7, -6, -5, -4, -3, -2, -1, 0, 1, 2, 3, 4, 5, 6, 7, > 8, 9, 10, > + -1 - (Long.MIN_VALUE / 2), 0 - (Long.MIN_VALUE / 2), 1 - > (Long.MIN_VALUE / 2), > + -1 + (Long.MAX_VALUE / 2), 0 + (Long.MAX_VALUE / 2), 1 + > (Long.MAX_VALUE / 2), > + }; > + for (long a : specialValues) { > + for (long b : specialValues) { > + BigInteger bdA = BigInteger.valueOf(a); > + BigInteger bdB = BigInteger.valueOf(b); > + BigInteger bdMul = bdA.multiply(bdB); > + if (bdMul.compareTo(BigInteger.valueOf(Long.MIN_VALUE)) < 0 > || > + bdMul.compareTo(BigInteger.valueOf(Long.MAX_VALUE)) > > 0) { > + try { > + FastMath.multiplyExact(a, b); > + Assert.fail("an exception should have been thrown " > + a + b); > + } catch (MathArithmeticException mae) { > + // expected > + } > + } else { > + Assert.assertEquals(bdMul, > BigInteger.valueOf(FastMath.multiplyExact(a, b))); > + } > + } > + } > + } > + > + @Test(expected=MathArithmeticException.class) > + public void testToIntExactTooLow() { > + FastMath.toIntExact(-1l + Integer.MIN_VALUE); > + } > + > + @Test(expected=MathArithmeticException.class) > + public void testToIntExactTooHigh() { > + FastMath.toIntExact(+1l + Integer.MAX_VALUE); > + } > + > + @Test > + public void testToIntExact() { > + for (int n = -1000; n < 1000; ++n) { > + Assert.assertEquals(n, FastMath.toIntExact(0l + n)); > + } > + Assert.assertEquals(Integer.MIN_VALUE, FastMath.toIntExact(0l + > Integer.MIN_VALUE)); > + Assert.assertEquals(Integer.MAX_VALUE, FastMath.toIntExact(0l + > Integer.MAX_VALUE)); > + } > + > + @Test > + public void testFloorDivInt() { > + Assert.assertEquals(+1, FastMath.floorDiv(+4, +3)); > + Assert.assertEquals(-2, FastMath.floorDiv(-4, +3)); > + Assert.assertEquals(-2, FastMath.floorDiv(+4, -3)); > + Assert.assertEquals(+1, FastMath.floorDiv(-4, -3)); > + try { > + FastMath.floorDiv(1, 0); > + Assert.fail("an exception should have been thrown"); > + } catch (MathArithmeticException mae) { > + // expected > + } > + for (int a = -100; a <= 100; ++a) { > + for (int b = -100; b <= 100; ++b) { > + if (b != 0) { > + Assert.assertEquals(poorManFloorDiv(a, b), > FastMath.floorDiv(a, b)); > + } > + } > + } > + } > + > + @Test > + public void testFloorModInt() { > + Assert.assertEquals(+1, FastMath.floorMod(+4, +3)); > + Assert.assertEquals(+2, FastMath.floorMod(-4, +3)); > + Assert.assertEquals(-2, FastMath.floorMod(+4, -3)); > + Assert.assertEquals(-1, FastMath.floorMod(-4, -3)); > + try { > + FastMath.floorMod(1, 0); > + Assert.fail("an exception should have been thrown"); > + } catch (MathArithmeticException mae) { > + // expected > + } > + for (int a = -100; a <= 100; ++a) { > + for (int b = -100; b <= 100; ++b) { > + if (b != 0) { > + Assert.assertEquals(poorManFloorMod(a, b), > FastMath.floorMod(a, b)); > + } > + } > + } > + } > + > + @Test > + public void testFloorDivModInt() { > + RandomGenerator generator = new Well1024a(0x7ccab45edeaab90al); > + for (int i = 0; i < 10000; ++i) { > + int a = generator.nextInt(); > + int b = generator.nextInt(); > + if (b == 0) { > + try { > + FastMath.floorDiv(a, b); > + Assert.fail("an exception should have been thrown"); > + } catch (MathArithmeticException mae) { > + // expected > + } > + } else { > + int d = FastMath.floorDiv(a, b); > + int m = FastMath.floorMod(a, b); > + Assert.assertEquals(FastMath.toIntExact(poorManFloorDiv(a, > b)), d); > + Assert.assertEquals(FastMath.toIntExact(poorManFloorMod(a, > b)), m); > + Assert.assertEquals(a, d * b + m); > + if (b < 0) { > + Assert.assertTrue(m <= 0); > + Assert.assertTrue(-m < -b); > + } else { > + Assert.assertTrue(m >= 0); > + Assert.assertTrue(m < b); > + } > + } > + } > + } > + > + @Test > + public void testFloorDivLong() { > + Assert.assertEquals(+1l, FastMath.floorDiv(+4l, +3l)); > + Assert.assertEquals(-2l, FastMath.floorDiv(-4l, +3l)); > + Assert.assertEquals(-2l, FastMath.floorDiv(+4l, -3l)); > + Assert.assertEquals(+1l, FastMath.floorDiv(-4l, -3l)); > + try { > + FastMath.floorDiv(1l, 0l); > + Assert.fail("an exception should have been thrown"); > + } catch (MathArithmeticException mae) { > + // expected > + } > + for (long a = -100l; a <= 100l; ++a) { > + for (long b = -100l; b <= 100l; ++b) { > + if (b != 0) { > + Assert.assertEquals(poorManFloorDiv(a, b), > FastMath.floorDiv(a, b)); > + } > + } > + } > + } > + > + @Test > + public void testFloorModLong() { > + Assert.assertEquals(+1l, FastMath.floorMod(+4l, +3l)); > + Assert.assertEquals(+2l, FastMath.floorMod(-4l, +3l)); > + Assert.assertEquals(-2l, FastMath.floorMod(+4l, -3l)); > + Assert.assertEquals(-1l, FastMath.floorMod(-4l, -3l)); > + try { > + FastMath.floorMod(1l, 0l); > + Assert.fail("an exception should have been thrown"); > + } catch (MathArithmeticException mae) { > + // expected > + } > + for (long a = -100l; a <= 100l; ++a) { > + for (long b = -100l; b <= 100l; ++b) { > + if (b != 0) { > + Assert.assertEquals(poorManFloorMod(a, b), > FastMath.floorMod(a, b)); > + } > + } > + } > + } > + > + @Test > + public void testFloorDivModLong() { > + RandomGenerator generator = new Well1024a(0xb87b9bc14c96ccd5l); > + for (int i = 0; i < 10000; ++i) { > + long a = generator.nextLong(); > + long b = generator.nextLong(); > + if (b == 0) { > + try { > + FastMath.floorDiv(a, b); > + Assert.fail("an exception should have been thrown"); > + } catch (MathArithmeticException mae) { > + // expected > + } > + } else { > + long d = FastMath.floorDiv(a, b); > + long m = FastMath.floorMod(a, b); > + Assert.assertEquals(poorManFloorDiv(a, b), d); > + Assert.assertEquals(poorManFloorMod(a, b), m); > + Assert.assertEquals(a, d * b + m); > + if (b < 0) { > + Assert.assertTrue(m <= 0); > + Assert.assertTrue(-m < -b); > + } else { > + Assert.assertTrue(m >= 0); > + Assert.assertTrue(m < b); > + } > + } > + } > + } > + > + private long poorManFloorDiv(long a, long b) { > + > + // find q0, r0 such that a = q0 b + r0 > + BigInteger q0 = BigInteger.valueOf(a / b); > + BigInteger r0 = BigInteger.valueOf(a % b); > + BigInteger fd = BigInteger.valueOf(Integer.MIN_VALUE); > + BigInteger bigB = BigInteger.valueOf(b); > + > + for (int k = -2; k < 2; ++k) { > + // find another pair q, r such that a = q b + r > + BigInteger bigK = BigInteger.valueOf(k); > + BigInteger q = q0.subtract(bigK); > + BigInteger r = r0.add(bigK.multiply(bigB)); > + if (r.abs().compareTo(bigB.abs()) < 0 && > + (r.longValue() == 0l || ((r.longValue() ^ b) & > 0x8000000000000000l) == 0)) { > + if (fd.compareTo(q) < 0) { > + fd = q; > + } > + } > + } > + > + return fd.longValue(); > + > + } > + > + private long poorManFloorMod(long a, long b) { > + return a - b * poorManFloorDiv(a, b); > + } > + > } > --------------------------------------------------------------------- To unsubscribe, e-mail: dev-unsubscr...@commons.apache.org For additional commands, e-mail: dev-h...@commons.apache.org