/**
   * Returns the matching interval.
   *
   * @param index
   * @param type
   * @param tValue
   * @return
   */
  @SuppressWarnings("unchecked")
  private Interval<T> getIntervalUpperSnap(
      IndexNode index, DataTypeWithRatioScale<T> type, T tValue) {

    // Find interval
    double shift =
        Math.floor(
            type.ratio(type.subtract(tValue, index.min), type.subtract(index.max, index.min)));
    T offset = type.multiply(type.subtract(index.max, index.min), shift);
    T value = type.subtract(tValue, offset);
    Interval<T> interval = null;

    for (int j = 0; j < intervals.size(); j++) {
      Interval<T> i = intervals.get(j);
      if (type.compare(i.min, value) <= 0 && type.compare(i.max, value) > 0) {

        // If on lower bound, use next-lower interval
        if (type.compare(value, i.min) == 0) {
          if (j > 0) {

            // Simply use the next one
            interval = intervals.get(j - 1);
            break;
          } else {

            // Wrap around
            interval = intervals.get(intervals.size() - 1);
            offset = type.multiply(type.subtract(index.max, index.min), shift - 1);
            break;
          }
        } else {
          interval = i;
          break;
        }
      }
    }

    if (interval == null && intervals.size() == 1) {
      interval = intervals.get(0);
    }

    // Check
    if (interval == null) {
      throw new IllegalStateException("Internal error. Sorry for that!");
    }

    // Create first result interval
    T lower = type.add(interval.min, offset);
    T upper = type.add(interval.max, offset);
    return new Interval<T>(this, (DataType<T>) type, lower, upper, interval.function);
  }
  /**
   * Returns the matching interval.
   *
   * @param index
   * @param type
   * @param tValue
   * @return
   */
  @SuppressWarnings("unchecked")
  private Interval<T> getInterval(IndexNode index, DataTypeWithRatioScale<T> type, T tValue) {

    // Find interval
    int shift =
        (int)
            Math.floor(
                type.ratio(type.subtract(tValue, index.min), type.subtract(index.max, index.min)));
    T offset = type.multiply(type.subtract(index.max, index.min), shift);
    Interval<T> interval = getInterval(index, type.subtract(tValue, offset));

    // Check
    if (interval == null) {
      throw new IllegalStateException("No interval found for: " + type.format(tValue));
    }

    // Create first result interval
    T lower = type.add(interval.min, offset);
    T upper = type.add(interval.max, offset);
    return new Interval<T>(this, (DataType<T>) type, lower, upper, interval.function);
  }