mirror of
https://github.com/apache/commons-math.git
synced 2025-02-11 12:36:05 +00:00
JIRA: MATH-675 Added isMonotone methods to MathUtils and cleaned up checkOrder.
git-svn-id: https://svn.apache.org/repos/asf/commons/proper/math/trunk@1173974 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
041df9cd9b
commit
cc40bb40a9
@ -1949,6 +1949,100 @@ public final class MathUtils {
|
||||
/** Constant for decreasing direction. */
|
||||
DECREASING
|
||||
}
|
||||
/**
|
||||
* Check that an array is monotone increasing or decreasing
|
||||
*
|
||||
* @param val Values.
|
||||
* @param dir Ordering direction.
|
||||
* @param strict Whether the order should be strict.
|
||||
* @return {@code true} if sorted, {@code false} otherwise
|
||||
*/
|
||||
public static boolean isMonotone(Comparable[] val, OrderDirection dir,
|
||||
boolean strict){
|
||||
Comparable previous = val[0];
|
||||
int max = val.length;
|
||||
int comp;
|
||||
for (int i = 1; i < max; i++) {
|
||||
switch (dir) {
|
||||
case INCREASING:
|
||||
comp = -val[i].compareTo(previous);
|
||||
if (strict) {
|
||||
if (0 <= comp) {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
if ( comp > 0) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case DECREASING:
|
||||
comp = val[i].compareTo(previous);
|
||||
if (strict) {
|
||||
if (comp >= 0) {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
if (comp > 0) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
// Should never happen.
|
||||
throw new IllegalArgumentException();
|
||||
}
|
||||
|
||||
previous = val[i];
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check that an array is monotone increasing or decreasing
|
||||
*
|
||||
* @param val Values.
|
||||
* @param dir Ordering direction.
|
||||
* @param strict Whether the order should be strict.
|
||||
* @return {@code true} if sorted, {@code false} otherwise
|
||||
*/
|
||||
public static boolean isMonotone( double[] val, OrderDirection dir,
|
||||
boolean strict){
|
||||
double previous = val[0];
|
||||
int max = val.length;
|
||||
for (int i = 1; i < max; i++) {
|
||||
switch (dir) {
|
||||
case INCREASING:
|
||||
if (strict) {
|
||||
if (val[i] <= previous) {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
if (val[i] < previous) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case DECREASING:
|
||||
if (strict) {
|
||||
if (val[i] >= previous) {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
if (val[i] > previous) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
// Should never happen.
|
||||
throw new IllegalArgumentException();
|
||||
}
|
||||
previous = val[i];
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check that the given array is sorted.
|
||||
@ -1964,30 +2058,40 @@ public final class MathUtils {
|
||||
public static boolean checkOrder(double[] val, OrderDirection dir,
|
||||
boolean strict, boolean abort) {
|
||||
double previous = val[0];
|
||||
boolean ok = true;
|
||||
|
||||
int max = val.length;
|
||||
for (int i = 1; i < max; i++) {
|
||||
switch (dir) {
|
||||
case INCREASING:
|
||||
if (strict) {
|
||||
if (val[i] <= previous) {
|
||||
ok = false;
|
||||
if (abort) {
|
||||
throw new NonMonotonousSequenceException((Number)val[i], (Number)previous, i, dir, strict);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
if (val[i] < previous) {
|
||||
ok = false;
|
||||
if (abort) {
|
||||
throw new NonMonotonousSequenceException((Number)val[i], (Number)previous, i, dir, strict);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case DECREASING:
|
||||
if (strict) {
|
||||
if (val[i] >= previous) {
|
||||
ok = false;
|
||||
if (abort) {
|
||||
throw new NonMonotonousSequenceException((Number)val[i], (Number)previous, i, dir, strict);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
if (val[i] > previous) {
|
||||
ok = false;
|
||||
if (abort) {
|
||||
throw new NonMonotonousSequenceException((Number)val[i], (Number)previous, i, dir, strict);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
break;
|
||||
@ -1995,15 +2099,9 @@ public final class MathUtils {
|
||||
// Should never happen.
|
||||
throw new IllegalArgumentException();
|
||||
}
|
||||
|
||||
if (!ok &&
|
||||
abort) {
|
||||
throw new NonMonotonousSequenceException(val[i], previous, i, dir, strict);
|
||||
}
|
||||
previous = val[i];
|
||||
}
|
||||
|
||||
return ok;
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -52,6 +52,9 @@ The <action> type attribute can be add,update,fix,remove.
|
||||
If the output is not quite correct, check for invisible trailing spaces!
|
||||
-->
|
||||
<release version="3.0" date="TBD" description="TBD">
|
||||
<action dev="gregs" type="update" issue="MATH-675">
|
||||
Added isMonotone methods in MathUtils. Optimized checkOrder method.
|
||||
</action>
|
||||
<action dev="erans" type="fix" issue="MATH-664">
|
||||
In class "AbstractLeastSquaresOptimizer": Allow to specify a singularity
|
||||
threshold in call to "getCovariances" method.
|
||||
|
@ -1087,7 +1087,7 @@ public final class MathUtilsTest {
|
||||
Assert.assertEquals(expected,
|
||||
MathUtils.reduce(orig, -period, offset),
|
||||
1e-6);
|
||||
|
||||
|
||||
Assert.assertTrue(Double.isNaN(MathUtils.reduce(orig, Double.NaN, offset)));
|
||||
Assert.assertTrue(Double.isNaN(MathUtils.reduce(Double.NaN, period, offset)));
|
||||
Assert.assertTrue(Double.isNaN(MathUtils.reduce(orig, period, Double.NaN)));
|
||||
@ -1096,13 +1096,13 @@ public final class MathUtilsTest {
|
||||
Assert.assertTrue(Double.isNaN(MathUtils.reduce(Double.POSITIVE_INFINITY,
|
||||
period, offset)));
|
||||
Assert.assertTrue(Double.isNaN(MathUtils.reduce(orig,
|
||||
Double.POSITIVE_INFINITY, offset)));
|
||||
Double.POSITIVE_INFINITY, offset)));
|
||||
Assert.assertTrue(Double.isNaN(MathUtils.reduce(orig,
|
||||
Double.POSITIVE_INFINITY, Double.POSITIVE_INFINITY)));
|
||||
Assert.assertTrue(Double.isNaN(MathUtils.reduce(Double.POSITIVE_INFINITY,
|
||||
period, Double.POSITIVE_INFINITY)));
|
||||
Assert.assertTrue(Double.isNaN(MathUtils.reduce(Double.POSITIVE_INFINITY,
|
||||
Double.POSITIVE_INFINITY, offset)));
|
||||
Double.POSITIVE_INFINITY, offset)));
|
||||
Assert.assertTrue(Double.isNaN(MathUtils.reduce(Double.POSITIVE_INFINITY,
|
||||
Double.POSITIVE_INFINITY, Double.POSITIVE_INFINITY)));
|
||||
}
|
||||
@ -1251,7 +1251,7 @@ public final class MathUtilsTest {
|
||||
try {
|
||||
MathUtils.round(1.234, 2, BigDecimal.ROUND_UNNECESSARY);
|
||||
Assert.fail();
|
||||
} catch (ArithmeticException ex) {
|
||||
} catch (ArithmeticException ex) {
|
||||
// expected
|
||||
}
|
||||
|
||||
@ -1650,6 +1650,52 @@ public final class MathUtilsTest {
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIsMonotone() {
|
||||
if(MathUtils.isMonotone(new double[] {-15, -5.5, -1, -1, 2,15},
|
||||
MathUtils.OrderDirection.INCREASING, true) ){
|
||||
Assert.fail("an exception should have been thrown");
|
||||
}
|
||||
|
||||
if(MathUtils.isMonotone(new double[] {-15, -5.5,-1,-2,2},
|
||||
MathUtils.OrderDirection.INCREASING, false)){
|
||||
Assert.fail("an exception should have been thrown");
|
||||
}
|
||||
|
||||
if(MathUtils.isMonotone(new double[] {3,3,-5.5,-11,-27.5},
|
||||
MathUtils.OrderDirection.DECREASING, true)){
|
||||
Assert.fail("an exception should have been thrown");
|
||||
}
|
||||
if( MathUtils.isMonotone(new double[] {3,-1,0,-5.5,-11,-27.5},
|
||||
MathUtils.OrderDirection.DECREASING, false) ){
|
||||
Assert.fail("an exception should have been thrown");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIsMonotoneComparable() {
|
||||
if(MathUtils.isMonotone(new Double[] {new Double(-15), new Double(-5.5), new Double(-1), new Double(-1), new Double(2), new Double(15)},
|
||||
MathUtils.OrderDirection.INCREASING, true) ){
|
||||
Assert.fail("an exception should have been thrown");
|
||||
}
|
||||
|
||||
if(MathUtils.isMonotone(new Double[] {new Double(-15), new Double(-5.5), new Double(-1), new Double(-2), new Double(2)},
|
||||
MathUtils.OrderDirection.INCREASING, false)){
|
||||
Assert.fail("an exception should have been thrown");
|
||||
}
|
||||
|
||||
if(MathUtils.isMonotone(new Double[] {new Double(3), new Double(3), new Double(-5.5), new Double(-11), new Double(-27.5)},
|
||||
MathUtils.OrderDirection.DECREASING, true)){
|
||||
Assert.fail("an exception should have been thrown");
|
||||
}
|
||||
if( MathUtils.isMonotone(new Double[] {new Double(3), new Double(-1), new Double(0), new Double(-5.5), new Double(-11), new Double(-27.5)},
|
||||
MathUtils.OrderDirection.DECREASING, false) ){
|
||||
Assert.fail("an exception should have been thrown");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCheckFinite() {
|
||||
try {
|
||||
@ -1696,7 +1742,7 @@ public final class MathUtilsTest {
|
||||
final double[] x1 = {2, 5, -3, 1, 4};
|
||||
final double[] x2 = {4, 25, 9, 1, 16};
|
||||
final double[] x3 = {8, 125, -27, 1, 64};
|
||||
|
||||
|
||||
MathUtils.sortInPlace(x1, x2, x3);
|
||||
|
||||
Assert.assertEquals(-3, x1[0], Math.ulp(1d));
|
||||
|
Loading…
x
Reference in New Issue
Block a user