code: public 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);
    }
docs: Returns the canonical form of this range in the given domain. The canonical form has the
  following properties:
  
  <ul>
  <li>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))}
  <li>uniqueness: unless {@code a.isEmpty()}, {@code ContiguousSet.create(a,
  domain).equals(ContiguousSet.create(b, domain))} implies {@code
  a.canonical(domain).equals(b.canonical(domain))}
  <li>idempotence: {@code a.canonical(domain).canonical(domain).equals(a.canonical(domain))}
  </ul>
  
  <p>Furthermore, this method guarantees that the range returned will be one of the following
  canonical forms:
  
  <ul>
  <li>[start..end)
  <li>[start..+∞)
  <li>(-∞..end) (only if type {@code C} is unbounded below)
  <li>(-∞..+∞) (only if type {@code C} is unbounded below)
  </ul>