/*
* Copyright (C) 2014 The Android Open Source Project
*
* 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 android.util;
import static com.android.internal.util.Preconditions.*;
import android.hardware.camera2.utils.HashCodeHelpers;
Immutable class for describing the range of two numeric values.
A range (or "interval") defines the inclusive boundaries around a contiguous span of values of some Comparable
type; for example, "integers from 1 to 100 inclusive."
All ranges are bounded, and the left side of the range is always >=
the right side of the range.
Although the implementation itself is immutable, there is no restriction that objects
stored must also be immutable. If mutable objects are stored here, then the range
effectively becomes mutable.
/**
* Immutable class for describing the range of two numeric values.
* <p>
* A range (or "interval") defines the inclusive boundaries around a contiguous span of
* values of some {@link Comparable} type; for example,
* "integers from 1 to 100 inclusive."
* </p>
* <p>
* All ranges are bounded, and the left side of the range is always {@code >=}
* the right side of the range.
* </p>
*
* <p>Although the implementation itself is immutable, there is no restriction that objects
* stored must also be immutable. If mutable objects are stored here, then the range
* effectively becomes mutable. </p>
*/
public final class Range<T extends Comparable<? super T>> {
Create a new immutable range.
The endpoints are [lower, upper]
; that is the range is bounded. lower
must be lesser or equal
to upper
.
Params: - lower – The lower endpoint (inclusive)
- upper – The upper endpoint (inclusive)
Throws: - NullPointerException – if
lower
or upper
is null
/**
* Create a new immutable range.
*
* <p>
* The endpoints are {@code [lower, upper]}; that
* is the range is bounded. {@code lower} must be {@link Comparable#compareTo lesser or equal}
* to {@code upper}.
* </p>
*
* @param lower The lower endpoint (inclusive)
* @param upper The upper endpoint (inclusive)
*
* @throws NullPointerException if {@code lower} or {@code upper} is {@code null}
*/
public Range(final T lower, final T upper) {
mLower = checkNotNull(lower, "lower must not be null");
mUpper = checkNotNull(upper, "upper must not be null");
if (lower.compareTo(upper) > 0) {
throw new IllegalArgumentException("lower must be less than or equal to upper");
}
}
Create a new immutable range, with the argument types inferred.
The endpoints are [lower, upper]
; that is the range is bounded. lower
must be lesser or equal
to upper
.
Params: - lower – The lower endpoint (inclusive)
- upper – The upper endpoint (inclusive)
Throws: - NullPointerException – if
lower
or upper
is null
/**
* Create a new immutable range, with the argument types inferred.
*
* <p>
* The endpoints are {@code [lower, upper]}; that
* is the range is bounded. {@code lower} must be {@link Comparable#compareTo lesser or equal}
* to {@code upper}.
* </p>
*
* @param lower The lower endpoint (inclusive)
* @param upper The upper endpoint (inclusive)
*
* @throws NullPointerException if {@code lower} or {@code upper} is {@code null}
*/
public static <T extends Comparable<? super T>> Range<T> create(final T lower, final T upper) {
return new Range<T>(lower, upper);
}
Get the lower endpoint.
Returns: a non-null
T
reference
/**
* Get the lower endpoint.
*
* @return a non-{@code null} {@code T} reference
*/
public T getLower() {
return mLower;
}
Get the upper endpoint.
Returns: a non-null
T
reference
/**
* Get the upper endpoint.
*
* @return a non-{@code null} {@code T} reference
*/
public T getUpper() {
return mUpper;
}
Checks if the value
is within the bounds of this range. A value is considered to be within this range if it's >=
the lower endpoint and <=
the upper endpoint (using the Comparable
interface.)
Params: - value – a non-
null
T
reference
Throws: - NullPointerException – if
value
was null
Returns: true
if the value is within this inclusive range, false
otherwise
/**
* Checks if the {@code value} is within the bounds of this range.
*
* <p>A value is considered to be within this range if it's {@code >=}
* the lower endpoint <i>and</i> {@code <=} the upper endpoint (using the {@link Comparable}
* interface.)</p>
*
* @param value a non-{@code null} {@code T} reference
* @return {@code true} if the value is within this inclusive range, {@code false} otherwise
*
* @throws NullPointerException if {@code value} was {@code null}
*/
public boolean contains(T value) {
checkNotNull(value, "value must not be null");
boolean gteLower = value.compareTo(mLower) >= 0;
boolean lteUpper = value.compareTo(mUpper) <= 0;
return gteLower && lteUpper;
}
Checks if another range
is within the bounds of this range. A range is considered to be within this range if both of its endpoints
are within this range.
Params: - range – a non-
null
T
reference
Throws: - NullPointerException – if
range
was null
Returns: true
if the range is within this inclusive range, false
otherwise
/**
* Checks if another {@code range} is within the bounds of this range.
*
* <p>A range is considered to be within this range if both of its endpoints
* are within this range.</p>
*
* @param range a non-{@code null} {@code T} reference
* @return {@code true} if the range is within this inclusive range, {@code false} otherwise
*
* @throws NullPointerException if {@code range} was {@code null}
*/
public boolean contains(Range<T> range) {
checkNotNull(range, "value must not be null");
boolean gteLower = range.mLower.compareTo(mLower) >= 0;
boolean lteUpper = range.mUpper.compareTo(mUpper) <= 0;
return gteLower && lteUpper;
}
Compare two ranges for equality.
A range is considered equal if and only if both the lower and upper endpoints
are also equal.
Returns: true
if the ranges are equal, false
otherwise
/**
* Compare two ranges for equality.
*
* <p>A range is considered equal if and only if both the lower and upper endpoints
* are also equal.</p>
*
* @return {@code true} if the ranges are equal, {@code false} otherwise
*/
@Override
public boolean equals(Object obj) {
if (obj == null) {
return false;
} else if (this == obj) {
return true;
} else if (obj instanceof Range) {
@SuppressWarnings("rawtypes")
Range other = (Range) obj;
return mLower.equals(other.mLower) && mUpper.equals(other.mUpper);
}
return false;
}
Clamps value
to this range. If the value is within this range, it is returned. Otherwise, if it is <
than the lower endpoint, the lower endpoint is returned, else the upper endpoint is returned. Comparisons are performed using the Comparable
interface.
Params: - value – a non-
null
T
reference
Returns: value
clamped to this range.
/**
* Clamps {@code value} to this range.
*
* <p>If the value is within this range, it is returned. Otherwise, if it
* is {@code <} than the lower endpoint, the lower endpoint is returned,
* else the upper endpoint is returned. Comparisons are performed using the
* {@link Comparable} interface.</p>
*
* @param value a non-{@code null} {@code T} reference
* @return {@code value} clamped to this range.
*/
public T clamp(T value) {
checkNotNull(value, "value must not be null");
if (value.compareTo(mLower) < 0) {
return mLower;
} else if (value.compareTo(mUpper) > 0) {
return mUpper;
} else {
return value;
}
}
Returns the intersection of this range and another range
. E.g. if a <
b <
c <
d, the intersection of [a, c] and [b, d] ranges is [b, c]. As the endpoints are object references, there is no guarantee which specific endpoint reference is used from the input ranges:
E.g. if a ==
a' <
b <
c, the intersection of [a, b] and [a', c] ranges could be either [a, b] or ['a, b], where [a, b] could be either the exact input range, or a newly created range with the same endpoints.
Params: - range – a non-
null
Range<T>
reference
Throws: - NullPointerException – if
range
was null
- IllegalArgumentException – if the ranges are disjoint.
Returns: the intersection of this range and the other range.
/**
* Returns the intersection of this range and another {@code range}.
* <p>
* E.g. if a {@code <} b {@code <} c {@code <} d, the
* intersection of [a, c] and [b, d] ranges is [b, c].
* As the endpoints are object references, there is no guarantee
* which specific endpoint reference is used from the input ranges:</p>
* <p>
* E.g. if a {@code ==} a' {@code <} b {@code <} c, the
* intersection of [a, b] and [a', c] ranges could be either
* [a, b] or ['a, b], where [a, b] could be either the exact
* input range, or a newly created range with the same endpoints.</p>
*
* @param range a non-{@code null} {@code Range<T>} reference
* @return the intersection of this range and the other range.
*
* @throws NullPointerException if {@code range} was {@code null}
* @throws IllegalArgumentException if the ranges are disjoint.
*/
public Range<T> intersect(Range<T> range) {
checkNotNull(range, "range must not be null");
int cmpLower = range.mLower.compareTo(mLower);
int cmpUpper = range.mUpper.compareTo(mUpper);
if (cmpLower <= 0 && cmpUpper >= 0) {
// range includes this
return this;
} else if (cmpLower >= 0 && cmpUpper <= 0) {
// this inludes range
return range;
} else {
return Range.create(
cmpLower <= 0 ? mLower : range.mLower,
cmpUpper >= 0 ? mUpper : range.mUpper);
}
}
Returns the intersection of this range and the inclusive range specified by [lower, upper]
. See intersect(Range)
for more details.
Params: - lower – a non-
null
T
reference - upper – a non-
null
T
reference
Throws: - NullPointerException – if
lower
or upper
was null
- IllegalArgumentException – if the ranges are disjoint.
Returns: the intersection of this range and the other range
/**
* Returns the intersection of this range and the inclusive range
* specified by {@code [lower, upper]}.
* <p>
* See {@link #intersect(Range)} for more details.</p>
*
* @param lower a non-{@code null} {@code T} reference
* @param upper a non-{@code null} {@code T} reference
* @return the intersection of this range and the other range
*
* @throws NullPointerException if {@code lower} or {@code upper} was {@code null}
* @throws IllegalArgumentException if the ranges are disjoint.
*/
public Range<T> intersect(T lower, T upper) {
checkNotNull(lower, "lower must not be null");
checkNotNull(upper, "upper must not be null");
int cmpLower = lower.compareTo(mLower);
int cmpUpper = upper.compareTo(mUpper);
if (cmpLower <= 0 && cmpUpper >= 0) {
// [lower, upper] includes this
return this;
} else {
return Range.create(
cmpLower <= 0 ? mLower : lower,
cmpUpper >= 0 ? mUpper : upper);
}
}
Returns the smallest range that includes this range and another range
. E.g. if a <
b <
c <
d, the extension of [a, c] and [b, d] ranges is [a, d]. As the endpoints are object references, there is no guarantee which specific endpoint reference is used from the input ranges:
E.g. if a ==
a' <
b <
c, the extension of [a, b] and [a', c] ranges could be either [a, c] or ['a, c], where ['a, c] could be either the exact input range, or a newly created range with the same endpoints.
Params: - range – a non-
null
Range<T>
reference
Throws: - NullPointerException – if
range
was null
Returns: the extension of this range and the other range.
/**
* Returns the smallest range that includes this range and
* another {@code range}.
* <p>
* E.g. if a {@code <} b {@code <} c {@code <} d, the
* extension of [a, c] and [b, d] ranges is [a, d].
* As the endpoints are object references, there is no guarantee
* which specific endpoint reference is used from the input ranges:</p>
* <p>
* E.g. if a {@code ==} a' {@code <} b {@code <} c, the
* extension of [a, b] and [a', c] ranges could be either
* [a, c] or ['a, c], where ['a, c] could be either the exact
* input range, or a newly created range with the same endpoints.</p>
*
* @param range a non-{@code null} {@code Range<T>} reference
* @return the extension of this range and the other range.
*
* @throws NullPointerException if {@code range} was {@code null}
*/
public Range<T> extend(Range<T> range) {
checkNotNull(range, "range must not be null");
int cmpLower = range.mLower.compareTo(mLower);
int cmpUpper = range.mUpper.compareTo(mUpper);
if (cmpLower <= 0 && cmpUpper >= 0) {
// other includes this
return range;
} else if (cmpLower >= 0 && cmpUpper <= 0) {
// this inludes other
return this;
} else {
return Range.create(
cmpLower >= 0 ? mLower : range.mLower,
cmpUpper <= 0 ? mUpper : range.mUpper);
}
}
Returns the smallest range that includes this range and the inclusive range specified by [lower, upper]
. See extend(Range)
for more details.
Params: - lower – a non-
null
T
reference - upper – a non-
null
T
reference
Throws: - NullPointerException – if
lower
or
upper
was null
Returns: the extension of this range and the other range.
/**
* Returns the smallest range that includes this range and
* the inclusive range specified by {@code [lower, upper]}.
* <p>
* See {@link #extend(Range)} for more details.</p>
*
* @param lower a non-{@code null} {@code T} reference
* @param upper a non-{@code null} {@code T} reference
* @return the extension of this range and the other range.
*
* @throws NullPointerException if {@code lower} or {@code
* upper} was {@code null}
*/
public Range<T> extend(T lower, T upper) {
checkNotNull(lower, "lower must not be null");
checkNotNull(upper, "upper must not be null");
int cmpLower = lower.compareTo(mLower);
int cmpUpper = upper.compareTo(mUpper);
if (cmpLower >= 0 && cmpUpper <= 0) {
// this inludes other
return this;
} else {
return Range.create(
cmpLower >= 0 ? mLower : lower,
cmpUpper <= 0 ? mUpper : upper);
}
}
Returns the smallest range that includes this range and the value
. See extend(Range)
for more details, as this method is equivalent to extend(Range.create(value, value))
.
Params: - value – a non-
null
T
reference
Throws: - NullPointerException – if
value
was null
Returns: the extension of this range and the value.
/**
* Returns the smallest range that includes this range and
* the {@code value}.
* <p>
* See {@link #extend(Range)} for more details, as this method is
* equivalent to {@code extend(Range.create(value, value))}.</p>
*
* @param value a non-{@code null} {@code T} reference
* @return the extension of this range and the value.
*
* @throws NullPointerException if {@code value} was {@code null}
*/
public Range<T> extend(T value) {
checkNotNull(value, "value must not be null");
return extend(value, value);
}
Return the range as a string representation "[lower, upper]"
. Returns: string representation of the range
/**
* Return the range as a string representation {@code "[lower, upper]"}.
*
* @return string representation of the range
*/
@Override
public String toString() {
return String.format("[%s, %s]", mLower, mUpper);
}
{@inheritDoc}
/**
* {@inheritDoc}
*/
@Override
public int hashCode() {
return HashCodeHelpers.hashCodeGeneric(mLower, mUpper);
}
private final T mLower;
private final T mUpper;
};