001/*
002 * Copyright (C) 2009 The Guava Authors
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 * http://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016
017package com.google.common.collect;
018
019import static com.google.common.base.Preconditions.checkArgument;
020import static com.google.common.collect.CollectPreconditions.checkNonnegative;
021
022import com.google.common.annotations.GwtCompatible;
023import com.google.common.primitives.Ints;
024import com.google.errorprone.annotations.CanIgnoreReturnValue;
025import java.io.Serializable;
026import java.math.BigInteger;
027import java.util.NoSuchElementException;
028
029/**
030 * A descriptor for a <i>discrete</i> {@code Comparable} domain such as all
031 * {@link Integer} instances. A discrete domain is one that supports the three basic
032 * operations: {@link #next}, {@link #previous} and {@link #distance}, according
033 * to their specifications. The methods {@link #minValue} and {@link #maxValue}
034 * should also be overridden for bounded types.
035 *
036 * <p>A discrete domain always represents the <i>entire</i> set of values of its
037 * type; it cannot represent partial domains such as "prime integers" or
038 * "strings of length 5."
039 *
040 * <p>See the Guava User Guide section on <a href=
041 * "https://github.com/google/guava/wiki/RangesExplained#discrete-domains">
042 * {@code DiscreteDomain}</a>.
043 *
044 * @author Kevin Bourrillion
045 * @since 10.0
046 */
047@GwtCompatible
048public abstract class DiscreteDomain<C extends Comparable> {
049
050  /**
051   * Returns the discrete domain for values of type {@code Integer}.
052   *
053   * @since 14.0 (since 10.0 as {@code DiscreteDomains.integers()})
054   */
055  public static DiscreteDomain<Integer> integers() {
056    return IntegerDomain.INSTANCE;
057  }
058
059  private static final class IntegerDomain extends DiscreteDomain<Integer> implements Serializable {
060    private static final IntegerDomain INSTANCE = new IntegerDomain();
061    
062    IntegerDomain() {
063      super(true);
064    }
065
066    @Override
067    public Integer next(Integer value) {
068      int i = value;
069      return (i == Integer.MAX_VALUE) ? null : i + 1;
070    }
071
072    @Override
073    public Integer previous(Integer value) {
074      int i = value;
075      return (i == Integer.MIN_VALUE) ? null : i - 1;
076    }
077    
078    @Override
079    Integer offset(Integer origin, long distance) {
080      checkNonnegative(distance, "distance");
081      return Ints.checkedCast(origin.longValue() + distance);
082    }
083
084    @Override
085    public long distance(Integer start, Integer end) {
086      return (long) end - start;
087    }
088
089    @Override
090    public Integer minValue() {
091      return Integer.MIN_VALUE;
092    }
093
094    @Override
095    public Integer maxValue() {
096      return Integer.MAX_VALUE;
097    }
098
099    private Object readResolve() {
100      return INSTANCE;
101    }
102
103    @Override
104    public String toString() {
105      return "DiscreteDomain.integers()";
106    }
107
108    private static final long serialVersionUID = 0;
109  }
110
111  /**
112   * Returns the discrete domain for values of type {@code Long}.
113   *
114   * @since 14.0 (since 10.0 as {@code DiscreteDomains.longs()})
115   */
116  public static DiscreteDomain<Long> longs() {
117    return LongDomain.INSTANCE;
118  }
119
120  private static final class LongDomain extends DiscreteDomain<Long> implements Serializable {
121    private static final LongDomain INSTANCE = new LongDomain();
122    
123    LongDomain() {
124      super(true);
125    }
126
127    @Override
128    public Long next(Long value) {
129      long l = value;
130      return (l == Long.MAX_VALUE) ? null : l + 1;
131    }
132
133    @Override
134    public Long previous(Long value) {
135      long l = value;
136      return (l == Long.MIN_VALUE) ? null : l - 1;
137    }
138
139    @Override
140    Long offset(Long origin, long distance) {
141      checkNonnegative(distance, "distance");
142      long result = origin + distance;
143      if (result < 0) {
144        checkArgument(origin < 0, "overflow");
145      }
146      return result;
147    }
148
149    @Override
150    public long distance(Long start, Long end) {
151      long result = end - start;
152      if (end > start && result < 0) { // overflow
153        return Long.MAX_VALUE;
154      }
155      if (end < start && result > 0) { // underflow
156        return Long.MIN_VALUE;
157      }
158      return result;
159    }
160
161    @Override
162    public Long minValue() {
163      return Long.MIN_VALUE;
164    }
165
166    @Override
167    public Long maxValue() {
168      return Long.MAX_VALUE;
169    }
170
171    private Object readResolve() {
172      return INSTANCE;
173    }
174
175    @Override
176    public String toString() {
177      return "DiscreteDomain.longs()";
178    }
179
180    private static final long serialVersionUID = 0;
181  }
182
183  /**
184   * Returns the discrete domain for values of type {@code BigInteger}.
185   *
186   * @since 15.0
187   */
188  public static DiscreteDomain<BigInteger> bigIntegers() {
189    return BigIntegerDomain.INSTANCE;
190  }
191
192  private static final class BigIntegerDomain extends DiscreteDomain<BigInteger>
193      implements Serializable {
194    private static final BigIntegerDomain INSTANCE = new BigIntegerDomain();
195
196    BigIntegerDomain() {
197      super(true);
198    }
199
200    private static final BigInteger MIN_LONG = BigInteger.valueOf(Long.MIN_VALUE);
201    private static final BigInteger MAX_LONG = BigInteger.valueOf(Long.MAX_VALUE);
202
203    @Override
204    public BigInteger next(BigInteger value) {
205      return value.add(BigInteger.ONE);
206    }
207
208    @Override
209    public BigInteger previous(BigInteger value) {
210      return value.subtract(BigInteger.ONE);
211    }
212
213    @Override
214    BigInteger offset(BigInteger origin, long distance) {
215      checkNonnegative(distance, "distance");
216      return origin.add(BigInteger.valueOf(distance));
217    }
218
219    @Override
220    public long distance(BigInteger start, BigInteger end) {
221      return end.subtract(start).max(MIN_LONG).min(MAX_LONG).longValue();
222    }
223
224    private Object readResolve() {
225      return INSTANCE;
226    }
227
228    @Override
229    public String toString() {
230      return "DiscreteDomain.bigIntegers()";
231    }
232
233    private static final long serialVersionUID = 0;
234  }
235  
236  final boolean supportsFastOffset;
237
238  /** Constructor for use by subclasses. */
239  protected DiscreteDomain() {
240    this(false);
241  }
242
243  /** Private constructor for built-in DiscreteDomains supporting fast offset. */
244  private DiscreteDomain(boolean supportsFastOffset) {
245    this.supportsFastOffset = supportsFastOffset;
246  }
247
248  /**
249   * Returns, conceptually, "origin + distance", or equivalently, the result of calling
250   * {@link #next} on {@code origin} {@code distance} times.
251   */
252  C offset(C origin, long distance) {
253    checkNonnegative(distance, "distance");
254    for (long i = 0; i < distance; i++) {
255      origin = next(origin);
256    }
257    return origin;
258  }
259
260  /**
261   * Returns the unique least value of type {@code C} that is greater than
262   * {@code value}, or {@code null} if none exists. Inverse operation to {@link
263   * #previous}.
264   *
265   * @param value any value of type {@code C}
266   * @return the least value greater than {@code value}, or {@code null} if
267   *     {@code value} is {@code maxValue()}
268   */
269  public abstract C next(C value);
270
271  /**
272   * Returns the unique greatest value of type {@code C} that is less than
273   * {@code value}, or {@code null} if none exists. Inverse operation to {@link
274   * #next}.
275   *
276   * @param value any value of type {@code C}
277   * @return the greatest value less than {@code value}, or {@code null} if
278   *     {@code value} is {@code minValue()}
279   */
280  public abstract C previous(C value);
281
282  /**
283   * Returns a signed value indicating how many nested invocations of {@link
284   * #next} (if positive) or {@link #previous} (if negative) are needed to reach
285   * {@code end} starting from {@code start}. For example, if {@code end =
286   * next(next(next(start)))}, then {@code distance(start, end) == 3} and {@code
287   * distance(end, start) == -3}. As well, {@code distance(a, a)} is always
288   * zero.
289   *
290   * <p>Note that this function is necessarily well-defined for any discrete
291   * type.
292   *
293   * @return the distance as described above, or {@link Long#MIN_VALUE} or
294   *     {@link Long#MAX_VALUE} if the distance is too small or too large,
295   *     respectively.
296   */
297  public abstract long distance(C start, C end);
298
299  /**
300   * Returns the minimum value of type {@code C}, if it has one. The minimum
301   * value is the unique value for which {@link Comparable#compareTo(Object)}
302   * never returns a positive value for any input of type {@code C}.
303   *
304   * <p>The default implementation throws {@code NoSuchElementException}.
305   *
306   * @return the minimum value of type {@code C}; never null
307   * @throws NoSuchElementException if the type has no (practical) minimum
308   *     value; for example, {@link java.math.BigInteger}
309   */
310  @CanIgnoreReturnValue
311  public C minValue() {
312    throw new NoSuchElementException();
313  }
314
315  /**
316   * Returns the maximum value of type {@code C}, if it has one. The maximum
317   * value is the unique value for which {@link Comparable#compareTo(Object)}
318   * never returns a negative value for any input of type {@code C}.
319   *
320   * <p>The default implementation throws {@code NoSuchElementException}.
321   *
322   * @return the maximum value of type {@code C}; never null
323   * @throws NoSuchElementException if the type has no (practical) maximum
324   *     value; for example, {@link java.math.BigInteger}
325   */
326  @CanIgnoreReturnValue
327  public C maxValue() {
328    throw new NoSuchElementException();
329  }
330}