Author: bayard
Date: Sun Jan 6 15:58:59 2008
New Revision: 609475
URL: http://svn.apache.org/viewvc?rev=609475&view=rev
Log:
Applying third patch from LANG-381. Fixes the minimum(float[]) type methods to
correctly return NaN when it is in the array, and adds an IEEE754rUtils class
that obeys the IEEE 754r update in which NaN in min/max methods should be
ignored unless all values are NaN.
Added:
commons/proper/lang/trunk/src/java/org/apache/commons/lang/math/IEEE754rUtils.java
(with props)
commons/proper/lang/trunk/src/test/org/apache/commons/lang/math/IEEE754rUtilsTest.java
(with props)
Modified:
commons/proper/lang/trunk/src/java/org/apache/commons/lang/math/NumberUtils.java
commons/proper/lang/trunk/src/test/org/apache/commons/lang/math/NumberUtilsTest.java
Added:
commons/proper/lang/trunk/src/java/org/apache/commons/lang/math/IEEE754rUtils.java
URL:
http://svn.apache.org/viewvc/commons/proper/lang/trunk/src/java/org/apache/commons/lang/math/IEEE754rUtils.java?rev=609475&view=auto
==============================================================================
---
commons/proper/lang/trunk/src/java/org/apache/commons/lang/math/IEEE754rUtils.java
(added)
+++
commons/proper/lang/trunk/src/java/org/apache/commons/lang/math/IEEE754rUtils.java
Sun Jan 6 15:58:59 2008
@@ -0,0 +1,265 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.lang.math;
+
+/**
+ * <p>Provides IEEE-754r variants of NumberUtils methods. </p>
+ *
+ * <p>See: <a
href="http://en.wikipedia.org/wiki/IEEE_754r">http://en.wikipedia.org/wiki/IEEE_754r</a></p>
+ *
+ * @since 2.4
+ * @version $Id: IEEE754rUtils.java 491076 2006-12-29 18:48:37Z bayard $
+ */
+public class IEEE754rUtils {
+
+ /**
+ * <p>Returns the minimum value in an array.</p>
+ *
+ * @param array an array, must not be null or empty
+ * @return the minimum value in the array
+ * @throws IllegalArgumentException if <code>array</code> is
<code>null</code>
+ * @throws IllegalArgumentException if <code>array</code> is empty
+ */
+ public static double min(double[] array) {
+ // Validates input
+ if (array == null) {
+ throw new IllegalArgumentException("The Array must not be null");
+ } else if (array.length == 0) {
+ throw new IllegalArgumentException("Array cannot be empty.");
+ }
+
+ // Finds and returns min
+ double min = array[0];
+ for (int i = 1; i < array.length; i++) {
+ min = min(array[i], min);
+ }
+
+ return min;
+ }
+
+ /**
+ * <p>Returns the minimum value in an array.</p>
+ *
+ * @param array an array, must not be null or empty
+ * @return the minimum value in the array
+ * @throws IllegalArgumentException if <code>array</code> is
<code>null</code>
+ * @throws IllegalArgumentException if <code>array</code> is empty
+ */
+ public static float min(float[] array) {
+ // Validates input
+ if (array == null) {
+ throw new IllegalArgumentException("The Array must not be null");
+ } else if (array.length == 0) {
+ throw new IllegalArgumentException("Array cannot be empty.");
+ }
+
+ // Finds and returns min
+ float min = array[0];
+ for (int i = 1; i < array.length; i++) {
+ min = min(array[i], min);
+ }
+
+ return min;
+ }
+
+ /**
+ * <p>Gets the minimum of three <code>double</code> values.</p>
+ *
+ * <p>NaN is only returned if all numbers are NaN as per IEEE-754r. </p>
+ *
+ * @param a value 1
+ * @param b value 2
+ * @param c value 3
+ * @return the smallest of the values
+ */
+ public static double min(double a, double b, double c) {
+ return min(min(a, b), c);
+ }
+
+ /**
+ * <p>Gets the minimum of two <code>double</code> values.</p>
+ *
+ * <p>NaN is only returned if all numbers are NaN as per IEEE-754r. </p>
+ *
+ * @param a value 1
+ * @param b value 2
+ * @return the smallest of the values
+ */
+ public static double min(double a, double b) {
+ if(Double.isNaN(a)) {
+ return b;
+ } else
+ if(Double.isNaN(b)) {
+ return a;
+ } else {
+ return Math.min(a, b);
+ }
+ }
+
+ /**
+ * <p>Gets the minimum of three <code>float</code> values.</p>
+ *
+ * <p>NaN is only returned if all numbers are NaN as per IEEE-754r. </p>
+ *
+ * @param a value 1
+ * @param b value 2
+ * @param c value 3
+ * @return the smallest of the values
+ */
+ public static float min(float a, float b, float c) {
+ return min(min(a, b), c);
+ }
+
+ /**
+ * <p>Gets the minimum of two <code>float</code> values.</p>
+ *
+ * <p>NaN is only returned if all numbers are NaN as per IEEE-754r. </p>
+ *
+ * @param a value 1
+ * @param b value 2
+ * @return the smallest of the values
+ */
+ public static float min(float a, float b) {
+ if(Float.isNaN(a)) {
+ return b;
+ } else
+ if(Float.isNaN(b)) {
+ return a;
+ } else {
+ return Math.min(a, b);
+ }
+ }
+
+ /**
+ * <p>Returns the maximum value in an array.</p>
+ *
+ * @param array an array, must not be null or empty
+ * @return the minimum value in the array
+ * @throws IllegalArgumentException if <code>array</code> is
<code>null</code>
+ * @throws IllegalArgumentException if <code>array</code> is empty
+ */
+ public static double max(double[] array) {
+ // Validates input
+ if (array== null) {
+ throw new IllegalArgumentException("The Array must not be null");
+ } else if (array.length == 0) {
+ throw new IllegalArgumentException("Array cannot be empty.");
+ }
+
+ // Finds and returns max
+ double max = array[0];
+ for (int j = 1; j < array.length; j++) {
+ max = max(array[j], max);
+ }
+
+ return max;
+ }
+
+ /**
+ * <p>Returns the maximum value in an array.</p>
+ *
+ * @param array an array, must not be null or empty
+ * @return the minimum value in the array
+ * @throws IllegalArgumentException if <code>array</code> is
<code>null</code>
+ * @throws IllegalArgumentException if <code>array</code> is empty
+ */
+ public static float max(float[] array) {
+ // Validates input
+ if (array == null) {
+ throw new IllegalArgumentException("The Array must not be null");
+ } else if (array.length == 0) {
+ throw new IllegalArgumentException("Array cannot be empty.");
+ }
+
+ // Finds and returns max
+ float max = array[0];
+ for (int j = 1; j < array.length; j++) {
+ max = max(array[j], max);
+ }
+
+ return max;
+ }
+
+ /**
+ * <p>Gets the maximum of three <code>double</code> values.</p>
+ *
+ * <p>NaN is only returned if all numbers are NaN as per IEEE-754r. </p>
+ *
+ * @param a value 1
+ * @param b value 2
+ * @param c value 3
+ * @return the largest of the values
+ */
+ public static double max(double a, double b, double c) {
+ return max(max(a, b), c);
+ }
+
+ /**
+ * <p>Gets the maximum of two <code>double</code> values.</p>
+ *
+ * <p>NaN is only returned if all numbers are NaN as per IEEE-754r. </p>
+ *
+ * @param a value 1
+ * @param b value 2
+ * @return the largest of the values
+ */
+ public static double max(double a, double b) {
+ if(Double.isNaN(a)) {
+ return b;
+ } else
+ if(Double.isNaN(b)) {
+ return a;
+ } else {
+ return Math.max(a, b);
+ }
+ }
+
+ /**
+ * <p>Gets the maximum of three <code>float</code> values.</p>
+ *
+ * <p>NaN is only returned if all numbers are NaN as per IEEE-754r. </p>
+ *
+ * @param a value 1
+ * @param b value 2
+ * @param c value 3
+ * @return the largest of the values
+ */
+ public static float max(float a, float b, float c) {
+ return max(max(a, b), c);
+ }
+
+ /**
+ * <p>Gets the maximum of two <code>float</code> values.</p>
+ *
+ * <p>NaN is only returned if all numbers are NaN as per IEEE-754r. </p>
+ *
+ * @param a value 1
+ * @param b value 2
+ * @return the largest of the values
+ */
+ public static float max(float a, float b) {
+ if(Float.isNaN(a)) {
+ return b;
+ } else
+ if(Float.isNaN(b)) {
+ return a;
+ } else {
+ return Math.max(a, b);
+ }
+ }
+
+}
Propchange:
commons/proper/lang/trunk/src/java/org/apache/commons/lang/math/IEEE754rUtils.java
------------------------------------------------------------------------------
svn:eol-style = native
Modified:
commons/proper/lang/trunk/src/java/org/apache/commons/lang/math/NumberUtils.java
URL:
http://svn.apache.org/viewvc/commons/proper/lang/trunk/src/java/org/apache/commons/lang/math/NumberUtils.java?rev=609475&r1=609474&r2=609475&view=diff
==============================================================================
---
commons/proper/lang/trunk/src/java/org/apache/commons/lang/math/NumberUtils.java
(original)
+++
commons/proper/lang/trunk/src/java/org/apache/commons/lang/math/NumberUtils.java
Sun Jan 6 15:58:59 2008
@@ -783,6 +783,7 @@
* @return the minimum value in the array
* @throws IllegalArgumentException if <code>array</code> is
<code>null</code>
* @throws IllegalArgumentException if <code>array</code> is empty
+ * @see IEEE754rUtils#min(double[]) IEEE754rUtils for a version of this
method that handles NaN differently
*/
public static double min(double[] array) {
// Validates input
@@ -795,6 +796,9 @@
// Finds and returns min
double min = array[0];
for (int i = 1; i < array.length; i++) {
+ if (Double.isNaN(array[i])) {
+ return Double.NaN;
+ }
if (array[i] < min) {
min = array[i];
}
@@ -810,6 +814,7 @@
* @return the minimum value in the array
* @throws IllegalArgumentException if <code>array</code> is
<code>null</code>
* @throws IllegalArgumentException if <code>array</code> is empty
+ * @see IEEE754rUtils#min(float[]) IEEE754rUtils for a version of this
method that handles NaN differently
*/
public static float min(float[] array) {
// Validates input
@@ -822,6 +827,9 @@
// Finds and returns min
float min = array[0];
for (int i = 1; i < array.length; i++) {
+ if (Float.isNaN(array[i])) {
+ return Float.NaN;
+ }
if (array[i] < min) {
min = array[i];
}
@@ -947,6 +955,7 @@
* @return the minimum value in the array
* @throws IllegalArgumentException if <code>array</code> is
<code>null</code>
* @throws IllegalArgumentException if <code>array</code> is empty
+ * @see IEEE754rUtils#max(double[]) IEEE754rUtils for a version of this
method that handles NaN differently
*/
public static double max(double[] array) {
// Validates input
@@ -959,6 +968,9 @@
// Finds and returns max
double max = array[0];
for (int j = 1; j < array.length; j++) {
+ if (Double.isNaN(array[j])) {
+ return Double.NaN;
+ }
if (array[j] > max) {
max = array[j];
}
@@ -974,6 +986,7 @@
* @return the minimum value in the array
* @throws IllegalArgumentException if <code>array</code> is
<code>null</code>
* @throws IllegalArgumentException if <code>array</code> is empty
+ * @see IEEE754rUtils#max(float[]) IEEE754rUtils for a version of this
method that handles NaN differently
*/
public static float max(float[] array) {
// Validates input
@@ -986,6 +999,9 @@
// Finds and returns max
float max = array[0];
for (int j = 1; j < array.length; j++) {
+ if (Float.isNaN(array[j])) {
+ return Float.NaN;
+ }
if (array[j] > max) {
max = array[j];
}
@@ -1078,6 +1094,7 @@
* @param b value 2
* @param c value 3
* @return the smallest of the values
+ * @see IEEE754rUtils#min(double, double, double) for a version of this
method that handles NaN differently
*/
public static double min(double a, double b, double c) {
return Math.min(Math.min(a, b), c);
@@ -1093,6 +1110,7 @@
* @param b value 2
* @param c value 3
* @return the smallest of the values
+ * @see IEEE754rUtils#min(float, float, float) for a version of this
method that handles NaN differently
*/
public static float min(float a, float b, float c) {
return Math.min(Math.min(a, b), c);
@@ -1182,6 +1200,7 @@
* @param b value 2
* @param c value 3
* @return the largest of the values
+ * @see IEEE754rUtils#max(double, double, double) for a version of this
method that handles NaN differently
*/
public static double max(double a, double b, double c) {
return Math.max(Math.max(a, b), c);
@@ -1197,6 +1216,7 @@
* @param b value 2
* @param c value 3
* @return the largest of the values
+ * @see IEEE754rUtils#max(float, float, float) for a version of this
method that handles NaN differently
*/
public static float max(float a, float b, float c) {
return Math.max(Math.max(a, b), c);
Added:
commons/proper/lang/trunk/src/test/org/apache/commons/lang/math/IEEE754rUtilsTest.java
URL:
http://svn.apache.org/viewvc/commons/proper/lang/trunk/src/test/org/apache/commons/lang/math/IEEE754rUtilsTest.java?rev=609475&view=auto
==============================================================================
---
commons/proper/lang/trunk/src/test/org/apache/commons/lang/math/IEEE754rUtilsTest.java
(added)
+++
commons/proper/lang/trunk/src/test/org/apache/commons/lang/math/IEEE754rUtilsTest.java
Sun Jan 6 15:58:59 2008
@@ -0,0 +1,53 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.lang.math;
+
+import junit.framework.TestCase;
+
+/**
+ * Unit tests [EMAIL PROTECTED] org.apache.commons.lang.math.IEEE754rUtils}.
+ *
+ * @version $Id: IEEE754rUtilsTest.java 583665 2007-10-11 01:34:13Z ggregory $
+ */
+public class IEEE754rUtilsTest extends TestCase {
+
+ public void testLang381() {
+ assertEquals(1.2, IEEE754rUtils.min(1.2, 2.5, Double.NaN), 0.01);
+ assertEquals(2.5, IEEE754rUtils.max(1.2, 2.5, Double.NaN), 0.01);
+ assertTrue(Double.isNaN(IEEE754rUtils.max(Double.NaN, Double.NaN,
Double.NaN)));
+ assertEquals(1.2f, IEEE754rUtils.min(1.2f, 2.5f, Float.NaN), 0.01);
+ assertEquals(2.5f, IEEE754rUtils.max(1.2f, 2.5f, Float.NaN), 0.01);
+ assertTrue(Float.isNaN(IEEE754rUtils.max(Float.NaN, Float.NaN,
Float.NaN)));
+
+ double[] a = new double[] { 1.2, Double.NaN, 3.7, 27.0, 42.0,
Double.NaN };
+ assertEquals(42.0, IEEE754rUtils.max(a), 0.01);
+ assertEquals(1.2, IEEE754rUtils.min(a), 0.01);
+
+ double[] b = new double[] { Double.NaN, 1.2, Double.NaN, 3.7, 27.0,
42.0, Double.NaN };
+ assertEquals(42.0, IEEE754rUtils.max(b), 0.01);
+ assertEquals(1.2, IEEE754rUtils.min(b), 0.01);
+
+ float[] aF = new float[] { 1.2f, Float.NaN, 3.7f, 27.0f, 42.0f,
Float.NaN };
+ assertEquals(1.2f, IEEE754rUtils.min(aF), 0.01);
+ assertEquals(42.0f, IEEE754rUtils.max(aF), 0.01);
+
+ float[] bF = new float[] { Float.NaN, 1.2f, Float.NaN, 3.7f, 27.0f,
42.0f, Float.NaN };
+ assertEquals(1.2f, IEEE754rUtils.min(bF), 0.01);
+ assertEquals(42.0f, IEEE754rUtils.max(bF), 0.01);
+ }
+
+}
Propchange:
commons/proper/lang/trunk/src/test/org/apache/commons/lang/math/IEEE754rUtilsTest.java
------------------------------------------------------------------------------
svn:eol-style = native
Modified:
commons/proper/lang/trunk/src/test/org/apache/commons/lang/math/NumberUtilsTest.java
URL:
http://svn.apache.org/viewvc/commons/proper/lang/trunk/src/test/org/apache/commons/lang/math/NumberUtilsTest.java?rev=609475&r1=609474&r2=609475&view=diff
==============================================================================
---
commons/proper/lang/trunk/src/test/org/apache/commons/lang/math/NumberUtilsTest.java
(original)
+++
commons/proper/lang/trunk/src/test/org/apache/commons/lang/math/NumberUtilsTest.java
Sun Jan 6 15:58:59 2008
@@ -1183,5 +1183,26 @@
NumberUtils.createNumber("01l");
NumberUtils.createNumber("1l");
}
+
+ public void testLang381() {
+ assertTrue(Double.isNaN(NumberUtils.min(1.2, 2.5, Double.NaN)));
+ assertTrue(Double.isNaN(NumberUtils.max(1.2, 2.5, Double.NaN)));
+ assertTrue(Float.isNaN(NumberUtils.min(1.2f, 2.5f, Float.NaN)));
+ assertTrue(Float.isNaN(NumberUtils.max(1.2f, 2.5f, Float.NaN)));
+
+ double[] a = new double[] { 1.2, Double.NaN, 3.7, 27.0, 42.0,
Double.NaN };
+ assertTrue(Double.isNaN(NumberUtils.max(a)));
+ assertTrue(Double.isNaN(NumberUtils.min(a)));
+
+ double[] b = new double[] { Double.NaN, 1.2, Double.NaN, 3.7, 27.0,
42.0, Double.NaN };
+ assertTrue(Double.isNaN(NumberUtils.max(b)));
+ assertTrue(Double.isNaN(NumberUtils.min(b)));
+
+ float[] aF = new float[] { 1.2f, Float.NaN, 3.7f, 27.0f, 42.0f,
Float.NaN };
+ assertTrue(Float.isNaN(NumberUtils.max(aF)));
+
+ float[] bF = new float[] { Float.NaN, 1.2f, Float.NaN, 3.7f, 27.0f,
42.0f, Float.NaN };
+ assertTrue(Float.isNaN(NumberUtils.max(bF)));
+ }
}