/******************************************************************************* * Copyright 2014 Analog Devices, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. ********************************************************************************/ package com.analog.lyric.dimple.model.domains; import org.eclipse.jdt.annotation.Nullable; /** * A discrete domain defined by a range of integers separated by a constant positive interval. * <p> * @see DiscreteDomain#range(int, int) * @see DiscreteDomain#range(int, int, int) */ public class IntRangeDomain extends IntDiscreteDomain { private static final long serialVersionUID = 1L; private final int _lowerBound; private final int _upperBound; private final int _size; private final int _interval; /*-------------- * Construction */ IntRangeDomain(int lowerBound, int upperBound, int interval) { super(computeHashCode(lowerBound, upperBound, interval)); if (interval < 1) { throw new IllegalArgumentException( String.format("Non-positive interval '%d' for integer range domain", interval)); } if (upperBound < lowerBound) { throw new IllegalArgumentException( String.format("Bad integer range [%d,%d]: upper bound lower than lower bound", lowerBound, upperBound)); } _lowerBound = lowerBound; _upperBound = upperBound; _interval = interval; long longInterval = interval; long size = (longInterval + upperBound - lowerBound) / longInterval; if (size > Integer.MAX_VALUE) { throw new IllegalArgumentException("Bad integer range: more than MAX_INTEGER (2^32) values in range"); } _size = (int)size; } private static int computeHashCode(int lowerBound, int upperBound, int interval) { return lowerBound + (upperBound * 11 + interval) * 13; } /*---------------- * Object methods */ @Override public boolean equals(@Nullable Object that) { if (this == that) { return true; } if (that instanceof IntRangeDomain) { IntRangeDomain thatRange = (IntRangeDomain)that; return _lowerBound == thatRange._lowerBound && _upperBound == thatRange._upperBound && _interval == thatRange._interval; } return false; } /*------------------------ * DiscreteDomain methods */ /** * Same as {@link #getIndex(Object)} but taking an int. */ @Override public int getIndex(int value) { value -= _lowerBound; value /= _interval; return value < _size ? value : -1; } @Override public int size() { return _size; } /*------------------------ * IntRangeDomain methods */ /** * Same as {@link #getElement(int)} but returning an unboxed int. */ @Override public int getIntElement(int i) { assertIndexInBounds(i, _size); return _lowerBound + i * _interval; } /** * The interval separating consecutive elements of the domain. * <p> * Guaranteed to be positive. */ public int getInterval() { return _interval; } /** * Returns the lower bound for the domain which is also the same as the first element. * <p> * @see #getUpperBound() */ public int getLowerBound() { return _lowerBound; } /** * Returns the upper bound for the domain. This will only be a member of the domain if it can be expressed * as an exact multiple of the interval added to the lower bound. * <p> * @see #getInterval() * @see #getLowerBound() */ public int getUpperBound() { return _upperBound; } }