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.
git-svn-id: https://svn.apache.org/repos/asf/commons/proper/lang/trunk@609475 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
ea4ce16289
commit
bee5b923c5
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -783,6 +783,7 @@ public class NumberUtils {
|
|||
* @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 @@ public class NumberUtils {
|
|||
// 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 @@ public class NumberUtils {
|
|||
* @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 @@ public class NumberUtils {
|
|||
// 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 @@ public class NumberUtils {
|
|||
* @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 @@ public class NumberUtils {
|
|||
// 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 @@ public class NumberUtils {
|
|||
* @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 @@ public class NumberUtils {
|
|||
// 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 @@ public class NumberUtils {
|
|||
* @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 @@ public class NumberUtils {
|
|||
* @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 @@ public class NumberUtils {
|
|||
* @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 @@ public class NumberUtils {
|
|||
* @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);
|
||||
|
|
|
@ -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 {@link 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);
|
||||
}
|
||||
|
||||
}
|
|
@ -1184,4 +1184,25 @@ public class NumberUtilsTest extends TestCase {
|
|||
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)));
|
||||
}
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue