/* __ __ __ __ __ ___
* \ \ / / \ \ / / __/
* \ \/ / /\ \ \/ / /
* \____/__/ \__\____/__/.ɪᴏ
* ᶜᵒᵖʸʳᶦᵍʰᵗ ᵇʸ ᵛᵃᵛʳ ⁻ ˡᶦᶜᵉⁿˢᵉᵈ ᵘⁿᵈᵉʳ ᵗʰᵉ ᵃᵖᵃᶜʰᵉ ˡᶦᶜᵉⁿˢᵉ ᵛᵉʳˢᶦᵒⁿ ᵗʷᵒ ᵈᵒᵗ ᶻᵉʳᵒ
*/
package io.vavr.collection;
import io.vavr.Function1;
import io.vavr.PartialFunction;
import io.vavr.Tuple3;
import io.vavr.Tuple2;
import io.vavr.control.Option;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.NoSuchElementException;
import java.util.Objects;
import java.util.function.*;
import java.util.stream.Collector;
/**
* An immutable {@code BitSet} implementation.
*
* @author Ruslan Sennov
*/
public interface BitSet<T> extends SortedSet<T> {
long serialVersionUID = 1L;
class Builder<T> {
final static Builder<Integer> DEFAULT = new Builder<>(i -> i, i -> i);
final Function1<Integer, T> fromInt;
final Function1<T, Integer> toInt;
Builder(Function1<Integer, T> fromInt, Function1<T, Integer> toInt) {
this.fromInt = fromInt;
this.toInt = toInt;
}
public Collector<T, ArrayList<T>, BitSet<T>> collector() {
final BinaryOperator<ArrayList<T>> combiner = (left, right) -> {
left.addAll(right);
return left;
};
return Collector.of(ArrayList::new, ArrayList::add, combiner, this::ofAll);
}
public BitSet<T> empty() {
return new BitSetModule.BitSet1<>(fromInt, toInt, 0L);
}
public BitSet<T> of(T t) {
final int value = toInt.apply(t);
if (value < BitSetModule.BITS_PER_WORD) {
return new BitSetModule.BitSet1<>(fromInt, toInt, 1L << value);
} else if (value < 2 * BitSetModule.BITS_PER_WORD) {
return new BitSetModule.BitSet2<>(fromInt, toInt, 0L, 1L << value);
} else {
return empty().add(t);
}
}
@SuppressWarnings("varargs")
@SafeVarargs
public final BitSet<T> of(T... values) {
return empty().addAll(Array.wrap(values));
}
public BitSet<T> ofAll(Iterable<? extends T> values) {
Objects.requireNonNull(values, "values is null");
return empty().addAll(values);
}
public BitSet<T> ofAll(java.util.stream.Stream<? extends T> javaStream) {
Objects.requireNonNull(javaStream, "javaStream is null");
return empty().addAll(Iterator.ofAll(javaStream.iterator()));
}
public BitSet<T> tabulate(int n, Function<? super Integer, ? extends T> f) {
Objects.requireNonNull(f, "f is null");
return empty().addAll(Collections.tabulate(n, f));
}
public BitSet<T> fill(int n, Supplier<? extends T> s) {
Objects.requireNonNull(s, "s is null");
return empty().addAll(Collections.fill(n, s));
}
}
static <T> Builder<T> withRelations(Function1<Integer, T> fromInt, Function1<T, Integer> toInt) {
return new Builder<>(fromInt, toInt);
}
@SuppressWarnings("RedundantTypeArguments")
static <T extends Enum<T>> Builder<T> withEnum(Class<T> enumClass) {
return new Builder<>(i -> enumClass.getEnumConstants()[i], Enum<T>::ordinal);
}
static Builder<Character> withCharacters() {
return new Builder<>(i -> (char) i.intValue(), c -> (int) c);
}
static Builder<Byte> withBytes() {
return new Builder<>(Integer::byteValue, Byte::intValue);
}
static Builder<Long> withLongs() {
return new Builder<>(Integer::longValue, Long::intValue);
}
static Builder<Short> withShorts() {
return new Builder<>(Integer::shortValue, Short::intValue);
}
/**
* Returns a {@link java.util.stream.Collector} which may be used in conjunction with
* {@link java.util.stream.Stream#collect(java.util.stream.Collector)} to obtain a {@link BitSet}.
*
* @return A {@link BitSet} Collector.
*/
static Collector<Integer, ArrayList<Integer>, BitSet<Integer>> collector() {
return Builder.DEFAULT.collector();
}
static BitSet<Integer> empty() {
return Builder.DEFAULT.empty();
}
static BitSet<Integer> of(Integer value) {
return Builder.DEFAULT.of(value);
}
static BitSet<Integer> of(Integer... values) {
return Builder.DEFAULT.of(values);
}
/**
* Returns a BitSet containing {@code n} values of a given Function {@code f}
* over a range of integer values from 0 to {@code n - 1}.
*
* @param n The number of elements in the BitSet
* @param f The Function computing element values
* @return A BitSet consisting of elements {@code f(0),f(1), ..., f(n - 1)}
* @throws NullPointerException if {@code f} is null
*/
static BitSet<Integer> tabulate(int n, Function<Integer, Integer> f) {
return Builder.DEFAULT.tabulate(n, f);
}
/**
* Returns a BitSet containing {@code n} values supplied by a given Supplier {@code s}.
*
* @param n The number of elements in the BitSet
* @param s The Supplier computing element values
* @return A BitSet of size {@code n}, where each element contains the result supplied by {@code s}.
* @throws NullPointerException if {@code s} is null
*/
static BitSet<Integer> fill(int n, Supplier<Integer> s) {
return Builder.DEFAULT.fill(n, s);
}
static BitSet<Integer> ofAll(Iterable<Integer> values) {
return Builder.DEFAULT.ofAll(values);
}
static BitSet<Integer> ofAll(java.util.stream.Stream<Integer> javaStream) {
return Builder.DEFAULT.ofAll(javaStream);
}
/**
* Creates a BitSet from boolean values.
*
* @param elements boolean values
* @return A new BitSet of boolean values
* @throws NullPointerException if elements is null
*/
static BitSet<Boolean> ofAll(boolean... elements) {
Objects.requireNonNull(elements, "elements is null");
return BitSet.withRelations(i -> i != 0, b -> b ? 1 : 0).ofAll(Iterator.ofAll(elements));
}
/**
* Creates a BitSet from byte values.
*
* @param elements byte values
* @return A new BitSet of byte values
* @throws NullPointerException if elements is null
*/
static BitSet<Byte> ofAll(byte... elements) {
Objects.requireNonNull(elements, "elements is null");
return BitSet.withBytes().ofAll(Iterator.ofAll(elements));
}
/**
* Creates a BitSet from char values.
*
* @param elements char values
* @return A new BitSet of char values
* @throws NullPointerException if elements is null
*/
static BitSet<Character> ofAll(char... elements) {
Objects.requireNonNull(elements, "elements is null");
return BitSet.withCharacters().ofAll(Iterator.ofAll(elements));
}
/**
* Creates a BitSet from int values.
*
* @param elements int values
* @return A new BitSet of int values
* @throws NullPointerException if elements is null
*/
static BitSet<Integer> ofAll(int... elements) {
Objects.requireNonNull(elements, "elements is null");
return BitSet.ofAll(Iterator.ofAll(elements));
}
/**
* Creates a BitSet from long values.
*
* @param elements long values
* @return A new BitSet of long values
* @throws NullPointerException if elements is null
*/
static BitSet<Long> ofAll(long... elements) {
Objects.requireNonNull(elements, "elements is null");
return BitSet.withLongs().ofAll(Iterator.ofAll(elements));
}
/**
* Creates a BitSet from short values.
*
* @param elements short values
* @return A new BitSet of short values
* @throws NullPointerException if elements is null
*/
static BitSet<Short> ofAll(short... elements) {
Objects.requireNonNull(elements, "elements is null");
return BitSet.withShorts().ofAll(Iterator.ofAll(elements));
}
/**
* Creates a BitSet of int numbers starting from {@code from}, extending to {@code toExclusive - 1}.
*
* @param from the first number
* @param toExclusive the last number + 1
* @return a range of int values as specified or the empty range if {@code from >= toExclusive}
*/
static BitSet<Integer> range(int from, int toExclusive) {
return BitSet.ofAll(Iterator.range(from, toExclusive));
}
static BitSet<Character> range(char from, char toExclusive) {
return BitSet.withCharacters().ofAll(Iterator.range(from, toExclusive));
}
static BitSet<Long> range(long from, long toExclusive) {
return BitSet.withLongs().ofAll(Iterator.range(from, toExclusive));
}
/**
* Creates a BitSet of int numbers starting from {@code from}, extending to {@code toExclusive - 1},
* with {@code step}.
*
* @param from the first number
* @param toExclusive the last number + 1
* @param step the step
* @return a range of long values as specified or the empty range if<br>
* {@code from >= toInclusive} and {@code step > 0} or<br>
* {@code from <= toInclusive} and {@code step < 0}
* @throws IllegalArgumentException if {@code step} is zero
*/
static BitSet<Integer> rangeBy(int from, int toExclusive, int step) {
return BitSet.ofAll(Iterator.rangeBy(from, toExclusive, step));
}
static BitSet<Character> rangeBy(char from, char toExclusive, int step) {
return BitSet.withCharacters().ofAll(Iterator.rangeBy(from, toExclusive, step));
}
static BitSet<Long> rangeBy(long from, long toExclusive, long step) {
return BitSet.withLongs().ofAll(Iterator.rangeBy(from, toExclusive, step));
}
/**
* Creates a BitSet of int numbers starting from {@code from}, extending to {@code toInclusive}.
*
* @param from the first number
* @param toInclusive the last number
* @return a range of int values as specified or the empty range if {@code from > toInclusive}
*/
static BitSet<Integer> rangeClosed(int from, int toInclusive) {
return BitSet.ofAll(Iterator.rangeClosed(from, toInclusive));
}
static BitSet<Character> rangeClosed(char from, char toInclusive) {
return BitSet.withCharacters().ofAll(Iterator.rangeClosed(from, toInclusive));
}
static BitSet<Long> rangeClosed(long from, long toInclusive) {
return BitSet.withLongs().ofAll(Iterator.rangeClosed(from, toInclusive));
}
/**
* Creates a BitSet of int numbers starting from {@code from}, extending to {@code toInclusive},
* with {@code step}.
*
* @param from the first number
* @param toInclusive the last number
* @param step the step
* @return a range of int values as specified or the empty range if<br>
* {@code from > toInclusive} and {@code step > 0} or<br>
* {@code from < toInclusive} and {@code step < 0}
* @throws IllegalArgumentException if {@code step} is zero
*/
static BitSet<Integer> rangeClosedBy(int from, int toInclusive, int step) {
return BitSet.ofAll(Iterator.rangeClosedBy(from, toInclusive, step));
}
static BitSet<Character> rangeClosedBy(char from, char toInclusive, int step) {
return BitSet.withCharacters().ofAll(Iterator.rangeClosedBy(from, toInclusive, step));
}
static BitSet<Long> rangeClosedBy(long from, long toInclusive, long step) {
return BitSet.withLongs().ofAll(Iterator.rangeClosedBy(from, toInclusive, step));
}
@Override
BitSet<T> add(T element);
@Override
BitSet<T> addAll(Iterable<? extends T> elements);
@Override
default <R> SortedSet<R> collect(PartialFunction<? super T, ? extends R> partialFunction) {
Objects.requireNonNull(partialFunction, "partialFunction is null");
return TreeSet.ofAll(Comparators.naturalComparator(), iterator().collect(partialFunction));
}
@Override
default BitSet<T> diff(Set<? extends T> elements) {
return removeAll(elements);
}
@Override
default BitSet<T> distinct() {
return this;
}
@Override
BitSet<T> distinctBy(Comparator<? super T> comparator);
@Override
<U> BitSet<T> distinctBy(Function<? super T, ? extends U> keyExtractor);
@Override
BitSet<T> drop(int n);
@Override
BitSet<T> dropRight(int n);
@Override
default BitSet<T> dropUntil(Predicate<? super T> predicate) {
Objects.requireNonNull(predicate, "predicate is null");
return dropWhile(predicate.negate());
}
@Override
BitSet<T> dropWhile(Predicate<? super T> predicate);
@Override
BitSet<T> filter(Predicate<? super T> predicate);
@Override
default <U> SortedSet<U> flatMap(Comparator<? super U> comparator, Function<? super T, ? extends Iterable<? extends U>> mapper) {
Objects.requireNonNull(mapper, "mapper is null");
return TreeSet.ofAll(comparator, iterator().flatMap(mapper));
}
@Override
default <U> SortedSet<U> flatMap(Function<? super T, ? extends Iterable<? extends U>> mapper) {
return flatMap(Comparators.naturalComparator(), mapper);
}
@Override
default <U> U foldRight(U zero, BiFunction<? super T, ? super U, ? extends U> f) {
Objects.requireNonNull(f, "f is null");
return iterator().foldRight(zero, f);
}
@Override
<C> Map<C, BitSet<T>> groupBy(Function<? super T, ? extends C> classifier);
@Override
default Iterator<BitSet<T>> grouped(int size) {
return sliding(size, size);
}
@Override
default boolean hasDefiniteSize() {
return true;
}
@Override
BitSet<T> init();
@Override
default Option<BitSet<T>> initOption() {
return isEmpty() ? Option.none() : Option.some(init());
}
/**
* An {@code BitSet}'s value is computed synchronously.
*
* @return false
*/
@Override
default boolean isAsync() {
return false;
}
@Override
default boolean isTraversableAgain() {
return true;
}
/**
* An {@code BitSet}'s value is computed eagerly.
*
* @return false
*/
@Override
default boolean isLazy() {
return false;
}
@Override
BitSet<T> intersect(Set<? extends T> elements);
@Override
Tuple2<BitSet<T>, BitSet<T>> partition(Predicate<? super T> predicate);
@Override
default BitSet<T> peek(Consumer<? super T> action) {
Objects.requireNonNull(action, "action is null");
if (!isEmpty()) {
action.accept(head());
}
return this;
}
@Override
default String stringPrefix() {
return "BitSet";
}
@Override
default <U> SortedSet<U> map(Comparator<? super U> comparator, Function<? super T, ? extends U> mapper) {
Objects.requireNonNull(mapper, "mapper is null");
return TreeSet.ofAll(comparator, iterator().map(mapper));
}
@Override
default <U> SortedSet<U> map(Function<? super T, ? extends U> mapper) {
return map(Comparators.naturalComparator(), mapper);
}
@Override
BitSet<T> remove(T element);
@Override
BitSet<T> removeAll(Iterable<? extends T> elements);
@Override
default BitSet<T> replace(T currentElement, T newElement) {
if (contains(currentElement)) {
return remove(currentElement).add(newElement);
} else {
return this;
}
}
@Override
default BitSet<T> replaceAll(T currentElement, T newElement) {
// a set has only one occurrence
return replace(currentElement, newElement);
}
@Override
default BitSet<T> retainAll(Iterable<? extends T> elements) {
return Collections.retainAll(this, elements);
}
@Override
BitSet<T> scan(T zero, BiFunction<? super T, ? super T, ? extends T> operation);
@Override
default <U> Set<U> scanLeft(U zero, BiFunction<? super U, ? super T, ? extends U> operation) {
return Collections.scanLeft(this, zero, operation, HashSet::ofAll);
}
@Override
default <U> Set<U> scanRight(U zero, BiFunction<? super T, ? super U, ? extends U> operation) {
return Collections.scanRight(this, zero, operation, HashSet::ofAll);
}
@Override
Iterator<BitSet<T>> slideBy(Function<? super T, ?> classifier);
@Override
default Iterator<BitSet<T>> sliding(int size) {
return sliding(size, 1);
}
@Override
Iterator<BitSet<T>> sliding(int size, int step);
@Override
Tuple2<BitSet<T>, BitSet<T>> span(Predicate<? super T> predicate);
@Override
default BitSet<T> tail() {
if (isEmpty()) {
throw new UnsupportedOperationException("tail of empty BitSet");
} else {
return drop(1);
}
}
@Override
default Option<BitSet<T>> tailOption() {
return isEmpty() ? Option.none() : Option.some(tail());
}
@Override
BitSet<T> take(int n);
@Override
BitSet<T> takeRight(int n);
@Override
default BitSet<T> takeUntil(Predicate<? super T> predicate) {
Objects.requireNonNull(predicate, "predicate is null");
return takeWhile(predicate.negate());
}
@Override
BitSet<T> takeWhile(Predicate<? super T> predicate);
@Override
default java.util.SortedSet<T> toJavaSet() {
return toJavaSet(ignore -> new java.util.TreeSet<>(comparator()));
}
@Override
default BitSet<T> union(Set<? extends T> elements) {
Objects.requireNonNull(elements, "elements is null");
return elements.isEmpty() ? this : addAll(elements);
}
@Override
default <T1, T2> Tuple2<TreeSet<T1>, TreeSet<T2>> unzip(
Function<? super T, Tuple2<? extends T1, ? extends T2>> unzipper) {
Objects.requireNonNull(unzipper, "unzipper is null");
return iterator().unzip(unzipper).map(i1 -> TreeSet.ofAll(Comparators.naturalComparator(), i1),
i2 -> TreeSet.ofAll(Comparators.naturalComparator(), i2));
}
@Override
default <T1, T2, T3> Tuple3<TreeSet<T1>, TreeSet<T2>, TreeSet<T3>> unzip3(
Function<? super T, Tuple3<? extends T1, ? extends T2, ? extends T3>> unzipper) {
Objects.requireNonNull(unzipper, "unzipper is null");
return iterator().unzip3(unzipper).map(
i1 -> TreeSet.ofAll(Comparators.naturalComparator(), i1),
i2 -> TreeSet.ofAll(Comparators.naturalComparator(), i2),
i3 -> TreeSet.ofAll(Comparators.naturalComparator(), i3));
}
@Override
default <U> TreeSet<Tuple2<T, U>> zip(Iterable<? extends U> that) {
Objects.requireNonNull(that, "that is null");
final Comparator<Tuple2<T, U>> tuple2Comparator = Tuple2.comparator(comparator(), Comparators.naturalComparator());
return TreeSet.ofAll(tuple2Comparator, iterator().zip(that));
}
@Override
default <U, R> TreeSet<R> zipWith(Iterable<? extends U> that, BiFunction<? super T, ? super U, ? extends R> mapper) {
Objects.requireNonNull(that, "that is null");
Objects.requireNonNull(mapper, "mapper is null");
return TreeSet.ofAll(Comparators.naturalComparator(), iterator().zipWith(that, mapper));
}
@Override
default <U> TreeSet<Tuple2<T, U>> zipAll(Iterable<? extends U> that, T thisElem, U thatElem) {
Objects.requireNonNull(that, "that is null");
final Comparator<Tuple2<T, U>> tuple2Comparator = Tuple2.comparator(comparator(), Comparators.naturalComparator());
return TreeSet.ofAll(tuple2Comparator, iterator().zipAll(that, thisElem, thatElem));
}
@Override
default TreeSet<Tuple2<T, Integer>> zipWithIndex() {
final Comparator<? super T> component1Comparator = comparator();
final Comparator<Tuple2<T, Integer>> tuple2Comparator = (t1, t2) -> component1Comparator.compare(t1._1, t2._1);
return TreeSet.ofAll(tuple2Comparator, iterator().zipWithIndex());
}
@Override
default <U> TreeSet<U> zipWithIndex(BiFunction<? super T, ? super Integer, ? extends U> mapper) {
Objects.requireNonNull(mapper, "mapper is null");
return TreeSet.ofAll(Comparators.naturalComparator(), iterator().zipWithIndex(mapper));
}
}
interface BitSetModule {
int ADDRESS_BITS_PER_WORD = 6;
int BITS_PER_WORD = 64;
abstract class AbstractBitSet<T> implements BitSet<T>, Serializable {
private static final long serialVersionUID = 1L;
final Function1<Integer, T> fromInt;
final Function1<T, Integer> toInt;
AbstractBitSet(Function1<Integer, T> fromInt, Function1<T, Integer> toInt) {
this.fromInt = fromInt;
this.toInt = toInt;
}
abstract int getWordsNum();
abstract long[] copyExpand(int wordsNum);
abstract long getWord(int index);
BitSet<T> createEmpty() {
return new BitSet1<>(fromInt, toInt, 0L);
}
@SuppressWarnings("unchecked")
BitSet<T> createFromAll(Iterable<? extends T> values) {
return values instanceof BitSet ? (BitSet<T>) values : createEmpty().addAll(values);
}
BitSet<T> fromBitMaskNoCopy(long[] elements) {
final int len = elements.length;
if (len == 0) {
return createEmpty();
} else if (len == 1) {
return new BitSet1<>(fromInt, toInt, elements[0]);
} else if (len == 2) {
return new BitSet2<>(fromInt, toInt, elements[0], elements[1]);
} else {
return new BitSetN<>(fromInt, toInt, elements);
}
}
private void setElement(long[] words, int element) {
final int index = element >> ADDRESS_BITS_PER_WORD;
words[index] |= (1L << element);
}
private void unsetElement(long[] words, int element) {
final int index = element >> ADDRESS_BITS_PER_WORD;
words[index] &= ~(1L << element);
}
long[] shrink(long[] elements) {
int newlen = elements.length;
while (newlen > 0 && elements[newlen - 1] == 0) {
newlen--;
}
final long[] newelems = new long[newlen];
System.arraycopy(elements, 0, newelems, 0, newlen);
return newelems;
}
BitSet<T> addElement(int element) {
final long[] copy = copyExpand(1 + (element >> ADDRESS_BITS_PER_WORD));
setElement(copy, element);
return fromBitMaskNoCopy(copy);
}
@Override
public BitSet<T> distinctBy(Comparator<? super T> comparator) {
Objects.requireNonNull(comparator, "comparator is null");
return isEmpty() ? this : createFromAll(iterator().distinctBy(comparator));
}
@Override
public <U> BitSet<T> distinctBy(Function<? super T, ? extends U> keyExtractor) {
Objects.requireNonNull(keyExtractor, "keyExtractor is null");
return isEmpty() ? this : createFromAll(iterator().distinctBy(keyExtractor));
}
@Override
public BitSet<T> drop(int n) {
if (n <= 0 || isEmpty()) {
return this;
} else if (n >= length()) {
return createEmpty();
} else {
return createFromAll(iterator().drop(n));
}
}
@Override
public BitSet<T> dropRight(int n) {
if (n <= 0 || isEmpty()) {
return this;
} else if (n >= length()) {
return createEmpty();
} else {
return createFromAll(iterator().dropRight(n));
}
}
@Override
public BitSet<T> dropWhile(Predicate<? super T> predicate) {
Objects.requireNonNull(predicate, "predicate is null");
final BitSet<T> bitSet = createFromAll(iterator().dropWhile(predicate));
return (bitSet.length() == length()) ? this : bitSet;
}
@Override
public BitSet<T> intersect(Set<? extends T> elements) {
Objects.requireNonNull(elements, "elements is null");
if (isEmpty()) {
return this;
} else if (elements.isEmpty()) {
return createEmpty();
} else {
final int size = size();
if (size <= elements.size()) {
return retainAll(elements);
} else {
final BitSet<T> results = createFromAll(elements).retainAll(this);
return (size == results.size()) ? this : results;
}
}
}
/**
* Returns this {@code BitSet} if it is nonempty,
* otherwise {@code BitSet} created from iterable, using existing bitset properties.
*
* @param other An alternative {@code Traversable}
* @return this {@code BitSet} if it is nonempty,
* otherwise {@code BitSet} created from iterable, using existing bitset properties.
*/
@Override
public BitSet<T> orElse(Iterable<? extends T> other) {
return isEmpty() ? createFromAll(other) : this;
}
/**
* Returns this {@code BitSet} if it is nonempty,
* otherwise {@code BitSet} created from result of evaluating supplier, using existing bitset properties.
*
* @param supplier An alternative {@code Traversable}
* @return this {@code BitSet} if it is nonempty,
* otherwise {@code BitSet} created from result of evaluating supplier, using existing bitset properties.
*/
@Override
public BitSet<T> orElse(Supplier<? extends Iterable<? extends T>> supplier) {
return isEmpty() ? createFromAll(supplier.get()) : this;
}
@Override
public Iterator<BitSet<T>> slideBy(Function<? super T, ?> classifier) {
return iterator().slideBy(classifier).map(this::createFromAll);
}
@Override
public Iterator<BitSet<T>> sliding(int size, int step) {
return iterator().sliding(size, step).map(this::createFromAll);
}
@Override
public Tuple2<BitSet<T>, BitSet<T>> span(Predicate<? super T> predicate) {
Objects.requireNonNull(predicate, "predicate is null");
return iterator().span(predicate).map(this::createFromAll, this::createFromAll);
}
@Override
public BitSet<T> scan(T zero, BiFunction<? super T, ? super T, ? extends T> operation) {
return Collections.scanLeft(this, zero, operation, this::createFromAll);
}
@Override
public Tuple2<BitSet<T>, BitSet<T>> partition(Predicate<? super T> predicate) {
Objects.requireNonNull(predicate, "predicate is null");
return iterator().partition(predicate).map(this::createFromAll, this::createFromAll);
}
@Override
public BitSet<T> filter(Predicate<? super T> predicate) {
Objects.requireNonNull(predicate, "predicate is null");
final BitSet<T> bitSet = createFromAll(iterator().filter(predicate));
return (bitSet.length() == length()) ? this : bitSet;
}
@Override
public <C> Map<C, BitSet<T>> groupBy(Function<? super T, ? extends C> classifier) {
return Collections.groupBy(this, classifier, this::createFromAll);
}
@Override
public Comparator<T> comparator() {
return Comparator.comparing(toInt);
}
@Override
public BitSet<T> takeWhile(Predicate<? super T> predicate) {
Objects.requireNonNull(predicate, "predicate is null");
final BitSet<T> result = createFromAll(iterator().takeWhile(predicate));
return (result.length() == length()) ? this : result;
}
@Override
@SuppressWarnings("unchecked")
public BitSet<T> addAll(Iterable<? extends T> elements) {
final Stream<Integer> source = Stream.ofAll(elements).map(toInt);
if (source.isEmpty()) {
return this;
} else {
final long[] copy = copyExpand(1 + (source.max().getOrElse(0) >> ADDRESS_BITS_PER_WORD));
source.forEach(element -> {
if (element < 0) {
throw new IllegalArgumentException("bitset element must be >= 0");
}
setElement(copy, element);
});
final BitSet<T> bitSet = fromBitMaskNoCopy(copy);
return (bitSet.length() == length()) ? this : bitSet;
}
}
@Override
public boolean contains(T t) {
final int element = toInt.apply(t);
if (element < 0) {
throw new IllegalArgumentException("bitset element must be >= 0");
}
final int index = element >> ADDRESS_BITS_PER_WORD;
return index < getWordsNum() && (getWord(index) & (1L << element)) != 0;
}
@Override
public BitSet<T> init() {
if (isEmpty()) {
throw new UnsupportedOperationException("init of empty TreeSet");
} else {
final long last = getWord(getWordsNum() - 1);
final int element = BITS_PER_WORD * (getWordsNum() - 1) + BITS_PER_WORD - Long.numberOfLeadingZeros(last) - 1;
return remove(fromInt.apply(element));
}
}
@Override
public Iterator<T> iterator() {
return new BitSetIterator<>(this);
}
@Override
public BitSet<T> take(int n) {
if (isEmpty() || n >= length()) {
return this;
} else if (n <= 0) {
return createEmpty();
} else {
return createFromAll(iterator().take(n));
}
}
@Override
public BitSet<T> takeRight(int n) {
if (isEmpty() || n >= length()) {
return this;
} else if (n <= 0) {
return createEmpty();
} else {
return createFromAll(iterator().takeRight(n));
}
}
@Override
public BitSet<T> remove(T t) {
if (contains(t)) {
final int element = toInt.apply(t);
final long[] copy = copyExpand(getWordsNum());
unsetElement(copy, element);
return fromBitMaskNoCopy(shrink(copy));
} else {
return this;
}
}
@Override
public BitSet<T> removeAll(Iterable<? extends T> elements) {
if (isEmpty()) {
return this;
} else {
final Stream<Integer> source = Stream.ofAll(elements).map(toInt);
if (source.isEmpty()) {
return this;
} else {
final long[] copy = copyExpand(getWordsNum());
source.forEach(element -> unsetElement(copy, element));
return fromBitMaskNoCopy(shrink(copy));
}
}
}
@Override
public String toString() {
return mkString(stringPrefix() + "(", ", ", ")");
}
@Override
public boolean equals(Object o) {
return Collections.equals(this, o);
}
@Override
public int hashCode() {
return Collections.hashUnordered(this);
}
}
class BitSetIterator<T> extends AbstractIterator<T> {
private final AbstractBitSet<T> bitSet;
private long element;
private int index;
BitSetIterator(AbstractBitSet<T> bitSet) {
this.bitSet = bitSet;
this.element = bitSet.getWord(0);
this.index = 0;
}
@Override
protected T getNext() {
final int pos = Long.numberOfTrailingZeros(element);
element &= ~(1L << pos);
return bitSet.fromInt.apply(pos + (index << ADDRESS_BITS_PER_WORD));
}
@Override
public boolean hasNext() {
if (element == 0) {
while (element == 0 && index < bitSet.getWordsNum() - 1) {
element = bitSet.getWord(++index);
}
return element != 0;
} else {
return true;
}
}
}
class BitSet1<T> extends AbstractBitSet<T> {
private static final long serialVersionUID = 1L;
private final long elements;
private final int len;
BitSet1(Function1<Integer, T> fromInt, Function1<T, Integer> toInt, long elements) {
super(fromInt, toInt);
this.elements = elements;
this.len = Long.bitCount(elements);
}
@Override
int getWordsNum() {
return 1;
}
@Override
long[] copyExpand(int wordsNum) {
if (wordsNum < 1) {
wordsNum = 1;
}
final long[] arr = new long[wordsNum];
arr[0] = elements;
return arr;
}
@Override
long getWord(int index) {
return elements;
}
@Override
public T head() {
if (elements == 0) {
throw new NoSuchElementException("head of empty BitSet");
} else {
return fromInt.apply(Long.numberOfTrailingZeros(elements));
}
}
@Override
public int length() {
return len;
}
@Override
public BitSet<T> add(T t) {
final int element = toInt.apply(t);
if (element < 0) {
throw new IllegalArgumentException("bitset element must be >= 0");
}
if (element < BITS_PER_WORD) {
final long mask = 1L << element;
if ((elements & mask) != 0) {
return this;
} else {
return new BitSet1<>(fromInt, toInt, elements | mask);
}
} else {
return addElement(element);
}
}
}
class BitSet2<T> extends AbstractBitSet<T> {
private static final long serialVersionUID = 1L;
private final long elements1, elements2;
private final int len;
BitSet2(Function1<Integer, T> fromInt, Function1<T, Integer> toInt, long elements1, long elements2) {
super(fromInt, toInt);
this.elements1 = elements1;
this.elements2 = elements2;
this.len = Long.bitCount(elements1) + Long.bitCount(elements2);
}
@Override
int getWordsNum() {
return 2;
}
@Override
long[] copyExpand(int wordsNum) {
if (wordsNum < 2) {
wordsNum = 2;
}
final long[] arr = new long[wordsNum];
arr[0] = elements1;
arr[1] = elements2;
return arr;
}
@Override
long getWord(int index) {
if (index == 0) {
return elements1;
} else {
return elements2;
}
}
@Override
public T head() {
if (elements1 == 0) {
return fromInt.apply(BITS_PER_WORD + Long.numberOfTrailingZeros(elements2));
} else {
return fromInt.apply(Long.numberOfTrailingZeros(elements1));
}
}
@Override
public int length() {
return len;
}
@Override
public BitSet<T> add(T t) {
final int element = toInt.apply(t);
if (element < 0) {
throw new IllegalArgumentException("bitset element must be >= 0");
}
final long mask = 1L << element;
if (element < BITS_PER_WORD) {
if ((elements1 & mask) != 0) {
return this;
} else {
return new BitSet2<>(fromInt, toInt, elements1 | mask, elements2);
}
} else if (element < 2 * BITS_PER_WORD) {
if ((elements2 & mask) != 0) {
return this;
} else {
return new BitSet2<>(fromInt, toInt, elements1, elements2 | mask);
}
} else {
return addElement(element);
}
}
}
class BitSetN<T> extends AbstractBitSet<T> {
private static final long serialVersionUID = 1L;
private final long[] elements;
private final int len;
BitSetN(Function1<Integer, T> fromInt, Function1<T, Integer> toInt, long[] elements) {
super(fromInt, toInt);
this.elements = elements;
this.len = calcLength(elements);
}
private static int calcLength(long[] elements) {
int len = 0;
for (long element : elements) {
len += Long.bitCount(element);
}
return len;
}
@Override
int getWordsNum() {
return elements.length;
}
@Override
long[] copyExpand(int wordsNum) {
if (wordsNum < elements.length) {
wordsNum = elements.length;
}
final long[] arr = new long[wordsNum];
System.arraycopy(elements, 0, arr, 0, elements.length);
return arr;
}
@Override
long getWord(int index) {
return elements[index];
}
@Override
public T head() {
int offset = 0;
int element = 0;
for (int i = 0; i < getWordsNum(); i++) {
if (elements[i] == 0) {
offset += BITS_PER_WORD;
} else {
element = offset + Long.numberOfTrailingZeros(elements[i]);
break;
}
}
return fromInt.apply(element);
}
@Override
public int length() {
return len;
}
@Override
public BitSet<T> add(T t) {
if (contains(t)) {
return this;
} else {
return addElement(toInt.apply(t));
}
}
}
}