Module org.apache.sis.util
Package org.apache.sis.measure

# Class NumberRange<E extends Number & Comparable<? super E>>

Object
Range<E>
NumberRange<E>

Type Parameters:
  `E` - the type of range elements as a subclass of `Number`.

All Implemented Interfaces:
  `Serializable`, `Formattable`, `CheckedContainer<E>`, `Emptiable`

Direct Known Subclasses:
  `MeasurementRange`

public class NumberRange<E extends Number & Comparable<? super E>> extends Range<E>
A range of numbers capable of widening conversions when performing range operations. `NumberRange` has no unit of measurement. For a range of physical measurements with unit of measure, see `MeasurementRange`.

`NumberRange` has some capability to convert different number types before to perform operations. In order to provide both this flexibility and the safety of generic types, most operations in this class are defined in two versions:

- Methods inherited from the `Range` parent class (`contains`, `intersect`, `intersects`, `union` and `subtract`) requires argument or range elements of type `<E>`. No type conversion is performed.
- Methods defined in this class with the `Any` suffix (`containsAny`, `intersectAny`, `intersectsAny`, `unionAny` and `subtractAny`) are more lenient on the argument or range element type `<E>`. Widening conversions are performed as needed.

The methods from the parent class are preferable when the ranges are known to contain elements of the same type, since they avoid the cost of type checks and conversions. The method in this class are convenient when the parameterized type is unknown (`<?>`).

Other methods defined in this class:

- Convenience `create(…)` static methods for every numeric primitive types.
- `castTo(Class)` for casting the range values to another type.
- `transform(MathTransform1D)` for applying an arbitrary conversion.

## Relationship with standards

`NumberRange` is the SIS class closest to the mathematical definition of interval. It is closely related, while not identical, to the ISO 19123 (Coverage geometry and functions) definition of "ranges". At the difference of the parent `Range` class, which can be used only with discrete coverages, the `NumberRange` class can also be used with continuous coverages.

## Immutability and thread safety

This class and the `MeasurementRange` subclasses are immutable, and thus inherently thread-safe. Other subclasses may or may not be immutable, at implementation choice. But implementers are encouraged to make sure that all subclasses remain immutable for more predictable behavior.

## Shared instances

Note: following is implementation details provided for information purpose. The caching policy may change in any SIS version.

All `create` static methods may return a shared instance. Those methods are preferred to the constructors when the range is expected to have a long lifetime, typically as instance given to parameter descriptor. Other methods do not check for shared instances, since the created object is often temporary.

Since:
  0.3
See Also:
  - `RangeFormat`
  - `RangeSet`
  - Wikipedia: Interval
  - Serialized Form

- ## Constructor Summary

  Constructors
  Constructor
  Description
  `NumberRange(Class<E> type, E minValue, boolean isMinIncluded, E maxValue, boolean isMaxIncluded)`
  Constructs a range of `Number` objects.
  `NumberRange(Class<E> type, ValueRange range)`
  Constructs a range of the given type with values from the given annotation.
  `NumberRange(Range<E> range)`
  Constructs a range with the same type and the same values than the specified range.

