canonical method
Returns the canonical form of this range in the given domain. The canonical form has the following properties:
- equivalence: {@code a.canonical().contains(v) == a.contains(v)} for all {@code v} (in other words, {@code ContiguousSet.create(a.canonical(domain), domain).equals( ContiguousSet.create(a, domain))}
- uniqueness: unless {@code a.isEmpty()}, {@code ContiguousSet.create(a, domain).equals(ContiguousSet.create(b, domain))} implies {@code a.canonical(domain).equals(b.canonical(domain))}
- idempotence: {@code a.canonical(domain).canonical(domain).equals(a.canonical(domain))}
Furthermore, this method guarantees that the range returned will be one of the following canonical forms:
- [start..end)
- [start..+∞)
- (-∞..end) (only if type {@code C} is unbounded below)
- (-∞..+∞) (only if type {@code C} is unbounded below)
Implementation
Range<C> canonical(DiscreteDomain<C> domain) {
checkNotNull(domain);
Cut<C> lower = lowerBound.canonical(domain);
Cut<C> upper = upperBound.canonical(domain);
return (lower == lowerBound && upper == upperBound)
? this
: create(lower, upper);
}