Return-Path: Delivered-To: apmail-commons-commits-archive@minotaur.apache.org Received: (qmail 66435 invoked from network); 29 Apr 2009 18:46:21 -0000 Received: from hermes.apache.org (HELO mail.apache.org) (140.211.11.3) by minotaur.apache.org with SMTP; 29 Apr 2009 18:46:21 -0000 Received: (qmail 1147 invoked by uid 500); 29 Apr 2009 18:34:32 -0000 Delivered-To: apmail-commons-commits-archive@commons.apache.org Received: (qmail 1073 invoked by uid 500); 29 Apr 2009 18:34:32 -0000 Mailing-List: contact commits-help@commons.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@commons.apache.org Delivered-To: mailing list commits@commons.apache.org Received: (qmail 1044 invoked by uid 99); 29 Apr 2009 18:34:30 -0000 Received: from nike.apache.org (HELO nike.apache.org) (192.87.106.230) by apache.org (qpsmtpd/0.29) with ESMTP; Wed, 29 Apr 2009 18:34:30 +0000 X-ASF-Spam-Status: No, hits=-2000.0 required=10.0 tests=ALL_TRUSTED X-Spam-Check-By: apache.org Received: from [140.211.11.4] (HELO eris.apache.org) (140.211.11.4) by apache.org (qpsmtpd/0.29) with ESMTP; Wed, 29 Apr 2009 18:34:22 +0000 Received: by eris.apache.org (Postfix, from userid 65534) id BB50323889F5; Wed, 29 Apr 2009 18:34:00 +0000 (UTC) Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: svn commit: r769867 - in /commons/proper/math/trunk/src: java/org/apache/commons/math/util/MathUtils.java site/xdoc/changes.xml test/org/apache/commons/math/util/MathUtilsTest.java Date: Wed, 29 Apr 2009 18:34:00 -0000 To: commits@commons.apache.org From: luc@apache.org X-Mailer: svnmailer-1.0.8 Message-Id: <20090429183400.BB50323889F5@eris.apache.org> X-Virus-Checked: Checked by ClamAV on apache.org Author: luc Date: Wed Apr 29 18:33:59 2009 New Revision: 769867 URL: http://svn.apache.org/viewvc?rev=769867&view=rev Log: Added an utility equality method between double numbers using tolerance in ulps (Units in Last Position) JIRA: MATH-264 Modified: commons/proper/math/trunk/src/java/org/apache/commons/math/util/MathUtils.java commons/proper/math/trunk/src/site/xdoc/changes.xml commons/proper/math/trunk/src/test/org/apache/commons/math/util/MathUtilsTest.java Modified: commons/proper/math/trunk/src/java/org/apache/commons/math/util/MathUtils.java URL: http://svn.apache.org/viewvc/commons/proper/math/trunk/src/java/org/apache/commons/math/util/MathUtils.java?rev=769867&r1=769866&r2=769867&view=diff ============================================================================== --- commons/proper/math/trunk/src/java/org/apache/commons/math/util/MathUtils.java (original) +++ commons/proper/math/trunk/src/java/org/apache/commons/math/util/MathUtils.java Wed Apr 29 18:33:59 2009 @@ -59,6 +59,9 @@ /** 2 π. */ private static final double TWO_PI = 2 * Math.PI; + private static final int NAN_GAP = 4 * 1024 * 1024; + private static final long SGN_MASK = 0x8000000000000000L; + /** * Private Constructor */ @@ -407,6 +410,39 @@ } /** + * Returns true iff both arguments are equal or within the range of allowed + * error (inclusive). + * Adapted from + * Bruce Dawson + * + * @param x first value + * @param y second value + * @param maxUlps {@code (maxUlps - 1)} is the number of floating point + * values between {@code x} and {@code y}. + * @return {@code true} if there are less than {@code maxUlps} floating + * point values between {@code x} and {@code y} + */ + public static boolean equals(double x, double y, int maxUlps) { + // Check that "maxUlps" is non-negative and small enough so that the + // default NAN won't compare as equal to anything. + assert maxUlps > 0 && maxUlps < NAN_GAP; + + long xInt = Double.doubleToLongBits(x); + long yInt = Double.doubleToLongBits(y); + + // Make lexicographically ordered as a two's-complement integer. + if (xInt < 0) { + xInt = SGN_MASK - xInt; + } + if (yInt < 0) { + yInt = SGN_MASK - yInt; + } + + return Math.abs(xInt - yInt) <= maxUlps; + } + + /** * Returns true iff both arguments are null or have same dimensions * and all their elements are {@link #equals(double,double) equals} * Modified: commons/proper/math/trunk/src/site/xdoc/changes.xml URL: http://svn.apache.org/viewvc/commons/proper/math/trunk/src/site/xdoc/changes.xml?rev=769867&r1=769866&r2=769867&view=diff ============================================================================== --- commons/proper/math/trunk/src/site/xdoc/changes.xml (original) +++ commons/proper/math/trunk/src/site/xdoc/changes.xml Wed Apr 29 18:33:59 2009 @@ -39,6 +39,10 @@ + + Added an utility equality method between double numbers using tolerance + in ulps (Units in Last Position) + Added support for any type of field in linear algebra (FielxMatrix, FieldVector, FieldLUDecomposition) Modified: commons/proper/math/trunk/src/test/org/apache/commons/math/util/MathUtilsTest.java URL: http://svn.apache.org/viewvc/commons/proper/math/trunk/src/test/org/apache/commons/math/util/MathUtilsTest.java?rev=769867&r1=769866&r2=769867&view=diff ============================================================================== --- commons/proper/math/trunk/src/test/org/apache/commons/math/util/MathUtilsTest.java (original) +++ commons/proper/math/trunk/src/test/org/apache/commons/math/util/MathUtilsTest.java Wed Apr 29 18:33:59 2009 @@ -353,6 +353,31 @@ assertFalse(MathUtils.equals(153.0000, 153.0625, .0624)); assertFalse(MathUtils.equals(152.9374, 153.0000, .0625)); } + + public void testEqualsWithAllowedUlps() { + assertTrue(MathUtils.equals(153, 153, 1)); + + assertTrue(MathUtils.equals(153, 153.00000000000003, 1)); + assertFalse(MathUtils.equals(153, 153.00000000000006, 1)); + assertTrue(MathUtils.equals(153, 152.99999999999997, 1)); + assertFalse(MathUtils.equals(153, 152.99999999999994, 1)); + + assertTrue(MathUtils.equals(-128, -127.99999999999999, 1)); + assertFalse(MathUtils.equals(-128, -127.99999999999997, 1)); + assertTrue(MathUtils.equals(-128, -128.00000000000003, 1)); + assertFalse(MathUtils.equals(-128, -128.00000000000006, 1)); + + assertTrue(MathUtils.equals(Double.POSITIVE_INFINITY, Double.POSITIVE_INFINITY, 1)); + assertTrue(MathUtils.equals(Double.MAX_VALUE, Double.POSITIVE_INFINITY, 1)); + + assertTrue(MathUtils.equals(Double.NEGATIVE_INFINITY, Double.NEGATIVE_INFINITY, 1)); + assertTrue(MathUtils.equals(-Double.MAX_VALUE, Double.NEGATIVE_INFINITY, 1)); + + + assertTrue(MathUtils.equals(Double.NaN, Double.NaN, 1)); + + assertFalse(MathUtils.equals(Double.NEGATIVE_INFINITY, Double.POSITIVE_INFINITY, 100000)); + } public void testArrayEquals() { assertFalse(MathUtils.equals(new double[] { 1d }, null));