- ## Method Summary

  Modifier and Type
  Method
  Description
  `static <N extends Number & Comparable<? super N>>
  NumberRange<N>`
  `castOrCopy(Range<N> range)`
  Returns the specified `Range` as a `NumberRange` object.
  `<N extends Number & Comparable<? super N>>
  NumberRange<N>`
  `castTo(Class<N> type)`
  Casts this range to the specified type.
  `boolean`
  `containsAny(Number value)`
  Returns `true` if this range contains the given value.
  `boolean`
  `containsAny(NumberRange<?> range)`
  Returns `true` if the supplied range is fully contained within this range.
  `static NumberRange<Byte>`
  `create(byte minValue, boolean isMinIncluded, byte maxValue, boolean isMaxIncluded)`
  Constructs a range of `byte` values.
  `static NumberRange<Double>`
  `create(double minValue, boolean isMinIncluded, double maxValue, boolean isMaxIncluded)`
  Constructs a range of `double` values.
  `static NumberRange<Float>`
  `create(float minValue, boolean isMinIncluded, float maxValue, boolean isMaxIncluded)`
  Constructs a range of `float` values.
  `static NumberRange<Integer>`
  `create(int minValue, boolean isMinIncluded, int maxValue, boolean isMaxIncluded)`
  Constructs a range of `int` values.
  `static NumberRange<Long>`
  `create(long minValue, boolean isMinIncluded, long maxValue, boolean isMaxIncluded)`
  Constructs a range of `long` values.
  `static NumberRange<Short>`
  `create(short minValue, boolean isMinIncluded, short maxValue, boolean isMaxIncluded)`
  Constructs a range of `short` values.
  `static <N extends Number & Comparable<? super N>>
  NumberRange<N>`
  `create(Class<N> type, N value)`
  Constructs a range containing a single value of the given type.
  `static NumberRange<?>`
  `createBestFit(boolean asFloat, Number minValue, boolean isMinIncluded, Number maxValue, boolean isMaxIncluded)`
  Constructs a range using the smallest integer type or floating point type that can hold the given values.
  `static NumberRange<?>`
  `createBestFit(Number minValue, boolean isMinIncluded, Number maxValue, boolean isMaxIncluded)`
  Constructs a range using the smallest type of `Number` that can hold the given values.
  `static NumberRange<Integer>`
  `createLeftBounded(int minValue, boolean isMinIncluded)`
  Constructs a range of `int` values without upper bound.
  `double`
  `getMaxDouble()`
  Returns the maximum value as a `double`.
  `double`
  `getMaxDouble(boolean inclusive)`
  Returns the maximum value with the specified inclusive or exclusive state.
  `double`
  `getMedian()`
  Computes the average of minimum and maximum values.
  `double`
  `getMinDouble()`
  Returns the minimum value as a `double`.
  `double`
  `getMinDouble(boolean inclusive)`
  Returns the minimum value with the specified inclusive or exclusive state.
  `double`
  `getSpan()`
  Computes the difference between minimum and maximum values.
  `NumberRange<?>`
  `intersectAny(NumberRange<?> range)`
  Returns the union of this range with the given range.
  `boolean`
  `intersectsAny(NumberRange<?> range)`
  Returns `true` if the supplied range intersects this range.
  `NumberRange<?>[]`
  `subtractAny(NumberRange<?> range)`
  Returns the range of values that are in this range but not in the given range.
  `NumberRange<?>`
  `transform(MathTransform1D converter)`
  Returns this range converted using the given converter.
  `NumberRange<?>`
  `unionAny(NumberRange<?> range)`
  Returns the union of this range with the given range.

  ### Methods inherited from class Range

  `contains, contains, equals, formatTo, getElementType, getMaxValue, getMinValue, hashCode, intersect, intersects, isBounded, isEmpty, isMaxIncluded, isMinIncluded, subtract, toString, union`

  ### Methods inherited from class Object

  `clone, finalize, getClass, notify, notifyAll, wait, wait, wait`

- ## Constructor Details

  - ### NumberRange

    public NumberRange(Range<E> range)
    Constructs a range with the same type and the same values than the specified range. This is a copy constructor.
    Parameters:
      `range` - the range to copy. The elements must be `Number` instances.

  - ### NumberRange

    public NumberRange(Class<E> type, ValueRange range) throws IllegalArgumentException
    Constructs a range of the given type with values from the given annotation. This constructor does not verify if the given type is wide enough for the values of the given annotation, because those information are usually static. If nevertheless the given type is not wide enough, then the values are truncated in the same way than the Java language casts primitive types.
    Parameters:
      `type` - the element type, restricted to one of `Byte`, `Short`, `Integer`, `Long`, `Float` or `Double`.
      `range` - the range of values.
    Throws:
      `IllegalArgumentException` - if the given type is not one of the primitive wrappers for numeric types.

  - ### NumberRange

    public NumberRange(Class<E> type, E minValue, boolean isMinIncluded, E maxValue, boolean isMaxIncluded)
    Constructs a range of `Number` objects.
    Parameters:
      `type` - the element type, usually one of `Byte`, `Short`, `Integer`, `Long`, `Float` or `Double`.
      `minValue` - the minimal value, or `null` if none.
      `isMinIncluded` - `true` if the minimal value is inclusive, or `false` if exclusive.
      `maxValue` - the maximal value, or `null` if none.
      `isMaxIncluded` - `true` if the maximal value is inclusive, or `false` if exclusive.

