package org.apache.hadoop.corona;
/**
* Given a targetFunction and a targetValue, find a positive number x so that
* targetFunction(x) == targetValue approximately
*/
abstract public class BinarySearcher {
private final static int MAXIMUM_ITERATION = 25;
private final static double ERROR_ALLOW_WHEN_COMPARE_FLOATS = 0.01;
abstract protected double targetFunction(double x);
public double getSolution(double targetValue) {
return getSolution(targetValue, -1);
}
public double getSolution(double targetValue, double initGuess) {
double rMax = 1.0;
double oldValue = -1;
for (int i = 0; i < MAXIMUM_ITERATION; ++i) {
double value = targetFunction(rMax);
if (value >= targetValue) {
break;
}
if (equals(value, oldValue)) {
return rMax; // Target value is not feasible. Just return rMax
}
rMax *= 2;
}
double left = 0, right = rMax;
double mid = initGuess > left && initGuess < right ?
initGuess : (left + right) / 2.0;
for (int i = 0; i < MAXIMUM_ITERATION; ++i) {
double value = targetFunction(mid);
if (equals(value, targetValue)) {
return mid;
}
if (value < targetValue) {
left = mid;
} else {
right = mid;
}
mid = (left + right) / 2.0;
}
return right;
}
private static boolean equals(double x, double y) {
return Math.abs(x - y) < ERROR_ALLOW_WHEN_COMPARE_FLOATS;
}
}