package geniusweb.bidspace; import java.math.BigDecimal; import java.math.RoundingMode; import org.eclipse.jdt.annotation.NonNull; /** * An interval [min, max]. * */ public class Interval { public static @NonNull Interval ZERO = new Interval(BigDecimal.ZERO, BigDecimal.ZERO); public static @NonNull Interval EMPTY = new Interval(BigDecimal.ONE, BigDecimal.ZERO); private final @NonNull BigDecimal min; private final @NonNull BigDecimal max; /** * AN interval [min,max]. If min > max, then there are no values in this * interval. * * @param min the minimum value of the interval (inclusive) * @param max the maximum value of the interval (inclusive) */ public Interval(@NonNull BigDecimal min, @NonNull BigDecimal max) { if (min == null || max == null) { throw new NullPointerException("min and max must contain not null"); } this.min = min; this.max = max; } /** * * @return the minimum value of the interval */ public @NonNull BigDecimal getMin() { return min; } /** * * @return the maximum value of the interval */ public @NonNull BigDecimal getMax() { return max; } /** * * @return true iff this range does not contain any element. */ public boolean isEmpty() { return min.compareTo(max) > 0; } /** * * @param value the value to test * @return true iff min ≤ value ≤ max */ public boolean contains(@NonNull BigDecimal value) { return min.compareTo(value) <= 0 && max.compareTo(value) >= 0; } /** * * @param other {@link Interval} to be added to this * @return new interval [ this.min + other.min , this.max + other.max ] */ public @NonNull Interval add(@NonNull Interval other) { return new Interval(min.add(other.min), max.add(other.max)); } /** * * @param other another {@link Interval} intersect with * @return intersection of this with other. returns null if intersection is * empty. */ public @NonNull Interval intersect(@NonNull Interval other) { return new Interval(min.max(other.min), max.min(other.max)); } /** * * @param other the other minmax to deal with * @return the range of values that, when added to a value from other, will * possibly get in our range. effectively, [min-other.max, * max-other.min]. Returns {@link #EMPTY} if the resulting range is * empty. */ public @NonNull Interval invert(@NonNull Interval other) { final @NonNull BigDecimal newmin = min.subtract(other.max); final @NonNull BigDecimal newmax = max.subtract(other.min); if (newmin.compareTo(newmax) > 0) return EMPTY; return new Interval(newmin, newmax); } /** * * @param value the value to subtract * @return Interval with both min and max reduced by value. */ public @NonNull Interval subtract(@NonNull BigDecimal value) { return new Interval(min.subtract(value), max.subtract(value)); } public @NonNull Interval multiply(@NonNull BigDecimal weight) { return new Interval(min.multiply(weight), max.multiply(weight)); } @Override public @NonNull String toString() { return "Interval[" + min + "," + max + "]"; } /** * @param precision number of digits required * @return this but with modified precision. The interval is rounded so that * the new interval is inside the old one. */ public @NonNull Interval round(int precision) { return new Interval(min.setScale(precision, RoundingMode.UP), max.setScale(precision, RoundingMode.DOWN)); } @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + ((max == null) ? 0 : max.hashCode()); result = prime * result + ((min == null) ? 0 : min.hashCode()); return result; } @Override public boolean equals(Object obj) { if (this == obj) return true; if (obj == null) return false; if (getClass() != obj.getClass()) return false; Interval other = (Interval) obj; if (max == null) { if (other.max != null) return false; } else if (max.compareTo(other.max) != 0) // THIS WAS FIXED MANUALLY TO USE COMPARETO return false; if (min == null) { if (other.min != null) return false; } else if (min.compareTo(other.min) != 0) // THIS WAS FIXED MANUALLY TO USE COMPARETO return false; return true; } }