- ## Method Details

  - ### create

    public static <N extends Number & Comparable<? super N>> NumberRange<N> create(Class<N> type, N value)
    Constructs a range containing a single value of the given type. The given value is used as the minimum and maximum values, inclusive.
    Type Parameters:
      `N` - compile-time value of `type`.
    Parameters:
      `type` - the element type, usually one of `Byte`, `Short`, `Integer`, `Long`, `Float` or `Double`.
      `value` - the value, or `null` for creating an unbounded range.
    Returns:
      a range containing the given value as its inclusive minimum and maximum.
    Since:
      1.0

  - ### create

    public static NumberRange<Byte> create(byte minValue, boolean isMinIncluded, byte maxValue, boolean isMaxIncluded)
    Constructs a range of `byte` values. If the minimum is greater than the maximum, then the range is empty. This method may return a shared instance, at implementation choice.
    Parameters:
      `minValue` - the minimal value.
      `isMinIncluded` - `true` if the minimal value is inclusive, or `false` if exclusive.
      `maxValue` - the maximal value.
      `isMaxIncluded` - `true` if the maximal value is inclusive, or `false` if exclusive.
    Returns:
      the new range of numeric values for the given endpoints.

  - ### create

    public static NumberRange<Short> create(short minValue, boolean isMinIncluded, short maxValue, boolean isMaxIncluded)
    Constructs a range of `short` values. If the minimum is greater than the maximum, then the range is empty. This method may return a shared instance, at implementation choice.
    Parameters:
      `minValue` - the minimal value.
      `isMinIncluded` - `true` if the minimal value is inclusive, or `false` if exclusive.
      `maxValue` - the maximal value.
      `isMaxIncluded` - `true` if the maximal value is inclusive, or `false` if exclusive.
    Returns:
      the new range of numeric values for the given endpoints.

  - ### create

    public static NumberRange<Integer> create(int minValue, boolean isMinIncluded, int maxValue, boolean isMaxIncluded)
    Constructs a range of `int` values. If the minimum is greater than the maximum, then the range is empty. This method may return a shared instance, at implementation choice.
    Parameters:
      `minValue` - the minimal value.
      `isMinIncluded` - `true` if the minimal value is inclusive, or `false` if exclusive.
      `maxValue` - the maximal value.
      `isMaxIncluded` - `true` if the maximal value is inclusive, or `false` if exclusive.
    Returns:
      the new range of numeric values for the given endpoints.
    See Also:
      - `createLeftBounded(int, boolean)`

  - ### create

    public static NumberRange<Long> create(long minValue, boolean isMinIncluded, long maxValue, boolean isMaxIncluded)
    Constructs a range of `long` values. If the minimum is greater than the maximum, then the range is empty. This method may return a shared instance, at implementation choice.
    Parameters:
      `minValue` - the minimal value.
      `isMinIncluded` - `true` if the minimal value is inclusive, or `false` if exclusive.
      `maxValue` - the maximal value.
      `isMaxIncluded` - `true` if the maximal value is inclusive, or `false` if exclusive.
    Returns:
      the new range of numeric values for the given endpoints.

  - ### create

    public static NumberRange<Float> create(float minValue, boolean isMinIncluded, float maxValue, boolean isMaxIncluded)
    Constructs a range of `float` values. The minimum and maximum values cannot be NaN but can be infinite. If the minimum is greater than the maximum, then the range is empty. This method may return a shared instance, at implementation choice.
    Parameters:
      `minValue` - the minimal value, or `Float​.NEGATIVE_INFINITY` if none.
      `isMinIncluded` - `true` if the minimal value is inclusive, or `false` if exclusive.
      `maxValue` - the maximal value, or `Float​.POSITIVE_INFINITY` if none.
      `isMaxIncluded` - `true` if the maximal value is inclusive, or `false` if exclusive.
    Returns:
      the new range of numeric values for the given endpoints.
    Throws:
      `IllegalArgumentException` - if `Float​.isNaN(float)` is `true` for a given value.

  - ### create

    public static NumberRange<Double> create(double minValue, boolean isMinIncluded, double maxValue, boolean isMaxIncluded)
    Constructs a range of `double` values. The minimum and maximum values cannot be NaN but can be infinite. If the minimum is greater than the maximum, then the range is empty. This method may return a shared instance, at implementation choice.
    Parameters:
      `minValue` - the minimal value, or `Double​.NEGATIVE_INFINITY` if none.
      `isMinIncluded` - `true` if the minimal value is inclusive, or `false` if exclusive.
      `maxValue` - the maximal value, or `Double​.POSITIVE_INFINITY` if none.
      `isMaxIncluded` - `true` if the maximal value is inclusive, or `false` if exclusive.
    Returns:
      the new range of numeric values for the given endpoints.
    Throws:
      `IllegalArgumentException` - if `Double​.isNaN(double)` is `true` for a given value.

  - ### createBestFit

    public static NumberRange<?> createBestFit(Number minValue, boolean isMinIncluded, Number maxValue, boolean isMaxIncluded)
    Constructs a range using the smallest type of `Number` that can hold the given values. The given numbers do not need to be of the same type since they will be casted as needed. More specifically this method returns:
    - `NumberRange<Byte>` if the given values are integers between 0x80 and 0x7f inclusive.
    - `NumberRange<Short>` if the given values are integers between -32768 and 32767 inclusive.
    - `NumberRange<Integer>` if the given values are integers between -2147483648 and 2147483647 inclusive.
    - `NumberRange<Long>` if the given values are integers between -9223372036854775808L and 9223372036854775807L inclusive.
    - `NumberRange<Float>` if the given values can be casted to `float` values without data lost.
    - `NumberRange<Double>` if none of the above types is suitable.
    This method may return a shared instance, at implementation choice.
    Parameters:
      `minValue` - the minimal value, or `null` if none.
      `isMinIncluded` - `true` if the minimal value is inclusive, or `false` if exclusive.
      `maxValue` - the maximal value, or `null` if none.
      `isMaxIncluded` - `true` if the maximal value is inclusive, or `false` if exclusive.
    Returns:
      the new range, or `null` if both `minValue` and `maxValue` are `null`.
    Throws:
      `IllegalArgumentException` - if the given numbers are not primitive wrappers for numeric types.

  - ### createBestFit

    public static NumberRange<?> createBestFit(boolean asFloat, Number minValue, boolean isMinIncluded, Number maxValue, boolean isMaxIncluded)
    Constructs a range using the smallest integer type or floating point type that can hold the given values. If `asFloat` is `false`, then the returned range can use any wrapper type and this method behaves as described in above method. If `asFloat` is `true`, then the returned range is restricted to `Float` and `Double` number types; integer types are casted to one of the floating point types.
    Parameters:
      `asFloat` - whether to restrict the returned range to floating point types.
      `minValue` - the minimal value, or `null` if none.
      `isMinIncluded` - `true` if the minimal value is inclusive, or `false` if exclusive.
      `maxValue` - the maximal value, or `null` if none.
      `isMaxIncluded` - `true` if the maximal value is inclusive, or `false` if exclusive.
    Returns:
      the new range, or `null` if both `minValue` and `maxValue` are `null`.
    Throws:
      `IllegalArgumentException` - if the given numbers are not primitive wrappers for numeric types.
    Since:
      1.2

  - ### createLeftBounded

    public static NumberRange<Integer> createLeftBounded(int minValue, boolean isMinIncluded)
    Constructs a range of `int` values without upper bound. This method may return a shared instance, at implementation choice.

    #### API note

    For creating left-bounded ranges of floating point values, use one of the `create(…)` methods with a `POSITIVE_INFINITY` constant. We do not provide variants for other integer types because this method is typically invoked for defining the multiplicity of an attribute.
    Parameters:
      `minValue` - the minimal value.
      `isMinIncluded` - `true` if the minimal value is inclusive, or `false` if exclusive.
    Returns:
      the new range of numeric values from `minValue` to positive infinity.
    Since:
      0.5
    See Also:
      - `create(int, boolean, int, boolean)`

  - ### castOrCopy

    public static <N extends Number & Comparable<? super N>> NumberRange<N> castOrCopy(Range<N> range)
    Returns the specified `Range` as a `NumberRange` object. If the specified range is already an instance of `NumberRange`, then it is returned unchanged. Otherwise a new number range is created using the copy constructor.
    Type Parameters:
      `N` - the type of elements in the given range.
    Parameters:
      `range` - the range to cast or copy.
    Returns:
      the same range than `range` as a `NumberRange` object.

  - ### castTo

    public <N extends Number & Comparable<? super N>> NumberRange<N> castTo(Class<N> type) throws IllegalArgumentException
    Casts this range to the specified type. If the cast from this range type to the given type is a narrowing conversion, then the cast is performed according the rules of the Java language: the high-order bytes are silently dropped.
    Type Parameters:
      `N` - the class to cast to.
    Parameters:
      `type` - the class to cast to. Must be one of `Byte`, `Short`, `Integer`, `Long`, `Float` or `Double`.
    Returns:
      the casted range, or `this` if this range already uses the specified type.
    Throws:
      `IllegalArgumentException` - if the given type is not one of the primitive wrappers for numeric types.

  - ### getMinDouble

    public double getMinDouble()
    Returns the minimum value as a `double`. If this range is unbounded, then `Double​.NEGATIVE_INFINITY` is returned.
    Returns:
      the minimum value.

  - ### getMinDouble

    public double getMinDouble(boolean inclusive)
    Returns the minimum value with the specified inclusive or exclusive state. If this range is unbounded, then `Double​.NEGATIVE_INFINITY` is returned.
    Parameters:
      `inclusive` - `true` for the minimum value inclusive, or `false` for the minimum value exclusive.
    Returns:
      the minimum value, inclusive or exclusive as requested.

  - ### getMaxDouble

    public double getMaxDouble()
    Returns the maximum value as a `double`. If this range is unbounded, then `Double​.POSITIVE_INFINITY` is returned.
    Returns:
      the maximum value.

  - ### getMaxDouble

    public double getMaxDouble(boolean inclusive)
    Returns the maximum value with the specified inclusive or exclusive state. If this range is unbounded, then `Double​.POSITIVE_INFINITY` is returned.
    Parameters:
      `inclusive` - `true` for the maximum value inclusive, or `false` for the maximum value exclusive.
    Returns:
      the maximum value, inclusive or exclusive as requested.

  - ### getMedian

    public double getMedian()
    Computes the average of minimum and maximum values. If numbers are integers, the average is computed using inclusive values (e.g. equivalent to `getMinDouble(true)`). Otherwise the minimum and maximum values are used as-is (because making them inclusive is considered an infinitely small change).

    Special cases:

    - If one bound is infinite, the return value is the same infinity.
    - If the two bounds are infinite, the return value is `Double​.NaN`.
    - If the range is empty, the return value is `Double​.NaN`.
    - If a bound is NaN, the return value is the same NaN (reminder: multiple NaN values are possible).
    Returns:
      (minimum + maximum) / 2 computed using inclusive values.
    Since:
      1.1

  - ### getSpan

    public double getSpan()
    Computes the difference between minimum and maximum values. If numbers are integers, the difference is computed using inclusive values (e.g. using `getMinDouble(true)`). Otherwise the minimum and maximum values are used as-is (because making them inclusive is considered an infinitely small change).

    Special cases:

    - If the range is empty, the return value is 0.
    - If at least one bound is infinite, the return value is `Double​.POSITIVE_INFINITY`.
    - If a bound is NaN, the return value is the same NaN (reminder: multiple NaN values are possible).
    Returns:
      (maximum − minimum) computed using inclusive values.
    Since:
      1.1

  - ### containsAny

    public boolean containsAny(Number value) throws IllegalArgumentException
    Returns `true` if this range contains the given value. This method converts `this` or the given argument to the widest numeric type, then performs the same work than `Range​.contains(Comparable)`.
    Parameters:
      `value` - the value to check for inclusion in this range, or `null`.
    Returns:
      `true` if the given value is non-null and included in this range.
    Throws:
      `IllegalArgumentException` - if the given range cannot be converted to a valid type through widening conversion.

  - ### containsAny

    public boolean containsAny(NumberRange<?> range) throws IllegalArgumentException
    Returns `true` if the supplied range is fully contained within this range. This method converts `this` or the given argument to the widest numeric type, then delegates to `Range​.contains(Range)`.
    Parameters:
      `range` - the range to check for inclusion in this range.
    Returns:
      `true` if the given range is included in this range.
    Throws:
      `IllegalArgumentException` - if the given range cannot be converted to a valid type through widening conversion, or if the units of measurement are not convertible.

  - ### intersectsAny

    public boolean intersectsAny(NumberRange<?> range) throws IllegalArgumentException
    Returns `true` if the supplied range intersects this range. This method converts `this` or the given argument to the widest numeric type, then delegates to `Range​.intersects(Range)`.
    Parameters:
      `range` - the range to check for intersection with this range.
    Returns:
      `true` if the given range intersects this range.
    Throws:
      `IllegalArgumentException` - if the given range cannot be converted to a valid type through widening conversion, or if the units of measurement are not convertible.

  - ### intersectAny

    public NumberRange<?> intersectAny(NumberRange<?> range) throws IllegalArgumentException
    Returns the union of this range with the given range. This method converts `this` or the given argument to the widest numeric type, then delegates to `Range​.intersect(Range)`.
    Parameters:
      `range` - the range to add to this range.
    Returns:
      the intersection of this range with the given range.
    Throws:
      `IllegalArgumentException` - if the given range cannot be converted to a valid type through widening conversion, or if the units of measurement are not convertible.

  - ### unionAny

    public NumberRange<?> unionAny(NumberRange<?> range) throws IllegalArgumentException
    Returns the union of this range with the given range. This method converts `this` or the given argument to the widest numeric type, then delegates to `Range​.union(Range)`.
    Parameters:
      `range` - the range to add to this range.
    Returns:
      the union of this range with the given range.
    Throws:
      `IllegalArgumentException` - if the given range cannot be converted to a valid type through widening conversion, or if the units of measurement are not convertible.

  - ### subtractAny

    public NumberRange<?>[] subtractAny(NumberRange<?> range) throws IllegalArgumentException
    Returns the range of values that are in this range but not in the given range. This method converts `this` or the given argument to the widest numeric type, then delegates to `Range​.subtract(Range)`.
    Parameters:
      `range` - the range to subtract.
    Returns:
      this range without the given range, as an array of length 0, 1 or 2.
    Throws:
      `IllegalArgumentException` - if the given range cannot be converted to a valid type through widening conversion, or if the units of measurement are not convertible.

  - ### transform

    public NumberRange<?> transform(MathTransform1D converter) throws TransformException
    Returns this range converted using the given converter.
    Parameters:
      `converter` - the converter to apply.
    Returns:
      the converted range, or `this` if the result is the same as this range.
    Throws:
      `TransformException` - if an error occurred during the conversion.
    Since:
      1.3