Return-Path: Delivered-To: apmail-harmony-commits-archive@www.apache.org Received: (qmail 33551 invoked from network); 13 Jun 2007 13:35:00 -0000 Received: from hermes.apache.org (HELO mail.apache.org) (140.211.11.2) by minotaur.apache.org with SMTP; 13 Jun 2007 13:35:00 -0000 Received: (qmail 74146 invoked by uid 500); 13 Jun 2007 13:35:03 -0000 Delivered-To: apmail-harmony-commits-archive@harmony.apache.org Received: (qmail 74058 invoked by uid 500); 13 Jun 2007 13:35:03 -0000 Mailing-List: contact commits-help@harmony.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@harmony.apache.org Delivered-To: mailing list commits@harmony.apache.org Received: (qmail 74049 invoked by uid 99); 13 Jun 2007 13:35:03 -0000 Received: from herse.apache.org (HELO herse.apache.org) (140.211.11.133) by apache.org (qpsmtpd/0.29) with ESMTP; Wed, 13 Jun 2007 06:35:03 -0700 X-ASF-Spam-Status: No, hits=-99.5 required=10.0 tests=ALL_TRUSTED,NO_REAL_NAME X-Spam-Check-By: apache.org Received: from [140.211.11.3] (HELO eris.apache.org) (140.211.11.3) by apache.org (qpsmtpd/0.29) with ESMTP; Wed, 13 Jun 2007 06:34:59 -0700 Received: by eris.apache.org (Postfix, from userid 65534) id 032351A981A; Wed, 13 Jun 2007 06:34:39 -0700 (PDT) Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: svn commit: r546865 - in /harmony/enhanced/classlib/branches/java6/modules/luni/src: main/java/java/lang/Math.java test/java/org/apache/harmony/luni/tests/java/lang/MathTest.java Date: Wed, 13 Jun 2007 13:34:38 -0000 To: commits@harmony.apache.org From: tellison@apache.org X-Mailer: svnmailer-1.1.0 Message-Id: <20070613133439.032351A981A@eris.apache.org> X-Virus-Checked: Checked by ClamAV on apache.org Author: tellison Date: Wed Jun 13 06:34:38 2007 New Revision: 546865 URL: http://svn.apache.org/viewvc?view=rev&rev=546865 Log: Apply patch HARMONY-4137 ([classlib][luni][java6] new methods nextAfter, nextUp in java.lang.Math) Modified: harmony/enhanced/classlib/branches/java6/modules/luni/src/main/java/java/lang/Math.java harmony/enhanced/classlib/branches/java6/modules/luni/src/test/java/org/apache/harmony/luni/tests/java/lang/MathTest.java Modified: harmony/enhanced/classlib/branches/java6/modules/luni/src/main/java/java/lang/Math.java URL: http://svn.apache.org/viewvc/harmony/enhanced/classlib/branches/java6/modules/luni/src/main/java/java/lang/Math.java?view=diff&rev=546865&r1=546864&r2=546865 ============================================================================== --- harmony/enhanced/classlib/branches/java6/modules/luni/src/main/java/java/lang/Math.java (original) +++ harmony/enhanced/classlib/branches/java6/modules/luni/src/main/java/java/lang/Math.java Wed Jun 13 06:34:38 2007 @@ -715,4 +715,128 @@ bits = (bits & DOUBLE_EXPONENT_MASK) >> DOUBLE_MANTISSA_BITS; return (int) bits - DOUBLE_EXPONENT_BIAS; } + + /** + * Answers a double next to the first given double value in the direction of + * the second given double. + * + * @param start + * the double value to start + * @param direction + * the double indicating the direction + * @return a double next to the first given double value in the direction of + * the second given double. + * + * @since 1.6 + */ + public static double nextAfter(double start, double direction) { + if (0 == start && 0 == direction) { + return direction; + } + return nextafter(start, direction); + } + + /** + * Answers a float next to the first given float value in the direction of + * the second given double value. + * + * @param start + * the float value to start + * @param direction + * the double indicating the direction + * @return a float next to the first given float value in the direction of + * the second given double. + * + * @since 1.6 + */ + @SuppressWarnings("boxing") + public static float nextAfter(float start, double direction) { + if (Float.isNaN(start) || Double.isNaN(direction)) { + return Float.NaN; + } + if (0 == start && 0 == direction) { + return new Float(direction); + } + if ((start == Float.MIN_VALUE && direction < start) + || (start == -Float.MIN_VALUE && direction > start)) { + return (start > 0 ? 0f : -0f); + } + if (Float.isInfinite(start) && (direction != start)) { + return (start > 0 ? Float.MAX_VALUE : -Float.MAX_VALUE); + } + if ((start == Float.MAX_VALUE && direction > start) + || (start == -Float.MAX_VALUE && direction < start)) { + return (start > 0 ? Float.POSITIVE_INFINITY + : Float.NEGATIVE_INFINITY); + } + if (direction > start) { + if (start > 0) { + return Float.intBitsToFloat(Float.floatToIntBits(start) + 1); + } + if (start < 0) { + return Float.intBitsToFloat(Float.floatToIntBits(start) - 1); + } + return +Float.MIN_VALUE; + } + if (direction < start) { + if (start > 0) { + return Float.intBitsToFloat(Float.floatToIntBits(start) - 1); + } + if (start < 0) { + return Float.intBitsToFloat(Float.floatToIntBits(start) + 1); + } + return -Float.MIN_VALUE; + } + return new Float(direction); + } + + /** + * Answers the next larger double value to d. + * + * @param d + * the double value to start + * @return the next larger double value of d. + * + * @since 1.6 + */ + public static double nextUp(double d) { + if (Double.isNaN(d)) { + return Double.NaN; + } + if ((d == Double.POSITIVE_INFINITY)) { + return Double.POSITIVE_INFINITY; + } + if (0 == d) { + return Double.MIN_VALUE; + } else if (0 < d) { + return Double.longBitsToDouble(Double.doubleToLongBits(d) + 1); + } else { + return Double.longBitsToDouble(Double.doubleToLongBits(d) - 1); + } + } + + /** + * Answers the next larger float value to d. + * + * @param f + * the float value to start + * @return the next larger float value of d. + * + * @since 1.6 + */ + public static float nextUp(float f) { + if (Float.isNaN(f)) { + return Float.NaN; + } + if ((f == Float.POSITIVE_INFINITY)) { + return Float.POSITIVE_INFINITY; + } + if (0 == f) { + return Float.MIN_VALUE; + } else if (0 < f) { + return Float.intBitsToFloat(Float.floatToIntBits(f) + 1); + } else { + return Float.intBitsToFloat(Float.floatToIntBits(f) - 1); + } + } } Modified: harmony/enhanced/classlib/branches/java6/modules/luni/src/test/java/org/apache/harmony/luni/tests/java/lang/MathTest.java URL: http://svn.apache.org/viewvc/harmony/enhanced/classlib/branches/java6/modules/luni/src/test/java/org/apache/harmony/luni/tests/java/lang/MathTest.java?view=diff&rev=546865&r1=546864&r2=546865 ============================================================================== --- harmony/enhanced/classlib/branches/java6/modules/luni/src/test/java/org/apache/harmony/luni/tests/java/lang/MathTest.java (original) +++ harmony/enhanced/classlib/branches/java6/modules/luni/src/test/java/org/apache/harmony/luni/tests/java/lang/MathTest.java Wed Jun 13 06:34:38 2007 @@ -702,6 +702,263 @@ assertEquals("Incorrect long min value", -19088976000089L, Math.min(-20, -19088976000089L)); } + + /** + * start number cases for test_nextAfter_DD in MathTest/StrictMathTest + * NEXTAFTER_DD_START_CASES[i][0] is the start number + * NEXTAFTER_DD_START_CASES[i][1] is the nextUp of start number + * NEXTAFTER_DD_START_CASES[i][2] is the nextDown of start number + */ + static final double NEXTAFTER_DD_START_CASES[][] = new double[][] { + { 3.4, 3.4000000000000004, 3.3999999999999995 }, + { -3.4, -3.3999999999999995, -3.4000000000000004 }, + { 3.4233E109, 3.4233000000000005E109, 3.4232999999999996E109 }, + { -3.4233E109, -3.4232999999999996E109, -3.4233000000000005E109 }, + { +0.0, Double.MIN_VALUE, -Double.MIN_VALUE }, + { 0.0, Double.MIN_VALUE, -Double.MIN_VALUE }, + { -0.0, Double.MIN_VALUE, -Double.MIN_VALUE }, + { Double.MIN_VALUE, 1.0E-323, +0.0 }, + { -Double.MIN_VALUE, -0.0, -1.0E-323 }, + { Double.MIN_NORMAL, 2.225073858507202E-308, 2.225073858507201E-308 }, + { -Double.MIN_NORMAL, -2.225073858507201E-308, + -2.225073858507202E-308 }, + { Double.MAX_VALUE, Double.POSITIVE_INFINITY, + 1.7976931348623155E308 }, + { -Double.MAX_VALUE, -1.7976931348623155E308, + Double.NEGATIVE_INFINITY }, + { Double.POSITIVE_INFINITY, Double.POSITIVE_INFINITY, + Double.MAX_VALUE }, + { Double.NEGATIVE_INFINITY, -Double.MAX_VALUE, + Double.NEGATIVE_INFINITY } }; + + /** + * direction number cases for test_nextAfter_DD/test_nextAfter_FD in + * MathTest/StrictMathTest + */ + static final double NEXTAFTER_DD_FD_DIRECTION_CASES[] = new double[] { + Double.POSITIVE_INFINITY, Double.MAX_VALUE, 8.8, 3.4, 1.4, + Double.MIN_NORMAL, Double.MIN_NORMAL / 2, Double.MIN_VALUE, +0.0, + 0.0, -0.0, -Double.MIN_VALUE, -Double.MIN_NORMAL / 2, + -Double.MIN_NORMAL, -1.4, -3.4, -8.8, -Double.MAX_VALUE, + Double.NEGATIVE_INFINITY }; + + /** + * @tests {@link java.lang.Math#nextAfter(double, double)} + * @since 1.6 + */ + @SuppressWarnings("boxing") + public void test_nextAfter_DD() { + // test for most cases without exception + for (int i = 0; i < NEXTAFTER_DD_START_CASES.length; i++) { + final double start = NEXTAFTER_DD_START_CASES[i][0]; + final long nextUpBits = Double + .doubleToLongBits(NEXTAFTER_DD_START_CASES[i][1]); + final long nextDownBits = Double + .doubleToLongBits(NEXTAFTER_DD_START_CASES[i][2]); + + for (int j = 0; j < NEXTAFTER_DD_FD_DIRECTION_CASES.length; j++) { + final double direction = NEXTAFTER_DD_FD_DIRECTION_CASES[j]; + final long resultBits = Double.doubleToLongBits(Math.nextAfter( + start, direction)); + final long directionBits = Double.doubleToLongBits(direction); + if (direction > start) { + assertEquals("Result should be next up-number.", + nextUpBits, resultBits); + } else if (direction < start) { + assertEquals("Result should be next down-number.", + nextDownBits, resultBits); + } else { + assertEquals("Result should be direction.", directionBits, + resultBits); + } + } + } + + // test for cases with NaN + for (int i = 0; i < NEXTAFTER_DD_START_CASES.length; i++) { + assertTrue("The result should be NaN.", Double.isNaN(Math + .nextAfter(NEXTAFTER_DD_START_CASES[i][0], Double.NaN))); + } + for (int i = 0; i < NEXTAFTER_DD_FD_DIRECTION_CASES.length; i++) { + assertTrue("The result should be NaN.", Double.isNaN(Math + .nextAfter(Double.NaN, NEXTAFTER_DD_FD_DIRECTION_CASES[i]))); + } + assertTrue("The result should be NaN.", Double.isNaN(Math.nextAfter( + Double.NaN, Double.NaN))); + + // test for exception + try { + Math.nextAfter((Double) null, 2.3); + fail("Should throw NullPointerException"); + } catch (NullPointerException e) { + // Expected + } + try { + Math.nextAfter(2.3, (Double) null); + fail("Should throw NullPointerException"); + } catch (NullPointerException e) { + // Expected + } + try { + Math.nextAfter((Double) null, (Double) null); + fail("Should throw NullPointerException"); + } catch (NullPointerException e) { + // Expected + } + } + + /** + * start number cases for test_nextAfter_FD in MathTest/StrictMathTest + * NEXTAFTER_FD_START_CASES[i][0] is the start number + * NEXTAFTER_FD_START_CASES[i][1] is the nextUp of start number + * NEXTAFTER_FD_START_CASES[i][2] is the nextDown of start number + */ + static final float NEXTAFTER_FD_START_CASES[][] = new float[][] { + { 3.4f, 3.4000003f, 3.3999999f }, + { -3.4f, -3.3999999f, -3.4000003f }, + { 3.4233E19f, 3.4233002E19f, 3.4232998E19f }, + { -3.4233E19f, -3.4232998E19f, -3.4233002E19f }, + { +0.0f, Float.MIN_VALUE, -Float.MIN_VALUE }, + { 0.0f, Float.MIN_VALUE, -Float.MIN_VALUE }, + { -0.0f, Float.MIN_VALUE, -Float.MIN_VALUE }, + { Float.MIN_VALUE, 2.8E-45f, +0.0f }, + { -Float.MIN_VALUE, -0.0f, -2.8E-45f }, + { Float.MIN_NORMAL, 1.1754945E-38f, 1.1754942E-38f }, + { -Float.MIN_NORMAL, -1.1754942E-38f, -1.1754945E-38f }, + { Float.MAX_VALUE, Float.POSITIVE_INFINITY, 3.4028233E38f }, + { -Float.MAX_VALUE, -3.4028233E38f, Float.NEGATIVE_INFINITY }, + { Float.POSITIVE_INFINITY, Float.POSITIVE_INFINITY, Float.MAX_VALUE }, + { Float.NEGATIVE_INFINITY, -Float.MAX_VALUE, + Float.NEGATIVE_INFINITY } }; + + /** + * @tests {@link java.lang.Math#nextAfter(float, double)} + * @since 1.6 + */ + @SuppressWarnings("boxing") + public void test_nextAfter_FD() { + // test for most cases without exception + for (int i = 0; i < NEXTAFTER_FD_START_CASES.length; i++) { + final float start = NEXTAFTER_FD_START_CASES[i][0]; + final int nextUpBits = Float + .floatToIntBits(NEXTAFTER_FD_START_CASES[i][1]); + final int nextDownBits = Float + .floatToIntBits(NEXTAFTER_FD_START_CASES[i][2]); + + for (int j = 0; j < NEXTAFTER_DD_FD_DIRECTION_CASES.length; j++) { + final double direction = NEXTAFTER_DD_FD_DIRECTION_CASES[j]; + final int resultBits = Float.floatToIntBits(Math.nextAfter( + start, direction)); + if (direction > start) { + assertEquals("Result should be next up-number.", + nextUpBits, resultBits); + } else if (direction < start) { + assertEquals("Result should be next down-number.", + nextDownBits, resultBits); + } else { + final int equivalentBits = Float.floatToIntBits(new Float( + direction)); + assertEquals( + "Result should be a number equivalent to direction.", + equivalentBits, resultBits); + } + } + } + + // test for cases with NaN + for (int i = 0; i < NEXTAFTER_FD_START_CASES.length; i++) { + assertTrue("The result should be NaN.", Float.isNaN(Math.nextAfter( + NEXTAFTER_FD_START_CASES[i][0], Float.NaN))); + } + for (int i = 0; i < NEXTAFTER_DD_FD_DIRECTION_CASES.length; i++) { + assertTrue("The result should be NaN.", Float.isNaN(Math.nextAfter( + Float.NaN, NEXTAFTER_DD_FD_DIRECTION_CASES[i]))); + } + assertTrue("The result should be NaN.", Float.isNaN(Math.nextAfter( + Float.NaN, Float.NaN))); + + // test for exception + try { + Math.nextAfter((Float) null, 2.3); + fail("Should throw NullPointerException"); + } catch (NullPointerException e) { + // Expected + } + try { + Math.nextAfter(2.3, (Float) null); + fail("Should throw NullPointerException"); + } catch (NullPointerException e) { + // Expected + } + try { + Math.nextAfter((Float) null, (Float) null); + fail("Should throw NullPointerException"); + } catch (NullPointerException e) { + // Expected + } + } + + /** + * @tests {@link java.lang.Math#nextUp(double)} + * @since 1.6 + */ + @SuppressWarnings("boxing") + public void test_nextUp_D() { + // This method is semantically equivalent to nextAfter(d, + // Double.POSITIVE_INFINITY), + // so we use the data of test_nextAfter_DD + for (int i = 0; i < NEXTAFTER_DD_START_CASES.length; i++) { + final double start = NEXTAFTER_DD_START_CASES[i][0]; + final long nextUpBits = Double + .doubleToLongBits(NEXTAFTER_DD_START_CASES[i][1]); + final long resultBits = Double.doubleToLongBits(Math.nextUp(start)); + assertEquals("Result should be next up-number.", nextUpBits, + resultBits); + } + + // test for cases with NaN + assertTrue("The result should be NaN.", Double.isNaN(Math + .nextUp(Double.NaN))); + + // test for exception + try { + Math.nextUp((Double) null); + fail("Should throw NullPointerException"); + } catch (NullPointerException e) { + // Expected + } + } + + /** + * @tests {@link java.lang.Math#nextUp(float)} + * @since 1.6 + */ + @SuppressWarnings("boxing") + public void test_nextUp_F() { + // This method is semantically equivalent to nextAfter(f, + // Float.POSITIVE_INFINITY), + // so we use the data of test_nextAfter_FD + for (int i = 0; i < NEXTAFTER_FD_START_CASES.length; i++) { + final float start = NEXTAFTER_FD_START_CASES[i][0]; + final int nextUpBits = Float + .floatToIntBits(NEXTAFTER_FD_START_CASES[i][1]); + final int resultBits = Float.floatToIntBits(Math.nextUp(start)); + assertEquals("Result should be next up-number.", nextUpBits, + resultBits); + } + + // test for cases with NaN + assertTrue("The result should be NaN.", Float.isNaN(Math + .nextUp(Float.NaN))); + + // test for exception + try { + Math.nextUp((Float) null); + fail("Should throw NullPointerException"); + } catch (NullPointerException e) { + // Expected + } + } /** * @tests java.lang.Math#pow(double, double)