gap method
Returns the maximal range lying between this range and {@code otherRange}, if such a range exists. The resulting range may be empty if the two ranges are adjacent but non-overlapping.
For example, the gap of {@code [1..5]} and {@code (7..10)} is {@code (5..7]}. The resulting range may be empty; for example, the gap between {@code [1..5)} {@code [5..7)} yields the empty range {@code [5..5)}.
The gap exists if and only if the two ranges are either disconnected or immediately adjacent (any intersection must be an empty range).
The gap operation is commutative.
@throws IllegalArgumentException if this range and {@code otherRange} have a nonempty intersection @since 27.0
Implementation
Range<C> gap(Range<C> otherRange) {
/*
* For an explanation of the basic principle behind this check, see
* https://stackoverflow.com/a/35754308/28465
*
* In that explanation's notation, our `overlap` check would be `x1 < y2 && y1 < x2`. We've
* flipped one part of the check so that we're using "less than" in both cases (rather than a
* mix of "less than" and "greater than"). We've also switched to "strictly less than" rather
* than "less than or equal to" because of *handwave* the difference between "endpoints of
* inclusive ranges" and "Cuts."
*/
if (lowerBound.compareTo(otherRange.upperBound) < 0 &&
otherRange.lowerBound.compareTo(upperBound) < 0) {
throw ArgumentError(
"Ranges have a nonempty intersection: $this, $otherRange");
}
bool isThisFirst = this.lowerBound.compareTo(otherRange.lowerBound) < 0;
Range<C> firstRange = isThisFirst ? this : otherRange;
Range<C> secondRange = isThisFirst ? otherRange : this;
return create(firstRange.upperBound, secondRange.lowerBound);
}