1b3a78b2ca9655396e2d73950221d187b7e5bb3baIgor Murashkin/* 2b3a78b2ca9655396e2d73950221d187b7e5bb3baIgor Murashkin * Copyright (C) 2014 The Android Open Source Project 3b3a78b2ca9655396e2d73950221d187b7e5bb3baIgor Murashkin * 4b3a78b2ca9655396e2d73950221d187b7e5bb3baIgor Murashkin * Licensed under the Apache License, Version 2.0 (the "License"); 5b3a78b2ca9655396e2d73950221d187b7e5bb3baIgor Murashkin * you may not use this file except in compliance with the License. 6b3a78b2ca9655396e2d73950221d187b7e5bb3baIgor Murashkin * You may obtain a copy of the License at 7b3a78b2ca9655396e2d73950221d187b7e5bb3baIgor Murashkin * 8b3a78b2ca9655396e2d73950221d187b7e5bb3baIgor Murashkin * http://www.apache.org/licenses/LICENSE-2.0 9b3a78b2ca9655396e2d73950221d187b7e5bb3baIgor Murashkin * 10b3a78b2ca9655396e2d73950221d187b7e5bb3baIgor Murashkin * Unless required by applicable law or agreed to in writing, software 11b3a78b2ca9655396e2d73950221d187b7e5bb3baIgor Murashkin * distributed under the License is distributed on an "AS IS" BASIS, 12b3a78b2ca9655396e2d73950221d187b7e5bb3baIgor Murashkin * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13b3a78b2ca9655396e2d73950221d187b7e5bb3baIgor Murashkin * See the License for the specific language governing permissions and 14b3a78b2ca9655396e2d73950221d187b7e5bb3baIgor Murashkin * limitations under the License. 15b3a78b2ca9655396e2d73950221d187b7e5bb3baIgor Murashkin */ 16b3a78b2ca9655396e2d73950221d187b7e5bb3baIgor Murashkin 17b3a78b2ca9655396e2d73950221d187b7e5bb3baIgor Murashkinpackage android.util; 18b3a78b2ca9655396e2d73950221d187b7e5bb3baIgor Murashkin 19b3a78b2ca9655396e2d73950221d187b7e5bb3baIgor Murashkinimport static com.android.internal.util.Preconditions.*; 20b3a78b2ca9655396e2d73950221d187b7e5bb3baIgor Murashkin 213c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkinimport android.hardware.camera2.utils.HashCodeHelpers; 22b3a78b2ca9655396e2d73950221d187b7e5bb3baIgor Murashkin 23b3a78b2ca9655396e2d73950221d187b7e5bb3baIgor Murashkin/** 24b3a78b2ca9655396e2d73950221d187b7e5bb3baIgor Murashkin * Immutable class for describing the range of two numeric values. 25b3a78b2ca9655396e2d73950221d187b7e5bb3baIgor Murashkin * <p> 26b3a78b2ca9655396e2d73950221d187b7e5bb3baIgor Murashkin * A range (or "interval") defines the inclusive boundaries around a contiguous span of 27b3a78b2ca9655396e2d73950221d187b7e5bb3baIgor Murashkin * values of some {@link Comparable} type; for example, 28b3a78b2ca9655396e2d73950221d187b7e5bb3baIgor Murashkin * "integers from 1 to 100 inclusive." 29b3a78b2ca9655396e2d73950221d187b7e5bb3baIgor Murashkin * </p> 30b3a78b2ca9655396e2d73950221d187b7e5bb3baIgor Murashkin * <p> 31b3a78b2ca9655396e2d73950221d187b7e5bb3baIgor Murashkin * All ranges are bounded, and the left side of the range is always {@code >=} 32b3a78b2ca9655396e2d73950221d187b7e5bb3baIgor Murashkin * the right side of the range. 33b3a78b2ca9655396e2d73950221d187b7e5bb3baIgor Murashkin * </p> 34b3a78b2ca9655396e2d73950221d187b7e5bb3baIgor Murashkin * 35b3a78b2ca9655396e2d73950221d187b7e5bb3baIgor Murashkin * <p>Although the implementation itself is immutable, there is no restriction that objects 36b3a78b2ca9655396e2d73950221d187b7e5bb3baIgor Murashkin * stored must also be immutable. If mutable objects are stored here, then the range 37b3a78b2ca9655396e2d73950221d187b7e5bb3baIgor Murashkin * effectively becomes mutable. </p> 38b3a78b2ca9655396e2d73950221d187b7e5bb3baIgor Murashkin */ 39b3a78b2ca9655396e2d73950221d187b7e5bb3baIgor Murashkinpublic final class Range<T extends Comparable<? super T>> { 40b3a78b2ca9655396e2d73950221d187b7e5bb3baIgor Murashkin /** 41b3a78b2ca9655396e2d73950221d187b7e5bb3baIgor Murashkin * Create a new immutable range. 42b3a78b2ca9655396e2d73950221d187b7e5bb3baIgor Murashkin * 43b3a78b2ca9655396e2d73950221d187b7e5bb3baIgor Murashkin * <p> 44b3a78b2ca9655396e2d73950221d187b7e5bb3baIgor Murashkin * The endpoints are {@code [lower, upper]}; that 45b3a78b2ca9655396e2d73950221d187b7e5bb3baIgor Murashkin * is the range is bounded. {@code lower} must be {@link Comparable#compareTo lesser or equal} 46b3a78b2ca9655396e2d73950221d187b7e5bb3baIgor Murashkin * to {@code upper}. 47b3a78b2ca9655396e2d73950221d187b7e5bb3baIgor Murashkin * </p> 48b3a78b2ca9655396e2d73950221d187b7e5bb3baIgor Murashkin * 49b3a78b2ca9655396e2d73950221d187b7e5bb3baIgor Murashkin * @param lower The lower endpoint (inclusive) 50b3a78b2ca9655396e2d73950221d187b7e5bb3baIgor Murashkin * @param upper The upper endpoint (inclusive) 51b3a78b2ca9655396e2d73950221d187b7e5bb3baIgor Murashkin * 52b3a78b2ca9655396e2d73950221d187b7e5bb3baIgor Murashkin * @throws NullPointerException if {@code lower} or {@code upper} is {@code null} 53b3a78b2ca9655396e2d73950221d187b7e5bb3baIgor Murashkin */ 54b3a78b2ca9655396e2d73950221d187b7e5bb3baIgor Murashkin public Range(final T lower, final T upper) { 55b3a78b2ca9655396e2d73950221d187b7e5bb3baIgor Murashkin mLower = checkNotNull(lower, "lower must not be null"); 56b3a78b2ca9655396e2d73950221d187b7e5bb3baIgor Murashkin mUpper = checkNotNull(upper, "upper must not be null"); 57b3a78b2ca9655396e2d73950221d187b7e5bb3baIgor Murashkin 58b3a78b2ca9655396e2d73950221d187b7e5bb3baIgor Murashkin if (lower.compareTo(upper) > 0) { 59b3a78b2ca9655396e2d73950221d187b7e5bb3baIgor Murashkin throw new IllegalArgumentException("lower must be less than or equal to upper"); 60b3a78b2ca9655396e2d73950221d187b7e5bb3baIgor Murashkin } 61b3a78b2ca9655396e2d73950221d187b7e5bb3baIgor Murashkin } 62b3a78b2ca9655396e2d73950221d187b7e5bb3baIgor Murashkin 63b3a78b2ca9655396e2d73950221d187b7e5bb3baIgor Murashkin /** 64b3a78b2ca9655396e2d73950221d187b7e5bb3baIgor Murashkin * Create a new immutable range, with the argument types inferred. 65b3a78b2ca9655396e2d73950221d187b7e5bb3baIgor Murashkin * 66b3a78b2ca9655396e2d73950221d187b7e5bb3baIgor Murashkin * <p> 67b3a78b2ca9655396e2d73950221d187b7e5bb3baIgor Murashkin * The endpoints are {@code [lower, upper]}; that 68b3a78b2ca9655396e2d73950221d187b7e5bb3baIgor Murashkin * is the range is bounded. {@code lower} must be {@link Comparable#compareTo lesser or equal} 69b3a78b2ca9655396e2d73950221d187b7e5bb3baIgor Murashkin * to {@code upper}. 70b3a78b2ca9655396e2d73950221d187b7e5bb3baIgor Murashkin * </p> 71b3a78b2ca9655396e2d73950221d187b7e5bb3baIgor Murashkin * 72b3a78b2ca9655396e2d73950221d187b7e5bb3baIgor Murashkin * @param lower The lower endpoint (inclusive) 73b3a78b2ca9655396e2d73950221d187b7e5bb3baIgor Murashkin * @param upper The upper endpoint (inclusive) 74b3a78b2ca9655396e2d73950221d187b7e5bb3baIgor Murashkin * 75b3a78b2ca9655396e2d73950221d187b7e5bb3baIgor Murashkin * @throws NullPointerException if {@code lower} or {@code upper} is {@code null} 76b3a78b2ca9655396e2d73950221d187b7e5bb3baIgor Murashkin */ 77b3a78b2ca9655396e2d73950221d187b7e5bb3baIgor Murashkin public static <T extends Comparable<? super T>> Range<T> create(final T lower, final T upper) { 78b3a78b2ca9655396e2d73950221d187b7e5bb3baIgor Murashkin return new Range<T>(lower, upper); 79b3a78b2ca9655396e2d73950221d187b7e5bb3baIgor Murashkin } 80b3a78b2ca9655396e2d73950221d187b7e5bb3baIgor Murashkin 81b3a78b2ca9655396e2d73950221d187b7e5bb3baIgor Murashkin /** 82b3a78b2ca9655396e2d73950221d187b7e5bb3baIgor Murashkin * Get the lower endpoint. 83b3a78b2ca9655396e2d73950221d187b7e5bb3baIgor Murashkin * 84b3a78b2ca9655396e2d73950221d187b7e5bb3baIgor Murashkin * @return a non-{@code null} {@code T} reference 85b3a78b2ca9655396e2d73950221d187b7e5bb3baIgor Murashkin */ 86b3a78b2ca9655396e2d73950221d187b7e5bb3baIgor Murashkin public T getLower() { 87b3a78b2ca9655396e2d73950221d187b7e5bb3baIgor Murashkin return mLower; 88b3a78b2ca9655396e2d73950221d187b7e5bb3baIgor Murashkin } 89b3a78b2ca9655396e2d73950221d187b7e5bb3baIgor Murashkin 90b3a78b2ca9655396e2d73950221d187b7e5bb3baIgor Murashkin /** 91b3a78b2ca9655396e2d73950221d187b7e5bb3baIgor Murashkin * Get the upper endpoint. 92b3a78b2ca9655396e2d73950221d187b7e5bb3baIgor Murashkin * 93b3a78b2ca9655396e2d73950221d187b7e5bb3baIgor Murashkin * @return a non-{@code null} {@code T} reference 94b3a78b2ca9655396e2d73950221d187b7e5bb3baIgor Murashkin */ 95b3a78b2ca9655396e2d73950221d187b7e5bb3baIgor Murashkin public T getUpper() { 96b3a78b2ca9655396e2d73950221d187b7e5bb3baIgor Murashkin return mUpper; 97b3a78b2ca9655396e2d73950221d187b7e5bb3baIgor Murashkin } 98b3a78b2ca9655396e2d73950221d187b7e5bb3baIgor Murashkin 99b3a78b2ca9655396e2d73950221d187b7e5bb3baIgor Murashkin /** 100007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin * Checks if the {@code value} is within the bounds of this range. 101007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin * 102b1a236b85fa8f3f46e3f6b76a7bf6f72faf9ee5dLajos Molnar * <p>A value is considered to be within this range if it's {@code >=} 103b1a236b85fa8f3f46e3f6b76a7bf6f72faf9ee5dLajos Molnar * the lower endpoint <i>and</i> {@code <=} the upper endpoint (using the {@link Comparable} 104b1a236b85fa8f3f46e3f6b76a7bf6f72faf9ee5dLajos Molnar * interface.)</p> 105007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin * 106007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin * @param value a non-{@code null} {@code T} reference 107007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin * @return {@code true} if the value is within this inclusive range, {@code false} otherwise 108007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin * 109007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin * @throws NullPointerException if {@code value} was {@code null} 110007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin */ 111b1a236b85fa8f3f46e3f6b76a7bf6f72faf9ee5dLajos Molnar public boolean contains(T value) { 112007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin checkNotNull(value, "value must not be null"); 113007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin 114007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin boolean gteLower = value.compareTo(mLower) >= 0; 115007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin boolean lteUpper = value.compareTo(mUpper) <= 0; 116007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin 117007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin return gteLower && lteUpper; 118007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin } 119007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin 120007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin /** 121b1a236b85fa8f3f46e3f6b76a7bf6f72faf9ee5dLajos Molnar * Checks if another {@code range} is within the bounds of this range. 122b1a236b85fa8f3f46e3f6b76a7bf6f72faf9ee5dLajos Molnar * 123b1a236b85fa8f3f46e3f6b76a7bf6f72faf9ee5dLajos Molnar * <p>A range is considered to be within this range if both of its endpoints 124b1a236b85fa8f3f46e3f6b76a7bf6f72faf9ee5dLajos Molnar * are within this range.</p> 125b1a236b85fa8f3f46e3f6b76a7bf6f72faf9ee5dLajos Molnar * 126b1a236b85fa8f3f46e3f6b76a7bf6f72faf9ee5dLajos Molnar * @param range a non-{@code null} {@code T} reference 127b1a236b85fa8f3f46e3f6b76a7bf6f72faf9ee5dLajos Molnar * @return {@code true} if the range is within this inclusive range, {@code false} otherwise 128b1a236b85fa8f3f46e3f6b76a7bf6f72faf9ee5dLajos Molnar * 129b1a236b85fa8f3f46e3f6b76a7bf6f72faf9ee5dLajos Molnar * @throws NullPointerException if {@code range} was {@code null} 130b1a236b85fa8f3f46e3f6b76a7bf6f72faf9ee5dLajos Molnar */ 131b1a236b85fa8f3f46e3f6b76a7bf6f72faf9ee5dLajos Molnar public boolean contains(Range<T> range) { 132b1a236b85fa8f3f46e3f6b76a7bf6f72faf9ee5dLajos Molnar checkNotNull(range, "value must not be null"); 133b1a236b85fa8f3f46e3f6b76a7bf6f72faf9ee5dLajos Molnar 134b1a236b85fa8f3f46e3f6b76a7bf6f72faf9ee5dLajos Molnar boolean gteLower = range.mLower.compareTo(mLower) >= 0; 135b1a236b85fa8f3f46e3f6b76a7bf6f72faf9ee5dLajos Molnar boolean lteUpper = range.mUpper.compareTo(mUpper) <= 0; 136b1a236b85fa8f3f46e3f6b76a7bf6f72faf9ee5dLajos Molnar 137b1a236b85fa8f3f46e3f6b76a7bf6f72faf9ee5dLajos Molnar return gteLower && lteUpper; 138b1a236b85fa8f3f46e3f6b76a7bf6f72faf9ee5dLajos Molnar } 139b1a236b85fa8f3f46e3f6b76a7bf6f72faf9ee5dLajos Molnar 140b1a236b85fa8f3f46e3f6b76a7bf6f72faf9ee5dLajos Molnar /** 141b3a78b2ca9655396e2d73950221d187b7e5bb3baIgor Murashkin * Compare two ranges for equality. 142b3a78b2ca9655396e2d73950221d187b7e5bb3baIgor Murashkin * 143b3a78b2ca9655396e2d73950221d187b7e5bb3baIgor Murashkin * <p>A range is considered equal if and only if both the lower and upper endpoints 144b3a78b2ca9655396e2d73950221d187b7e5bb3baIgor Murashkin * are also equal.</p> 145b3a78b2ca9655396e2d73950221d187b7e5bb3baIgor Murashkin * 146b3a78b2ca9655396e2d73950221d187b7e5bb3baIgor Murashkin * @return {@code true} if the ranges are equal, {@code false} otherwise 147b3a78b2ca9655396e2d73950221d187b7e5bb3baIgor Murashkin */ 148b3a78b2ca9655396e2d73950221d187b7e5bb3baIgor Murashkin @Override 149007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin public boolean equals(Object obj) { 150b3a78b2ca9655396e2d73950221d187b7e5bb3baIgor Murashkin if (obj == null) { 151b3a78b2ca9655396e2d73950221d187b7e5bb3baIgor Murashkin return false; 152007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin } else if (this == obj) { 153b3a78b2ca9655396e2d73950221d187b7e5bb3baIgor Murashkin return true; 154007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin } else if (obj instanceof Range) { 155b3a78b2ca9655396e2d73950221d187b7e5bb3baIgor Murashkin @SuppressWarnings("rawtypes") 156b3a78b2ca9655396e2d73950221d187b7e5bb3baIgor Murashkin Range other = (Range) obj; 157b3a78b2ca9655396e2d73950221d187b7e5bb3baIgor Murashkin return mLower.equals(other.mLower) && mUpper.equals(other.mUpper); 158b3a78b2ca9655396e2d73950221d187b7e5bb3baIgor Murashkin } 159b3a78b2ca9655396e2d73950221d187b7e5bb3baIgor Murashkin return false; 160b3a78b2ca9655396e2d73950221d187b7e5bb3baIgor Murashkin } 161b3a78b2ca9655396e2d73950221d187b7e5bb3baIgor Murashkin 162b3a78b2ca9655396e2d73950221d187b7e5bb3baIgor Murashkin /** 163b1a236b85fa8f3f46e3f6b76a7bf6f72faf9ee5dLajos Molnar * Clamps {@code value} to this range. 164b1a236b85fa8f3f46e3f6b76a7bf6f72faf9ee5dLajos Molnar * 165b1a236b85fa8f3f46e3f6b76a7bf6f72faf9ee5dLajos Molnar * <p>If the value is within this range, it is returned. Otherwise, if it 166b1a236b85fa8f3f46e3f6b76a7bf6f72faf9ee5dLajos Molnar * is {@code <} than the lower endpoint, the lower endpoint is returned, 167b1a236b85fa8f3f46e3f6b76a7bf6f72faf9ee5dLajos Molnar * else the upper endpoint is returned. Comparisons are performed using the 168b1a236b85fa8f3f46e3f6b76a7bf6f72faf9ee5dLajos Molnar * {@link Comparable} interface.</p> 169b1a236b85fa8f3f46e3f6b76a7bf6f72faf9ee5dLajos Molnar * 170b1a236b85fa8f3f46e3f6b76a7bf6f72faf9ee5dLajos Molnar * @param value a non-{@code null} {@code T} reference 171b1a236b85fa8f3f46e3f6b76a7bf6f72faf9ee5dLajos Molnar * @return {@code value} clamped to this range. 172b1a236b85fa8f3f46e3f6b76a7bf6f72faf9ee5dLajos Molnar */ 173b1a236b85fa8f3f46e3f6b76a7bf6f72faf9ee5dLajos Molnar public T clamp(T value) { 174b1a236b85fa8f3f46e3f6b76a7bf6f72faf9ee5dLajos Molnar checkNotNull(value, "value must not be null"); 175b1a236b85fa8f3f46e3f6b76a7bf6f72faf9ee5dLajos Molnar 176b1a236b85fa8f3f46e3f6b76a7bf6f72faf9ee5dLajos Molnar if (value.compareTo(mLower) < 0) { 177b1a236b85fa8f3f46e3f6b76a7bf6f72faf9ee5dLajos Molnar return mLower; 178b1a236b85fa8f3f46e3f6b76a7bf6f72faf9ee5dLajos Molnar } else if (value.compareTo(mUpper) > 0) { 179b1a236b85fa8f3f46e3f6b76a7bf6f72faf9ee5dLajos Molnar return mUpper; 180b1a236b85fa8f3f46e3f6b76a7bf6f72faf9ee5dLajos Molnar } else { 181b1a236b85fa8f3f46e3f6b76a7bf6f72faf9ee5dLajos Molnar return value; 182b1a236b85fa8f3f46e3f6b76a7bf6f72faf9ee5dLajos Molnar } 183b1a236b85fa8f3f46e3f6b76a7bf6f72faf9ee5dLajos Molnar } 184b1a236b85fa8f3f46e3f6b76a7bf6f72faf9ee5dLajos Molnar 185b1a236b85fa8f3f46e3f6b76a7bf6f72faf9ee5dLajos Molnar /** 186b1a236b85fa8f3f46e3f6b76a7bf6f72faf9ee5dLajos Molnar * Returns the intersection of this range and another {@code range}. 187b1a236b85fa8f3f46e3f6b76a7bf6f72faf9ee5dLajos Molnar * <p> 188b1a236b85fa8f3f46e3f6b76a7bf6f72faf9ee5dLajos Molnar * E.g. if a {@code <} b {@code <} c {@code <} d, the 189b1a236b85fa8f3f46e3f6b76a7bf6f72faf9ee5dLajos Molnar * intersection of [a, c] and [b, d] ranges is [b, c]. 190b1a236b85fa8f3f46e3f6b76a7bf6f72faf9ee5dLajos Molnar * As the endpoints are object references, there is no guarantee 191b1a236b85fa8f3f46e3f6b76a7bf6f72faf9ee5dLajos Molnar * which specific endpoint reference is used from the input ranges:</p> 192b1a236b85fa8f3f46e3f6b76a7bf6f72faf9ee5dLajos Molnar * <p> 193b1a236b85fa8f3f46e3f6b76a7bf6f72faf9ee5dLajos Molnar * E.g. if a {@code ==} a' {@code <} b {@code <} c, the 194b1a236b85fa8f3f46e3f6b76a7bf6f72faf9ee5dLajos Molnar * intersection of [a, b] and [a', c] ranges could be either 195b1a236b85fa8f3f46e3f6b76a7bf6f72faf9ee5dLajos Molnar * [a, b] or ['a, b], where [a, b] could be either the exact 196b1a236b85fa8f3f46e3f6b76a7bf6f72faf9ee5dLajos Molnar * input range, or a newly created range with the same endpoints.</p> 197b1a236b85fa8f3f46e3f6b76a7bf6f72faf9ee5dLajos Molnar * 198b1a236b85fa8f3f46e3f6b76a7bf6f72faf9ee5dLajos Molnar * @param range a non-{@code null} {@code Range<T>} reference 199b1a236b85fa8f3f46e3f6b76a7bf6f72faf9ee5dLajos Molnar * @return the intersection of this range and the other range. 200b1a236b85fa8f3f46e3f6b76a7bf6f72faf9ee5dLajos Molnar * 201b1a236b85fa8f3f46e3f6b76a7bf6f72faf9ee5dLajos Molnar * @throws NullPointerException if {@code range} was {@code null} 202b1a236b85fa8f3f46e3f6b76a7bf6f72faf9ee5dLajos Molnar * @throws IllegalArgumentException if the ranges are disjoint. 203b1a236b85fa8f3f46e3f6b76a7bf6f72faf9ee5dLajos Molnar */ 204b1a236b85fa8f3f46e3f6b76a7bf6f72faf9ee5dLajos Molnar public Range<T> intersect(Range<T> range) { 205b1a236b85fa8f3f46e3f6b76a7bf6f72faf9ee5dLajos Molnar checkNotNull(range, "range must not be null"); 206b1a236b85fa8f3f46e3f6b76a7bf6f72faf9ee5dLajos Molnar 207b1a236b85fa8f3f46e3f6b76a7bf6f72faf9ee5dLajos Molnar int cmpLower = range.mLower.compareTo(mLower); 208b1a236b85fa8f3f46e3f6b76a7bf6f72faf9ee5dLajos Molnar int cmpUpper = range.mUpper.compareTo(mUpper); 209b1a236b85fa8f3f46e3f6b76a7bf6f72faf9ee5dLajos Molnar 210b1a236b85fa8f3f46e3f6b76a7bf6f72faf9ee5dLajos Molnar if (cmpLower <= 0 && cmpUpper >= 0) { 211b1a236b85fa8f3f46e3f6b76a7bf6f72faf9ee5dLajos Molnar // range includes this 212b1a236b85fa8f3f46e3f6b76a7bf6f72faf9ee5dLajos Molnar return this; 213b1a236b85fa8f3f46e3f6b76a7bf6f72faf9ee5dLajos Molnar } else if (cmpLower >= 0 && cmpUpper <= 0) { 214b1a236b85fa8f3f46e3f6b76a7bf6f72faf9ee5dLajos Molnar // this inludes range 215b1a236b85fa8f3f46e3f6b76a7bf6f72faf9ee5dLajos Molnar return range; 216b1a236b85fa8f3f46e3f6b76a7bf6f72faf9ee5dLajos Molnar } else { 217b1a236b85fa8f3f46e3f6b76a7bf6f72faf9ee5dLajos Molnar return Range.create( 218b1a236b85fa8f3f46e3f6b76a7bf6f72faf9ee5dLajos Molnar cmpLower <= 0 ? mLower : range.mLower, 219b1a236b85fa8f3f46e3f6b76a7bf6f72faf9ee5dLajos Molnar cmpUpper >= 0 ? mUpper : range.mUpper); 220b1a236b85fa8f3f46e3f6b76a7bf6f72faf9ee5dLajos Molnar } 221b1a236b85fa8f3f46e3f6b76a7bf6f72faf9ee5dLajos Molnar } 222b1a236b85fa8f3f46e3f6b76a7bf6f72faf9ee5dLajos Molnar 223b1a236b85fa8f3f46e3f6b76a7bf6f72faf9ee5dLajos Molnar /** 224b1a236b85fa8f3f46e3f6b76a7bf6f72faf9ee5dLajos Molnar * Returns the intersection of this range and the inclusive range 225b1a236b85fa8f3f46e3f6b76a7bf6f72faf9ee5dLajos Molnar * specified by {@code [lower, upper]}. 226b1a236b85fa8f3f46e3f6b76a7bf6f72faf9ee5dLajos Molnar * <p> 227b1a236b85fa8f3f46e3f6b76a7bf6f72faf9ee5dLajos Molnar * See {@link #intersect(Range)} for more details.</p> 228b1a236b85fa8f3f46e3f6b76a7bf6f72faf9ee5dLajos Molnar * 229b1a236b85fa8f3f46e3f6b76a7bf6f72faf9ee5dLajos Molnar * @param lower a non-{@code null} {@code T} reference 230b1a236b85fa8f3f46e3f6b76a7bf6f72faf9ee5dLajos Molnar * @param upper a non-{@code null} {@code T} reference 231b1a236b85fa8f3f46e3f6b76a7bf6f72faf9ee5dLajos Molnar * @return the intersection of this range and the other range 232b1a236b85fa8f3f46e3f6b76a7bf6f72faf9ee5dLajos Molnar * 233b1a236b85fa8f3f46e3f6b76a7bf6f72faf9ee5dLajos Molnar * @throws NullPointerException if {@code lower} or {@code upper} was {@code null} 234b1a236b85fa8f3f46e3f6b76a7bf6f72faf9ee5dLajos Molnar * @throws IllegalArgumentException if the ranges are disjoint. 235b1a236b85fa8f3f46e3f6b76a7bf6f72faf9ee5dLajos Molnar */ 236b1a236b85fa8f3f46e3f6b76a7bf6f72faf9ee5dLajos Molnar public Range<T> intersect(T lower, T upper) { 237b1a236b85fa8f3f46e3f6b76a7bf6f72faf9ee5dLajos Molnar checkNotNull(lower, "lower must not be null"); 238b1a236b85fa8f3f46e3f6b76a7bf6f72faf9ee5dLajos Molnar checkNotNull(upper, "upper must not be null"); 239b1a236b85fa8f3f46e3f6b76a7bf6f72faf9ee5dLajos Molnar 240b1a236b85fa8f3f46e3f6b76a7bf6f72faf9ee5dLajos Molnar int cmpLower = lower.compareTo(mLower); 241b1a236b85fa8f3f46e3f6b76a7bf6f72faf9ee5dLajos Molnar int cmpUpper = upper.compareTo(mUpper); 242b1a236b85fa8f3f46e3f6b76a7bf6f72faf9ee5dLajos Molnar 243b1a236b85fa8f3f46e3f6b76a7bf6f72faf9ee5dLajos Molnar if (cmpLower <= 0 && cmpUpper >= 0) { 244b1a236b85fa8f3f46e3f6b76a7bf6f72faf9ee5dLajos Molnar // [lower, upper] includes this 245b1a236b85fa8f3f46e3f6b76a7bf6f72faf9ee5dLajos Molnar return this; 246b1a236b85fa8f3f46e3f6b76a7bf6f72faf9ee5dLajos Molnar } else { 247b1a236b85fa8f3f46e3f6b76a7bf6f72faf9ee5dLajos Molnar return Range.create( 248b1a236b85fa8f3f46e3f6b76a7bf6f72faf9ee5dLajos Molnar cmpLower <= 0 ? mLower : lower, 249b1a236b85fa8f3f46e3f6b76a7bf6f72faf9ee5dLajos Molnar cmpUpper >= 0 ? mUpper : upper); 250b1a236b85fa8f3f46e3f6b76a7bf6f72faf9ee5dLajos Molnar } 251b1a236b85fa8f3f46e3f6b76a7bf6f72faf9ee5dLajos Molnar } 252b1a236b85fa8f3f46e3f6b76a7bf6f72faf9ee5dLajos Molnar 253b1a236b85fa8f3f46e3f6b76a7bf6f72faf9ee5dLajos Molnar /** 254b1a236b85fa8f3f46e3f6b76a7bf6f72faf9ee5dLajos Molnar * Returns the smallest range that includes this range and 255b1a236b85fa8f3f46e3f6b76a7bf6f72faf9ee5dLajos Molnar * another {@code range}. 256b1a236b85fa8f3f46e3f6b76a7bf6f72faf9ee5dLajos Molnar * <p> 257b1a236b85fa8f3f46e3f6b76a7bf6f72faf9ee5dLajos Molnar * E.g. if a {@code <} b {@code <} c {@code <} d, the 258b1a236b85fa8f3f46e3f6b76a7bf6f72faf9ee5dLajos Molnar * extension of [a, c] and [b, d] ranges is [a, d]. 259b1a236b85fa8f3f46e3f6b76a7bf6f72faf9ee5dLajos Molnar * As the endpoints are object references, there is no guarantee 260b1a236b85fa8f3f46e3f6b76a7bf6f72faf9ee5dLajos Molnar * which specific endpoint reference is used from the input ranges:</p> 261b1a236b85fa8f3f46e3f6b76a7bf6f72faf9ee5dLajos Molnar * <p> 262b1a236b85fa8f3f46e3f6b76a7bf6f72faf9ee5dLajos Molnar * E.g. if a {@code ==} a' {@code <} b {@code <} c, the 263b1a236b85fa8f3f46e3f6b76a7bf6f72faf9ee5dLajos Molnar * extension of [a, b] and [a', c] ranges could be either 264b1a236b85fa8f3f46e3f6b76a7bf6f72faf9ee5dLajos Molnar * [a, c] or ['a, c], where ['a, c] could be either the exact 265b1a236b85fa8f3f46e3f6b76a7bf6f72faf9ee5dLajos Molnar * input range, or a newly created range with the same endpoints.</p> 266b1a236b85fa8f3f46e3f6b76a7bf6f72faf9ee5dLajos Molnar * 267b1a236b85fa8f3f46e3f6b76a7bf6f72faf9ee5dLajos Molnar * @param range a non-{@code null} {@code Range<T>} reference 268b1a236b85fa8f3f46e3f6b76a7bf6f72faf9ee5dLajos Molnar * @return the extension of this range and the other range. 269b1a236b85fa8f3f46e3f6b76a7bf6f72faf9ee5dLajos Molnar * 270b1a236b85fa8f3f46e3f6b76a7bf6f72faf9ee5dLajos Molnar * @throws NullPointerException if {@code range} was {@code null} 271b1a236b85fa8f3f46e3f6b76a7bf6f72faf9ee5dLajos Molnar */ 272b1a236b85fa8f3f46e3f6b76a7bf6f72faf9ee5dLajos Molnar public Range<T> extend(Range<T> range) { 273b1a236b85fa8f3f46e3f6b76a7bf6f72faf9ee5dLajos Molnar checkNotNull(range, "range must not be null"); 274b1a236b85fa8f3f46e3f6b76a7bf6f72faf9ee5dLajos Molnar 275b1a236b85fa8f3f46e3f6b76a7bf6f72faf9ee5dLajos Molnar int cmpLower = range.mLower.compareTo(mLower); 276b1a236b85fa8f3f46e3f6b76a7bf6f72faf9ee5dLajos Molnar int cmpUpper = range.mUpper.compareTo(mUpper); 277b1a236b85fa8f3f46e3f6b76a7bf6f72faf9ee5dLajos Molnar 278b1a236b85fa8f3f46e3f6b76a7bf6f72faf9ee5dLajos Molnar if (cmpLower <= 0 && cmpUpper >= 0) { 279b1a236b85fa8f3f46e3f6b76a7bf6f72faf9ee5dLajos Molnar // other includes this 280b1a236b85fa8f3f46e3f6b76a7bf6f72faf9ee5dLajos Molnar return range; 281b1a236b85fa8f3f46e3f6b76a7bf6f72faf9ee5dLajos Molnar } else if (cmpLower >= 0 && cmpUpper <= 0) { 282b1a236b85fa8f3f46e3f6b76a7bf6f72faf9ee5dLajos Molnar // this inludes other 283b1a236b85fa8f3f46e3f6b76a7bf6f72faf9ee5dLajos Molnar return this; 284b1a236b85fa8f3f46e3f6b76a7bf6f72faf9ee5dLajos Molnar } else { 285b1a236b85fa8f3f46e3f6b76a7bf6f72faf9ee5dLajos Molnar return Range.create( 286b1a236b85fa8f3f46e3f6b76a7bf6f72faf9ee5dLajos Molnar cmpLower >= 0 ? mLower : range.mLower, 287b1a236b85fa8f3f46e3f6b76a7bf6f72faf9ee5dLajos Molnar cmpUpper <= 0 ? mUpper : range.mUpper); 288b1a236b85fa8f3f46e3f6b76a7bf6f72faf9ee5dLajos Molnar } 289b1a236b85fa8f3f46e3f6b76a7bf6f72faf9ee5dLajos Molnar } 290b1a236b85fa8f3f46e3f6b76a7bf6f72faf9ee5dLajos Molnar 291b1a236b85fa8f3f46e3f6b76a7bf6f72faf9ee5dLajos Molnar /** 292b1a236b85fa8f3f46e3f6b76a7bf6f72faf9ee5dLajos Molnar * Returns the smallest range that includes this range and 293b1a236b85fa8f3f46e3f6b76a7bf6f72faf9ee5dLajos Molnar * the inclusive range specified by {@code [lower, upper]}. 294b1a236b85fa8f3f46e3f6b76a7bf6f72faf9ee5dLajos Molnar * <p> 295b1a236b85fa8f3f46e3f6b76a7bf6f72faf9ee5dLajos Molnar * See {@link #extend(Range)} for more details.</p> 296b1a236b85fa8f3f46e3f6b76a7bf6f72faf9ee5dLajos Molnar * 297b1a236b85fa8f3f46e3f6b76a7bf6f72faf9ee5dLajos Molnar * @param lower a non-{@code null} {@code T} reference 298b1a236b85fa8f3f46e3f6b76a7bf6f72faf9ee5dLajos Molnar * @param upper a non-{@code null} {@code T} reference 299b1a236b85fa8f3f46e3f6b76a7bf6f72faf9ee5dLajos Molnar * @return the extension of this range and the other range. 300b1a236b85fa8f3f46e3f6b76a7bf6f72faf9ee5dLajos Molnar * 301b1a236b85fa8f3f46e3f6b76a7bf6f72faf9ee5dLajos Molnar * @throws NullPointerException if {@code lower} or {@code 302b1a236b85fa8f3f46e3f6b76a7bf6f72faf9ee5dLajos Molnar * upper} was {@code null} 303b1a236b85fa8f3f46e3f6b76a7bf6f72faf9ee5dLajos Molnar */ 304b1a236b85fa8f3f46e3f6b76a7bf6f72faf9ee5dLajos Molnar public Range<T> extend(T lower, T upper) { 305b1a236b85fa8f3f46e3f6b76a7bf6f72faf9ee5dLajos Molnar checkNotNull(lower, "lower must not be null"); 306b1a236b85fa8f3f46e3f6b76a7bf6f72faf9ee5dLajos Molnar checkNotNull(upper, "upper must not be null"); 307b1a236b85fa8f3f46e3f6b76a7bf6f72faf9ee5dLajos Molnar 308b1a236b85fa8f3f46e3f6b76a7bf6f72faf9ee5dLajos Molnar int cmpLower = lower.compareTo(mLower); 309b1a236b85fa8f3f46e3f6b76a7bf6f72faf9ee5dLajos Molnar int cmpUpper = upper.compareTo(mUpper); 310b1a236b85fa8f3f46e3f6b76a7bf6f72faf9ee5dLajos Molnar 311b1a236b85fa8f3f46e3f6b76a7bf6f72faf9ee5dLajos Molnar if (cmpLower >= 0 && cmpUpper <= 0) { 312b1a236b85fa8f3f46e3f6b76a7bf6f72faf9ee5dLajos Molnar // this inludes other 313b1a236b85fa8f3f46e3f6b76a7bf6f72faf9ee5dLajos Molnar return this; 314b1a236b85fa8f3f46e3f6b76a7bf6f72faf9ee5dLajos Molnar } else { 315b1a236b85fa8f3f46e3f6b76a7bf6f72faf9ee5dLajos Molnar return Range.create( 316b1a236b85fa8f3f46e3f6b76a7bf6f72faf9ee5dLajos Molnar cmpLower >= 0 ? mLower : lower, 317b1a236b85fa8f3f46e3f6b76a7bf6f72faf9ee5dLajos Molnar cmpUpper <= 0 ? mUpper : upper); 318b1a236b85fa8f3f46e3f6b76a7bf6f72faf9ee5dLajos Molnar } 319b1a236b85fa8f3f46e3f6b76a7bf6f72faf9ee5dLajos Molnar } 320b1a236b85fa8f3f46e3f6b76a7bf6f72faf9ee5dLajos Molnar 321b1a236b85fa8f3f46e3f6b76a7bf6f72faf9ee5dLajos Molnar /** 322b1a236b85fa8f3f46e3f6b76a7bf6f72faf9ee5dLajos Molnar * Returns the smallest range that includes this range and 323b1a236b85fa8f3f46e3f6b76a7bf6f72faf9ee5dLajos Molnar * the {@code value}. 324b1a236b85fa8f3f46e3f6b76a7bf6f72faf9ee5dLajos Molnar * <p> 325b1a236b85fa8f3f46e3f6b76a7bf6f72faf9ee5dLajos Molnar * See {@link #extend(Range)} for more details, as this method is 326b1a236b85fa8f3f46e3f6b76a7bf6f72faf9ee5dLajos Molnar * equivalent to {@code extend(Range.create(value, value))}.</p> 327b1a236b85fa8f3f46e3f6b76a7bf6f72faf9ee5dLajos Molnar * 328b1a236b85fa8f3f46e3f6b76a7bf6f72faf9ee5dLajos Molnar * @param value a non-{@code null} {@code T} reference 329b1a236b85fa8f3f46e3f6b76a7bf6f72faf9ee5dLajos Molnar * @return the extension of this range and the value. 330b1a236b85fa8f3f46e3f6b76a7bf6f72faf9ee5dLajos Molnar * 331b1a236b85fa8f3f46e3f6b76a7bf6f72faf9ee5dLajos Molnar * @throws NullPointerException if {@code value} was {@code null} 332b1a236b85fa8f3f46e3f6b76a7bf6f72faf9ee5dLajos Molnar */ 333b1a236b85fa8f3f46e3f6b76a7bf6f72faf9ee5dLajos Molnar public Range<T> extend(T value) { 334b1a236b85fa8f3f46e3f6b76a7bf6f72faf9ee5dLajos Molnar checkNotNull(value, "value must not be null"); 335b1a236b85fa8f3f46e3f6b76a7bf6f72faf9ee5dLajos Molnar return extend(value, value); 336b1a236b85fa8f3f46e3f6b76a7bf6f72faf9ee5dLajos Molnar } 337b1a236b85fa8f3f46e3f6b76a7bf6f72faf9ee5dLajos Molnar 338b1a236b85fa8f3f46e3f6b76a7bf6f72faf9ee5dLajos Molnar /** 339b3a78b2ca9655396e2d73950221d187b7e5bb3baIgor Murashkin * Return the range as a string representation {@code "[lower, upper]"}. 340b3a78b2ca9655396e2d73950221d187b7e5bb3baIgor Murashkin * 341b3a78b2ca9655396e2d73950221d187b7e5bb3baIgor Murashkin * @return string representation of the range 342b3a78b2ca9655396e2d73950221d187b7e5bb3baIgor Murashkin */ 343b3a78b2ca9655396e2d73950221d187b7e5bb3baIgor Murashkin @Override 344b3a78b2ca9655396e2d73950221d187b7e5bb3baIgor Murashkin public String toString() { 345b3a78b2ca9655396e2d73950221d187b7e5bb3baIgor Murashkin return String.format("[%s, %s]", mLower, mUpper); 346b3a78b2ca9655396e2d73950221d187b7e5bb3baIgor Murashkin } 347b3a78b2ca9655396e2d73950221d187b7e5bb3baIgor Murashkin 348b3a78b2ca9655396e2d73950221d187b7e5bb3baIgor Murashkin /** 349b3a78b2ca9655396e2d73950221d187b7e5bb3baIgor Murashkin * {@inheritDoc} 350b3a78b2ca9655396e2d73950221d187b7e5bb3baIgor Murashkin */ 351b3a78b2ca9655396e2d73950221d187b7e5bb3baIgor Murashkin @Override 352b3a78b2ca9655396e2d73950221d187b7e5bb3baIgor Murashkin public int hashCode() { 3530819c75680c81a4e9c8a1ec518ac62cceccf3f56Eino-Ville Talvala return HashCodeHelpers.hashCodeGeneric(mLower, mUpper); 354b3a78b2ca9655396e2d73950221d187b7e5bb3baIgor Murashkin } 355b3a78b2ca9655396e2d73950221d187b7e5bb3baIgor Murashkin 356b3a78b2ca9655396e2d73950221d187b7e5bb3baIgor Murashkin private final T mLower; 357b3a78b2ca9655396e2d73950221d187b7e5bb3baIgor Murashkin private final T mUpper; 358b3a78b2ca9655396e2d73950221d187b7e5bb3baIgor Murashkin}; 359