package plume;
import java.io.Serializable;
import java.util.*;
/**
* LimitedSizeIntSet stores up to some maximum number of unique
* integer values, at which point its rep is nulled, in order to save space.
* <p>
* The advantage of this class over LimitedSizeSet<Integer> is that
* it does not autobox the int values, so it takes less memory.
*
* @see LimitedSizeSet
**/
// Consider adding:
// * @deprecated Use LimitedSizeSet instead
// @Deprecated
public class LimitedSizeIntSet
implements Serializable, Cloneable
{
// We are Serializable, so we specify a version to allow changes to
// method signatures without breaking serialization. If you add or
// remove fields, you should change this number to the current date.
static final long serialVersionUID = 20031021L;
// public final int max_values;
// If null, then at least num_values distinct values have been seen.
// The size is not separately stored, because that would take extra space.
protected int /*@Nullable*/ [] values;
// The number of active elements (equivalently, the first unused index).
int num_values;
public LimitedSizeIntSet(int max_values) {
assert max_values > 0;
// this.max_values = max_values;
values = new int[max_values];
num_values = 0;
}
public void add(int elt) {
if (values == null)
return;
for (int i=0; i < num_values; i++) {
if (values[i] == elt) {
return;
}
}
if (num_values == values.length) {
values = null;
num_values++;
return;
}
values[num_values] = elt;
num_values++;
}
public void addAll(LimitedSizeIntSet s) {
if (repNulled())
return;
if (s.repNulled()) {
int values_length = values.length;
// We don't know whether the elements of this and the argument were
// disjoint. There might be anywhere from max(size(), s.size()) to
// (size() + s.size()) elements in the resulting set.
if (s.size() > values_length) {
num_values = values_length+1;
values = null;
return;
} else {
throw new Error("Arg is rep-nulled, so we don't know its values and can't add them to this.");
}
}
for (int i=0; i<s.size(); i++) {
assert s.values != null : "@SuppressWarnings(nullness): no relevant side effect: add's side effects do not affect s.values, whether or not this == s";
add(s.values[i]);
if (repNulled()) {
return; // optimization, not necessary for correctness
}
}
}
public boolean contains(int elt) {
if (values == null) {
throw new UnsupportedOperationException();
}
for (int i=0; i < num_values; i++) {
if (values[i] == elt) {
return true;
}
}
return false;
}
/**
* A lower bound on the number of elements in the set. Returns either
* the number of elements that have been inserted in the set, or
* max_size(), whichever is less.
**/
/*@Pure*/
public int size() {
return num_values;
}
/**
* An upper bound how many distinct elements can be individually
* represented in the set.
* Returns max_values+1 (where max_values is the argument to the constructor).
**/
public int max_size() {
if (values == null) {
return num_values;
} else {
return values.length + 1;
}
}
/*@AssertNonNullIfFalse("values")*/
/*@Pure*/
public boolean repNulled() {
return values == null;
}
public LimitedSizeIntSet clone() {
LimitedSizeIntSet result;
try {
result = (LimitedSizeIntSet) super.clone();
} catch (CloneNotSupportedException e) {
throw new Error(); // can't happen
}
if (values != null) {
result.values = values.clone();
}
return result;
}
/**
* Merges a list of LimitedSizeIntSet objects into a single object that
* represents the values seen by the entire list. Returns the new
* object, whose max_values is the given integer.
**/
public static LimitedSizeIntSet merge (int max_values, List<LimitedSizeIntSet> slist) {
LimitedSizeIntSet result = new LimitedSizeIntSet(max_values);
for (LimitedSizeIntSet s : slist) {
result.addAll(s);
}
return result;
}
public String toString() {
return ("[size=" + size() + "; " +
((values == null) ? "null" : ArraysMDE.toString(values))
+ "]");
}
}