BinarySearch { public static <T> T find(DoubleFunction<T> pointAtValue, ToDoubleFunction<T> comparator, double lowerBound, double upperBound) { Preconditions.checkArgument(lowerBound <= upperBound, "lower bound " + lowerBound + " must not be greater than upper bound " + upperBound); T lowerBoundPoint = pointAtValue.apply(lowerBound); double lowerBoundComp = comparator.applyAsDouble(lowerBoundPoint); if (lowerBoundComp == 0) { return lowerBoundPoint; } Preconditions.checkArgument(lowerBoundComp < 0, "Invalid search parameter"); T upperBoundPoint = pointAtValue.apply(upperBound); double upperBoundComp = comparator.applyAsDouble(upperBoundPoint); if (upperBoundComp == 0) { return upperBoundPoint; } Preconditions.checkArgument(upperBoundComp > 0, "Invalid search parameter"); while (true) { double mid = (lowerBound + upperBound) / 2.0; T newPoint = pointAtValue.apply(mid); double comp = comparator.applyAsDouble(newPoint); Preconditions.checkState(mid > lowerBound && mid < upperBound); if (comp == 0) { return newPoint; } else if (comp < 0) { lowerBound = mid; } else { upperBound = mid; } } } private  BinarySearch(); static T find(DoubleFunction<T> pointAtValue, ToDoubleFunction<T> comparator, double lowerBound, double upperBound);  }
@Test void find_whenLowerBoundIsGreaterThanUpperBound_thenThrowsException() { assertThatThrownBy(() -> BinarySearch.find(BinarySearchTest::getRangeForValue, r -> 0, 10, 5)) .isInstanceOf(IllegalArgumentException.class); }