/** * Copyright (C) 2014-2016 LinkedIn Corp. (pinot-core@linkedin.com) * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.linkedin.pinot.core.operator.filter; import com.google.common.base.Preconditions; import com.linkedin.pinot.common.utils.Pairs; /** * Various utilities to deal with integer ranges, with both bounds being inclusive (eg. for docId ranges). */ public class IntRanges { private static final boolean ENABLE_PRECONDITION_CHECKS = false; /** * Clips a range in place, making sure that its lower value is greater or equals to lowerBound and its upper value is * smaller or equals to upperBound. * * @param range The range to clip * @param lowerBound The lower bound * @param upperBound The upper bound */ public static void clip(Pairs.IntPair range, int lowerBound, int upperBound) { range.setLeft(Math.max(range.getLeft(), lowerBound)); range.setRight(Math.min(range.getRight(), upperBound)); } /** * Checks whether a range is invalid (upper bound lower to the lower bound) * * @return true if the range is invalid */ public static boolean isInvalid(Pairs.IntPair range) { return range.getRight() < range.getLeft(); } /** * Checks whether two ranges are mergeable (either overlapping or adjacent), assuming neither is degenerate. * * @param firstRange The first range to check * @param secondRange The second range to check */ public static boolean rangesAreMergeable(Pairs.IntPair firstRange, Pairs.IntPair secondRange) { if (ENABLE_PRECONDITION_CHECKS) { Preconditions.checkArgument(!isInvalid(firstRange)); Preconditions.checkArgument(!isInvalid(secondRange)); } final boolean rangesAreAtLeastOneUnitApart = firstRange.getRight() < secondRange.getLeft() - 1 || secondRange.getRight() < firstRange.getLeft() - 1; return !rangesAreAtLeastOneUnitApart; } /** * Merge the second range into the first one, mutating the first one in place, assuming the ranges are not disjoint. * * @param firstRange The range to merge the second into * @param secondRange The range to merge with the first one */ public static void mergeIntoFirst(Pairs.IntPair firstRange, Pairs.IntPair secondRange) { if (ENABLE_PRECONDITION_CHECKS) { Preconditions.checkArgument(rangesAreMergeable(firstRange, secondRange)); } firstRange.setLeft(Math.min(firstRange.getLeft(), secondRange.getLeft())); firstRange.setRight(Math.max(firstRange.getRight(), secondRange.getRight())); } }