Added normalizeArray method to MathUtils.

git-svn-id: https://svn.apache.org/repos/asf/commons/proper/math/trunk@809394 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Phil Steitz 2009-08-30 18:10:16 +00:00
parent ad6960636a
commit e89db38df8
3 changed files with 107 additions and 0 deletions

View File

@ -987,6 +987,62 @@ public final class MathUtils {
public static double normalizeAngle(double a, double center) {
return a - TWO_PI * Math.floor((a + Math.PI - center) / TWO_PI);
}
/**
* <p>Normalizes an array to make it sum to a specified value.
* Returns the result of the transformation <pre>
* x |-> x * normalizedSum / sum
* </pre>
* applied to each non-NaN element x of the input array, where sum is the
* sum of the non-NaN entries in the input array.</p>
*
* <p>Throws IllegalArgumentException if <code>normalizedSum</code> is infinite
* or NaN and ArithmeticException if the input array contains any infinite elements
* or sums to 0</p>
*
* <p>Ignores (i.e., copies unchanged to the output array) NaNs in the input array.</p>
*
* @param values input array to be normalized
* @param normalizedSum target sum for the normalized array
* @return normalized array
* @throws ArithmeticException if the input array contains infinite elements or sums to zero
* @throws IllegalArgumentException if the target sum is infinite or NaN
*/
public static double[] normalizeArray(double[] values, double normalizedSum)
throws ArithmeticException, IllegalArgumentException {
if (Double.isInfinite(normalizedSum)) {
throw MathRuntimeException.createIllegalArgumentException(
"Cannot normalize to an infinite value");
}
if (Double.isNaN(normalizedSum)) {
throw MathRuntimeException.createIllegalArgumentException(
"Cannot normalize to NaN");
}
double sum = 0d;
final int len = values.length;
double[] out = new double[len];
for (int i = 0; i < len; i++) {
if (Double.isInfinite(values[i])) {
throw MathRuntimeException.createArithmeticException(
"Array contains an infinite element", values[i], i);
}
if (!Double.isNaN(values[i])) {
sum += values[i];
}
}
if (sum == 0) {
throw MathRuntimeException.createArithmeticException(
"Array sums to zero");
}
for (int i = 0; i < len; i++) {
if (Double.isNaN(values[i])) {
out[i] = Double.NaN;
} else {
out[i] = values[i] * normalizedSum / sum;
}
}
return out;
}
/**
* Round the given value to the specified number of decimal places. The

View File

@ -39,6 +39,9 @@ The <action> type attribute can be add,update,fix,remove.
</properties>
<body>
<release version="2.1" date="TBD" description="TBD">
<action dev="psteitz" type="add">
Added normalizeArray method to MathUtils.
</action>
<action dev="luc" type="fix" issue="MATH-290" due-to="Benjamin McCann">
Fixed a NullPointerException in simplex solver when no solution is possible
and some constraints are negative.

View File

@ -796,6 +796,54 @@ public final class MathUtilsTest extends TestCase {
}
}
}
public void testNormalizeArray() {
double[] testValues1 = new double[] {1, 1, 2};
TestUtils.assertEquals(
new double[] {.25, .25, .5},
MathUtils.normalizeArray(testValues1, 1),
Double.MIN_VALUE);
double[] testValues2 = new double[] {-1, -1, 1};
TestUtils.assertEquals(
new double[] {1, 1, -1},
MathUtils.normalizeArray(testValues2, 1),
Double.MIN_VALUE);
// Ignore NaNs
double[] testValues3 = new double[] {-1, -1, Double.NaN, 1, Double.NaN};
TestUtils.assertEquals(
new double[] {1, 1,Double.NaN, -1, Double.NaN},
MathUtils.normalizeArray(testValues3, 1),
Double.MIN_VALUE);
// Zero sum -> ArithmeticException
double[] zeroSum = new double[] {-1, 1};
try {
MathUtils.normalizeArray(zeroSum, 1);
fail("expecting ArithmeticException");
} catch (ArithmeticException ex) {}
// Infinite elements -> ArithmeticException
double[] hasInf = new double[] {1, 2, 1, Double.NEGATIVE_INFINITY};
try {
MathUtils.normalizeArray(hasInf, 1);
fail("expecting ArithmeticException");
} catch (ArithmeticException ex) {}
// Infinite target -> IllegalArgumentException
try {
MathUtils.normalizeArray(testValues1, Double.POSITIVE_INFINITY);
fail("expecting IllegalArgumentException");
} catch (IllegalArgumentException ex) {}
// NaN target -> IllegalArgumentException
try {
MathUtils.normalizeArray(testValues1, Double.NaN);
fail("expecting IllegalArgumentException");
} catch (IllegalArgumentException ex) {}
}
public void testRoundDouble() {
double x = 1.234567890;