mirror of
https://github.com/apache/commons-math.git
synced 2025-02-14 05:56:10 +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. */
|
/** Constant for decreasing direction. */
|
||||||
DECREASING
|
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.
|
* Check that the given array is sorted.
|
||||||
@ -1964,30 +2058,40 @@ public final class MathUtils {
|
|||||||
public static boolean checkOrder(double[] val, OrderDirection dir,
|
public static boolean checkOrder(double[] val, OrderDirection dir,
|
||||||
boolean strict, boolean abort) {
|
boolean strict, boolean abort) {
|
||||||
double previous = val[0];
|
double previous = val[0];
|
||||||
boolean ok = true;
|
|
||||||
|
|
||||||
int max = val.length;
|
int max = val.length;
|
||||||
for (int i = 1; i < max; i++) {
|
for (int i = 1; i < max; i++) {
|
||||||
switch (dir) {
|
switch (dir) {
|
||||||
case INCREASING:
|
case INCREASING:
|
||||||
if (strict) {
|
if (strict) {
|
||||||
if (val[i] <= previous) {
|
if (val[i] <= previous) {
|
||||||
ok = false;
|
if (abort) {
|
||||||
|
throw new NonMonotonousSequenceException((Number)val[i], (Number)previous, i, dir, strict);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (val[i] < previous) {
|
if (val[i] < previous) {
|
||||||
ok = false;
|
if (abort) {
|
||||||
|
throw new NonMonotonousSequenceException((Number)val[i], (Number)previous, i, dir, strict);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case DECREASING:
|
case DECREASING:
|
||||||
if (strict) {
|
if (strict) {
|
||||||
if (val[i] >= previous) {
|
if (val[i] >= previous) {
|
||||||
ok = false;
|
if (abort) {
|
||||||
|
throw new NonMonotonousSequenceException((Number)val[i], (Number)previous, i, dir, strict);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (val[i] > previous) {
|
if (val[i] > previous) {
|
||||||
ok = false;
|
if (abort) {
|
||||||
|
throw new NonMonotonousSequenceException((Number)val[i], (Number)previous, i, dir, strict);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@ -1995,15 +2099,9 @@ public final class MathUtils {
|
|||||||
// Should never happen.
|
// Should never happen.
|
||||||
throw new IllegalArgumentException();
|
throw new IllegalArgumentException();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!ok &&
|
|
||||||
abort) {
|
|
||||||
throw new NonMonotonousSequenceException(val[i], previous, i, dir, strict);
|
|
||||||
}
|
|
||||||
previous = val[i];
|
previous = val[i];
|
||||||
}
|
}
|
||||||
|
return true;
|
||||||
return ok;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -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!
|
If the output is not quite correct, check for invisible trailing spaces!
|
||||||
-->
|
-->
|
||||||
<release version="3.0" date="TBD" description="TBD">
|
<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">
|
<action dev="erans" type="fix" issue="MATH-664">
|
||||||
In class "AbstractLeastSquaresOptimizer": Allow to specify a singularity
|
In class "AbstractLeastSquaresOptimizer": Allow to specify a singularity
|
||||||
threshold in call to "getCovariances" method.
|
threshold in call to "getCovariances" method.
|
||||||
|
@ -1087,7 +1087,7 @@ public final class MathUtilsTest {
|
|||||||
Assert.assertEquals(expected,
|
Assert.assertEquals(expected,
|
||||||
MathUtils.reduce(orig, -period, offset),
|
MathUtils.reduce(orig, -period, offset),
|
||||||
1e-6);
|
1e-6);
|
||||||
|
|
||||||
Assert.assertTrue(Double.isNaN(MathUtils.reduce(orig, Double.NaN, offset)));
|
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(Double.NaN, period, offset)));
|
||||||
Assert.assertTrue(Double.isNaN(MathUtils.reduce(orig, period, Double.NaN)));
|
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,
|
Assert.assertTrue(Double.isNaN(MathUtils.reduce(Double.POSITIVE_INFINITY,
|
||||||
period, offset)));
|
period, offset)));
|
||||||
Assert.assertTrue(Double.isNaN(MathUtils.reduce(orig,
|
Assert.assertTrue(Double.isNaN(MathUtils.reduce(orig,
|
||||||
Double.POSITIVE_INFINITY, offset)));
|
Double.POSITIVE_INFINITY, offset)));
|
||||||
Assert.assertTrue(Double.isNaN(MathUtils.reduce(orig,
|
Assert.assertTrue(Double.isNaN(MathUtils.reduce(orig,
|
||||||
Double.POSITIVE_INFINITY, Double.POSITIVE_INFINITY)));
|
Double.POSITIVE_INFINITY, Double.POSITIVE_INFINITY)));
|
||||||
Assert.assertTrue(Double.isNaN(MathUtils.reduce(Double.POSITIVE_INFINITY,
|
Assert.assertTrue(Double.isNaN(MathUtils.reduce(Double.POSITIVE_INFINITY,
|
||||||
period, Double.POSITIVE_INFINITY)));
|
period, Double.POSITIVE_INFINITY)));
|
||||||
Assert.assertTrue(Double.isNaN(MathUtils.reduce(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,
|
Assert.assertTrue(Double.isNaN(MathUtils.reduce(Double.POSITIVE_INFINITY,
|
||||||
Double.POSITIVE_INFINITY, Double.POSITIVE_INFINITY)));
|
Double.POSITIVE_INFINITY, Double.POSITIVE_INFINITY)));
|
||||||
}
|
}
|
||||||
@ -1251,7 +1251,7 @@ public final class MathUtilsTest {
|
|||||||
try {
|
try {
|
||||||
MathUtils.round(1.234, 2, BigDecimal.ROUND_UNNECESSARY);
|
MathUtils.round(1.234, 2, BigDecimal.ROUND_UNNECESSARY);
|
||||||
Assert.fail();
|
Assert.fail();
|
||||||
} catch (ArithmeticException ex) {
|
} catch (ArithmeticException ex) {
|
||||||
// expected
|
// 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
|
@Test
|
||||||
public void testCheckFinite() {
|
public void testCheckFinite() {
|
||||||
try {
|
try {
|
||||||
@ -1696,7 +1742,7 @@ public final class MathUtilsTest {
|
|||||||
final double[] x1 = {2, 5, -3, 1, 4};
|
final double[] x1 = {2, 5, -3, 1, 4};
|
||||||
final double[] x2 = {4, 25, 9, 1, 16};
|
final double[] x2 = {4, 25, 9, 1, 16};
|
||||||
final double[] x3 = {8, 125, -27, 1, 64};
|
final double[] x3 = {8, 125, -27, 1, 64};
|
||||||
|
|
||||||
MathUtils.sortInPlace(x1, x2, x3);
|
MathUtils.sortInPlace(x1, x2, x3);
|
||||||
|
|
||||||
Assert.assertEquals(-3, x1[0], Math.ulp(1d));
|
Assert.assertEquals(-3, x1[0], Math.ulp(1d));
|
||||||
|
Loading…
x
Reference in New Issue
Block a user