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