LongRangeSet (@NotNull LongRangeSet other) { if (other.isEmpty() || other == this) return this; if (other instanceof Point) { return other.join(this); } if (other instanceof Range) { if (other.min() <= max() && min() <= other.max() || (other.max() < min() && other.max() + 1 == min()) || (other.min() > max() && max() + 1 == other.min())) { return range(Math.min(min(), other.min()), Math.max(max(), other.max())); } if (other.max() < min()) { return new RangeSet(new long[]{other.min(), other.max(), min(), max()}); } return new RangeSet(new long[]{min(), max(), other.min(), other.max()}); } long[] longs = other.asRangeArray(); int minIndex = Arrays.binarySearch(longs, min()); if (minIndex < 0) { minIndex = -minIndex - 1; if (minIndex % 2 == 0 && minIndex > 0 && longs[minIndex - 1] + 1 == min()) { minIndex--; } } else if (minIndex % 2 == 0) { minIndex++; } int maxIndex = Arrays.binarySearch(longs, max()); if (maxIndex < 0) { maxIndex = -maxIndex - 1; if (maxIndex % 2 == 0 && maxIndex < longs.length && max() + 1 == longs[maxIndex]) { maxIndex++; } } else if (maxIndex % 2 == 0) { maxIndex++; } long[] result = new long[longs.length + 2]; System.arraycopy(longs, 0, result, 0, minIndex); int pos = minIndex; if (minIndex % 2 == 0) { result[pos++] = min(); } if (maxIndex % 2 == 0) { result[pos++] = max(); } System.arraycopy(longs, maxIndex, result, pos, longs.length - maxIndex); return fromRanges(result, longs.length + pos - maxIndex); }