Return-Path: X-Original-To: apmail-commons-dev-archive@www.apache.org Delivered-To: apmail-commons-dev-archive@www.apache.org Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by minotaur.apache.org (Postfix) with SMTP id 6BC51176B8 for ; Wed, 8 Oct 2014 07:12:04 +0000 (UTC) Received: (qmail 68818 invoked by uid 500); 8 Oct 2014 07:12:03 -0000 Delivered-To: apmail-commons-dev-archive@commons.apache.org Received: (qmail 68718 invoked by uid 500); 8 Oct 2014 07:12:03 -0000 Mailing-List: contact dev-help@commons.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: "Commons Developers List" Delivered-To: mailing list dev@commons.apache.org Received: (qmail 68706 invoked by uid 99); 8 Oct 2014 07:12:03 -0000 Received: from nike.apache.org (HELO nike.apache.org) (192.87.106.230) by apache.org (qpsmtpd/0.29) with ESMTP; Wed, 08 Oct 2014 07:12:03 +0000 X-ASF-Spam-Status: No, hits=-0.0 required=5.0 tests=SPF_PASS X-Spam-Check-By: apache.org Received-SPF: pass (nike.apache.org: domain of luc@spaceroots.org designates 80.67.176.229 as permitted sender) Received: from [80.67.176.229] (HELO smtp.spaceroots.org) (80.67.176.229) by apache.org (qpsmtpd/0.29) with ESMTP; Wed, 08 Oct 2014 07:11:35 +0000 Received: from [192.168.163.2] (lehrin.spaceroots.org [192.168.163.2]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.spaceroots.org (Postfix) with ESMTPSA id 20A165409F for ; Wed, 8 Oct 2014 09:11:34 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=simple/simple; d=spaceroots.org; s=mail; t=1412752294; bh=lwehwroY/Ah8/SU1GISKtYzPTN/VpoqBpo8FLqdIVS4=; h=Date:From:To:Subject:References:In-Reply-To; b=m/dBkPyrcjeeNgYxawoFyemaRrGo38/D9zjVA3gTbbeCA/PI7DWozY1sSn00d/Mh9 D606SACD/gMddwV2sacPCLtAquj6hpxj99XaMufy3JU1Yw/Heb4ZiyiA4+UFqJlr5N O0uBpfCV2pdkJi4MmhuXHe8at5t+SBa2LMofzR/8= Message-ID: <5434E396.2090505@spaceroots.org> Date: Wed, 08 Oct 2014 09:11:18 +0200 From: Luc Maisonobe User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:31.0) Gecko/20100101 Icedove/31.0 MIME-Version: 1.0 To: Commons Developers List Subject: Re: git commit: Added all Java 8 StrictMath methods to FastMath. References: In-Reply-To: Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit X-Virus-Checked: Checked by ClamAV on apache.org Hi Sebb, Le 07/10/2014 23:40, sebb a écrit : > On 7 October 2014 12:55, 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 >> Authored: Tue Oct 7 13:54:55 2014 +0200 >> Committer: Luc Maisonobe >> 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 @@ >> >> >> >> - scm:svn:http://svn.apache.org/repos/asf/commons/proper/math/trunk >> - scm:svn:https://svn.apache.org/repos/asf/commons/proper/math/trunk >> - http://svn.apache.org/viewvc/commons/proper/math/trunk >> + scm:git:http://git-wip-us.apache.org/repos/asf/commons-math.git >> + scm:git:https://git-wip-us.apache.org/repos/asf/commons-math.git >> + https://git-wip-us.apache.org/repos/asf?p=commons-math.git >> > > The pom.xml change appears to belong to a different commit; it does > not seem to relate to the log message. Nice catch, thanks. It seems to be an error. This change was intended to be in a commit of its own, and I obviously forgot to do it. It seems I make more and more errors like this as I'm getting older (I turned 50 a few days ago ;-) I sincerely try to be more careful, sorry best regards, Luc > >> >> >> 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). >> "> >> + >> + Added all Java 8 StrictMath methods to FastMath, so FastMath remains compatible >> + with newer Java versions. >> + >> >> Added Gumbel, Laplace, Logistic and Nakagami distributions. >> >> >> 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. >> *

Note: 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. >> + *

>> + * 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). >> + *

>> + * @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. >> + *

>> + * 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). >> + *

>> + * @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. >> + *

>> + * 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). >> + *

>> + * @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. >> + *

>> + * 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). >> + *

>> + * @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-unsubscribe@commons.apache.org > For additional commands, e-mail: dev-help@commons.apache.org > > --------------------------------------------------------------------- To unsubscribe, e-mail: dev-unsubscribe@commons.apache.org For additional commands, e-mail: dev-help@commons.apache.org